# Independent codec/lifecycle source review — 2026-09-11 Codex-956atf `/root/analysis_core_review`. Reviewed the nine frozen source/dependency inputs in `.local/analysis-core-worktree-20260911` over `cdebb49d894952a189b144cc52deaf444e91d343`, plus the implementation handoff. Read prior `harness/release-analysis-decoder-review-20260911.md`, issue1 comment370, current `AnalysisCoreSchema820260911` Wiki and empty open-PR inventory. Review ownership is issue1 comment378. Only this new root report and named Gitea handoff were written; no source edits, Cargo/rustc/test execution, native/WSL/Linux/VPN changes, Git mutation or further delegation. ## Verdict **No confirmed material source defect found in this frozen candidate.** It is suitable for root's first isolated Windows compilation/subprocess gate. This is source review, not a claim that the candidate compiles, satisfies its memory/stack requirements or completes schema8 transport. `DEPTH_128_VALIDATED` remains false at `crates/oa-core/src/persistence/json_codec.rs:22`; retain that setting pending the actual closure gates and root's explicit activation decision. All paths below are relative to the isolated worktree. The static checker milestone's previous depth/analysis/numeric/Clippy passes do not cover this new lifecycle/persistence delta. ## Checked behavior - `persistence/json_codec.rs:87`: original bytes are checked against the byte cap before the fixed512-container scanner traverses them. Tokens include keys, values and punctuation. A nonempty container charges its first entry and charges each subsequent comma-delimited entry; object values do not spuriously count as a second member. Parent state survives nested containers. Escaped quote/backslash pairs do not alter container depth, and raw string spans conservatively bound decoded UTF-8 for valid JSON. The scanner may pass malformed scalar/whitespace/comma syntax, but it never accepts a Project: the following Serde passes still reject it. I found no valid-JSON route that allocates uncounted array entries/object members through this scanner. - `persistence.rs:144`, `json_codec.rs:219`: the version visitor consumes the original stream, rejects repeated decoded `schema_version`, and skips other values rather than constructing a current-schema header Value. Current Project decoding still uses the original bytes, so duplicate keys cannot be normalized away by a DOM. Both probe and current reader call `end()`. Legacy versions retain their original typed readers and default Serde depth guard; the bounded pre6 Value is inspected and then discarded before typed construction. `reject_source7_fields` preserves parent-before-child and map/array traversal order with its reversed worklist insertion. The public source-language branch remains distinct and is not newly claimed as codec closure. - `analysis/expression_serde.rs:82`: NodeGuard checks logical128, aggregate262144 and per-tree65536 before the remote visitor constructs the node. Depth-zero entry resets only per-tree accounting inside an operation scope; disjoint bindings retain aggregate accounting. Guard drop unwinds depth and Scope restores prior state on ordinary failure/unwind. No mutable TLS borrow spans Serde/user code or the stack switch. The private remote derive retains the original13 tagged variants and field types; original duplicate/unknown-field handling remains Serde's responsibility. No unguarded public inherent remote decoder was introduced. - `expression_serde.rs:201`, `:231`: List item1025 is refused by a seed before Expr deserialization. Call keys are decoded as scoped ParameterId, checked for duplicates and width before `next_value`, so an escaped duplicate key cannot construct a second deep value first. Guard failures propagate immediately through the concrete Project reader. Standalone Expr Serde gets a root meter; generic wrappers containing several independent Expr roots are not claimed to share a persistence document meter. - `analysis/expression_lifecycle.rs:60`, `:99`: Drop moves owned children to a heap worklist, leaving boxed Boolean sentinels or empty collections. Reentry through a detached node sees only those shallow owners; nesting does not follow the original tree depth. Partially constructed Serde locals therefore use the same Expr destruction behavior. Allocation still occurs during ordinary destruction, and arbitrary trusted in-memory trees can exhaust heap memory; the implementation makes no stronger promise. - `expression_lifecycle.rs:111`, `:171`, `:284`: Clone creates matching variant metadata and child slots, then fills disjoint mutable slots iteratively. Equality checks variant metadata, list length/order and exact Call keys before comparing corresponding children. Debug schedules child Expr nodes explicitly and only invokes ordinary scalar Debug on fixed non-Expr values. The compact Debug output intentionally does not promise the old pretty layout. Pending worklists scale with admitted tree size/width; they are not128-entry stacks and are not described as such in this review. - `json_codec.rs:309`, `:357`, `:387`: reader/writer checks precede reserve/extension, with bounded geometric reserve requests. File metadata is an early rejection only; chunk reads also catch growth. JSON output is compact, includes its trailing newline in the cap, then passes the same profile and depth setting through typed current decoding and Project equality before filesystem mutation. `persistence.rs:945` validates the Project before encoding; successful JSON readback is therefore checked against an already validated value. Conflict comparison streams fixed chunks. The sibling temporary file is created only after encoding/readback; a later conflict removes it through normal temporary-file cleanup and preserves the destination. The existing non-CAS race remains explicitly documented. ## Resource and compatibility qualifications The profile now supplies finite byte/text/entry/node cardinalities. It does not supply an exact allocation-byte/RSS bound: typed slot sizes, BTreeMap/Vec capacity, decoder scratch, duplicate/partial values and retained original/output/reopened Project buffers all contribute. A64MiB raw string may still cause a correspondingly large bounded String/scratch allocation before an Exact-specific rejection. The new coarse document bound addresses the earlier absence of a document allocation policy; it does not turn the per-literal Exact limit into a preallocation string visitor. The500000 per-container ceiling avoids the earlier obvious contraction of500000 ordered references, while the ordinary100000-object map no longer inherits an Expr65536 cap. The prepared compatibility test checks100000 ordinary typed elements, scans500000 UUID references, checks caller model counts, and roundtrips metadata exceeding1MiB. It does not establish that every possible combination of allowed record payloads fits every aggregate profile ceiling, or that every formerly unlimited native model remains admitted. The handoff explicitly labels the new ceilings as provisional document policy. Preserve that distinction when reporting compatibility. The direct dependency/lock diff adds stacker0.1.25, psm0.1.32, ar_archive_writer0.5.3 and object0.39.1 without changing existing versions. Enabling serde_json's `unbounded_depth` feature only exposes its API; the false production switch continues to leave the parser guard active. Expr entry instrumentation requests64KiB reserve/512KiB segments and the fixed outer boundary requests512KiB reserve/2MiB segments. These requested values and the128-guard limit are not proof of actual stack consumption, Windows stack-switch behavior, allocator overhead or failure safety. No upstream implementation execution or platform measurement was performed by this reviewer. The inspected stored Project/element/relation/data/semantic-fact shapes are finite nesting outside Expr; their graph recursion is represented by IDs. Existing parent/relation traversal and checked analysis traversal use iterative walks. This supports the scoped outer-document design, but is not a whole-program stack proof. A successful legacy temporary Value remains iteratively discarded; partial legacy Value teardown still relies on the retained Serde recursion guard and actual outer-stack capacity. Generic `serde_json::Value`, source AST/formatting, external command/REST/CLI adapters and all unrelated caller closures remain the known separate integration boundaries, as the author records. ## Required root gates and remaining evidence gaps 1. Run the exact `persistence::json_codec::tests::codec_lifecycle_subprocess` gate first. Its five child phases use separately configured128KiB threads and120s deadlines; inspect the actual child status and phase diagnostics. The source uses the same private implementation with candidate depth enabled, while production stays conservative. Reading these assertions is not evidence that remote derive, borrowing, custom Drop, stack switching or partial unwind compiles or succeeds. 2. Run all six codec tests, analysis28, numeric26 and strict all-target core Clippy; cover the changed frozen legacy/migration and checked-save regressions. The existing child phases mainly exercise current-schema unary/Call depth, large balanced tree decoding and manual unary ownership. They do not independently prove deepest pre6 partial Value failure, every mixed Expr-variant lifecycle shape, or all large ordinary/historical Project shapes on the small stack. Include those cases when closing the broader profile, rather than treating a depth-only pass as full closure. 3. After debug success, run the Windows release driver/filter and measure actual process peak memory/time for accepted and rejected wide/deep shapes. The driver emits counts and elapsed time, not peak memory. Scanner-only/typed-only compatibility tests do not certify large-model validation or UI speed. Retain exact source, toolchain/profile, binary and terminal identities for all claims. 4. Linux checks remain deferred by the user's explicit instruction. Do not run or automatically resume them, and do not activate the production switch on the assumption they passed. Keep source8, generic Value and transport adapters, output/error caps, evaluator and final product acceptance separately open. No implementation correction is requested from source review alone. An actual compiler/subprocess failure should be preserved and then drive a bounded correction and re-review. ## Independent frozen hash readback | Input | SHA256 | | --- | --- | | `Cargo.lock` | `19499D93DDE6F2E2A00AB4B7D5F37689DD7A7D492B2B5E23063A761607839FC5` | | `crates/oa-core/Cargo.toml` | `3377D3D9D43FE0023AC09728B0D20205F86A6755F15518DC0CD035780B47A95D` | | `crates/oa-core/src/analysis.rs` | `845C3629098A13F3FFFAAC3E37D6A3CF8B7BDF33A8110465459990EB3FE70B11` | | `crates/oa-core/src/analysis/types.rs` | `27363B1755F3C0943685A9837C69E010857811D4F67A0751B20EFDD9C1707AA3` | | `crates/oa-core/src/analysis/expression_lifecycle.rs` | `5D66E4E8F33FC8F90EC364251079617A36226E3EA68AC321ABAE74096E1C7C8C` | | `crates/oa-core/src/analysis/expression_serde.rs` | `581E4704FB4F2049E31C7731267BC9D52E3F17625B664C3D7C5F19CAA961C819` | | `crates/oa-core/src/persistence.rs` | `EDA5E697ADB29A8BF38B0D367099BD23267455E4792F97607E13DC0B232A3476` | | `crates/oa-core/src/persistence/json_codec.rs` | `2AA2C52EEA794ACB85744440192DF9EF5193160AD6EBD1FEBAA824E144AADD90` | | `crates/oa-core/src/persistence/json_codec/tests.rs` | `7065CC9E177A5699432888110936529C621F13E7C4B164566AB1FD14B61D6B9C` | Implementation handoff SHA256 independently matches `38F80E88A3945720336ED65D008CC5F260ECE2830957ADE54DF7561324726169`.