Skip to content

fix: SMT translator String/Float64 param sorts + string predicates (v0.0.111)#456

Merged
aallan merged 8 commits into
mainfrom
fix/smt-string-float64-params
Apr 13, 2026
Merged

fix: SMT translator String/Float64 param sorts + string predicates (v0.0.111)#456
aallan merged 8 commits into
mainfrom
fix/smt-string-float64-params

Conversation

@aallan

@aallan aallan commented Apr 10, 2026

Copy link
Copy Markdown
Owner

Summary

  • String and Float64 function parameters now use correct Z3 sorts — they were falling through to declare_int() (the else fallback in verifier.py). String params are now declared via declare_string() (Z3 SeqSort) and Float64 via declare_float64() (Z3 RealSort). This was the root cause of all the other failures.
  • StringLit now translates to z3.StringVal() — string literals in contract expressions (e.g. requires(string_starts_with(@String.0, "https://"))) were returning None from translate_expr, silently demoting contracts to Tier 3.
  • string_length uses z3.Length() for String sorts — replaces the uninterpreted function, giving Z3 full semantics so string_length("literal") > 0 is provable at call sites. The uninterpreted fallback is kept for non-string sorts.
  • string_contains, string_starts_with, string_ends_with now Tier 1 — encoded via Z3 native string theory (z3.Contains, z3.PrefixOf, z3.SuffixOf).
  • float_is_nan / float_is_infinite explicitly return None — previously fell through silently. Now documented: encoding as BoolVal(False) would be unsound (would drop the runtime guard), so Tier 3 is correct for these.

Discovered while running vera verify examples/inference.vera after adding Mistral support — requires(string_length(@String.0) > 0) was emitting a Tier 3 warning on working code.

Test plan

  • TestStringLengthVerification (3 tests) — string_length contracts verify Tier 1
  • TestStringPredicateVerification (5 tests) — string_contains/starts_with/ends_with Tier 1; float_is_nan/infinite correctly Tier 3
  • vera verify examples/inference.vera — now 4/4 Tier 1, no warnings
  • Overall tier baseline updated: 172 T1 / 19 T3 (was 170/21)
  • Full suite: 3,247 passed, 11 skipped
  • mypy vera/ — clean

Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Native solver support for string operations: contains, starts-with, ends-with and length.
  • Bug Fixes

    • Improved handling of string literals and refined string/float parameter sorts in verification.
    • Float NaN/infinite checks preserved as runtime-tier fallbacks.
  • Tests

    • Expanded test suite (3,239 → 3,250) and added tests; Tier 1 verified contracts increased by 2.
  • Chores / Documentation

    • Version bumped to 0.0.111; changelog, history, README, roadmap and testing docs updated.

aallan and others added 3 commits April 10, 2026 17:28
string_length() was missing from _translate_call in smt.py, causing
requires(string_length(@String.0) > 0) and similar contracts to fall
back to Tier 3 runtime checks even though the constraint is trivially
decidable.

Fix: treat string_length as an uninterpreted function with the axiom
result >= 0, matching the pattern used for array_length, map_size, and
set_size. The inference.vera example now verifies 4/4 Tier 1 (was 3/4
Tier 1 + 1 Tier 3).

Adds TestStringLengthVerification (3 tests) covering:
- requires(string_length > 0) → Tier 1
- ensures(@Int.result >= 0) on string_length return → Tier 1
- string_length in comparison expression → Tier 1

Updates tier count baseline: 172 T1 / 19 T3 (was 170 / 21).

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

Fixes a class of contracts that silently fell to Tier 3 (runtime check)
despite being statically decidable.

Root cause: verifier.py declared String and Float64 function parameters as
z3.IntSort (the else fallback), so String slot refs had the wrong sort and
z3.Contains/PrefixOf/SuffixOf received Int sorts instead of SeqSort.

Changes:
- verifier.py: add _is_string_type / _is_float64_type helpers; declare
  String params/returns via smt.declare_string() (z3.SeqSort) and Float64
  via smt.declare_float64() (z3.RealSort)
- smt.py: add StringLit → z3.StringVal() translation so string literals
  in contracts are encodable
- smt.py: use z3.Length() for string_length on SeqSort args (instead of
  an uninterpreted function) so Z3 can prove string_length("literal") > 0
  at call sites; uninterpreted fallback retained for non-string sorts
- smt.py: add string_contains → z3.Contains, string_starts_with →
  z3.PrefixOf, string_ends_with → z3.SuffixOf (native string theory)
- smt.py: add explicit return None for float_is_nan / float_is_infinite
  with comment explaining why BoolVal(False) would be unsound (Float64 is
  modeled as reals; making the check always-False would silently drop the
  runtime guard)

test_verifier.py: add TestStringPredicateVerification (5 tests)
  - string_contains/starts_with/ends_with → Tier 1
  - float_is_nan/float_is_infinite → Tier 3 (correct, preserved)

test_verifier_coverage.py: update 7 tests that used StringLit as
  "untranslatable" stand-in; StringLit is now translatable so tests
  switch to FloatLit; string equality / string predicate tests updated
  from "expects Tier 3" to "expects Tier 1"

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

coderabbitai Bot commented Apr 10, 2026

Copy link
Copy Markdown

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Bumps project to v0.0.111 and updates SMT translation and verifier declarations so String and Float64 use correct Z3 sorts; translates string literals to z3.StringVal(), adds native Z3 string ops, and preserves float_is_nan/float_is_infinite as Tier‑3 fallbacks.

Changes

Cohort / File(s) Summary
Version & Docs
CHANGELOG.md, HISTORY.md, README.md, ROADMAP.md, TESTING.md, pyproject.toml, vera/__init__.py
Bumped project version to 0.0.111; updated changelog/HISTORY, README/ROADMAP/TESTING figures and test counts, and pyproject.toml/vera.__version__.
SMT Translation
vera/smt.py
Translate ast.StringLitz3.StringVal(); implement string_lengthz3.Length for SeqSort (uninterpreted fallback otherwise, constrained >= 0); map string_contains/string_starts_with/string_ends_with to Z3 Contains/PrefixOf/SuffixOf; float_is_nan/float_is_infinite now return None (Tier‑3 fallback).
Verifier Declarations
vera/verifier.py
Declare function parameters/results as Z3 SeqSort (String) or Real (Float64) when types (including RefinedType) are String/Float64 via new _is_string_type / _is_float64_type helpers; _is_bool_type extended to accept RefinedType of Bool.
Tests — behaviour & expectations
tests/test_verifier.py, tests/test_verifier_coverage.py
Added tests asserting string_length and string predicate preconditions are Tier‑1, added refined-type param tests, adjusted Tier‑1/Tier‑3 counts, converted several string Tier‑3 tests to Tier‑1, and updated SMT edge-case tests to use FloatLit for untranslatable expressions.

Sequence Diagram(s)

sequenceDiagram
    participant AST as AST / Tests
    participant Translator as SMT Translator
    participant Verifier as Verifier
    participant Z3 as Z3 Solver

    Note over AST,Verifier: Old flow (pre-change)
    AST->>Translator: emit StringLit / string ops / Float64 param
    Translator->>Translator: unsupported or wrong sort → returns None
    Translator-->>Verifier: no native Z3 term (Tier 3 fallback)

    Note over AST,Verifier: New flow (v0.0.111)
    AST->>Translator: StringLit
    Translator->>Z3: z3.StringVal(literal)
    Z3-->>Translator: String term

    AST->>Verifier: declare param/result of type String/Float64
    Verifier->>Translator: request declaration
    Translator->>Z3: declare SeqSort / Real constant
    Z3-->>Verifier: Z3-typed constant

    AST->>Translator: string_length / contains / starts_with / ends_with
    Translator->>Z3: z3.Length / z3.Contains / z3.PrefixOf / z3.SuffixOf
    Z3-->>Translator: Int/Bool terms (Tier 1)

    AST->>Translator: float_is_nan / float_is_infinite
    Translator->>Translator: return None
    Note over Translator: Tier 3 runtime guard preserved
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

compiler, tests, docs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly and specifically describes the main changes: SMT translator fixes for String/Float64 parameter sorts and string predicates, with the version bump included.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/smt-string-float64-params

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

@codecov

codecov Bot commented Apr 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.55556% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.35%. Comparing base (53514f9) to head (0c85ae4).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
vera/smt.py 92.85% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #456      +/-   ##
==========================================
+ Coverage   90.34%   90.35%   +0.01%     
==========================================
  Files          50       50              
  Lines       19502    19544      +42     
  Branches      225      225              
==========================================
+ Hits        17619    17659      +40     
- Misses       1879     1881       +2     
  Partials        4        4              
Flag Coverage Δ
javascript 50.67% <ø> (ø)
python 95.28% <95.55%> (-0.01%) ⬇️

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

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

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 223: Update the outdated release count string "**110 tagged releases**"
in the ROADMAP.md text to "**111 tagged releases**" (the line reading "**630+
commits, 110 tagged releases, 3,247 tests, 96% coverage, 73 conformance
programs, 30 examples, 13 spec chapters.**") so the documented release count
matches v0.0.111; ensure the revised sentence keeps the same formatting and link
to HISTORY.md unchanged.

In `@vera/verifier.py`:
- Around line 460-463: The string/float branch falls through to declare_int when
types are wrapped in RefinedType; update the logic that decides sorts so
RefinedType(String, ...) and RefinedType(Float64, ...) are detected. Either
extend _is_string_type and _is_float64_type to unwrap RefinedType (inspect
param_ty.base or param_ty.type and return True when the inner type is the
primitive) or add explicit checks before the declare_int fallback to detect
RefinedType wrappers and call smt.declare_string(z3_name) or
smt.declare_float64(z3_name) accordingly (referencing _is_string_type,
_is_float64_type, RefinedType, declare_string, declare_float64, and declare_int
to locate the relevant branches).
🪄 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: c43f428e-b3ab-4c5a-9a8f-fca8c04ac2ba

📥 Commits

Reviewing files that changed from the base of the PR and between 53514f9 and 5bf8831.

⛔ 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/**
  • uv.lock is excluded by !**/*.lock, !uv.lock
📒 Files selected for processing (11)
  • CHANGELOG.md
  • HISTORY.md
  • README.md
  • ROADMAP.md
  • TESTING.md
  • pyproject.toml
  • tests/test_verifier.py
  • tests/test_verifier_coverage.py
  • vera/__init__.py
  • vera/smt.py
  • vera/verifier.py

Comment thread ROADMAP.md Outdated
Comment thread vera/verifier.py
…test count to 3,249

_is_string_type and _is_float64_type only checked ty == STRING / ty == FLOAT64,
so a function parameter typed as a refinement of String or Float64 (e.g.
type NonEmptyString = { @string | string_length(@String.0) > 0 }) would fall
through to declare_int (IntSort) instead of declare_string / declare_float64.
This caused string predicates (string_length, string_contains, etc.) to use the
uninterpreted-function fallback rather than Z3 native string theory, producing
spurious Tier 3 downgrades.

Fix matches the existing pattern in _is_nat_type:
  return ty == STRING or (isinstance(ty, RefinedType) and ty.base == STRING)
  return ty == FLOAT64 or (isinstance(ty, RefinedType) and ty.base == FLOAT64)

Also fix ROADMAP.md release count (110 → 111) and bump test counts from 3,247
to 3,249 across TESTING.md, ROADMAP.md, and README.md.

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan aallan dismissed a stale review April 13, 2026 18:30

Random from outside the project. Not relevant.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
vera/verifier.py (1)

983-985: ⚠️ Potential issue | 🟡 Minor

_is_bool_type does not unwrap RefinedType, unlike the other helpers.

The new _is_string_type (line 996) and _is_float64_type (line 1001) both unwrap RefinedType to check the base type. Similarly, _is_nat_type (line 980) unwraps RefinedType. However, _is_bool_type only checks for exact equality with BOOL.

If a refined Bool type (RefinedType(BOOL, ...)) is ever used as a parameter or return type, it would fall through to declare_int instead of declare_bool.

Proposed fix for consistency
     `@staticmethod`
     def _is_bool_type(ty: Type) -> bool:
         """Check if a type is Bool."""
-        return ty == BOOL
+        return ty == BOOL or (isinstance(ty, RefinedType) and ty.base == BOOL)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@vera/verifier.py` around lines 983 - 985, The _is_bool_type helper currently
compares ty directly to BOOL and must instead unwrap RefinedType like the other
helpers; update _is_bool_type to detect if ty is a RefinedType, replace ty with
its underlying/base type (as done in _is_string_type/_is_float64_type, e.g., ty
= ty.base_type or ty.type depending on your RefinedType field name), then
compare the unwrapped ty to BOOL so refined boolean types are recognized as
booleans by declare_bool.
🤖 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 `@vera/verifier.py`:
- Around line 983-985: The _is_bool_type helper currently compares ty directly
to BOOL and must instead unwrap RefinedType like the other helpers; update
_is_bool_type to detect if ty is a RefinedType, replace ty with its
underlying/base type (as done in _is_string_type/_is_float64_type, e.g., ty =
ty.base_type or ty.type depending on your RefinedType field name), then compare
the unwrapped ty to BOOL so refined boolean types are recognized as booleans by
declare_bool.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 882fabaf-7a7c-4b02-8238-d49142d043cd

📥 Commits

Reviewing files that changed from the base of the PR and between 5bf8831 and e6de1ae.

📒 Files selected for processing (5)
  • README.md
  • ROADMAP.md
  • TESTING.md
  • tests/test_verifier.py
  • vera/verifier.py

_is_bool_type only checked ty == BOOL, leaving RefinedType(base=BOOL)
params falling through to declare_int (IntSort) instead of declare_bool
(BoolSort). Fix follows the same pattern as _is_nat_type, _is_string_type,
and _is_float64_type:

  return ty == BOOL or (isinstance(ty, RefinedType) and ty.base == BOOL)

Adds test_refined_bool_param_verifies_cleanly to TestRefinedTypeParamSorts.
Updates test count from 3,249 to 3,250 across TESTING.md, ROADMAP.md,
and README.md.

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

aallan commented Apr 13, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Fixed — _is_bool_type now follows the same pattern as all other primitive helpers:

def _is_bool_type(ty: Type) -> bool:
    """Check if a type is Bool (including refinements of Bool)."""
    return ty == BOOL or (isinstance(ty, RefinedType) and ty.base == BOOL)

Added test_refined_bool_param_verifies_cleanly to TestRefinedTypeParamSorts. All four primitive type helpers (_is_nat_type, _is_bool_type, _is_string_type, _is_float64_type) now consistently unwrap RefinedType wrappers.

@coderabbitai

coderabbitai Bot commented Apr 13, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

@aallan: Confirmed — the fix is correct and the pattern is now fully consistent across all four primitive type predicates. The _is_bool_type implementation correctly handles both bare BOOL and RefinedType wrappers whose .base == BOOL, matching _is_string_type and _is_float64_type exactly. Adding test_refined_bool_param_verifies_cleanly to TestRefinedTypeParamSorts gives the refined-Bool path the same regression coverage as the String and Float64 paths.


✏️ Learnings added
Learnt from: aallan
URL: https://github.com/aallan/vera/pull/456

Timestamp: 2026-04-13T22:02:43.196Z
Learning: In `vera/verifier.py`, all four primitive type predicate helpers (`_is_nat_type`, `_is_bool_type`, `_is_string_type`, `_is_float64_type`) follow the same pattern: `ty == PRIMITIVE or (isinstance(ty, RefinedType) and ty.base == PRIMITIVE)`. This ensures refined parameter types (RefinedType wrappers) are recognised and declared with the correct Z3 sort rather than falling back to IntSort. Each helper has a corresponding `test_refined_<type>_param_verifies_cleanly` test in `TestRefinedTypeParamSorts` in `tests/test_verifier.py`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: aallan
Repo: aallan/vera PR: 414
File: vera/codegen/core.py:258-265
Timestamp: 2026-03-28T22:06:21.085Z
Learning: In `vera/codegen/core.py` and `vera/codegen/api.py` (PR `#414`), `CompileResult.fn_param_types` carries erased WASM-level tags (`i64`, `f64`, `i32`, `i32_pair`) rather than Vera-level kinds. This is intentional for the current CLI: `i32_pair` = String only (Array CLI not yet supported), `i64` = Int/Nat, `f64` = Float64, `i32` = Bool/Byte (identical CLI parsing). Carrying Vera-level parameter kinds through CompileResult to distinguish Nat vs Int (negative rejection) and Bool vs Byte is a future-proofing refactor explicitly deferred from PR `#414` and filed as a follow-up note by aallan.

Learnt from: aallan
Repo: aallan/vera PR: 350
File: tests/test_codegen.py:8630-8633
Timestamp: 2026-03-25T16:32:11.316Z
Learning: Repo aallan/vera PR `#350`: tests/test_codegen.py includes explicit WAT import‑gating coverage for JSON host imports — tests test_json_parse_wat_import, test_json_stringify_wat_import, and test_json_no_imports_when_unused verify that "vera.json_parse"/"vera.json_stringify" imports are emitted only when referenced and absent when unused.

Learnt from: aallan
Repo: aallan/vera PR: 0
File: :0-0
Timestamp: 2026-03-29T10:15:51.538Z
Learning: In aallan/vera, general housekeeping PRs (CI hardening, documentation, tooling) may acceptably bundle incidental code fixes (e.g. adding `vera --version` CLI support, HTTP Content-Type headers, urlopen timeouts) without requiring them to be split into separate PRs. Do not flag such bundling as a scope concern in this repository.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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_verifier.py`:
- Around line 1892-1914: The test test_refined_bool_param_verifies_cleanly
currently uses ensures(true) so it doesn't exercise Bool sort handling; update
the contract to be Bool-dependent by replacing ensures(true) with a boolean
assertion that references the parameter (e.g. ensures(`@Flag.0`)) so the verifier
must treat the parameter as Bool, and while here check that RefinedType wrappers
are handled by the verifier helper _is_bool_type (and other primitive-type
helpers) so they recognise RefinedType — adjust the test
(test_refined_bool_param_verifies_cleanly) and/or verifier predicates (e.g.
_is_bool_type in vera/verifier.py) accordingly.
- Around line 1706-1838: Replace the repeated parse_to_ast/typecheck/verify
plumbing in the new tests (e.g., test_string_length_gt_zero_requires_tier1,
test_string_length_ensures_tier1, test_string_length_comparison_tier1,
test_string_contains_tier1, test_string_starts_with_tier1,
test_string_ends_with_tier1, test_float_is_nan_stays_tier3,
test_float_is_infinite_stays_tier3) with the test helpers used across the suite:
call _verify_ok() or _verify_err() (or _check_ok/_check_err where appropriate)
with the source string and then assert against the returned summary, so you
remove the explicit parse_to_ast/typecheck/verify sequence and use
_verify/_verify_ok to maintain consistency and reduce duplication.
🪄 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: d28851c0-36ca-463f-96e2-ae8134cb6ea2

📥 Commits

Reviewing files that changed from the base of the PR and between e6de1ae and af0a325.

📒 Files selected for processing (5)
  • README.md
  • ROADMAP.md
  • TESTING.md
  • tests/test_verifier.py
  • vera/verifier.py

Comment thread tests/test_verifier.py
Comment thread tests/test_verifier.py
… test

Replace inline parse_to_ast/typecheck/verify sequences in 11 tests across
TestStringLengthVerification, TestStringPredicateVerification, and
TestRefinedTypeParamSorts with the existing _verify() helper, removing
~33 lines of duplicated plumbing.

Strengthen test_refined_bool_param_verifies_cleanly: replace ensures(true)
(vacuous — proves regardless of sort) with requires(@Flag.0)/ensures(@Bool.result)
so the test actually exercises BoolSort handling. With IntSort, Z3 cannot
treat the parameter as a boolean guard; with BoolSort the contract is Tier 1.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 9: Update the test totals row in TESTING.md by replacing the outdated
"3,239 passed" with the correct "3,247 passed" and ensure the top-level total
count (the "3,250 across 27 files" number) is reconciled with the PR run output
(adjust the overall total to match passed + skipped if necessary) so the table
reflects "3,247 passed, 11 skipped" exactly.

In `@tests/test_verifier.py`:
- Around line 1703-1704: Update the docstring on class
TestStringLengthVerification to reflect that string_length() for `@String`
arguments uses the native z3.Length(...) translation rather than an
uninterpreted function; mention that uninterpreted functions are only used as a
fallback for non-string sorts so the docstring accurately describes current SMT
behaviour.
🪄 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: e9ad389b-d707-47f1-87d0-16abd535a1c6

📥 Commits

Reviewing files that changed from the base of the PR and between af0a325 and df9e084.

📒 Files selected for processing (2)
  • TESTING.md
  • tests/test_verifier.py

Comment thread TESTING.md
Comment thread tests/test_verifier.py Outdated
…eted fn

The class docstring said 'via uninterpreted function' but string_length() now
uses z3.Length() for SeqSort (String) arguments, giving Z3 full native string
theory semantics. The uninterpreted function is only a fallback for non-SeqSort
sorts, which is never reached in practice for @string parameters.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
TESTING.md (1)

9-9: ⚠️ Potential issue | 🟡 Minor

Overview test totals are stale against this PR’s recorded run.

Line 9 still says 3,239 passed, but the PR metadata for this change set reports 3,247 passed and 11 skipped. Please update the passed count and the aggregate test total so the row remains internally consistent.

📝 Proposed fix
-| **Tests** | 3,250 across 27 files (~34,000 lines of test code; 3,239 passed, 11 skipped) |
+| **Tests** | 3,258 across 27 files (~34,000 lines of test code; 3,247 passed, 11 skipped) |

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` at line 9, Update the test summary row in TESTING.md to reflect
the new counts: change the passed count from 3,239 to 3,247 and the aggregate
total from 3,250 to 3,258 (since 3,247 passed + 11 skipped = 3,258), keeping the
existing table formatting and the rest of the text intact so the row remains
internally consistent.
🤖 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_verifier.py`:
- Around line 1741-1749: The test test_string_length_comparison_tier1 currently
only requires(`@Int.0` >= 0) and ensures(true), so it never exercises the contract
path that calls string_length in the longer_than function; update the test to
assert the actual postcondition by replacing the trivial ensures(true) (or
adding an assertion after invocation) with ensures(string_length(`@String.0`) >
`@Int.0`) or otherwise invoke longer_than in a way that forces evaluation of
string_length so the Tier‑1 encoding is exercised; locate the longer_than
function and the test case name test_string_length_comparison_tier1 to apply
this change.

---

Duplicate comments:
In `@TESTING.md`:
- Line 9: Update the test summary row in TESTING.md to reflect the new counts:
change the passed count from 3,239 to 3,247 and the aggregate total from 3,250
to 3,258 (since 3,247 passed + 11 skipped = 3,258), keeping the existing table
formatting and the rest of the text intact so the row remains internally
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: b92502f7-a726-4f05-a20b-2c35859142a9

📥 Commits

Reviewing files that changed from the base of the PR and between df9e084 and a80e0ef.

📒 Files selected for processing (2)
  • TESTING.md
  • tests/test_verifier.py

Comment thread tests/test_verifier.py
…ng_length

Replace ensures(true) (vacuous) with ensures(string_length(@String.0) >= 0) so
string_length is exercised in a contract clause, not just the function body.
Z3 proves this via native z3.Length() semantics, giving >=2 Tier 1 contracts.

Co-Authored-By: Claude <noreply@anthropic.invalid>
@aallan aallan merged commit 764e9d4 into main Apr 13, 2026
19 checks passed
@aallan aallan deleted the fix/smt-string-float64-params branch April 13, 2026 23:00
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.

1 participant