From 9c638da2fd2f3dd194d8bba51690fa5c46a5b872 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sun, 3 May 2026 20:03:25 -0700 Subject: [PATCH] fix: gbrain-sync orchestrator resolves brain-sync sibling via import.meta.dir Codex M9: runBrainSyncPush hardcoded ~/.claude/skills/gstack/bin/gstack-brain-sync, so any host that wasn't Claude Code (Codex CLI, dev workspace) hit the existsSync guard and silently skipped curated-artifact push. Replace with the sibling-resolution pattern already in runMemoryIngest at line 193. Regression test asserts the orchestrator no longer takes the lying-skip path when HOME has no ~/.claude/skills/gstack tree. --- bin/gstack-gbrain-sync.ts | 2 +- test/gstack-gbrain-sync.test.ts | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/bin/gstack-gbrain-sync.ts b/bin/gstack-gbrain-sync.ts index e2ce7a4b..a62c3cb7 100644 --- a/bin/gstack-gbrain-sync.ts +++ b/bin/gstack-gbrain-sync.ts @@ -219,7 +219,7 @@ function runBrainSyncPush(args: CliArgs): StageResult { return { name: "brain-sync", ran: false, ok: true, duration_ms: 0, summary: "would: gstack-brain-sync --discover-new --once" }; } - const brainSyncPath = join(HOME, ".claude", "skills", "gstack", "bin", "gstack-brain-sync"); + const brainSyncPath = join(import.meta.dir, "gstack-brain-sync"); if (!existsSync(brainSyncPath)) { return { name: "brain-sync", ran: false, ok: true, duration_ms: 0, summary: "skipped (gstack-brain-sync not installed)" }; } diff --git a/test/gstack-gbrain-sync.test.ts b/test/gstack-gbrain-sync.test.ts index c8841268..1cd07b89 100644 --- a/test/gstack-gbrain-sync.test.ts +++ b/test/gstack-gbrain-sync.test.ts @@ -137,4 +137,26 @@ describe("gstack-gbrain-sync CLI", () => { expect(state.last_stages.length).toBe(0); rmSync(home, { recursive: true, force: true }); }); + + it("brain-sync stage resolves the sibling binary, not a HOME-rooted path", () => { + // Regression for Codex M9: pre-fix the orchestrator looked up + // ~/.claude/skills/gstack/bin/gstack-brain-sync, which silently no-op'd + // on Codex installs and dev workspaces with the misleading summary + // "skipped (gstack-brain-sync not installed)". Post-fix it resolves + // a sibling via import.meta.dir and actually invokes the script. + const home = makeTestHome(); + const gstackHome = join(home, ".gstack"); + mkdirSync(gstackHome, { recursive: true }); + + const r = runScript( + ["--incremental", "--no-code", "--no-memory", "--quiet"], + { HOME: home, GSTACK_HOME: gstackHome }, + ); + + // Don't assert exit code (sibling spawn may legitimately error in a + // sandboxed test). Assert only that we did NOT take the lying-skip path. + const combined = r.stdout + r.stderr; + expect(combined).not.toContain("skipped (gstack-brain-sync not installed)"); + rmSync(home, { recursive: true, force: true }); + }); });