Fix spawn into mise/direnv repos: inherit trust, retry start, add spawn reap #4
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix-spawn-agent-start-race"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Two celilo spawns created the worktree but never started an agent, leaving orphans behind.
Root cause
The failed pane sat at a shell prompt full of this:
herdr agent startrequires the pane to be at its interactive prompt. Spawn called it the instantworktree createreturned, and a worktree with untrusted config spends its shell startup printing errors instead of getting there.celiloandlunacycleboth have.mise.tomland.envrc— precisely the repos where this bit.Confirmed a race, not a hard failure: the identical
agent starton the identical pane succeeded minutes later.Fix 1 — inherit trust instead of re-asking (removes the cause)
Being prompted to approve "this particular worktree of a project I already trust" is friction with no security value. It's the same file.
The safety rule is what makes this sound:
If the content differs — the base moved ahead of your checkout — that's genuinely new, and spawn says so and leaves it. It can never grant trust the source lacks.
Content equality is the correct test because direnv's own trust is content-keyed: the allow filename is not
sha256(path)(44eaa8…≠96da11…), which is why editing an.envrcrevokes it.Detection uses each tool's own query interface —
direnv status --json→state.foundRC.allowed == 0, andmise trust --show→<path>: trusted, matched exactly sinceuntrustedcontainstrustedas a substring.Fix 2 — retry the start
Three attempts, 3s backoff. Belt and braces now that Fix 1 removes the usual cause.
Fix 3 —
spawn reap <workspace>From the same incident: the agent that hit the failure couldn't clean up after itself. The documented recipe was a compound shell line (
herdr worktree remove … && git branch -D …), the permission classifier blocked it, and two orphaned worktrees were left for the operator. A recovery path an agent can't execute isn't a recovery path.One first-party command now does it. The branch logic is the part worth reviewing:
git branch -drefuses a spawn branch whenever localmaintrailsorigin/main— most of the time (celilo is 23 behind)-Deverywhere would silently eat real workFailure paths now print
spawn reap <ws>instead of the two-command recipe.Verification
inherited direnv+mise trust, briefed agent,TRUST-OKreplymise: trusted ·direnv: allowed=0ROUNDTRIP-OK, clean reapw1P(primary checkout) / unknown workspaceopenspec validate --allSpec gains a trust-inheritance requirement (4 scenarios), a retry scenario, a single-command-recovery scenario, and a
reaprequirement (4 scenarios).Residual
The retry makes the race survivable but doesn't prove it's gone — it never reproduced on demand. Fix 1 should make it moot for the repos where it actually happened.
🤖 Generated with Claude Code
spawn reapfor recoverable cleanup f0b25de72fRetry agent start, and addto Fix spawn into mise/direnv repos: inherit trust, retry start, addspawn reapfor recoverable cleanupspawn reap