docs: settle teardown design (review before implementation) - #1067
Conversation
Deliverable for the settle teardown cut from #1059, for review before any reimplementation. Contains the full inventory of all seven paths that write or clear settled_at with file:line and callers (four of the seven clearers are implicit, and one runs per terminal output chunk), a six-case race matrix, and a proposed design: a single settle-writer chokepoint owning a monotonic persisted lifecycle revision, an explicit exclusive 'settling' state, and the rule that an accepted user turn aborts the settle rather than the reverse. Every one of the 16 P1 findings from the six review rounds is mapped to the design constraint it implies and the mechanism that neutralises it, so the review capital is not lost. Three findings are load-bearing: enumerate the writers first, verify the detector actually changes on the event it guards, and put the guarantee in the writer rather than each caller. #1059 did none of the three. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (1)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Five amendments from design review of #1067. 1. C4 during settling — the sharpest hole. Teardown itself produces output, so if C4 bumped the guard revision or tripped abort, every real teardown would self-abort and a settle could never land. Added a per-clearer behavior table for the settling window: C3/C6/C7 (turn start, turn failed, attention request) abort because each represents a human decision that outranks settled; C4/C5 (output preview, activity touch) are SWALLOWED — no clear, no revision bump, no abort. Before settling starts all five behave as today. 2. Multi-device authority — VERIFIED BYPASSABLE, now a hard precondition. terminal_sessions is a CRR table and iOS writes settled_at into its own replica optimistically (Database.swift:2128, from SyncService.swift:9286) before sending the remote command. Intent routes through the host chokepoint correctly, but the replica write carries no revision, so a host guard that REJECTS a settle can still be overridden by the phone's row merging upstream. Step 0 of the sequencing is now: make settled_at host-authoritative and replace the optimistic write with local pending UI. 3. Revision column — local-only. C4 writes terminal_sessions per output chunk and cr-sqlite clocks are per column, so a revision column on that table would add a clock entry to the highest-frequency write in the product for a value no other device can use. It goes in a local-only table in LOCAL_ONLY_CRR_EXCLUDED_TABLES, keyed by session id, with an in-memory fallback that degrades identically to the settling state on restart. 4. 3d signed off with both additions: the residue must stay discoverable (diagnostics surface + orphan-reaper eligibility, not just a label, with detached nohup/setsid work reported separately since it is genuinely unreachable), and an analytics event per docs/logging.md — coarse reason and bucketed count, deduplicated per session so a failing fleet is not a burst. 5. Abort result decided: typed settle_aborted_by_activity, never silent success, with the contract documented for all five entry points. PR-merge auto-settle additionally must not mark a PR handled for an aborted session. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Design deliverable for the settle teardown cut from #1059. Doc only — no code. Requested for review before any reimplementation is scheduled.
docs/features/terminals-and-sessions/settle-teardown-design.mdsettled_at, with file:line and callers. Four of the seven clearers are implicit (never named "unsettle"), and one (setLastOutputPreview) runs per terminal output chunk. This inventory is the thing Background-work liveness in canonical phase + archive port-lease ordering #1059 didn't do first.lastActivityAtis not that detector — it's backed bylast_output_at, which turn-start never writes.settlingstate, and the rule that an accepted user turn aborts the settle, never the reverse. Plus the open decision on unconfirmed teardown (§3d) — the one place the honest answer and the quiet answer differ, flagged for sign-off.🤖 Generated with Claude Code
Greptile Summary
This documentation-only PR specifies the proposed architecture and rollout sequence for race-safe session settlement and teardown.
Confidence Score: 4/5
The PR should not merge as the approved implementation design until the outstanding mutation inventory is made internally consistent.
The design requires every settlement mutation to pass through one chokepoint, but its inventory still gives conflicting counts and classifications, so implementers cannot reliably determine the complete scope of that invariant.
Files Needing Attention: docs/features/terminals-and-sessions/settle-teardown-design.md
Important Files Changed
Sequence Diagram
sequenceDiagram participant Caller participant SessionService participant Teardown participant Activity Caller->>SessionService: Request settle SessionService->>SessionService: Enter settling and capture revision SessionService->>Teardown: Stop runtime work alt Accepted user activity arrives Activity->>SessionService: Clear lifecycle marker SessionService->>Teardown: Abort remaining stops SessionService-->>Caller: settle_aborted_by_activity else Revision remains unchanged Teardown-->>SessionService: Stop results SessionService->>SessionService: Conditionally persist settled_at SessionService-->>Caller: Typed settle outcome endReviews (2): Last reviewed commit: "docs(sessions): amend settle-teardown de..." | Re-trigger Greptile
Context used: