fix(sync-gbrain): define Step 4 helper args and one atomic write path

Both census read-ready attempts spent turns reading the helper source to
resolve <user-args>, inspecting fixture internals kept inside the repo,
and reconciling 'Read + Edit' with the tmp+mv atomic write, then hit
max turns before the verdict.
This commit is contained in:
garrytan committed 2026-09-29 16:19:39 +00:00
1 parent 5c900eb18c
commit 39fc663894
3 files changed
+26 -15

No files matched your search

+10 -5
View File
@@ -672,6 +672,10 @@ Capability check (per /plan-eng-review §6):
bun run ~/.claude/skills/gstack/bin/gstack-gbrain-read-capability.ts <user-args>
```
`<user-args>` are the same flags this /sync-gbrain invocation passed to Step 2,
unchanged (empty for a plain run). The helper needs no other input: run it once
and use its JSON result; do not inspect its source or the gbrain CLI first.
The helper reports JSON `status: ready` only after the successful code sync's
source and real worktree match `.gbrain-source`, the source registration points
to that worktree, and a bounded, source-scoped list/get returns the same page.
@@ -746,16 +750,17 @@ sync code walk for them requires an explicit `--allow-reclone` opt-in.
<!-- gstack-gbrain-search-guidance:end -->
```
Use the Read + Edit tools. The find-and-replace target is the entire region
from `<!-- gstack-gbrain-search-guidance:start -->` through
Read CLAUDE.md once and compute its new content. The replacement target is
the entire region from `<!-- gstack-gbrain-search-guidance:start -->` through
`<!-- gstack-gbrain-search-guidance:end -->`. If those markers are missing,
search for `## GBrain Search Guidance (configured by /sync-gbrain)` heading
and replace from there to the next `## ` or EOF. If no heading exists, append
the entire block at the end of CLAUDE.md.
**Atomic write:** write the new CLAUDE.md content to a tmp file alongside it
(e.g., `CLAUDE.md.sync-gbrain.tmp`) then `mv` to atomic-rename, so a crash
mid-write never leaves the file half-modified.
**Atomic write (the only write path; do not Edit CLAUDE.md in place):** Write
the complete new content to `CLAUDE.md.sync-gbrain.tmp` beside it, then `mv` it
over CLAUDE.md, so a crash mid-write never leaves the file half-modified. Verify
the block count in the same Bash call as the `mv`, then go to Step 5.
**If `status=unknown`** — preserve the existing guidance block, if any, and
report the helper's reason as WARN with advice to retry `/sync-gbrain` or the
+10 -5
View File
@@ -323,6 +323,10 @@ Capability check (per /plan-eng-review §6):
bun run ~/.claude/skills/gstack/bin/gstack-gbrain-read-capability.ts <user-args>
```
`<user-args>` are the same flags this /sync-gbrain invocation passed to Step 2,
unchanged (empty for a plain run). The helper needs no other input: run it once
and use its JSON result; do not inspect its source or the gbrain CLI first.
The helper reports JSON `status: ready` only after the successful code sync's
source and real worktree match `.gbrain-source`, the source registration points
to that worktree, and a bounded, source-scoped list/get returns the same page.
@@ -397,16 +401,17 @@ sync code walk for them requires an explicit `--allow-reclone` opt-in.
<!-- gstack-gbrain-search-guidance:end -->
```
Use the Read + Edit tools. The find-and-replace target is the entire region
from `<!-- gstack-gbrain-search-guidance:start -->` through
Read CLAUDE.md once and compute its new content. The replacement target is
the entire region from `<!-- gstack-gbrain-search-guidance:start -->` through
`<!-- gstack-gbrain-search-guidance:end -->`. If those markers are missing,
search for `## GBrain Search Guidance (configured by /sync-gbrain)` heading
and replace from there to the next `## ` or EOF. If no heading exists, append
the entire block at the end of CLAUDE.md.
**Atomic write:** write the new CLAUDE.md content to a tmp file alongside it
(e.g., `CLAUDE.md.sync-gbrain.tmp`) then `mv` to atomic-rename, so a crash
mid-write never leaves the file half-modified.
**Atomic write (the only write path; do not Edit CLAUDE.md in place):** Write
the complete new content to `CLAUDE.md.sync-gbrain.tmp` beside it, then `mv` it
over CLAUDE.md, so a crash mid-write never leaves the file half-modified. Verify
the block count in the same Bash call as the `mv`, then go to Step 5.
**If `status=unknown`** — preserve the existing guidance block, if any, and
report the helper's reason as WARN with advice to retry `/sync-gbrain` or the
@@ -6,10 +6,11 @@ import { spawnSync } from 'node:child_process';
const root = path.resolve(import.meta.dir, '../..');
export function createReadinessFixture(kind: 'ready' | 'unknown') {
const workDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gbrain-ready-'));
const home = path.join(workDir, '.fixture-home');
const bin = path.join(workDir, '.fixture-bin');
fs.mkdirSync(home); fs.mkdirSync(bin);
const base = fs.mkdtempSync(path.join(os.tmpdir(), 'gbrain-ready-'));
const workDir = path.join(base, 'repo');
const home = path.join(base, 'home');
const bin = path.join(base, 'bin');
fs.mkdirSync(workDir); fs.mkdirSync(home); fs.mkdirSync(bin);
const init = spawnSync('git', ['init', '--quiet'], { cwd: workDir, timeout: 10_000 });
if (init.status !== 0) throw new Error('readiness fixture git init failed');
fs.writeFileSync(path.join(workDir, '.gbrain-source'), 'client-fixture\n');
@@ -57,6 +58,6 @@ else { console.error('unsupported operation'); process.exit(3); }
sourceIntact: () => fs.readFileSync(path.join(workDir, '.gbrain-source'), 'utf8') === pin
&& fs.readFileSync(path.join(stateDir, '.gbrain-sync-state.json'), 'utf8') === state
&& !fs.existsSync(path.join(workDir, 'code')),
cleanup: () => fs.rmSync(workDir, { recursive: true, force: true }),
cleanup: () => fs.rmSync(base, { recursive: true, force: true }),
};
}