# Owner-Isolated Diagnostic Mode — Stage 25 Critic Review

Reviewed immutable revision `/home/cube/projects/richard/traning coach/.gjc/_session-019f8455-334a-7000-99ca-318dfd0e06b1/plans/ralplan/019f8455-334a-7000-99ca-318dfd0e06b1/stage-25-revision.md`. The RALPLAN index records that exact revision at SHA-256 `61dedc2e522ce2c28807918299b9faa53ac5479c647b964f2f0354b79e9e2b20`, matching the assignment. Product files were inspected read-only; no tests were run.

## Verdict
**REJECT**

## Claim Checks

Revision 25 closes several Stage-24 findings. It corrects ordinary identity semantics to distinct full triples/destination pairs rather than distinct user IDs; names a diagnostic state module, session APIs, a 60-minute exclusive TTL and restart-unvalidated state; selects a session-scoped diagnostic registry loader without relaxing `CustomerSpec`/`RegistryDocument`; binds or disables the trainer private-DM bridge; preserves the ordinary `GateDPreflightReceipt` v1 contract; authenticates snapshot export with a current-boot capability; enumerates incident classes; names synthetic provenance and promotion trust roots; and explicitly limits reporting to typed/local surfaces.

The corresponding current boundaries were verified. `customer_coaching.py:264-359` permits a shared `user_id` when full triples and chat/topic spaces differ. `customer_admin.py:1500-1512` exposes only the ordinary committed-activation runtime loader. `telegram.py:4230-4315` unconditionally obtains that ordinary loader during coordinator construction. `nutrition_coaching.py:350-499` builds enabled routes and reloads through the ordinary loader, while `:863-1010` and `telegram.py:4565-4678,8739-8773` implement the user-ID/private-DM bridge. `GateDPreflightReceipt` remains a closed v1 mapping in `customer_admin.py:4318-4410`.

The revised plan is still not executable without security-critical design choices:

1. **Diagnostic bootstrap remains undefined and circular.** `load_diagnostic_runtime_customer_registry(profile_root, session_capability)` requires a capability before gateway construction, but the plan does not define which prepare/activate API returns that capability, how it is owner-authenticated, how the gateway receives it, or what explicit non-config bootstrap selects the diagnostic branch. The current gateway always calls `load_committed_customer_registry`; an executor must invent the branch and its trust boundary. A config flag alone is prohibited, while automatic discovery would violate the rule that ordinary startup never infers diagnostics.
2. **The isolated enabled registry is not protected from the ordinary loader.** The plan keeps `RegistryDocument` and `load_runtime_customer_registry` unchanged and says same-user/distinct-triple records remain ordinarily valid. During activation it enables the disposable customer in an isolated registry, but supplies no diagnostic schema marker that the ordinary loader rejects. An ordinary gateway pointed at that profile can therefore construct the same enabled routes without session revalidation. Expiry is evaluated on calls, yet no expiry worker or crash-recovery transaction is defined to force the registry disabled immediately. This defeats the claimed sole diagnostic admission path.
3. **Activation/cleanup is not transactionally specified.** Session append, registry enablement, activation receipt changes and terminal disablement span multiple durable objects. `profile_authority_lock` serializes but does not make those writes atomic. The plan gives no prepared/committing/recovery state, write order, recovery journal, or behavior for a crash between active-session append and registry enable/disable. “Enabled transactionally” and “forcibly reversed” are outcomes, not an implementable recovery protocol.
4. **Snapshot synchronization is insufficient for the promised coherent replay.** The proposed shared read lock coordinates only with writers using `.adaptive-authority.lock`. Canonical wizard events, adaptive delivery journals and schedule reservations use separate locks in `store.py`, `adaptive_nutrition.py`, `customer_schedule.py` and gateway code. A snapshot may combine revisions from different moments or observe an in-flight reservation. No per-incident source-ledger map, multi-ledger revision fence, retry-on-change algorithm, or explicit acceptance of a point-in-time inconsistency is defined. The stronger assertion that the full tree's bytes and metadata remain unchanged also needs an exact metadata definition/read strategy because ordinary reads can change atime.
5. **Synthetic replay integration points are missing.** The plan says production loaders reject `provenance=diagnostic_synthetic` and only the diagnostic runtime accepts it, but the file sequence omits the actual event/projection loaders (`models.py`, `store.py`, `wizard.py`, `adaptive_nutrition.py`, and `customer_schedule.py` as applicable). Current `Provenance.source_type` is an unrestricted string and current ordinary loaders have no diagnostic-provenance rejection. The executor would have to decide which ledgers are materialized and which loaders enforce the boundary.
6. **The exact contracts requested at Stage 24 remain absent.** `DiagnosticPreflightReceipt` has no enumerated check/count/digest keys or reason-code allowlist; no state-by-state table gives receipt result, route result, row delta and provider count; supported incidents are listed but their exact source ledgers and minimal inputs are not mapped per class; and the “closed list” of promotable config schema keys is not actually enumerated. These are compatibility and security contracts, not harmless implementation details.
7. **One referenced test path is not present.** The profile has `tests/test_customer_coaching_domain.py`, not the listed `tests/test_customer_coaching.py`. A new test file is allowed only conditionally elsewhere in the plan, so the intended existing test target is ambiguous.
8. **Acceptance criterion 2 conflicts with compatibility.** It says solo-owner role sharing works only through an active diagnostic session, while the goal, migration section and current validator all preserve ordinary same-user/distinct-destination records. The criterion must say diagnostic authority/workflows—not identity sharing itself—require the active session.

### Representative implementation simulation

- **Boot a diagnostic gateway:** current `TelegramAdapter` reaches the ordinary loader before coordinator/operator capability construction. The plan provides neither a pre-construction owner capability nor a selected constructor/CLI injection point, so there is no implementable way to choose the diagnostic loader without inventing ambient/config authority.
- **Activate and expire a session:** appending `active` and enabling the isolated registry cannot be atomic across the ledger and registry. A crash can leave an active-disabled or terminal/expired-enabled profile; the plan gives no recovery state. Because the ordinary loader does not reject that registry, the enabled failure state is routable outside the diagnostic gate.
- **Export and replay `reservation_race`:** the authority shared lock does not fence the adaptive/schedule reservation writers. The exporter can observe different ledger revisions, and the plan does not say which rows/concurrency markers form the source fingerprint. Materialization then lacks named production-loader changes to reject its synthetic provenance.

## Missing Evidence

Definitely missing:

1. A non-ambient diagnostic bootstrap contract: authenticated capability issuer, capability handoff, gateway constructor/config boundary and exact loader-selection callsite.
2. A diagnostic registry/document marker or equivalent ordinary-loader rejection that prevents enabled isolated state from being consumed through the production path.
3. A crash-recoverable multi-object activation/expiry/cleanup protocol with exact state/write order and failure recovery.
4. Per-incident source-ledger/input/fingerprint tables and a coherent multi-ledger snapshot algorithm.
5. Named provenance enforcement files/callsites for production rejection and diagnostic acceptance.
6. Exact diagnostic receipt keys/reason codes, state outcome matrix and promotable config schema-key allowlist.
7. Resolution of the ordinary identity-sharing acceptance contradiction and the missing test-file reference.

## Approval Boundary

The principles, rejected permanent-master option, corrected ordinary identity semantics, explicit TTL/restart state, private-DM containment, v1 receipt compatibility, de-identification constraints, human-only live operations and no-Telegram-UI boundary may be retained. Execution of diagnostic registry enablement, gateway loader branching, capabilities, snapshots, replay materialization, promotion manifests or live/manual operations is not approved until the missing admission, recovery and snapshot contracts are revised. No tests, live Telegram actions, credential actions, manual P2–P6 or deployment were approved or performed.

## Summary

- **Clarity:** Improved substantially, but bootstrap, expiry and replay loader boundaries still require invention.
- **Verifiability:** Broad test categories exist; exact schemas, reason codes, row/provider matrices and coherent snapshot proof do not.
- **Completeness:** Session names and risks are present; admission, crash recovery, ledger mapping and enforcement callsites are missing.
- **Big Picture:** The isolation goal is sound, but the unchanged ordinary loader can consume the enabled isolated registry.
- **Principle/Option Consistency:** Default-off intent is strong; acceptance criterion 2 contradicts preserved ordinary shared-user semantics.
- **Alternatives Depth:** Major rejected options are covered; capability handoff and diagnostic-registry representation alternatives are not resolved.
- **Risk/Verification Rigor:** Good pre-mortem, but several preventions do not yet have executable mechanisms.

## Required Changes

1. Define the exact diagnostic bootstrap: who mints the initial owner/session capability, its fields/authentication, how the gateway receives it, and the precise constructor/loader branch. Prove neither config alone nor automatic profile discovery can select diagnostics.
2. Use a distinct diagnostic registry/document marker rejected by `load_runtime_customer_registry`, or specify an equivalent mandatory session check in every path that could consume the isolated registry. Reconcile this with unchanged ordinary shared-user semantics.
3. Add a crash-recovery state/write protocol for session append plus isolated registry enable/disable, including expiry without traffic, restart, partial write, cleanup failure and idempotent repair.
4. Map every incident class to exact source ledgers, bounded branch inputs, logical concurrency markers and outcome fields. Define a coherent read protocol across each ledger's real writer lock or a validated revision-before/after retry algorithm; define which metadata the no-mutation test compares.
5. Name and include every loader/model/projection file that must reject or accept diagnostic synthetic provenance, with exact ordinary-vs-diagnostic behavior.
6. Enumerate the diagnostic receipt's complete check/count/digest/reason schema, state-by-state route/row/provider expectations, and exact promotable config schema keys.
7. Correct the test target to `test_customer_coaching_domain.py` or explicitly mark a new file, and rewrite acceptance criterion 2 so only diagnostic authority/workflows—not ordinary legal identity sharing—are session-only.
