Files
orca/docs
420447e063 fix(agent-status): retire a removed worktree's hook-status rows (#23881)
* fix(agent-status): retire a removed worktree's hook-status rows

Rows whose terminal was never reattached had no teardown path, so they
outlived the worktree in last-status.json for up to 7 days.

Fixes #23068

* fix(agent-status): skip panes another owner has since reclaimed

* fix(agent-status): clear only the removed owner's claims on a shared pane

* fix(agent-status): retire hook-status rows a host scan proved removed

`worktrees:forgetRemovedForExecutionHost` is the only path that ever retires an
off-host WorktreeMeta row: gcStaleWorktreeMeta skips any row whose repo or
hostId is not local. It already prunes the cleanup and space-analysis snapshots
for a worktree a remote scan proved gone, but left that worktree's hook-status
rows behind in `last-status.json` — the same stranding this branch fixes for the
in-Orca delete, reached through the other trigger.

A scan the host answered is positive evidence of removal rather than loss of
contact, so it is the host evidence `ssh-execution-boundary.md` requires, and it
publishes no verdict. The drop is scoped to the scanned host's id, so a same-id
worktree on another connection keeps its rows, and a runtime host falls through
the method's own early return because a paired server owns its own store.

Also names the shared-pane condition in `dropStatusEntriesForRemovedWorktree`,
which was the one place the two-owner logic was hard to read.

* fix(agent-status): stop a removed worktree's row returning on a shared pane

The mixed-owner branch deleted the removed worktree's row but left the pane
unfenced, so the stale row came straight back. `getAgentStatusDisposition`
returns `accept` for an unfenced pane, and the removed worktree's agent can
still post a late turn on a pane it shares with another owner — I reproduced the
`working` row being rewritten to memory and to `last-status.json`, which is the
symptom #23068 is about.

A launch-token fence cannot close this: `ingestTerminalStatus` calls the
disposition gate with no event, so the token check never runs and an OSC report
carries no token to check. The pane fence the sole-owner path already uses does
suppress it, and it lifts on PTY reattach or a new agent's turn.

Fencing the pane would otherwise discard the surviving owner's claims, which is
what the branch existed to protect, so both of its records are captured first
and restored after: its persisted authority commitment (its resume identity) and
its current authority observation. The observation also fixes a second defect on
this path — `deleteStatusEntry` drops it whatever `preserveAuthority` says, so
the surviving owner silently lost `current_runtime` attestation until its next
hook event.

Both are covered by tests that fail against the previous commit.

* fix(agent-status): decide a reused pane by its occupant, and retire rows for local scan-proved removals

A pane has one terminal, so its newest row names who occupies it. A saved
commitment naming a different owner is what an earlier occupant left behind,
and serialization already drops it while the row disagrees. Removal now retires
a pane the removed worktree occupies, and on a pane another owner occupies it
clears only the removed worktree's outlived commitment. This replaces the
capture-and-restore handling of two-owner panes.

The local authoritative-scan prune is the local twin of the SSH scan forget: it
drops a worktree's metadata once the scan proves it gone, and now retires its
status rows too.

* fix(agent-status): preserve foreign authority during worktree removal

* fix(agent-status): preserve terminal connection validation

* fix(agent-status): keep ordinary OSC admission unchanged

* refactor(agent-status): colocate the remote envelope type

* fix(agent-status): revoke removed startup authority evidence

* fix(agent-status): retain foreign startup claims during removal

---------

Co-authored-by: Neil <neil@stably.ai>
Co-authored-by: Neil <4138956+nwparker@users.noreply.github.com>
2026-10-05 20:12:38 -07:00
..
2026-10-05 12:43:43 +00:00
2026-08-28 00:59:21 -07:00