Console hand-off: usage floor, off-pass close

Task 7462 · Done · Coder · created · updated

Follow-ups from task 7370 (console chat ↔ terminal hand-off, PR #6020), found by its review lanes: 1. Usage on a hand-off terminal front: the resumed vendor transcript (Codex rollout / Gemini chat file) also holds the chat front's turns, already counted from ACP events. The legacy fold may count them twice. Fold a hand-off TUI row only from its resume point, using a per-line time floor at `launched_at`. 2. The node's hand-off close wait (`reconcile._close_for_handoff`, up to 45 s) runs inside the reconcile pass and stalls the pass's publish. Move it off the pass, or have the CP pre-close. 3. The close wait polls `fresh_window_id_for(slot.path)`, which also matches an operator's own pane in the worktree. Wait on the old host's own window or process instead. 4. Re-check the leased account's eligibility (disabled, revoked, at its limit) before `POST /runtime/handoff` re-issues the lease. 5. `runtime.events_append` should refuse a session the launcher did not create as ACP. Today an agent can flip a legacy row to `runtime=acp` and write `native_session_ref` (the hand-off now also checks it is a UUID). Out of scope: the hand-off flow itself; adding Claude, DeepSeek or Antigravity TUI resume. Done means: - A test proves that after chat → terminal → chat, a task's metrics count each turn once. - A node test shows other intents enacted while a hand-off close is pending. - An operator pane in the slot neither delays nor is killed by a hand-off. - A hand-off on a disabled account answers 409. - A non-ACP session's `runtime.events_append` is refused.

Outcome

Hand-off follow-ups merged in PR #6047 (c5e3bbb26): per-row usage window, close wait off the reconcile pass and tied to the old front's process, 409 on an ineligible account, ACP-only event verbs. Quick gate and changed-area tests green. Its deploy was superseded by a newer one. Hardening deferred to draft #7500.

Pull request

Artifacts

Activity

  • Created
  • Run
  • Runner started
  • Runner ended (done)