mirror of https://github.com/garrytan/gstack.git
test(gbrain-doctor): pin schema_version:2 doctor parse path (#1418)
Adds an exec-path regression test that runs a fake gbrain shim emitting the v0.25+ doctor JSON shape (schema_version: 2, status: "warnings", exit 1 for health_score < 100, no top-level `engine` field). Confirms freshDetectEngineTier recovers stdout from the non-zero exit and falls back to GBRAIN_HOME/config.json for the engine label. The pre-existing test for #1415 only stripped gbrain from PATH; this test exercises the actual doctor parse path, closing the gap that codex's plan review flagged. Also documents the schema_version separation in lib/gbrain-local-status.ts: the local CacheEntry stays at version 1, distinct from the doctor-output schema_version which we accept across versions in gstack-memory-helpers. Closes #1418 (credit @mvanhorn for surfacing the doctor + schema_v2 collapse). The fix landed pre-emptively in v1.29.x; this commit pins it with a stronger test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8b03c357ef
commit
8c956fa2a8
|
|
@ -51,6 +51,12 @@ export interface ClassifyOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface CacheEntry {
|
interface CacheEntry {
|
||||||
|
// Local-cache schema version, controlled by gstack. Not to be confused
|
||||||
|
// with `gbrain doctor --json` output schema_version (gbrain v0.25+ emits
|
||||||
|
// schema_version: 2). Doctor-output parsing lives in
|
||||||
|
// lib/gstack-memory-helpers.ts:freshDetectEngineTier and accepts both
|
||||||
|
// doctor-output versions. This cache stays strictly at version 1 — a
|
||||||
|
// future shape change here requires an explicit migration.
|
||||||
schema_version: 1;
|
schema_version: 1;
|
||||||
status: LocalEngineStatus;
|
status: LocalEngineStatus;
|
||||||
cached_at: number;
|
cached_at: number;
|
||||||
|
|
|
||||||
|
|
@ -341,4 +341,41 @@ describe("detectEngineTier", () => {
|
||||||
const result = detectEngineTier();
|
const result = detectEngineTier();
|
||||||
expect(result.engine).toBe("supabase");
|
expect(result.engine).toBe("supabase");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("parses schema_version:2 doctor JSON via the exec path (regression for #1418)", () => {
|
||||||
|
// Stronger pin than the PATH-stripped fallback above: install a fake
|
||||||
|
// gbrain shim that successfully exits with status 1 (health_score < 100,
|
||||||
|
// mirroring real-world Supabase brains) and emits the v2 doctor JSON
|
||||||
|
// shape — schema_version: 2, status: "warnings", no top-level `engine`.
|
||||||
|
// The parser must still produce a usable EngineDetect by falling back
|
||||||
|
// to GBRAIN_HOME/config.json when `engine` is absent from doctor output.
|
||||||
|
const binDir = mkdtempSync(join(tmpdir(), "gstack-gbrain-shim-"));
|
||||||
|
const shim = join(binDir, "gbrain");
|
||||||
|
writeFileSync(
|
||||||
|
shim,
|
||||||
|
`#!/bin/sh
|
||||||
|
if [ "$1" = "doctor" ]; then
|
||||||
|
cat <<'JSON'
|
||||||
|
{"schema_version":2,"status":"warnings","health_score":90,"checks":[{"name":"resolver_health","status":"ok","message":"42 skills"}]}
|
||||||
|
JSON
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ "$1" = "--version" ]; then
|
||||||
|
echo "gbrain 0.35.0.0"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
`,
|
||||||
|
{ mode: 0o755 }
|
||||||
|
);
|
||||||
|
process.env.PATH = `${binDir}:${process.env.PATH || ""}`;
|
||||||
|
writeFileSync(
|
||||||
|
join(testGbrainHome, "config.json"),
|
||||||
|
JSON.stringify({ engine: "pglite" }),
|
||||||
|
"utf-8"
|
||||||
|
);
|
||||||
|
const result = detectEngineTier();
|
||||||
|
expect(result.engine).toBe("pglite");
|
||||||
|
rmSync(binDir, { recursive: true, force: true });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue