# Independent PLAN Review โ `audit-cargo-packaging`
## Verdict: REQUEST CHANGES
The diagnosis is correct and well evidenced, and the chosen remedy is the right shape. I verified the causal chain from the supplied bodies rather than taking the narrative on trust: `audit/2026-10-12-bao-bounded-proof/nostd-parent/Cargo.toml` (item 005, line 7) declares `cyber-bao = { path = "/tmp/radio-bao-proof-parent-b933/cyber-bao", ... }`; Cargo's Git source enumerates every manifest in the checkout and recursively reads their path dependencies, so that absolute path resolves to a second on-disk `cyber-bao v0.1.0` and produces exactly the `skipping duplicate package` text in `records/consumer-ce0-lock.stderr` (029) and `-metadata.stderr` (032). The other six manifests use `../../../cyber-bao`, which resolves to the checkout's own `cyber-bao/Cargo.toml` and therefore dedupes silently โ so the defect is real, singular in origin, and renaming all seven is a sound, conservative over-fix. The preservation strategy (never rewrite `files.json`, archive originals, stage logical layout in `/tmp`) is the right call given that both 2026-10-12 indices self-hash their own verifier (items 018, 019).
The blockers below are about the *verification* being able to fail, and about two stated equalities that cannot hold as written.
## Blockers
**1. Step 5's "zero Cargo warnings" check is vacuous without a same-session differential control and an explicit precondition on the external probe directory.**
The warning exists only because `/tmp/radio-bao-proof-parent-b933/cyber-bao` happens to exist on this machine (research correctly concedes this). If that directory is gone when the candidate is measured โ reboot, `/tmp` reaping, or another task's cleanup โ the after-run emits zero warnings whether or not the rename happened, and the capsule would assert a repair it never demonstrated. Required: within the same measurement session, (a) assert `/tmp/radio-bao-proof-parent-b933/cyber-bao/Cargo.toml` exists and record its hash/size, (b) run the identical fresh-consumer pipeline against the **unmodified ce0 tree** through the *same* local-commit acquisition path used for the candidate and record the warning reproducing, then (c) run the candidate and record it absent. The existing `records/consumer-ce0-*` receipts (027โ032) do not satisfy (b): they pin `git+https://github.com/cyberia-to/radio?rev=ce0โฆ`, a different source mechanism from step 4's local object store, and they predate the candidate run.
**2. Step 3's decisive check for `2026-10-09` has no stated feasible invocation mechanism.**
`prepare-crate` in `reproduce.nu` (010) is a plain `def`, not `export def`, so it is not importable; and Nu's `source`/`use` require parse-time-constant paths, which a `mktemp -d` staging directory is not. Either name the mechanism (e.g. a child `nu -c $"source ($staged)/reproduce.original.nu.txt; prepare-crate โฆ"` with the path interpolated, or a fixed const staging path) or restate the check honestly. This matters more than for the other two capsules, because 2026-10-09 is the one script whose exercise is deliberately partial: if "invoke its unchanged `prepare-crate`" silently degrades into "stage files and diff them," the comparison of exported manifest/lock/probe bytes loses its link to the original code path. Also enumerate the other inputs `prepare-crate` consumes from `$receipt` (`Cargo.lock`, `probe.rs`, and for the surrounding `main`, `SOURCE-FREEZE.json`, `FIXTURE-SHA256SUMS`, `expected-probe.stdout`) in the staging mapping.
**3. Step 5's "exactly the prior literal outputs and unchanged input/source hashes before/after" cannot hold for metadata and must be narrowed.**
Step 4 pins a *local* commit via a Git dependency, so the consumer's source URL becomes `file:///โฆ` and the rev is the new candidate, not `ce0fb312โฆ`. Every package id, `source` string, `manifest_path` and checkout-hash directory in `cargo metadata` will therefore differ from `consumer-before.json` (023) and `consumer-ce0-metadata.stdout` (031). As written, an implementer either fails the check or quietly redefines it. Restate as: byte-equal **reader-control program stdout** for all eight cases in both profiles; byte-equal `cyber-bao`/Hemera **source file** hashes; and an explicit enumerated allowlist of permitted metadata differences (source URL scheme, candidate rev, checkout directory hash, `at` timestamp) with everything else โ feature sets, dependency graph edges, `rust-version`, target lists โ required equal.
**4. The committed tree will be internally inconsistent with its own historical indices, and nothing is required to record that.**
After this change, `audit/2026-10-12-bao-bounded-proof/verify.nu` holds wrapper bytes while that capsule's `files.json` still records `verify.nu` = `dd3c9729โฆ`/10975 (019); same for the research capsule's `70ccf93eโฆ`/4241 (018). Not rewriting those indices is the correct decision, but the plan only commits to binding "original-to-archive mappings." Require the new capsule to carry an explicit, machine-readable row per affected index entry stating: historical index path โ archived filename that satisfies it โ the fact that a direct, unstaged check of that row against the worktree now fails by design. Without it, the first auditor who hand-checks `files.json` against the tree reads this as corruption. (I confirmed neither verifier enforces directory completeness, so the extra `*.txt` and `*.original.nu.txt` files do not break the replays, and the reported counts โ 89/9 and 619/115/85 โ are preserved as long as nothing new lands in `records/`, `epochs/` or `bindings/`.)
**5. Internal contradiction between "retain โฆ default paths" and "resolve the actual repository/sibling paths."**
`reproduce.nu` (010) defaults `--radio-repo = ~/cyber/radio` and `--hemera-repo = ~/cyber/hemera`; these are *not* FILE_PWD-derived, whereas both verifiers' `$own` defaults *are* (`$root | path dirname | path dirname`), which staging would silently redirect into `/tmp`. State per script which it is: verifiers must always receive explicitly resolved `--repo`/`--siblings`; the reproducer either keeps `~/cyber/radio` verbatim (and the capsule documents that running from a non-canonical worktree still consults `~/cyber/radio`) or deliberately overrides it (and the capsule documents the changed default). Both are defensible; leaving it ambiguous is not.
**6. `inputs/consumer-before.json` / `consumer-after.json` are mislabeled for a frozen capsule.**
Both (023, 024) are timestamped 01:20:13 and 01:23:51, both carry identical `kadek_parent` and identical ce0 source hashes, and both predate `observation.json`'s 01:31:22 `no_source_edit: true` (022). Neither is a post-repair measurement; they are the two profiles of the pre-change reader control. Rename them (e.g. `consumer-ce0-debug/-release`) before freezing, and reserve `before`/`after` for the step-5 differential pair from blocker 1.
## Advice (non-blocking)
- Generalize the invariant behind failure mode 1: in addition to the basename inventory, assert that **no tracked manifest anywhere in the tree** declares a path dependency that is absolute or escapes the repository root. That is the actual class of defect; the seven renames are one instance of it, and the check is cheap and durable. It also covers the `quinn`/`nettools` manifests, which are workspace-`exclude`d but still enumerated by the Git source and were not supplied to me.
- Record in the new capsule that `nostd-parent/Cargo.toml.txt` is permanently unreplayable by design (absolute path to a directory that will vanish), so no future agent "repairs" the frozen bytes.
- Document the expected post-merge behavior of `--live` on both verifiers: it asserts `HEAD == <historical parent>` and a clean worktree, so it must fail after this commit. Say so explicitly, with the reason, or a future reader will attribute the failure to the wrapper.
- State whether staging keeps or removes the `.txt` duplicates alongside the restored logical names. Either works for these verifiers (neither checks for extras), but future completeness checks will care.
- Add a forward guard โ a line in the audit convention docs, or a check in the new capsule โ that new archived harnesses must be committed as `Cargo.toml.txt` from the outset. Otherwise this defect returns with the next capsule.
- Step 2's "complete committed tree comparison outside the allowed audit/task paths must be empty" is the strongest control in the plan; keep it literal and machine-checked, and include `Cargo.lock` and both workspace manifests (014, 015) in the equality set explicitly.
Nothing in the plan proposes a Rust, API, specification, version, release or Kadek-dependency change, and the scope limits around soft3, row 4, and the unrefreshed red gates are stated accurately. Close blockers 1โ6 and I expect this to approve.