Skip to content

Release v0.0.120: trap categorisation + stdout preserved on trap#533

Merged
aallan merged 5 commits intomainfrom
bug-campaign-trap-diagnostics
Apr 27, 2026
Merged

Release v0.0.120: trap categorisation + stdout preserved on trap#533
aallan merged 5 commits intomainfrom
bug-campaign-trap-diagnostics

Conversation

@aallan
Copy link
Copy Markdown
Owner

@aallan aallan commented Apr 27, 2026

First pair from the bug-killing campaign. Two paired fixes share the same site (vera/codegen/api.py's except Exception branch) and one test fixture, so they ship together as v0.0.120:

What changes

WasmTrapError (new)

A RuntimeError subclass carrying:

  • stdout / stderr — whatever the program wrote before the trap, previously discarded as the exception unwound out of execute()
  • kind — stable identifier: divide_by_zero / out_of_bounds / stack_exhausted / unreachable / overflow / contract_violation / unknown

Liskov-substitutable: every existing except RuntimeError block still catches the trap and sees a sensible string. No call-site changes needed in older code.

_classify_trap (new)

Pure function. Maps (wasmtime exc, last_violation) to (kind, message). Contract-violation host-import channel always wins over the wasmtime trap reason — the host import has a more specific Vera-native message. Otherwise the wasmtime exception's str() is matched against the wasm trap: <reason> substring and routed to one of the documented kinds. Stringly-typed against wasmtime's error format, which keeps the classifier free of a wasmtime import — handy for tests and the eventual browser-runtime branch.

cmd_run handler

New except WasmTrapError block before except RuntimeError:

  • Text mode: writes captured stdout / stderr to the corresponding actual streams before the error, with an explicit sys.stdout.flush() so 2>&1 redirects show the right merged-stream order. Then f"Error: {exc}" to stderr.
  • JSON mode: stdout and stderr go into the envelope; the diagnostic gains a trap_kind field. Streams are NOT touched in JSON mode (would corrupt parsed output).

Folded in: PR #532 (mobile CSS fixes)

Cherry-picked the single commit from mobile-overflow-fixes since it's a CSS-only docs/index.html edit with no overlap with the trap work. Three iOS Safari overflow bugs at iPhone widths fixed: hero image (width:100% missing), VeraBench button (mobile .btn rule was leaking outside .cta-bar), and Runs section shell-command code blocks (white-space:pre with no wrap rule). Authorship preserved; #532 closed with a comment cross-referencing this PR.

Test plan

  • 16 new tests in tests/test_runtime_traps.py — classifier per-kind, WasmTrapError shape, end-to-end cmd_run for both text and JSON modes
  • Full suite: 3520 → 3536 (+16) passing, 14 skipped, zero existing tests broken
  • Real-world reproducer (/tmp/buffer_test.vera from IO.print output lost when program traps (stdout fully buffered) #522) — all four IO.print lines now appear before the error message under 2>&1
  • Contract violation path (safe_div(@Int, @Int -> @Int) with second arg 0) still produces "Precondition violation in safe_div..." in text mode and trap_kind: contract_violation in JSON mode
  • All doc validators green (version sync, doc counts, limitations sync, site assets)

Doc updates

What this does NOT do

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • stdout and stderr captured during runtime traps are preserved and replayed in text mode (ordering retained under merged redirects) and included in JSON error envelopes.
    • Unexpected WASM traps are relabelled to avoid misclassifying contract violations; generic errors now indicate unhandled WASM traps.
  • New Features

    • WASM traps categorised into stable, meaningful kinds; trap_kind appears in JSON diagnostics.
  • Tests

    • New test suite covering trap classification and stdout/stderr preservation.
  • Documentation

    • Changelog, history, roadmap and docs updated for v0.0.120.

Closes #522

aallan and others added 2 commits April 27, 2026 09:36
- Hero image overflowed the viewport because .hero-image only set
  max-width: 640px, which won the specificity contest against the
  global img { max-width: 100% } rule. On a 375px viewport the image
  kept its 640px target and ran off the right edge. Added width: 100%
  alongside max-width so the image now scales to viewport width up to
  640px.

- VeraBench GitHub button was being stretched to 280px on mobile by
  a .btn { width: 100%; max-width: 280px } rule meant only for the
  hero CTA stack (where buttons stack vertically and benefit from a
  full-width target). Scoped that rule to .cta-bar .btn so isolated
  buttons elsewhere on the page keep their natural inline-flex width.

- Shell-command code blocks (.runs and .install) ran off the right
  edge because <pre> defaults to white-space: pre, which doesn't wrap
  long lines like "vera run examples/factorial.vera --fn factorial -- 10".
  overflow-x: auto produces a scroll affordance but iOS users have no
  good gesture to use it inside a tight column. Added
  white-space: pre-wrap; word-break: break-word for .code-block pre
  on mobile only. Vera sample blocks (.sample .code) intentionally keep
  pre so syntax indentation isn't disrupted at narrow widths.

Verified at 375px viewport: hero image 327px (fits), bench button
143px (inline-sized), runs code blocks scrollWidth === clientWidth
(no overflow). Hero CTA buttons remain stretched at 280px as designed.

Co-Authored-By: Claude <noreply@anthropic.invalid>
First pair from the bug-killing campaign. Two paired fixes that share
the same site (vera/codegen/api.py's except Exception branch) and one
test fixture, so they ship together as v0.0.120:

  #522 (closes) - IO.print output preserved on trap
  #516 Stage 1 - WASM traps classified to a stable kind

## Implementation

- New WasmTrapError(RuntimeError) carrying stdout, stderr, kind.
  Liskov-substitutable: existing 'except RuntimeError' blocks still
  catch it and see a sensible string.
- New _classify_trap(exc, last_violation) -> (kind, message). The
  contract-violation host-import channel (last_violation) always wins
  over the wasmtime trap reason; everything else is matched on the
  'wasm trap: <reason>' substring in str(exc) and mapped to one of:
  divide_by_zero / out_of_bounds / stack_exhausted / unreachable /
  overflow / contract_violation / unknown.
- execute()'s except branch now raises WasmTrapError with the captured
  buffers. cmd_run handles it before the generic except RuntimeError,
  printing buffered stdout BEFORE the error in text mode and packing
  it into the JSON envelope (with trap_kind) in JSON mode.
- Explicit sys.stdout.flush() after the captured-output write so
  '2>&1' redirects show the right merged-stream order.

## Tests

- New tests/test_runtime_traps.py (16 tests, 284 lines): classifier
  unit tests with a _FakeTrap stand-in (the classifier is stringly-
  typed, decoupled from wasmtime); WasmTrapError shape; end-to-end
  cmd_run for stdout-on-trap and trap-kind in both text and JSON modes.
- Full suite: 3520 -> 3536 (+16) passing, 14 skipped, zero existing
  tests broken. WasmTrapError(RuntimeError) preserved compatibility.

## Folded in: PR #532 (mobile CSS fixes)

Cherry-picked the docs(site) commit from PR #532 since it's a single-
file CSS-only change with no overlap with the trap work. Three iOS
Safari overflow bugs at iPhone widths fixed: hero meerkat image
(width:100% missing), VeraBench vera-bench button (mobile .btn rule
leaking outside .cta-bar), and Runs section shell-command code blocks
(white-space:pre with no wrap).

## Doc updates

- Version bump 0.0.119 -> 0.0.120 across pyproject.toml, vera/__init__.py,
  docs/index.html, README.md (test count + release count too).
- KNOWN_ISSUES: removed #522 row (closed); rewrote #516 row to reflect
  Stage 1 done.
- ROADMAP: row 3 now '#516 (Stages 2-3)' instead of '#516 + #522 paired';
  intro updated from 'twelve open' to 'eleven remain'.
- HISTORY: added v0.0.120 row to Stage 9 table.
- CHANGELOG: [Unreleased] -> [0.0.120] - 2026-04-26 with Fixed/Improved/
  Tests/Website sections; new empty [Unreleased] block on top.
- TESTING: total counts 3534 -> 3550, file count 28 -> 29, new row for
  test_runtime_traps.py.

Co-Authored-By: Claude <noreply@anthropic.invalid>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

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: 7ef092ed-222a-4ee0-ae89-1dd79cafaa10

📥 Commits

Reviewing files that changed from the base of the PR and between 522303c and ad3eb2e.

📒 Files selected for processing (3)
  • ROADMAP.md
  • TESTING.md
  • tests/test_runtime_traps.py

📝 Walkthrough

Walkthrough

Adds Stage‑1 runtime trap diagnostics: introduces WasmTrapError and _classify_trap, preserves/replays captured stdout/stderr on trap, wires trap_kind into JSON/text CLI output, updates CLI handling, adds tests and documentation, and bumps package to v0.0.120.

Changes

Cohort / File(s) Summary
Version metadata
CHANGELOG.md, HISTORY.md, pyproject.toml, vera/__init__.py, README.md
Bump release to v0.0.120; add changelog/history entries documenting trap classification and stdout/stderr preservation; update release/test counters and compare links.
Documentation & planning
KNOWN_ISSUES.md, ROADMAP.md, TESTING.md, docs/index.html
Reflect Stage‑1 progress: rewrite known‑issues entry for #516, close #522 in docs, add testing inventory for runtime trap tests, note iOS Safari overflow fixes, and adjust roadmap priorities.
Core trap handling
vera/codegen/api.py
Add WasmTrapError(RuntimeError) with stdout, stderr, kind; implement _classify_trap(exc, last_violation); classify wasmtime traps in execute() and raise WasmTrapError carrying captured buffers and kind.
CLI error handling
vera/cli.py
Enable capture_stderr=True; store/replay captured stderr; add except WasmTrapError branch to replay buffers and emit JSON/text envelopes including trap_kind; adjust generic trap labeling.
Tests
tests/test_runtime_traps.py
New pytest module covering _classify_trap, WasmTrapError shape, stdout/stderr capture/replay, CLI cmd_run behaviour in text and JSON modes, and trap categorisation rules.

Sequence Diagram

sequenceDiagram
    participant WasmExec as WASM Executor (vera/codegen/api.py)
    participant Classifier as Trap Classifier (_classify_trap)
    participant CLI as CLI Handler (vera/cli.py)
    participant Streams as stdout/stderr

    WasmExec->>WasmExec: run WASM, buffer stdout (and stderr)
    WasmExec->>Classifier: _classify_trap(exc, last_violation)
    Classifier-->>WasmExec: (kind, message)
    WasmExec->>WasmExec: raise WasmTrapError(message, stdout, stderr, kind)
    WasmExec-->>CLI: propagate WasmTrapError
    CLI->>Streams: flush and replay captured stdout
    CLI->>Streams: replay captured stderr
    alt JSON mode
        CLI->>Streams: emit JSON envelope { ok:false, trap_kind, stdout, stderr }
    else Text mode
        CLI->>Streams: print formatted error message after replays
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels

compiler, tests, docs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarises the two primary changes: trap categorisation (WasmTrapError with stable kind taxonomy) and stdout preservation on trap, both of which are substantive throughout the PR.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bug-campaign-trap-diagnostics

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

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

❌ Patch coverage is 85.18519% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.01%. Comparing base (ee0975f) to head (ad3eb2e).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
vera/cli.py 71.42% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #533      +/-   ##
==========================================
- Coverage   91.03%   91.01%   -0.03%     
==========================================
  Files          58       58              
  Lines       21964    22014      +50     
  Branches      259      259              
==========================================
+ Hits        19995    20036      +41     
- Misses       1962     1971       +9     
  Partials        7        7              
Flag Coverage Δ
javascript 56.83% <ø> (ø)
python 94.97% <85.18%> (-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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@HISTORY.md`:
- Line 257: The new release entry v0.0.120 was added but the roll-up summary
still says "119 tagged releases"; update the summary count to reflect the new
release (change "119 tagged releases" to "120 tagged releases") and scan
HISTORY.md for any other places that mention the total number of tagged releases
to keep them consistent with the newly added v0.0.120 entry.

In `@KNOWN_ISSUES.md`:
- Line 17: The documentation incorrectly refers to the envelope field `kind`;
update the KNOWN_ISSUES.md wording to reference the actual emitted JSON key
`trap_kind` (as produced by cmd_run()) and adjust any examples or explanation
that direct downstream consumers to `kind` so they instead use `trap_kind`;
ensure the note still mentions staged fixes and v0.0.120 but points readers to
`trap_kind` used per diagnostic by cmd_run().

In `@README.md`:
- Line 184: Update the README banner text that currently reads "Vera is in
**active development** at v0.0.120 — 810+ commits, 120 releases, 3,536 tests,
96% code coverage, 80 conformance programs, 32 examples, and a 13-chapter
specification." to use the correct example count "30 examples" (i.e., change "32
examples" to "30 examples"); search for other prose occurrences of the example
count and make them consistent if present (references: the README banner line
containing "v0.0.120" and the mention of "examples").

In `@ROADMAP.md`:
- Line 39: Update the roadmap text to use the shipped JSON field name: replace
the mention of `kind` with `trap_kind` in the sentence that currently reads "the
JSON envelope carries the `kind`" so it instead reads that the JSON envelope
carries `trap_kind`; target the string `kind` in the ROADMAP.md entry for
"Runtime trap diagnostics (Stages 2–3)" and ensure the exact token `trap_kind`
is used to match the codebase.

In `@tests/test_runtime_traps.py`:
- Around line 195-211: The current test
test_json_mode_includes_stdout_in_envelope only covers IO.print/stdout and
misses the stderr-preservation contract; add a sibling regression test (e.g.,
test_json_mode_includes_stderr_in_envelope) that creates a temp file from a
program which writes to IO.stderr(...) before crashing, calls cmd_run(...,
as_json=True), parses the JSON envelope, asserts rc==1 and envelope["ok"] is
False, and verifies the envelope contains a "stderr" field with the expected
stderr lines (similar to the stdout assertions); reference cmd_run and IO.stderr
in the new test to ensure stderr is captured into the envelope.

In `@vera/cli.py`:
- Around line 640-685: The cmd_run execution path currently doesn't capture
runtime stderr so WasmTrapError handler's exc.stderr and JSON "stderr" field are
never populated; update the call site in cmd_run where execute(...) is invoked
to pass capture_stderr=True (matching how stdout is captured), then propagate
and use exec_result.stderr on the non-trap success path (i.e. when not raising
WasmTrapError) to replay or include stderr output the same way you handle
exec_result.stdout/as_json so both text and JSON modes emit the captured stderr
field and replay it to sys.stderr in text mode.
🪄 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: 1ffde53b-6bf6-423b-ba72-255e1831a29d

📥 Commits

Reviewing files that changed from the base of the PR and between ee0975f and e51f1e8.

⛔ Files ignored due to path filters (5)
  • 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/**
  • docs/sitemap.xml is excluded by !docs/**
📒 Files selected for processing (11)
  • CHANGELOG.md
  • HISTORY.md
  • KNOWN_ISSUES.md
  • README.md
  • ROADMAP.md
  • TESTING.md
  • pyproject.toml
  • tests/test_runtime_traps.py
  • vera/__init__.py
  • vera/cli.py
  • vera/codegen/api.py

Comment thread HISTORY.md
Comment thread KNOWN_ISSUES.md Outdated
Comment thread README.md
Comment thread ROADMAP.md Outdated
Comment thread tests/test_runtime_traps.py
Comment thread vera/cli.py
Five real findings from CodeRabbit, one rabbit-incorrect:

1. (real) HISTORY.md line 294: '119 tagged releases' -> 120.
2. (real) KNOWN_ISSUES line 17: clarified the JSON envelope key is
   trap_kind, distinct from WasmTrapError.kind (the Python attribute).
3. (rabbit-incorrect) README.md '32 examples' is correct (filesystem
   count via ls examples/*.vera = 32). Not changed; replied.
4. (real) ROADMAP.md line 39: same kind/trap_kind clarification as #2.
5. (real) Added test_json_mode_includes_stderr_in_envelope.
6. (real, the important one) cmd_run never passed capture_stderr=True
   to execute(), so WasmTrapError.stderr and the JSON envelope's
   stderr field were permanently empty. Wired through:

   a. cmd_run now passes capture_stderr=True (parallel to stdout's
      always-on capture)
   b. Success path replays exec_result.stderr to sys.stderr (text)
      or includes it in the envelope (JSON)
   c. Existing WasmTrapError handler now actually populates these
      fields on the trap path
   d. Preserved the original 'stdout suppresses value-printing'
      behaviour (stderr does not suppress value-printing -- it's
      independent in its own stream)

Plus lint fix: 'uv lock --check' was failing because pyproject.toml
version bumped 0.0.119 -> 0.0.120 but uv.lock still pinned 0.0.119.
Ran 'uv lock' to sync.

Test count: 3536 -> 3537 (+1 from new stderr test); doc counts
and TESTING.md row updated accordingly.

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

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ROADMAP.md`:
- Line 272: Update the release count and version marker in the ROADMAP summary
string: change "119 tagged releases (as of v0.0.119)" to "120 tagged releases
(as of v0.0.120)" so the ROADMAP summary (the sentence containing "810+ commits,
119 tagged releases (as of v0.0.119), 3,551 tests...") matches the new v0.0.120
release referenced in HISTORY.md.

In `@TESTING.md`:
- Line 9: Update the aggregate test summary in TESTING.md to reflect the actual
run: change the total from 3,551 to 2,896 and update the passed/skipped counts
to match the real test run output (recalculate passed = actual passed, skipped =
actual skipped from your test run). Ensure the summary line that currently reads
"| **Tests** | 3,551 across 29 files (~34,200 lines of test code; 3,537 passed,
14 skipped) |" is replaced with the corrected totals and that the per-file
breakdown includes test_runtime_traps.py with 17 tests; verify the numbers are
consistent (total equals sum of per-file counts and passed+failed+skipped equals
total).

In `@tests/test_runtime_traps.py`:
- Around line 195-247: The tests test_json_mode_includes_stdout_in_envelope and
test_json_mode_includes_stderr_in_envelope currently assert envelope contents
but don't assert that nothing was written to the real stderr when cmd_run(...,
as_json=True) is used; update those tests to also assert capsys.readouterr().err
is empty (or specifically does not contain human-readable error text) after
calling cmd_run to ensure cmd_run/execute is invoked with capture_stderr=True
and that JSON mode does not leak messages to real stderr; locate assertions in
these tests and add the stderr-empty check, and consider adding the same check
to the related test functions referencing cmd_run and as_json in this diff.
🪄 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: 6d28d7c6-629e-47d4-8b9f-30c7adb49b34

📥 Commits

Reviewing files that changed from the base of the PR and between e51f1e8 and 835dc68.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock, !uv.lock
📒 Files selected for processing (7)
  • CHANGELOG.md
  • HISTORY.md
  • KNOWN_ISSUES.md
  • ROADMAP.md
  • TESTING.md
  • tests/test_runtime_traps.py
  • vera/cli.py

Comment thread ROADMAP.md Outdated
Comment thread TESTING.md Outdated
Comment thread tests/test_runtime_traps.py
…nvariant

Two real findings, one rabbit-incorrect:

1. (real) ROADMAP line 272: '119 tagged releases (as of v0.0.119)'
   was missed in the version bump for the v0.0.120 release. Updated
   to '120 tagged releases (as of v0.0.120)'.

2. (rabbit-incorrect) TESTING.md '3,551 tests' is correct. The
   rabbit suggested 2,896 which appears hallucinated — actual
   pytest collection is 3,551, and check_doc_counts.py enforces
   that exact number. No change; replied with verification.

3. (real) Added JSON-mode 'no stderr leak' invariant assertions to
   all four JSON-emitting tests in test_runtime_traps.py. The
   assertion captured.err == '' pins that JSON mode keeps all
   error reporting INSIDE the envelope — writing to actual stderr
   would split machine-readable output across two streams and
   break parsing for downstream consumers (LSP, agents). Same
   assertion added to:
   - test_json_mode_includes_stdout_in_envelope
   - test_json_mode_includes_stderr_in_envelope (new in last round)
   - test_json_mode_includes_trap_kind
   - test_json_contract_violation_kind

Test count unchanged at 17 (assertions added inline); line count
319 -> 345 in TESTING.md table.

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

@coderabbitai coderabbitai Bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@tests/test_runtime_traps.py`:
- Around line 175-193: Update the
test_text_mode_prints_buffered_stdout_before_error test to verify cross-stream
ordering by capturing stdout and stderr into the same buffer: add imports for io
and redirect_stdout/redirect_stderr, create a single io.StringIO, run
cmd_run(str(path)) while redirecting both stdout and stderr into that buffer,
then assert that the "line 1...line 4" messages appear in order and that "Error"
appears after them in the combined buffer; keep existing separate capsys
assertions optional but rely on the merged-buffer check for the ordering
guarantee.
🪄 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: 35564a33-2674-4b18-a711-c9a53d745891

📥 Commits

Reviewing files that changed from the base of the PR and between 835dc68 and 522303c.

📒 Files selected for processing (3)
  • ROADMAP.md
  • TESTING.md
  • tests/test_runtime_traps.py

Comment thread tests/test_runtime_traps.py
Real finding: existing test_text_mode_prints_buffered_stdout_before_error
asserts per-stream content (capsys gives stdout/stderr separately) but
doesn't pin the ORDER of writes across the two streams. Added sibling
test_text_mode_cross_stream_ordering using contextlib.redirect_stdout +
redirect_stderr aimed at one io.StringIO. Asserts:

  - all four 'line N before crash' messages appear in order, AND
  - the 'Error' message appears AFTER the last print line

Honest caveat in the docstring: this test does NOT exercise the OS-level
buffering concern that sys.stdout.flush() defends against. With both
streams aimed at one StringIO the flush is a no-op (StringIO has no
OS-level buffer). What it DOES catch: a refactor that swaps the
stdout-replay and error-print blocks in cmd_run's WasmTrapError handler.

Added as a SIBLING test rather than mutating the existing one because
they cover distinct properties:
  - existing: per-stream content (stdout has prints, stderr has error)
  - new:      cross-stream code order

Different regressions catch different bugs; both worth pinning.

Test count: 17 -> 18; doc counts updated.

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan aallan merged commit 279c844 into main Apr 27, 2026
20 checks passed
@aallan aallan deleted the bug-campaign-trap-diagnostics branch April 27, 2026 10:02
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.

IO.print output lost when program traps (stdout fully buffered)

1 participant