Skip to content

feat(corpus): third witness IFClite and the full-project export artifact g-2026-0002 - #1

Merged
DrunkOnJava merged 1 commit into
mainfrom
feat/third-witness-ifclite-and-g-2026-0002
Aug 30, 2026
Merged

feat(corpus): third witness IFClite and the full-project export artifact g-2026-0002#1
DrunkOnJava merged 1 commit into
mainfrom
feat/third-witness-ifclite-and-g-2026-0002

Conversation

@DrunkOnJava

@DrunkOnJava DrunkOnJava commented Aug 30, 2026

Copy link
Copy Markdown
Owner

Syncs the umbrella with rvt-rs #205 (dbf2347) and #207 (bdddd52).

The edge is still one edge — RVT → IFC via the Revit 2024 exporter — but it now carries two artifacts and three independent reading lineages, and the second artifact is the one that says how much the first was worth.

The third witness: IFClite

ifc-lite is adopted: crate ifc-lite-core 7.1.1 (MPL-2.0, Rust, upstream LTplus-AG/ifc-lite), a byte-level STEP scanner sharing no code with IfcOpenShell. That resolves the registry's one open entry, which carried a wrong license (MIT) against a bare ifc-lite slug and was gate-ineligible under SPEC.md §19 note 4. registry/README.md now records what it resolved to instead of what was unknown.

witnesses/ifc-lite/ vendors the glue from rvt-rs tools/ci/witness-ifc-lite/ at dbf2347. Only the manifest-reading path differs: it takes the bridge file directly and checks bridge.file_hash_sha256 / bytes / schema, the same contract tools/witness-ifcopenshell.py already implements. Counting, canonicalization, hashing and the observation shape are unchanged — which is why the committed observations still hash identically across both repositories. It is its own Cargo workspace root, so MPL-2.0 code never links into the Apache-2.0 tree. It is glue, not a decoder: the umbrella still parses no format bytes itself.

g-2026-0002: the full project export

Same .rvt, same committed rvt-rs observation, different bridge file: 2024_Core_Interior_slim.ifc, 1,665,968 bytes, 19,879 entities, against g-2026-0001's 20 KB element fixture. The origin URL was verified by fetching and hashing.

The result is the honest one:

Category Export rvt-rs Status
walls (IFCWALL) 360 0 known_gap, rvt-rs#30
doors (IFCDOOR) 132 0 known_gap, rvt-rs#32
columns (IFCCOLUMN) 256 0 known_gap, rvt-rs#204
rooms/spaces (IFCSPACE) 116 18 known_gap, rvt-rs#33
floors (IFCSLAB) 80 64 known_gap, rvt-rs#31
levels (IFCBUILDINGSTOREY) 15 12 decoder_baseline, rvt-rs#33
windows (IFCWINDOW) 6 0 known_gap, rvt-rs#32
materials (IFCMATERIAL) 10 102 known_gap, rvt-rs#34 — over-count
property sets (IFCPROPERTYSET) 0 64 known_gap, rvt-rs#35 — over-count against zero

So the claimed surface is four fields and nine categories are excluded first-class with their tracking issues. The excluded table is the deliverable, not a footnote. levels is retained here though it is dropped in g-2026-0001: there it has no source_ifc_type, here it has one and both bridge readers see it.

Gate

verdict.yml installs Rust stable (dtolnay/rust-toolchain, SHA-pinned), caches with Swatinem/rust-cache, builds the glue with --locked and runs it for every artifact alongside IfcOpenShell. A manifest bridge witness now declares runner_kind (python or cargo); tools/replay.sh dispatches on the same field.

tools/check-registry.py gained a §9.6 pin check for anything the umbrella builds itself: the registry version, the exact Cargo pin, a committed Cargo.lock, the manifest version_pin and the binary's own WITNESS_ID/WITNESS_VERSION must be one number. That mirrors rvt-rs's ifc_lite_gate_is_wired_and_version_pinned, which cannot be imported here.

SPEC 1.0.1

SPEC.md is a byte-identical copy of rvt-rs docs/octetproof-spec.md at bdddd52. Patch release, non-semantic: §19 note 4 records the ifc-lite resolution, and the header and §16.3 point at this repository instead of calling it planned. No schema, diff-function or provenance change, so every document here still declares schema_version: "1.0.0".

Local verification

$ python3 tools/validate-corpus.py
corpus: 6 observation(s) and 2 verdict(s) conform to the 1.0.0 schemas

$ 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/index.py --check
corpus/MANIFEST_INDEX.json: chain head 7a8a62ca4449… ok (2 artifact(s))

$ tools/replay.sh corpus/artifacts/g-2026-0001
g-2026-0001: PASS — witnesses ifc-lite, ifcopenshell, rvt-rs
  surface: 8 fields, excluded: 4, 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)

$ tools/replay.sh corpus/artifacts/g-2026-0002
g-2026-0002: PASS — witnesses ifc-lite, ifcopenshell, rvt-rs
  surface: 4 fields, excluded: 9, 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)

Both bridge observations hash identically to each other on both artifacts (8cf40465… and 882e1e0f…): two unrelated STEP readers, different languages, byte-identical canonical payloads. That corroborates the bridge-side reading and nothing more — entity_counts is a shallow surface.

Chain head 7a8a62ca4449a3e22c31dfbb6eff44fe73a0fde3f776d9f1ab7c279e99279842; g-2026-0002's prev_hash is the canonical hash of g-2026-0001's entry.

https://claude.ai/code/session_01BaHKf1Rw5aJBGK5y3xmx7C


Note

Medium Risk
Changes expand the fail-closed CI gate (Rust builds, crates.io/PyPI pins, corpus verdict hashes) and license isolation for MPL glue; mistakes in pinning or runner dispatch would break replay for all artifacts.

Overview
Adds a third gated witness (IFClite ifc-lite-core 7.1.1, MPL-2.0) and a second golden artifact (g-2026-0002) on the same RVT→IFC edge, so the corpus now exercises three lineages and contrasts the thin 20 KB IFC fixture with the full ~1.6 MB project export.

IFClite is adopted in registry/witnesses.json (upstream/license resolved to LTplus-AG/ifc-lite / MPL-2.0). New witnesses/ifc-lite/ is separate-workspace Rust glue (pinned Cargo.lock, --locked builds) that emits §6.2 observations; g-2026-0001 gains runner_kind and an ifc-lite bridge entry plus committed observation and recomputed verdict. g-2026-0002 adds manifest, observations, verdict, PROVENANCE.md, and an updated MANIFEST_INDEX chain.

Gate and replay now dispatch bridge witnesses by runner_kind (python vs cargo): verdict.yml installs Rust stable, caches witnesses/ifc-lite, builds cargo runners, and runs both bridge processes; tools/replay.sh mirrors that. tools/check-registry.py enforces §9.6 pin alignment for cargo witnesses (registry version, Cargo.toml, manifest version_pin, WITNESS_* in main.rs).

Docs/spec: SPEC.md 1.0.1 (patch: umbrella link, ifc-lite license note); README/CONTRIBUTING/NOTICE/corpus docs updated for two artifacts, three witnesses, and replay requiring Rust ≥ 1.87.

Reviewed by Cursor Bugbot for commit 278a2c4. Configure here.

…act g-2026-0002

Syncs the umbrella with rvt-rs PR #205 (dbf2347) and PR #207 (bdddd52).

The edge is still one edge — RVT to IFC via the Revit 2024 exporter — but it
now carries two artifacts and three independent reading lineages, and the
second artifact is the one that says how much the first was worth.

## The third witness: IFClite

`ifc-lite` is adopted: crate `ifc-lite-core` 7.1.1 (MPL-2.0, Rust, upstream
LTplus-AG/ifc-lite), a byte-level STEP scanner sharing no code with
IfcOpenShell. That resolves the registry's one open entry, which carried a
wrong license (MIT) against a bare `ifc-lite` slug and was gate-ineligible
under SPEC.md 19 note 4. registry/README.md now records what it resolved to
instead of what was unknown.

`witnesses/ifc-lite/` vendors the glue from rvt-rs `tools/ci/witness-ifc-lite/`
at dbf2347. Only the manifest-reading path differs: it takes the bridge file
directly and checks `bridge.file_hash_sha256` / `bytes` / `schema`, the same
contract `tools/witness-ifcopenshell.py` already implements. Counting,
canonicalization, hashing and the observation shape are unchanged, which is
why the committed observations still hash identically across both repos. It
is its own Cargo workspace root, so MPL-2.0 code never links into the
Apache-2.0 tree; it is glue, not a decoder — the umbrella still parses no
format bytes itself.

## g-2026-0002: the full project export

Same `.rvt`, same committed rvt-rs observation, different bridge file:
`2024_Core_Interior_slim.ifc`, 1,665,968 bytes, 19,879 entities, against
g-2026-0001's 20 KB element fixture. Origin URL verified by fetch and hash.

The result is the honest one. Both bridge readers count 360 IFCWALL, 132
IFCDOOR, 256 IFCCOLUMN, 116 IFCSPACE, 80 IFCSLAB and 15 IFCBUILDINGSTOREY
where rvt-rs recovers 0, 0, 0, 18, 64 and 12. So the claimed surface is four
fields, nine categories are excluded first-class with their rvt-rs tracking
issues, and the excluded table is the deliverable rather than a footnote.
`levels` is retained here though it is dropped in g-2026-0001: there it has no
`source_ifc_type`, here it has one and both bridge readers see it.

## Gate

verdict.yml installs Rust stable (dtolnay/rust-toolchain, SHA-pinned), caches
with Swatinem/rust-cache, builds the glue with `--locked` and runs it for
every artifact alongside IfcOpenShell. A manifest bridge witness now declares
`runner_kind` (`python` or `cargo`); replay.sh dispatches on the same field.

`tools/check-registry.py` gained a 9.6 pin check for anything the umbrella
builds itself: the registry `version`, the exact Cargo pin, a committed
Cargo.lock, the manifest `version_pin` and the binary's own WITNESS_ID /
WITNESS_VERSION must be one number. That mirrors rvt-rs's
`ifc_lite_gate_is_wired_and_version_pinned`, which cannot be imported here.

## SPEC 1.0.1

SPEC.md is a byte-identical copy of rvt-rs `docs/octetproof-spec.md` at
bdddd52. Patch release, non-semantic: 19 note 4 records the ifc-lite
resolution, and the header and 16.3 point at this repository instead of
calling it planned. No schema, diff-function or provenance change, so every
document here still declares `schema_version: "1.0.0"`.

## Local verification

    $ python3 tools/validate-corpus.py
    corpus: 6 observation(s) and 2 verdict(s) conform to the 1.0.0 schemas

    $ 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/index.py --check
    corpus/MANIFEST_INDEX.json: chain head 7a8a62ca4449... ok (2 artifact(s))

    $ OCTETPROOF_PYTHON=.../ifcos/bin/python tools/replay.sh corpus/artifacts/g-2026-0001
    bridge: _replay/g-2026-0001/2024_Core_Interior.ifc 20392 bytes sha256 d07c7462aee2... ok
    == bridge witness: ifcopenshell (python, tools/witness-ifcopenshell.py)
    observation_hash_sha256: 8cf4046509bb788406e93261f0dcb10708fbf33ae195d12f8ddc99b41a93398f
    == bridge witness: ifc-lite (cargo, witnesses/ifc-lite)
    cross-witness: IFClite agrees with the manifest for every source_ifc_type
    corpus: 9 observation(s) and 2 verdict(s) conform to the 1.0.0 schemas
    g-2026-0001: PASS - witnesses ifc-lite, ifcopenshell, rvt-rs
      surface: 8 fields, excluded: 4, 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
    bridge: _replay/g-2026-0002/2024_Core_Interior_slim.ifc 1665968 bytes sha256 bfdf36ffb0bb... ok
    == bridge witness: ifcopenshell (python, tools/witness-ifcopenshell.py)
    IFCBUILDINGSTOREY 15  IFCWALL 360  IFCSLAB 80  IFCROOF 0  IFCDOOR 132
    IFCWINDOW 6  IFCSPACE 116  IFCCOLUMN 256  IFCBEAM 0  IFCFLOWTERMINAL 0
    IFCMATERIAL 10  IFCUNITASSIGNMENT 1  IFCPROPERTYSET 0
    observation_hash_sha256: 882e1e0f7d546bed2b4cf94e0cb8867f257321235203adcb0ed48e8ef521b4f8
    == bridge witness: ifc-lite (cargo, witnesses/ifc-lite)
    cross-witness: IFClite agrees with the manifest for every source_ifc_type
    corpus: 9 observation(s) and 2 verdict(s) conform to the 1.0.0 schemas
    g-2026-0002: PASS - witnesses ifc-lite, ifcopenshell, rvt-rs
      surface: 4 fields, excluded: 9, 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

Both bridge observations hash identically to each other on both artifacts
(8cf40465... and 882e1e0f...): two unrelated STEP readers, different
languages, byte-identical canonical payloads. That corroborates the
bridge-side reading and nothing more - `entity_counts` is a shallow surface.

Chain head 7a8a62ca4449a3e22c31dfbb6eff44fe73a0fde3f776d9f1ab7c279e99279842;
g-2026-0002's `prev_hash` is the canonical hash of g-2026-0001's entry.

Claude-Session: https://claude.ai/code/session_01BaHKf1Rw5aJBGK5y3xmx7C
@cursor

cursor Bot commented Aug 30, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot 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_fdfb4432-3b47-47e5-aff0-620e0e31e8f8)

@DrunkOnJava
DrunkOnJava merged commit cbccc5c into main Aug 30, 2026
5 checks passed
@DrunkOnJava
DrunkOnJava deleted the feat/third-witness-ifclite-and-g-2026-0002 branch August 30, 2026 11:42
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