1%

Section 12: Verification & Benchmarks

Context: Representation optimization is uniquely dangerous because bugs manifest as silent data corruption rather than crashes. If a value is narrowed incorrectly, the program produces wrong results without any error. The only way to catch this is exhaustive comparison between optimized and unoptimized paths.

Normative 2026-07-14 architecture correction: historical two-path “interpreter versus LLVM” wording below is expanded by this section to the full executor matrix. ori_eval remains the representation-abstract oracle, ori_vm consumes VmLayoutPlan, and LLVM plus ori_backend consume the same CompiledLayoutPlan. WASM is direct compiled ori_backend output. No narrower checklist, legacy script name, or aggregate score may waive a VM, LLVM profile/AOT, native target, leak, per-program speed, or memory cell required here.

Reference implementations:

  • Rust crater: Tests compiler changes against the entire crates.io ecosystem
  • LLVM test-suite: Standardized benchmarks for measuring optimization impact
  • Go test/bench/: Microbenchmarks for individual operations + macrobenchmarks for real programs

Depends on: ALL sections (this is the final verification).


12.1 Test Matrix

Build a comprehensive test matrix covering every optimization through the full pipeline.

  • §02 Transitive Triviality:

    • Option<int> — trivial (no RC)
    • Option<str> — non-trivial (RC)
    • (int, bool, float) — trivial
    • (int, str) — non-trivial
    • Result<int, Ordering> — trivial
    • Result<int, str> — non-trivial
    • Nested: Option<Option<int>> — trivial
    • Recursive struct — non-trivial
    • Struct with all scalar fields — trivial
    • Newtype type UserId = int — trivial (resolves through Named)
    • Newtype type Name = str — non-trivial
    • FFI type CPtr — trivial (opaque pointer, no RC)
    • Generic Pair<int> — trivial vs Pair<str> — non-trivial
    • All primitive tags covered (exhaustive — 12 variants)
    • Iterator/DoubleEndedIterator — trivial (Box-allocated, no RC header)
  • §04 Integer Narrowing:

    • Loop counter for i in 0..100 → i8
    • Struct field with bounded constructor → narrowed
    • Function parameter with single call site → narrowed
    • Public function parameter → NOT narrowed
    • Arithmetic on narrowed values → correct overflow handling
    • Cross-module function call → correct ABI widening
  • §05 Float Narrowing:

    • Constant 0.5 in struct → f32 storage
    • Arithmetic result → NOT narrowed (conservative)
    • Mixed f32-storage + f64-arithmetic → correct fpext/fptrunc
  • §06 Struct Layout:

    • { bool, int, bool } → reordered (int first)
    • { int, int } → unchanged (already optimal)
    • #repr("c") struct → declaration order preserved
    • #repr("transparent") newtype → same layout as inner field
    • #repr("aligned", 16) struct → alignment ≥ 16
    • #repr("packed") struct → no padding, alignment = 1
    • Tuple (bool, int, bool) → reordered
  • §07 Enum Repr:

    • Option<bool> → 1 byte (niche)
    • Option<Ordering> → 1 byte (niche)
    • Option<str> → 24 bytes (null data-ptr niche, no tag field — same size as str itself)
    • All-unit enum → tag only
    • Single-variant enum → newtype erasure
  • §08 Escape Analysis:

    • Temporary list with proved function lifetime + static extent → stack/frame candidate; both VM and compiled plans validate independently
    • Runtime-sized temporary with complete bounded cleanup → region candidate; syntax alone does not force promotion
    • Returned list → rejects storage whose lifetime ends before the caller; longer-lived storage remains planner-selected
    • Closure-captured value → lifetime follows the closure; escaping capture is not stack/frame eligible
    • Borrowed parameter → preserves its declared/proved lifetime; borrowing alone does not imply local or escaping placement
  • §09 ARC Header:

    • OwnerBound::Bounded(0) + OwnershipObservationFacts with no additional-credit or sharing-observation events → each physical plan may select no count storage and must still execute child/user drops
    • Bounded sharing → compiled narrow-counter candidate and independent VM schema candidate; wider safe representations remain valid references
    • Unbounded/unknown sharing → bounded-width layouts rejected; each plan selects a sufficient dynamic mechanism rather than assuming universal i64
  • §10 Thread-Local ARC:

    • Single-threaded program → AIMS freezes Confined; optimized plan variants select non-atomic bookkeeping while conservative atomic variants remain valid
    • Multi-threaded with channel → shared values freeze PotentiallyShared and require race-safe mechanisms; independently proved confined values may use thread-confined mechanisms
  • §11 Collections:

    • Short string → SSO
    • Long string → heap
    • Empty list → inline
    • Large list → heap
    • [bool] → packed
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (12.1) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-12.1 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 12.1: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.


12.2 Multi-Executor Equivalence

Verify that canonical and optimized layouts produce identical observable behavior through every applicable executor from the same immutable frontend provenance.

  • Evolve ./diagnostics/dual-exec-verify.sh into the shared multi-executor harness, preserving its existing CLI through a compatibility wrapper where needed. The explicit matrix is:

    • ori_eval canonical IR oracle;
    • VM with canonical VmLayoutPlan and optimized VmLayoutPlan;
    • LLVM debug, LLVM release, and linked AOT with canonical and optimized CompiledLayoutPlan;
    • every admitted ori_backend target with canonical and optimized CompiledLayoutPlan, including a complete WASM module executed by the pinned WASM runtime/host harness;
    • optimized versus canonical within each executor, plus every executor versus ori_eval for shared semantics.
  • Record ExecutableProgram identity, neutral ReprEvidence fingerprint, selected VmLayoutPlan or CompiledLayoutPlan fingerprint, TargetSpec where applicable, executor/profile, artifact identity, entered/fallback/unsupported state, and normalized outcome for every cell. A legacy ReprPlan ID may be recorded only as migration evidence. A missing or fallback cell is not parity.

  • Add cross-backend identity tests proving LLVM and ori_backend consume the exact same field offsets, enum encodings, compiled FunctionAbi, RC-header choices, and runtime declaration classifications. Equality of independently recomputed values is insufficient.

  • Add --no-repr-opt flag to ori build:

    • Skips all §02-§11 optimizations
    • Builds explicit canonical VmLayoutPlan or CompiledLayoutPlan entries rather than triggering backend fallback
    • Produces the reference artifact/output for comparison
  • Run comparison on all applicable spec tests, admitted existing Ori fixtures, and the bytecode-VM broad corpus:

    ./diagnostics/dual-exec-verify.sh --compare-repr-opt tests/
    • Every test must produce bit-identical output (same values, same ordering)
    • Float comparisons must also be bit-identical — no ULP tolerance. The §05 narrowing guarantee is “zero precision loss”, so any output difference indicates a narrowing bug or a printing bug, both of which must be caught. (If a future optimization allows lossy narrowing via opt-in #repr("f32"), those specific tests can use ULP tolerance, but the default must be exact.)
  • Run comparison on every benchmark family at multiple input scales: micro semantic slices; medium allocation/string/collection/call/control programs; graph and nested semantics; combined application-shaped workloads; failure/unwind/limit paths. Results match exactly, including integer/float bits, stdout/effect order, panic class/source, exit status, RC/drop trace obligations, and final live memory.

  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (12.2) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-12.2 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 12.2: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.


12.3 Memory Safety Verification

  • VM ownership accounting is a prerequisite to every VM memory reading: recursively/iteratively retain and release child handles, fund COW clone children, and report live/peak/allocated object and byte counts, allocation traffic, frame/register bytes, bytecode/metadata bytes, and whole-process RSS. Final VM-owned live objects and bytes are zero after success, panic, resource-limit failure, and rejected malformed input.

  • Compiled paths record ORI_CHECK_LEAKS, RC/drop trace correspondence, sanitizer/Valgrind results, and workload-attributable peak bytes separately for LLVM and ori_backend. Direct compiled WASM records linear-memory high-water, allocation traffic, retained host handles, and final live state.

  • Run memory growth-slope tests at multiple input sizes and nesting/call depths. A flat final-live count cannot hide unbounded peak or retained cache/JIT metadata; interpreter-only and tiered/JIT memory are reported separately.

  • Valgrind (heap memory):

    ./diagnostics/valgrind-aot.sh tests/valgrind/
    • All existing Valgrind tests must pass
    • Add new Valgrind tests for:
      • SSO string operations (inline → heap transitions)
      • SVO list operations (inline → heap transitions)
      • Stack-promoted values with RC’d fields
      • Narrowed struct fields with padding
      • Niche-filled enum pattern matching
  • Create diagnostics/asan-test.sh (new script — required for AddressSanitizer testing):

    • Build ori with AddressSanitizer: RUSTFLAGS="-Zsanitizer=address" cargo +nightly b --target x86_64-unknown-linux-gnu
    • Run the spec test suite with the ASan-enabled binary
    • Run the Valgrind test suite programs through the ASan binary
    • Exit non-zero if any ASan report fires (exit code check)
    • Follow the pattern of valgrind-aot.sh: support --no-color flag, print summary at end
    • Document the environment restriction: this is a nightly + Linux/x86_64 workflow; if unavailable, the script must fail clearly rather than silently skipping
  • AddressSanitizer (stack memory):

    ./diagnostics/asan-test.sh
    • Stack-promoted values must not be accessed after function return
    • No buffer overflows in packed bool arrays
    • No out-of-bounds in narrow-element collections
  • Stress tests:

    • Create 10M small allocations → stress RC header compression
    • Create 10K threads sharing values → stress atomic/non-atomic boundary
    • Deeply nested Option<Option<...<int>>> → stress niche filling
    • 100MB packed bool array → stress packed operations
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (12.3) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-12.3 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 12.3: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.


12.4 Performance Benchmarks

  • Use one frozen benchmark registry shared with plans/bytecode-vm, with output checking, environment/tool revisions, warmup policy, repeated shell-free samples, confidence/dispersion, input scale, call/nesting depth, working-set size, executor/profile, and fallback counters. Include isolated slices and combined application workloads; neither can substitute for the other.

  • VM interpreter-only gate: Ori/Python runtime ratio is <= 0.50 per admitted program and by corpus geometric mean; workload-attributable peak memory is <= 0.50 Python per program and by geometric mean; unadjusted RSS is no worse than Python; final live memory is zero. The completion north star is pinned LuaJIT -joff time and memory. JIT/tiered results use separate rows and cannot satisfy interpreter-only gates.

  • Compiled gate: measure LLVM debug/release/AOT and ori_backend fast/optimizing tiers separately per target, including direct compiled WASM. Representation wins must not regress the reference LLVM path or violate the native-backend promotion ledgers.

  • A performance sample is invalid when any parity, leak, artifact-identity, fallback, unsupported, or output-check gate fails. Speed and memory are co-equal; retain only corpus-wide Pareto improvements or an explicitly reviewed tradeoff with no adverse scale slope.

  • Baseline (before optimizations):

    # NOTE: perf-baseline.sh currently emits a human-readable table, not JSON.
    # Either add a --json flag to perf-baseline.sh, or create perf-compare.sh
    # to parse the existing table format. Using .txt extension to match current output.
    ./scripts/perf-baseline.sh --release > baseline.txt
    • Current baseline coverage is only bench_hello, bench_small, and bench_medium; add the string/struct/ARC-heavy programs before using the broader target table below as a release gate
  • Create scripts/perf-compare.sh (new script — required for baseline comparison):

    • Takes two perf-baseline.sh output files as arguments
    • Parses the table format from perf-baseline.sh (human-readable, not JSON)
    • Reports per-benchmark delta, geometric mean improvement/regression, and highlights any metric exceeding its threshold
    • Exits non-zero if any threshold is violated (per the targets table in §12.4)
    • Follow the pattern of cow-benchmark.sh --compare for argument parsing and output formatting
  • Post-optimization measurement:

    ./scripts/perf-baseline.sh --release > optimized.txt
    ./scripts/perf-compare.sh baseline.txt optimized.txt
  • Metrics to track:

    MetricMeasurementTarget
    Compile timetime ori build< 10% regression
    AOT binary sizels -la output≤ 5% increase from extra codepaths
    Runtime (bench_medium)time ./bench_medium≥ 10% improvement
    Runtime (string-heavy)time ./string_bench≥ 30% improvement (SSO)
    Memory (struct-heavy)peak RSS≥ 20% reduction (narrowing)
    Memory (collection-heavy)peak RSS≥ 30% reduction (SVO + SSO)
    RC operationsgrep ori_rc output.ll | wc -l≥ 40% fewer (triviality + escape)
    VM interpreter runtimefrozen Python/LuaJIT comparators≤ 0.50× Python floor; match/beat LuaJIT -joff north star
    VM workload memoryVM counters + adjusted/unadjusted RSS≤ 0.50× Python floor; match/beat LuaJIT -joff north star
    Compiled layout identityshared-plan fingerprints/entriesexact identity across LLVM and ori_backend
  • Microbenchmarks (add to compiler/oric/benches/):

    • repr_narrowing: Measure ReprPlan computation time
    • range_analysis: Measure range analysis time per function
    • escape_analysis: Measure escape analysis time per function
    • rc_atomic_vs_nonatomic: Measure RC operation throughput
  • Macrobenchmarks (add to tests/benchmarks/):

    • string_processing.ori: Short string manipulation (SSO benefit)
    • data_structures.ori: Small struct creation/destruction (narrowing benefit)
    • option_heavy.ori: Option manipulation (niche benefit)
    • arc_heavy.ori: Many small heap allocations (header compression benefit)
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (12.4) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-12.4 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 12.4: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.


12.5 Code Journeys

Run /code-journey to test the full pipeline end-to-end with progressively complex programs.

  • Run /code-journey with programs exercising each optimization:

    • Journey 1: Simple narrowing (loop counter, struct field)
    • Journey 2: SSO strings (creation, concat, slice)
    • Journey 3: Escape analysis (temporary values, closures)
    • Journey 4: Thread-local ARC (single-threaded vs multi-threaded)
    • Journey 5: Combined (program using all optimizations together)
  • All CRITICAL findings triaged (fixed or tracked)

  • Evaluator, VM, LLVM debug/release/AOT, and admitted ori_backend targets produce identical results and cleanup outcomes for all journeys; the combined journey includes direct compiled WASM where the feature surface is supported

  • Journey results archived in plans/code-journeys/

  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (12.5) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-12.5 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 12.5: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.


12.6 Documentation

  • Update CLAUDE.md with:

    • ori_repr crate description and key paths
    • ReprPlan proof/eligibility query interface and tracing
    • VmLayoutPlan versus shared CompiledLayoutPlan ownership
    • ori_target::TargetSpec and the LLVM/ori_backend anti-fork contract
    • ReprAttribute enum and #repr attribute interaction
    • New runtime functions (ori_rc_*_nonatomic, ori_rc_*_i8/i16/i32, SSO, SVO)
    • --no-repr-opt flag documentation
    • dependency shape: ori_target and {ori_types, ori_arc, ori_ir} feed ori_repr; ori_vm consumes VM facts; LLVM and ori_backend consume the shared compiled plan; oric owns selection
  • Update spec (docs/ori_lang/v2026/spec/annex-e-system-considerations.md):

    • Mark implemented optimizations as “implemented” vs “future”
    • Update the built-in type representations table to match the current runtime baseline before adding new optimizations:
      • str is the 24-byte SSO-capable form, not { len, data }
      • Option<T> / Result<T, E> currently lower with i64 tags in LLVM, not i8
      • RC-managed heap values currently use the V5 32-byte header (data_size, elem_dec_fn, elem_count, strong_count)
    • Add SSO/SVO to the built-in type representations table
  • Update .claude/rules/ with:

    • ReprPlan query patterns
    • How to add new representation optimizations
  • Update plans/repr-opt/00-overview.md with final metrics

  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (12.6) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-12.6 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 12.6: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.


12.7 Completion Checklist

Scripts created in this section:

  • diagnostics/asan-test.sh created and functional (builds ASan binary, runs spec+valgrind tests, exits non-zero on ASan report)
  • scripts/perf-compare.sh created and functional (parses perf-baseline.sh output, reports deltas, exits non-zero on threshold violations)
  • tests/valgrind/threads/ directory created with thread_local_only.ori and channel_send.ori

Verification:

  • Test matrix covers all §02-§11 features (every checkbox in 12.1)
  • Multi-executor verification: 0 evaluator/VM/LLVM/ori_backend mismatches across all applicable spec, fixture, benchmark, combined-application, and failure-path cells; no hidden fallback or unrecorded unavailable cell
  • Valgrind: 0 errors across all Valgrind tests (old + new)
  • AddressSanitizer: 0 errors (via diagnostics/asan-test.sh)
  • Helgrind: 0 races in threading test programs (via ./diagnostics/valgrind-aot.sh --helgrind tests/valgrind/threads/)
  • Stress tests pass (10M allocations, 10K threads, 100MB packed array)
  • Speed and memory baselined with before/after comparison for VM interpreter-only, each compiled backend/profile/target, and any tiered/JIT mode separately
  • No compile-time regression > 10%
  • Runtime improvement ≥ 10% on benchmark suite
  • Memory reduction ≥ 20% on struct-heavy benchmarks
  • RC operation count reduced ≥ 40% on typical programs
  • VM remains at least 2× Python per program and by geometric mean, workload memory is at most 0.5× Python, final live memory is zero, and the LuaJIT -joff gap ledger is complete
  • LLVM and ori_backend consume identical CompiledLayoutPlan/compiled ABI entries on all shared targets; direct compiled WASM completes its module/runtime/host matrix
  • Code journeys pass — evaluator/VM/LLVM/ori_backend outcomes match
  • All documentation updated
  • ./test-all.sh green
  • ./clippy-all.sh green
  • /tpr-review passed — independent Codex review found no critical or major issues (or all findings triaged)
  • /impl-hygiene-review passed — implementation hygiene review clean (phase boundaries, SSOT, algorithmic DRY, naming). MUST run AFTER /tpr-review is clean.
  • /improve-tooling retrospective completed — MANDATORY at section close, after both reviews are clean. Reflect on the section’s debugging journey (which diagnostics/ scripts you ran, which command sequences you repeated, where you added ad-hoc dbg!/tracing calls, where output was hard to interpret) and identify any tool/log/diagnostic improvement that would have made this section materially easier OR that would help the next section touching this area. Implement every accepted improvement NOW (zero deferral) and commit each via SEPARATE /commit-push. The retrospective is mandatory even when nothing felt painful — that is exactly when blind spots accumulate. See .claude/skills/improve-tooling/SKILL.md “Retrospective Mode” for the full protocol.

Exit Criteria: Running ./scripts/perf-compare.sh baseline.txt optimized.txt shows:

  • Runtime: geometric mean ≥ 10% improvement across benchmark suite
  • Memory: geometric mean ≥ 20% reduction across benchmark suite
  • RC operations: ≥ 40% fewer in generated LLVM IR
  • VM floor: per-program and geometric-mean runtime ≤ 0.50× Python, workload memory ≤ 0.50× Python, unadjusted RSS no worse, final live bytes/objects zero; LuaJIT -joff remains the completion north star
  • Correctness: 0 mismatches in the full executor matrix, compiled layout/ABI identity proven, 0 VM leak-accounting failures, 0 sanitizer/Valgrind errors
  • All commands: ./test-all.sh, ./clippy-all.sh, ./llvm-test.sh, VM production suite, native-backend target matrix, and direct compiled WASM suite green

12.R Third Party Review Findings

  • [TPR-12-001][minor] — Resolved by §12.2’s canonical-versus-optimized matrix for every executor, including evaluator versus unoptimized LLVM AOT and explicit canonical-plan entries rather than fallback.