fix: whitelist engine-locked at all three gbrain-usable gates (#2456)

#2194 taught the classifier to report a PGLite lock held by a live
\`gbrain serve\` as engine-locked instead of broken-config, but none of the
three "is gbrain usable?" gates accepted the new status — so the symptom
moved from a wrong error to a quieter wrong suppression: gbrain-refresh
stripped GBRAIN_CONTEXT_LOAD / GBRAIN_SAVE_RESULTS blocks out of every
generated SKILL.md after every upgrade, on the RECOMMENDED /setup-gbrain
default (PGLite + local-stdio MCP spawns gbrain serve at session start).

engine-locked is the same class as timeout (#1964): the engine is
installed and healthy, a legitimate holder has the lock. All three gates
now agree:

- bin/gstack-gbrain-detect --is-ok exits 0 on engine-locked
- bin/gstack-config gbrain-refresh case arm renders instead of suppressing
- scripts/gen-skill-docs.ts --respect-detection treats it as detected

Test mirrors the existing timeout case in
test/gbrain-detection-override.test.ts (engine-locked renders brain
blocks; the sibling no-cli case still proves suppression works).

Applies the reporter's patch + test from the issue.

Fixes #2456

Co-authored-by: Mateus Moraes <mmoraes@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-08-16 10:01:44 -07:00
co-authored by Mateus Moraes Claude Fable 5
parent 5b65f91a8c
commit f9f3c9801a
4 changed files with 56 additions and 20 deletions
+8 -8
View File
@@ -44,14 +44,14 @@ function loadGbrainOverride(): { detected: boolean } {
try {
const json = JSON.parse(fs.readFileSync(detectionPath, 'utf-8')) as { gbrain_local_status?: string };
// "timeout" = slow-but-healthy engine (#1964); "thin-client" = remote-HTTP
// MCP brain with no local engine by design (#2051). Both usable — same
// treatment as "ok", matching gstack-gbrain-detect --is-ok.
return {
detected:
json.gbrain_local_status === 'ok' ||
json.gbrain_local_status === 'timeout' ||
json.gbrain_local_status === 'thin-client',
};
// MCP brain with no local engine by design (#2051); "engine-locked" = same
// class (#2456): PGLite is single-writer, so a live `gbrain serve` (e.g.
// an MCP server) owns the embedded DB — gbrain is installed and healthy,
// a legitimate holder has the lock, so a transient lock must not silently
// strip brain blocks from every SKILL.md. All usable — same treatment as
// "ok", matching gstack-gbrain-detect --is-ok.
const USABLE = ['ok', 'timeout', 'thin-client', 'engine-locked'];
return { detected: USABLE.includes(json.gbrain_local_status ?? '') };
} catch {
return { detected: false };
}