Repository navigation
Fence new daemon work while a rename retires it - #1271
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Admission and the idle check share one lock, so no launch, local spawn or eval prepare can slip in between them; a committed fence is persisted so a restarted process under the old name inherits it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fence is taken before leftover recovery and committed only just before bootout, so every refusal leaves both ids as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Those refusals left the old service running, yet the lane still marked its id retired and refused the next rename as already done. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/agentic_review |
PR Summary by QodoFence daemon work before retiring a service during rename
AI Description
Diagram
High-Level Assessment
Files changed (42)
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Code Review by Qodo
1.
|
A rename whose old plist is gone now refuses a still-loaded label instead of leaving that daemon running beside the renamed one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A cancel removes a run from the cache while its question may still run, and a marker left after a confirmed bootout would fence a daemon renamed back within the lease. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit 3356e75 |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AI-2704 (Linear-only; there is no GitHub issue)
What & why
A rename boots out the old daemon, killing whatever it runs. Settings' idle check was a stale snapshot, so a launch admitted between it and the bootout was killed — including work still in the consent prompt or worktree setup, local
kcap agent startspawns and eval runs. The daemon now has one admission fence: server launches, local spawns and eval prepares admit through it, and a rename acquires it only when nothing is in flight and the daemon is idle, under the same lock. The CLI holds it over the control socket from before leftover-marker recovery, commits it just before bootout, and refuses withagents_active,fence_unsupportedorfence_unavailable(exit 30) otherwise. Settings restores the saved name on those, and the lane no longer marks the old id retired after a refusal that changed nothing — which also blocked a retry aftertarget_occupied.Where to look
A committed fence is written to disk before the daemon answers, survives the CLI's connection, and is inherited by a restarted process under the old name; only abort on the open connection or a 2-minute lease lifts it. A CLI that dies between commit and bootout can leave an idle daemon closed to new work for that lease — deliberate, since a broken connection is indistinguishable from one mid-bootout. A running daemon older than the fence fails closed (
fence_unsupported): restart it, then rename. The design is indocs/superpowers/specs/.Verification
New daemon tests drive admission versus acquire, commit/abort/close/lease, marker inheritance and unreadable markers, and refused launches, spawns and prepares over a real socket. ServiceVerify retire tests cover each refusal before anything changes; a mutant that skips the fence fails 7 of them. App tests cover name restore and the lane retry.
🤖 Generated with Claude Code