corpus: mirror rvt-rs #226/#230/#231 — relations and storeys join the surface; spec 1.1.0 - #6
Merged
Merged
Conversation
… surface; spec 1.1.0
Brings the umbrella to OctetProof 1.1.0 and mirrors the current rvt-rs corpus
state. The protocol gains two additive field classes and the corpus gains two
agreement classes it did not have: topology, and labels-with-units.
Protocol (byte-identical copies from rvt-rs, the same policy as the registry)
SPEC.md 1.0.2 -> 1.1.0
schemas/witness-observation.schema.json schema_version enum ["1.0.0","1.1.0"],
optional observation.relations and
observation.storeys
schemas/witness-verdict.schema.json diff only_in_a / only_in_b
registry/witnesses.json already byte-identical, unchanged
1.1.0 is minor and additive (SPEC.md 16.1, 20). The diff function, the
canonicalizer, the provenance model and the verdict statuses are unchanged; a
1.0.0 observation is still valid input.
Gate (tools/)
verdict.py ports the two field classes from rvt-rs
tools/ci/witness-verdict.py. A `relations` category
carrying relation_ifc_type contributes
relations.<TYPE>; a `storeys` category carrying
storey_ifc_type contributes storeys.<TYPE>. Both are
exact sorted-multiset equality with no tolerance
concept (7.2); a diff carries the set sizes in
value_a / value_b plus only_in_a / only_in_b and
tolerance_applied: false. The surface is built counts
-> relations -> storeys, which is the order the
committed verdict records. A witness compared on a
set-valued class must declare it in
semantic_surface_covered, else MANIFEST_ERROR. The
umbrella-manifest shape is kept: semantic_surface and
excluded stay explicit and now cross-check against all
three blocks, so a status flip is still MANIFEST_ERROR
rather than a silent surface change.
witness-ifcopenshell.py
ports the relation and storey extraction. The storey
elevation is resolved through
ifcopenshell.util.unit.calculate_unit_scale and
rendered in feet at 1e-6 as a fixed six-decimal
string, -0 normalised to 0.
jsonschema_mini.py implements maxItems, the one keyword the new schemas
introduce. It fails loudly on unimplemented keywords,
so without this the corpus would not validate at all.
validate-corpus.py reports against the 1.1.0 schemas.
compare-verdict.py, fetch.py, index.py, check-registry.py, replay.sh
unchanged; the new fields needed nothing from them and
the 9.6 pin is still one number (ifc-lite-core =7.1.1).
Witness glue (witnesses/ifc-lite/)
Re-mirrored from tools/ci/witness-ifc-lite/ in DrunkOnJava/rvt-rs at
a0044f4a11361626c2a4b9fb93c4696ac6b1c6e6 (PR #230): fills_element_pairs and
building_storey_set, the latter resolving units with
ifc_lite_core::extract_length_unit_scale. The only deviation from upstream
remains the manifest-reading path (bridge.file_hash_sha256 / bridge.bytes /
bridge.schema, bridge file passed directly). Cargo.lock unchanged, no new
dependency, version pin unchanged.
Corpus
Observations and verdicts for both artifacts copied verbatim from
research/witness/<alias>/ in rvt-rs. Both manifests rebuilt from the
project-count fixtures under the documented drop rules (decoder_* dropped, a
category kept iff it carries its block's type key), gaining `relations` and
`storeys` blocks and `levels` as `known`. Both declare
octetproof_version 1.1.0, because both now carry 1.1.0 blocks.
MANIFEST_INDEX.json regenerated: chain head 5e6a64228083.
g-2026-0001 4 surface fields, 9 excluded -> 6 surface, 10 excluded
g-2026-0002 10 surface fields, 4 excluded -> 13 surface, 3 excluded
g-2026-0002 now claims 360 IFCWALL, 256 IFCCOLUMN, 132 IFCDOOR, 80 IFCSLAB,
20 IFCSHADINGDEVICE, 15 IFCBUILDINGSTOREY, 6 IFCWINDOW, 1 IFCUNITASSIGNMENT
and three zeroes, plus 138 IfcRelFillsElement [host Tag, filling Tag] pairs
and the 15 [name, elevation] storeys. Three known_gap exclusions remain:
IFCSPACE (116 vs 18), IFCMATERIAL (10 vs 102) and IFCPROPERTYSET (0 vs 854).
g-2026-0001 stays thin — three of its five counts are zero on both sides —
with one exception worth the record: Revit writes the complete fifteen-storey
spatial hierarchy into even a one-element 20 KB export, so
storeys.IFCBUILDINGSTOREY is as strong on the fixture as on the full export.
relations.IFCRELFILLSELEMENT goes the other way and is excluded
decoder_baseline: that fixture carries no IfcRelFillsElement at all.
Local verification, clean _replay, both artifacts end to end
$ OCTETPROOF_PYTHON=.../ifcos/bin/python tools/replay.sh corpus/artifacts/g-2026-0001
corpus: 9 observation(s) and 2 verdict(s) conform to the 1.1.0 schemas
g-2026-0001: PASS - witnesses ifc-lite, ifcopenshell, rvt-rs
surface: 6 fields, excluded: 10, diffs: 0
replay ifc-lite: match
replay ifcopenshell: match
replay rvt-rs: match
verdict matches the committed record (ignored: artifact_id, replay, timestamp, verdict_hash_sha256)
== replay OK: g-2026-0001 PASS, observations replayed, verdict matches
$ OCTETPROOF_PYTHON=.../ifcos/bin/python tools/replay.sh corpus/artifacts/g-2026-0002
corpus: 9 observation(s) and 2 verdict(s) conform to the 1.1.0 schemas
g-2026-0002: PASS - witnesses ifc-lite, ifcopenshell, rvt-rs
surface: 13 fields, excluded: 3, diffs: 0
replay ifc-lite: match
replay ifcopenshell: match
replay rvt-rs: match
verdict matches the committed record (ignored: artifact_id, replay, timestamp, verdict_hash_sha256)
== replay OK: g-2026-0002 PASS, observations replayed, verdict matches
$ python3 tools/index.py --check
corpus/MANIFEST_INDEX.json: chain head 5e6a64228083... ok (2 artifact(s))
$ python3 tools/check-registry.py
witnesses.json: valid - 11 nodes, 47 witnesses, 7 artifacts, 3 edges, 9 agreements; 2 corpus manifest(s) resolve
$ python3 tools/validate-corpus.py
corpus: 6 observation(s) and 2 verdict(s) conform to the 1.1.0 schemas
Both bridge witnesses hash identically on both artifacts - 99e6cd7a on
g-2026-0001, 5a101408 on g-2026-0002 - across all 14 entity types, all 138
relation pairs and all 15 storey pairs, including the unit resolution, which
each reader performed with its own code.
Fail-closed paths exercised, not just assumed: mutating one relation host tag
and one storey elevation in a fresh ifc-lite observation produces DISAGREE
with only_in_a / only_in_b naming exactly the changed members; stripping
`storeys` from a witness's semantic_surface_covered produces MANIFEST_ERROR; a
three-element pair and an out-of-enum schema_version are both rejected by
jsonschema_mini.
Docs: README's "what exists today" rewritten around the three agreement
classes with the real numbers, both PROVENANCE.md files rewritten (witness-set
hashes, surfaces, exclusion tables), corpus/README's departure table updated
for the 1.1.0 blocks and the octetproof_version policy, tools/README gains the
field-class table and the reasons the storey elevation is a string and storey
names are not Unicode-normalised, CONTRIBUTING's coverage vocabulary extended.
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_02b93722-8fdd-45e7-98d0-2e57a6d796d0) |
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.
Brings the umbrella to OctetProof 1.1.0 and mirrors the current rvt-rs corpus state (rvt-rs main
5da2570, PRs #226 / #230 / #231). The protocol gains two additive field classes; the corpus gains two agreement classes it did not have — topology, and labels-with-units.The result
g-2026-0001(20 KB element fixture)g-2026-0002(full project export)g-2026-0002now claims, agreed exactly by all three witnesses at tolerance 0: 360IFCWALL, 256IFCCOLUMN, 132IFCDOOR, 80IFCSLAB, 20IFCSHADINGDEVICE, 15IFCBUILDINGSTOREY, 6IFCWINDOW, 1IFCUNITASSIGNMENT, three zeroes — plus 138IfcRelFillsElement[host Tag, filling Tag]pairs and the 15[name, elevation]storeys,Basement 2at −40 ft throughLevel 13at 185.5 ft.Three
known_gapexclusions remain, and they are the deliverable:IFCSPACE116 vs 18,IFCMATERIAL10 vs 102 (an over-count),IFCPROPERTYSET0 vs 854 (an over-count against zero). That table used to have nine rows.g-2026-0001stays thin — three of its five counts are zero on both sides — with one exception worth recording: Revit writes the complete fifteen-storey spatial hierarchy into even a one-element 20 KB export, sostoreys.IFCBUILDINGSTOREYis as strong on the fixture as on the 19,879-entity project export.relations.IFCRELFILLSELEMENTgoes the other way and is excludeddecoder_baseline: that fixture carries noIfcRelFillsElementat all, so the two sides of that edge are not comparable on it.What changed
Protocol —
SPEC.md1.0.2 → 1.1.0 and both schemas, byte-identical copies from rvt-rs (the same policy as the registry).schema_versionnow an enum of["1.0.0","1.1.0"]; optionalobservation.relations/observation.storeys; verdict diffs gainonly_in_a/only_in_b. Minor and additive (§16.1, §20) — the diff function, canonicalizer, provenance model and status vocabulary are unchanged, and a 1.0.0 observation is still valid input.registry/witnesses.jsonwas already byte-identical and is untouched.Gate —
tools/verdict.pyports both field classes fromtools/ci/witness-verdict.py: exact sorted-multiset equality, no tolerance concept, diffs carrying set sizes plus the members each side holds alone. The surface is built counts → relations → storeys, the order the committed verdict records. A witness compared on a set-valued class must declare it insemantic_surface_coveredor the verdict isMANIFEST_ERROR. The umbrella-manifest shape is kept —semantic_surface/excludedstay explicit and now cross-check against all three blocks.tools/witness-ifcopenshell.pyports the extraction, resolving the elevation withifcopenshell.util.unit.tools/jsonschema_mini.pyimplementsmaxItems, the one keyword the new schemas introduce — it fails loudly on unimplemented keywords, so without it the corpus would not validate at all.compare-verdict.py,fetch.py,index.py,check-registry.pyandreplay.shneeded nothing.Witness glue —
witnesses/ifc-lite/re-mirrored from rvt-rsa0044f4(PR #230), gainingfills_element_pairsandbuilding_storey_set(units viaifc_lite_core::extract_length_unit_scale). The only deviation from upstream remains the manifest-reading path.Cargo.lockunchanged, no new dependency, §9.6 pin still one number:ifc-lite-core = "=7.1.1".Corpus — observations and verdicts copied verbatim from
research/witness/<alias>/; both manifests rebuilt from the project-count fixtures under the documented drop rules, gainingrelationsandstoreysblocks andlevelsasknown; both declareoctetproof_version: "1.1.0"because both now carry 1.1.0 blocks.MANIFEST_INDEX.jsonregenerated, chain head5e6a64228083.Local verification — clean
_replay, both artifacts end to endplus
tools/index.py --check(chain head ok),tools/check-registry.py(47 witnesses, 2 manifests resolve, §9.6 pin held) andtools/validate-corpus.py(6 observations + 2 verdicts conform to the 1.1.0 schemas).Both bridge witnesses hash identically on both artifacts —
99e6cd7a…on g-2026-0001,5a101408…on g-2026-0002 — across all 14 entity types, all 138 relation pairs and all 15 storey pairs, including the unit resolution, which each reader performed with its own code.Fail-closed paths exercised, not assumed. Mutating one relation host tag and one storey elevation in a fresh ifc-lite observation produces
DISAGREEwithonly_in_a/only_in_bnaming exactly the changed members; strippingstoreysfrom a witness'ssemantic_surface_coveredproducesMANIFEST_ERROR; a three-element pair and an out-of-enumschema_versionare both rejected byjsonschema_mini.Docs
README's "what exists today" rewritten around the three agreement classes with the real numbers; both
PROVENANCE.mdfiles rewritten (witness-set hashes, surfaces, exclusion tables);corpus/READMEdeparture table updated for the 1.1.0 blocks and theoctetproof_versionpolicy;tools/READMEgains the field-class table and the reasons a storey elevation travels as a string and storey names are deliberately not Unicode-normalised; CONTRIBUTING's coverage vocabulary extended.Note
Medium Risk
Touches the verification gate’s diff logic and committed corpus verdicts; mistakes could pass wrong agreement or break CI replay, but the change is additive and schema-backward-compatible.
Overview
OctetProof 1.1.0 adds two comparable surface classes —
relations(sorted host/filling pair multisets) andstoreys(sorted[name, elevation-in-feet]sets with per-file unit normalization) — and this PR lands the spec, schemas, gate, witnesses, and golden corpus on that release.Protocol & CI:
SPEC.mdand observation/verdict JSON Schemas move to 1.1.0 (schema_versionaccepts1.0.0and1.1.0; optionalobservation.relations/observation.storeys; verdict diffs may includeonly_in_a/only_in_b)..github/workflows/verdict.ymland docs now validate against 1.1.0 schemas.Gate & witnesses:
tools/verdict.pydiffs the new set-valued fields with exact multiset equality and requires witnesses to declarerelations/storeysinsemantic_surface_coveredor failMANIFEST_ERROR.tools/witness-ifcopenshell.pyemits the new payload keys;tools/jsonschema_mini.pygainsmaxItemsfor pair-shaped arrays.witnesses/ifc-lite/is re-mirrored from rvt-rs (PR #230) with relation and storey extraction.Corpus: Both artifacts declare
octetproof_version: "1.1.0", gainrelations/storeysmanifest blocks, and ship regenerated observations and verdicts (updated hashes;MANIFEST_INDEXchain head refreshed). g-2026-0002 widens the claimed surface (e.g. walls, doors, slabs, 138IFCRELFILLSELEMENTpairs, 15 storeys; exclusions shrink from nine gaps to three). g-2026-0001 adds storey agreement on the thin fixture while excluding the relation field where the bridge has no fills.Reviewed by Cursor Bugbot for commit 9ef497e. Configure here.