mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-15 01:15:29 +02:00
fix(gbrain): classify probe timeout as its own status; sync proceeds instead of skipping (#1964)
The 5s engine probe misclassified healthy-but-slow engines (cold Supabase pooler connections measured at 6.9-10.7s) as broken-config, so /sync-gbrain silently skipped code+memory and told the user their config was malformed. - New "timeout" status: probe killed at the deadline with no recognized stderr pattern. Default deadline is now 15s, overridable via GSTACK_GBRAIN_PROBE_TIMEOUT_MS (tests set 300ms against a fake that sleeps 2s). - Sync stages PROCEED on timeout with a stderr warning naming the env knob; a genuinely-dead engine surfaces its real error at the first operation instead of a false config diagnosis. - Consistency everywhere "ok" gated behavior: gstack-gbrain-detect --is-ok exits 0 on timeout, and gen-skill-docs' detection gate accepts it, so a slow engine no longer silently suppresses brain-aware features. - Status cache: key now includes the effective probe timeout (raising it invalidates a cached timeout) and GBRAIN_HOME; config detection honors GBRAIN_HOME so relocated-home users stop being misclassified as missing-config. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
8e4662e930
commit
da06ef1504
@@ -42,7 +42,7 @@ interface FakeEnv {
|
||||
*/
|
||||
function makeEnv(opts: {
|
||||
withGbrain: boolean;
|
||||
gbrainBehavior?: "ok" | "broken-db" | "broken-config";
|
||||
gbrainBehavior?: "ok" | "broken-db" | "broken-config" | "slow";
|
||||
withConfig: boolean;
|
||||
}): FakeEnv {
|
||||
const tmp = mkdtempSync(join(tmpdir(), "gbrain-sync-skip-"));
|
||||
@@ -65,19 +65,26 @@ function makeEnv(opts: {
|
||||
|
||||
if (opts.withGbrain) {
|
||||
const behavior = opts.gbrainBehavior || "ok";
|
||||
const stderrLine =
|
||||
behavior === "broken-db"
|
||||
? 'echo "Cannot connect to database: . Fix: Check your connection URL in ~/.gbrain/config.json" >&2'
|
||||
: behavior === "broken-config"
|
||||
? 'echo "Error: malformed config.json" >&2'
|
||||
: "";
|
||||
const exitCode = behavior === "ok" ? 0 : 1;
|
||||
// "slow": healthy engine, cold pooler connection (#1964) — sleeps past the
|
||||
// (test-lowered) probe timeout on `sources list`, then answers fine.
|
||||
const sourcesBlock =
|
||||
behavior === "slow"
|
||||
? ` sleep 2
|
||||
echo '{"sources":[]}'
|
||||
exit 0`
|
||||
: behavior === "ok"
|
||||
? ` echo '{"sources":[]}'
|
||||
exit 0`
|
||||
: ` ${
|
||||
behavior === "broken-db"
|
||||
? 'echo "Cannot connect to database: . Fix: Check your connection URL in ~/.gbrain/config.json" >&2'
|
||||
: 'echo "Error: malformed config.json" >&2'
|
||||
}
|
||||
exit 1`;
|
||||
const fake = `#!/bin/sh
|
||||
if [ "$1" = "--version" ]; then echo "gbrain 0.33.1.0"; exit 0; fi
|
||||
if [ "$1 $2" = "sources list" ]; then
|
||||
if [ ${exitCode} -eq 0 ]; then echo '{"sources":[]}'; exit 0; fi
|
||||
${stderrLine}
|
||||
exit ${exitCode}
|
||||
${sourcesBlock}
|
||||
fi
|
||||
if [ "$1" = "--help" ]; then echo " import"; exit 0; fi
|
||||
exit 0
|
||||
@@ -95,7 +102,11 @@ exit 0
|
||||
};
|
||||
}
|
||||
|
||||
function runOrchestrator(env: FakeEnv, args: string[]): { stdout: string; stderr: string; exitCode: number } {
|
||||
function runOrchestrator(
|
||||
env: FakeEnv,
|
||||
args: string[],
|
||||
extraEnv: Record<string, string> = {},
|
||||
): { stdout: string; stderr: string; exitCode: number } {
|
||||
// Initialize a git repo in the sandbox so repoRoot() finds it (otherwise
|
||||
// code stage skips with "not in git repo" before our check ever fires).
|
||||
spawnSync("git", ["init", "-q", env.home], { encoding: "utf-8" });
|
||||
@@ -113,6 +124,7 @@ function runOrchestrator(env: FakeEnv, args: string[]): { stdout: string; stderr
|
||||
HOME: env.home,
|
||||
GSTACK_HOME: env.gstackHome,
|
||||
PATH: `${env.bindir}:/usr/bin:/bin`,
|
||||
...extraEnv,
|
||||
},
|
||||
});
|
||||
return {
|
||||
@@ -123,6 +135,23 @@ function runOrchestrator(env: FakeEnv, args: string[]): { stdout: string; stderr
|
||||
}
|
||||
|
||||
describe("gstack-gbrain-sync — split-engine SKIP (plan D12)", () => {
|
||||
it("PROCEEDS (with warning) when the engine probe times out — slow is not broken (#1964)", () => {
|
||||
const env = makeEnv({ withGbrain: true, gbrainBehavior: "slow", withConfig: true });
|
||||
try {
|
||||
const r = runOrchestrator(env, ["--code-only"], {
|
||||
GSTACK_GBRAIN_PROBE_TIMEOUT_MS: "300",
|
||||
});
|
||||
const out = r.stdout + r.stderr;
|
||||
// The stage must NOT be skipped with the local-engine reason...
|
||||
expect(out).not.toContain("local engine timeout");
|
||||
expect(out).not.toContain("config.json is malformed");
|
||||
// ...and the proceed-with-warning line must name the env knob.
|
||||
expect(out).toContain("GSTACK_GBRAIN_PROBE_TIMEOUT_MS");
|
||||
} finally {
|
||||
env.cleanup();
|
||||
}
|
||||
}, 30_000); // proceeding runs the real code-import path against the slow fake (~11s)
|
||||
|
||||
it("SKIPs code stage when local engine is broken-db; brain-sync still attempted", () => {
|
||||
const env = makeEnv({ withGbrain: true, gbrainBehavior: "broken-db", withConfig: true });
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user