Skip to content

fix(OMN-15391): make the round-1 supersessions falsifiable — retire 8 tautologies + 15 fail-open absence legs, gate both classes - #5501

Merged
jonahgabriel merged 2 commits into
devfrom
jonah/omn-15391-rb2-falsifiable-bindings
Jul 29, 2026
Merged

jonahgabriel merged 2 commits into
devfrom
jonah/omn-15391-rb2-falsifiable-bindings

Conversation

@jonahgabriel

@jonahgabriel jonahgabriel commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Round-2 remediation of OCC#5481 (OMN-15391, merged 7a6e9965a). That PR retired 14 narrative-only evidence items — and shipped two new defect classes of its own, both caught by adversarial review. This PR repairs every instance by the same append-only supersession idiom (#4528) and, because a rule is not a mechanism, ships both defect classes as lint rules wired into the pre-commit hook and the corpus-wide pytest ratchet in this same commit.

Ticket: OMN-15391. Contract repair only — no ticket is flipped (see dependency note at the bottom).

Defect 1 — 8 tautological PR-existence stamps → new lint Rule C

The occ-self-bind-<N>-lit-rb15391 items each carried exactly one check:

gh pr view <N> --repo OmniNode-ai/onex_change_control --json number --jq '.number == <N>' | grep -qx true

This asserts N == N: true by construction for every PR that exists. I executed all 8 — every one returns rc=0, and none can go RED for any product reason.

These are not replaced with a "better" binding check, because none exists. The live OMN-14505/OMN-15309 predicate refuses both exhaustive candidate shapes, for two different and individually correct reasons:

Candidate binding shape Verdict (executed)
gh api .../pulls/<N>/files ... | grep -qx 'contracts/<TICKET>.yaml' INSIDE_OWN_DIFF — reads back OCC's own contract tree
gh api .../pulls/<N> --jq '.merged_at' ... INSIDE_OWN_DIFF — PR metadata proves the change exists, not that anything it claims is true

An OCC self-bind stamp is by construction a statement about OCC's own tree and a PR's own metadata — both halves are exactly what the predicate refuses. Each is therefore superseded by an entry recording the binding as unprovable-on-record (the operator's OMN-15376 amend-on-record ruling), whose check proves the unprovability rather than the binding: it runs the predicate against both candidate shapes and goes RED if either is ever admitted. tests/unit/test_occ_self_bind_unprovable_on_record_omn15391.py, 8 tests.

Defect 2 — 15 absence legs that fail OPEN → new lint Rule D

Every paired absence leg was ... | grep -c '<marker>' | grep -qx 0. check_values run under sh -c without pipefail, so a producer that 404s / is denied / errors emits nothing, grep -c prints 0, and the leg exits 0 — GREEN, having read nothing.

Reproduced by execution before any edit:

  • the shape returns rc=0 against OmniNode-ai/no_such_repo_xyz, a repo that does not exist;
  • with an invalid token the private-repo green leg correctly returns rc=1 while its absence leg returns rc=0;
  • 4 of the 12 shipped legs were passing purely on a 404 — the file is net-new and absent at the parent ref, so they never read anything even with a good token.

Adding pipefail does not rescue the shape either: grep -c exits 1 on a zero count, so it would fail on exactly the case it asserts. Two fail-closed replacements, chosen per item:

  • File present at parent — read once into a variable, prove the read landed with a structural anchor present at both refs, then assert absence:
    body=$(gh api ...?ref=PARENT) && printf '%s' "$body" | grep -qF 'ANCHOR' && ! printf '%s' "$body" | grep -qF 'MARKER'
  • Path absent at parent (net-new) — pair a reachability control with the absence assertion, so a 404 counts as evidence only after the same token demonstrably read the same ref:
    gh api 'repos/O/R/commits/PARENT' --jq '.sha' | grep -qx 'PARENT' && ! gh api 'repos/O/R/contents/FILE?ref=PARENT' --silent

Per-contract repair table

All 23 superseding items; all 38 checks executed here (rc in the last column).

Contract Superseded item Shape New item rc
OMN-14979 occ-self-bind-5408-lit-rb15391 C→unprovable occ-self-bind-5408-unprovable-rb2 0
OMN-14979 dod-14979-infra746-bucket-rb15391 D→reachability+absent dod-14979-infra746-bucket-rb2 0,0
OMN-14980 occ-self-bind-5415-lit-rb15391 C→unprovable occ-self-bind-5415-unprovable-rb2 0
OMN-14980 dod-14980-infra751-writer-rb15391 D→anchored read dod-14980-infra751-writer-rb2 0,0
OMN-15299 occ-self-bind-5414-lit-rb15391 C→unprovable occ-self-bind-5414-unprovable-rb2 0
OMN-15299 dod-15299-infra750-plangate-rb15391 D→anchored read dod-15299-infra750-plangate-rb2 0,0
OMN-15353 dod-15353-infra760-redgreen-rb15391 D→reachability+absent dod-15353-infra760-redgreen-rb2 0,0
OMN-15362 occ-self-bind-5473-lit-rb15391 C→unprovable occ-self-bind-5473-unprovable-rb2 0
OMN-15362 dod-15362-omniclaude1961-stamp-rb15391 D→reachability+absent dod-15362-omniclaude1961-stamp-rb2 0,0
OMN-15365 occ-self-bind-5407-lit-rb15391 C→unprovable occ-self-bind-5407-unprovable-rb2 0
OMN-15365 dod-15365-infra747-fenced-rb15391 D→anchored read dod-15365-infra747-fenced-rb2 0,0
OMN-15366 occ-self-bind-5413-lit-rb15391 C→unprovable occ-self-bind-5413-unprovable-rb2 0
OMN-15366 dod-15366-infra749-digest-rb15391 D→anchored read dod-15366-infra749-digest-rb2 0,0
OMN-15370 occ-self-bind-5411-lit-rb15391 C→unprovable occ-self-bind-5411-unprovable-rb2 0
OMN-15370 dod-15370-infra748-devhost-rb15391 D→anchored read dod-15370-infra748-devhost-rb2 0,0
OMN-15375 occ-self-bind-5418-lit-rb15391 C→unprovable occ-self-bind-5418-unprovable-rb2 0
OMN-15375 dod-15375-infra752-noderole-rb15391 D→anchored read dod-15375-infra752-noderole-rb2 0,0
OMN-15376 dod-15376-infra2537-baselines-rb15391 D→anchored read dod-15376-infra2537-baselines-rb2 0,0
OMN-15376 dod-omn-15376-ac2-reconciling-alter D→anchored read dod-omn-15376-ac2-reconciling-rb2 0,0
OMN-15383 dod-15383-infra758-guard-rb15391 D→anchored read dod-15383-infra758-guard-rb2 0,0
OMN-15383 dod-15383-infra758-redgreen-rb15391 D→reachability+absent dod-15383-infra758-redgreen-rb2 0,0
OMN-15391 dod-15391-infra2537-baselines-bound D→anchored read dod-15391-infra2537-baselines-rb2 0,0
OMN-15391 dod-15391-omniclaude1961-bound D→reachability+absent dod-15391-omniclaude1961-rb2 0,0

Scope note: the last three rows are beyond the 20 items the review named — contracts/OMN-15391.yaml (this ticket's own contract) carried the same fail-open shape in 2 items, and contracts/OMN-15376.yaml in 1. Repairing the rules while leaving my own contract defective would have been exactly the failure under review.

Falsifiability proven by mutation, not asserted

Every replacement was mutated and re-run. All mutations go RED (rc≠0):

Shape invalid token nonexistent repo pointed at merge ref anchor mutated wrong PR
Anchored-read absence (10) RED RED RED RED —
Reachability+absent (5) RED RED RED — —
Unprovable-on-record (8) — — — — RED (predicate admits→test fails)

Mechanism (both rules ship as gates here)

scripts/lint_contract_check_values.py gains Rule C and Rule D, wired through:

  1. the existing pre-commit hook lint-contract-check-values (changed files), and
  2. the corpus-wide pytest ratchet, which is the load-bearing surface — the hook only sees changed files, so it would never have caught the 23 checks OCC#5481 appended to contracts CI never resolved.

Ratchet accounting — the round-1 review called the OMN-15382 shrink "laundering"

Both new rules get a shrink-only, set-equality corpus baseline, plus a test forbidding any -rb2 item from ever appearing in either.

  • Rule C baseline is EMPTY, and that is a real finding. A loose first draft reported 32 corpus hits; 24 were false positives on the occ-self-bind-pr-<n> idiom, which ANDs the identity comparison with falsifiable .state/.headRefName predicates and therefore can go RED. The rule was narrowed to fire only when the identity comparison is the entire jq program, with a negative control drawn from the live text of contracts/OMN-15383.yaml. True corpus count was 8 — all from OCC#5481, all retired here. No historical debt exists, so the zero point is an empty set and any new tautology hard-fails immediately.
  • Rule D baseline is 11 dod-00N-era items in contracts this PR does not otherwise touch (each needs its own anchor researched against the real file at the real ref). Down from 26 live at round-1 landing.

Net: 23 vacuous/fail-open checks retired, 0 untracked violations added.

Round-1 count correction (review item 4)

The review is right and I am restating it plainly. OCC#5481's body claimed 14 + 15 = 29; the correct reconciliation of the ticket's 29 items is 13 retired + 16 deferred. The 14th retired item (contracts/OMN-15362.yaml) post-dates the ticket and is not among its 29, and the "Deferred, precisely" table headed "15 of the 29" had rows summing to 16. Nothing was silently dropped — the arithmetic was wrong in two offsetting places. #5481 is merged and its body is immutable in substance; this paragraph is the correction on record.

Honest limits

  1. 9 of the repaired items bind facts in the PRIVATE OmniNode-ai/omninode_infra repo. Under OCC's hosted runner (repo-scoped github.token) those endpoints 404 and the checks go RED. That RED means "cannot evaluate here" — but unlike the superseded legs it is now reached by a real failure rather than a vacuous pass, and node_dod_verify (operator token) evaluates them for real. This is the corrected version of round 1's "Honest limits M0: Bootstrap onex-change-control Poetry package + repo structure + baseline CI #1", which claimed fail-closed behaviour the absence legs did not actually have.
  2. Red/green items bind the discriminating test's PRESENCE at the merged commit, not its execution. Unchanged from round 1, restated because it still applies.
  3. pre-commit run --all-files is still red on this branch — and was already red on dev. Attribution measured against an untouched dev worktree at the same base: check-receipt-honesty, check-receipt-hardening (168 findings), and check-evidence-commit-shas (1 finding) are byte-identical before and after this change — 0 new. lint-contract-check-values goes 1441 → 1452; the 11 new detections are exactly the 11 Rule D baseline entries (verified by set diff), i.e. my own new rule reporting pre-existing legacy debt that is now tracked. On the 12 contracts this PR actually changes, the hook exits 0.
  4. Self-authorship is unchanged. The same lane authored the repair, its contract and its rules. What is different from round 1 is that the claims are now checkable by someone else without a privileged token: the Rule C/D unit tests, the unprovability tests, and the corpus ratchets are all hermetic and run in this repo's CI over every contract.

Verification

  • 38 new checks executed: all rc=0; all classify ADMISSIBLE under LIVE_PROBE | EXECUTED_HERMETIC.
  • Append-only: contracts/ diff is 681 insertions / 0 deletions. Originals verified preserved by parse-and-compare after yamlfmt reflow (23 new items, 0 mutated originals) — not by eyeball.
  • 12/12 repaired contracts pass validate-yaml.
  • 514 tests pass on .200, including 65 lint-rule tests, 8 unprovability tests, and 6 corpus ratchets.
  • Rule 11a: gates and push ran on .200 via patch-transfer; the git tree hash is identical on both hosts (6947117a), which is a Merkle hash over every path, mode and byte — so the gates ran on exactly the reviewed tree, closing the edit-locality trap.

Dependency

Ticket flips downstream of these repairs wait on OMN-15390 — node_dod_verify has no contract-entry supersedes_dod_evidence handling, so an append-only supersession cannot yet retire an item from its tally. This PR is contract repair plus gate wiring only; it flips nothing.

🤖 Generated with Claude Code

Evidence-Ticket: OMN-15391
Evidence-Source: OCC#5502

@coderabbitai

coderabbitai Bot commented Jul 29, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 18 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5eac5654-e963-4526-a47b-f7ec514a1965

📥 Commits

Reviewing files that changed from the base of the PR and between 0f015d7 and f040281.

📒 Files selected for processing (20)
  • .onex_ratchets/omn_15391_rule_c_baseline.yaml
  • .onex_ratchets/omn_15391_rule_d_baseline.yaml
  • contracts/OMN-14979.yaml
  • contracts/OMN-14980.yaml
  • contracts/OMN-15299.yaml
  • contracts/OMN-15353.yaml
  • contracts/OMN-15362.yaml
  • contracts/OMN-15365.yaml
  • contracts/OMN-15366.yaml
  • contracts/OMN-15370.yaml
  • contracts/OMN-15375.yaml
  • contracts/OMN-15376.yaml
  • contracts/OMN-15383.yaml
  • contracts/OMN-15391.yaml
  • drift/dod_receipts/OMN-15391/dod-15391-infra2537-baselines-rb2/command.yaml
  • drift/dod_receipts/OMN-15391/dod-15391-omniclaude1961-rb2/command.yaml
  • scripts/lint_contract_check_values.py
  • tests/unit/scripts/test_lint_contract_check_values.py
  • tests/unit/scripts/test_lint_contract_check_values_corpus_baseline.py
  • tests/unit/test_occ_self_bind_unprovable_on_record_omn15391.py

Comment @coderabbitai help to get the list of available commands.

jonahgabriel added a commit that referenced this pull request Jul 29, 2026
…/OMN-15391.yaml

occ-preflight/eligibility on #5501 failed closed with reason=missing_receipt for
OMN-15391:dod-15391-infra2537-baselines-rb2:command and
OMN-15391:dod-15391-omniclaude1961-rb2:command — the OCC in-repo trap: an OCC PR
validates its own contract + receipts from the PR's in-tree checkout, so the two
items this PR appends to its own contract need receipts in the same PR.

Both receipts are generated by executing the real joined command and reading the
real result; contract_sha256 and contract_entry_sha256 are computed with
omnibase_core.validation.validator_receipt_gate rather than transcribed. The
contract hash (9d4d35e7...) matches the value the failing CI run itself reported,
confirming the local bytes are the bytes CI sees.

probe_stdout does NOT narrate a proof. grep -q and gh api --silent are quiet on
success, so there is no stdout to record; the receipts say exactly that and give
the observable result (joined rc=0, per-leg rc=[0,0]) instead of inventing a
'PASS: ...' sentence. Writing a narrative there would reproduce, inside this
ticket's own evidence, the defect the ticket exists to retire.
@jonahgabriel
jonahgabriel force-pushed the jonah/omn-15391-rb2-falsifiable-bindings branch from 669040c to f315041 Compare July 29, 2026 20:47
jonahgabriel added a commit that referenced this pull request Jul 29, 2026
* evidence: OCC companion pass 1 for #5501

* evidence: OCC companion self-bind for #5502

* evidence: pin OCC self-bind check for OMN-15391 companion

* evidence: refresh OMN-15391 self-bind receipt hash

* evidence: refresh OMN-15391 receipt contract hashes

---------

Co-authored-by: node-occ-companion-effect <occ-companion-effect@omninode.ai>
… tautologies + 15 fail-open absence legs, and gate both classes

Round-2 remediation of OCC#5481 (merged 7a6e996). That PR retired 14
narrative-only evidence items, but shipped two new defect classes of its own.
Both are repaired here by the same append-only idiom (#4528), and both are now
mechanically gated so they cannot recur.

DEFECT 1 — 8 tautological PR-existence stamps (new lint Rule C).
The `occ-self-bind-<N>-lit-rb15391` items each carried exactly one check:
`gh pr view <N> ... --jq '.number == <N>' | grep -qx true`. That asserts N == N
— true by construction for every PR that exists. All 8 were executed: all
return rc=0 and none can go RED for any product reason.

These are NOT replaced with a better binding check, because none exists. The
live OMN-14505/OMN-15309 predicate refuses BOTH exhaustive candidate shapes as
INSIDE_OWN_DIFF: reading the companion PR's file list is reading back OCC's own
contract tree, and reading /pulls/<N> metadata proves only that the change
exists. An OCC self-bind stamp is by construction a statement about OCC's own
tree and a PR's own metadata, so both halves are exactly what the predicate
refuses. Each is therefore superseded by an entry recording the binding as
UNPROVABLE-ON-RECORD (the operator's OMN-15376 amend-on-record ruling), whose
check proves the unprovability rather than the binding: it executes the
predicate against both candidate shapes and goes RED if either is ever
admitted.

DEFECT 2 — 15 absence legs that fail OPEN (new lint Rule D).
Every paired absence leg was `... | grep -c '<marker>' | grep -qx 0`. Without
pipefail a failed producer emits nothing, `grep -c` prints 0, and the leg exits
0 — GREEN, having read nothing. Proven by execution: the shape returns rc=0
against OmniNode-ai/no_such_repo_xyz, a repo that does not exist; and 4 of the
12 shipped legs were passing purely on a 404 because the file is net-new and
absent at the parent ref. Two fail-closed replacements, chosen per item:
  * file present at parent — read once into a variable, prove the read with a
    structural anchor present at BOTH refs, then assert absence.
  * path absent at parent — pair a reachability control (the same token must
    resolve the parent sha in the same repo) with the path-absence assertion,
    so a 404 counts as absence only after a demonstrated read.
Scope beyond the 12: also repairs the 2 same-shape legs in contracts/
OMN-15391.yaml (this ticket's own contract) and 1 in contracts/OMN-15376.yaml.

MECHANISM (a rule is not a mechanism — both ship as gates in this commit).
scripts/lint_contract_check_values.py gains Rule C and Rule D, wired through
the existing pre-commit hook AND the corpus-wide pytest ratchet. The corpus
ratchet is the load-bearing surface: the pre-commit hook only sees CHANGED
files, so it would never have caught the 23 checks OCC#5481 appended to
contracts CI never resolved.

RATCHET ACCOUNTING (round-1 review called the OMN-15382 shrink laundering).
Both new rules get a shrink-only, set-equality corpus baseline, and a test
forbids any `-rb2` item from ever appearing in either.
  * Rule C baseline is EMPTY. A loose first draft reported 32 corpus hits, but
    24 were FALSE POSITIVES on the `occ-self-bind-pr-<n>` idiom, which ANDs the
    identity comparison with falsifiable `.state`/`.headRefName` predicates and
    therefore can go RED. The rule was narrowed to fire only when the identity
    comparison is the entire jq program, with a negative control drawn from the
    live text of contracts/OMN-15383.yaml. True corpus count was 8 — all from
    OCC#5481, all retired here. No historical debt exists, so the ratchet's
    zero point is an empty set and any new tautology hard-fails immediately.
  * Rule D baseline is 11 `dod-00N`-era items in contracts this PR does not
    otherwise touch (each needs its own anchor researched against the real file
    at the real ref). Down from 26 live at round-1 landing.

EXECUTED EVIDENCE
  * 38 new checks: all rc=0, all ADMISSIBLE under LIVE_PROBE|EXECUTED_HERMETIC.
  * Falsifiability by mutation, not assertion: Shape-A absence legs go RED
    under invalid token, nonexistent repo, pointed at the merge ref, and
    anchor mutated; Shape-B legs go RED under invalid token, nonexistent repo,
    and pointed at the merge ref where the path exists.
  * contracts/ diff is 681 insertions / 0 deletions — every original preserved
    byte-for-byte, verified by parse-and-compare after yamlfmt, not by eyeball.
  * 12/12 repaired contracts pass validate-yaml.
  * Gates on .200 via patch-transfer, git tree hash identical on both hosts.

No ticket is flipped. Flips still wait on OMN-15390 (node_dod_verify has no
contract-entry supersedes_dod_evidence handling).
…/OMN-15391.yaml

occ-preflight/eligibility on #5501 failed closed with reason=missing_receipt for
OMN-15391:dod-15391-infra2537-baselines-rb2:command and
OMN-15391:dod-15391-omniclaude1961-rb2:command — the OCC in-repo trap: an OCC PR
validates its own contract + receipts from the PR's in-tree checkout, so the two
items this PR appends to its own contract need receipts in the same PR.

Both receipts are generated by executing the real joined command and reading the
real result; contract_sha256 and contract_entry_sha256 are computed with
omnibase_core.validation.validator_receipt_gate rather than transcribed. The
contract hash (9d4d35e7...) matches the value the failing CI run itself reported,
confirming the local bytes are the bytes CI sees.

probe_stdout does NOT narrate a proof. grep -q and gh api --silent are quiet on
success, so there is no stdout to record; the receipts say exactly that and give
the observable result (joined rc=0, per-leg rc=[0,0]) instead of inventing a
'PASS: ...' sentence. Writing a narrative there would reproduce, inside this
ticket's own evidence, the defect the ticket exists to retire.
@jonahgabriel
jonahgabriel force-pushed the jonah/omn-15391-rb2-falsifiable-bindings branch from f315041 to f040281 Compare July 29, 2026 20:58
@jonahgabriel
jonahgabriel merged commit 9d3cf65 into dev Jul 29, 2026
58 checks passed
@jonahgabriel
jonahgabriel deleted the jonah/omn-15391-rb2-falsifiable-bindings branch July 29, 2026 21:05
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