Summary
brain-aware planning (v1.52) advertises support for "any thin-client MCP" brain, but the
classifier lib/gbrain-local-status.ts freshClassify() probes via gbrain sources list --json — a local-DB-only command. Under thin-client mode this is intentionally not
routable, so the probe throws, the catch falls through to the defensive broken-config
default, and gen-skill-docs --respect-detection suppresses every brain block. A healthy
thin-client brain therefore never gets brain-aware planning.
Environment
- gstack
v1.52.1.0 (current main, 070722a)
- gbrain
0.41.28.0, thin-client mode (remote MCP over HTTP; no local DB)
- Cause is OS-independent (first hit on Windows, but not platform-specific)
Reproduction
- Configure gbrain as a thin-client (remote
mcp_url, no local engine). Doctor is healthy:
gbrain doctor --json --fast → {"mode":"thin-client","status":"ok",...}
- The probe command is refused by design:
$ gbrain sources list --json
`gbrain sources` is not routable. sources commands manage local DB + config rows.
Per-subcommand thin-client routing lands in v0.31.x. For now: use `sources_list` /
`sources_status` MCP tools, or run on the host. (exit 1)
gstack-config gbrain-refresh → ~/.gstack/gbrain-detection.json shows
"gbrain_doctor_ok": true, "gbrain_mcp_mode": "remote-http", "gbrain_local_status": "broken-config"
(healthy thin-client, yet broken-config).
bun run gen:skill-docs:user → planning SKILL.md files contain no brain blocks
(gen-skill-docs.ts:50 un-suppresses only when gbrain_local_status === 'ok').
Root cause
In lib/gbrain-local-status.ts freshClassify(), once the on-PATH check (L224) and
config-exists check (L227) pass — both true for a thin-client — it probes with
execFileSync("gbrain", ["sources","list","--json"]) (L239). gbrain sources is local-DB-only
and explicitly not routable in thin-client mode, so the call throws; the stderr matches neither
"Cannot connect to database" nor "config.json", hitting the defensive broken-config
default (L260). The 5-state enum has no healthy-thin-client path and freshClassify never
checks the mode.
Suggested fix
Detect thin-client mode before the sources list probe and treat a healthy thin-client as
ok. The signal already exists: gbrain doctor --json --fast returns mode: "thin-client" +
status: ok|warnings, and detect already calls it in detectDoctor() (bin/gstack-gbrain-detect
:121) — the mode field is one parse away. detectMcpMode() independently returns remote-http
too. e.g. in freshClassify: if doctor reports thin-client mode and ok/warnings status, return
"ok" without running the host/local-DB-only sources list probe.
Workaround (until fixed)
Override detection externally, no gstack edits: confirm health via gbrain doctor, then write
"gbrain_local_status": "ok" into ~/.gstack/gbrain-detection.json (keeping the other real
detect fields) and run bun run gen:skill-docs:user. Must be re-run after every ./setup or
gstack-config gbrain-refresh, since both rewrite detection.json from the broken probe.
Secondary (minor)
scripts/resolvers/gbrain.ts generateGBrainContextLoad tells the agent to run
gbrain get_page "<slug>", but the thin-client CLI has no get_page subcommand
(Unknown command: get_page); the CLI verb is gbrain get. (get_page is the MCP op name.)
Summary
brain-aware planning (v1.52) advertises support for "any thin-client MCP" brain, but the
classifier
lib/gbrain-local-status.tsfreshClassify()probes viagbrain sources list --json— a local-DB-only command. Under thin-client mode this is intentionally notroutable, so the probe throws, the catch falls through to the defensive
broken-configdefault, and
gen-skill-docs --respect-detectionsuppresses every brain block. A healthythin-client brain therefore never gets brain-aware planning.
Environment
v1.52.1.0(currentmain,070722a)0.41.28.0, thin-client mode (remote MCP over HTTP; no local DB)Reproduction
mcp_url, no local engine). Doctor is healthy:gbrain doctor --json --fast→{"mode":"thin-client","status":"ok",...}gstack-config gbrain-refresh→~/.gstack/gbrain-detection.jsonshows"gbrain_doctor_ok": true, "gbrain_mcp_mode": "remote-http", "gbrain_local_status": "broken-config"(healthy thin-client, yet
broken-config).bun run gen:skill-docs:user→ planning SKILL.md files contain no brain blocks(
gen-skill-docs.ts:50un-suppresses only whengbrain_local_status === 'ok').Root cause
In
lib/gbrain-local-status.tsfreshClassify(), once the on-PATH check (L224) andconfig-exists check (L227) pass — both true for a thin-client — it probes with
execFileSync("gbrain", ["sources","list","--json"])(L239).gbrain sourcesis local-DB-onlyand explicitly not routable in thin-client mode, so the call throws; the stderr matches neither
"Cannot connect to database"nor"config.json", hitting the defensivebroken-configdefault (L260). The 5-state enum has no healthy-thin-client path and
freshClassifyneverchecks the mode.
Suggested fix
Detect thin-client mode before the
sources listprobe and treat a healthy thin-client asok. The signal already exists:gbrain doctor --json --fastreturnsmode: "thin-client"+status: ok|warnings, anddetectalready calls it indetectDoctor()(bin/gstack-gbrain-detect:121) — the
modefield is one parse away.detectMcpMode()independently returnsremote-httptoo. e.g. in
freshClassify: if doctor reports thin-client mode and ok/warnings status, return"ok"without running the host/local-DB-onlysources listprobe.Workaround (until fixed)
Override detection externally, no gstack edits: confirm health via
gbrain doctor, then write"gbrain_local_status": "ok"into~/.gstack/gbrain-detection.json(keeping the other realdetect fields) and run
bun run gen:skill-docs:user. Must be re-run after every./setuporgstack-config gbrain-refresh, since both rewrite detection.json from the broken probe.Secondary (minor)
scripts/resolvers/gbrain.tsgenerateGBrainContextLoadtells the agent to rungbrain get_page "<slug>", but the thin-client CLI has noget_pagesubcommand(
Unknown command: get_page); the CLI verb isgbrain get. (get_pageis the MCP op name.)