## Summary
Stage 29 preserves the Stage-28 isolation, human-only, source-export, ordinary-production, read-only, package-integrity, and full-triple route boundaries while directly closing the prior mutating-reader, omitted-package-data, and stale-route admission gaps. It still leaves a P1 provider-start race: a delivery can pass its pre-provider recheck, release the admission lock, then begin the provider call after durable detaching has linearized. Do not implement until the provider invocation boundary is made atomic relative to detach.

## Claims
- The immutable RALPLAN index records `stage-29-planner.md` with SHA-256 `dc5c8b84fc4f7f0fe4ed5e55397669c5f441d0a79178525295040408c9638eb3` (`index.jsonl:41`), matching the assigned target.
- Stage 29 names non-mutating source-module APIs, opens verified existing locks read-only with `O_NOFOLLOW|O_CLOEXEC`, rejects missing/unsafe/replaced locks, retains same-inode writer `LOCK_EX`, and requires before/after tree plus race proof (`stage-29-planner.md:25-38`). This closes the Stage-28 critic’s mutating `locked()`/schedule-reader blocker without widening evidence scope.
- Stage 29 explicitly packages `checkin_cli.policies/*.json`, loads it exclusively with `importlib.resources`, digest-checks it, and requires an offline built-wheel/install resource test (`stage-29-planner.md:40-49`). This closes the source-tree-only package-data blocker.
- Stage 29 stores a route’s full triple, compares sender user/chat/topic, carries generation into final admission, and uses a shared admission lock for lifecycle transitions and reservation admission (`stage-29-planner.md:51-64`). This closes the earlier stale-route/full-triple defect at the reservation boundary.
- All Stage-28 contracts remain in force by explicit incorporation and non-expansion statement (`stage-29-planner.md:1-4, 92-100`). The plan adds no live Telegram, deployment, credentials, manual P2–P6, or product UI scope.

## Analysis
### Spec compliance
The plan is narrow and correctly preserves Stage-28’s established contracts while making the exact three final remediation areas concrete: read APIs rather than the known mutating lock APIs, installable policy bytes rather than source-only resources, and a generation-carrying route/admission fence rather than route-map removal alone. The read-lock design is fail-closed and its recursive before/after invariant is sufficient to detect the prior physical mutation class. The package design proves the installed artifact, not merely the checkout. The full-triple comparison is explicit rather than inferred from the `(chat_id, topic_id)` map key.

### Remaining linearization defect
The lifecycle and reservation operations share an admission lock, and a reservation that wins is revalidated before provider use. That is necessary but not sufficient for the stated zero-provider-after-detaching promise. The plan does not state that the provider invocation boundary itself is protected by the lock or an equivalent lease. Therefore an attempt may validate `active` immediately before provider work, release admission protection, then a close/expiry/stop persist `detaching` and remove routes; the attempt can subsequently invoke the provider. The counter is only said to delay terminal cleanup, which cannot undo a provider call that began after the durable detaching fence.

The strongest antithesis is that a reservation winning before detach makes all later work “in flight.” That would be a permissible semantic choice only if the plan explicitly allowed post-detach provider invocation for that reservation. It conflicts with its own acceptance requiring provider zero after the detaching linearization point and with the planned provider-boundary generation-race assertion. Treating the precheck as the call’s linearization point is likewise insufficient unless the actual provider-start operation is inseparable from that protected step.

### Constructive synthesis
Define a provider-start handshake and its durable/cancellation semantics. Either (a) atomically execute/commit the provider-start boundary before releasing the shared admission protection, or (b) enter a quiescing state that blocks new admissions, drain each pre-admitted lease through provider-start or provider-zero terminalization, and only then append durable `detaching`. State exactly whether the lease extends through invocation initiation or provider completion; do not use an async task scheduling gap as provider-start. Add a deterministic test that pauses after the final state/generation check but before actual provider invocation, races close/expiry/stop, and asserts the chosen linearization invariant, durable rows, and zero/one provider count.

## Root Cause
The plan protects state validation and durable reservation, but does not define a shared linearization point for the real provider invocation. Cleanup draining is later than the required authorization fence.

## Findings
1. **HIGH — `stage-29-planner.md:58-59` (reported P1).** The pre-provider recheck can complete before `detach` commits `detaching`, yet provider invocation is not required to begin under the same lock/lease. Impact: a provider call can begin after the durable close/expiry/stop fence, violating the stated provider-zero contract. Fix: make provider-start atomic with admission protection, or drain pre-admitted attempts before the durable fence; specify counter lifetime, cancellation/crash behavior, and an exact race test.

## Recommendations
1. Amend only the detachment subsection with an explicit provider-start linearization/lease protocol and the deterministic test above.
2. Retain unchanged the shared-inode reader APIs, package-data/offline wheel test, full-triple route check, Stage-28 references, verification commands, and human-only boundary; they are correctly scoped.
3. Re-review the amended plan against the post-final-check/pre-invocation interleaving before approval.

## Architectural Status
BLOCK

## Code Review Recommendation
REQUEST CHANGES

## Tradeoffs
- **Provider-start handshake before releasing admission protection (recommended):** preserves the claimed removal-wins/provider-zero contract; needs an exact start primitive rather than ambiguous task scheduling.
- **Quiesce/drain before appending `detaching`:** permits pre-admitted work to reach a defined start boundary but delays the durable close fence; safe if new admission is blocked first.
- **Current precheck plus later cleanup drain:** simplest but permits a call after the durable fence; reject.
