fix(tabs-sync): quality closes on continuity work + opencode terminal-signal research#521
Merged
Merged
Conversation
confirm_delivery matched `Ok(_)` on the timed-out oneshot receiver, so a dropped sender (`Ok(Err(RecvError))` -- the pending ack entry cancelled or purged before the client answered) read as a confirmed delivery. The pane was then marked restored instead of staying in-progress for a safe retry. Match only `Ok(Ok(_))` as confirmation; a dropped sender now takes the delivery-unconfirmed failure path. Regression test drives the restore endpoint with a client whose ack entry is purged instead of answered and asserts deliveryConfirmed=false, the failed reason, and the in-progress write-ahead marker. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…lient) The plan doc and the main.rs registry comment said snapshots keep the "last 5 generations per device"; the actual behavior (correct, tested) is MAX_SNAPSHOT_GENERATIONS = 5 per (device, client) with MAX_SNAPSHOT_FILES_PER_DEVICE = 40 across all clients of a device. Fix the wording where it lied; no behavior change. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
…ndings Research-only deliverable: what a plain opencode CLI in a terminal pane exposes for busy-vs-idle, turn boundaries, and queued prompts. Ran the real opencode 1.18.3 CLI in a throwaway HOME/project (run + TUI under script), inspected its SQLite schema/rows/sockets/locks, sampled the real DB read-only with bounded queries, and compared against the freshopencode serve-SSE status source. Recommendation: full truly-idle support via bounded opencode.db polling keyed off the existing OpencodeLocator binding (time.completed edge, positive-completion only); status-inert for unbound panes; no grace-window heuristics. Queued-prompt detection deferred (session_input semantics unverified without an authed long turn). 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
danshapiro
pushed a commit
that referenced
this pull request
Jul 24, 2026
Conflict resolutions (both sides' behavior preserved everywhere): - crates/freshell-ws/src/lib.rs, terminal.rs, opencode_association.rs + 12 tests/*.rs WsState constructors: kept BOTH this branch's `activity: None` field and #523's new `session_existence` probe field (trivial adjacent-field conflicts). #523's brand-new tests/pane_reconcile.rs gained `activity: None` too. - crates/freshell-terminal/src/registry.rs: kept BOTH the TERM-15/16 activity tap (ActivityEvent/ActivityObserver, tap field + init, the Created-tap fire in create()) and #523's reconciliation additions (respawn liveness/cap consts + fields, keyed_create_inflight, the §5.4 duplicate-live-PTY backstop — ordered before the Created tap). create() gained #523's create_request_id param; this branch's two activity-observer tests updated to pass None for it. - crates/freshell-server/src/main.rs: kept #523's session_index block first (ws_state.session_existence references it), then this branch's activity-hub construction + registry observer install. - docs checklist + playwright.config.ts auto-merged (both sides' notes and MATRIX/rust-only spec entries retained). Cross-track integration (#524 truly-idle client): the Rust terminal.idle emission matches shared/ws-protocol.ts's new TerminalIdleSchema byte-for-byte ({type, terminalId, at, reason: 'grace'|'queue-empty'}), so the rust leg of test/e2e-browser/specs/truly-idle-alerting.spec.ts is now ENABLED (test.fixme removed) — the full production pipeline (PTY submit -> busy blue -> BEL -> idle + turn.complete -> 2s grace -> terminal.idle -> one alert edge + tab shade) passes against the real Rust server. Verification: cargo test --workspace 1656 passed / 0 failed; clippy clean on touched files; rust-chromium PW (3 activity + truly-idle rust leg) green 2x (4 passed 1.1m, 4 passed 42.5s); coordinated npm test full-suite success exit=0 (3982 + 4547 + 350 passed; two earlier runs each hit one unrelated pre-existing flake — DOM-identity, sidebar-filter, EADDRINUSE:40301 — each passes in isolation). 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Track 5 of the post-continuity quality wave: the missing independent review of e7a4add, the two known minors from that review loop, and the opencode terminal-signal research deliverable.
Task A — Independent review of e7a4add (verdict: clean beyond the known minors)
Adversarial review of
e7a4addb("fix(tabs-sync): custom CLI modes, cross-client ordering, and bounded restore marker"), the final fix round that never got re-reviewed. Reviewed as a senior engineer against the three risk areas named in the task:Cross-client capturedAt ordering — no findings.
cross_client_capture_orderis a total order over queue heads (capturedAt → revision → clientInstanceId → path); paths are unique, somax_by/min_byselection is fully deterministic despite HashMap queue collection order (tabs_persist.rs:152-175).order_generations_newest_first) compares only per-client queue HEADS, preserving within-client revision monotonicity under clock rollback — the non-transitivity trap of mixing both comparison rules in one sort is correctly avoided, and the doc comment says exactly why.enforce_device_file_cap) mirrors the merge with oldest-first per-client queues;file_countbookkeeping guaranteesmin_byalways has a nonempty head; a client's higher-revision-but-older-clock file is correctly protected behind its queue head.union_of_newest_per_clientlabel tie-break is deterministic (clientInstanceId is unique per candidate by construction).Restore-marker caps — no findings.
> MAXrejects); boundary tests cover at/over for bytes, pane count, and all three identifiers.read_marker_docTOCTOU betweenmetadata()andread_to_stringis re-checked post-read.validate_restore_projectionpreflight runs before the pane loop, andrestore_rejects_over_limit_marker_plan_before_side_effectsproves no marker file and no pane on rejection.persist_markerstill precedes the create/deliver (tabs_snapshots.rs:799), andwrite_ahead_marker_is_durable_before_tab_create_is_sentfences it.Any-nonempty-mode acceptance — no regression.
mode_is_known(terminal_tabs.rs:588, 400 for unregistered modes) andcli_spec_known(terminal.rs:762).pane_to_create_bodypasses mode through with no seven-mode enum assumption; restore of an unregistered mode fails loudly as afailedentry, never a silent shell fallback.Non-blocking notes (recorded, deliberately not restyled):
MarkerSizeWriter's over-cap message reads "serialized byte limit is X (more than X)" — repeats the cap instead of the actual size. Cosmetic; the fail-loud path still identifies the file and cause.validate_restore_projectionsizes projected terminal ids with a 36-byte UUID placeholder; a hypothetical future id format >36 bytes would pass preflight and fail loudly post-side-effect instead. Exact today, safe-by-fail-loud tomorrow.confirm_delivery— fixed here as Task B1.Task B — Known minors
confirm_deliverydropped-sender bug (fixed, TDD): the ack wait matchedOk(_)on the timed-out oneshot receiver, soOk(Err(RecvError))— a dropped sender, e.g. the pending entry cancelled/purged before the client answered — read as delivery confirmation and marked the panerestored. Now onlyOk(Ok(_))confirms. Regression test (red first: it reproduceddeliveryConfirmed:true+restored) drives the restore endpoint with a client whose ack entry is purged instead of answered and asserts thedelivery-unconfirmedfailure path plus the retainedin-progresswrite-ahead marker.main.rscomment claimed "last 5 generations per device"; actual (correct, tested) behavior isMAX_SNAPSHOT_GENERATIONS = 5per (device, client),MAX_SNAPSHOT_FILES_PER_DEVICE = 40per device. Wording fixed in both places (and the doc's embedded copy of the comment).Task C — OpenCode terminal-signal research
docs/plans/2026-07-23-opencode-terminal-signals.md— evidence-backed findings from running the real opencode 1.18.3 CLI in a throwaway HOME (run + TUI underscript), schema/row inspection, socket/lock inspection, and bounded read-only sampling of the real 4.4 GB DB. Headlines: the standalone TUI has no socket, no lock/heartbeat, and emits zero bare BELs (the claude/codex turn-complete pipeline cannot be extended to it); the durable signal is the SQLitemessage.data.time.completednull→set edge (witherrorabsent for positive completion); subagent activity is separable viasession.parent_id;session_inputis structurally a prompt queue but its on-disk visibility while queued is honestly UNVERIFIED. Recommendation: full truly-idle support via boundedopencode.dbpolling keyed off the existingOpencodeLocatorbinding; unbound panes stay status-inert; no grace-window heuristics; effort 2-4 days.Verification
cargo fmt --check: only the pre-existingdirectory_index.rsdrift (outside this diff, already noted as pre-existing in e7a4add's own message)cargo clippy --workspace --all-targets: zero warnings in files touched by this PR (background warnings pre-existing)cargo test --workspace: 1524 passed, 0 failedFRESHELL_TEST_SUMMARY="track5 quality closes pre-PR" npm test: full-suite success at 51f5719 (coordinator-recorded)🤖 Generated with Amplifier