Activity Overview

Commits and releases over time

  • Commits
  • Releases
  • Authors

Repository Explorer

301 commits in all time Jun 29, 2026 03:25 – Sep 27, 2026 03:25 UTC
Mutation-test the five rules that had none, and count the mutations
f7bcb90 claimed "wrong_target was the only rule in the file without a mutation test; A to L
cover the rest". That was false, and nothing enforced it. Four table-hygiene rules had no
mutation -- `ambiguous`, `reused`, the UNCHECKED `kind` whitelist, and the audit-sheet clause of
the count check -- and mutation N reaches only the `isinstance(row, Live)` half of
`wrong_target`: delete the `row.target == cite.path` comparison and N still fails.

Five mutations close that, each proven by neutralising the rule it names and running the file:

  O  a citation that two rows answer         assert not result.ambiguous
  P  one row answering two citations         assert not result.reused
  Q  an UNCHECKED row of an invented kind    the `kind` whitelist
  R  an audit sheet that cites no line       assert in_audit_sheet
  S  a path-qualified citation answered by   row.target == cite.path
     a LIVE row about another file

Each neutralisation fails exactly its own test and nothing else: 31 tests in the file, 30 pass
and 1 fails, seven times over.

The whitelist was a bare `assert ... <= {...}` with no message. It now names the kinds it
refuses, so its failure says what is wrong.

The module docstring lists these mutations in prose, and prose cannot be checked clause by
clause. What can be checked is the count, so
test_the_mutations_are_a_contiguous_lettered_run asserts the letters run from `a` with none
missing and none repeated, and that the docstring states that number in words. Renaming mutation
A to T, and changing "Nineteen" to "Eighteen", each fail that test alone.

sdk/tests: 176 passed, 5 skipped -- 170 before these six tests -- with TRELYAN_REQUIRE_KAT=1,
TRELYAN_REQUIRE_GIT=1 and the Falcon library built from the vendored tree. Every skip is
reported; none is counted as a pass. The 28 errors in sdk/test_inscription.py are LocalNet
connection refusals, identical on HEAD.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 4ee6b577 Branch test/audit-readiness-citations-current Document 1/173 ++ 4 --
Correct two statements in mutation M's docstring
The docstring said the guard's two lines carry "two `.github/workflows/ci.yml` comments". The
next commit on this branch, 2c2daeb, added a third, so the count was stale one commit later and
nothing enforces it. It now names those comments without counting them.

It also said deleting the guard used to leave the suite green because "the skip branch is the
only one ever taken". Neither branch is taken: every environment the suite runs in can read the
object store, so `_unavailable` is never called at all. The claim around it -- that deleting the
two lines leaves the suite green while this test is absent -- is true and was reproduced; only
the stated mechanism was wrong.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit f542c24d Branch test/audit-readiness-citations-current Document 1/7 ++ 6 --
Test the anti-skip switch and the wrong-target rule
TRELYAN_REQUIRE_GIT is what makes four written claims true: this file's
docstring says twice that the environmental skips fail when it is set (the end
of check 4, and WHAT IS NOT CHECKED), and two .github/workflows/ci.yml comments
say a skipped check is not a pass. Nothing tested it -- deleting the two lines
in _unavailable that read the variable left the suite green, because every
environment the suite runs in can read the object store.

wrong_target was the only rule in the file without a mutation test; A to L cover
the rest. It is the only rule that reads the path a citation spells out, so an
exemption in a dated record could answer a path-qualified contract citation with
nothing else objecting.

Mutation M patches _blob_id_in_commit to a lookup that says the store cannot be
asked, then asserts through _must_fail_not_skip that the banner-to-blob check
FAILS with the variable set, and, as the negative control, that it raises
Skipped with the variable unset. _must_fail_not_skip now takes the exception the
check raises: pytest.fail raises Failed, which is not an AssertionError, so
pytest.raises(AssertionError) would not have caught it.

Mutation N plants a path-qualified citation in
contracts/COMPILE_REVIEW_2026-06-01.md and a dated UNCHECKED row for it, and
asserts test_every_citation_is_in_the_table fails with the rule's own message.

Evidence. Mutations were run in a mirror clone under the scratchpad, never in
this worktree; the environment was the suite's own (TRELYAN_REQUIRE_KAT=1,
TRELYAN_REQUIRE_GIT=1, FALCON_DET1024_LIB built from this tree's vendored src).

  mirror baseline                                   25 passed
  delete the two-line guard in _unavailable          1 failed (mutation M,
                                                     "the check SKIPPED where it
                                                     must fail"), 24 passed
  restored                                          25 passed
  delete the wrong_target rule in
  test_every_citation_is_in_the_table                1 failed (mutation N,
                                                     "DID NOT RAISE"), 24 passed
  restored                                          25 passed

In this worktree: full sdk suite 170 passed, 5 skipped -- the same five skips as
before this change (four algo-pqc-kit interop, one 3.10 argv premise), none of
them in this file. tests/test_app_id_references_are_coherent.py replayed: 30
passed. tests/test_signature_kat.py with the library built: 8 passed, 0 skipped.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit f7bcb90e Branch test/audit-readiness-citations-current Document 1/71 ++ 8 --
Say what a depth-1 checkout does to wire-format: it fails, not skips
The comment justifying fetch-depth: 0 in the wire-format job said a depth-1
checkout would make the banner-to-blob check SKIP in every run. That job sets
TRELYAN_REQUIRE_GIT=1 on the step that runs pytest, and that variable turns an
object store that cannot be asked into a failure, so a depth-1 checkout would
fail the job instead of quietly skipping the check. The sentence now says that.

Evidence: a depth-1 clone of this branch, same environment as the job.

  TRELYAN_REQUIRE_GIT=1   3 failed, 22 passed
                          (test_the_recorded_blob_id_is_the_blob_the_banner_
                          commit_holds, and mutations K and L, each
                          "TRELYAN_REQUIRE_GIT=1, but cannot read
                          205d874:contracts/inscription.py from the object
                          store")
  variable unset          22 passed, 3 skipped
                          ("this is a shallow clone; it holds only the tip")

The other fetch-depth: 0 comment, in signature-kat, says only "same reason as
wire-format: the banner-to-blob read needs the history". That is what that job
does -- it also sets TRELYAN_REQUIRE_GIT=1, on the step that runs the whole
suite -- so it states no silent skip and needed no correction.

No behaviour changes here: the file still parses to the same ten jobs, with
wire-format keeping fetch-depth: 0 and TRELYAN_REQUIRE_GIT=1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 2c2daeb5 Branch test/audit-readiness-citations-current Document 1/3 ++ 1 --
Remove the ci.yml shape control and the claim it was added to enforce
Check 7 (test_ci_can_reach_and_run_the_checks_in_this_file, and its
mutation M) read .github/workflows/ci.yml as text and asserted four
facts about it. It was defective three times running. The last version
matched its own needle inside a YAML comment, so commenting out the
setting it guarded still passed; it identified jobs by one hard-coded
spelling of `pytest tests`; and the comment it added to the wire-format
job -- "Runs on the schedule too, unlike every other job here" -- was
false. Reading the workflow: the Monday cron "23 6 * * 1" also runs
secret-scan, vendored-falcon-integrity, teal-matches-source and
required-merge-gates, which carry no `if: github.event_name !=
'schedule'`. Four other jobs, not none.

An unenforceable claim is removed, not re-armed with another control.
So:

* The check, its mutation, and everything only they used
  (PLANT_DOCS, CI_WORKFLOW, TRIGGER_PATHS, JOB_HEAD, RUNS_THE_SUITE,
  SCHEDULE_GUARD, _ci_text, _ci_jobs, _covered,
  _documents_this_file_names) are deleted. REQUIRE_GIT stays: it is
  check 4's skip-versus-fail switch, not part of check 7.
* The docstring sentences that asserted properties of ci.yml are gone.
  What replaces them says the opposite and is true: this file does not
  read the workflow, the two lists are kept in step by review, and a
  document that enters the scan later is outside the filters unless
  somebody lists it.
* wire-format goes back to `if: github.event_name != 'schedule'`, as on
  origin/main, and the false comment goes with it. Unguarding it was a
  CI-shape change argued for by check 7; with check 7 gone nothing
  argues for it.

What stays in ci.yml is what the citation test needs in order to run at
all: the root documents in both `paths` filters (a doc-only commit
triggered no job, which is how a wrong citation merged green), and
`fetch-depth: 0` plus TRELYAN_REQUIRE_GIT=1 in the two jobs that run
`pytest tests`, so check 4's object-store read runs instead of skipping.
Nothing asserts those; the comment above the filters now says so.

Evidence, all in a mirror copy under scratchpad/simplifyC-mirror, never
in the worktree, interpreter .venv/Scripts/python.exe with
TRELYAN_REQUIRE_KAT=1, TRELYAN_REQUIRE_GIT=1 and the Falcon DLL built
from the vendored third_party/falcon-det1024/src with MinGW gcc 16.1.0:

  baseline                                    23 passed, 0 skipped
  two lines inserted above _build_message     7 failed, incl.
                                              test_every_cited_line_still_holds_its_construct
  restored                                    23 passed
  `contracts/inscription.py:305` appended to  7 failed, incl.
  AUDIT_READINESS.md                          test_every_citation_is_in_the_table
                                              (54 extracted vs 52 listed)
  restored                                    23 passed
  one LIVE row deleted from the table         7 failed, incl.
                                              test_every_citation_is_in_the_table
  restored                                    23 passed
  `(L208)` deleted from AUDIT_READINESS.md    7 failed, incl.
                                              test_every_table_entry_is_still_cited
  restored                                    23 passed

Worktree: full sdk suite 168 passed, 5 skipped. The five skips are
pre-existing and environmental -- four for algo-pqc-kit not installed,
one for an interpreter that accepts -P. None is a citation check.
test_app_id_references_are_coherent.py: 30 passed, 0 skipped; no
literal 7xxxxxxxx app id was added to either edited file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 7ed26a05 Branch test/audit-readiness-citations-current Document 2/24 ++ 159 --
Fail a banner commit this repository cannot resolve, and test ci.yml instead of asserting it
Review round 3 found that the control added by 0090c02 could be switched off by the
very document it polices. _blob_id_in_commit returned None for "no .git", "no git",
"shallow clone" AND "this repository does not hold that commit", and every caller
skipped on None. So the shortest path to green after a contract change was no longer
to overwrite CONTRACT_BLOB_AT's value under the existing key -- BANNER-1 catches that
-- but to change the KEY: point AUDIT_READINESS.md's banner at a hash nobody can
resolve and record the current blob under it. The blob-equality half then passes
because the pair is self-consistent, the object-store half skipped, and the scope
sheet named a revision that does not exist while the suite exited 0. test_mutation_k,
the self-test for that control, skipped in the same state, because pytest.skip raised
inside pytest.raises(AssertionError) propagates as Skipped, not as a failure.

_blob_id_in_commit now returns a BlobLookup that separates "the store cannot be asked"
from "the store was asked and this repository does not contain it". The first is
environmental and still skips; the second is chosen by the author of the document under
review and now FAILS. TRELYAN_REQUIRE_GIT=1 turns the environmental skip into a failure
too, and ci.yml sets it in both jobs that run `pytest tests` -- the same reasoning as the
grep in signature-kat: passing must require that the check RAN. Two new mutations,
test_mutation_l (a fabricated banner commit) and the hardened test_mutation_k, assert a
FAILURE rather than "not a pass", through a helper that refuses to let the check skip.

Three facts about ci.yml were stated in the docstring as settled and enforced by nothing:
that the five root documents are in both paths filters, that the suite jobs check out
with fetch-depth: 0, and (implicitly) that the checks are reachable at all. CI-1
(fetch-depth 0 -> 1) and CI-2 (the root documents removed) both survived the whole suite
at exit 0. test_ci_can_reach_and_run_the_checks_in_this_file reads the workflow as text --
no YAML dependency, as the four other tests that read it do -- and requires every document
a row, ROOT_COMPILE_DOCS or a mutation names to be in both filters, every `pytest tests`
job to carry fetch-depth: 0 and TRELYAN_REQUIRE_GIT=1, and one such job to run on the
schedule. test_mutation_m proves each of those four with a planted ci.yml.

The filters gained SECURITY.md, PUBLIC_CLAIMS_HARDENING_2026-06-01.md, PINNED_BUILD.md,
ROADMAP.md and LOCALNET_VALIDATION_2026-06-01.md, and wire-format no longer skips the
Monday schedule: the whole-tree sweep of check 6 reads files no paths list can enumerate,
and the schedule is the only thing that reaches those. required-merge-gates already counts
a job's success the same as its schedule-skip, so the gate set is unchanged.

Two prose corrections, both claims that were checkable and wrong. The bullet added by
0090c02 said the three files excluded from the scan hold no line citation "today"; that
is true of the two TARGETs and false of this file, which holds 114 by its own extractor,
several of them live present-tense claims about contract line numbers that nothing checks.
And the paragraph recording the superseded wording quoted "124 differing lines" for all
five documents; contracts/requirements.txt said "124 cosmetically-different lines", which
is why OLD_COUNT_FORM already refuses both.

Mutation proofs, each in a cp -r scratch copy against the whole sdk suite, KAT armed:
BANNER-2 (banner -> d0d0bee, CONTRACT_BLOB_AT rekeyed) now 3 failed, was exit 0; CI-1 and
CI-2 now 2 failed each, both were exit 0; CI-3 (TRELYAN_REQUIRE_GIT removed from ci.yml)
2 failed; FIX-3 (the object-store read deleted) 3 failed under TRELYAN_REQUIRE_GIT=1, and
167 passed / 8 skipped without it -- which is what the env gate and the ci.yml test exist
to make impossible in CI. Negative controls still caught: BANNER-1 1 failed, DRIFT-2 4
failed. Baseline 170 passed, 5 skipped with and without TRELYAN_REQUIRE_GIT; the new file
alone 25 passed, 0 skipped. The five skips are the pre-existing ones. App-id rule replayed
over 316 tracked paths: no unclassified file.

Security Impact: no contract, proof or crypto code changed. The change is to what the test
suite refuses. A stale scope sheet that previously merged green through a skipped check now
fails the suite, and CI can no longer be edited to stop these checks running without that
same suite going red. contracts/inscription.py is untouched, so AUDIT_READINESS.md's banner
commit and CONTRACT_BLOB_AT still hold and no LIVE row needed re-verifying.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 3117455b Branch test/audit-readiness-citations-current Document 2/334 ++ 53 --
Close the checks that a sixth document or a rewritten blob id could walk past
Review of the branch found four ways its own machinery could be walked past.

1. Check 6 walked a hard-coded five-name tuple while the citation half of the
   same file walks the tree, so the stale "124 differing lines" claim could
   re-enter through any sixth document and nothing noticed. Proven: the phrase
   planted in REVIEWER.md, and "99 lines of the approval TEAL" planted in
   PINNED_BUILD.md, both SURVIVED the whole sdk suite. Every scanned document is
   now swept as well - the superseded form is refused anywhere, and a document
   outside the five may state the count only if it states the committed one.
   Both plants are now KILLED.

2. CONTRACT_BLOB_AT was a self-consistent pair: it proved the contract is the
   blob the dict records for the string "205d874", never that it is the blob
   commit 205d874 holds. Appending a line below every cited construct and
   overwriting the value under the same key left AUDIT_READINESS.md asserting a
   false revision while the suite stayed green. The id is now read back with
   `git rev-parse <banner commit>:contracts/inscription.py`. Unreadable (no
   .git, no git, or a shallow clone that lacks the commit) is a reported SKIP,
   never a pass; the blob-equality check is unchanged and still runs either way.

3. A bare `:N` was only read in a document that also carried a `path:N`.
   AUDIT_READINESS.md carries none - its style is `contracts/inscription.py`
   plus `(L288)` - so a `:305` written into the one document this file exists
   for reached no production check. It tripped only the extractor self-test, by
   the accident that that test plants a path form into the same document. A bare
   `:N` is now read in every markdown file that names inscription.py; outside
   markdown the old gate stands, because there a bare `:N` is usually a port
   (ci.yml says "algod on :4001"). The change adds zero citations to the current
   tree: 53 before, 53 after.

4. CI never ran any of this on the change class it was written for. A commit
   confined to AUDIT_READINESS.md, README.md, REVIEWER.md, CONTRIBUTING.md or
   THREAT_MODEL_AND_TRACEABILITY.md matched no `paths` filter, so a wrong
   citation merged green and first failed on some later, unrelated change. All
   five are in both filters now, which also closes the gap for
   test_cited_documents_exist.py and test_app_id_references_are_coherent.py. The
   two jobs that run `pytest tests` check out with fetch-depth: 0 so the
   object-store read in 2 runs there instead of skipping on a depth-1 clone.

Each new rule is mutation-proven in the file (mutations i, j, k re-run the real
test functions against planted inputs), and all four holes were re-run against
the whole suite in a scratch copy: KILLED, tree restored byte-identical.

Also states plainly what the scan does not read: the two TARGET files and this
file are excluded, and only the ten TEXT_SUFFIXES are opened. The docstring said
"every text file that names inscription.py" and disclosed only contracts/out/.

Not addressed here, deliberately: AUDIT-NOTE A1 at contracts/inscription.py:32
still quotes `op.falcon_verify(m, falcon_sig.bytes, pubkey)` while line 304
calls `.native`. Correcting it changes the contract's blob, which forces the
banner commit and CONTRACT_BLOB_AT to move in the same commit and every LIVE row
to be re-verified. That is its own change, and Brandon's call.

Tests: sdk suite 167 passed, 5 skipped (the same 5 as before this commit, none
from this file); this file alone 22 passed, 0 skipped; app-id rule replayed
independently - 23 tracked text files mention a 7xxxxxxxx id, all classified.

Security Impact: no protocol, contract or crypto code changes. contracts/ is
untouched. The only behaviour change outside sdk/tests/ is which events trigger
CI, which widens coverage. Three document-hygiene checks that could be walked
past now fail closed; nothing that failed before passes now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 0090c022 Branch test/audit-readiness-citations-current Document 2/201 ++ 16 --
Make verify_trelyan.py's approval comparison fail in a test too
670bc14 closed the review's mechanism-absent blocker for
contracts/verify_deployment.py: no test made its approval-program comparison
fail, though the module docstring claimed every comparison it prints can FAIL.
The identical gap in the reviewer script was left open. Four mutants of
sdk/examples/verify_trelyan.py survived the whole suite:

  VA1  the committed-TEAL assembly compared with itself
  VA2  the 2026-09-03 pin compared with itself
  VA3  the approval redeploy banner never printed
  VA4  the "approval program fetched" check made unconditionally true

Every existing case served the real 709 B approval bytes, so the pin and
assembly checks passed in all of them and nothing drove the drift path - the
same shape as the verify_deployment.py blocker, on the script the README's
headline points a reviewer at.

_run() now takes an approval_field, defaulting to the real program, so exactly
one side moves per case. test_a_differing_approval_program_fails_and_names_the
_redeploy serves a 709 B program differing in one flipped bit: exit 1, FAIL on
the pin and assembly checks only, "approval program fetched" still PASS, the
committed approval TEAL actually assembled, the redeploy banner printed, and
both fingerprints present in it. Equal lengths keep the banner's two sizes the
same, so only the fingerprints can tell the programs apart. The clear-state
checks are asserted unaffected.

The file is renamed test_verify_trelyan_clear_state.py ->
test_verify_trelyan_programs.py because it now covers both programs; nothing
referenced the old name, and it carries no app id, so the app-id rule does not
see the rename.

Mutation proofs redone from scratch this round against a scratchpad mirror
(never the worktree; each mutant applied once, source sha256 restored and
compared after each). 19 mutants of verify_deployment.py and verify_trelyan.py
all CAUGHT, including A1 (approval compared with itself), S7 (the app read via
--compile-url) and RA, the three the review reported as survivors. VA1, VA2 and
VA3 SURVIVED before this test and are CAUGHT by it.

NOT fixed, and deliberately not papered over: VA4 survives, and so does its
clear-state twin VC4. Both "... program fetched" checks only run once a program
has been read, so neither can fail where it stands; an absent field is NOT
CHECKED instead (db13751). Making them able to fail is a behaviour change to a
CI-visible script that no finding asked for, so it is reported rather than
guessed at. No docstring claims those two can fail.

Also unchanged: cd4051d's subject still over-states what is compared. Rewording
it needs a history rewrite, which this round was told not to do.

Checks: full sdk suite 181 passed, 5 skipped with the KAT armed (a
falcondet1024.dll built this round from the worktree's vendored src); the 5
skips are 4 algo-pqc-kit interop cases with the package not installed and 1
isolated-signer test whose 3.10 premise this interpreter does not meet - no
skip is counted as a pass. The three affected test files: 38 passed.
py_compile on the changed file. contracts/verify_deployment.py run live and
read-only against the deployed app: MATCH on all five components, exit 0.
App-id rule replayed independently over git ls-files with the rule's own
lookaround regex: FROZEN 7, LIVE_CLAIM 17, 23 files mention an id, 0
unclassified, 0 classified files missing. yaml.safe_load on ci.yml, rust-ci.yml,
testnet-followup.yml and testnet-redeploy.yml. The file is LF-only, has no NUL
bytes and is cp1252-encodable.

Security Impact: test-only, outside contracts/. No executable line of
verify_trelyan.py or verify_deployment.py changes, and no contract source,
committed TEAL, ARC-56 spec or deploy path changes. What changed: the reviewer
script's approval-program pin and assembly comparisons are now pinned as able
to fail, so a future edit that makes either unable to fail turns this file red.
What could break: nothing selects on the test file's name. Nothing needs
re-audit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 5fd367a7 Branch feat/whole-app-deployment-check Document 1/60 ++ 10 --
State the root-compile line count as 67 and test it against contracts/out
782dd09 rewrote the build-invocation sentences in CONTRIBUTING.md,
THREAT_MODEL_AND_TRACEABILITY.md and contracts/verify_teal_matches_source.py
and left their "124 differing lines" in place; README.md and
contracts/requirements.txt say the same. 124 was true when the phrase was
written in 58b61ff (2026-08-16): the approval TEAL then had 62
`// inscription.py:` comments, and a root compile removed and re-added each
one. The approval TEAL now has 67.

Measured with the pinned puyapy 5.8.1 on copies of the source outside the
tree. From contracts/ with the bare filename, all five artifacts match at
58b61ff and at HEAD. From a root layout, into an out-dir beside the source:
approval.teal -62/+62 at 58b61ff and -67/+67 at HEAD, arc56.json -1/+1 at
both, and no change to clear.teal or either .puya.map. An out-dir that is not
beside the source also changes one line of approval.puya.map.

The five places now say "67 lines of the approval TEAL" plus the ARC-56 JSON
line that embeds that TEAL. requirements.txt also mentions the .puya.map. The
verifier's history paragraph keeps 124 but dates it to 58b61ff.
THREAT_MODEL's "then reproduces" now says the byte-for-byte match applies to
the contracts/ invocation.

Check 6 in the citation test counts the lines holding `// inscription.py:` in
the committed approval TEAL. Each of the five documents must state that
number exactly once, and none may use the old "N differing lines" form. A
second test checks that the ARC-56 JSON embeds that TEAL on one line. The
committed documents fail check 6 at 782dd09, all five of them. In-file
mutation test h covers three cases: a TEAL with one comment fewer, the old
phrase restored in one document, and a count stated twice. Each fails.
Removing the old-form rule or the exactly-once rule from a scratch copy makes
test h fail. contracts/verify_teal_matches_source.py still exits 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit e575f333 Branch test/audit-readiness-citations-current Document 6/114 ++ 13 --
Fail a citation that passes on another copy of its needle
Review of 782dd09 found three places where the citation test's docstring
claimed more than the code enforced.

1. A needle was only required to appear on the cited line, never to be the
   copy the sentence means. THREAT_MODEL_AND_TRACEABILITY.md cites the SDK
   client's fallback at inscription.py:182 with the needle
   `self.app.send.inscribe(`, which the first attempt also holds (line 140).
   Inserting 42 lines above the first attempt put it on line 182, moved the
   fallback to 224, and every test still passed. stale() now requires a
   single-line row's needle to occur on exactly one line of its target, or the
   row to name (n, of): the cited line is the n-th of exactly `of` lines
   holding it. The :182 row declares (2, 2). A range row must hold at least
   one needle that occurs on one line only; every current range row already
   does.

2. The docstring said UNCHECKED rows cannot exempt a live document, but only
   rows of kind "dated" were held to a dated filename. A "not-a-contract-line"
   row in AUDIT_READINESS.md silenced an unreviewed (L306). Rows of either
   kind must now sit in a *_YYYY-MM-DD.md record.

3. The docstring now says what CI does not do: ci.yml's path filters do not
   include root-level documents, and both jobs that run `pytest tests` skip
   the schedule, so a change confined to AUDIT_READINESS.md, README.md,
   REVIEWER.md, CONTRIBUTING.md or THREAT_MODEL_AND_TRACEABILITY.md runs none
   of these checks. The workflow is unchanged.

New in-file mutation tests re-run the real test functions: the 42-line
insertion and a new copy landing on :182 (e), a range narrowed to a repeated
needle (f), and an exemption of each kind planted in AUDIT_READINESS.md (g).
Each fails. Deleting each new rule from a scratch copy makes its mutation
test fail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit ea45abd9 Branch test/audit-readiness-citations-current Document 1/135 ++ 13 --
Scope the remaining live-TestNet wording and cite the latest follow-up run
1e55383's body said every "deployment match" sentence now names what is
compared, but the same commit wrote the bare "Live TestNet deployment match"
into a ci.yml comment and two printed lines (ci.yml, rust-ci.yml), and kept
the 2026-09-03 green beside it, when that check compared the approval program
only. Those lines, and the older bare "Live TestNet match" in ci.yml's failure
branch and a rust-ci.yml comment, now say "the live TestNet comparison
(programs, state schemas, extra pages)"; the ci.yml comment also names what is
not compared (global-state contents, boxes, creator) and that the 2026-09-03
green compared the approval program only.

Other corrections:
  - README Status paragraph: "latest: run 34123818653, 2026-09-07" was no
    longer the latest. It now cites "latest on main as of 2026-09-17: run
    34846966733, 2026-09-14, on a886b7d, which compared the approval program
    only" (gh run list/view: push run 34830219541 and schedule run
    34846966733 on a886b7d both succeeded; job "Committed approval TEAL vs
    deployed approval program").
  - extra-program-pages was said to "equal the committed artifacts" or be
    compared "with the committed artifacts" (CONTRIBUTING.md, ROADMAP.md,
    DEMO.md, tutorial 04, README Status and reviewer paragraphs,
    LOCALNET_VALIDATION_2026-06-01.md, the spec's G2 paragraph,
    testnet-followup.yml's exit-code comment). No artifact declares a value:
    the expected value is the minimum the assembled committed programs need,
    which is what deploy_testnet.py's create() gets from algokit-utils 4.2.3
    (calculate_extra_program_pages, applied when extra_program_pages is not
    passed). Each sentence now says that, and says the schemas are compared
    with the committed ARC-56 spec.
  - testnet-followup.yml verify-live ::error:: text: a FAIL means the live
    app differs from the committed TEAL only when it is one of the two
    "deployed ... program is what the committed ... TEAL assembles to"
    checks; a pin FAIL alone means the app or the pin constant changed.

The ci.yml, rust-ci.yml and testnet-followup.yml ::error:: edits were written
by an interrupted earlier fix round of this workflow (07:03-07:04 on
2026-09-17) and reviewed here before committing.

Correction to db13751's Security Impact: Dockerfile.verify copies
contracts/out/ next to the script, so the hermetic container does run the
clear-state assembly check; it does not report it as not checked. The job to
re-verify there is reviewer-containers, which asserts "0 not checked".

Not fixed: cd4051d's subject, "Compare the whole deployed app, not only its
approval program", over-states what is compared (global-state contents, boxes
and the creator are not). Rewording it needs a history rewrite, which this
fix round was told not to do.

Checks: yaml.safe_load on the three workflows; the app-id rule replayed over
git ls-files (cached and untracked; FROZEN 7, LIVE_CLAIM 17, 23 files
mention an id, 0 unclassified); full sdk suite 180 passed, 5 skipped (KAT
armed).

Security Impact: text only - comments, printed strings and docs; no
executable logic, contract source, committed TEAL, ARC-56 spec or deploy path
changes, and nothing under contracts/. What could break: nothing selects on
the changed printed lines (no job or check-run name changes). Nothing needs
re-audit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit d21df597 Branch feat/whole-app-deployment-check Document 10/28 ++ 23 --
Report an absent clear-state program as not checked in verify_trelyan.py
sdk/examples/verify_trelyan.py read a missing clear-state-program as empty
bytes. Its "fetched", pin and assembly checks then FAILED, and it printed
"AWAITING TESTNET REDEPLOY ... The live clear-state program differs from the
committed clear-state TEAL" and exited 1, although no program had been read.
contracts/verify_deployment.py treats the same response as exit 2 (could not
check), and the reviewer script's own rule is that a check that did not run is
counted as NOT CHECKED, not as a failure.

Now an absent or empty clear-state-program makes all three clear-state checks
SKIP (not checked), so with nothing else failing the script exits 2; the
committed clear-state TEAL is not assembled, and the redeploy banner is printed
only when a program was actually read and differs. A present program is
checked exactly as before, so the live run is unchanged: 21 passed, 0 failed,
0 not checked against the TestNet app on 2026-09-17. One printed line also
stops saying extra-program-pages is compared "against the committed
artifacts": it is compared with the minimum the assembled programs need.

The clear-state checks had no offline test. sdk/tests/test_verify_trelyan_clear_state.py
runs the script with runpy against a stubbed urlopen (application, boxes and
/v2/teal/compile; any other request raises), serving the real 709 B approval
program so its pin passes, and covers three cases: a matching clear-state
program (exit 0, no FAIL or SKIP), an absent key or empty string (exit 2,
exactly the three clear-state SKIP lines, no FAIL line, no banner, clear TEAL
not assembled), and a differing program (exit 1, FAIL on the pin and assembly
checks, banner printed). The "trelyan-pq import" version is patched because
an uninstalled source tree reports "+source", which is not the path under
test.

Mutation proofs (scratchpad mirror, 37 tests, source sha256 restored after
each), all CAUGHT: V1 absent field read as empty and FAILED (the pre-fix
behaviour), V2 assembly check run when nothing was read, V3 that check silently
dropped instead of NOT CHECKED, V4 clear-state pin compared with the approval
pin, V5 assembly compared with itself, V6 banner never printed. All six
SURVIVED against HEAD's test files. Correction to 670bc14's body: it counted
25 verify_deployment.py mutants; the run had 23 (M01-M18 with M15b, A1, S7,
RA, BA), all CAUGHT, and 29 in total with V1-V6.

Security Impact: read-only reviewer tooling outside contracts/; nothing is
signed or sent. What changed: an algod response without a clear-state program
is now "not checked" (exit 2) instead of drift (exit 1). What could break:
testnet-followup.yml's verify-live job exits 2 instead of 1 for such a
response, and treats both as red. What must be re-verified: the verify-live
job on this branch, and the Dockerfile.verify container run, which copies the
script without contracts/out and so already reports the assembly checks as
not checked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit db13751e Branch feat/whole-app-deployment-check Document 2/173 ++ 9 --
Make every verify_deployment.py comparison fail in a test, approval first
The test module's docstring said every comparison verify_deployment.py prints
can FAIL, but no test made the approval-program comparison fail: replacing the
deployed approval bytes with the expected ones in build_components (mutant A1)
left the whole sdk suite green. A review of the branch found that and six more
survivors against cd4051d's tests: swapped num-uint/num-byte-slice or
ints/bytes reads (the committed schemas are symmetric, 1+1 and 0+0, so a swap
could never show), a missing approval-program, schema object or params object
read as empty, a DRIFT banner naming only the first differing component,
--recompile skipping the ARC-56 state.schema, and the deployed app being read
via --compile-url instead of --algod.

Added or extended, all offline (assemble/fetch_app_params or _get_json stubbed,
urlopen raising):
  - approval program differs: exit 1, its line is DRIFT, "differing: approval
    program", and both approval hashes and sizes in the banner;
  - two components differ: the exact "differing: clear-state program,
    extra-program-pages" line;
  - asymmetric committed schema (2 uints, 1 byte-slice) via a temporary
    --arc56, global and local: deployed 2+1 is MATCH, 1+2 is DRIFT;
  - a missing approval-program, clear-state-program, global-state-schema or
    local-state-schema, and a response with no params object or a non-object
    params: exit 2, no MATCH or DRIFT line;
  - --recompile with a fresh approval TEAL that assembles differently, and
    with a fresh ARC-56 state.schema that differs: exit 1, FAIL line;
  - --compile-url routes both assemblies and not the app read: the fetch stub
    records its algod argument, asserted to be the explicit --algod.
The component-line helper now matches only MATCH/DRIFT lines, because the
approval banner line also contains "approval program ... committed".

The docstring now says five components are compared and that global-state
contents (including the admin address), box contents and the creator are not,
and it drops the 2026-09-14 "until" date: origin/main still compares the
approval program only, so that date was a local commit date, not a change on
main. cd4051d's subject ("Compare the whole deployed app") over-states the
same way; it is not reworded here because that would rewrite history.

Most of these tests were written by an earlier fix round of this workflow
(scratchpad wafix_mutate.py, 07:02-07:06 on 2026-09-17), which was interrupted
before committing; they were reviewed here, and the approval-drift,
recompile-approval and algod-routing tests were added.

Mutation proofs (scratchpad mirror, never the worktree; each mutant applied
exactly once, all 37 tests of this file, test_testnet_drift_banner.py and
test_verify_trelyan_clear_state.py collected, source sha256 restored after
each): 25 mutants of verify_deployment.py, all CAUGHT by their named tests,
including A1 (approval compared with itself), S7 (app read via
--compile-url), RA (--recompile approval TEAL compared with itself), M12/M13
(swapped schema counts), M14/M15/M15b/M16 (missing fields read as empty), M17
(banner names only the first component) and M18 (--recompile schema check
disabled). Against HEAD's test files A1, S7 and RA SURVIVED (20 ran, 0
failed), so these tests are what kill them.

Security Impact: test-only. No executable line of contracts/verify_deployment.py
changes; no contract source, committed TEAL, ARC-56 spec or deploy path changes.
What changed: the exit-0/1/2 contract of verify_deployment.py is now pinned for
all five components, the missing-field rules and --compile-url routing. What
could break: a future edit that makes any of those comparisons unable to fail
now turns this file red. Nothing needs re-audit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 670bc148 Branch feat/whole-app-deployment-check Document 1/161 ++ 16 --
Scope README and tutorial pin claims to source; correct harness notes
2824b51 missed two sentences of the same kind. README.md said the pinned
Falcon C source is what "the AVM verifier also runs", and tutorial 02 said
the signer is "the same code path Algorand uses for State Proofs". What was
checked is source: go-algorand's go.mod and go.sum resolve algorand/falcon
v0.1.0 (ce15e75b) at master and v5.0.2-stable, crypto/merklesignature signs
and verifies through crypto.FalconSigner/FalconVerifier, and those call
falcon_det1024_keygen, _sign_compressed and _verify_compressed through cgo,
the same functions the SDK binds. Which build any node runs was not
checked. Both sentences now say so, and test_pin_claims_are_source_level.py
retires "verifier also runs" and "the same code path algorand uses". The
shorter phrase is not retired: the protocol spec states it under an
[ASSUMPTION/PLATFORM] tag.

2824b51's message and the test docstring said the first review found the
wording in eight more files. It was seven: AUDIT_READINESS.md,
PINNED_BUILD.md, REVIEWER.md, sdk/README.md, sdk/docs/DEMO.md, the verify
fuzz harness and test_binding_surface.py. The docstring now says seven and
names the two files the second review found.

PROVENANCE.md called the directory "a byte-for-byte subset" of the pinned
commit. Its own Layout section says src/ is the complete tree. That was
re-checked: the 27 files of src/ are the same path set as the upstream git
tree at ce15e75b (no symlinks or submodules), and Go dirhash h1 over them
equals go.sum's h1:xl832kfZ... The sentence now says src/ is a byte-for-byte
copy of the complete tree.

The fuzz harness comment said the harness skips the opcode's 1793-byte
public-key check. It does not: it always passes a 1793-byte buffer. Only
the non-empty-signature check is skipped. The WHAT WE MUTATE note said
pubkey length is unconstrained (it is fixed) and that over-long signatures
are exercised. The signature length is data[0] % size, so it is at most
255 bytes, shorter than every KAT signature (1232 or 1233 bytes). The
comment now says so. No harness code changed.

Docs, comments and one test only. No change under
third_party/falcon-det1024/src, SHA256SUMS, the pin or build flags.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 16eaa96a Branch docs/provenance-go-mod-requires Document 5/30 ++ 13 --
Scope the remaining pin claims to go-algorand's source, not nodes
ad1f6c0 fixed PROVENANCE.md but left the same claim in eight places.
PINNED_BUILD.md, REVIEWER.md, AUDIT_READINESS.md, sdk/README.md,
sdk/docs/DEMO.md, the verify fuzz harness and test_binding_surface.py
still said the pinned code is what the network, the chain or the opcode
runs. What was checked is source: go-algorand's go.mod requires
algorand/falcon v0.1.0 and go.sum pins these bytes. Which build any
TestNet or MainNet node runs was not checked, and each site now says so.

test_binding_surface.py also still cited
FALCON_PIN_BUMP_EVIDENCE_2026-08-11.md, which does not exist. It now
cites PROVENANCE.md. The fuzz harness comment now says the opcode
reaches the same C function only after Go-side checks the harness skips
(1793-byte public key, non-empty signature), under different flags.
PROVENANCE.md's h1 recipe now states the line order and the newline;
the old wording gave a different hash when read literally.

Two guards, because a review showed reverting PROVENANCE.md passed the
whole suite. test_pin_claims_are_source_level.py fails if any retired
node-level sentence comes back, or if PROVENANCE.md or PINNED_BUILD.md
stops saying node builds were not checked. test_cited_documents_exist.py
now also scans code and workflow files for known-absent documents.
Both were mutation-tested against each reverted file.

Docs, comments and tests only. No change under
third_party/falcon-det1024/src, SHA256SUMS, the pin or build flags.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 2824b51d Branch docs/provenance-go-mod-requires Document 10/176 ++ 19 --
Test that every inscription.py line citation still names its construct
AUDIT_READINESS.md maps I1-I5 / C1-C5 to line ranges in contracts/inscription.py.
Those ranges went stale once already: the contract changed after the sheet's
"as of 2026-06-17" date and nothing noticed, so (for example) the falcon_verify
citation landed on the write-once assert. PR #47 re-pointed them to 205d874 with a
one-off script. This makes that check part of the sdk suite.

sdk/tests/test_inscription_line_citations_are_current.py extracts every citation of
an inscription.py line (path:N, path:N-M, a bare :N beside a path:N, L-numbers with
hyphen or en dash, and "line"/"Lines" lists) from every text file that names
inscription.py. Each must match exactly one reviewed row. LIVE rows (35) carry exact
substrings chosen from the citing sentence and must appear inside the cited line or
range, of the contract or of the SDK client for the sentences about it. UNCHECKED
rows (18) are dated 2026-06-01 records of the pre-compile draft and tokens that are
not lines of the file, and a "dated" row must sit in a dated filename. The test fails
on an unlisted citation, an orphaned row, a construct no longer in its span, or a
contract blob that no longer matches the commit the sheet's banner names. The count
extracted must be non-zero and equal the table size (53).

Mutation tests re-run the real test functions against monkeypatched inputs: two lines
inserted above _build_message, a planted (L305), a deleted (L302), and an empty scan
each fail. SKIP_DIRS and REPO are held identical to test_cited_documents_exist.py.

Writing the table found `// inscription.py:156` in CONTRIBUTING.md,
THREAT_MODEL_AND_TRACEABILITY.md and the verify_teal_matches_source.py docstring,
described as a comment the committed TEAL carries. contracts/out/ stopped carrying it
in 14515d4 (2026-08-27) and line 156 of the contract is blank. Those sentences give the
comment's form, so they now say NNN, as the verifier's docstring and ci.yml already
did. Docstring and prose only; no code path changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 782dd09a Branch test/audit-readiness-citations-current Document 4/680 ++ 7 --
Say exactly what the deployment check compares, everywhere it is claimed
cd4051d made contracts/verify_deployment.py compare five components of the
TestNet application: the approval program, the clear-state program, the
global and local state schemas, and extra-program-pages. Eighteen files still
described that check as approval-program-only ("clear-state not compared",
"approval program only", "bytecode match"). Those sentences now under-claim,
and a bare "deployment match" could be read as the whole application. Each one
now names what is compared, and wherever a reader could take it as the whole
app it also says what is not: global-state contents (including the admin
address), box contents and the creator.

Covered: job and step names, ::error:: text and comments in
testnet-followup.yml (the contract-drift job is renamed "Committed artifacts vs
deployed app - programs, state schemas, extra pages (follow-up; not a merge
gate)", and BLOCKERS.md step 7 names it); comments and printed lines in
ci.yml, rust-ci.yml and testnet-redeploy.yml; README, REVIEWER.md,
AUDIT_READINESS.md, the BLOCKERS.md redeploy checklist and success line,
CONTRIBUTING.md, ROADMAP.md, the spec's G2 paragraph, the LocalNet record's
status banner, DEMO.md and tutorial 04; Dockerfile.verify and
scripts/verify_all.sh; and the docstrings of verify_teal_matches_source.py and
verify_client_matches_arc56.py. The REVIEWER.md and AUDIT_READINESS.md pin
tables gain the clear-state fingerprint (82924751..., 4 B), the schemas
(global 1 uint + 1 byte-slice, local 0 + 0) and extra-program-pages 0, and the
retarget lists gain PINNED_CLEAR_STATE_SHA512_256.

Evidence the docs cite comes from read-only runs on 2026-09-17 against app
770964251: verify_deployment.py printed MATCH for all five components (exit 0)
and verify_trelyan.py printed 21 passed, 0 failed, 0 not checked. The
2026-09-07 CI runs (34123818653, 34123725705) are still cited and now say they
compared the approval program only. Dates for when the new comparisons were
added are left out, because they would read as merge dates on main.
Historical records (BLOCKERS.md's closed-drift section, the 2026-09-03 18/18
result) are left as measured. THREAT_MODEL_AND_TRACEABILITY.md needed no
change: it makes no comparison claim, and its "Replace the approval program"
row is about on_update, which is still accurate.

Security Impact: text only. Under contracts/, two docstrings change
(verify_teal_matches_source.py, verify_client_matches_arc56.py); no executable
line, contract source, committed TEAL, ARC-56 spec or deploy path changes.
What could break: renaming the contract-drift job renames its check run, so
anything selecting the old name "Committed approval TEAL vs deployed approval
program (follow-up; not a merge gate)" stops matching. The workflow and
BLOCKERS.md say it is not a required check; GitHub branch protection was not
read. What must be re-verified: the TestNet follow-up should show the renamed
job green on this branch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit 1e553833 Branch feat/whole-app-deployment-check Document 18/88 ++ 62 --
Compare the whole deployed app, not only its approval program
PR #47's first follow-up. contracts/verify_deployment.py compared one
component of the TestNet application: the approval program. The clear-state
program, both state schemas and extra-program-pages were never compared, so a
deployment could differ from the committed artifacts in any of them and the
check still printed MATCH.

verify_deployment.py now compares five components, prints one line for each,
and exits 0 only when all five match:
  - approval program: assembled committed approval TEAL vs deployed bytes;
  - clear-state program: assembled contracts/out/TrelyanInscription.clear.teal
    vs params["clear-state-program"];
  - global-state-schema and local-state-schema: ARC-56 state.schema
    (ints/bytes) vs num-uint/num-byte-slice, a missing count reading as 0;
  - extra-program-pages: the minimum the two assembled programs need,
    max(0, (len(approval) + len(clear) - 1) // 2048). Neither artifact
    declares a value: the ARC-56 file has no field for it, and
    deploy_testnet.py calls create() without extra_program_pages, so
    algokit-utils v4 fills in exactly this minimum. An absent field reads
    as 0, because algod omits it when it is zero.
On DRIFT the banner names every differing component. The exit codes are
unchanged: 0 match, 1 drift, 2 could not check. A missing params object,
program or schema object, or an unreadable ARC-56 state.schema, exits 2.
--compile-url is used for both assemblies. --recompile now also re-derives
the clear-state TEAL and the ARC-56 state.schema. print_awaiting_redeploy
keeps every substring test_testnet_drift_banner.py asserts.

sdk/examples/verify_trelyan.py checks the clear-state program the way it
checks the approval program: it is fetched, compared with
PINNED_CLEAR_STATE_SHA512_256 (8292475190892234..., 4 B), and compared with
what the committed clear-state TEAL assembles to, or reported as not
checked. The pin was computed on 2026-09-14 from the live app and from the
assembled committed TEAL, and the two agreed. Against the live app the
script now reports 21 passed, 0 failed, 0 not checked.

sdk/tests/test_verify_deployment_whole_app.py needs no network: it stubs
assemble() and fetch_app_params(), and makes urlopen raise. It covers a
clear-state drift while the approval program matches (exit 1, clear-state
named), a drift in either schema (exit 1), an extra-pages drift (exit 1), a
missing clear-state-program (exit 2), all components matching (exit 0), a
zero count omitted from a schema object, --compile-url on both assemblies,
--recompile on the clear-state TEAL, and the page formula at its
boundaries. Each test was mutation-proven: the comparison it guards was
broken in the source, the test failed, and the source was restored.

Security Impact: this change touches only read-only verification tooling
under contracts/ and the reviewer example. No contract source, committed
TEAL, ARC-56 spec or deploy path changed, and nothing is signed or sent.
What changed: a MATCH now also requires the clear-state program, both
state schemas and extra-program-pages to equal the committed artifacts.
What could break: an algod that omits clear-state-program or a schema
object now makes the check exit 2 instead of passing on the approval
program alone. A future deploy that passes a non-minimal
extra_program_pages will show as DRIFT until this formula is updated. And
PINNED_CLEAR_STATE_SHA512_256 must be retargeted on any redeploy whose
clear-state TEAL changes. What must be re-verified: the TestNet follow-up
(contract-drift and verify-live) should go green on this branch; a local
read-only run on 2026-09-14 printed MATCH on all five components for the
current app. Still NOT compared: global-state contents (including the
admin address), box contents, and the creator.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit cd4051d4 Branch feat/whole-app-deployment-check Document 3/633 ++ 113 --
Say go-algorand requires falcon v0.1.0, not that it vendors it
PROVENANCE.md, a release.yml comment and a test docstring said go-algorand
"vendors" algorand/falcon@ce15e75b, and PROVENANCE.md went on to say that
commit is what the AVM falcon_verify opcode "actually runs". Neither was
checked. PR #47 left the PROVENANCE sentence as a deliberate exception.

Re-verified on 2026-09-14 from primary sources:
- go-algorand's go.mod requires github.com/algorand/falcon v0.1.0 with no
  replace directive, on master (3f804559) and at v4.3.0-stable (3e5d694b).
- git ls-remote: tag v0.1.0 (object ebbdb56e) peels to ce15e75b; the Go
  module proxy's v0.1.0.info records the same Origin.Hash.
- go.sum at both refs pins v0.1.0 to h1:xl832kfZ...; recomputing Go's
  dirhash h1 over the 27 vendored files under src/ gives the same value.
- go-algorand has no vendor/ directory at either ref.
- opFalconVerify -> crypto.FalconVerifier.VerifyBytes -> the module's
  PublicKey.Verify, a cgo call into falcon_det1024_verify_compressed.

What any TestNet or MainNet node runs was not checked, and the text now
says so. The do-not-bump reason is restated in those checkable terms,
replacing an unmeasured "would break byte identity against the chain".

Docs and comments only. Nothing under src/ or SHA256SUMS changes, and the
integrity step hashes only src/, so the vendored-tree check is unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit ad1f6c04 Branch docs/provenance-go-mod-requires Document 3/42 ++ 13 --
Make the repo's in-tree public claims checkable (#47)
Docs, comments, printed strings, CI trigger paths and step/job names only; no signing, verification or contract logic change. Reviewed over nine rounds (claims auditor, adversary, council_adversarial). CI on 3cd8029: 38 pass, 4 skipped by design.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Git Commit a886b7d6 Branch main Document 46/291 ++ 227 --