Skip to content

feat: buildc receipt verify arm for tool-call receipts - #36

Merged
HarperZ9 merged 7 commits into
mainfrom
feat/tool-call-receipt-verify
Jul 31, 2026
Merged

feat: buildc receipt verify arm for tool-call receipts#36
HarperZ9 merged 7 commits into
mainfrom
feat/tool-call-receipt-verify

Conversation

@HarperZ9

Copy link
Copy Markdown
Owner

Rust verify/read side for flywheel.tool-call-receipt/v1. Mirrors model_receipt.rs: fixed-order seal, shared failure taxonomy, golden fixture pinned in both repos proving the cross-language canonicalization contract. Chain allowlist widened.

HarperZ9 and others added 7 commits July 29, 2026 11:49
monte_carlo gains a two-arm DECLARED | EXECUTED status. Under the new
--mc-executed flag (opt-in; requires the full --mc-* declaration and
forces --columns to 3), the kernel prints a three-column row per
post-burn-in step, <invariant_scalar> <successes> <trials>, and receipt
verify RE-DERIVES the Wilson or normal-approx-95 interval from those
raw sufficient-statistic columns, entirely in verifier-owned code,
never from the kernel's own arithmetic.

The recompute runs twice. Stage A, over the sealed measurement series
before any re-run: a tampered-and-resealed interval is a pure data
contradiction, rejectable with no C compiler, so the self-test's
no-compiler property stays intact. Stage B, over the re-parsed re-run
series: a new failure class, MC_INTERVAL_DRIFT, for a receipt that
stays internally coherent while no longer describing the run it names.
Mutation-tested (Stage B skipped for EXECUTED receipts) to confirm it
is load-bearing, not redundant with Stage A.

The declared sample count becomes a WITNESSED denominator: the final
row's trials must equal monte_carlo.samples, the single biggest
honesty gain of the slice. Coherence is checked as a cumulative
Bernoulli count (integers below 2^53, trials incrementing by exactly
1, successes non-decreasing in {0, 1}, successes <= trials on every
row). Executable vocabulary v1: estimator proportion; interval methods
normal-approx-95 (refused at the boundary proportion, a zero-width
interval there overclaims precision) and wilson-95; clopper-pearson-95
is sealed-successes-only, not executable (needs a verified inverse
incomplete beta with no in-tree oracle), refused at emit and verify.

An EXECUTED block adds three not_claimed entries, present if and only
if the block is EXECUTED: sample_independence, interval_coverage,
estimator_semantics. EXECUTED hardens the interval arithmetic and the
denominator; it cannot and does not harden that the draws are
independent, that the named confidence level covers the true value, or
that the indicator counts what the author says it counts. This is
load-bearing honesty, not decoration: the receipt states in sealed
machine-readable form exactly which reading of an EXECUTED interval is
licensed.

Backward compatible: DECLARED receipts stay valid forever. The five
new fields are Option with skip_serializing_if; a DECLARED block's
serialized JSON carries exactly its original four keys, pinned by a
new test asserting the key set directly rather than assuming
skip_serializing_if behaves.

Shipped with: a new kernel pair, mc_pi_rejection_executed.bld and its
wrong-area negative fixture, same seed-42 stream as the DECLARED
sibling, calibration numbers measured by running the emitted receipt
(not invented): successes 1551 of 2000, estimate 0.7755, wilson-95
interval [0.7566951910008709, 0.7932485159471586]. The negative
fixture seals the slice's central lesson: the wrong-area factor only
scales the estimate, never the raw successes/trials counters, so the
interval executes and re-derives cleanly while the slack column still
blows the truth band. Corpus 27 -> 29. A tenth self-test case (nudge
the sealed interval_high on an EXECUTED block, reject through Stage A).
Nine new CLI tests covering the round trip and every emit-refusal path.
Docs (SCIENTIFIC-RECEIPT flags/schema/family/failure-classes/self-test/
corpus, CHANGELOG) and the plan/design docs in the writing-plans idiom.

Verified: full suite 1,644 passed / 0 failed (up from a 1,605 pre-slice
baseline measured at the start of final verification), exit codes
captured before any pipe; corpus 29/29, run twice for determinism;
self-test 10/10; cargo fmt --check clean. Every new gate
mutation-tested by literal inverse edit, never git checkout: sixteen
gates broken, observed red, restored, observed green, including one
mutation (a sign flip inside the Wilson formula's square root) that
only the hand-computed-value unit test catches, and one (the Stage B
skip) that proves Stage B is not redundant with Stage A.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…eline

Pure count refresh, re-verified fresh on this branch rather than trusting
slice-authoring-time numbers (the units slice merged to main after the
executed-intervals slice was authored, so the rebased totals differ from
both slices' own reports): cargo test 1683 passed, 0 failed, 11 ignored
(lib 1004 with 1001 passed and 3 ignored, bin 179, cli 341, gpu 12,
lexer 52, parser 98); buildc receipt corpus 29/29; verifier --self-test
10/10 on a freshly emitted executed-interval receipt; buildc corpus
verify 8/8. The STATUS baseline enumeration also gains the wave's three
newest members (executed intervals, drop flags, unit-annotated types) so
the rise it explains matches what produced it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The review's one finding: MC_INTERVAL_CLOPPER_PEARSON_95 was used only in
tests, tripping dead_code. The arm that refuses the method now formats its
message through the constant, making it the single source of the name.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Design: docs/superpowers/specs/2026-07-29-model-boundary-receipts-design.md

Emission is harness-side (harness/model_shim.py's --receipt-dir flag, the
local-model / _wshim repo); this commit ships buildc's read side only.

- New docs/MODEL-RECEIPT.md: the buildlang-model-boundary-receipt/v0 schema
  contract (field table, SHIM-WITNESSED vs DECLARED tags, the seal and
  cross-language canonicalization contract). docs/SCIENTIFIC-RECEIPT.md
  gains a pointer section; the scientific verifier's CAPABILITY_INADMISSIBLE
  refusal of any Model-observing program is untouched.
- New compiler/src/model_receipt.rs: the fourth receipt verify arm (beside
  gpu, scientific-runtime, and check), wired into both the plain and --json
  `receipt verify` dispatch. Offline only (no re-run): seal recompute
  (SEAL_MISMATCH), digest well-formedness (DIGEST_MALFORMED), and the three
  named field-shape contracts (FIELD_CONTRACT_VIOLATION) -- no new failure
  classes, the shared taxonomy is reused whole.
- compiler/src/main.rs: cmd_receipt_chain_build's member-schema gate widens
  from a single-schema equality to a two-schema allowlist
  (scientific-runtime + model-boundary-receipt). Chain verify needed zero
  changes: pinned seals and subprocess re-verification already dispatch
  through the new arm.
- compiler/tests/fixtures/model-receipt-golden.json: the byte-identical
  golden fixture (echo-mode COMPLETED receipt) both repos pin, seal
  6bb2a09c47f5eaa2e3208a5eadcd6d57d1faffa74a567e024e920571c3794035. The
  no-floats schema is what makes serde_json::to_vec and Python's
  json.dumps(..., separators=(",", ":"), ensure_ascii=False) agree
  byte-for-byte.
- Tamper coverage (unit tests in model_receipt.rs, CLI tests in cli.rs
  against the real buildc binary): a resealed field-shape violation, a seal
  mismatch, and a propose/dispose chain (a model receipt beside a
  Model-free disposer kernel's scientific receipt) that breaks with
  CHAIN_LINK_UNVERIFIED when only the model member is tampered.
- The model receipt is not a corpus member and not a --self-test case (a
  different artifact kind, not scientific evidence): corpus 29/29 and
  self-test 10/10 stay unchanged, re-run and recorded. Full suite: 1,698
  passed, 0 failed (+15 over the prior 1,683 baseline); cargo fmt clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…po byte pin

The review's one Important: local-model pins the shared golden fixture
eol=lf but buildlang had no .gitattributes at all, so a fresh Windows
clone with autocrlf would smudge the fixture bytes. No current test
breaks (verify recomputes seals from the parsed struct, proven
empirically in review), but the cross-repo byte-identity provenance
claim depends on the bytes, so both repos now pin it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the Rust verify/read side for flywheel.tool-call-receipt/v1, the
schema emitted by local-model's ToolExecutor when receipt_dir is set.
Mirrors model_receipt.rs in structure: struct declaration order is the
canonical sealed order, seal recompute blanks seal.hex, verify checks
SEAL_MISMATCH first then DIGEST_MALFORMED then FIELD_CONTRACT_VIOLATION.

The golden fixture (tool-receipt-golden.json) is produced by the Python
emit side and pinned with the same seal in both repos — the cross-language
canonicalization contract. The Rust test golden_fixture_reseals_to_its_
pinned_seal hard-codes the pinned hex, proving serde_json::to_vec and
Python json.dumps agree byte-for-byte.

Dispatch: new schema arm in both receipt verify paths (json + non-json),
chain allowlist widened to admit tool-call receipts beside scientific and
model-boundary receipts. 6 Rust tests pass (including golden).
@HarperZ9
HarperZ9 merged commit 4ed5218 into main Jul 31, 2026
2 of 3 checks passed
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