fix(gbrain): honor GBRAIN_HOME as workspace root, not state dir

gstack-gbrain-detect, gbrain-local-status.ts, and gbrain-exec.ts all
resolved GBRAIN_HOME/config.json when GBRAIN_HOME was set, but fell
back to $HOME/.gbrain/config.json (nested) when unset. The real
gbrain CLI always nests state under a .gbrain dir inside GBRAIN_HOME
regardless — confirmed empirically, pointing GBRAIN_HOME straight at
the .gbrain dir breaks the CLI with "No brain configured".

Net effect for any relocated-GBRAIN_HOME setup: gstack-gbrain-detect
always reported gbrain_config_exists:false and gbrain_local_status
"missing-config" even with a fully working gbrain install, and
buildGbrainEnv silently never seeded DATABASE_URL for spawned gbrain
calls. Every /sync-gbrain and /setup-gbrain invocation hit this.

Fix: always join GBRAIN_HOME (or the userHome fallback) with ".gbrain"
before appending "config.json", in all three places.
This commit is contained in:
kajetanma 2026-07-20 10:58:59 +02:00
parent a3259400a3
commit f87e9ca1f8
3 changed files with 25 additions and 4 deletions

View File

@ -51,8 +51,16 @@ const CONFIG_BIN = join(SCRIPT_DIR, "gstack-config");
// Honors GBRAIN_HOME — must stay consistent with lib/gbrain-local-status's
// config resolution, or the detect JSON reports gbrain_local_status "ok"
// alongside gbrain_config_exists false for relocated-home users.
// The real `gbrain` CLI always nests state under a `.gbrain` dir inside
// GBRAIN_HOME (GBRAIN_HOME is the workspace root, not the state dir itself —
// confirmed empirically: pointing GBRAIN_HOME straight at the `.gbrain` dir
// breaks the CLI with "No brain configured"). This used to join GBRAIN_HOME
// directly with "config.json" when set, only adding the nested ".gbrain" in
// the unset/default-to-userHome fallback — a relocated-GBRAIN_HOME user
// always got a false gbrain_config_exists:false.
const GBRAIN_CONFIG = join(
process.env.GBRAIN_HOME || join(userHome(), ".gbrain"),
process.env.GBRAIN_HOME || userHome(),
".gbrain",
"config.json",
);
const CLAUDE_JSON = join(userHome(), ".claude.json");

View File

@ -98,8 +98,13 @@ export function buildGbrainEnv(opts: BuildGbrainEnvOptions = {}): NodeJS.Process
const out: NodeJS.ProcessEnv = { ...baseEnv };
if (baseEnv.GSTACK_RESPECT_ENV_DATABASE_URL === "1") return out;
// GBRAIN_HOME is the workspace root; the real `gbrain` CLI always nests
// its state under a `.gbrain` dir inside it (confirmed empirically —
// pointing GBRAIN_HOME straight at `.gbrain` breaks the CLI). This used
// to join GBRAIN_HOME directly with "config.json", silently failing to
// seed DATABASE_URL for any relocated-GBRAIN_HOME user.
const homeBase = baseEnv.HOME || homedir();
const gbrainHome = baseEnv.GBRAIN_HOME || join(homeBase, ".gbrain");
const gbrainHome = join(baseEnv.GBRAIN_HOME || homeBase, ".gbrain");
const configPath = join(gbrainHome, "config.json");
if (!existsSync(configPath)) return out;

View File

@ -114,10 +114,18 @@ export function cacheFilePath(): string {
);
}
/** Honors GBRAIN_HOME (codex D11) — same resolution as buildGbrainEnv. */
/**
* Honors GBRAIN_HOME (codex D11) same resolution as buildGbrainEnv.
* GBRAIN_HOME is the workspace root; the real `gbrain` CLI always nests its
* state under a `.gbrain` dir inside it (confirmed empirically pointing
* GBRAIN_HOME straight at `.gbrain` breaks the CLI). This used to join
* GBRAIN_HOME directly with "config.json" when set, only nesting under
* ".gbrain" in the unset/default fallback a relocated-GBRAIN_HOME user
* always got a false gbrain_config_exists:false.
*/
function gbrainConfigPath(env?: NodeJS.ProcessEnv): string {
const e = env ?? process.env;
const gbrainHome = e.GBRAIN_HOME || join(userHome(e), ".gbrain");
const gbrainHome = join(e.GBRAIN_HOME || userHome(e), ".gbrain");
return join(gbrainHome, "config.json");
}