fix(resident): honor named refs over sticky bindings - #2192
Conversation
There was a problem hiding this comment.
Changes requested: Named-ref rollback can leave the stored binding and checked-out branch inconsistent, and two resident spec items still contradict the new behavior.
Warning
Changes requested · head 57dc22a · 3 findings: 1 major, 2 minor
| Severity | Finding | Where |
|---|---|---|
| major | F1 Rollback restores the old ref without restoring its worktree | deploy/cloudflare-resident/worker.ts:6139 |
| minor | F2 Spec contradiction — resident-repos.md item 30: differing named hints now replace the binding rather than being ignored | docs/reference/specs/resident-repos.md:46 |
| minor | F3 Spec contradiction — resident-repos.md item 66: a readable reuse attach can now be refused when the ref changed | docs/reference/specs/resident-repos.md:97 |
Full review
F1 — A named-ref attach can recreate the checkout on the new branch, then fail while materializing dependencies or credentials. The rollback restores the old binding but leaves the checkout on the new branch. If both refs share a tip, the next attach for the old ref sees a clean matching HEAD and reuses the wrong local branch, so work or pushes can target the wrong branch. Roll back the worktree too, or defer the binding change until the entire attach succeeds.
F2 — Item 30 still says a later differing hint is ignored and requires a new thread. Update it to state that an explicitly named ref replaces the sticky fallback.
F3 — Item 66 says every readable reuse attach is reused and lists only missing, unreadable, or mode-switched trees as refusals. The new refChanged path also refuses a readable tree; document that exception and its proof.
57dc22a to
9b91573
Compare
There was a problem hiding this comment.
Changes requested: An explicit same-ref attach does not persist named authority, so a later own-PR hint can still move the binding.
Warning
Changes requested · head 9b91573 · 1 finding: 1 minor
| Severity | Finding | Where |
|---|---|---|
| minor | F1 Spec contradiction — docs/reference/specs/resident-repos.md item 16: explicit same-ref attach remains default-bound | deploy/cloudflare-resident/worker.ts:5430 |
Full review
F1 — replacingRef requires the ref string to change, so explicitly naming the already-bound default branch returns the existing row without changing boundBy to name. A later own-PR-derived attach can therefore move a branch the requester explicitly pinned, contrary to item 16. Separate named authority from path replacement: persist the named provenance even when existing.ref === ref, while avoiding unnecessary checkout recreation.
There was a problem hiding this comment.
LGTM: The named-ref rebinding, provisional checkout rollback, and coordinator branch reconciliation are coherent and covered by the updated contracts.
Note
Approved · head 9b91573 · no findings
Full review
No findings. The change is ready to merge.
9b91573 to
7915dfb
Compare
|
Re-review requested at 7915dfb — F1 from the second arm (an explicit same-ref attach kept |
There was a problem hiding this comment.
LGTM: The named-ref authority and atomic replacement flow are consistent with the updated specs and preserve the fallback and own-PR cases.
Note
Approved · head 7915dfb · no findings
Full review
No findings. The named-ref authority and atomic replacement flow match the updated specifications.
There was a problem hiding this comment.
Changes requested: An explicit named ref can still be silently overridden by stale return metadata.
Warning
Changes requested · head 7915dfb · 1 finding: 1 major
| Severity | Finding | Where |
|---|---|---|
| major | F1 Explicit named refs can be bypassed by a historical return record | src/execution/resident.ts:1316 |
Full review
F1 — returned is persisted binding history, not proof that this attach legitimately moved the requested ref. An older worker can return main for an explicit fix/x request while carrying a historical {from: "fix/x", to: "main"} record, causing the client to accept and run on the wrong branch. Remove the returnedFromHint exemption; legitimate own-PR-derived returns are already exempt through ownPr.
7915dfb to
13b744c
Compare
|
Re-review requested at 13b744c — F1 from the third round (a historical |
There was a problem hiding this comment.
LGTM: Named-ref rebinding is fail-closed and transactionally preserves the prior binding on attach failure, with aligned specs and regression coverage.
Note
Approved · head 13b744c · no findings
Full review
No actionable findings. The named-ref rebinding and rollback behavior are consistent with the updated specs and regression coverage.
There was a problem hiding this comment.
Changes requested: A thrown disk-admission failure can publish a replacement ref even though the attach never succeeds.
Warning
Changes requested · head 13b744c · 1 finding: 1 major
| Severity | Finding | Where |
|---|---|---|
| major | F1 Spec contradiction — resident-repos.md item 16: a failed attach can persist the replacement binding | deploy/cloudflare-resident/worker.ts:5715 |
Full review
F1 — For an evicted prior binding, allocateThreadUser immediately persists the replacement because deferRefWrite is false. If any run or storage operation inside admitThreadDisk throws, execution escapes before the rollback-protected block, leaving the new sticky ref stored even though the attach failed. A later unnamed attach can therefore bind to the failed replacement branch. Keep the replacement provisional through disk admission, or catch admission failures and restore the prior binding before rethrowing.
|
Parked for the morning after four review rounds (13 verdicts across 57dc22a → 9b91573 → 7915dfb → 13b744c): each round's fix to the named-ref rebinding exposed one more path where a binding is written before the whole attach has succeeded — rollback consistency (r1), same-ref authority (r2), the stale |
Co-Authored-By: coreplane-switchboard[bot] <318072483+coreplane-switchboard[bot]@users.noreply.github.com>
Co-Authored-By: coreplane-switchboard[bot] <318072483+coreplane-switchboard[bot]@users.noreply.github.com>
Co-Authored-By: coreplane-switchboard[bot] <318072483+coreplane-switchboard[bot]@users.noreply.github.com>
Co-Authored-By: coreplane-switchboard[bot] <318072483+coreplane-switchboard[bot]@users.noreply.github.com>
13b744c to
b194744
Compare
A re-issued ship attempt's coding child worked and pushed on the previous attempt's unit branch because the resident's sticky ref binding outlived the attempt that set it (#2169: attempt 2 of the #2141 fix was labelled
…9e347f/u1, its hand-off recorded the resident-bound…dd8be2/u1, and PR #2168 opened from the older branch).Why. A child's branch is the one its spawn names; the resident's sticky binding is a fallback for an ask that names none, never an override of a named ref; and the pipeline row records the ref the child actually pushed so the row and the PR head agree. Fixes #2169.
Where to look. 1.
deploy/cloudflare-resident/worker.ts— a namedrefHint(not the by-default resolution, no own-PR move) is authoritative and re-binds the sticky binding to it. 2.src/execution/resident.ts— the attach fails closed when a Worker predating the invariant answers another ref than the one named. 3.src/channels/adminCoordinator.ts— afterpr_openedthe unit row adopts the pushed PR head ref when the run's own push record names it. 4.src/execution/residentReuse.ts— a ref change recreates the worktree instead of reusing another ref's tree. Regressions inresident.test.ts,rebindAttach.test.ts,adminCoordinator.test.ts; spec rows inresident-repos.mdandagent-ship.md.Risk. The resident attach path; a wrong precedence would provision the wrong branch — the fail-closed check in
resident.tsnames the mismatch instead.Verified. 311 focused tests, scoped typecheck, formatting, hygiene, specs and title checks passed in the coding run (
d28e8940); the ship runner aborted the unit under the Worker/container skew (#2187) after the push, so this PR is opened by the operator from the pushed head.Receipt runnable when: worker:bot ≥ this PR's merge sha and event: an
agent:shipre-issue of a died attempt — the child's card, the pipeline row and the PR head all name the new attempt's ref.🤖 Generated with Claude Code