feat(parity): L0-1a — every supported model computes the same function on GPU as on CPU or the GPU refuses it (manifest, C14, REG-15 admission, effective-config parity) - #3026
Conversation
|
§13.11 rung 1 — quorum shadow verdict Shadow mode: this records a verdict and merges nothing. A refusal |
… binary c642576eecb62daa) — apr parity --json over 78 positions: qwen2.5-coder-1.5b min cosine 0.9508 at position 0 (|Δlogit|max 11.97), qwen2.5-coder-7b min 0.9986; under the horizon rule (min over >= 64 positions >= 0.98 [U]) 1.5B RED / 7B GREEN before any kernel edit (#3017) Pmat-Ticket: PMAT-1065
…est.sh -> evidence/models/supported.yaml, 18 models, every entry cites file:line; --check refuses a hand-typed entry; 6-row case table); C14 scripts/check_model_parity.sh --manifest (apr parity over >= 64 positions per manifest model, min cosine vs evidence/parity/thresholds.yaml — 0.98 [U] until item 5 measures it; UNMEASURED reported, README-cited unmeasured RED; SKIP_PARITY_GATE is an override that prints and refuses; 6-row case table over the lambda records: 1.5B RED, 7B GREEN, must-RED twin, < 64 positions refused) (#3017, PMAT-1065) Pmat-Ticket: PMAT-1065
…tree already does (cited), the five-whys hypothesis for the N-lane quorum; threshold basis = PARITY_GATE_COSINE_MIN (mod.rs:803), itself [U] Pmat-Ticket: PMAT-1065
…S (record corrected); the fused Q8_1 FFN is off by default (gpu_profile.rs:238), so the five-whys step 3 is refuted on default config and the 1.5B/7B asymmetry on the unfused path is the open question; the surviving zero-risk fix is REG-15's selected: line; lanes were one family (gap) Pmat-Ticket: PMAT-1065
…s its duplicate under driver v5.1) — receipt, record, scripts and manifest cite it Pmat-Ticket: PMAT-1065
…izon gate, the derived manifest, REG-15 admission); ci.yml guard-runner-labels runs the manifest case table + --check and C14's case table; every 0.65.2 (1.5B, cuda) dogfood receipt relabelled INVALID-CORRECTNESS citing #2971 (PMAT-1065) Pmat-Ticket: PMAT-1065
… a forced backend never downgrades — CliError::ParityFailed with its own code read at test time; unforced prints selected: cpu (reason: parity FAILED …); PASS prints selected: cuda …), override_line() for SKIP_PARITY_GATE, parse_gate_error over the load-time gate's message; 7 hermetic tests (worker-written, orchestrator-verified) (#2971, PMAT-1065) Pmat-Ticket: PMAT-1065
…oad failure: a parity-gate failure prints selected: cpu (reason: parity FAILED cosine=… threshold=…) when unforced (apr chat today) and refuses when forced (R-0b's --backend); apr compare prints the override line only when the user set SKIP_PARITY_GATE (diff-benchmark's silent set_var waits for its own decomposition — the file is over the complexity gate) (#2971, PMAT-1065) Pmat-Ticket: PMAT-1065
…pare override), the worker ledger, the cuda type-check on lambda, and the gaps (diff-benchmark decomposition, effective-config block, apr devices --model, dogfood C14, threshold measurement, gx10) Pmat-Ticket: PMAT-1065
…lsifier (FAILs the run if it ever passes), then check_model_parity.sh --manifest over the built binary: PASS when measured, FAIL on a measured failure or an override, REPORT with the reason on a host that holds no manifest model (the pre-publish proof is make fleet-verify ROW=release on lambda and gx10) (#2971, PMAT-1065) Pmat-Ticket: PMAT-1065
…e lambda 1.5B record must be RED and the 7B record GREEN under evidence/parity/thresholds.yaml (read by regex, no default), both over >= 64 positions; the full manifest runs only in dogfood, the release and R-8 (#2971, PMAT-1065) Pmat-Ticket: PMAT-1065
…ambda) sits at min cosine 0.9986 in all five runs and the known-bad pair (1.5B@lambda) at 0.9508 in all five (both deterministic, stdev 0.0); 0.98 lies between; [U] until the gx10 pair (#2971, PMAT-1065) Pmat-Ticket: PMAT-1065
…ositions,threshold,basis} — the load-time gate returns the cosine it measured, the CUDA model carries a ParityGateRecord (PASS | skipped under the SKIP_PARITY_GATE override | not-run) set by one admission helper, the report is never absent (not-run on cpu residency or a non-cuda build); shape test (#2971, PMAT-1065) Pmat-Ticket: PMAT-1065
…cs under --features cuda) Pmat-Ticket: PMAT-1065
…st targets (GREEN on a GPU-less host; the live manifest is the fleet-verify leg); receipt carries the v6 DONE-IF ledger Pmat-Ticket: PMAT-1065
…itations moved); accept.sh GREEN on this host (10/10 legs) Pmat-Ticket: PMAT-1065
…rive_model_manifest.sh --check must go RED in guard-runner-labels) and min_cosine 0.90 (the 1.5B sentinel must PASS and sentinel_1p5b_on_lambda_is_red must FAIL in workspace-test). REVERTED after the RED run ids are captured (I3) Pmat-Ticket: PMAT-1065
… row 7); UNMEASURED is a per-host REPORT and a host that measured nothing is not a pass (the fleet-level rule is R-5's); aliases of one file are measured once (longest name first); the case table judges under its own threshold fixture and writes the tracked twin only when absent; PAR-F-003's test is the admission level (R-0b owns backend_refusal_case_table); the manifest's admission rule is stated (#2971, PMAT-1065) Pmat-Ticket: PMAT-1065
…one() so the silent SKIP_PARITY_GATE set_var becomes the printed override (the file was over the complexity gate) (#2971, PMAT-1065) Pmat-Ticket: PMAT-1065
…to R-0b, two documented) in the receipt Pmat-Ticket: PMAT-1065
…ED line (SC2075); the round-1 guard job stopped at the bashrs step before reaching the manifest mutation Pmat-Ticket: PMAT-1065
…ade STALE (diff_benchmark_report.rs::run, error.rs::resolve_model_path, gguf/cuda/mod.rs::preload_and_verify are now under both thresholds) — the shrink-only ratchet demands the delete Pmat-Ticket: PMAT-1065
…t alias only resolves without --features cuda (cuda build of apr-cli was RED: E0107) Pmat-Ticket: PMAT-1065
… new I8 sentinel test (thresholds_demand_at_least_sixty_four_positions) must turn workspace-test RED; round-1 mutants (typed manifest entry, min_cosine 0.90) reverted — their RED is run 34049865821 (guard: manifest derivation step; workspace-test: sentinel_1p5b test) Pmat-Ticket: PMAT-1065
…sis I8); the I8 threshold test stays. Round-2 RED: run 34052968770 (workspace-test: thresholds_demand_at_least_sixty_four_positions, 3/3 tries); round-1 RED: run 34049865821 (guard: manifest derivation step; workspace-test: sentinel_1p5b) Pmat-Ticket: PMAT-1065
…EQUIRED_TOP_LEVEL_KEYS 12 -> 13; the shape test was RED on the GREEN leg (run 34093549220) Pmat-Ticket: PMAT-1065
…e type is already must_use (clippy double_must_use under deny(clippy::all)) Pmat-Ticket: PMAT-1065
…s into guard-tree BSE-001 M2 split the old guard-runner-labels job into guard-tree (cargo-free, dispatched by scripts/guard_tree.sh) and guard-cargo. The four L0-1a steps (derive_model_manifest.sh --self-test/--check, check_model_parity.sh --self-test) are cargo-free by `grep -cE '(^|[^a-z_-])cargo '` == 0 on both scripts, so they re-anchor into guard-tree after check_row_pr_write_set.sh, the same neighbour they had before the split. Also drops unfused_test.json — a 0-byte file left at the repo root by the round-2 mutation run (193d626) and committed by accident. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH
…hold [U] lifted, the divergence is model-selected not device-selected Card items (iv) and (vi). `make fleet-verify` does not exist (BSE's G-11b), so the measurement was taken rather than waited on. gx10-a5b5, aarch64, NVIDIA GB10 (sm_121), driver 590.48.01, apr 0.65.2 (c04eda8) sha256 21d182d69505159c. Mechanism engaged, not intended: every run's stderr carries `[GH-480] Patched N backward branch(es) for sm_121 JIT workaround`, a path lambda's sm_89 build does not have. model positions<0.98 min cosine max|dlogit|@0 verdict qwen2.5-coder-1.5b-instruct-q4_k_m 1 0.950611 12.0087 RED qwen2.5-coder-7b-instruct-q4_k_m 0 0.998465 0.8032 GREEN n=5 per cell, stdev 0.0 in all four cells across both hosts. THE FINDING. Two GPU generations, two ISAs, two host architectures, one running a JIT workaround the other does not have — and the known-bad pair lands within 2.2e-4 of the same cosine (lambda 0.950827, gx10 0.950611) while the known-good pair on the same silicon is 0.9985+. The divergence is selected by the MODEL (hidden 1536/heads 12/kv 2 /GQA 6 vs 3584/28/4/7), not by the device. Every "an sm_89 kernel is wrong" or "the sm_121 JIT patch corrupts a branch" hypothesis is refuted before L0-1b dispatches a lane. It is asserted, not merely written down: the_two_hosts_agree_on_each_model_to_ within_a_thousandth goes RED if that stops holding. The driver's 0.9418 / 5.38 were guessed to be gx10's numbers by all three earlier lanes. They are not: gx10 measures 0.950611 / 12.0087. The source report's provenance stays [U]; the defect it names is confirmed on both required hosts. Item (iv) CLOSED, the [U] on evidence/parity/thresholds.yaml lifted: 0.98 now separates two measured known-good pairs from two measured known-bad pairs with 0.0185 of margin under the lower good floor, asserted at >= 0.01 on each side, because a gate that passes with no headroom is a finding (0.63.0 hansei) and a near-tie once inverted a whole diagnosis (#2359). Falsifiers added: check_model_parity.sh --self-test 7 -> 9 rows (both polarities on BOTH hosts); sentinel_tests 4 -> 8 (1.5B RED / 7B GREEN per host, cross-host agreement, threshold margin on both sides). Refs #2971, PMAT-1065 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH
…ies is one file
check_hardcoded_paths.sh refused +25 shipped machine-specific paths — 24 of them
`"model": "/home/noah/models/…"` inside the apr parity --json output, one a hardcoded
cargo in accept.sh. That guard has no allowlist by design, and its own header sets the
precedent for evidence: redacting a host path "would delete the evidence and fabricate a
cleaner history".
Neither redaction nor an exemption was needed, because the path was never part of the
measurement.
* Every canonical record RE-TAKEN with the model named relatively (`cd ~/models &&
apr parity ./<model>.gguf …`), same pinned binaries (lambda c642576eecb62daa, gx10
21d182d69505159c), same prompt. The metrics array and every other key are
BYTE-IDENTICAL to the absolute-path run; only `model` differs — compared field by
field, not asserted.
* n5/ drops its ten JSONs per host. All five runs of each model were byte-identical to
each other AND to the canonical record — stdev 0 understates it, the whole file was
the same file — so five copies carried nothing their sha256 does not. DETERMINISM.md
records the hashes and the distinct-count; runs.log keeps the ten exit codes.
* accept.sh: CARGO="${CARGO:-$HOME/.cargo/bin/cargo}" — still never a bare `cargo`
(a shell function of that name overrides CARGO_TARGET_DIR), no longer a machine path.
Also `make readme-sync`: the CONTRACT_COUNT block stated 1815 and the merge tree carries
1816 (main's contracts/patterns/ratchet-verdict-d2-v1.yaml plus this row's
apr-gpu-cpu-parity-v1.yaml). That block is GENERATED, so it is an equality, not a ratchet.
check_hardcoded_paths.sh --full: delta +0. sentinel_tests 8/8. accept.sh 12/12.
Refs #2971, PMAT-1065
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH
…achine path check_hardcoded_paths.sh refused +25 shipped paths; the resolution was neither a redaction nor an exemption — the records were re-taken with the model named relatively (byte-identical metrics, same pinned binaries) and the n=5 series collapsed to its sha256, because all five runs were byte-identical to the canonical record. delta +0. Refs #2971, PMAT-1065 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH
Card ledger, 2026-09-08 — the row is complete except one item that is another row's command
The second host, and what it settles
n=5 per cell, stdev 0.0 in all four. The divergence is selected by the MODEL, not by the device — which refutes every "an sm_89 kernel is wrong" / "the sm_121 JIT corrupts a branch" hypothesis before L0-1b dispatches a lane, and is asserted by Item (iv) is closed by the same measurement: 0.98 now separates two known-good pairs from two known-bad pairs with 0.0185 of margin under the lower good floor, asserted at ≥ 0.01 on each side because a gate that passes with no headroom is a finding. Two guards, answered rather than routed around
Receipt: |
…refusal proof never ran on main Found by asking of this row what R-0b's regenerated tree-reader ledger asked of its sibling: which of this PR's test targets does a workflow actually execute? $ grep -rc reg15_admission .github/workflows/ -> no match crates/apr-cli/tests/reg15_admission.rs is card item (i)'s falsifier — seven hermetic tests, among them forced_backend_over_a_failed_parity_gate_refuses_with_the_code_from_ error_rs, which is the whole claim of REG-15: a forced backend never silently downgrades. BSE-17's quick tier runs it on a PR that touches apr-cli, but the full tier and every push to main run `--lib` plus ONE explicit list of --test targets, and it was not on that list. Merged as it stood, nothing on main would ever have executed it again — the exact trap recorded for the beats line (a new test target is theater until it is added there). It joins that line beside cli_commands. Note the scale of the standing problem while passing: apr-cli carries 64 integration targets and the line names 7 of them (#2341). Refs #2971, PMAT-1065 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH
…on of both sides #3026 merged, so main now carries the three L0-1a manifest steps and this branch carries the release_criteria self-test step. Both are additive steps in the same guard-tree job and neither replaces the other; the resolution is the union, verified by counting each step rather than by eye. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH
…66's single claim, measured L0-1a landed (#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 #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 #2971, #2873 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH
… folded into the one with 11 falsifiers Epic #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 (#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 #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 #3058, #2971, #2873 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018RouwmUL7vFfJyCx9qLEoH
#3026 (L0-1a) landed after v0.1 was written and shipped four things this spec called new: the derived model manifest, C14 (check_model_parity.sh), the parity contract apr-gpu-cpu-parity-v1.yaml, and a PR-time sentinel pair in workspace-test. And binary-release.yml already builds and attaches tagged-release assets. The spec now starts from those instead of proposing them. What changed: - Section 3.1 lists what already ships and from where. There are FOUR target sets to reconcile, not two: nightly's 5, binary-release's 4 (with musl), C13's 5, and this section's 4. musl is an open question -- tagged releases already ship it for pv, and including it makes the matrix 8 artifacts, not 4. binary-release.yml's own header invites other CLIs to opt in, which is a smaller change than a new workflow, and it lets hosted runners build while house hardware only verifies. That also takes most of RD-4's contention problem away, since gx10 stops being a builder. - Section 5.2: the manifest exists and is a CITATION INDEX (name, family, size, cited_by), not the sha256/hidden/heads pin this section assumed. Same filename, two different artifacts. Extend the deriver or use a different file; do not hand-write a second, which is what its --check exists to stop. - Section 7: the sentinel pair already runs at PR time against recorded lambda evidence. The real gap is LIVE kernel execution, which is a narrower ask than "no parity check at PR time". RD-3 restated on that. - Section 8: apr-gpu-cpu-parity-v1.yaml exists; this document uses it rather than creating it. Two parity contracts now cover CPU/GPU parity and need an owner -- a falsifier added to one does not constrain the other. - M3's threshold is no longer [U]: 0.98, measured n=5 on both hosts against a known-good and a known-bad pair, stdev 0. - Counts corrected everywhere: 4 of 21 present, 17 absent, re-tested with find against origin/main ebc9e9d. The review's GT-1 is amended in the same commit, and it overtakes finding F5: the draft's contract name was right and the file exists. F5 becomes "two contracts now cover one invariant" rather than "do not mint it". No RD is decided. Pmat-Ticket: PMAT-1092
…claimed dc99835 said "The review's GT-1 is amended in the same commit". It was not. The edit targeted PMAT-1092-review.md; GT-1 lives in ground-truth.md, so the assert fired, the python exited 1, and git commit ran anyway. set -euo pipefail was on the first line and did not stop it. That is the third time in this branch a commit message has described an edit that did not happen -- e7244c3, 6e14065, and now dc99835 -- and every one was caught the same way: by checking the file afterwards rather than trusting the script exited. The lesson is not "remember set -e". It is that in this environment the shell's exit handling cannot be relied on, so the check has to be explicit and the commit has to be gated on it. This commit was. The content: GT-1 now carries the 2026-09-09 re-measurement against origin/main ebc9e9d -- 4 present, 17 absent -- names the three that #3026 shipped, and records that this overtakes finding F5. The original c04eda8 measurement is preserved below it, because the review's reasoning was built on that number. Pmat-Ticket: PMAT-1092
Ticket
#2971 (alfredodeza's report; P0; DAG row L0-1a, ticket PMAT-1065, epic #2873). #3017 was closed as its duplicate.
Claim
Claim 2 of 0.66, the bounded half: every model in
evidence/models/supported.yaml(derived, never typed) is measured over ≥ 64 positions against a threshold that carries its basis, and a model that fails is refused by the GPU with its reason printed — never silently run on the CPU under a forced request. The op that diverges on Qwen2.5-1.5B and its fix are L0-1b.RED test
c977cad58—apr parityon lambda (RTX 4090, the 0.65.2 cuda installc642576eecb62daa), 78 positions: 1.5B min cosine 0.9508 at position 0 (token 785), 7B 0.9986; n=5 repeats are bit-for-bit identical (d2a566642).d56f65430—sentinel_1p5b_on_lambda_is_red_under_the_horizon_rule/sentinel_7b_on_lambda_is_green_under_the_horizon_rule(lib tests, rideworkspace-test).tests/fixtures/parity/defective/one-position-at-0.5.json(C14 case-table row 3).Acceptance (
.pr/L0-1/accept.sh, orchestrator's run,.pr/L0-1/accept.log)cargo check -p aprender-serve -p apr-cli --features cudaon lambda (CUDA 12.8): clean at 35c330c.Mutation (I3)
a5db15200— a hand-typed manifest entry +min_cosine: 0.90sentinel_1p5b_on_lambda_is_redFAILSmin_positions: 1Contract
contracts/apr-gpu-cpu-parity-v1.yaml— kind: pattern; PAR-OB-001..003 ↔ PAR-F-001..003.pv validate(viascripts/pv_bin.sh):0 error(s), 0 warning(s) — Contract is valid.Quorum
review-only row: one agy lane on this diff — verdict recorded in
.pr/L0-1/quorum.mdand the receipt before arming. The L0-1 root-cause quorum (three lanes, one family — a recorded gap) refuted the fused-FFN hypothesis on default config; L0-1b answers the rest by measurement.Receipt
docs/audits/impl-PMAT-1065-receipt.md(v6 DONE-IF ledger: (i) admission level ✓, (ii) ✓, (iii) blocked on R-0a, (iv) one pair measured, (v) ✓, (vi) pending G-11b, (vii) ✓).Writes
scripts/derive_model_manifest.sh,scripts/check_model_parity.sh,scripts/dogfood.sh(C14 rows),evidence/models/supported.yaml,evidence/parity/{thresholds.yaml,l0-1/**},evidence/dogfood/0.65.2/{lambda,gx10}.json(validity relabel),tests/fixtures/parity/defective/**,crates/apr-cli/src/commands/{parity_admission.rs,chat_generate_session_02.rs,comparison.rs,mod.rs},crates/apr-cli/src/error.rs,crates/apr-cli/tests/reg15_admission.rs,crates/aprender-serve/src/gguf/cuda/{mod.rs,mod_parity_gate.rs},crates/aprender-serve/src/api/effective_config.rs,contracts/apr-gpu-cpu-parity-v1.yaml,.github/workflows/ci.yml(three guard-runner-labels steps),.pr/L0-1/accept.sh, the receipt. No DAG, roadmap, README or spec edit.