Skip to content

evidence: re-seal the Apple route ledger; give promotion_rules a consumer - #673

Merged
gstoner merged 3 commits into
mainfrom
evidence/apple-route-ledger-reseal
Sep 1, 2026
Merged

gstoner merged 3 commits into
mainfrom
evidence/apple-route-ledger-reseal

Conversation

@gstoner

@gstoner gstoner commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Started as the one red lane on this Mac and turned into three findings.

1. The red lane was right to be red

test_strict_retune_ledger_admits_on_its_exact_live_apple_host had been failing
here, and I reported it as "pre-existing" more than once without looking. The
ledger was rejected on four independent axes: os_version (26.5.2 →
26.6.2), compiler_fingerprint, runtime_fingerprint (this session edited
apple_gpu_runtime.mm), and stale_evidence — expired 2026-08-20, twelve days
prior. The gate was working; the evidence was dead.

Re-measured, not re-stamped: benchmark_legacy_retune.py --profile extended, 2 runs × 24 rows, through the existing sealer. Zero rejections
against the live context; 16 decisions and 8 ineligible, identical key sets to
July
— nothing lost, nothing invented.

Near-miss. The first re-run used --profile core. It admitted cleanly —
rejected == () — with 8 decisions instead of 16. That would have halved
the Apple route evidence while reading as success. Diffing decision keys
against the committed ledger caught it; the admission result never would have.

2. One real route change, and not for the obvious reason

retune_mla_decode end-to-end flips explicitabsorbed at both shapes.
absorbed was never the slower route: in July it was 54–57% faster and won
100% of paired trials in both runs, held back solely because its cross-run
speedup spread (5.97%) missed the ledger's own 5% cap by ~1 point. The re-run:
37–39% faster, again 100% paired wins, spread 2.3%. The flip is "the
measurement became consistent enough to conclude"
, not "the kernel got
faster"
.

Diagnostic and deliberately not a route claim
(absolute_time_drift_is_diagnostic_only): absolute times moved the other way —
absorbed 518µs → 836µs at 128-token and 482µs → 557µs at 64, while explicit
held (1.15× / 0.96×). The larger shape's regression is outside this harness's
own run drift; the smaller is not. Cause is confounded across OS, runtime edits
and compiler fingerprint, and is not attributed.

3. The structural finding: promotion_rules had no consumer

The aggregator computes and applies the thresholds; the sealer copies them into
the ledger for audit; and across twelve committed ledgers nothing ever read
them back
. load_strict_route_ledger checks provenance exhaustively — schema,
scope, exact context, freshness, source digests, native provenance, correctness,
timing domain, device, duplicates — and the promotion criteria not at all, so
status: "promote_candidate" was self-certifying. A row naming a route that
lost every paired trial would have been admitted and served. Decision #29, in
the evidence layer rather than the IR.

The loader now rejects a decision its own ledger's rules refuse — a
production gate, not an audit script. Across all 12 committed strict ledgers:
59 promotions checked, 0 violations, so it confirms the aggregator rather
than accusing it. A missing rules block fails closed: without a threshold
there is nothing to hold a promotion to, and the honest verdict is
"unverifiable", not "fine".

The suite's own fixtures were forging promotions

Turning the gate on made four tests red, and they were right to go red: both
fixture files build ledgers with promote_candidate, no route_evidence and
no rules block at all
— exactly the forgery the check exists to catch. Fixed
the fixtures, not the checker; relaxing it to skip validation when evidence is
absent would reinstate the fail-open hole. No sealed ledger can lack
route_evidence (the aggregator sets it unconditionally), which is why all 12
committed ledgers still load unchanged.

Beyond making the red go away: a negative test the fixtures previously could
not express — six forged violations plus evidence-absent, rules-absent, and a
retain_incumbent control — and the shared fixture moved to
tests/_support/apple.py, since two files build these ledgers and a third
checks the committed ones.

Also investigated, deliberately not fixed here

APPLE-DISPATCH-WEDGE-1 (Apple todo). A sweep hung 70 minutes inside
commit_mpsgraph_and_wait_with_timeout. I first wrote that its 30s timeout
was being ignored; that is false.
A probe built against the on-machine SDK
(Decision #27) shows the API honouring its deadline to the millisecond —
including the exact failure shape, a committed buffer awaiting an unreachable
value, returning NO at 1001ms — and sampling the probe mid-wait yields the
identical frame at the identical address as the hung process, so it provably
exercises the same path.

What remains unestablished is whether 70 minutes was one uninterruptible wait or
~140 sequential 30s timeouts; sample cannot separate them and the process
was killed first. What is established under either hypothesis: no circuit
breaker.
Seven call sites (6×30s, 1×60s); on timeout the caller falls back to
the host path correctly, but nothing records the device as unusable, and the
function clears the dispatch telemetry on entry, erasing the prior timeout's
evidence. A device that wedges early turns a 4-minute suite into an unbounded
one and leaves no trace of why.

Not fixed here because of a hard ordering constraint: runtime_fingerprint is
sha256(apple_gpu_runtime.mm), so editing that file invalidates the ledger this
PR seals. The fix must land with a re-run and re-seal. Probe kept at
tools/apple_probes/.

Validation

Full unit sweep on the Mac: 16988 passed, 3259 skipped, 0 failed (19:30) —
the first fully clean full sweep of this session; the previously red lane is
green because it was re-measured. Apple subset: 3452 passed, 1 skipped, 0
failed (4:03). mypy 483 files clean; ruff clean on every touched file (the
377 repo-wide errors are pre-existing and identical on main); generated docs
in sync.

Measured on the Mac (M1 Max, macOS 26.6.2) — the only host that can produce
this evidence.

Cross-backend (AGENTS.md:81-85) — ROUTE-LEDGER-RULES-UNCONSUMED-2026-09-01

backend outcome
Apple parity validated — measured here.
NVIDIA follow-up requirednoise_policy (0.03/0.04) is asserted equal to a constant and never compared to any row's margin, so a promotion inside the noise band passes every check. Its ratchet is otherwise well built (cross-checks the count against the rows, guards the vacuous-pass case, requires timing-domain consensus).
ROCm follow-up required, furthest from checkable — its gate is prose: "correct oracle plus shape-specific repeated-median gate". Closing it means first deciding that phrase's numeric form.
x86 not applicable — no route ledger; its baselines are comparisons, not promotions.

🤖 Generated with Claude Code

gstoner and others added 3 commits September 1, 2026 09:46
…umer

The red lane first. `test_strict_retune_ledger_admits_on_its_exact_live_apple_host`
had been failing on this Mac and I reported it as "pre-existing" more than
once. It was right to fail: the ledger was rejected on four independent
axes -- os_version (26.5.2 -> 26.6.2), compiler_fingerprint,
runtime_fingerprint (this session edited apple_gpu_runtime.mm), and
stale_evidence (expired 2026-08-20, twelve days before). The gate was
working; the evidence was dead.

Re-measured, not re-stamped: benchmark_legacy_retune.py --profile extended,
2 runs x 24 rows, sealed through the existing sealer. Zero rejections
against the live context, 16 decisions and 8 ineligible, identical key
sets to July -- nothing lost, nothing invented.

Near-miss: the first re-run used --profile core, which admitted cleanly
with 8 decisions instead of 16. `rejected == ()` would have read as
success while halving the Apple route evidence. Diffing decision keys
against the committed ledger caught it; the admission result did not.

One real route change. retune_mla_decode end-to-end flips explicit ->
absorbed at both shapes, and the cause is not the obvious one: `absorbed`
was never slower. In July it was 54-57% faster with 100% paired wins in
both runs, held back solely because its cross-run speedup spread (5.97%)
missed the ledger's own 5% cap by ~1 point. The re-run measures 37-39%
faster, again 100% paired wins, spread 2.3%. The flip is "the measurement
became consistent enough to conclude", not "the kernel got faster".

Diagnostic, not a route claim: absolute times moved the wrong way
(absorbed 518us -> 836us at 128-token, 482us -> 557us at 64; explicit
held at 1.15x / 0.96x). Larger shape is outside the harness's own drift,
smaller is not. Cause is confounded and is NOT attributed.

The structural finding: `promotion_rules` was a declaration with no
consumer. The aggregator computes and applies the thresholds, the sealer
copies them into the ledger for audit, and across twelve committed
ledgers nothing ever read them back. load_strict_route_ledger checks
provenance exhaustively -- schema, scope, exact context, freshness,
source digests, native provenance, correctness, domain, device,
duplicates -- and the promotion criteria not at all, so
status: "promote_candidate" was self-certifying. A row naming a route
that lost every paired trial would have been served. Decision #29, in the
evidence layer rather than the IR.

promotion_rule_violations() re-derives each promotion from the retained
evidence, and the LOADER now rejects a decision its own ledger's rules
refuse -- a production gate, not an audit script. Across all 12 committed
strict ledgers: 59 promotions checked, 0 violations, so it confirms the
aggregator rather than accusing it. Mutation-verified against seven
forged rows; a missing rules block fails CLOSED, because without a
threshold the honest verdict is "unverifiable", not "fine".

Four backends assessed under ROUTE-LEDGER-RULES-UNCONSUMED-2026-09-01:
Apple parity validated (measured here, the only host that can);
NVIDIA follow-up required (noise_policy is asserted equal to a constant
and never compared to any row's margin); ROCm follow-up required and
furthest from checkable (its promotion_gate is prose); x86 not
applicable (no route ledger -- its baselines are comparisons, not
promotions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The promotion-rules gate turned four tests red, and they were right to go
red: both files hand-build ledgers with `status: "promote_candidate"`,
no `route_evidence`, and no `promotion_rules` block at all. The old loader
accepted them because it validated provenance exhaustively and the
promotion criteria not at all -- so the suite's own fixtures were exactly
the forgery the new check exists to catch.

Fixed the fixtures, not the checker. Relaxing it to skip validation when
evidence is absent would reinstate the fail-open hole: unverifiable is not
the same as fine. No sealed ledger can lack route_evidence -- the
aggregator sets it unconditionally and the sealer copies it forward --
which is why all 12 committed ledgers still load unchanged.

Two things beyond making the red go away:

- A negative test the fixtures previously could not express: six forged
  violations (lost every trial / speedup under minimum / spread over cap /
  no numerical proof / no resource evidence / no paired trials), plus
  evidence-absent, plus rules-block-absent, plus a `retain_incumbent`
  control proving a non-promotion is not held to promotion thresholds.
  Without it, fixing a fixture is just moving the goalposts.
- The shared fixture lives in tests/_support/apple.py rather than being
  imported test-module-from-test-module. Two files build these ledgers and
  a third checks the committed ones; three copies of a threshold set is how
  they drift apart.

Apple sweep: 3452 passed, 1 skipped, 0 failed (4:03).

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

I wrote that commit_mpsgraph_and_wait_with_timeout's namesake guarantee
"doesn't hold" -- that waitUntilSignaledValue:timeoutMS: was ignoring its
30s deadline during the 70-minute sweep hang. That is false, and this
records the check rather than the guess.

A standalone probe built against the on-machine SDK (Decision #27)
measures the API honouring its deadline to the millisecond: 251ms for
250, 1001 for 1000, 3000.2 for 3000, and -- the exact shape of the
failure -- a committed buffer awaiting an unreachable value returns NO
after 1001ms. Sampling the probe mid-wait yields the identical frame at
the identical address as the hung process
(IOSurfaceSharedEvent waitUntilSignaledValue:timeoutMS: + 72 [0x1988de184]),
so it provably exercises the same path rather than a lookalike.

What remains unestablished is which of two things took 70 minutes: one
uninterruptible wait (a driver wedge defeating the kernel-side deadline)
or ~140 sequential 30s timeouts. `sample` aggregates by stack so it
cannot separate them, and I killed the process before forward progress
could be checked. No GPU fault in the log, no hang report -- so the wedge
hypothesis has no positive evidence either. Both stay open; it has not
reproduced.

What IS established is a defect under either hypothesis: there is no
circuit breaker. Seven call sites (6x30s, 1x60s); on timeout the caller
correctly falls back to the host path, but nothing records that the
device is unusable, so every later dispatch pays the full timeout again.
And commit_mpsgraph_and_wait_with_timeout clears the dispatch telemetry
ON ENTRY, erasing the previous timeout's evidence before the next
attempt. g_last_gpu_error_kind is a thread_local last-error for
reporting, not accumulating state, and nothing consults it. A device that
wedges early turns a 4-minute suite into an unbounded one and leaves no
trace of why.

Not fixing it here, and the reason is a hard ordering constraint worth
recording: AppleRouteContext.runtime_fingerprint is
sha256(apple_gpu_runtime.mm), so editing that file invalidates the strict
route ledger this branch just re-sealed. The fix has to land together
with a benchmark re-run and re-seal, not before or after.

The probe is kept at tools/apple_probes/ so the next person can re-run it
instead of rebuilding the argument.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T16:25:01.920300Z 17ec7e6 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 17ec7e6168

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread python/tessera/compiler/apple_route_selector.py
Comment thread docs/audit/backend/apple/todo.md
@gstoner
gstoner merged commit 41cd18c into main Sep 1, 2026
13 checks passed
@gstoner
gstoner deleted the evidence/apple-route-ledger-reseal branch September 1, 2026 18:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant