Repository navigation
S2: the question inbox — every pending question, answerable without opening the session #1786
Description
Important
Problem — A question asked by a session the user isn't currently viewing goes unnoticed: the question dock only surfaces inside an open session view. Sessions have hung for hours this week on answerable questions for exactly this reason. The shared question rows already exist fleet-wide (P2) — the data has nowhere to be received.
Approach — One inbox surface in the panel: a badge plus a side panel listing every pending question with its session, riding P2's shared pending rows and the reply path that works end-to-end (probe-verified). Questions are answerable directly from the inbox — no session view required. The inbox makes "no session can silently wait on a human" a UI invariant, not a monitoring discipline.
Scope — in: the inbox surface (badge + side panel + reply action), fleet-wide pending-question reads, settling on any answer, absorption of the diagnostic reply telemetry. · out: the in-session dock (unchanged), any engine or shared-store change (if a state gap is discovered, stop and name it — the parent issue says so).
Acceptance Criteria
- A question asked by a session the client has NOT opened appears in the inbox (badge count + list entry) without opening that session.
- The inbox lists every pending question with its session identity and a staleness read; answering from the inbox completes the reply end-to-end — the reply request returns success and the session's turn resumes (headless-probe verified).
- A question answered anywhere — this panel, another panel, or the owning session view — settles the inbox entry everywhere (the shared settle is idempotent; duplicate/replayed answers are safe no-ops).
- A stale row (owner gone, heartbeat expired) reads honestly as stale, never blocks the rest of the inbox, and clears by TTL — an unreachable owner never wedges the inbox.
- The diagnostic reply captures currently baked into the live dist (question-reply-attempt / ok / failed, an unbranched local build) are either absorbed as the inbox's own telemetry floor or reverted by the slice — never left orphaned.
- End-to-end headless probe: a fresh client boots, a question from an unopened session surfaces in the inbox, is answered from the inbox, and the turn resumes.
Testing Decisions
Extend the existing app context suites (the ServerSession store tests and the live dispatch seam pins) for the inbox's store/reducer behavior; the existing headless probe suite for the end-to-end path. No new suites for surfaces that already have suites.
Key Decisions
- The inbox is a client-side consumer of existing shared rows — no engine change, no new state ownership.
- Inbox freshness rides the existing event flow plus row TTLs; the fix(fleet): remote session keeps its working rail + tab state after reopen (fleet-aware status re-seed) (#1766) #1768 reconcile semantics (recency-guarded, honest absence keeps current value) apply to inbox reads.
Constraints & Invariants
- No session can silently wait on a human: any pending question reachable from this client's store must be visible in the inbox within one event cycle.
- No engine deploys in this slice.
- The reply path's idempotency (idempotent settle) is load-bearing — never answer twice by accident and never wedge on a double-answer.
Prior Art
- P2's shared pending rows (record/heartbeat/settle + TTLs) — the data layer, already live.
- The question card dispatch seam pins (fix(app): live question/permission cards — session-content dispatch drops the events that render them #1753 lineage) — the render path a live question already takes.
- The reply-path probes and the diagnostic telemetry markers in the live dist (identifiable by their capture names in the built bundle).
- Remote session loses its working rail + tab active state after reopen (fleet-aware status re-seed) #1766/fix(fleet): remote session keeps its working rail + tab state after reopen (fleet-aware status re-seed) (#1766) #1768's reconcileStatuses semantics — the staleness/recency rhyme.
Source
Part of #1785. Build order: this slice first (highest value; exercises the reply path end-to-end).
Notes
The reply instrumentation source was never branched — the markers in the built bundle identify the call-sites; reproduce the diagnostic, then fold it in or remove it.
Activity
aarontrowbridge commentedon Oct 13, 2026
Merged into the integration branch amico/issue-1785-seamless-attach (ff to 92618c0). Director-verified: scoped 70/0, full-suite 1664 pass / 24 fail with the failure set byte-identical to the known lane baseline (the server-sdk.test.ts splice repair removed 2 load errors), drift gate PASS (965 files). The end-to-end headless-probe gate (fresh client → question from an unopened session → answered from the inbox → turn resumes) remains pending the deploy decision — tracked on the parent.