# Proof audit pass 1 — issue 15135

Scope: read-only audit of defb7e6e6b..491622c835 in the issue-15135 worktree. No browser/server started, no repository edits, commits, or forge operations. Test execution results below are supplied by the lead, not independently rerun.

## Exception decision

**Server-only exception applies. Visual fixture matrix: EMPTY (0 rows). Behavioral matrix: NONEMPTY.** The complete diff changes only Orchestrator.ts archive command validation and runtimeLayer.test.ts. No frontend, contract, transport, provider adapter, or visible render surface is edited. The new error is surfaced through existing error handling; it does not introduce a render surface. Under the user's explicit exception, red regression tests plus a real-app runtime transcript are the appropriate proof; screenshots are not required.

The guard reads all projected runs and rejects thread.archive if ANY run is starting, running, or waiting, before archive events and detach/cleanup effects are constructed. It is provider- and caller-independent at the shared command boundary. Existing preparing/queued cancellation and idle-session detach remain downstream.

## Minimum behavioral proof matrix

| State at archive | Required outcome | Inspected test coverage / evidence |
| --- | --- | --- |
| starting | Reject with actionable stop-before-archive error; archivedAt stays null; run remains starting | New parameterized runtimeLayer case explicitly asserts error type, /still running/, status unchanged, archivedAt null. Lead reports red on base, green on fixed revision. |
| running | Same rejection; live provider turn continues | New parameterized case covers rejection and unchanged projection; real-app after transcript must establish continuation. Lead reports red on base, green on fixed revision. |
| waiting | Same rejection; waiting run remains waiting | New parameterized case covers rejection and unchanged projection. Lead reports red on base, green on fixed revision. |
| preparing only | Archive succeeds; preparation/run/attempt/node cancel and cannot resume after replay or late callbacks | Existing “cancels preparing work on archive and keeps it cancelled through replay” checks cancellation, archive, idempotent receipt, replay, unarchive, and late callback rejection. |
| queued only (no starting/running/waiting run) | Archive succeeds; queued run cancels, queue position clears; archived work cannot start later | Existing implementation explicitly selects queued and preparing runs for cancellation. No direct queued-only archive assertion located in runtimeLayer tests inspected. A settle queue test is not archive proof. Coverage gap: add/identify one focused queued-only archive control if claiming complete matrix coverage. |
| idle / no live run | Archive still succeeds, appears in archive; unarchive still works; existing idle-session cleanup remains reachable | Existing lifecycle test asserts archive shell behavior; watch archive/unarchive test covers reverse action. No new idle-session detach assertion in this diff. |
| active plus queued/preparing work | Reject entire archive, leaving both active and pending work intact | Guard uses runs.some across all runs before mutation. Code supports this; new cases contain a single run and do not directly assert mixed-run atomicity. Useful strengthening, not a separate active-state regression. |

Supplied run summary: all three new active-state cases failed on main; runtimeLayer 86 and control-read/MCP 234 passed on the fix. This audit inspected test source, not raw test logs, so exact execution provenance/counts remain lead-attested.

## Real-app transcript checks

Inspected before-runtime.json: revision defb7e6e6b; real web client and Claude; current-thread t3_thread_organize input {"action":"archive"} with no threadId. archivedAt becomes non-null; run fails with “provider event stream closed unexpectedly”; dynamic tool remains running with completedAt null. No final assistant reply is recorded. This is concrete reproduction of self-archive killing its own tool call.

The after transcript must record:

1. Fixed revision (491622c835 or a documented descendant containing the guard), disposable isolated development environment, real client/provider identity, and the equivalent self-archive prompt.
2. Actual t3_thread_organize invocation with action archive and no threadId, establishing the current-thread MCP path rather than an idle target or manually dispatched command.
3. Settled tool result carrying the archive rejection and actionable stop-before-archive message. A generic tool transport failure or a still-running tool item is insufficient.
4. archivedAt remains null after the rejected tool call; no archive-induced detach or credential revocation. Direct event/effect evidence is useful if available; successful continued provider output supplies observable continuation proof.
5. Claude continues after the rejection, produces a final reply (ideally the requested “done”), and the run reaches completed with completedAt set. No unexpected stream-closed failure or stranded dynamic tool item remains.
6. Correlated thread/run identity and timestamps/order connecting the tool attempt, rejection, final reply, and final persisted state. Redact tokens, pairing URLs, credentials, and unrelated conversation data before any public upload.

The real-app transcript need only exercise the running self-archive failure; deterministic regression tests supply starting/waiting coverage. Separate real-provider runs for every provider or client are not required for this shared server guard.

## Gaps and friction

- After transcript is owned by the lead and was not present during this pass; runtime completion proof remains pending.
- Direct queued-only archive coverage is not established. Existing preparing and idle controls do cover their intended branches.
- New rejection tests do not explicitly inspect absent detach/terminal cleanup effects, exact full actionable error text, or mixed-run preservation. Early guard placement supports these invariants; the after transcript should demonstrate the critical no-detach consequence.
- No code defect identified in this bounded proof audit. No browser/server contention introduced. No extra visual work required under the authorized exception.
- This matrix contains code/test observations and sanitized reproduction facts only; no credentials, pairing links, customer data, or raw runtime transcript are included. Safe for the requested public ghdrop upload.
