Small docs sweep: #557 + #561 + #560 + #607 + #608 + #512#650
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughDocumentation-only sweep: mark ADT ChangesMatch-Arm Slot-Stack Semantics and Contract Verification Status
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related issues
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 #650 +/- ##
=======================================
Coverage 90.95% 90.95%
=======================================
Files 59 59
Lines 23197 23197
Branches 259 259
=======================================
Hits 21098 21098
Misses 2092 2092
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:
|
Three small spec corrections that surfaced during today's bug burn-down audit: - **#557** — `spec/03-slot-references.md` Example 9 (line 292) previously said the match-arm pattern binding "shadows the function parameter". "Shadow" left undefined; two readings were equally consistent with the prose (replace vs push-on-top). The compiler implements push-on-top — the function parameter remains accessible at `@T.1` (`@T.2`, etc.) — which matches `let`'s rule but isn't derivable from the docs. Replaced the one-liner with an explicit paragraph spelling out the push-on-binding semantics, the resulting De Bruijn ordering for multi-field constructors (leftmost = deepest = highest index, rightmost = shallowest), and the non-commutative-operations caveat that exposes the rule. - **#561** — `spec/06-contracts.md` had two tier-accuracy bugs: - §6.3.1 (Tier 1 list) was missing "calls to pure functions that have their own contracts", and §6.3.2 (Tier 2 NYI list) incorrectly included it. Pure-fn calls in `ensures` already verify at Tier 1 in v0.0.143 — the verifier inlines the callee's contract at the call site. Same for `@T.result` and `if/then/else` in contracts, which similarly already work at Tier 1. Moved all three from §6.3.2 to §6.3.1. - §6.3.3 said "Bounded quantification is decidable for finite bounds and is handled by Z3 via finite unrolling". That reads as "Tier 1 decidable", but Tier 2 (the Z3-guided tier that would handle it) is [#427](NYI). In practice every `forall`/`exists` in a contract falls to Tier 3 today. Clarified the prose to make this explicit, both for `forall` and `exists`. - **#560** — the `invariant(...)` clause on `data` declarations is documented in `spec/02-types.md` §2.4.1, `spec/06-contracts.md` §6.2.3, and `SKILL.md`, but every documented form fails with `[E130] no <DataName> bindings in scope` at v0.0.143 (and at v0.0.127 when the issue was filed). Added inline NYI markers at all three sites pointing at #560, with the working alternative (refinement types). Added the limitation to spec/06-contracts.md's §6.9 Limitations table. Allowlist line-number shifts auto-fixed via `scripts/fix_allowlists.py --fix`, with one manual correction to a duplicate-key collision the auto-fix introduced in `scripts/check_skill_examples.py` (the known footgun: when the fixer undercounts a multi-line edit, two adjacent entries can collapse onto the same dict key — Python silently drops the first). Closes #557. Closes #561. Closes #560. Co-Authored-By: Claude <noreply@anthropic.invalid>
4fd7527 to
38160dc
Compare
PR #650's lint check (`check_changelog_updated.py`) was failing because the original three-spec-fix commit didn't have a `[Unreleased]` CHANGELOG entry — fixed here, and the scope is widened to bundle three more aging small-docs issues that share the same shape. Six closures now in one PR: - **#557** (already in this PR): match-arm slot semantics "shadow" → "push-on-binding" in `spec/03-slot-references.md` Example 9. - **#561** (already in this PR): Tier 1 vs Tier 2 vs Tier 3 accuracy in `spec/06-contracts.md` (pure-fn calls in ensures actually verify at Tier 1; quantifiers actually fall to Tier 3). - **#560** (already in this PR): `invariant(...)` NYI markers in `spec/02 §2.4.1`, `spec/06 §6.2.3`, and `SKILL.md`. New in this commit: - **#607**: new `spec/02-types.md` §2.2.1 "`Int` and `Nat` compatibility" subsection covering the bidirectional subtyping (`Nat <: Int` always; `Int <: Nat` permitted with verifier-discharged obligation). Plus a cross-reference paragraph in `SKILL.md`'s "Primitive types" listing telling agents not to insert `nat_to_int` defensively. - **#608**: new `SKILL.md` "IO model: terminal vs browser" subsection under the Browser compilation section, explaining that programs using `IO.sleep` + ANSI escapes for terminal pacing/rendering compile cleanly to `--target browser` but render escapes as literal text and busy-wait the main thread. Recommended pattern: "Vera pure simulation core + JS driver via `requestAnimationFrame`". `README.md`'s "write once, run anywhere" line qualified to acknowledge the IO seam. - **#512**: all 31 Stage 11 rows in `HISTORY.md` (v0.0.112 → v0.0.138) trimmed to the canonical `**X** ([#N]).` template now embedded in long-term memory. Detailed mechanism descriptions for each version stay in CHANGELOG under their respective `## [0.0.X]` section. CHANGELOG: new `[Unreleased] / ### Documentation` section covering all six closures with the rationale per fix. Allowlist drift fixed via `scripts/fix_allowlists.py --fix` plus four manual corrections for the known duplicate-key footgun (`feedback_spec_allowlist.md`) — `scripts/check_skill_examples.py` had four collapsed-key collisions after the auto-fix; lines 435 (Tuple), 1099 (HTML constructor match), 2092 (import aliasing), 2097 (import syntax) restored to their correct positions, plus line 1218 (Requires clause fragment) corrected from stale 1202. All consistency checks green: - `python scripts/check_doc_counts.py` - `python scripts/check_spec_examples.py` - `python scripts/check_skill_examples.py` - `python scripts/check_limitations_sync.py` - `python scripts/check_readme_examples.py` Closes #557. Closes #560. Closes #561. Closes #607. Closes #608. Closes #512. Co-Authored-By: Claude <noreply@anthropic.invalid>
The lead sentence of the new `Int` and `Nat` compatibility subsection used the word "implicitly", which set the wrong frame for Vera's design principles. "Implicit" suggests "silent and unchecked"; the Int→Nat flow is actually "syntactically silent, semantically verified" — the verifier emits a proof obligation and Z3 discharges it (or it falls to a runtime check). Reworded the lead to make the verifier's mediating role explicit: Vera's type checker accepts both flows without an explicit cast — but the narrowing direction (Int <: Nat) is not unchecked: the type checker emits a verification obligation that the contract verifier discharges via Z3, so the flow is syntactically silent but semantically verified. This matches Vera's "verification is a first-class citizen" design point: subtyping that can be proved doesn't need to be spelled out at every call site. Also changed "The conversion is implicit and either statically verified or guarded at runtime" to "The conversion is syntactically silent and either statically verified or guarded at runtime" for the same reason. Bullets and rest of subsection unchanged — they were already accurate (explicitly named "verifier-discharged" and "Tier 1"/"Tier 3" mechanics). Co-Authored-By: Claude <noreply@anthropic.invalid>
There was a problem hiding this comment.
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 `@README.md`:
- Line 149: The sentence asserting "Mandatory parity tests ensure identical
behaviour between the command-line and browser runtimes for all language
constructs" is too strong given documented runtime differences; update the
README sentence that follows the `vera compile --target browser` description to
state that mandatory parity tests ensure identical behaviour only for
tested/supported language constructs/features (not all constructs), and
explicitly call out that I/O and runtime-specific behaviours such as `IO.sleep`
and ANSI escape handling are exceptions; keep the reference to SKILL.md §Browser
compilation (`SKILL.md#browser-compilation`) and preserve the explanation that
the browser target expects Vera as a simulation core with JavaScript driving
timing/rendering.
🪄 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: 6c23181e-1497-47a3-b801-c588d0d7f31e
⛔ Files ignored due to path filters (2)
docs/SKILL.mdis excluded by!docs/**docs/llms-full.txtis excluded by!docs/**
📒 Files selected for processing (9)
CHANGELOG.mdHISTORY.mdREADME.mdSKILL.mdscripts/check_skill_examples.pyscripts/check_spec_examples.pyspec/02-types.mdspec/03-slot-references.mdspec/06-contracts.md
The reword for #608 strengthened the parity claim to "for all language constructs" — which is immediately contradicted by the next sentence describing the IO seam. CodeRabbit-flagged. Tightened to "for the pure-language surface (arithmetic, ADTs, pattern matching, closures, contracts, effects-as-host-imports, etc.)" — accurate and naturally segues into the IO-exception paragraph that follows. Also reframed "The IO surface differs between targets" to "The IO surface is the documented exception" so the structural relationship between the two sentences is explicit rather than implied. Co-Authored-By: Claude <noreply@anthropic.invalid>
There was a problem hiding this comment.
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 `@spec/02-types.md`:
- Around line 28-37: Update the implementation note that currently references
"Section 2.1" to instead reference "Section 2.2.1" where the `Nat <: Int`
compatibility rules are documented; locate the text mentioning the `Nat <: Int`
relationship (the implementation note around the `Nat <: Int` phrase) and
replace the section pointer so it reads "Section 2.2.1".
🪄 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: bbd464e7-fa3f-409e-bc35-c7eb616b463d
📒 Files selected for processing (1)
spec/02-types.md
The implementation note on `Int <: Nat` referenced "Section 2.1" as the home of the `Nat <: Int` rule. When the #607 work created the new §2.2.1 "`Int` and `Nat` compatibility" subsection, the pointer became stale — §2.1 is just the high-level Overview, while the formal subtyping rules now live in §2.2.1. Updated the pointer to §2.2.1. (CodeRabbit said "around line 28-37" in the finding text; the actual reference is at line 277. Verified by grep — no other "Section 2.1" pointers exist in the file that mention the Int/Nat relationship.) Co-Authored-By: Claude <noreply@anthropic.invalid>
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 `@spec/02-types.md`:
- Around line 136-137: Update the paragraph that currently asserts invariants
are "checked at every construction site" to explicitly mark that behavior as
future or not currently enforced; reference the `invariant(...)` clause on
`data` declarations and state that enforcement at construction sites is intended
but not implemented in the reference compiler (tracked in issue `#560`), or
prepend "In future" / "Not yet enforced" to that sentence so the subsection is
factually consistent with the "Not yet implemented" status and with Section 2.6
(refinement types) guidance.
- Around line 30-37: The spec claims both Nat <: Int and verifier-backed Int <:
Nat in §2.2.1 but §2.8's formal numeric-subtyping relation omits Int <: Nat;
reconcile by either (A) adding the verifier-backed Int <: Nat rule into the
formal relation in §2.8 with a note that it is conditional and discharged by the
verifier (e.g., "Int <: Nat when the verifier can prove value >= 0; otherwise
runtime check"), or (B) explicitly mark the §2.2.1 narrowing as an
implementation-only concession (not part of the formal relation) and add
cross-reference text in §2.8 explaining the exception; update the wording for
"Int <: Nat" and the formal relation to mention the verifier/runtime-check
semantics and ensure the same phrasing appears in both §2.2.1 and §2.8 to keep
the normative rules consistent.
🪄 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: 6b07bd83-e356-4229-86ed-10da29bfe602
📒 Files selected for processing (2)
README.mdspec/02-types.md
… tier Filed during PR #650's review pass — an audit of the spec found ~10 sites where the documented language behaviour contradicts the spec's own foundational principles in §0.2 (Explicitness) and §0.3 (no shorthand / no implicit conversions / no default arguments). Examples: the implicit prelude (§9.1.2), `effects(pure)` default on function types (§2.5), multiple `requires` clauses being equivalent to a single `requires` with && (§5.4), `@Fn<A,B>.0` shorthand (§3.7), ability auto-derivation, implicit `resume` binding inside handler arms, IO operations available without a user-side `effect IO` block, optional `module` statement. Recommendation in the issue body: Option 1 — strengthen §0.3 to enumerate the deliberate implicit surfaces as exceptions (one PR, honest framing, no behaviour change), then file individual triage PRs for items where the implicitness is unfixed legacy rather than load-bearing design. Stabilisation-tier rather than enhancement because LLMs reading the spec take §0.2.2 literally — internal inconsistency is a real confusion source, not cosmetic. Co-Authored-By: Claude <noreply@anthropic.invalid>
There was a problem hiding this comment.
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 `@ROADMAP.md`:
- Line 22: The Agent-integration tier rows in ROADMAP.md currently reuse Order 8
which conflicts with the new Stabilisation row; update the Agent-integration
tier's Order column values so they are sequentially numbered 9, 10, and 11
(i.e., change each "Order 8" entry under the "Agent-integration" tier to 9–11
respectively) to restore unique global ordering and preserve the intended
"resumes once stabilisation is done" sequence.
🪄 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: b734880c-e1fe-457c-99fb-ce4ad2bb7696
📒 Files selected for processing (1)
ROADMAP.md
…invariant claim (CodeRabbit valid)
Two findings, both valid:
**Finding 1 — §2.4.1 line 149 contradicts the NYI block above it.**
The line "The invariant is checked by the contract verifier at
every construction site." is in present tense and asserts as fact
something that's directly contradicted by the "Status: Not yet
implemented" callout earlier in the same subsection. Reworded to
future tense ("When implemented, the invariant will be checked...")
and made the present-day fact explicit ("At present...no checking
occurs and refinement types (§2.6) are the working alternative").
**Finding 2 — §2.2.1 calls Int↔Nat "subtypes of each other" but
§2.8's formal subtyping relation only includes Nat <: Int.**
§2.8 already documents Int <: Nat correctly as an
"Implementation note" sitting alongside (not inside) the formal
relation rules 1–5, which explicitly say "no other subtyping" at
rule 5. But §2.2.1 was phrased as if Int <: Nat is a peer
subtyping rule, creating cross-section inconsistency.
Reworded §2.2.1 to mirror §2.8's framing exactly:
- `Nat <: Int` is a **formal subtyping rule** — it follows from
refinement subtyping (§2.6.2, §2.8 rule 3). No proof obligation,
no runtime check.
- `Int -> Nat` is **not a formal subtyping rule** (explicitly
excluded by §2.8 rule 5). Instead it's a **verifier-mediated
relaxation**: type checker permits the flow + emits a
verification obligation + Tier 1 verifier discharges via Z3 (or
falls to Tier 3 runtime check).
Added cross-references in both directions (§2.2.1 → §2.8 rule 3
and §2.8 rule 5; §2.8's implementation note already references
§2.2.1 from a previous commit on this PR). Added an explicit
note tying the distinction to §0.2.2 ("no implicit behaviour"):
the formal subtyping rule is a logical consequence of refinement
subtyping (not implicit), and the verifier-mediated relaxation is
syntactically silent but semantically verified (the verifier is
the explicit check, not the syntax).
Co-Authored-By: Claude <noreply@anthropic.invalid>
Summary
Small docs sweep — six aging documentation issues closed in one PR. No code changes; touches
spec/02-types.md,spec/03-slot-references.md,spec/06-contracts.md,SKILL.md,README.md, andHISTORY.md.Closes #557 — match-arm slot semantics
spec/03-slot-references.mdExample 9 said the match-arm pattern binding "shadows the function parameter" without defining "shadow". Two readings were equally consistent with the prose (replace vs push-on-top); the compiler implements push-on-top. Replaced the one-liner with an explicit paragraph spelling out push-on-binding semantics, the resulting De Bruijn ordering for multi-field constructors, and the non-commutative-operations caveat that exposes the rule.Closes #561 — Tier 1 vs Tier 2 vs Tier 3 accuracy
Two tier-accuracy bugs in
spec/06-contracts.md:ensures/@T.result/if/then/elsewere listed under Tier 2 NYI but actually verify at Tier 1 today. Moved all three from §6.3.2 to §6.3.1.forall/existsfalls to Tier 3 today.Closes #560 —
invariant(...)NYI markersThe
invariant(...)clause ondatadeclarations is documented inspec/02 §2.4.1,spec/06 §6.2.3, andSKILL.md, but every documented form fails with[E130] no <DataName> bindings in scopeat v0.0.144. Added inline NYI markers at all three sites pointing at #560, with the working alternative (refinement types). Added the limitation tospec/06's §6.9 Limitations table.Closes #607 —
Int↔NatsubtypingAdded a new
spec/02-types.md§2.2.1 "IntandNatcompatibility" subsection covering the bidirectional subtyping (Nat <: Intalways;Int <: Natpermitted with verifier-discharged obligation). Practical-implication note tells agents not to insertnat_to_intdefensively when callingarray_lengthetc. into@Natpositions. Cross-reference added toSKILL.md's "Primitive types" listing.Closes #608 — Terminal-vs-browser IO seam
Added
SKILL.md"IO model: terminal vs browser" subsection under §Browser compilation. Programs usingIO.sleepfor animation pacing + ANSI escapes for cursor control compile cleanly to--target browserbut render escapes as literal text and busy-wait the main thread. Recommended browser pattern documented: "Vera pure simulation core + JS driver viarequestAnimationFrame". Two runtime gaps tracked separately (#609 JSPI sleep, #610 ANSI subset interpreter).README.md's "write once, run anywhere" line qualified to acknowledge the IO seam.Closes #512 — Stage 11 HISTORY trim
All 31 Stage 11 rows in
HISTORY.md(v0.0.112 → v0.0.138) trimmed to match the early-stage one-sentence format established in Stage 1–8. Per the canonical template now in long-term memory:**X** ([#N]).per row, no em-dash separator, no secondary clauses, no implementation detail. Detailed mechanism descriptions for each version stay in CHANGELOG under their respective## [0.0.X]section.Out-of-scope sweep finding
While verifying spec-doc state for #561/#557/#560, also discovered #226 (Typed Holes) was listed in
spec/00-introduction.md"Future Features" table despite being closed 2026-03-30 (six weeks stale). Fixed in the v0.0.144 release PR #651 (already merged); flagged here for traceability and as the motivating example for thecheck_limitations_sync.py --check-statesworkflow that should be run before each release.Validation
python scripts/check_doc_counts.py—Documentation counts are consistent (3803 tests, 29 files, 86 conformance, 34 examples, 25 hooks, 7 CI jobs).python scripts/check_spec_examples.py—All parseable spec code blocks pass (parse + check + verify).python scripts/check_skill_examples.py—All SKILL.md Vera code blocks parse successfully.(61 allowlisted, 58 parseable, 0 failed)python scripts/check_limitations_sync.py—Limitation tracking is consistent (34 in KNOWN_ISSUES.md, 18 in vera/README.md, 4 across spec chapters).python scripts/check_readme_examples.py—All README Vera code blocks parse successfully.Allowlist drift fixed via
scripts/fix_allowlists.py --fixplus four manual corrections for the duplicate-key footgun inscripts/check_skill_examples.py(the known fix_allowlists.py issue — see feedback_spec_allowlist.md note).Closes #557.
Closes #560.
Closes #561.
Closes #607.
Closes #608.
Closes #512.
🤖 Generated with Claude Code
Summary by CodeRabbit