Console hand-off: usage floor, off-pass close
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.
Artifacts
Activity
- Created
- Run
- Runner started
- Runner ended (done)