ogar-loco: proof-carrying vocabularies, the 3-ref min_shape fix, and the permanent floor - #240
Merged
Merged
Conversation
…the permanent floor External review of #239 surfaced the panic edge: Program traversal indexed call.values[slot] with slot driven by v.body_refs(), so an unvalidated vocabulary claiming more than three references panicked. Conformance would have rejected that vocabulary, but nothing forced conformance to have run before traversal. - conformance::validate(v) -> CheckedVocabulary<V>: the proof-carrying wrapper, constructible only through validation. references_are_resolvable and branches_of now require it, turning the test-time convention into a type. The wrapper delegates ALL Vocabulary methods (composed included -- conformance validated the composed answers, so re-deriving from the hooks could answer differently than what was validated). - Fixing the edge surfaced a second defect: the default min_shape mapped everything >=2 refs to Triples, wrongly rejecting a LEGAL three-reference domain function (three refs fit Quads exactly). Fixed in the trait default and in shared_core, pinned two-sided: the three-ref vocabulary conforms and defaults to Quads; the hostile 200-ref vocabulary is refused by validate even with a Quads override (no shape holds more than three value bytes). - DOMAIN_FLOOR declared PERMANENT stored-byte ABI: 0x00..=0x8F universal forever, 0x90..=0xFF vocabulary-local forever. Moving the floor would silently reinterpret persisted programs, so it is documented as permanent and pinned by a const assert whose message names why the 'fix' would be wrong. Gates: fmt, clippy -D warnings, tests (38 loco + 7 blockly), rustdoc -D warnings -- all green.
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_5959b23e-0cc8-423e-a49e-3a38a3db5b1b) |
AdaWorldAPI
marked this pull request as ready for review
August 5, 2026 12:55
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hardening pass on #239, from the external review of the merge — both review findings implemented, plus a third defect the fix itself surfaced.
1. The
>3 body_refspanic edge — closed by typeProgram::references_are_resolvable/branches_ofindexedcall.values[slot]withslotdriven byv.body_refs(); an unvalidated vocabulary claiming more than three references panicked. Conformance would have rejected that vocabulary — but nothing forced conformance to have run.Fix, per the review's "better still" option:
conformance::validate(v) → CheckedVocabulary<V>, constructible only through validation. The traversal methods now require the wrapper, so holding it IS the proof thatbody_refs ≤ 3everywhere (the shape check bounds it: noLaneShapeholds more than three value bytes). The wrapper delegates allVocabularymethods, composed included — conformance validated the composed answers, so re-deriving from the hooks could answer differently than what was validated.debug_asserts remain as the belt.2. A defect the fix surfaced: the default
min_shapewrongly rejected THREE referencesThe trait default mapped everything ≥2 refs to
Triples— so a legal three-reference domain function (fitsQuadsexactly) failed conformance unless the vocabulary overrodemin_shape. Fixed in the trait default andshared_core(2 → Triples,3+ → Quads), pinned two-sided:three_body_references_are_legal_and_default_to_quads— the conforming 3-ref vocabulary passes and defaults toQuads(would have failed before the fix);validate_refuses_a_vocabulary_whose_refs_exceed_a_calls_capacity— the hostile 200-ref vocabulary is refused even with aQuadsoverride, and traversal is unreachable without the wrapper it refused to construct.3.
DOMAIN_FLOORis PERMANENT stored-byte ABI0x00..=0x8Funiversal forever;0x90..=0xFFvocabulary-local forever. Moving the floor would silently reinterpret every persisted program — the layout-reclaim hazard the reserve-don't-reclaim rule forbids. Now documented on the constant and pinned by aconstassert whose failure message says why the "fix" would be wrong.Gates
cargo fmt --check/clippy --all-targets --all-features -- -D warnings/ tests (38 ogar-loco + 7 ogar-blockly) /RUSTDOCFLAGS="-D warnings" cargo doc— all green, scoped-p ogar-loco -p ogar-blockly. Plan ledger appended (docs/BLOCK-EDITOR-PLAN.md§ W6 hardening).🤖 Generated with Claude Code
https://claude.ai/code/session_011DN5odWu4eisdevH9bPWyz
Generated by Claude Code