Skip to content

docs(worktree): scratch space is not isolated between workers - #351

Merged
stellarfeline merged 1 commit into
mainfrom
docs/worker-scratch-isolation
Aug 10, 2026
Merged

docs(worktree): scratch space is not isolated between workers#351
stellarfeline merged 1 commit into
mainfrom
docs/worker-scratch-isolation

Conversation

@stellarfeline

Copy link
Copy Markdown
Owner

The harness hands every worker a scratchpad path it calls "session-specific, isolated". The isolating token is the planner session's id — so every worker fanned out from one dispatch gets the same string. One flat directory, no per-agent segment.

Measured, 2026-08-09. Four concurrent workers, four independent before/after trees, one namespace:

worker names chosen
1 base/ · after/
2 out-base/ · out-new/ (both nobodys-cave-island)
3 zh-base/ · zh-new/
4 out/base-<campaign> · out/new-<campaign>

Worker 1's base/ was replaced mid-run by worker 2's repo checkout — verified: $SP/base/campaigns now resolves into wt-state. Worker 1's own setup line was rm -rf $SP/base && mkdir -p $SP/base, so with the arrival order reversed it would have deleted worker 2's tree. Same shape as the git add -A near-miss the constitution already records, one layer over.

This was not bad luck. A before/after byte comparison is the evidence this project demands of everyone who touches emission, and base is the first word all of them reach for.

Why it is worse than a lost directory

The loud failure is the safe one — worker 1 got ENOENT and noticed. The quiet one is the danger. A byte-identity proof is find base/ | shasum against the same over after/. Had the foreign tree landed before the hash instead of after, the run would have hashed someone else's repo. Worse: worker 2 was writing build outputs of the same campaign. Had those names collided, a worker could have compared worker 2's before-tree against worker 2's after-tree and reported its own change byte-identical — hundreds of files, all matching, a number nobody can re-derive from the PR.

That is a green gate that binds to nothing, and review cannot see it, because the output is indistinguishable from a pass.

The asymmetry against the worktree-collision precedent this mirrors: a code leak fails CI; a corrupted evidence tree fails nothing. It emits a sentence in a PR description.

What this PR does, and what it does not

Adopts the convention — each worker gets its own scratch subdirectory, named in the dispatch prompt, same token as its worktree — and records the measurement so the next session does not rediscover it.

It does not build the real fix, which is named in the file: a baseline hash manifest that records the git SHA and delvec --version it was produced from, with the comparison asserting them. That turns a swapped tree into a loud failure and covers every piece of before/after evidence, not just the ones in a shared directory. Filed separately.

What CI proves

Doc-only. check-doc-dupes and check-reference-versions green.

The harness scratchpad path's isolating token is the PLANNER SESSION's id, so
every worker fanned out from one dispatch is handed the same string. It is one
flat directory. Measured 2026-08-09: four concurrent workers all built
before/after trees in it — base/after, out-base/out-new, zh-base/zh-new,
out/base-<campaign>/out/new-<campaign> — and one worker's base/ was replaced
mid-run by another's repo checkout. Its own setup line was 'rm -rf $SP/base',
so with the arrival order reversed it would have deleted the other tree.

Not bad luck: a before/after byte comparison is the evidence this project
demands of everyone touching emission, and 'base' is the word all of them reach
for.

The loud failure is the safe one — that worker got ENOENT and noticed. The
quiet one is a byte-identity proof that hashed somebody else's tree. Another
worker was writing outputs of the SAME campaign under out-base/out-new; had the
names collided, a worker could have compared that worker's before against that
worker's after and reported its own change byte-identical. A green that binds to
nothing, invisible to review because it looks exactly like a pass.

Asymmetry against the worktree-collision precedent this mirrors: a code leak
fails CI; a corrupted evidence tree fails nothing.

Convention adopted: each worker gets its own scratch subdirectory, named in the
dispatch prompt, same token as its worktree. The stronger fix is named but not
built here — a baseline manifest that records the git SHA and delvec version it
came from, and a comparison that asserts them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AjQ5p1Kv5MrkGPumi7yXWL
@stellarfeline
stellarfeline merged commit 1ae0452 into main Aug 10, 2026
12 checks passed
@stellarfeline
stellarfeline deleted the docs/worker-scratch-isolation branch August 10, 2026 00:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant