Skip to content

FEAT-085 (#113): lattice laws for the bits domain, checked up to γ - #158

Merged
avrabe merged 1 commit into
mainfrom
feat-085-lattice-laws
Aug 26, 2026
Merged

FEAT-085 (#113): lattice laws for the bits domain, checked up to γ#158
avrabe merged 1 commit into
mainfrom
feat-085-lattice-laws

Conversation

@avrabe

@avrabe avrabe commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

First slice of #113. Also surfaces a second gate-coverage defect — filed as #157.

The gap, measured

18 join/meet functions across 8 domains. Exactly one domain (octagon) has any lattice-law test, and it checks commutativity + top-absorption on hand-picked values. No proptest/quickcheck/arbitrary/cargo-fuzz in the workspace.

This slice takes scry-sai-bits — 6 of the 18, the most intricate arithmetic (CRT, mod_inverse), already flagged by #105.

Checked up to γ, never structurally — and that's the point

Two encodings can denote the same set, so == on representations is too strong. This project has already been bitten by exactly that: the Verus join proof (FEAT-012) was false and unverified for months because it asserted join(a,b) == join(b,a) structurally, which fails for distinct bottom encodings.

These assert the semantic version over the exhaustive [0,256) domain the crate already sweeps.

The soundness-critical law is join_is_an_upper_bound_up_to_gamma. If a join drops an element, every fixpoint built on it under-approximates and the analyzer can report PROVEN-SAFE for something reachable. Commutativity, associativity, idempotence are hygiene; that one is the product. Its dual catches a meet that invents an element.

Mutation-checked surgically

meet → TOP    kills exactly meet_is_a_lower_bound_up_to_gamma + 1 pre-existing
join → self   also fires, but uninformative: `alpha` is itself built from join

The surgical one is the evidence; I'm reporting the broad one as uninformative rather than counting it.

No new dependency — the crate's existing alpha/contains/sweep idiom is reused rather than adding proptest to a published crate.

Credit: prompted by the Wasm Research Day Q&A, where a Binaryen engineer reported good luck fuzzing their own abstract domains for exactly this. Independent corroboration from a second group beats an in-house opinion that fuzzing would be good.

It also unearthed #157

Local verification was blocked by a pre-existing clippy error on main — a doc line beginning > 2^63, read as an unterminated blockquote. Confirmed pre-existing by stashing and re-running clean: main fails identically.

CI never saw it because the Clippy job covers four packages — the same four the Test job used before #141. Widening one per-package gate did not fix the pattern; I checked cargo test because that was the reported symptom and didn't ask the same question of the gate three lines above it.

Fixed here since it blocks this branch; the scope defect is #157.

Honest scope

One domain. 12 of the 18 functions — interval, pentagon, float, handle, segment, poly, viz — remain unguarded. This does not make #113 done.

tests 0 · clippy 0 · fmt 0 · rivet validate 0 · claim-check 0.

…gamma

scry#113 says the analyzer's frontend is unguarded. Measured: 18 join/meet
functions across 8 domains, exactly ONE domain (octagon) has any lattice-law
test, and it checks commutativity plus top-absorption on hand-picked values.
No proptest/quickcheck/arbitrary/cargo-fuzz anywhere in the workspace.

First slice: scry-sai-bits — 6 of the 18 functions, the most intricate
arithmetic (CRT, mod_inverse), and the domain scry#105 already flags.

CHECKED UP TO GAMMA, NEVER STRUCTURALLY, and that choice is the point. Two
encodings can denote the same set, so `==` on representations is too strong —
and this project has been bitten by exactly that: the Verus join proof
(FEAT-012) was FALSE and unverified for months because it asserted
`join(a,b) == join(b,a)` structurally, which fails for distinct bottom
encodings. These assert the semantic version over the exhaustive [0,256)
domain the crate already sweeps.

The soundness-critical law is join_is_an_upper_bound_up_to_gamma: if a join
drops an element, every fixpoint built on it under-approximates and the
analyzer can report PROVEN-SAFE for something reachable. Commutativity,
associativity and idempotence are hygiene; that one is the product. Its dual
catches a meet that INVENTS an element.

MUTATION-CHECKED SURGICALLY. Forcing `meet` to return TOP kills exactly
meet_is_a_lower_bound_up_to_gamma plus one pre-existing test, and nothing else.
A broad mutation (join returns self) also fires but is uninformative, because
`alpha` is itself built from join — so the surgical one is the evidence.

No new dependency: the crate already has an alpha/contains/sweep idiom, reused
rather than adding proptest to a published crate.

Credit: prompted by the Wasm Research Day Q&A, where a Binaryen engineer
reported good luck fuzzing their own abstract domains for exactly this —
independent corroboration from a second group, which beats an in-house opinion
that fuzzing would be good.

ALSO FIXES A PRE-EXISTING CLIPPY ERROR that blocked local verification here: a
doc line beginning `> 2^63` read as an unterminated Markdown blockquote.
Confirmed pre-existing by stashing and re-running on a clean tree — main fails
identically. CI never saw it because the Clippy job covers only four packages,
the same four the Test job used before scry#141. Filed as scry#157, with the
lesson that widening one per-package gate did not fix the pattern.

HONEST SCOPE: one domain. 12 of the 18 functions — interval, pentagon, float,
handle, segment, poly, viz — remain unguarded. This does not make scry#113 done.

tests=0 clippy=0 fmt=0 rivet=0 claim-check=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KkNzkNYzPh7366DkNijeNc
@github-actions

Copy link
Copy Markdown

📐 rivet artifact delta

PR: #158 Base SHA: 76162466

Validation

head — `rivet validate` result
  SR-11 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-12 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-13 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-2 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-3 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-4 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-5 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-6 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-7 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-8 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-9 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SYS-1 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-2 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-3 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-4 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-5 (system-req, status: accepted) — missing: sys-integration-verification
  → run `rivet validate --explain SR-1` to see which link type and source types satisfy a gap

Result: PASS (142 warnings)
Schemas: common@0.3.0 (embedded), dev@0.3.0 (embedded), research@0.1.0 (embedded), research-ext@0.1.0 (on-disk), safety-case@0.1.0 (embedded), aspice@0.2.0 (embedded)
base — `rivet validate` result (for comparison)
  SR-11 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-12 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-13 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-2 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-3 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-4 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-5 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-6 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-7 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-8 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SR-9 (sw-req, status: accepted) — missing: sw-integration-verification, unit-verification
  SYS-1 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-2 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-3 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-4 (system-req, status: accepted) — missing: sys-integration-verification
  SYS-5 (system-req, status: accepted) — missing: sys-integration-verification
  → run `rivet validate --explain SR-1` to see which link type and source types satisfy a gap

Result: PASS (141 warnings)
Schemas: common@0.3.0 (embedded), dev@0.3.0 (embedded), research@0.1.0 (embedded), research-ext@0.1.0 (on-disk), safety-case@0.1.0 (embedded), aspice@0.2.0 (embedded)

Artifact stats

base head
Total artifacts 254 255
full stats — head
Artifact summary:
  academic-reference               24
  competitive-analysis             11
  design-decision                  22
  feature                          85
  market-finding                    7
  requirement                      21
  safety-context                    3
  safety-goal                       5
  safety-justification              4
  safety-solution                   6
  safety-strategy                   1
  stakeholder-req                   3
  sw-req                           13
  sw-verification                  13
  sys-verification                  5
  system-req                        5
  technology-evaluation            12
  verification                     15
  TOTAL                           255

Orphan artifacts (no links): 12
  CA-001
  CA-002
  CA-003
  CA-004
  CA-005
  CA-006
  CA-007
  CA-008
  CA-009
  CA-010
  CA-011
  FEAT-078

Diagnostics: 0 error(s), 142 warning(s), 17 info(s)

Diff (base → head)

+ FEAT-085  v3.6 — Lattice laws, checked up to gamma, for the bits domain (scry#113 first slice)

1 added, 0 removed, 0 modified, 254 unchanged

~ NEW    WARN: [FEAT-085] prose mentions 'FEAT-012' but no typed link to it; add a link in `links:` or remove the mention
0 new errors, 0 resolved errors, 1 new warnings, 0 resolved warnings

AADL model — head

spar/scry.aadl: OK

Posted by the rivet-delta workflow. Informational only — does not gate the PR.

@avrabe
avrabe merged commit 7b36741 into main Aug 26, 2026
11 checks passed
@avrabe
avrabe deleted the feat-085-lattice-laws branch August 26, 2026 18:23
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