Witness tool identity in the Bifrost adapters and record Amendment A9 - #87
Merged
Conversation
Two adapters were publishing a version they never read. Both are fixed here, ahead of anything else: a report that asserts its own pin is the one defect a freeze cannot survive, because the assertion stays green while the binary underneath it moves. - **The modeling adapter** built every declined cell's retained rationale from `ModelingTool::pinned_identity()` — the constant `"Bifrost v0.10.6"`. Twenty of a language's twenty-four modeling assertions are such rationales, so twenty retained decisions per run named a build by memory rather than by measurement. - **The tool-native adapter** did the same for its report's `tool_version` *and* its `tool_build_identity` (`"Bifrost v0.10.6 built-in policy packs"`), which is worse in kind: that row declines all six templates, so it never invokes the analyzer at all and had no witnessed identity anywhere in the artifact. `modeling_version_identity` becomes `witness_tool_identity`, is called once per run **before** the population is walked — including runs whose every cell is declined — and is threaded into `modeling_unsupported_reason`, `native_unsupported_reason`, `native_activation`, and both partitions' retained decision documents (`pinned_tool_identity` → `witnessed_tool_identity`). The native report now records the witnessed version and the witnessed build identity alongside the activation shape. A declined cell is still decided from the template identity with no analyzer invocation over the fixture — that contract is untouched. What changes is that the *run* proves which binary it was pinned to. Two supporting rules: Bifrost's witnessing no longer degrades to `"unknown"` on a failed `--version` (a run whose every result is a capability decision has no other evidence, so an unwitnessed identity there is a report asserting a pin it never observed), and `pinned_identity()` is documented as a document reference that may not reach a report field or a rationale. Tests assert every retained reason names the identity the caller measured. No report is re-run here and no pinned-version statement moves: the evidence re-run lands with the re-pin. `cargo fmt --check` · `cargo test` (160) · `validate` (840 cases) · `validate-reports` (62). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
## Summary The preregistration declined category Z for Bifrost on a sentence in this repository's own adapter README — *"Sanitizer lowering is a future Bifrost CLI capability."* Measured against build `44d9a5be416432bf8ed414afd3ea0031245ebb57`, the sentence is false. Category Z moves to scored: Bifrost's set goes from two of the twelve templates to four, one of six categories to two. The measurement is four-way rather than two-way, because this is the direction in which a partition published by the engine's own vendor is least trustworthy — and it holds in all three wave-M1 languages: | Direction | Result | |---|---| | The grammar accepts `(sanitizer … :input … :output … :removes […])` | empty `diagnostics` | | The declaration suppresses | template 5's negative, 0 findings, `completion: complete` — not vacuous | | Removing it restores the flow | 1 finding, `definite` / `complete`, strong source-to-sink anchor | | Binding is by identity, not name shape | template 6's positive, through the *undeclared* `sanitize`, still reported | - **The other four cells were re-examined and do not move.** E and B have no surface at all — `:entry-points`, `:entry_points`, `:stores`, `:persistence` are each rejected as unknown fields. P and O have adjacent sections the grammar *does* accept (`:transforms`, `:external-models`), but a `transform` entry is a label-rewriting declaration rather than argument→return propagation, and acceptance is not lowering — the rule this document applied to a v0.9.5 schema pointer applies here too. That negative result is recorded in A9 rather than left implied. - **The three modeling policies gain the sanitizer stanza**, declaring `scrub` and deliberately not its sibling `sanitize`, keeping the artifact-declares-exactly-its-scored-categories invariant true in both directions: the runner test now *requires* `:sanitizers` and still forbids the four declined sections. - **The README is corrected, not quietly.** The retired sentence is quoted by the tool-native profile's own category-Z rationale, whose cell turns on the absent shipped endpoint catalog rather than on lowering; that document's amendment is not this one's to make, and A9 says so. Evidence is retained under `reports/raw/amendment-a9-bifrost-sanitizer/`, produced by `scripts/probe-bifrost-sanitizer-lowering.sh` — the same run-it-twice shape as the per-language load-bearing probes beside it. No report is re-run and no pinned-version statement moves. The retained modeling reports predate this amendment and still record category Z as `unsupported`; the scored evidence lands with the next evidence re-run, which the README and the two language rows say in place. ## Validation `cargo fmt --check` · `cargo test` (160) · `validate` (840 cases) · `validate-reports` (62). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… count `docs/adapters.md` and the Semgrep adapter README each restate the modeling partition's scored counts from outside the preregistration, so each said "Bifrost 2 of 12" and "Bifrost's one of six" after A9 promoted category Z. Both now name the amendment rather than the stale number. No pinned-version statement and no report changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The JavaScript and Java modeling rows quote a configuration hash for a run made against the pre-A9 artifact. Now that the committed policies carry the sanitizer declaration, a reader recomputing either hash gets a different value, so each row says plainly that it describes the retained pre-A9 run and that the re-run is pending. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wave N1's rows were written under a rule this branch overturns. #86 stated it in `run_native` and in four documents: a row the partition scores nothing for is *never invoked at all — not even for its version banner*, so its report carries `pinned_identity()`, and the Python row verified this by running against `/nonexistent/joern` and getting byte-identical evidence. Half of that rule is right and is preserved exactly: no declined cell is ever handed to the analyzer, and every outcome is still decided from the template identity before anything runs. The other half — that the report should then *assert* a version — is the defect the first commit of this branch fixes, and a 0 / 6 row is where it bites hardest: its twelve retained rationales are the whole of its evidence, so a constant would go on naming the previous pin after the binary underneath it moved. - `docs/native-profile.md` gains **the run-level identity is witnessed, including at 0 / 6** under outcome honesty, which separates the two halves: "before the tool is invoked" is a statement about cells; `tool_version` and `tool_build_identity` name which binary the run was pinned to, and a name is only evidence if something read it. Reading `--version` is not analyzing a fixture, so the three-way distinction is untouched. - The consequence is stated rather than hidden: a 0 / 6 run no longer completes against a nonexistent binary path. It fails, because a run that cannot witness its own pin has nothing truthful to put in those two fields. `docs/python-native.md` says so where its original verification stood. - The three adapter READMEs and `docs/java-native.md` say "never asked about a fixture" where they said "never invoked", which is what those runs actually establish. Also: both amendment preambles now state the interleaving explicitly — A8 in the tool-native profile is followed by A9 in the modeling matrix — since the single sequence now crosses documents in both directions. Rebased onto #86: main's shapes taken wholesale (the native partition's language dimension, `native_supported_templates(tool, language)`, the `{build} — {activation}` build-identity composition, and #86's all-three-languages population test), with the witnessing semantics re-applied on top. ## Validation `cargo fmt --check` · `cargo test` (162) · `validate` (852 cases) · `validate-reports` (66). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DavidBakerEffendi
added a commit
that referenced
this pull request
Aug 28, 2026
The v0.5.0 release: the Bifrost v0.10.7 fix cycle measured, and the first publication of the modeling (#15) and tool-native (#16) tiers. Four commits: the 66-report re-run at one fixture revision, the freeze manifest, the audited results, and the release notes + site snapshot. ## Freeze 852 cases / 66 reports / 4 analyzers — Bifrost v0.10.7 (build `44d9a5be`, identity witnessed per PR #87), CodeQL 2.26.3, Joern 4.0.610, Semgrep CE 1.174.0 — fixture revision `sha256:9df209ed…`, tag `v0.5.0` at main tip `7d688c6` (already pushed). `validate-freeze` green; the v0.4.0 manifest is superseded, never mutated. ## Fix-cycle headlines (derived from the frozen results, diffed against v0.4.0's) - Bifrost runner errors **22 → 0**; kernel decisive-correct **222 → 435**; smoke **115 → 117** of 118. - Ruby kernel decides for the first time: **0/58 → 21/58** (36 inconclusive, 1 FP). Rust `gap_contract` crash class (bifrost-dev#2638): 12 runner errors → 10 correct + 2 inconclusive. - Honest negatives, published: four **new** v0.10.7 false positives (bifrost-dev#2731 — C#/Go loop-carried, C#/Ruby infeasible-branch); the ten `element-object` crash cases resolve to *inconclusive*, not correct; the Java `direct-propagation` smoke-vs-kernel instability persists unreconciled on this build; inconclusive concentrations remain (Ruby 36, Kotlin 30, PHP/C++ 26, C#/TS 24). ## First tier publications - **Modeling** (benchmark-controlled): Bifrost's Amendment-A9 category-Z cells decide **12/12 correct** in their first scored run; CodeQL 24/24 ×3; Joern 14/16 (A2 partition, 4/6 categories); Semgrep 10/10 over its 5-template A3 partition. - **Tool-native**: CodeQL Java 11/12, Python 10/12, JavaScript 9/12 — misses are the preregistered hazards; Semgrep's vendored-snapshot asymmetry (Python 8/12 with 4 FPs via a shipped audit rule vs JS/Java 0/6); Bifrost and Joern decline-all with witnessed run identity (A10 rationale). - The landing page gains two separately fenced tier sections — the core-kernel filter that guarantees no pooling stays; declined tiers render as "declines the tier", never `0/N`; a Model profile column keeps benchmark-controlled and tool-native visually distinct; vendor colors keep the fixed identity map. ## Site v0.4.0 archived with evidenceRef pinned to `86a29e0`; v0.5.0 snapshot pages added; `/current` redirects to v0-5-0; `astro check` clean, 31 pages build. ## Verification `cargo fmt --check` · `cargo test` 162 · `validate` 852 · `validate-reports` 66 · `validate-freeze` green · `generate-results --check` current · `astro check` + build clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.
Pre-freeze corrections ahead of the v0.10.8 re-pin and v0.5.0 freeze. Nothing here binds a Bifrost version: the committed pin stays v0.10.6, no report bytes change (the only additions under
reports/are the 15 new Amendment A9 probe evidence files), and the v0.4.0 freeze manifest verifies green.1. Witness the tool identity instead of asserting it
Both the Bifrost modeling adapter and the Bifrost tool-native adapter published a hardcoded "Bifrost v0.10.6" identity they never read — the native adapter never invoked the binary at all (its row declines all six templates). Any re-pin would have silently published a false version into every declined cell's retained rationale.
Now both adapters witness identity from the pinned binary once per run, before the population is walked, so a run whose every cell is declined still records a real identity. Retained decision documents rename
pinned_tool_identity→witnessed_tool_identity; the native report carries the witnessed build identity; tests assert every retained rationale names a measured identity. Per-cell decline semantics are unchanged (no cell ever reaches the analyzer).2. Amendment A9 — Bifrost's modeling category Z promoted to scored
The Bifrost partition marked category Z (sanitizer declarations) unsupported on the adapter README's claim that sanitizer lowering was a future CLI capability. Measured false on Bifrost v0.10.7 (build
44d9a5be): the RQLPanalysisgrammar accepts a(sanitizer :id … :selector … :input … :output … :removes […])stanza, and a load-bearing probe on the committed fixtures in all three modeling languages showsEvidence retained under
reports/raw/amendment-a9-bifrost-sanitizer/(15 files), reproducible viascripts/probe-bifrost-sanitizer-lowering.sh. Bifrost moves from 2 to 4 scored modeling templates; P/O/E/B stay unsupported — with the record corrected to note:transforms/:external-modelsare grammar-accepted but their lowering is unshown, and acceptance is not lowering per the preregistration's own rule.MODELING_PARTITION, the count tests, the artifact-declares-only-scored-categories invariant (now requires:sanitizers), and the threemodel-*.rqlpartifacts updated accordingly. The JS/Java modeling rows' quoted configuration hashes are labelled as describing the pre-A9 run, re-run pending at the v0.10.8 re-pin.Amendment sequence stays monotonic and cross-document: A1 (challenge tier), A2–A5 + A9 (modeling matrix), A6–A8 (native profile); both amendment preambles now state the interleaving.
Deferred to the v0.10.8 re-pin PR
docs/native-profile.md's category-Z rationale still quotes the README sentence A9 retired; the cell's outcome is unaffected (the CLI ships no endpoint catalog), and correcting the wording is a dated tool-native amendment left for the re-pin PR.Verification
cargo fmt --checkclean ·cargo test162 passed ·validate852 cases ·validate-reports66 reports ·generate-results --checkcurrent ·validate-freezegreen (v0.4.0 manifest untouched). The A9 probe re-run post-rebase is byte-identical to the retained evidence.🤖 Generated with Claude Code