Add HtmlNode standard library type (#311)#363
Conversation
HtmlNode ADT: HtmlElement(String, Map<String, String>, Array<HtmlNode>), HtmlText(String), HtmlComment(String). Four host imports (html_parse, html_to_string, html_query, html_text) plus one prelude function (html_attr). Lenient parsing via Python html.parser, CSS selector subset for queries. Browser runtime uses DOMParser. New conformance test ch09_html (63 programs). New example html.vera. 19 new unit tests (10 checker + 9 codegen). Version bump to v0.0.100. Co-Authored-By: Claude <noreply@anthropic.invalid>
|
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:
📝 WalkthroughWalkthroughAdds a new HtmlNode ADT and five html_* built-ins (parse, to_string, query, text, attr); wires prelude injection, environment registration, type/wasm inference, codegen host imports, WASM marshalling, browser runtime host implementations, tests, manifests, docs and release metadata for v0.0.100. Changes
Sequence Diagram(s)sequenceDiagram
participant Code as Vera code
participant Wasm as WASM module
participant Host as Browser / JS host
participant Heap as WASM heap / Map store
Code->>Wasm: call html_parse(ptr,len)
Wasm->>Host: import "vera.html_parse"(ptr,len)
Host->>Host: DOMParser.parseFromString (lenient)
Host->>Host: build JS HtmlNode ADT
Host->>Heap: writeHtml(node) -> handle_ptr (alloc strings/attrs/children)
Host-->>Wasm: return Ok(handle_ptr) / Err(err_ptr)
Code->>Wasm: call html_query(handle, sel_ptr)
Wasm->>Host: import "vera.html_query"(handle, sel_ptr)
Host->>Host: perform selector match (limited CSS subset)
Host->>Heap: writeHtml for each match -> array_ptr,len
Host-->>Wasm: return (array_ptr, count)
Code->>Wasm: call html_text(handle)
Wasm->>Host: import "vera.html_text"(handle)
Host->>Host: recursively extract text
Host->>Heap: alloc string -> ptr,len
Host-->>Wasm: return (ptr, len)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 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 docstrings
🧪 Generate unit tests (beta)
Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #363 +/- ##
==========================================
- Coverage 91.22% 90.32% -0.90%
==========================================
Files 48 49 +1
Lines 18429 18999 +570
Branches 215 219 +4
==========================================
+ Hits 16811 17161 +350
- Misses 1614 1834 +220
Partials 4 4
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: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/test_verifier.py (1)
1590-1603: 🧹 Nitpick | 🔵 TrivialUpdate the stale docstring to reflect the new expected counts.
The docstring on Line 1591 states "145 T1 / 15 T3 without module resolution", but the assertions now expect 167 T1 / 20 T3 / 187 total. This discrepancy will mislead future reviewers.
📝 Suggested docstring update
def test_overall_tier_counts(self) -> None: - """All examples together: 145 T1 / 15 T3 without module resolution.""" + """All examples together: 167 T1 / 20 T3 without module resolution.""" t1 = t3 = total = 0🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_verifier.py` around lines 1590 - 1603, Update the docstring on test_overall_tier_counts to match the current expected totals: change "145 T1 / 15 T3 without module resolution." to reflect "167 T1 / 20 T3 / 187 total" (or equivalent wording); locate the test by the function name test_overall_tier_counts and its usage of EXAMPLES_DIR, parse_to_ast, typecheck, verify and ensure the new docstring matches the assertions for t1, t3, and total.
🤖 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_checker.py`:
- Around line 2155-2193: Add negative type tests for the HTML built-ins: update
the existing test methods (test_html_query, test_html_text_fn, test_html_attr)
to include _check_err cases that pass wrong argument types. For html_query add
one case where the first arg is not a HtmlNode (e.g. 42) and one where the
selector is not a String (e.g. 42) using _check_err(..., "type"); for html_text
add a case where the arg is not a HtmlNode (e.g. "not a node") using
_check_err(..., "type"); for html_attr add a case where the node arg is wrong
and a case where the attribute name arg is not a String (e.g. 42) using
_check_err(..., "type"). Ensure each new test mirrors the existing test
structure and uses the same return types (Array<HtmlNode>, String,
Option<String>) in the checked snippet.
In `@tests/test_codegen.py`:
- Around line 9171-9196: Expand WAT import-gating tests to cover each HTML
builtin individually: add per-operation assertions like in
test_html_parse_wat_import for html_to_string, html_query, and html_text (e.g.,
new tests similar to test_html_parse_wat_import that compile a tiny program
calling each builtin and assert the corresponding string appears in result.wat)
and extend test_html_no_imports_when_unused to verify each of '"html_parse"',
'"html_to_string"', '"html_query"', and '"html_text"' are absent when not used;
follow the existing JSON/Http per-op test patterns and reuse the _compile_ok
flow and assertion style from test_html_parse_wat_import to ensure sibling
absence checks are included.
- Around line 9105-9118: The current test_html_query_by_tag only exercises tag
selectors ("p"); extend this test (or add sibling tests) to cover class
selectors (e.g., elements with class="..."), ID selectors (e.g., "#id"),
attribute-presence selectors (e.g., "[attr]"), and descendant selectors (e.g.,
"div p") by parsing HTML with representative nodes via html_parse and asserting
html_query returns expected counts for each selector; update assertions to
include calls to html_query(`@HtmlNode.0`, "<selector>") for each selector type
and match the Ok/Err pattern used in the existing test so failures surface for
html_query, html_parse, and HtmlNode handling.
In `@vera/browser/runtime.mjs`:
- Around line 1775-1783: The htmlToString serializer builds attrStr from
node.attrs without escaping special characters, so attribute values containing &
or " (and other special chars) can break output; update htmlToString to escape
attribute values before concatenation (e.g., implement a small helper like
escapeAttr and call it when iterating node.attrs to replace & with &, " with
", < with < and > with >), then use the escaped value when appending
to attrStr (refer to htmlToString, attrStr and node.attrs to locate the change).
In `@vera/codegen/api.py`:
- Around line 1676-1697: The serializer _html_to_string_py must HTML-escape node
text, attribute values and comment content before emitting strings: in the
"text" branch escape &, <, >; when building attr_str escape &, <, > and
double-quote characters in attribute values; in the "comment" branch ensure the
content does not contain the sequence "-->" (or replace/encode it) before
wrapping in <!-- -->; implement these escapes where _html_to_string_py reads
node.get("content", "") and where it iterates attrs.items() so round-trip
serialisation produces valid HTML.
---
Outside diff comments:
In `@tests/test_verifier.py`:
- Around line 1590-1603: Update the docstring on test_overall_tier_counts to
match the current expected totals: change "145 T1 / 15 T3 without module
resolution." to reflect "167 T1 / 20 T3 / 187 total" (or equivalent wording);
locate the test by the function name test_overall_tier_counts and its usage of
EXAMPLES_DIR, parse_to_ast, typecheck, verify and ensure the new docstring
matches the assertions for t1, t3, and total.
🪄 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: 3eaa0faf-3cf1-4f5a-b4ea-798586043976
⛔ Files ignored due to path filters (7)
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/**docs/sitemap.xmlis excluded by!docs/**examples/html.verais excluded by!**/*.veratests/conformance/ch09_html.verais excluded by!**/*.vera
📒 Files selected for processing (31)
CHANGELOG.mdCLAUDE.mdREADME.mdROADMAP.mdSKILL.mdTESTING.mdpyproject.tomlscripts/check_readme_examples.pyscripts/check_skill_examples.pyscripts/check_spec_examples.pyspec/09-standard-library.mdtests/conformance/manifest.jsontests/test_checker.pytests/test_codegen.pytests/test_readme.pytests/test_verifier.pyvera/__init__.pyvera/browser/runtime.mjsvera/codegen/api.pyvera/codegen/assembly.pyvera/codegen/compilability.pyvera/codegen/core.pyvera/codegen/functions.pyvera/codegen/modules.pyvera/codegen/monomorphize.pyvera/environment.pyvera/prelude.pyvera/wasm/calls.pyvera/wasm/context.pyvera/wasm/html_serde.pyvera/wasm/inference.py
- Add 5 wrong-type checker tests (html_query, html_text, html_attr) - Add per-operation WAT import tests (html_to_string, html_query, html_text) - Add CSS selector tests (class, ID, descendant) - Fix HTML escaping in api.py: escape text content, attribute values, and comment dashes in html_to_string serializer - Fix browser runtime htmlToString: add escapeHtml/escapeAttr helpers - Fix verifier docstring to match actual tier counts - Fix doc counts (3,056 tests) Co-Authored-By: Claude <noreply@anthropic.invalid>
There was a problem hiding this comment.
♻️ Duplicate comments (2)
tests/test_codegen.py (2)
9222-9266:⚠️ Potential issue | 🟠 MajorAttribute-presence selector coverage is still missing.
The feature contract includes attribute-presence selectors, but current selector tests cover tag/class/id/descendant only. Please add a
[attr]case.🧪 Proposed selector test addition
+ def test_html_query_attribute_presence(self) -> None: + """html_query with attribute-presence selector.""" + source = ''' +public fn main(-> `@Int`) + requires(true) ensures(true) effects(pure) +{ + let `@Result`<HtmlNode, String> = + html_parse("<div><a href=\\"u\\">x</a><a>y</a></div>"); + match `@Result`<HtmlNode, String>.0 { + Ok(`@HtmlNode`) -> array_length(html_query(`@HtmlNode.0`, "[href]")), + Err(`@String`) -> 0 + } +} +''' + assert _run(source) == 1As per coding guidelines: “DO flag … missing edge cases for new compiler features”.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 9222 - 9266, Add a new test method alongside test_html_query_by_class/test_html_query_by_id/test_html_query_descendant that exercises attribute-presence selectors (e.g., name it test_html_query_attribute_presence); create a source string that calls html_parse on HTML containing an element with an attribute (like <div data-foo="x"> or <div data-foo></div>) plus another element without it, then match the Result and call array_length(html_query(`@HtmlNode.0`, "[data-foo]")) and assert _run(source) == 1 to verify the selector returns only the element with the attribute.
9195-9220:⚠️ Potential issue | 🟠 Major
html_queryimport-gating is not being proven in isolation.
test_html_query_wat_importcurrently callshtml_parse, so it cannot verify thathtml_queryalone gates imports correctly. Please mirror the JSON/Http per-op pattern by asserting sibling absence for query-only usage.🧪 Proposed test tightening
def test_html_query_wat_import(self) -> None: """html_query generates a WASM host import.""" source = """ public fn main(-> `@Int`) requires(true) ensures(true) effects(pure) -{ - let `@Result`<HtmlNode, String> = html_parse("<p>x</p>"); - match `@Result`<HtmlNode, String>.0 { - Ok(`@HtmlNode`) -> array_length(html_query(`@HtmlNode.0`, "p")), - Err(`@String`) -> 0 - } -} +{ array_length(html_query(HtmlText("x"), "p")) } """ result = _compile_ok(source) assert '"html_query"' in result.wat + assert '"html_parse"' not in result.wat + assert '"html_to_string"' not in result.wat + assert '"html_text"' not in result.watBased on learnings: per-operation import-gating tests in
tests/test_codegen.pyfor JSON/Http require used import presence and sibling import absence.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 9195 - 9220, Update test_html_query_wat_import so it does not call html_parse: change the source to invoke html_query directly with an HtmlNode literal (analogous to test_html_text using HtmlText("hello")), then assert '"html_query"' is in result.wat and assert '"html_parse"' is not in result.wat; refer to the test function name test_html_query_wat_import and the symbols html_query and html_parse to locate and modify the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@tests/test_codegen.py`:
- Around line 9222-9266: Add a new test method alongside
test_html_query_by_class/test_html_query_by_id/test_html_query_descendant that
exercises attribute-presence selectors (e.g., name it
test_html_query_attribute_presence); create a source string that calls
html_parse on HTML containing an element with an attribute (like <div
data-foo="x"> or <div data-foo></div>) plus another element without it, then
match the Result and call array_length(html_query(`@HtmlNode.0`, "[data-foo]"))
and assert _run(source) == 1 to verify the selector returns only the element
with the attribute.
- Around line 9195-9220: Update test_html_query_wat_import so it does not call
html_parse: change the source to invoke html_query directly with an HtmlNode
literal (analogous to test_html_text using HtmlText("hello")), then assert
'"html_query"' is in result.wat and assert '"html_parse"' is not in result.wat;
refer to the test function name test_html_query_wat_import and the symbols
html_query and html_parse to locate and modify the test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 9b725188-97c0-4d5d-ada6-8f0d7b25e715
📒 Files selected for processing (6)
TESTING.mdtests/test_checker.pytests/test_codegen.pytests/test_verifier.pyvera/browser/runtime.mjsvera/codegen/api.py
6 new codegen tests: comment roundtrip, text escaping, attribute value escaping, attribute presence selector, parsed attributes, void elements. Fix doc counts (3,062 tests). Co-Authored-By: Claude <noreply@anthropic.invalid>
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
TESTING.md (2)
82-82:⚠️ Potential issue | 🟡 MinorUpdate stale conformance program count.
Line 82 still references "62 small, focused programs", but the Overview table at Line 11 and the directory structure comment at Line 120 both correctly state 63 programs after this PR adds
ch09_html.vera.📝 Proposed fix
-The conformance suite is a collection of 62 small, focused programs in `tests/conformance/` that systematically validate every language feature against the spec. Each program is self-contained, imports nothing, and tests one feature or a small group of related features. +The conformance suite is a collection of 63 small, focused programs in `tests/conformance/` that systematically validate every language feature against the spec. Each program is self-contained, imports nothing, and tests one feature or a small group of related features.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@TESTING.md` at line 82, Update the stale count string "62 small, focused programs" in TESTING.md to "63 small, focused programs" so it matches the Overview table and directory structure note (this is the phrase to search for and replace; no code changes required beyond updating that text).
154-154:⚠️ Potential issue | 🟡 MinorUpdate stale parametrised test count.
The comment claims 305 tests, but the "Test Files" table at Line 76 correctly shows
test_conformance.pynow has 315 tests (63 conformance programs × 5 test levels each). The comment predates even the previous count of 310.📝 Proposed fix
-# Via pytest (parametrized — 305 tests) +# Via pytest (parametrized — 315 tests) pytest tests/test_conformance.py -v🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@TESTING.md` at line 154, Update the stale test count in the header "Via pytest (parametrized — 305 tests)" to reflect the current total of 315 tests (derived from test_conformance.py having 63 programs × 5 levels = 315); locate the header string "Via pytest (parametrized — 305 tests)" and change the displayed number to 315 so it matches the Test Files table and the actual parametrized tests for test_conformance.py.
♻️ Duplicate comments (1)
tests/test_codegen.py (1)
9171-9221:⚠️ Potential issue | 🟡 MinorTighten HTML per-operation import-gating tests for full isolation parity.
Line [9195] still couples
html_querywithhtml_parse, and the import-gating tests do not consistently assert sibling absence for allhtml_*imports in each per-op test. This can miss gating regressions.Suggested test tightening
@@ def test_html_parse_wat_import(self) -> None: @@ result = _compile_ok(source) assert '"html_parse"' in result.wat + assert '"html_to_string"' not in result.wat + assert '"html_query"' not in result.wat + assert '"html_text"' not in result.wat @@ def test_html_to_string_wat_import(self) -> None: @@ result = _compile_ok(source) assert '"html_to_string"' in result.wat assert '"html_parse"' not in result.wat + assert '"html_query"' not in result.wat + assert '"html_text"' not in result.wat @@ def test_html_query_wat_import(self) -> None: @@ -{ - let `@Result`<HtmlNode, String> = html_parse("<p>x</p>"); - match `@Result`<HtmlNode, String>.0 { - Ok(`@HtmlNode`) -> array_length(html_query(`@HtmlNode.0`, "p")), - Err(`@String`) -> 0 - } -} +{ array_length(html_query(HtmlText("x"), "p")) } """ result = _compile_ok(source) assert '"html_query"' in result.wat + assert '"html_parse"' not in result.wat + assert '"html_to_string"' not in result.wat + assert '"html_text"' not in result.wat @@ def test_html_text_wat_import(self) -> None: @@ result = _compile_ok(source) assert '"html_text"' in result.wat assert '"html_parse"' not in result.wat + assert '"html_to_string"' not in result.wat + assert '"html_query"' not in result.watBased on learnings: In
tests/test_codegen.py, JSON/Http import-gating tests use per-operation checks with sibling-absence assertions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 9171 - 9221, Tests for per-operation HTML import gating are leaking: test_html_query embeds html_parse and most tests don't assert that other html_* imports are absent. Update each test (test_html_parse_wat_import, test_html_to_string_wat_import, test_html_query_wat_import, test_html_text_wat_import) so they only exercise the single operation under test (e.g., make test_html_query stop calling html_parse and instead construct an HtmlNode/HtmlText directly or use an API that doesn't import html_parse) and add explicit sibling-absence assertions in every test: when asserting the expected import (e.g., '"html_query"'), also assert the other three imports ('"html_parse"', '"html_to_string"', '"html_text"') are not in result.wat, and do the analogous checks in the other tests to ensure full isolation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@TESTING.md`:
- Line 316: Update the stale example count in TESTING.md: change the table entry
that reads "All 27 `.vera` examples pass `vera check` + `vera verify`" to
reflect 29 examples (i.e., "All 29 `.vera` examples pass `vera check` + `vera
verify`"). Locate the table row referencing `check_examples.py` and update the
numeric count only so it matches the new examples/html.vera addition.
In `@tests/test_codegen.py`:
- Around line 9328-9349: The test test_html_parse_with_attributes currently uses
a vacuous assertion (assert result >= 0); update the test so it actually
verifies the attribute value by querying the parsed HTML and asserting the
"class" attribute equals "main" (or that its length is 4). Concretely, in the
source snippet use html_query to select the div node returned by html_parse,
call html_attr on that node for "class", and replace the final assert with a
concrete check (e.g. assert attr == "main" or assert string_length(attr) == 4)
referencing the symbols html_parse, html_query, and html_attr.
---
Outside diff comments:
In `@TESTING.md`:
- Line 82: Update the stale count string "62 small, focused programs" in
TESTING.md to "63 small, focused programs" so it matches the Overview table and
directory structure note (this is the phrase to search for and replace; no code
changes required beyond updating that text).
- Line 154: Update the stale test count in the header "Via pytest (parametrized
— 305 tests)" to reflect the current total of 315 tests (derived from
test_conformance.py having 63 programs × 5 levels = 315); locate the header
string "Via pytest (parametrized — 305 tests)" and change the displayed number
to 315 so it matches the Test Files table and the actual parametrized tests for
test_conformance.py.
---
Duplicate comments:
In `@tests/test_codegen.py`:
- Around line 9171-9221: Tests for per-operation HTML import gating are leaking:
test_html_query embeds html_parse and most tests don't assert that other html_*
imports are absent. Update each test (test_html_parse_wat_import,
test_html_to_string_wat_import, test_html_query_wat_import,
test_html_text_wat_import) so they only exercise the single operation under test
(e.g., make test_html_query stop calling html_parse and instead construct an
HtmlNode/HtmlText directly or use an API that doesn't import html_parse) and add
explicit sibling-absence assertions in every test: when asserting the expected
import (e.g., '"html_query"'), also assert the other three imports
('"html_parse"', '"html_to_string"', '"html_text"') are not in result.wat, and
do the analogous checks in the other tests to ensure full isolation.
🪄 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: ddb585e4-6fce-4bae-8d29-44b045d6f6d9
📒 Files selected for processing (2)
TESTING.mdtests/test_codegen.py
- Fix examples count 27->29, conformance prose 62->63, pytest 305->315 - Add sibling-absence assertions to per-operation WAT import tests - Fix test_html_parse_with_attributes: query by class then verify attribute value length (4 for 'main') - Fix codegen line count Co-Authored-By: Claude <noreply@anthropic.invalid>
- test_html_parse_comment_roundtrip: exercises write_html comment path - test_html_query_empty_result: no-match selector returns empty array - test_html_nested_elements: text extraction from nested tags Co-Authored-By: Claude <noreply@anthropic.invalid>
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
TESTING.md (3)
291-291:⚠️ Potential issue | 🟡 MinorUpdate stale example count in Round-Trip Testing section.
This line references "27 example programs", but the current total is 29 after this PR adds
examples/html.vera.📝 Proposed fix
-Every one of the 27 example programs in `examples/` is tested through **every pipeline stage** +Every one of the 29 example programs in `examples/` is tested through **every pipeline stage**As per coding guidelines: keep validation expectations and documented counts in sync with the PR's added conformance/program.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@TESTING.md` at line 291, Update the stale example count in the Round-Trip Testing section: change the sentence that currently says "27 example programs" to "29 example programs" (this refers to the descriptive line about examples in `examples/` being tested through every pipeline stage in TESTING.md) so the documented count matches the newly added examples like `examples/html.vera`.
207-207:⚠️ Potential issue | 🟡 MinorUpdate stale example count in Contract Verification Coverage section.
This line references "all 27 example programs", but the PR adds
examples/html.vera, bringing the total to 29 (as correctly reflected on lines 12, 40, and 316).📝 Proposed fix
-Across all 27 example programs: +Across all 29 example programs:As per coding guidelines: keep validation expectations and documented counts in sync with the PR's added conformance/program.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@TESTING.md` at line 207, Update the stale count in the "Contract Verification Coverage" section that currently reads "all 27 example programs" to reflect the new total "all 29 example programs" (the PR added examples/html.vera); locate the phrase in TESTING.md within the Contract Verification Coverage paragraph and change the numeric count to 29 so it matches the other references (lines that already show 29).
233-267:⚠️ Potential issue | 🟡 MinorAdd Html stdlib feature to Language Feature Coverage table.
The table systematically documents all Chapter 9 stdlib features (Markdown, Regex, Decimal, Json, Http), but the newly added Html feature is missing. This creates a factual gap in the documented language coverage.
📝 Proposed fix
Add after line 265 (the Json entry):
| Ch 9: Stdlib | Json (json_parse, json_stringify, json_get, json_set) | test_codegen, test_checker | ch09_json | json | +| Ch 9: Stdlib | Html (html_parse, html_to_string, html_query, html_text, html_attr) | test_codegen, test_checker | ch09_html | html | | Ch 9: Stdlib | Http effect (http_get, http_post) | test_codegen, test_checker | ch09_http | http_client |As per coding guidelines: ensure HTML-related code samples/conformance entry are covered by the existing validation scripts.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@TESTING.md` around lines 233 - 267, Add a new row to the Language Feature Coverage table for the Html stdlib feature immediately after the Json entry: add "Ch 9: Stdlib | Html | test_codegen, test_checker, test_html | ch09_html | html_examples" (or the actual test-suite and conformance id you use, e.g., test_html and ch09_html) so the table mirrors other Ch 9 entries; ensure the new "ch09_html" conformance id and test file names match your existing validation scripts so HTML-related examples are picked up by the validation pipeline.
♻️ Duplicate comments (1)
tests/test_codegen.py (1)
9200-9215:⚠️ Potential issue | 🟠 MajorIsolate
html_queryimport-gating in this WAT test.Line [9206] also calls
html_parse, so this does not provehtml_queryis independently gated nor that sibling HTML imports remain absent for query-only usage.🧪 Proposed tightening
def test_html_query_wat_import(self) -> None: """html_query generates a WASM host import.""" source = """ public fn main(-> `@Int`) requires(true) ensures(true) effects(pure) -{ - let `@Result`<HtmlNode, String> = html_parse("<p>x</p>"); - match `@Result`<HtmlNode, String>.0 { - Ok(`@HtmlNode`) -> array_length(html_query(`@HtmlNode.0`, "p")), - Err(`@String`) -> 0 - } -} +{ array_length(html_query(HtmlText("x"), "p")) } """ result = _compile_ok(source) assert '"html_query"' in result.wat + assert '"html_parse"' not in result.wat + assert '"html_to_string"' not in result.wat + assert '"html_text"' not in result.watBased on learnings,
tests/test_codegen.pyalready uses per-operation WAT import-gating patterns for JSON/Http and HTML should mirror that.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 9200 - 9215, The test test_html_query_wat_import currently calls html_parse and html_query together, so it does not prove html_query import is independently gated; change the test to exercise only html_query (remove the html_parse call and any match branches that rely on HtmlNode construction from html_parse) so the compiled result.wat contains the "html_query" import without also requiring other HTML imports like html_parse; update the source string in test_html_query_wat_import to produce or reference an HtmlNode value usable by html_query (e.g., provide a dummy HtmlNode literal or construct the call site to directly call html_query with a minimal HtmlNode value) and keep the final assertion assert '"html_query"' in result.wat.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@TESTING.md`:
- Line 358: Update the stale count text for the `check_examples.py` entry in the
validation scripts table: change the referenced "All 27 examples" to "All 29
examples" so it matches the other table entry (line referencing 29) and the
repository's current total; locate the table row containing the string
`check_examples.py` and update only the numeric count to 29 to keep validation
expectations consistent.
In `@tests/test_codegen.py`:
- Around line 9307-9319: The test test_html_attr_value_escaping currently only
asserts result > 0; change it to call html_to_string(HtmlElement(...)) to get
the serialized string and assert the escaping contract directly: that the
attribute value for "title" does not contain a raw double-quote and is escaped
(e.g. contains title="a"b" or the equivalent HTML entity) — use
html_to_string, HtmlElement, and the map_insert/map_new construction already in
the test to build the element and assert the exact escaped substring instead of
a numeric check.
---
Outside diff comments:
In `@TESTING.md`:
- Line 291: Update the stale example count in the Round-Trip Testing section:
change the sentence that currently says "27 example programs" to "29 example
programs" (this refers to the descriptive line about examples in `examples/`
being tested through every pipeline stage in TESTING.md) so the documented count
matches the newly added examples like `examples/html.vera`.
- Line 207: Update the stale count in the "Contract Verification Coverage"
section that currently reads "all 27 example programs" to reflect the new total
"all 29 example programs" (the PR added examples/html.vera); locate the phrase
in TESTING.md within the Contract Verification Coverage paragraph and change the
numeric count to 29 so it matches the other references (lines that already show
29).
- Around line 233-267: Add a new row to the Language Feature Coverage table for
the Html stdlib feature immediately after the Json entry: add "Ch 9: Stdlib |
Html | test_codegen, test_checker, test_html | ch09_html | html_examples" (or
the actual test-suite and conformance id you use, e.g., test_html and ch09_html)
so the table mirrors other Ch 9 entries; ensure the new "ch09_html" conformance
id and test file names match your existing validation scripts so HTML-related
examples are picked up by the validation pipeline.
---
Duplicate comments:
In `@tests/test_codegen.py`:
- Around line 9200-9215: The test test_html_query_wat_import currently calls
html_parse and html_query together, so it does not prove html_query import is
independently gated; change the test to exercise only html_query (remove the
html_parse call and any match branches that rely on HtmlNode construction from
html_parse) so the compiled result.wat contains the "html_query" import without
also requiring other HTML imports like html_parse; update the source string in
test_html_query_wat_import to produce or reference an HtmlNode value usable by
html_query (e.g., provide a dummy HtmlNode literal or construct the call site to
directly call html_query with a minimal HtmlNode value) and keep the final
assertion assert '"html_query"' in result.wat.
🪄 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: 643c846c-3bb3-4662-9848-33d4d0612965
📒 Files selected for processing (2)
TESTING.mdtests/test_codegen.py
- Fix 27->29 example counts (4 occurrences) and 62->63 conformance - Add Language Feature Coverage rows for Map/Set/Decimal, Json, Html, Http - Fix test_html_attr_value_escaping: assert exact length (24) - Fix test_html_query_wat_import: construct HtmlElement directly, no html_parse dependency, full sibling-absence assertions - Fix conformance pytest snippet 305->315 Co-Authored-By: Claude <noreply@anthropic.invalid>
|
Merging with codecov/patch at ~89% (target 95.35%). The gap is the same structural issue as every PR touching the host runtime:
Project coverage is 95.24% (-0.11% from baseline). All 3,065 tests pass. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
TESTING.md (1)
207-214:⚠️ Potential issue | 🟡 MinorContract coverage figures are internally inconsistent.
This section says
162Tier‑1 out of177total (91.0%), but that ratio is ~91.5%; it also conflicts with the overview metric (162 of 179). Please align total contracts and derived percentage across both sections.As per coding guidelines: "
**/*.md: Review Markdown files for factual accuracy against the codebase, broken links, and outdated information."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@TESTING.md` around lines 207 - 214, The contract coverage numbers in the "Across all 29 example programs" table are inconsistent: it lists "Tier 1 (static) 162", "Total 177", and "91.0%" (which is ~91.5%), and this conflicts with the other overview metric "162 of 179"; confirm the actual contract counts from the test output/codebase and then update the table and the overview metric so both show the same total and a correctly computed percentage (e.g., 162/177 → 91.5% or 162/179 → 90.5%); ensure you update the numeric cells "Tier 1 (static) 162", "Tier 3 (runtime) 16", "Total X" and the percentage string wherever "162 of 177" or "162 of 179" appear so all instances match and the derived percent is accurate.
♻️ Duplicate comments (1)
tests/test_codegen.py (1)
9090-9104:⚠️ Potential issue | 🟠 MajorStrengthen weak HTML test oracles to assert the actual contract.
These assertions are currently too permissive (
> 0) and can pass even when the advertised behaviour is broken (roundtrip fidelity, comment preservation, nested text extraction).Suggested tightening (concrete behavioural checks)
@@ def test_html_to_string_roundtrip(self) -> None: """html_to_string serializes back to HTML.""" source = """ public fn main(-> `@Int`) requires(true) ensures(true) effects(pure) { let `@Result`<HtmlNode, String> = html_parse("<p>hi</p>"); match `@Result`<HtmlNode, String>.0 { - Ok(`@HtmlNode`) -> string_length(html_to_string(`@HtmlNode.0`)), + Ok(`@HtmlNode`) -> + if string_contains(html_to_string(`@HtmlNode.0`), "<p>hi</p>") then { 1 } else { 0 }, Err(`@String`) -> 0 } } """ - assert _run(source) > 0 + assert _run(source) == 1 @@ def test_html_parse_comment_roundtrip(self) -> None: """Parsed HTML comments survive roundtrip through html_to_string.""" source = ''' public fn main(-> `@Int`) requires(true) ensures(true) effects(pure) { let `@Result`<HtmlNode, String> = html_parse("<!-- hello --><p>text</p>"); match `@Result`<HtmlNode, String>.0 { - Ok(`@HtmlNode`) -> string_length(html_to_string(`@HtmlNode.0`)), + Ok(`@HtmlNode`) -> + if string_contains(html_to_string(`@HtmlNode.0`), "<!-- hello -->") then { 1 } else { 0 }, Err(`@String`) -> 0 } } ''' - result = _run(source) - assert result > 0 # roundtrip produces non-empty HTML + assert _run(source) == 1 @@ def test_html_nested_elements(self) -> None: """html_text extracts text from nested elements.""" source = ''' public fn main(-> `@Int`) requires(true) ensures(true) effects(pure) { let `@Result`<HtmlNode, String> = html_parse("<div><span>hello</span> <em>world</em></div>"); match `@Result`<HtmlNode, String>.0 { - Ok(`@HtmlNode`) -> string_length(html_text(`@HtmlNode.0`)), + Ok(`@HtmlNode`) -> + if string_contains(html_text(`@HtmlNode.0`), "hello") then { + if string_contains(html_text(`@HtmlNode.0`), "world") then { 1 } else { 0 } + } else { 0 }, Err(`@String`) -> 0 } } ''' - result = _run(source) - assert result > 0 # extracts "hello world" text + assert _run(source) == 1As per coding guidelines, “DO flag: Tests that don't assert anything meaningful.”
Also applies to: 9371-9386, 9402-9417
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_codegen.py` around lines 9090 - 9104, The test test_html_to_string_roundtrip uses a weak oracle (assert _run(source) > 0); update it to assert the actual contract by invoking _run(source) and comparing the returned HTML/text to expected values (e.g., that html_to_string roundtrips to "<p>hi</p>" or that string_length(html_to_string(...)) equals the expected length and that comments/nested text are preserved). Locate the test function test_html_to_string_roundtrip and the helper _run, replace the > 0 check with precise assertions against the expected serialized HTML/text and length, and apply the same tightening to the related tests referenced (the tests around the other occurrences that call _run).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@TESTING.md`:
- Around line 207-214: The contract coverage numbers in the "Across all 29
example programs" table are inconsistent: it lists "Tier 1 (static) 162", "Total
177", and "91.0%" (which is ~91.5%), and this conflicts with the other overview
metric "162 of 179"; confirm the actual contract counts from the test
output/codebase and then update the table and the overview metric so both show
the same total and a correctly computed percentage (e.g., 162/177 → 91.5% or
162/179 → 90.5%); ensure you update the numeric cells "Tier 1 (static) 162",
"Tier 3 (runtime) 16", "Total X" and the percentage string wherever "162 of 177"
or "162 of 179" appear so all instances match and the derived percent is
accurate.
---
Duplicate comments:
In `@tests/test_codegen.py`:
- Around line 9090-9104: The test test_html_to_string_roundtrip uses a weak
oracle (assert _run(source) > 0); update it to assert the actual contract by
invoking _run(source) and comparing the returned HTML/text to expected values
(e.g., that html_to_string roundtrips to "<p>hi</p>" or that
string_length(html_to_string(...)) equals the expected length and that
comments/nested text are preserved). Locate the test function
test_html_to_string_roundtrip and the helper _run, replace the > 0 check with
precise assertions against the expected serialized HTML/text and length, and
apply the same tightening to the related tests referenced (the tests around the
other occurrences that call _run).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 00800ea7-27b7-4c85-bdb5-7514b260bf50
📒 Files selected for processing (2)
TESTING.mdtests/test_codegen.py
Summary
Parse HTML responses from Http.get, extract structured data, query by CSS selector.
HtmlNode ADT
5 built-in operations
CSS selector support
Tag name (`div`), class (`.foo`), ID (`#bar`), attribute (`[href]`), descendant (`div p`).
Architecture
New files
Documentation
Closes #311.
Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Documentation
Tests
Chores