Skip to content

freshClassify health probe uses gbrain sources list, misclassifying healthy thin-client brains as broken-config → brain-aware blocks suppressed #1792

@lucha0404

Description

@lucha0404

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

  1. Configure gbrain as a thin-client (remote mcp_url, no local engine). Doctor is healthy:
    gbrain doctor --json --fast{"mode":"thin-client","status":"ok",...}
  2. 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)
    
  3. 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).
  4. 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.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions