- Walked: 2026-05-29 by Claude against commit
bf12b0f7d8; the current browser/BFF evidence was subsequently deepened through 2026-07-16. - Reconciled: 2026-07-18 against the current journey, fixture/live inbox union, shared incident lifecycle store, per-operator decision store, audit routes, and focused browser suites. This was a source reconciliation, not a fresh runtime walk.
- Verdict: partial — deep automation proves filtering, reactive selection, per-operator verdicts, audited shared acknowledge/assign/escalate/ snooze/resolve actions, public-report union, and failure guards. Incident ingestion, producer dedupe, realtime/on-call delivery, SLA automation, full deep-link routing, and list/count refresh from lifecycle state remain open.
- Primary specs:
incident-triage.spec.tsandoperator-inbox-decision-bff.spec.ts.
Result at a glance#
| Evidence lane | Current result | Authority limit |
|---|---|---|
| Browser inbox catalog | Six authored base rows plus live public-scene abuse reports; filters and selection are reactive | Base rows are fixtures; live reports are not lifecycle records |
| Per-operator verdict | Rationale-gated create/read/reopen, audit id, reload, auth/payload guards, and operator isolation | Separate review record; not shared incident state |
| Shared lifecycle | Acknowledge, assign, escalate, snooze, resolve, history, audit, and durable snapshot wiring | Seeded records; no production create/ingestion endpoint |
| Failure policy | Duplicate acknowledge, rationale floors, severity/snooze/resolution rules, scope, and network errors | Does not cover producer duplication or realtime loss |
| Queue synchronization | Selected action targets track the current browser row | Resolving does not remove the fixture row or update header count |
| Operations completion | Not closed | No paging, SLA clock, reconnect channel, or PIR obligation |
Evidence map#
Three related records participate in the current UI: the browser catalog, the per-operator decision, and the shared lifecycle state. Keeping them separate is the central correctness boundary.
flowchart LR
A[Six fixture inbox rows] --> C[Browser inbox union]
B[Live public-scene reports] --> C
C --> D[Filter and select]
D --> E[Per-operator review verdict]
E --> F[Decision receipt and audit id]
D --> G[Shared lifecycle actions]
G --> H[Incident state, history, and incident audit]
H -. no list refetch .-> C
B -. no lifecycle materialization .-> H
I[Production incident producer] -. absent .-> H
H -. no realtime or SLA adapter .-> J[On-call and downstream response]
Proven observations#
Catalog and selection#
/operator/adminrenders the six base Auto/Editorial/Tenant rows and unions available public-scene abuse reports. All/category filters use real category fields, and selecting a row updates detail, severity, evidence blocks, per-operator decision target, and shared lifecycle-action target./operator/incidentsexposes the current feed and exact open/recent lanes, ids, severity/mitigation cells, generated timestamp, and footer destinations.- Anonymous users are redirected before either operator surface renders.
Two durable write seams#
AdminInboxDecisionPanelrequires at least 20 trimmed characters, records a per-operator verdict, exposes a real audit id, supports GET readback/reopen, and isolates one operator's record from another's.- Shared incident actions use a different store. Acknowledge is single-writer; assign records the assignee; escalation is monotonic and rationale-gated; snooze follows severity/duration policy; resolve records a terminal class and rationale.
- Successful lifecycle verbs append ordered history and discrete
incident.*audit events. Durable snapshot hydrate/write-through is available when the admin database is configured.
Failure honesty#
- Duplicate acknowledge returns 409 with the original actor remaining canonical. Short escalation/resolution rationales fail both in the UI and at the BFF without state or audit mutation.
- Invalid resolution classes, non-monotonic escalation, S1/excessive snooze, missing scope, and network failures remain explicit. The browser does not paint an optimistic lifecycle state when the write fails.
- A public report can appear in the browser union without automatically gaining shared lifecycle state. The result preserves that limitation instead of implying every visible row supports the same verbs.
Boundaries and gaps#
- A fixture row is not incident ingestion. The shared lifecycle store starts from seeded incidents and exposes no production create route, producer contract, recurrence counter, or dedupe key.
- A per-operator verdict is not shared status. Its audit id and reopen operation serve reviewer accountability; acknowledge/assign/escalate/snooze/ resolve remain separate shared mutations.
- A live union row is not a lifecycle record. Public-scene reports can enter the browser catalog without materializing a matching shared incident.
- A successful mutation is not queue synchronization. The fixture-backed list and header counts do not refetch from lifecycle state, so resolve does not remove the row or decrement the count in the current view.
- Filtering is not durable operator context. Selected filter and row state are component-local rather than URL-addressable or shareable.
- Escalation state is not on-call delivery. No realtime subscription, missed-window reconciliation, paging adapter, acknowledgement SLA, breach event, or post-incident-review workflow is connected.
- Some evidence destinations remain partial. The current deep-link matrix is not complete or universally return-addressable.
- One browser is not concurrency coverage. Duplicate producers, two simultaneous resolvers, stale selected rows, and cross-tab updates need explicit policies beyond the existing acknowledge conflict.
Re-run evidence#
The current focused suite can be run serially with:
bash
PW_BROWSER_CHANNEL=chrome pnpm exec playwright test \
-c apps/oshun/web/playwright.config.ts \
apps/oshun/web/e2e/incident-triage.spec.ts \
apps/oshun/web/e2e/operator-inbox-decision-bff.spec.ts \
--workers=1
It requires the real-development-infrastructure web/BFF composition and the test reseed path for deterministic incident state. A green run proves the current queue/decision/lifecycle core; it must not be reported as live incident ingestion, paging, or SLA operations.
Source trail#
- Source-reconciled journey
- Incident-triage browser suite
- Per-operator decision suite
- Admin inbox console
- Inbox decision panel
- Shared lifecycle actions
- Incident lifecycle route
- Incident lifecycle store
Cross-references#
- Citation-drift result
- Public-scene abuse-report journey
- User flag-to-review journey
- Operator admin view
- Operator overview
- Journey coverage matrix
Open questions#
- What production ingestion contract, recurrence model, and idempotency key will create shared lifecycle incidents from every producer?
- How will public-report union rows materialize shared incident state before the UI exposes lifecycle controls for them?
- When will the inbox list/counts subscribe or refetch after mutations, and how will filters/selection survive URL sharing and reconnect?
- Which realtime snapshot, missed-window reconciliation, paging, SLA, breach, and post-incident-review contracts complete the operator loop?
- What deep-link/return envelope covers every incident category without losing selected incident, filter, tenant, or evidence context?