Release v0.0.157#690
Conversation
`IO.read_char` effect operation for single-character input (#618 terminal half). Browser half awaits JSPI from #609. Bump version across 6 files: vera/__init__.py, pyproject.toml, uv.lock, README.md, docs/index.html. CHANGELOG.md and HISTORY.md updated for the release entry; site assets regenerated. Closing the loop on #618: this PR was a four-CodeRabbit-round + pr-review-toolkit-multi-agent-review journey. Final shape: - Unix TTY uses termios cbreak mode (`tty.setcbreak()`) which preserves ISIG so Ctrl-C still raises SIGINT (not the raw mode I initially used). - Windows TTY uses `msvcrt.getwch()`. - Non-TTY (piped/redirected stdin) shared across platforms via `sys.stdin.read(1)` for identical encoding behaviour. - KeyboardInterrupt at every blocking call raises `_VeraExit(130)` (mirrors `host_sleep`'s #589-class WasmTrapError avoidance). - Termios restore failure captured separately so it doesn't mask the read error. - Ctrl-D in cbreak mode maps to `Err("EOF")` (since ICANON is off in cbreak); piped `\x04` stays a literal byte (since a pipe is a byte stream). - Browser stub returns clear `Result.Err` pointing at #609 + #618; wiring is in place so when JSPI lands, only the hostReadChar body needs replacing. Co-Authored-By: Claude <noreply@anthropic.invalid>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR releases v0.0.157 by coordinating version updates across package metadata (pyproject.toml, vera.init.py), release documentation (CHANGELOG.md, HISTORY.md), and project status (README.md). The Stage 12 entry documents the new Changesv0.0.157 Release Coordination
Sequence Diagram(s)Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #690 +/- ##
=======================================
Coverage 90.88% 90.88%
=======================================
Files 60 60
Lines 23529 23529
Branches 259 259
=======================================
Hits 21384 21384
Misses 2138 2138
Partials 7 7
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 304: Update the HISTORY.md entry for the IO.read_char effect to remove
the claim of "explicit UTF-8 encoding" for the non-TTY path and replace it with
wording that matches the implementation: state that the non‑TTY fallback reads a
single byte/character using sys.stdin.read(1) (single-character read behavior)
rather than performing an explicit re-encoding; reference the IO.read_char
effect operation and the non‑TTY/pipe path in the same sentence so the release
note matches the runtime contract.
In `@README.md`:
- Line 186: Replace every stale in-file occurrence of the old example count so
the README is consistent: update the string "35 examples" (currently at the
first project-summary sentence) and the string "34 example Vera programs" (in
the project tree section) to the new total (use the same numeric value in both
places) — search for those exact phrases in README.md and replace both
occurrences with the updated example count.
🪄 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: 4680da4c-1c27-46d1-8ac6-cf4a24d30ddf
⛔ Files ignored due to path filters (5)
docs/index.htmlis excluded by!docs/**docs/index.mdis excluded by!docs/**docs/llms-full.txtis excluded by!docs/**docs/llms.txtis excluded by!docs/**uv.lockis excluded by!**/*.lock,!uv.lock
📒 Files selected for processing (5)
CHANGELOG.mdHISTORY.mdREADME.mdpyproject.tomlvera/__init__.py
Two minor doc accuracy fixes: 1. HISTORY.md L304 — the v0.0.157 release row claimed the non-TTY pipe path uses "explicit UTF-8 encoding", but the implementation just calls `sys.stdin.read(1)` with whatever encoding stdin already has (no explicit re-encoding step). The `encoding="utf-8"` is on the test subprocess calls, not the production code path. Replaced with "reading one character via `sys.stdin.read(1)`" which accurately describes the runtime contract. 2. README.md L230 — project-tree comment still said "34 example Vera programs" while L186 was already updated to 35. Brought the two references into agreement. Co-Authored-By: Claude <noreply@anthropic.invalid>
Summary
Release v0.0.157 — ships the terminal half of
IO.read_char(#618).Unblocks real-time CLI programs (paced REPLs, terminal games) that couldn't be written before because
IO.read_lineis line-buffered. Browser half awaits JSPI suspend/resume from #609; same primitiveIO.sleepwill use.What's in this release
Added
IO.read_chareffect operation:op read_char(Unit -> @Result<String, String>). Returns one Unicode character from stdin, orErr("EOF")when the stream closes (Ctrl-D on a Unix TTY also maps to EOF).tty.setcbreak(). cbreak preserves ISIG so Ctrl-C still raises SIGINT (unlike raw mode which would suppress it). Ctrl-D mapped to EOF since ICANON is off in cbreak.msvcrt.getwch()for raw single-key reads.sys.stdin.read(1)shared across platforms — identical encoding behaviour, nomsvcrt.getwch()on redirected stdin.Result.Errpointing at #609 + #618; wiring is in place so when JSPI lands only thehostReadCharbody needs replacing.IO-effect-extension pattern asIO.sleep/IO.time/IO.stderr(#463): a single new op on the existing effect, not a new<Terminal>effect.Tests
tests/conformance/ch07_io_read_char.vera(verify-level — pins the type signature and effect-row wiring).tests/test_cli.py::TestIOOperationscovering the piped-input path: happy path, EOF, UTF-8 round-trip.tests/test_codegen.py::TestIOOperationscovering thestdin_buffixture path: single read, empty-buf EOF, sequential cursor advance, read-then-EOF, UTF-8, and the intentional non-TTY\x04-stays-literal asymmetry.Documentation
spec/07-effects.md— addedread_charrow to the IO operations table; bumped operation count "ten → eleven".spec/12-runtime.md— addedvera.read_charimport row and browser-runtime IO behaviour table entry.SKILL.md— addedIO.read_charrow; bumped operation count in two places; updated browser-runtime summary.examples/read_char.vera— new example demonstrating the read-one-char pattern with full failure-mode handling.CHANGELOG.md— comprehensive[0.0.157]section detailing the implementation journey.Review trail — for posterity
This was a four-CodeRabbit-round + internal multi-agent review journey on PR #689. Each layer caught material things the others missed.
217845a)encoding="utf-8"onsubprocess.run, initial try/except wrapping for system errors9983b2c)msvcrt.getwch()even for piped stdin)e6d549e)host_sleepalready had this fix; the missingexcept KeyboardInterruptinhost_read_charwas a real bug AND my "same stance as host_sleep" comment was factually wrong); termios restore masking the read error; tcgetattr error reporting the wrong message; redundant localimport os; stale conformance-test cross-reference (test_codegen.py→test_cli.py); zero coverage of thestdin_buffixture path (added 5 new tests).2bc2cb6)tty.setraw()clears ISIG (the previous round'sexcept KeyboardInterruptclause was actually unreachable in TTY mode — Ctrl-C arrived as\x03byte instead of raising); restore_exc was being swallowed instead of surfaced when reads succeededtry/except: passpattern (coincidentally fixed by the round-3restore_exccapture, demonstrating defense-in-depth)9e4a903)\x04) in cbreak mode needs to map toErr("EOF")since ICANON is off and Ctrl-D arrives as a literal byte; CHANGELOG had stale "raw-mode" wording surviving from before the round-3 setcbreak switchThe headline win:
setraw→setcbreakwas a latent correctness bug that would have shipped to users. Three rounds of review couldn't have caught it without all three: my agents reasoned about WHY theexcept KeyboardInterruptwas needed, but CodeRabbit pattern-matched on "setraw + KeyboardInterrupt" as a known incompatibility, and the lint caught the residual swallow.Validation
pytest tests/— 3,806 passed, 15 skipped, 16 stress-deselected (+99 browser tests)mypy vera/cleanruff check --select S vera/clean (the previously-failing S110 rule passes after therestore_exccapture)python scripts/check_conformance.py— 87/87python scripts/check_examples.py— 35/35 (check + verify)python scripts/check_doc_counts.py— consistent (3,936 tests, 32 files, 87 conformance, 35 examples)python scripts/check_version_sync.py— v0.0.157 across 6 filespython scripts/check_limitations_sync.py— consistent (28/17/4)python scripts/check_site_assets.py— up-to-dateecho "X" | vera run examples/read_char.vera→You pressed: X9e4a903)Post-merge
Standard release-tag workflow once merged: pull main, tag
v0.0.157on the merge commit, push tag,gh release create v0.0.157with the extracted CHANGELOG section.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Chores