## Summary
Stage-28 closes the Stage-27 specification gaps for fixed roots and spec digests, a dormant coordinator-free control route, source-only export, exact evidence readers, promotion identity, state-specific preflight, and reproducible verification. It still cannot meet its claimed removal-wins/provider-zero boundary: its route-map lock does not serialize detachment with an already-dispatched handler's final reservation/provider admission. Define a shared detaching/session-generation fence before implementation.

## Claims
- The immutable RALPLAN index records `stage-28-revision.md` at revision stage 28 with the assigned SHA-256 `f489a4b446e9e661e8e97c9af7e7d77d1512e06c8dd88fd02aa77099e93f12ed` (`index.jsonl:38`).
- Stage 28 concretely closes the Stage-27 ambiguity areas: fixed policy-root/spec validation (`stage-28-revision.md:270-275`), a coordinator-free dormant `DiagnosticControlService` and exact callbacks (`:277-289`), the adapter-owned route map (`:291-299`), source-only export (`:301-311`), bounded readers (`:313-326`), promotion markers (`:328-330`), commands/report schema (`:332-350`), state receipts (`:352-362`), and compile/manual boundary (`:364-368`).
- The existing gateway has separate callback/routing branches after adaptive-review handling (`/home/cube/projects/richard/hermes-agent/gateway/platforms/telegram.py:4975-5085,6540-6680`), so the plan's all-ingress first-match ordering is necessary and appropriately explicit.
- Current `profile_authority_lock` creates/chmods its lock state (`/home/cube/.hermes/profiles/physique-coach/workspace/checkin_cli/checkin_cli/customer_admin.py:127-158`); the plan's separately read-only fenced reader is therefore an actual required boundary rather than redundant scope.

## Analysis
### Stage-27 closure
The final addendum supplies the key missing implementation choices instead of leaving them to executors. It pins the diagnostic process to one configured isolated root under a compiled policy, prevents an enabled-registry/coordinator prerequisite from defeating dormant control, distinguishes the source export path from isolated replay, and turns evidence/promotion/verification requirements into named interfaces, roots, files, and commands. Its source export write protocol is also appropriately fail-closed: consume capability, create a no-follow exclusive temporary file, validate in memory, fsync, rename, and fsync the directory.

### Remaining architecture defect
The asserted route-race property is not implied by the specified operations. A role handler can snapshot a route under `_diagnostic_route_lock`, release it, successfully revalidate an active session, and advance toward its final pre-provider check. Concurrent `diagnostic_close`, expiry, or `stop()` can then clear the map before its asynchronous cleanup disables/terminalizes the registry/session. In that window the handler still observes an active session and can reserve or invoke the provider. A later revalidation is insufficient unless it is serialized with a state/generation transition that has already made detachment visible. The existing promise to check immediately before reservation/call (`:197`) and to remove routes before disable/terminal append (`:206`) creates precisely this interleaving.

The strongest antithesis is to accept already-dispatched work as naturally in-flight. That is unsafe here because the plan calls route removal “removal wins fail closed,” requires expiry/stop/close to detach before production work, and otherwise gives no linearization point or declared exception. A test named dispatch-vs-close without its expected no-reservation/provider outcome cannot close the gap.

## Root Cause
Route ownership is synchronized independently from lifecycle/provider admission. Clearing a route map is not an authority revocation until the active session state or an equivalent generation fence is atomically changed and observed by the final reservation/provider admission path.

## Findings
1. **HIGH — `stage-28-revision.md:286-299` (reported P1).** `diagnostic_close` removes role routes before cleanup, while lookup releases the same lock before its revalidation. A handler can cross that gap and use an active session during teardown. Impact: a close/expiry/stop can permit a new diagnostic reservation/provider call after detachment has begun. Fix: introduce a shared detaching/session-generation fence that is set before route removal and atomically tested with the final reservation admission; either drain/serialize admitted sends through the close linearization point or explicitly retain and test a pre-detach reservation rule. Assert dispatch-vs-close/expiry/stop has no post-fence reservation or provider call.

## Recommendations
1. Block implementation until the P1 detachment/admission linearization contract and exact race assertions are added.
2. Keep the Stage-28 closed-root, dormant-control, source-only export, evidence, promotion, and verification contracts unchanged; they resolve the cited Stage-27 findings.
3. Make the race test schedule the critical interleaving: snapshot route -> dispatch revalidation -> removal -> final reservation/provider boundary, then assert the defined fence outcome and row/provider deltas.

## Architectural Status
BLOCK

## Code Review Recommendation
REQUEST CHANGES

## Tradeoffs
- **Shared detaching generation plus final admission fence (recommended):** gives close/expiry/stop a clear authority-revocation linearization point; requires a small cross-layer API and deterministic race hooks.
- **Drain a session read lease across an admitted send:** gives simpler linearizability but may delay close completion; safe when close waits for the lease.
- **Map lock/revalidation only (current):** lower implementation cost, but cannot establish removal-wins once dispatch has released the map lock; reject.
