Skip to content

feat(G-11): shared-file write contention — row PRs never write the DAG, roadmap, spec block or README counts; DAG status derived from receipts; README counts a ratchet (PMAT-1062) - #3020

Merged
noahgift merged 8 commits into
mainfrom
agent/G-11
Sep 6, 2026

Conversation

@noahgift

@noahgift noahgift commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

PP-066 DAG row G-11 (driver v4: G-11a) · ticket PMAT-1062 · Closes #3012 · epic #2873. Receipt: docs/audits/impl-PMAT-1062-receipt.md.

Why. Eight armed row PRs (#3001, #3003–#3009) each hand-edited pp-066-dag.yaml (status), roadmap.yaml (pmat work complete) or a README count line; every merge made the other seven DIRTY through a queue that lands ~1 PR/hour. None of those files is a row's to write.

What lands.

  1. scripts/check_row_pr_write_set.sh — the DAG and the release spec are orchestrator-only on every branch (agent/pp-066-*, agent/pr-triage*); a row PR (agent/<id>, <id> a DAG row, read at the base) additionally may not write roadmap.yaml or a README count line. --no-renames (a rename's source is a write); merge_group/push print REPORT and exit 0 (judged at the pull_request run, which is required: gate needs guard-runner-labels, ruleset "Green Main"). 14-row case table.
  2. scripts/lib/dag_status.py — a row's status is derived from docs/audits/impl-<pmat_id>-receipt.md (the C0-7 marker rule, byte-faithful: CRLF and mid-string quotes behave exactly as check_receipt_complete.sh). render_dag.py prints it; dag_invariants.py D7 refuses a typed status that disagrees; past-expiry reads it. D7 rows 12–16.
  3. scripts/check_readme_claims.sh and crates/aprender-core/tests/readme_contract.rs (FALSIFY-README-005/007) — counts are a ratchet: lag allowed, overstatement RED, --exact for the orchestrator; a self-contradicting README RED. 7-row case table. (The Rust tests rode workspace-test and would have failed every row PR that left the README lagging.)
  4. ci.yml guard-runner-labels: README case table before its live step; write-set case table + live step after the DAG invariants.
  5. Contract contracts/apr-row-pr-write-set-v1.yaml (kind: pattern; WS-OB-001..004 ↔ WS-F-001..004). pv validate: valid.

Mutation evidence (I3) — on this branch, never in the queue.

leg commit what run
RED (README ratchet, row 3) 053eee448 + c245dc24c (semantic) README claims must match measurement FAILED run 34038067035, job 101499760324
RED (D7, rows 12/14/15/16) 2a9ab0df6 (README mutant reverted, D7 + write-set kept) DAG-invariants guard case table FAILED run 34038496093, job 101500915181
RED (write-set, rows 2/9/11) eda2ea746 (D7 reverted, write-set kept) Row-PR write-set case table FAILED run 34040294692, job 101505945716
GREEN d9c2aeff2 (the last revert; receipt status: complete) guard-runner-labels SUCCESS (14/14 · 16/16 · 7/7) run 34041439234

A first run (34037532260) failed at the bashrs shrink-only step (8 → 11: SC2075 ×2 in the new guard, SEC011 ×1 in the README self-test) — a real defect of this branch, fixed in 9a997e653; the job stops at its first failing step, hence one RED run per guard.

Acceptance (.pr/G-11/accept.sh equivalent, re-run by the orchestrator after the rebase onto main b0a0a51 — .pr/G-11-verify3.log):

bash scripts/check_row_pr_write_set.sh --self-test      # 14/14
bash scripts/check_dag_invariants.sh --selftest         # 16/16
bash scripts/check_readme_claims.sh --self-test         # 7/7
python3 scripts/render_dag.py --check                   # byte-identical (91 rows on main)
bash scripts/check_guards_are_wired.sh                  # PASS (ratcheted)
cargo test -p aprender-core --test readme_contract      # 15 passed (own target dir, pinned cargo)

Review quorum: 3 agy lanes, 3/3 implement-with-changes; every finding re-verified and folded (disposition table in the receipt): the non-agent/<id> bypass, --no-renames, CRLF/quote parity, the drift Catch-22 stated in the message, cli_command_count through compare_count, the Rust README tests, case-table order. Q2 (is the pull_request run required?) settled by the ruleset: gate requires guard-runner-labels.
Write set: scripts, tests, contracts/, ci.yml (one job's steps), this receipt. No DAG/roadmap/README/spec edit — the rule, obeyed by its own PR (the README lags by one contract, which the ratchet permits).

…DAG, the roadmap, the spec or a README count line (check_row_pr_write_set.sh, 11-row case table); a DAG row's status is DERIVED from its receipt (scripts/lib/dag_status.py; render_dag.py prints it; dag_invariants.py D7 refuses a disagreeing typed status; past-expiry reads it); README counts are a ratchet (lag allowed, overstatement RED, --exact for the orchestrator; 7-row case table); contract apr-row-pr-write-set-v1; wired case-table-then-live (PMAT-1062)

Pmat-Ticket: PMAT-1062
…strator-only on EVERY branch (a PR from a non-agent/<id> branch no longer walks through), --no-renames with the DAG read at the base (a rename is a write, not ENV), CRLF/quote parity between dag_status.py and check_receipt_complete.sh (D7 row 16), the drift message states the partial-then-orchestrator discipline, cli_command_count through compare_count, README case table before its live step, and the Rust README tests (FALSIFY-README-005/007) become the same lag-allowed ratchet — they rode workspace-test and would have failed every row PR that left the README lagging (PMAT-1062)

Pmat-Ticket: PMAT-1062
…he DAG dropped from rule 1 (write-set row 2), README equality restored (README row 3), derived_status trusts the typed key (D7 rows 12/15). REVERTED in the next commit; the PR body cites both run ids (PMAT-1062)

Pmat-Ticket: PMAT-1062
@github-actions

github-actions Bot commented Sep 6, 2026 •

Copy link
Copy Markdown

§13.11 rung 1 — quorum shadow verdict

S13-SHADOW pr=3020 head=d9c2aeff2bd66d1ae7158c4bed4737411726a023 verdict=REFUSE class=Q1 arm_rc=1

Shadow mode: this records a verdict and merges nothing. A refusal
to arm is not a block (§13 adds zero rows to §7) — the pull request is
exactly as green as it was.

…wo refusal messages (SC2075), the README self-test scratch dir through safe_rm_scratch (SEC011); 8 -> 8 on the runner's count (the mutants of 053eee4 stay in place for the RED leg)

Pmat-Ticket: PMAT-1062
…e lag branch), not a syntax error — row 3 RED for the right reason

Pmat-Ticket: PMAT-1062
…RED on 'README claims must match measurement' (row 3, lag RED). The D7 and write-set mutants stay for the next RED leg

Pmat-Ticket: PMAT-1062
…on 'DAG-invariants guard case table' (rows 12/14/15/16). The write-set mutant stays for the last RED leg

Pmat-Ticket: PMAT-1062
…6) was RED on 'Row-PR write-set case table'; all three registered mutations proven RED at CI (34038067035 / 34038496093 / 34040294692); receipt PMAT-1062 complete (the receipt says complete inside the PR before auto-merge is armed)

Pmat-Ticket: PMAT-1062
@noahgift
noahgift enabled auto-merge September 6, 2026 15:10
@noahgift noahgift added pp-066 PP-066 (0.66) DAG row inst:A PP-066 instance claim (I14): inst:A labels Sep 6, 2026
@noahgift
noahgift added this pull request to the merge queue Sep 6, 2026
Merged via the queue into main with commit 3792afa Sep 6, 2026
17 of 18 checks passed
@noahgift
noahgift deleted the agent/G-11 branch September 6, 2026 17:38
noahgift added a commit that referenced this pull request Sep 6, 2026
crates/apr-cli/tests/cli_commands.rs::get_help_commands and ::help_subcommands
fell under both thresholds when the registry test was rewritten; the ratchet
refuses a kept row for a fixed function (the next regression at that coordinate
would land for free). Verified locally: check_complexity_ratchet.sh rc=0,
689 recorded offenders, 2 removed, none new, none grown, none stale.

Also drops this branch's README count bump: G-11 (#3020) makes the README counts
a ratchet the orchestrator regenerates, and check_row_pr_write_set.sh refuses a
count line on a row branch. PASS: row PR agent/R-0 writes no shared file.

(PMAT-989, #2904)
noahgift added a commit that referenced this pull request Sep 7, 2026
…ed tree — main gained analyser mentions (#3020, #3030) after the first stamp; the baseline is introduced by this PR, so its initial count is the merged tree's

Pmat-Ticket: PMAT-1063
noahgift added a commit that referenced this pull request Sep 8, 2026
…nly in release-assets.yml at refs/tags/v*; base-owned promotion; derived fail-closed publish cascade; KEY row (#3045, PMAT-1079); spec v2.1

Spec v2.1 (Appendix A 2.1) and DAG (103 rows) record the delta of 2026-09-08:

- BUILD != TEST. Assets build under the clean-room recipe (scripts/run_clean_room.sh, the
  forjar-pinned toolchain, fingerprint recorded); GPU verification is the fleet-verify receipt
  taken against the asset, never a build log.
- The x86_64-cuda asset (= apr-x86_64-unknown-linux-gnu, cli,cuda per D-10) builds on lambda only
  inside release-assets.yml at a v* tag: runner group gpu-release restricted to that workflow at
  refs/tags/v*, a JIT ephemeral runner for one job, lambda's queue slot claimed (host_queues.lambda
  4; S-1 -> 5, S-2 -> 6). Every other target: the CI clean-room runner.
- Promotion is a base-owned workflow_dispatch job over four receipts carrying the asset sha256 with
  C14 PASS and parity != skipped. No workflow runs cargo publish; scripts/publish_cascade.sh derives
  its set from cargo metadata in topological order and refuses branch/dirty/prerelease/token.
- New row KEY (#3045, PMAT-1079, owner noahgift, expiry 2026-10-02 [U]): until
  keys/apr-release-minisign.pub is on main the manifest job and the C13 gate refuse and R-5 stays
  blocked_by KEY; DONE-IF present -> R-6 pins its fingerprint. R-5/R-6/TAG-0.66.0 <- KEY.
  The gpu-release group stays a blocked_by: RUNNER-GROUP note on R-5, as the delta directs.
- R-5 <- G-11b: make fleet-verify is G-11b's deliverable and is absent today [V].

Two corrections this session's verification pass found by measuring rather than reading:
- The delta's embedded-SASS premise is false for this binary. apr generates PTX text in Rust
  (crates/aprender-gpu/src/ptx/) and the driver JIT-compiles it, cubins landing in
  ~/.cache/trueno/ptx (driver/ptx_cache.rs:3), so nothing SASS-shaped ships. The A now requires
  cuobjdump --list-elf to list NO ELF and reads the emitted PTX's .target on both hosts.
- PMAT-1078 was not free: agent/R-5's contracts/apr-publish-cascade-v1.yaml:4 stamps it. KEY took
  PMAT-1079. An id is taken the moment a branch writes it, minted or not (pmat#1169 class).

Also recorded: the three divergences of agent/R-5 (authored at 19c015f before this delta) that
the row PR closes - an aarch64-cuda asset on gx10, .github/release-assets.pub, hosted builders;
its promotion gate and cascade already match [V]. G-11's typed status flipped to complete from
docs/audits/impl-PMAT-1062-receipt.md (#3020 merged 3792afa) and the §5.0 block re-rendered -
D7 and render_dag.py --check were RED on this branch before this commit.

Guards on this tree: render_dag.py --check PASS (byte-identical, 103 rows) - check_dag_invariants.sh
PASS - check_receipt_complete.sh --dag PASS - check_roadmap_diff_additive.sh PASS (lifecycle only;
acceptance_criteria is not a lifecycle field) - check_roadmap_ids_unique.sh PASS (822) -
check_no_claim_literals.sh PASS - check_perf_claims_cite_receipts.sh PASS -
check_row_pr_write_set.sh ok (orchestrator branch).

Pmat-Ticket: PMAT-993
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X1cW8TnmNe3hgjragNjUxr
noahgift added a commit to guyernest/aprender that referenced this pull request Sep 13, 2026
…ms ratchet, executable criteria), DAG rows/edges/amendments, decision receipts, roadmap mints, rescope quorum record (paiml#3025)

* docs(PP-066): PHASE 0 reconcile status 2026-09-06 — main is vacuously green (ratchet SKIPPED under pmat 3.31.0 at 04:35Z, ARMED and RED under 3.37.0 from 07:53Z, cited from job logs); only agent/G-10 unpushed (PR-A); C0 uncredited; D-2..D-11 recorded on paiml#2873

Pmat-Ticket: PMAT-966

* docs(PP-066): orchestrator write-back 2026-09-06 — DAG rows G-11 (paiml#3012, PMAT-1062), G-10b (paiml#3013, PMAT-1063), G-10c (paiml#3014, PMAT-1064), U-1 (paiml#3015, pmat#1200, expiry = C0-3 - 6 d), S-0 (paiml#3016, D-3 speed lane on perf-solo); amendments: P-1.1/P-1.2 -> 0.67 (D-11), C0-3 blocked by U-1 (R4), G-10 expiry 10-03 -> 09-12 (PR-A armed); §5.0 re-rendered (96 rows); roadmap mints PMAT-1061..1064 by hand (pmat#1169)

Pmat-Ticket: PMAT-966

* docs(PP-066): decisions D-2/D-3/D-5/D-8/D-9/D-10/D-11 recorded — seven decision receipts (status: complete, each citing its paiml#2873 comment), DEC rows complete, roadmap tickets PMAT-1018..1023 + PMAT-985 completed with proof, §5.0 re-rendered

Pmat-Ticket: PMAT-966

* docs(PP-066): roadmap — PMAT-1018..1023 and PMAT-985 (decisions D-2/D-3/D-8/D-9/D-10/D-11/D-5) completed with proof (the paiml#2873 comments and their decision receipts)

Pmat-Ticket: PMAT-966

* docs(PP-066): ordering commit (driver v4) — rows L0-1 (paiml#3017, P0), G-11b (paiml#3018), R-8 (paiml#3019); R-0a/R-0b split folded from paiml#3003 (R-0b paiml#3002 PMAT-1060, design-quorum record carried over); edges L0-1/G-11/G-11b <- G-10, every open 0.66 row <- G-11, C0-3 <- U-1, R-0b <- R-0+L0-1, R-2 <- R-0b+D-9, B-G1/R-5 <- R-2, R-6/R-8 <- R-5, R-7 <- R-6, T-0 <- L0-1, TAG-0.66.0 <- every 0.66 row; amendments for the four slack violations the edges exposed (G-10 -> 09-06, R-3 -> 09-19, R-2 -> 10-02, B-G1 -> 10-09); §5.0 re-rendered (100 rows)

Pmat-Ticket: PMAT-966

* docs(PP-066): ordering commit fix-up — I-18 expiry (anchor I-15 + 7 d = 10-03) -> 2026-10-09 for the R-2 -> I-18 edge; check_dag_invariants.sh exit 0 at 100 rows

Pmat-Ticket: PMAT-966

* docs(PP-066): G-10 (PMAT-1059) complete — paiml#3011 merged b0a0a51; receipt marker flipped, roadmap completed with proof, estimates row (turns 15, delegate tokens 64665, wall 2700 s, basis first-run [U])

Pmat-Ticket: PMAT-1059

* docs(PP-066): DAG row G-10 complete (paiml#3011 merged b0a0a51); §5.0 re-rendered

Pmat-Ticket: PMAT-1059

* docs(PP-066): tickets minted by hand for the rows created this session — L0-1 PMAT-1065 (paiml#3017, P0), G-11b PMAT-1066 (paiml#3018), R-8 PMAT-1067 (paiml#3019), S-0 PMAT-1068 (paiml#3016), U-1 PMAT-1069 (paiml#3015); DAG pmat_ids written; §5.0 re-rendered

Pmat-Ticket: PMAT-966

* docs(PP-066): SPEC-2.0 rescope in the DAG (driver v5) — 18-row 0.66 scope; 39 rows -> 0.67 each with cut_by and the claim it protected; L0-1 split into L0-1a (bounded) + L0-1b (unbounded); SPEC-2.0 row; C0-2 (pin); B-G1 folded into R-7; v5 edges; TAG-0.66.0 <- every kept row; invariants exit 0 at 102 rows; §5.0 re-rendered

Pmat-Ticket: PMAT-966

* docs+scripts(SPEC-2.0): spec v2.0 §4.1 — three claims, the 18-row scope and the 39 cut rows with the claim each protected (generated from the DAG), the claims ratchet, the executable criteria table; scripts/release_criteria.sh (C0 C4 C5 C6 C7 C8 C9 C11 C13 C14 one exit-coded command each, C0 first through the analyser pin, never vacuous, 6-row case table; C1 C2 C3 C10 C12 -> 0.67); scripts/run_clean_room.sh (C8 via ../infra beside the main checkout, ENV exit 2 otherwise)

Pmat-Ticket: PMAT-966

* docs(SPEC-2.0): rescope quorum record (scope-holds-with-changes; the scope-fails premise on C3 refuted by the spec: R-0b ships the resolution) — nine claim removals assigned to R-7, C5 -> 0.67 (Q3 unanimous), the ratchet-universe sentence corrected, L0-1a/L0-1b cite paiml#2971 (paiml#3017 closed as duplicate), SPEC-2.0 = paiml#3023; release_criteria.sh credits nine

Pmat-Ticket: PMAT-966

* docs(SPEC-2.0): the rescope record cites the hits by file:line without repeating the literals (the claims ratchet covers docs/audits too — it went RED on its own record)

Pmat-Ticket: PMAT-966

* docs(PP-066): session docs commit 2026-09-06 — tickets minted/completed from the DAG and the receipts, README counts exact, status doc, kaizen

Pmat-Ticket: PMAT-966

* docs(SPEC-2.0): the rescope record cites the spec line its verdict rests on (R-0b ships the resolution) and names C5's residue row (T-0h, 0.67) — driver v5.2 DONE-IF

Pmat-Ticket: PMAT-966

* docs(PP-066): renumber R-0b's ticket PMAT-1060 -> PMAT-1073 (PMAT-1060 is minted by paiml#3027, BSE-001 H4); mint PMAT-1072 for the paiml#3028 main-red hotfix (PR paiml#3030)

Pmat-Ticket: PMAT-1071

* docs(PP-066): driver kaizen — hotfix DONE-IF re-lists PRs; instrument change vs data defect; pre-commit complexity expansion; arms before instrument; checkout restores the index

Pmat-Ticket: PMAT-1071

* docs(PP-066): driver kaizen — three-family quorum mechanics; measure a criterion's distribution before designing a fallback; a PATH tool is not a pin

Pmat-Ticket: PMAT-1071

* ci(PP-066): release_criteria.sh --self-test runs in guard-runner-labels — the criteria script is a decision surface and check_guards_are_wired.sh refused it unwired

Pmat-Ticket: PMAT-1071

* docs(PP-066): session 2026-09-07 — status doc, kaizen (hook expansion, env arm first, update-branch pull), PMAT-1072 completed (proof:PR#3030)

Pmat-Ticket: PMAT-1071

* docs(PP-066): drop two duplicate top-level roadmap entries (title-id twins of [19] and [66]) the 2026-09-06 re-serialisation appended — main's duplicate-id guard refuses them

Pmat-Ticket: PMAT-1071

* docs(PP-066): decision rows D-5/D-2/D-3 cite their receipts as proof; the issue-comment URL stays as prose (the completion guard dereferences paths and merged PRs only)

Pmat-Ticket: PMAT-1071

* docs(PP-066): every decision row cites its receipt path as proof; issue-comment links stay as prose (the completion guard dereferences paths and merged PRs only)

Pmat-Ticket: PMAT-1071

* docs(PP-066): kaizen — never bare git stash (shared stack); the complexity hook charges a file's whole include! expansion, declare modules from a clean included file

Pmat-Ticket: PMAT-1071

* docs(PP-066): R-5 delta v6.1 — build != test; x86_64-cuda on lambda only in release-assets.yml at refs/tags/v*; base-owned promotion; derived fail-closed publish cascade; KEY row (paiml#3045, PMAT-1079); spec v2.1

Spec v2.1 (Appendix A 2.1) and DAG (103 rows) record the delta of 2026-09-08:

- BUILD != TEST. Assets build under the clean-room recipe (scripts/run_clean_room.sh, the
  forjar-pinned toolchain, fingerprint recorded); GPU verification is the fleet-verify receipt
  taken against the asset, never a build log.
- The x86_64-cuda asset (= apr-x86_64-unknown-linux-gnu, cli,cuda per D-10) builds on lambda only
  inside release-assets.yml at a v* tag: runner group gpu-release restricted to that workflow at
  refs/tags/v*, a JIT ephemeral runner for one job, lambda's queue slot claimed (host_queues.lambda
  4; S-1 -> 5, S-2 -> 6). Every other target: the CI clean-room runner.
- Promotion is a base-owned workflow_dispatch job over four receipts carrying the asset sha256 with
  C14 PASS and parity != skipped. No workflow runs cargo publish; scripts/publish_cascade.sh derives
  its set from cargo metadata in topological order and refuses branch/dirty/prerelease/token.
- New row KEY (paiml#3045, PMAT-1079, owner noahgift, expiry 2026-10-02 [U]): until
  keys/apr-release-minisign.pub is on main the manifest job and the C13 gate refuse and R-5 stays
  blocked_by KEY; DONE-IF present -> R-6 pins its fingerprint. R-5/R-6/TAG-0.66.0 <- KEY.
  The gpu-release group stays a blocked_by: RUNNER-GROUP note on R-5, as the delta directs.
- R-5 <- G-11b: make fleet-verify is G-11b's deliverable and is absent today [V].

Two corrections this session's verification pass found by measuring rather than reading:
- The delta's embedded-SASS premise is false for this binary. apr generates PTX text in Rust
  (crates/aprender-gpu/src/ptx/) and the driver JIT-compiles it, cubins landing in
  ~/.cache/trueno/ptx (driver/ptx_cache.rs:3), so nothing SASS-shaped ships. The A now requires
  cuobjdump --list-elf to list NO ELF and reads the emitted PTX's .target on both hosts.
- PMAT-1078 was not free: agent/R-5's contracts/apr-publish-cascade-v1.yaml:4 stamps it. KEY took
  PMAT-1079. An id is taken the moment a branch writes it, minted or not (pmat#1169 class).

Also recorded: the three divergences of agent/R-5 (authored at 19c015f before this delta) that
the row PR closes - an aarch64-cuda asset on gx10, .github/release-assets.pub, hosted builders;
its promotion gate and cascade already match [V]. G-11's typed status flipped to complete from
docs/audits/impl-PMAT-1062-receipt.md (paiml#3020 merged 3792afa) and the §5.0 block re-rendered -
D7 and render_dag.py --check were RED on this branch before this commit.

Guards on this tree: render_dag.py --check PASS (byte-identical, 103 rows) - check_dag_invariants.sh
PASS - check_receipt_complete.sh --dag PASS - check_roadmap_diff_additive.sh PASS (lifecycle only;
acceptance_criteria is not a lifecycle field) - check_roadmap_ids_unique.sh PASS (822) -
check_no_claim_literals.sh PASS - check_perf_claims_cite_receipts.sh PASS -
check_row_pr_write_set.sh ok (orchestrator branch).

Pmat-Ticket: PMAT-993
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X1cW8TnmNe3hgjragNjUxr

* docs(PP-066): collapse the PMAT-1074/PMAT-1077 roadmap re-serialisation back to base bytes

The 2026-09-08 merge re-ordered two planned entries; check_roadmap_diff_additive.sh
(PMAT-980) reads that as a re-serialisation and refused, which took `gate` down
through guard-tree. scripts/roadmap_trim.py restores the base ordering; no field
changed in either entry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* docs(PP-066): the roadmap keeps its SORTED order; PMAT-1077's block bytes differ only by a stray blank line

Two guards disagreed on the same file and the first fix satisfied the wrong one.
check_roadmap_diff_additive.sh (G-6) called PMAT-1077 re-serialised, so 5e2bd40
ran roadmap_trim.py, which restores base ORDER — and base order puts PMAT-1074/1077
before PMAT-1069..1073, which check_roadmap_sorted.sh (BSE-09a) then refused:
"PMAT-1069 at line 16527 sorts before PMAT-1077 earlier in the file".

The actual cause is neither ordering. `classify_pair` compares the entry BLOCK text,
and a block runs to the next `- id:`; PMAT-1079 had been appended with a blank line
before it, so PMAT-1077's block carried a trailing empty line that main's copy (where
PMAT-1077 is last in the file) does not have. One blank line, no field changed.

Dropping that blank line makes PMAT-1077's block byte-identical to main's AND keeps
the sorted insertion 1069 → 1079. Both guards pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* feat(G-11b): track scripts/pp066_state.sh and scripts/session_docs_commit.sh — the STATE and SESSION-END tools

Both have been in use for several sessions as working-tree files and were never
committed. That is the "free pass while untracked" trap running the other way:
check_shell_lint_ratchet.sh's universe is `find scripts -maxdepth 1 -name '*.sh'`
(the working tree, not `git ls-files`), so an untracked script already counts
against the ratchet while no reviewer can see it. session_docs_commit.sh was
contributing one such error line — bashrs 7.0.1 reads the `do` of a `for` nested
inside a single-line `if ...; then ...; fi` as the `if`'s body opener (SC2136) —
so the kaizen block is expanded onto its own lines. 177 scripts, 8 error lines,
baseline 8, PASS (ratcheted).

Refs PMAT-1066, paiml#3018

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* docs(PP-066): paiml#3022 and paiml#3024 join the 0.66 scope as rows F-1 and F-2 (operator ruling 2026-09-08)

F-1 (PMAT-1080, paiml#3022, P0): `apr chat` silently loaded its built-in Demo model for a
sharded SafeTensors index — exit 0, zero tokens, the real model's path printed in the
banner. `Path::extension()` returns the last dot-segment, so on
`model.safetensors.index.json` (the exact filename `apr pull` writes and recommends) it
is Some("json") and matched no arm. Shipped in PR paiml#3050 as a structural fix, not an
added arm: `resolve_chat_format` is one decision — suffix before extension, then magic
bytes, then a refusal from error.rs — and Demo is not an outcome for a path that exists.

F-2 (PMAT-1081, paiml#3024 ask 3, owner bse): the live matrix runs nightly against real
models, and the two axes still uncovered — an `apr serve` column and a sharded-GGUF row
(merge_gguf_shards, for which no fixture builder exists) — are named rather than dropped.

The rows earn their place in a rescoped 18-row release by claim (1): apr reports
truthfully and never silently substitutes what the user named. paiml#3022 is the strongest
instance of that failure in the tree — the substitution reported SUCCESS — and paiml#3024 is
why it survived: qwen-story-daily was green the same night and structurally could not
have caught it (`grep -c "apr chat"` is 0, `grep -c index.json` is 0).

DAG 103 -> 105 rows, 0.66 lane 32 -> 34; invariants PASS (violations=0); the spec's §5.0
block re-rendered byte-identical; roadmap 824 -> 826, sorted, unique, additive.

Refs paiml#3022, paiml#3024, paiml#2873

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* docs(PP-066): session 2026-09-08 — tickets minted, PMAT-1062 completed, status doc, six kaizen lines

Minted by hand (pmat#1169, `pmat work add` collides): PMAT-1082 for L0-1b (paiml#2971 — the
root cause is named: a crushed Q8_K activation block routes that matmul to the
f32-activation kernel, and the CPU reference was the inaccurate side, not the GPU) and
PMAT-1083 for SPEC-2.0 (paiml#3023). PMAT-1062 (G-11) flipped to completed — its receipt says
complete and PR paiml#3038 is merged.

Kaizen, all six from defects met today:
  * two guards disagreed about roadmap.yaml and the first fix satisfied the wrong one; the
    cause was neither ordering but a blank line inside the previous entry's compared BLOCK
  * `. scripts/apr_bin.sh` does not honour CARGO_TARGET_DIR (it reads cargo metadata's
    target_directory); APR_BIN is the documented pin
  * evidence need not carry a machine path — invoke the tool relatively and compare the
    two outputs field by field before claiming they are the same measurement
  * N identical evidence files are one file plus a sha256
  * a gate's RED leg is cheap: build the merge base in a second worktree
  * a second host can refute a hypothesis class before a lane is dispatched

DAG 105 rows, invariants PASS; §5.0 re-rendered byte-identical; roadmap 828 entries,
sorted, unique, additive; README counts exact.

Refs paiml#2873

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* docs(PP-066): drop docs/specifications/DOCUMENT_TEXT_MAP.md — session scratch, committed by an over-broad `git add -A docs/`

It is a flat concatenation of the spec at v1.5, produced by an earlier session as a
reading aid and left untracked. Committing it would put a STALE second copy of
PP-066-release-spec.md (v1.5 against the tree's v2.1) under docs/specifications/, where
the claims ratchet and every doc guard would then have two sources for the same text.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* docs(PP-066): session 2026-09-08 part 2 — five kaizen lines, status doc refreshed

All five from defects met in this segment: two of my own PRs shipped a falsifier no
workflow executed; a new test-selection tier surfaced a test that had been RED on clean
main and unrun; an anchored grep meant to fix a pass-grep was itself a false green; the
release had two candidate signing-key paths; and a textual guard was answered with an
allowlist entry and a reason rather than by rewording the file to dodge its regex.

Refs paiml#2873, paiml#3051

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* docs(PP-066): the kaizen file tripped its own lesson, plus two more lines

Kaizen line 5 quoted a throughput literal while explaining how a textual guard flags a
must-match fixture — and docs/ is exactly the surface the claims ratchet reads, so the
line about textual guards was refused by one. De-literalised; the fact is unchanged.

Two new lines: the claims ratchet's aperture is the `///` vs `//` boundary and a refactor
can cross it (R-0b promoted rationale comments into rustdoc, turning four numbers main
already carried into published speed claims; re-baselining a MOVED line is refused by
design because the ratchet is set-based); and: run the shared guards across every branch
in one pass — three guards over six worktrees took minutes and found four failures CI had
not reported yet, each of which would otherwise have cost a serial ~1h cycle.

Refs paiml#2873

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* docs(PP-066): D-13 — 0.66 ships checksummed, UNSIGNED assets; KEY moves to 0.67

Operator, 2026-09-08: "skip it and deprioritize". Signing was the only step on the release
path that needed a human, and it was gating a release whose three claims do not include
provenance.

  * KEY (PMAT-1079, paiml#3045) -> lane 0.67, first row of the provenance track
  * R-5 (PMAT-993) and R-6 (PMAT-994) drop KEY from blockers — both unblocked
  * C13's command drops "+ minisign signature"
  * 0.66 lane 34 -> 33 rows; invariants PASS; §5.0 re-rendered byte-identical

WHAT THIS COSTS, STATED RATHER THAN ABSORBED. Claim (3) keeps its INTEGRITY reading and
loses its AUTHENTICITY one. A sha256 still proves the asset matches the manifest the
release job produced, and the four host receipts still prove that sha256 is what was
tested. It does not prove WHO produced it: the manifest and the assets live in the same
GitHub release, so whoever can replace an asset can replace its checksum.

So the release must say so, in the three places a user could otherwise infer otherwise:
the notes' install section, R-6's installer output at install time, and the vocabulary —
no artefact, script, contract or note may call a 0.66 asset "signed" or "verified". Those
four obligations are recorded on the decision (paiml#2873) and are what makes the smaller claim
honest rather than merely smaller.

Refs paiml#2873, paiml#3045

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* docs(PP-066): D-14 — 0.66.0 is the CUDA parity fix and nothing else (26 -> 5 open rows)

Operator, 2026-09-08: "lets reduce scope as goal is mainly to fix CUDA issue".

0.66.0 now makes ONE of the mission's three claims — (2): every model in the manifest
computes the same function on GPU as on CPU, or the GPU refuses it. Claims (1) and (3)
move to 0.67 IN FULL, and the notes will say so rather than leave it inferable.

KEPT (12 rows, 7 already complete, 5 open): L0-1b (the fix — a crushed Q8_K activation
block routes that matmul to the f32 kernel; 1.5B 0.9508 -> 0.999761 on lambda and
0.950611 -> 0.999583 on gx10, first_divergence none on both), L0-1a (what makes it
checkable and the failure honest: derived manifest, C14, the >=64-position rule, the
measured threshold, REG-15's refusal instead of a silent downgrade), F-1 (the same class
one layer up, already measured and armed), SPEC-2.0, TAG-0.66.0.

CUT to 0.67, each row now carrying `cut_by` and the `claim_protected` it was defending:
R-0/R-0b/R-2 (registry, apr devices, dogfood-reads-registry — claim 1), R-3 (training
banner), R-5/R-6/R-7/R-8 (assets, installer, README-first, nightly install — claim 3),
C0-1/C0-2/C0-4 (credit gates: they gate CREDIT, not correctness — I9), G-10b/G-11b
(tooling), F-2 (the nightly format matrix).

TAG-0.66.0's blockers reduce from 19 to the 6 kept rows. NO release assets and NO
installer in 0.66 — `cargo install aprender` is the only supported install, which with
D-13 (checksummed, not signed) means claim (3) is not made at all rather than made
weakly. scripts/publish_cascade.sh is cherry-picked from agent/R-5; the rest stays behind.

DAG invariants PASS (105 rows, 0 violations); §5.0 re-rendered byte-identical.

Refs paiml#2873, paiml#2971, paiml#3022

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* fix(PP-066): every PP-066 ticket's kind: label is DERIVED from its DAG row — paiml-implement was refused on 80% of the epic

`paiml-implement` refuses at Phase 0 (`kind-gate.sh`, AUTO-IMPL-SKILL-001 T-1) unless the
ticket's roadmap entry carries `kind:<code|triage|docs|measurement>`. Attempting to run it
on R-5/PMAT-993 returned exit 2, and it was not one ticket:

    PP-066 tickets in docs/roadmaps/roadmap.yaml : 105
    carrying a kind: label                       :  21
    NOT carrying one                             :  84

The label is now DERIVED, not typed, because the DAG already says it: SPEC-/DEC-/TAG- rows
are docs; a row with a command-shaped acceptance or a contract is code. 103 entries written,
derived=103 missing=0 wrong=0, and `check_kind_labels_derived.sh` refuses drift in either
direction (a missing label AND a label that disagrees with its row).

TWO rows are UNDECIDABLE and are REPORTED rather than guessed — refusing to guess is not
refusing the tree, so they do not fail the guard:
  G-2 (PMAT-985)  "one line in spec §0 with decided_by and date"   — correctly prose, a docs row
  R-8 (PMAT-1067) "the workflow is green once on all four hosts"   — a PROSE acceptance on a
                  code row, which is the "a prose test: never runs" defect in another costume

MY OWN FIRST DRAFT SHIPPED THE DEFECT THIS GUARD EXISTS TO PREVENT, and it is worth the
record: it read the roadmap by line regex in both directions. `--update` then CORRUPTED the
file — 284 entries carry the inline `labels: []`, which has no `  - ` block to scan, so the
insert landed after a flow sequence and the YAML stopped loading — and `--check` reported
`missing=0 wrong=0` on the wreckage, because a regex reader cannot see a parse error. A
writer that can break the file its own checker reads is exactly the class this guard is for.
Fixed both ends: the verdict now PARSES the roadmap, the writer handles the inline form, and
it refuses to write a rewrite that does not parse or that loses an entry. The case-table
fixture carries both label forms so the corruption cannot come back.

Case table 7/7, both polarities. No ci.yml edit needed: guard_tree.sh's universe is
`git ls-files 'scripts/check_*.sh'`, and the guard advertises `--self-test` in its usage, so
the dispatcher gives it both rows. check_guards_are_wired PASS, roadmap sorted/unique/additive
PASS (828 entries, 0 non-label fields changed).

Refs paiml#2873, PMAT-1093

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* docs(PP-066): mint PMAT-1093 and PMAT-1094 by hand

PMAT-1093 was cited by the kind-label commit and never existed — a Refs pointing at
nothing, which is the small version of the defect pmat#1240 describes. Minted retroactively
as `completed` with its acceptance command and `proof:` path.

PMAT-1094 (paiml#3055): the `*-lint --json` outcome surface emits three shapes for one field,
one of them a Rust `Debug` string in a JSON API. Found sweeping paiml#3051; the tests in paiml#3053
accept all three deliberately and document the table, so this ticket's falsifier is the
DELETION of `assert_outcome_ok`'s two string arms.

Both by hand: `pmat work add` mints colliding ids (pmat#1169), and now pmat#1240 — two
agents minting in parallel branches land on the same id and the merge deletes one, with
`work validate` passing because uniqueness is preserved by the loss.

roadmap 828 -> 830, sorted, unique; kind labels derived=103 missing=0 wrong=0.

Refs paiml#2873, paiml#3055

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* fix(TAG-0.66.0): the release's first step can return a verdict, and its credited set is derived

`scripts/release_criteria.sh --all` is step 1 of the release sequence. It could not produce
a verdict: measured 2026-09-08, C0, C4, C7 and C8 each hit a 120 s timeout and --all ran
past ten minutes with nothing printed. Three defects, one of them mine to have noticed
sooner.

1. C0 RE-RAN FOR EVERY CRITERION. `run_one` gated each criterion on `bash "$0" C0` (I9's
   credited-first rule), and C0 shells out to `pmat comply check` AND a `gh api` call. Nine
   criteria therefore paid that cost nine times. It is now evaluated ONCE per process and
   only while C0 is itself in the credited set. C7 alone runs in 57 s; through the old gate
   it timed out at 120 s.

2. THE CREDITED SET WAS STALE AFTER D-14 and is now DERIVED, not chosen: a criterion is
   credited iff at least one row the spec's §4 table names as its owner is still lane 0.66.

       C7  SPEC-2.0  KEEP   the claims ratchet — load-bearing for D-13/D-14's vocabulary
       C8  SPEC-2.0  KEEP   clean-room before publish; cargo publish rests on it
       C9  C0-7      KEEP   every credited row has a complete receipt
       C14 L0-1a     KEEP   GPU = CPU per manifest model, or the GPU refuses it — 0.66's ONE claim
       C0  C0-1/2/4  MOVE   all 0.67; keeping it made --all both unpassable and unrunnable
       C4  R-6,R-2   MOVE   four host receipts THROUGH the R-6 installer, which 0.66 does not ship
       C6  G-10a…    MOVE   two owners are not rows at all; its script does not exist (ENV 2)
       C11 R-0a/0b   MOVE   the backend registry is 0.67
       C13 KEY,R-5,R-6 MOVE no assets and no installer in 0.66 (D-13, D-14)

3. THE SUCCESS BANNER CARRIED A SECOND, HAND-TYPED COPY of the list, so editing the set
   would have left it asserting the old one. It prints $CREDITED now.

Two new self-test rows, both mutation-proven: hand-editing CREDITED to add C13 turns the
derivation row RED (6/7), restoring it returns 7/7; and the banner row greps the source for
a literal `ALL CREDITED (C…` and refuses one.

CORRECTING MY OWN EARLIER READING: not all of the ten minutes was a defect. C8 is
`make -C machines/clean-room clean-room-p1`, a real multi-minute docker build, and it is
SUPPOSED to be slow — it is the hard gate before publish. Worth naming separately: the
release sequence runs `release_criteria.sh --all` and then `run_clean_room.sh`, so the
clean room currently builds twice.

Current state on this branch: C7 CREDITED (57 s), C9 CREDITED (0 s), C14 ENV 2 —
`scripts/check_model_parity.sh` lives on agent/L0-1, which is in the merge queue — and C8
is the long build. C14's ENV is the correct answer, never a pass.

Refs paiml#2873, PMAT-1083

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* evidence(TAG-0.66.0): C14 runs live and PASSES over the manifest — 0.66's single claim, measured

L0-1a landed (paiml#3026), so scripts/check_model_parity.sh is on main and C14 stopped being ENV.
Run verbatim as the criterion defines it, on lambda, with a cuda apr built from agent/L0-1b
(sha256 776cbbdb4306b5d8 — the tree carrying L0-1b's fix):

    PASS qwen2.5-coder-1.5b-instruct: 78 positions, min cosine 0.9998 at position 36
    PASS qwen2.5-coder-0.5b-instruct: 78 positions, min cosine 0.9996 at position 0
    PASS qwen2.5-coder-7b-instruct:   78 positions, min cosine 0.9996 at position 22
    C14: measured=3 rc=0

The first row is the model paiml#2971 is about. It read 0.950827 on this host before the fix and
reads 0.9998 after, against a threshold whose basis is two measured known-good pairs across
two GPU architectures.

Fourteen models are UNMEASURED because this host does not hold them, and the script REPORTS
rather than fails — no single host holds every model the README names, and the fleet-level
rule belongs to the release.

From the outside, `apr chat --gpu` on the 1.5B now prints
`[GGUF CUDA: NVIDIA GeForce RTX 4090 …]` and answers correctly, with no `falling back to
CPU` anywhere in the output.

ONE GAP, NAMED RATHER THAN GLOSSED: the driver's Resolved criterion asks for
`selected: cuda … parity: PASS` on the success path, and that line does not appear —
REG-15's admission line is printed by `on_cuda_load_error`, so it is emitted only when
something goes wrong. Reporting the selection only on failure is weaker than the criterion
asks. That belongs to claim (1), which D-14 moved to 0.67 with R-0b; 0.66 makes claim (2),
and claim (2) is what the table above measures.

Refs paiml#2971, paiml#2873

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* fix(B3): one parity contract, not two — L0-1a's apr-gpu-cpu-parity-v1 folded into the one with 11 falsifiers

Epic paiml#3058 §B3: do not create contracts/apr-gpu-cpu-parity-v1.yaml; extend
contracts/apr-cpu-vs-gpu-output-parity-v1.yaml, which already exists with 11 falsification
tests. L0-1a shipped the duplicate anyway (paiml#3026, merged), so this removes it.

Verified before acting, not taken on faith: the existing contract carries 11 FALSIFY ids and
58 KB of history; mine carried 3 obligations and 3 falsifiers in 10 KB.

THE TWO ARE THE SAME ARGUMENT SPLIT IN HALF, which is the real cost B3 names. The existing
contract already records the paiml#1864 five-whys whose root cause is "the gate's domain was too
narrow (single-step instead of multi-step)" — and L0-1a's >= 64-position horizon rule is the
answer to exactly that. Half the reasoning sat in each file.

Ported as FALSIFY-CPU-GPU-012/013/014, each with the mutation that turns it RED:
  012  the manifest is derived, never typed        derive_model_manifest.sh --self-test  (6/6)
  013  the domain is >= 64 positions, both         check_model_parity.sh --self-test     (9/9)
       polarities on BOTH required GPU hosts
  014  a forced backend never downgrades           cargo test --test reg15_admission     (7/7)
All three re-run here, green. `pv validate`: 0 errors, 14 falsifiers.

THE STALE ANCHOR, AND A SHARPER VERSION OF B3's POINT. B3 is right that the contract cites
`mod.rs:268-279` for the SKIP_PARITY_GATE bypass and that :268-279 is something else (a doc
comment about qtype resolution). But B3's proposed replacement, `:333`/`:349`, had ALREADY
DRIFTED by the time I read it — L0-1a and L0-1b moved the bypass to :390/:406 on this branch.
The fix for a drifting line anchor cannot be a different line anchor, so both live citations
now anchor on the SYMBOL (`grep for the literal SKIP_PARITY_GATE`) and say why. The 1.1.0
changelog entry keeps its line numbers: it is history, and history is allowed to be stale.

References repointed in the DAG (4), the spec table, parity_admission.rs, reg15_admission.rs
and .pr/L0-1/accept.sh. DAG invariants PASS; §5.0 re-rendered byte-identical.

Refs paiml#3058, paiml#2971, paiml#2873

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* evidence(F1): the model dogfood run BY HAND on both GPU hosts — four cells, and one result stronger than the gate asks for

Epic paiml#3058 §F1: run it by hand on lambda-labs and gx10, needing none of the missing
automation. Four cells for the 7B — {lambda-labs, gx10} x {cpu, gpu} — as §5.5 receipts under
docs/audits/release/v0.66.0-pre/models/.

  M3  parity over >= 64 positions   GREEN on both GPU cells: 78 positions, 283 op rows,
                                    first_divergence None; lm_head 0.99958 (lambda) and
                                    0.99978 (gx10); worst op ffn_out@L23 0.994065 and
                                    attention@L22 0.996844
  M4  determinism                   GREEN, all four cells
  M6  7B service smoke              GREEN, all four cells — loads, non-empty output, zero OOM

THE RESULT WORTH MORE THAN ANY SINGLE CELL: the greedy stream sha256 is 6f38f13e5debd285 in
ALL FOUR cells. Same model bytes, two architectures (x86_64 sm_89 and aarch64 sm_121) and
both backends produce a byte-identical token stream. M4 only asks for determinism WITHIN a
cell; this is determinism across the fleet.

MY FIRST M4 RUN REPORTED NO, AND MY INSTRUMENT WAS WRONG. It compared whole stdout, whose
last line is `Completed in 12.63s` — a clock, not a nondeterminism. The generated text was
byte-identical both times. The comparator now strips that line, which is the same rule this
repo already enforces on required gates: no wall-clock assertion inside a correctness check.

EXCLUSIONS ARE NAMED, NEVER SKIPPED, because §5.5 says a missing cell is NO-GO:
  M1 artifact identity   0.66 ships no assets and no manifest (D-13, D-14) — nothing to compare
  M2 registry readback   `apr devices` is R-0a, 0.67
  M5 refusal semantics   PARTIAL — the FX fixtures are R-0a; the admission level is covered by
                         reg15_admission 7/7, now FALSIFY-CPU-GPU-014 in the parity contract
  M7 transport parity    NOT RUN — needs a port and a client; named, not dropped
  M8 performance         NOT RECORDED DELIBERATELY — the claims ratchet refuses a throughput
                         literal on a documented surface and 0.66 makes no speed claim

VERDICT WITHHELD, on purpose. Each receipt says "not GO and not NO-GO": this is a dry run on
a pre-tag directory, and a receipt calling itself GO with M1 and M2 structurally excluded
would be the theater §1.1 forbids.

Refs paiml#3058, paiml#2971, paiml#2873

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH

* roadmap: PMAT-1062's `completed` cites its proof (BSE-01)

check_roadmap_completion_is_cited.sh went RED on this branch: PMAT-1062 said
`status: completed` with `github_issue: null` and `notes: null`, so nothing
could dereference the claim.

Checked before citing rather than after, because the guard's own precedent
(PERF-004) is an entry marked completed whose PR was closed unmerged. All three
things the title names are on origin/main:

  guard job runs all, reports all   guard_tree.sh + the guard-tree job, paiml#3037
                                    (git log -S'  guard-tree:' names ff122fa)
  aprender timeout-minutes          paiml#3037 added timeout-minutes 90/90/22
  CARGO_TARGET_DIR per container    all six container steps carry
                                    -e CARGO_TARGET_DIR=/workspace/target

So `completed` is honest and the fix is the citation, not the status.

The edit is applied through a YAML load/verify rather than a regex rewrite --
my own kind-label guard corrupted this file once by treating it as text, and
reported missing=0 wrong=0 on the wreckage. Entry count asserted unchanged
(830) and the citation asserted present after the write.

Verified: check_roadmap_completion_is_cited.sh PASS; guard_tree.sh --no-cargo
41 checks, 0 failed.

Refs paiml#3025

Pmat-Ticket: PMAT-1083

* docs: README CONTRACT_COUNT states 1816 — this branch removes the duplicate parity contract

guard-cargo's "README claims must match measurement" was RED: the README said
1817 (main's count) while this branch's tree carries 1816. The one-file delta is
contracts/apr-gpu-cpu-parity-v1.yaml, deleted here per epic paiml#3058 §B3 — the
instruction was to extend the contract that already had 11 falsifiers rather
than mint a second one over the same property, and the duplicate had already
merged on L0-1a.

Re-derived with `make readme-sync`, which reads `find contracts/ -name "*.yaml"`
and rewrote both CONTRACT_COUNT blocks. Not hand-edited.

Refs paiml#3025

Pmat-Ticket: PMAT-1083

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
noahgift added a commit to guyernest/aprender that referenced this pull request Sep 15, 2026
…/wgpu at startup and `apr devices` prints every kind as a line (PMAT-989, paiml#2904) (paiml#3004)

* chore(roadmap): PMAT-989 kind:code label (kind-gate)

Pmat-Ticket: PMAT-989

* docs(PP-066): R-0 design quorum record (3/3 implement-with-changes, 3/3 split) — DAG: R-0 = R-0a, new R-0b (paiml#3002, PMAT-1060), R-2/B-G1 gain R-0b and move under the §12 rule, I-18 anchor +14; spec §12 llamafile citation corrected (lane 3); §5.0 re-rendered

Pmat-Ticket: PMAT-989

* test(R-0a): registry_case_table — RED: trueno::registry does not exist; cpu always Ready, every kind a line, NotCompiled/NoBackend named, REG-4/7/9/12 and the two-API device_uid dedup (PMAT-989, paiml#2904)

Pmat-Ticket: PMAT-989

* feat(R-0a): trueno::registry — BackendRegistry::discover(): cpu always Ready, every kind of {cpu,cuda,wgpu,metal,hip} an explicit entry (NotCompiled / NoBackend / DriverNotFound / NoDevice / ProbeFailed), CUDA through the dlopen'd driver API, wgpu adapters with transport, REG-7 reserve as ReserveExceedsFree, REG-8 selection printed, device_uid dedup across APIs, object-safe BackendFactory + MockBackendFactory, JSON + printed block, fixtures never mistaken for the machine (PMAT-989, paiml#2904)

Pmat-Ticket: PMAT-989

* feat(R-0a): apr devices [--json] — the registry printed (every kind a line, selection with its reason, overrides loud: APR_RESERVE_BYTES, APR_REGISTRY_FIXTURE); hermetic failure catalogue with must-RED twins (FX-7, FX-11, REG-4/9/12, schema) on fixture registries; contracts/schemas/apr-devices-v1.schema.json; a reserve refusal propagates to the device's other-API entries; both integration targets wired into ci.yml; cli_commands.rs --help parsers decomposed (pre-existing cognitive 47/36 blocked the file) (PMAT-989, paiml#2904)

Pmat-Ticket: PMAT-989

* contract(R-0a): apr-backend-registry-v1 (invariants i and iii discharged; ii/iv/v are R-0b's and not claimed) + apr-devices-schema-v1 (one shape on every host, absence is a line); README contract count 1813 (PMAT-989, paiml#2904)

Pmat-Ticket: PMAT-989

* docs(audits): impl-PMAT-989 receipt (R-0a, status: partial) + estimate rows

Pmat-Ticket: PMAT-989

* fix(R-0a): review quorum changes — the CLI contract lists devices once; the CUDA factory's DriverNotFound / ProbeFailed / NoDevice are all reachable (dlopen first, then count); the schema refuses documents serde refuses (strict nested objects, per-kind reason payloads, no kind on ready) with a twin row; override lines print what the registry holds; two non_goals recorded (a context per device during discovery; uid normalisation across APIs) (PMAT-989, paiml#2904)

Pmat-Ticket: PMAT-989

* docs(audits): impl-PMAT-989 receipt — review quorum record and adjudication (four claims true, two false, two limitations recorded)

Pmat-Ticket: PMAT-989

* fix(R-0a): two different cards with one name through one API stay two devices (intel's two W5700X both enumerate as 'AMD Unknown (RADV NAVI10)' and collapsed into one device_uid — found by the four-host dogfood); case-table row 10; receipt: dogfood blocks from lambda, gx10, intel, mini — every host Ready>=1 (PMAT-989, paiml#2904)

Pmat-Ticket: PMAT-989

* docs(PP-066): §5.0 re-rendered on the merged tree (G-10 + R-0b, 92 rows) — rendered blocks drift on the queue's 3-way merge

Pmat-Ticket: PMAT-989

* docs(R-0): book chapter book/src/cli/devices.md + page contract apr-page-cli-devices-v1 (FALSIFY-BOOK-CLI-PARITY-001 red on paiml#3004: apr devices had no chapter)

Pmat-Ticket: PMAT-989

* docs(R-0): README contract count 1814 on the third line too

Pmat-Ticket: PMAT-989

* docs(R-0): DAG/spec edits are carried by the R-0 amendment PR (paiml#3003); this branch is code + receipt only

Pmat-Ticket: PMAT-989

* docs(R-0): the design-quorum record is carried by paiml#3003 too

Pmat-Ticket: PMAT-989

* docs(R-0): roadmap entry edits for PMAT-989 are carried by paiml#3003; this branch leaves roadmap.yaml untouched

Pmat-Ticket: PMAT-989

* fix(R-0a): delete the two complexity_baseline rows this PR made STALE

crates/apr-cli/tests/cli_commands.rs::get_help_commands and ::help_subcommands
fell under both thresholds when the registry test was rewritten; the ratchet
refuses a kept row for a fixed function (the next regression at that coordinate
would land for free). Verified locally: check_complexity_ratchet.sh rc=0,
689 recorded offenders, 2 removed, none new, none grown, none stale.

Also drops this branch's README count bump: G-11 (paiml#3020) makes the README counts
a ratchet the orchestrator regenerates, and check_row_pr_write_set.sh refuses a
count line on a row branch. PASS: row PR agent/R-0 writes no shared file.

(PMAT-989, paiml#2904)

* test(R-0a): MUTANT — drop the pass-1 refusals so the reserve refusal does not propagate across a device's APIs (reverted in the next commit)

Driver v6 P2 requires the mutant to be PUSHED and the PR's own CI to go RED,
not a local run. Local pre-push result at this commit:
  cargo test -p aprender-compute --test registry_case_table
  9 passed; 1 failed - a_reserve_refusal_propagates_to_the_devices_other_api_entries
  'the twin carries the sibling's measured free memory: Ready'
Exactly one test moves, so the RED is attributable to this one line.

(PMAT-989, paiml#2904)

* Revert "test(R-0a): MUTANT" + receipt status: complete with the mutation run ids

Reverts 4a66e20. The mutant was PUSHED and the PR CI went RED on it, as
driver v6 P2 requires:

  RED   run 34049785730, job workspace-test 101531455145, step 11
        "Integration tests" - FAILURE, exit 101.
        fx7_reserve_exceeding_free_memory_is_a_named_refusal FAILED
        (9 passed; 1 failed). The printed block names the defect:
          cuda unavailable reason=ReserveExceedsFree{reserve=..., free=21474836480}
          selected: wgpu device[0]
        i.e. the library selected the wgpu twin of the very RTX 4090 the
        cuda driver had just refused for the reserve.
  GREEN this commit.

Two independent tests catch the one-line mutant; CI short-circuits at the
first, so the catalogue row fires before the case-table row that fails
locally. The mutant was aimed at the job that actually runs them: the
integration line carrying --test registry_case_table is in workspace-test
(ci.yml:408), NOT in ci / test - ci / test was GREEN on the mutant commit
and proves nothing about it.

Receipt flipped to status: complete with turns, and a Resume section
recording the two blockers this session found (the complexity ratchet STALE
rows this PR created, and G-11 landing the row write-set guard after this
branch was cut).

(PMAT-989, paiml#2904)

* audit(R-0a): re-audit the surface ledger for the code this PR moved (dogfood coverage gate G2.1)

check_dogfood_coverage.sh landed on main with G-10/G-11 and is RED on this
branch: G2.1 freshness refuses a ledger left behind the code it describes, and
this PR inserts 7 lines at extended_commands.rs:631 and 5 at
dispatch_analysis.rs:484 - both cited evidence files.

  - 64 citations re-pointed through an EXACT old->new line map (difflib over
    origin/main's copy vs HEAD's; every one of the 2160 + 1832 old lines maps,
    0 unmapped, 2 that a text search called AMBIGUOUS resolved by the map).
    Row order is preserved and no row is lost - G2.2 reconciliation reads 833
    comparand rows all present.
  - one new row: apr devices, cluster 10 apr-core-commands, evidence
    extended_commands.rs:636, in_dogfood_skill=yes. That is measured, not
    asserted: dogfood_surfaces.sh enumerates subcommands from the BUILT
    binary's --help, and its own awk parser lists 'devices' among 111
    subcommands of a binary that reports fae3b7f == HEAD (pinned through
    APR_BIN + scripts/apr_bin.sh, which refuses a stale one - it refused
    three).
  - the stated counts that must move with the ledger: the contract's overall
    block (833/143/0.1717 -> 834/144/0.1727, as scripts/dogfood_baseline.py
    now measures), its two T2 pairing lines, and the same line in the
    apr-dogfood skill.

DOGFOOD COVERAGE GATE: PASS (G2.1-G2.6 all green, 144/834 covered, 28
per-binary floors held). pv validate on the contract: 0 errors.

(PMAT-989, paiml#2904)

* docs(R-0): receipt records the surface-ledger re-audit as resume item 5 (PMAT-989, paiml#2904)

* fix(R-0): the three per-{binary,band,cluster} baselines the new row moves, and the receipt marker G-11 derives the DAG status from

Two guards this branch had not yet seen, both new on main with G-10/G-11:

1. `python3 scripts/dogfood_baseline.py --check` (guard-runner-labels step 46)
   compares EVERY baseline block in contracts/apr-dogfood-coverage-v1.yaml
   against the ledger, not just `overall`. The `apr devices` row moves three
   more: per_binary apr 370/143 -> 371/144, per_cluster apr-core-commands
   109/38 -> 110/39, per_band q7_8 9/9 -> 10/10 (the row is quality 8).
   CHECK PASSED: every baseline in the contract matches the ledger.

2. G-11 DERIVES the DAG row status from this receipt's front matter, so
   flipping it to `complete` in a ROW PR takes render_dag.py --check to DRIFT
   and check_dag_invariants.sh to D7 'typed status open disagrees with the
   receipt (derived complete); status is derived, never typed'. The protocol
   both guards state is that a row PR ships `partial` and the ORCHESTRATOR
   docs commit flips the marker AND re-renders the spec block together. Marker
   restored to partial with that as its stated reason; the Verdict section
   says plainly that the work is done and why the marker reads as it does.
   render_dag --check rc=0, check_dag_invariants rc=0 (91 rows, 0 violations).

Found by running all 77 non-self-test guard invocations of guard-runner-labels
locally instead of discovering them one CI cycle at a time.

(PMAT-989, paiml#2904)

* fix(R-0): tree_reader_tests.txt re-derived — registry_failure_catalogue is a quick-tier target now

guard-cargo on the merge: '> apr-cli --test registry_failure_catalogue' derived-only. check_tree_reader_tests.sh --update, re-run rc=0.

Pmat-Ticket: PMAT-1098

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Noah Gift <claude@noahgift.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

inst:A PP-066 instance claim (I14): inst:A pp-066 PP-066 (0.66) DAG row

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PP-066 G-11: shared-file write contention — row PRs never write the DAG, roadmap, spec block or README counts; DAG status derived from receipts

1 participant