Skip to content

v0.0.138: fix #593 closure-return shadow-push + ENVIRONMENT.md#598

Merged
aallan merged 7 commits into
mainfrom
claude/fix-593-closure-return-shadow-push
May 7, 2026
Merged

v0.0.138: fix #593 closure-return shadow-push + ENVIRONMENT.md#598
aallan merged 7 commits into
mainfrom
claude/fix-593-closure-return-shadow-push

Conversation

@aallan

@aallan aallan commented May 7, 2026

Copy link
Copy Markdown
Owner

Summary

Test plan

  • 4 new tests in TestClosureReturnShadowPushBalance — positive regression, eager-GC behavioural (flat array_map and recursive Life-shape), and structural WAT assertion of the return-value push
  • Full test suite: 3,737 passed, 14 skipped (4 new, no regressions)
  • All 86 conformance programs pass, all 33 examples pass
  • Original life_full_program.vera at 12×30 × 200 generations: exit 0, 0 U+FFFD bytes (was 6,320 pre-fix)
  • Same program under VERA_EAGER_GC=1: 0 U+FFFD, completed all printed generations
  • mypy clean, version sync clean, limitations sync clean, doc counts clean, site assets up-to-date

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added ENVIRONMENT.md centralising all VERA_* environment variables and inference key guidance
    • Introduced VERA_EAGER_GC diagnostic knob
  • Bug Fixes

    • Fixed GC shadow‑stack imbalance for non‑allocating closure return values in array operations
    • Added regression tests covering the closure return‑value GC fix and eager‑GC diagnostics
    • Documented a macOS abort during process teardown after Ctrl‑C
  • Documentation

    • Updated README, CHANGELOG, HISTORY and related docs for v0.0.138 and env‑var guidance

The bug: array_map / array_mapi always emit a per-iteration "$gc_sp
-= 4" after each call_indirect when the element type is heap-pointer-
like (b_needs_unwind path).  But _compile_lifted_closure only emitted
the matching gc_shadow_push of the return value when the closure body
itself allocated (ctx.needs_alloc=True).

A closure body like fn(@Bool -> @string) { render_cell(@Bool.0) }
where render_cell returns String literals (data segment, no heap
alloc) had needs_alloc=False, so its epilogue emitted no push -- but
the array_map loop popped anyway, dropping $gc_sp BELOW the
surrounding function's prologue baseline.  Subsequent shadow-stack
pushes overwrote slots holding still-live roots, so the next GC mark
phase missed those roots and swept their referents -- manifested as
silent string corruption (Conway's Life rendering -- the original
issue's symptom: U+FFFD bytes interleaved with valid output) or
call_indirect out-of-bounds table access trap at smaller scales.

Fix: lift the return-value push out of the if-ctx.needs_alloc branch
in _compile_lifted_closure.  Always push when the return type is a
heap pointer (i32_pair or i32 ADT).  No gc_sp save/restore needed in
the non-allocating branch -- nothing to clean up -- just intercept
the return to publish the root.

Diagnostic: added VERA_EAGER_GC=1 environment variable that prepends
call $gc_collect to every $alloc invocation.  Surfaced the rooting
imbalance on the very first iteration rather than only at scale,
which was the diagnostic that cracked the investigation.  Permanent
debug knob now -- documented in new top-level ENVIRONMENT.md catalogue.

Validation:
- 4 new tests in TestClosureReturnShadowPushBalance cover positive
  regression, eager-GC behavioural (flat array_map and recursive
  Life-shape), and structural WAT assertion of the return-value push
- Original life_full_program.vera at 12x30 x 200 generations: exit 0,
  zero U+FFFD corruption (was 6,320 U+FFFD pre-fix)
- Full test suite: 3,737 passed, 14 skipped (no regressions)
- All 86 conformance programs pass, all 33 examples pass

Documentation:
- New ENVIRONMENT.md centralises the eight VERA_* environment variables
  (provider keys, runtime overrides, dev knobs) -- previously scattered
  across README, AGENTS, TESTING, CONTRIBUTING, SKILL, CLAUDE.
  Cross-linked from each.
- KNOWN_ISSUES.md, ROADMAP.md, HISTORY.md updated to reflect #593
  closure rather than carrying the open-bug entry.

Closes #593

Co-Authored-By: Claude <noreply@anthropic.invalid>
@codecov

codecov Bot commented May 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.92%. Comparing base (f19bf1c) to head (d9f831e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #598      +/-   ##
==========================================
+ Coverage   90.87%   90.92%   +0.04%     
==========================================
  Files          59       59              
  Lines       22968    22997      +29     
  Branches      259      259              
==========================================
+ Hits        20873    20910      +37     
+ Misses       2088     2080       -8     
  Partials        7        7              
Flag Coverage Δ
javascript 57.36% <ø> (ø)
python 94.74% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8ac1c683-2a2b-4afa-ba52-d6aa4b5d215c

📥 Commits

Reviewing files that changed from the base of the PR and between f83bdd4 and d9f831e.

📒 Files selected for processing (1)
  • TESTING.md

📝 Walkthrough

Walkthrough

This release v0.0.138 fixes a GC shadow-stack push/pop imbalance in lifted closures returning heap pointers when the closure body is non-allocating. The core fix centralises return-pointer detection and adds unconditional epilogue root-pushing for pointer-returning non-allocating closures. A compile-time VERA_EAGER_GC diagnostic knob forces GC on every allocation. A new ENVIRONMENT.md centralises all VERA_* variable documentation.

Changes

GC shadow-stack closure-return fix and diagnostic infrastructure

Layer / File(s) Summary
Closure return-root GC epilogue fix
vera/codegen/closures.py
Centralised computation of ret_is_pointer independent of allocation. Added unconditional gc_shadow_push for non-allocating closures returning String, Array or i32-pair pointers to balance caller-side unwind expectations.
Regression test suite
tests/test_codegen_closures.py
New TestClosureReturnShadowPushBalance class validates non-allocating pointer-returning closures via array_map/array_mapi, stress-tests under eager GC, recursive render checks, and WAT-level structural assertions including alloc-prologue injection and truthy-env parsing.
VERA_EAGER_GC compile-time diagnostic knob
vera/codegen/assembly.py
Environment-variable-driven conditional injection of call $gc_collect prefix into every generated $alloc WAT function to force aggressive collection and surface rooting imbalances.
ENVIRONMENT.md centralised documentation
ENVIRONMENT.md
Canonical reference for inference API keys, provider/model overrides, and diagnostic knobs (VERA_EAGER_GC, VERA_JS_COVERAGE).
Version and CI/script enhancements
vera/__init__.py, pyproject.toml, scripts/check_version_sync.py, scripts/check_doc_counts.py
Bumped version to 0.0.138; added uv.lock validation to version sync script; added docs/index.html conformance/example count validation.
Documentation cross-references & release notes
AGENTS.md, SKILL.md, CLAUDE.md, CONTRIBUTING.md, README.md, TESTING.md, ROADMAP.md, HISTORY.md, KNOWN_ISSUES.md, CHANGELOG.md
Updated docs to reference ENVIRONMENT.md, add VERA_EAGER_GC usage/test commands and example-run guidance, record v0.0.138 release/test metrics, and add macOS wasmtime cleanup abort note.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • aallan/vera#572: Modifies closure return-value ret_is_pointer classification in vera/codegen/closures.py, directly related.
  • aallan/vera#569: Related fixes to closure-lifting GC/root handling in vera/codegen/closures.py.
  • aallan/vera#454: Earlier changes to _compile_lifted_closure affecting i32_pair and host-import propagation; relevant to this fix.

Suggested labels

compiler, tests, ci, docs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarises the two main components of this release: fixing issue #593 (closure-return shadow-push imbalance) and introducing centralised ENVIRONMENT.md documentation.
Docstring Coverage ✅ Passed Docstring coverage is 84.62% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/fix-593-closure-return-shadow-push

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Microsoft Presidio Analyzer (2.2.362)
TESTING.md

Microsoft Presidio Analyzer failed to scan this file


Comment @coderabbitai help to get the list of available commands and usage tips.

aallan and others added 2 commits May 7, 2026 15:54
CI lint job runs `uv lock --check` which requires the lockfile to
match `pyproject.toml`.  The version bump in the previous commit
invalidated it.

Co-Authored-By: Claude <noreply@anthropic.invalid>
Catches the failure mode that broke #598 CI: bumping the version in
pyproject.toml + vera/__init__.py without regenerating uv.lock.  The
lint job's uv-lock --check flagged it, but the round-trip is avoidable
if the pre-commit hook catches the drift locally.

Anchors on the [[package]] / name = vera / version = X.Y.Z triple in
uv.lock rather than a global vera regex, so a future transitive dep
named vera (unlikely but possible) wouldn't false-match.

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan

aallan commented May 7, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown
✅ Actions performed

Full review triggered.

The site landing page's status block had drifted to '81-program
conformance suite and 32 worked examples' while the live counts were
86 and 33.  Static HTML, no automated check on it, so it had been
silently stale for several releases.

Updates the numbers to 86 / 33 and extends scripts/check_doc_counts.py
with a new section 13 that pins both counts via regex against the live
conformance manifest and examples directory — same approach as the
existing checks for TESTING.md, README.md, ROADMAP.md, etc.

Co-Authored-By: Claude <noreply@anthropic.invalid>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@HISTORY.md`:
- Line 275: The HISTORY entry added v0.0.138 but left the roll-up footer count
at "137 tagged releases"; update the footer/summary counts that mention "137
tagged releases" (and any other staged-release totals in the HISTORY
footer/ROADMAP/Stage 11 sections) to "138 tagged releases" so the file is
internally consistent with the new v0.0.138 entry.

In `@ROADMAP.md`:
- Around line 38-40: Update the stabilisation-gate summary sentence that still
reads “#1–#4 are closed” to reflect the new ordered list (items 1–3 now defined
in the preceding section); locate the sentence that references the numbered
issues/gates and change it to reference the correct range (e.g., “#1–#3 are
closed” or rephrase to “the top three gates are closed”) so the ROADMAP text
matches the reordered list entries.

In `@tests/test_codegen_closures.py`:
- Around line 979-1095: The PR adds an eager-GC non-allocating pointer-return
regression test for array_map but misses the array_mapi unwind path; add a new
test function (e.g. test_eager_gc_array_mapi_with_non_allocating_string_closure)
that mirrors test_eager_gc_array_map_with_non_allocating_string_closure but uses
array_mapi calls and a closure signature fn(`@Bool`, `@Nat` -> `@String`) that returns
pick(`@Bool.0`); compile under with mock.patch.dict(os.environ, {"VERA_EAGER_GC":
"1"}), execute the result, and assert the same expected stdout ("...X....") to
cover the array_mapi edge case in pick, render_cell, and run_loop-related paths.
- Around line 1148-1158: The current predicate building non_alloc_with_push only
checks for "global.set $gc_sp" and absence of "call $alloc", which can be
satisfied by a plain stack-restore without an actual return-root shadow push;
update the predicate in the test to assert an explicit push sequence for the
return-root in candidate_bodies (e.g., require the closure body to contain the
push instruction sequence used by the runtime such as the explicit push-call or
i32.const + call that represents the shadow-push of the return root) instead of
relying solely on "global.set $gc_sp"; modify the comprehension that defines
non_alloc_with_push to look for that explicit push pattern (referencing the
variable non_alloc_with_push and the candidate_bodies list) so the test only
passes when a real return-root push is present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2d293ea8-9510-4aec-a4bd-9f69e27f6c68

📥 Commits

Reviewing files that changed from the base of the PR and between f19bf1c and c6b2f30.

⛔ Files ignored due to path filters (6)
  • docs/SKILL.md is excluded by !docs/**
  • docs/index.html is excluded by !docs/**
  • docs/index.md is excluded by !docs/**
  • docs/llms-full.txt is excluded by !docs/**
  • docs/llms.txt is excluded by !docs/**
  • uv.lock is excluded by !**/*.lock, !uv.lock
📒 Files selected for processing (18)
  • AGENTS.md
  • CHANGELOG.md
  • CLAUDE.md
  • CONTRIBUTING.md
  • ENVIRONMENT.md
  • HISTORY.md
  • KNOWN_ISSUES.md
  • README.md
  • ROADMAP.md
  • SKILL.md
  • TESTING.md
  • pyproject.toml
  • scripts/check_doc_counts.py
  • scripts/check_version_sync.py
  • tests/test_codegen_closures.py
  • vera/__init__.py
  • vera/codegen/assembly.py
  • vera/codegen/closures.py

Comment thread HISTORY.md
Comment thread ROADMAP.md
Comment thread tests/test_codegen_closures.py
Comment thread tests/test_codegen_closures.py
@aallan

aallan commented May 7, 2026

Copy link
Copy Markdown
Owner Author

Comprehensive PR review (3 specialised agents, parallel)

Three agents reviewed in parallel: code quality, test coverage, comment accuracy. Skipped type-design (no new types) and silent-failure-hunter (no error-handling changes). Posting findings + action plan here for the permanent record.

Critical issues

  1. Test gap: ADT branch of the fix is completely untested. The fix at vera/codegen/closures.py:406-422 has two branches — i32_pair (String / Array) and i32 ADT. All four new tests cover only i32_pair. Verified by the test analyzer: a non-allocating identity closure over an ADT (fn(@Box -> @Box) { @Box.0 }) traps with shadow-stack overflow at 50 elements pre-fix and works post-fix — exactly the shape the second branch ships.
  2. Comment file:line citations will rot. Three places cite vera/wasm/calls_arrays.py:649-655 / :1430-1439 / :780-784 / :1557-1561 (closures.py comment, two test docstrings). calls_arrays.py is 2,472 lines and changes routinely; within 2–3 releases these will be wrong. Drop the numbers, keep symbol references (_translate_array_map's b_needs_unwind flag).
  3. _emit_alloc docstring inaccuracy. vera/codegen/assembly.py:481 says "prepend... to the body" but the call $gc_collect actually goes after the local declarations (WAT requires locals first). Cosmetic but misleading.
  4. Class docstring claims "three layers" with four tests. TestClosureReturnShadowPushBalance docstring's closing sentence at tests/test_codegen_closures.py:920-936 lists three layers but the class has four tests. Trivial wording fix.

Important issues

  1. array_mapi non-allocating-closure case structurally untested. All four new tests use array_map; the recursive Life-shape test does call array_mapi but its closure returns Bool, which doesn't trigger b_needs_unwind. The pop site at _translate_array_mapi is structurally identical to array_map's but unpinned by the new suite.
  2. No structural test that VERA_EAGER_GC=1 actually injects call $gc_collect. If the env-var-reading code silently regresses to a no-op, the eager-GC tests still pass because they degenerate to the non-eager case. A 5-line WAT-grep test pins the mechanism.

Suggestions

  • VERA_EAGER_GC env-var accepts 1/true/yes but rejects True/YES/On — lowercase before comparing
  • Test per-method docstrings duplicate the class docstring's bug narrative
  • ENVIRONMENT.md provider-key table has awkwardly wrapping "Required" cells
  • Tighten the 20-line bug-narrative comment in closures.py to ~12 lines
  • Stale # pragma: no cover comments on i32_pair paths in _compile_lifted_closure (the new tests cover those branches)

What's well done

  • The fix is correct, minimal, well-targeted: ret_is_pointer predicate exactly mirrors b_needs_unwind; the lift reduces duplication while expanding coverage
  • Test docstrings explain pre-fix behaviour, post-fix expectation, and why the test exists
  • The bug-narrative comment in closures.py earns its line count by capturing why the asymmetric if/elif branches exist
  • ENVIRONMENT.md "Adding a new environment variable" section establishes a maintenance protocol against future drift
  • Both new check-script enhancements (uv.lock + docs/index.html status block) close real holes with robust patterns
  • mock.patch.dict(os.environ, ...) isolation is correct

Action plan

Will implement (1)–(6) plus the trivial mechanical fixes as a follow-up commit on this branch:

  1. Add ADT-branch structural test (covers the second half of the fix)
  2. Add array_mapi non-allocating-closure structural test
  3. Add VERA_EAGER_GC injection structural test
  4. Drop file:line citations from comments; replace with symbol references
  5. Fix "prepend to body" → "first instruction after local declarations"
  6. Fix "three layers" → match actual count
  7. Tighten test docstring duplication
  8. Lowercase VERA_EAGER_GC env-var comparison

Skipping the ADT behavioural and eager-GC behavioural tests — the structural test is the higher-leverage pin (it would have failed pre-fix; behavioural tests can pass coincidentally at small scale).

Recommendation from code-reviewer was approve-and-merge; the test-analyzer's ADT-branch gap is the only finding worth blocking on, and that's a 10-minute additional test, not a fix change.

Mechanical fixes (review-comment-analyzer findings):
- Drop file:line citations in closures.py + test docstrings; replace
  with symbol references (calls_arrays.py is 2,472 lines and changes
  routinely; line ranges would shift within 2-3 releases).
- Fix _emit_alloc docstring: "prepend to body" -> "first instruction
  after local declarations" (WAT requires locals at the top so the
  call $gc_collect goes after them, not at the very start).
- Trim TestClosureReturnShadowPushBalance class docstring's "three
  layers" claim to match the actual four test layers.
- Tighten redundant per-test docstrings that re-explained the bug
  story already covered in the class docstring.
- Lowercase VERA_EAGER_GC env-var comparison so True/YES/On/etc. are
  also accepted.

New tests (review-pr-test-analyzer findings):
- test_lifted_closure_emits_return_root_push_for_non_allocating_adt_return:
  structural assertion for the i32-ADT branch of the fix at
  closures.py:421-425.  Pre-fix this branch was completely untested;
  exercised here via a non-allocating identity closure over a Box ADT
  through array_map.
- test_array_mapi_non_allocating_closure_emits_balanced_push: pin
  _translate_array_mapi's pop site independently of array_map's so
  a future refactor that touches one but not both is caught.
- test_vera_eager_gc_injects_gc_collect_into_alloc_body: pin the
  eager-GC diagnostic mechanism itself.  Without this, a silent
  regression in the env-var-reading code would degenerate the
  eager-GC behavioural tests to the non-eager case (still passing,
  but no longer pinning the rooting balance).
- test_vera_eager_gc_accepts_case_insensitive_truthy_values
  (parametrized over 1, true, TRUE, Yes, On, "true "): pin the
  case-insensitive allowlist behaviour.

Suite: 3,746 passed (up from 3,737, +9 from new tests), 14 skipped.
Doc counts and version sync are clean.

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan

aallan commented May 7, 2026

Copy link
Copy Markdown
Owner Author

Review action plan: complete

Commit 64c4223 addresses all critical and important findings from the review above:

Mechanical fixes:

  • Dropped file:line citations in closures.py and test docstrings; replaced with symbol references (the b_needs_unwind flag, _translate_array_map/_translate_array_mapi). No more line-number rot.
  • Fixed _emit_alloc docstring: "prepend to body" → "first instruction after local declarations" (WAT requires locals at the top).
  • Trimmed TestClosureReturnShadowPushBalance class docstring's "three layers" claim to match the actual four test layers.
  • Tightened redundant per-test docstrings — they no longer re-explain the bug story already covered in the class docstring.
  • Lowercased VERA_EAGER_GC env-var comparison so True/YES/On/etc. are also accepted.

New tests (all passing):

  • test_lifted_closure_emits_return_root_push_for_non_allocating_adt_return — closes the i32-ADT branch coverage gap (the test analyzer's primary critical finding). Uses fn(@Box -> @Box) { @Box.0 } identity over an ADT through array_map; pre-fix this branch was completely untested.
  • test_array_mapi_non_allocating_closure_emits_balanced_push — pins _translate_array_mapi's pop site independently of array_map's. Behavioural + eager-GC.
  • test_vera_eager_gc_injects_gc_collect_into_alloc_body — pins the diagnostic mechanism itself by checking $alloc's WAT prologue directly. Without this, a silent regression in the env-var-reading code would degenerate the eager-GC behavioural tests to the non-eager case (still passing, no longer pinning rooting balance).
  • test_vera_eager_gc_accepts_case_insensitive_truthy_values — parametrized over 1, true, TRUE, Yes, On, and "true " (trailing space). Locks down the case-insensitive allowlist.

Suite: 3,746 passed (up from 3,737, +9 from the new tests + parametrized variants), 14 skipped. Doc counts and version sync are clean.

Skipped: ADT behavioural + ADT eager-GC behavioural tests. The structural test is the higher-leverage pin — it would have failed pre-fix; behavioural tests can pass coincidentally at small scale.

1. HISTORY.md "137 tagged releases" -> 138 (line 315): the v0.0.138
   row was added but the rollup footer count still said 137.

2. ROADMAP.md stabilisation-gate sentence: "order #5 starts when
   #1-#4 are closed" -> "order #4 starts when #1-#3 are closed".
   The earlier deletion of the #593 row (now closed) shifted the
   stabilisation tier to three items; the agent-integration tier
   numbering is also renumbered 5/6/7 -> 4/5/6 to match.

3. New test: test_eager_gc_array_mapi_with_non_allocating_string_closure
   mirrors the existing array_map String eager-GC test for the
   array_mapi unwind path with a fn(@Bool, @nat -> @string) closure
   returning pick(@Bool.0).  The existing array_mapi ADT test
   (test_array_mapi_non_allocating_closure_emits_balanced_push)
   covered the i32 branch; this new test covers the i32-pair branch.

4. Tighten the structural #593 predicate.  Pre-fix it accepted any
   "global.set $gc_sp" + absent "call $alloc"; CodeRabbit observed
   that a bare "global.set $gc_sp" could in principle be a stack-
   restore rather than a push.  In practice the prologue's
   gc_sp_save/restore is gated on ctx.needs_alloc and the regex
   already excludes call $alloc, so a non-allocating body cannot
   contain a restore -- but the literal predicate was weaker than
   the intent.  Adds _has_gc_shadow_push helper that anchors on the
   canonical "i32.const 4 / i32.add / global.set $gc_sp" SP-increment
   sequence emitted by gc_shadow_push (vera/wasm/helpers.py).  Used
   by both the i32-pair and i32-ADT structural tests; a non-push
   artefact in the body can no longer satisfy the assertion.

Plus: HISTORY.md tooling section gains a v0.0.138 row for
VERA_EAGER_GC alongside the existing tooling milestones (cross-
linked to ENVIRONMENT.md, which already has the full reference
section for it).

Suite: 3,747 passed (+1 from new array_mapi String test), 14 skipped.

Co-Authored-By: Claude <noreply@anthropic.invalid>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@TESTING.md`:
- Line 9: TESTING.md's overall test total (3,760) is out of sync with the
embedded conformance subtotal and the test_conformance.py listing; recompute the
canonical counts by running pytest collection (e.g., pytest --collect-only -q)
to get the authoritative total and per-file counts, then update the conformance
section number (the embedded "425 tests") and the test_conformance.py entry to
match the collected totals so all embedded totals in TESTING.md are consistent
with the pytest-collected counts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 683131ae-f524-4600-92df-0a732d80acd5

📥 Commits

Reviewing files that changed from the base of the PR and between c6b2f30 and 64c4223.

📒 Files selected for processing (6)
  • README.md
  • ROADMAP.md
  • TESTING.md
  • tests/test_codegen_closures.py
  • vera/codegen/assembly.py
  • vera/codegen/closures.py

Comment thread TESTING.md Outdated
CodeRabbit on #598 caught that line 190's "Via pytest (parametrized
-- 425 tests)" disagrees with the table at line 79 (which correctly
says 430) and with pytest --collect-only (which reports 430 tests
collected for tests/test_conformance.py).

This is the same fix CodeRabbit flagged on PR #594 just before that
PR merged.  It was applied via the Edit tool at the time but landed
in a local stash rather than the branch (the merge happened before
the push) so the fix was effectively lost.  Stash dropped as part
of this commit.

scripts/check_doc_counts.py confirms documentation counts are
consistent post-fix; the canonical 430 = 86 conformance programs *
5 check phases (parse/check/verify/run/format-idempotency).

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan aallan merged commit f63c031 into main May 7, 2026
20 checks passed
@aallan aallan deleted the claude/fix-593-closure-return-shadow-push branch May 7, 2026 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Conway's Life at 12x30 still corrupts strings from gen 1 onwards (additional trigger beyond #588)

1 participant