Skip to content

feat(registry): S3b — apr-cli call sites resolve through the backend registry, and a static guard keeps cfg! backend reads at zero - #3344

Open
noahgift wants to merge 3 commits into
mainfrom
PMAT-3041-s3b-callers
Open

noahgift wants to merge 3 commits into
mainfrom
PMAT-3041-s3b-callers

Conversation

@noahgift

@noahgift noahgift commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Second slice of the #3041 split, per docs/audits/pr-3041-split-plan.md (#3334). Stacked on #3342 (S3a) — until S3a merges, this PR's diff shows S3a's commits too.

S3a added the resolution library without changing any caller. This is where behaviour moves: twelve call sites stop reading cfg!(feature = "cuda") and start resolving through the registry, and a static guard keeps them that way.

What changes, and what proves each one

call site before → after covered by
dispatch.rs inlined cuda check + ensure_availablerun_preflightensure_available_forregistry::announce (FeatureDisabled 9 / BackendUnavailable 14, never a cpu downgrade) 2 new run_preflight tests
dispatch_analysis.rs ensure_available(...)ensure_available_for(...) mutation-proven: reverting this single site turns every_accelerator_surface_calls_the_refusal RED, naming apr chat
accel.rs cfg!(any(cuda,wgpu))registry::build_has_accelerator() 3 new tests on the switched entry point, which had none
serve/mod.rs cfg-gated guard → ensure_accelerator_available_in(cfg, reg), fixture-driven 4 tests, now over 4 fixture registries × 20 requests instead of the build's own cfg
bench.rs, lib.rs, finetune.rs, handler_gpu_completion.rs, tests_offload_report_pp14.rs cfg!registry::compiled(kind) / compute_class() existing oracles, re-pointed at the registry
handlers_include_01.rs, chat_load_tokenizers.rs, chat_generate_session_02.rs add registry::parity_line(..) at the CUDA loads (REG-15) cuda-only paths — named as gaps, not claimed as covered

Two gates that could not fail, found and fixed here

  • The three-surface source scan searched for accel::ensure_available, which is a substring of the new ensure_available_for. It passed identically before and after the very switch it was the only oracle for.
  • The new guard's own EXIT trap referenced a function-local under set -u, so it exited 1 after printing 10/10 rows.

The static guard

scripts/check_backend_registry.sh: 10 case-table rows, --self-test, and a row that copies the real accel.rs, appends a cfg!(any(feature = "cuda", feature = "wgpu")) leak, and requires the guard to go RED naming the file. bashrs: 0 errors, no pipe into grep -q.

It is ported off ripgrep to grep -rnE (plan decision D4b): no check_*.sh invokes rg, no workflow provisions it, and the clean-room runner has none — the rg form self-tests straight into env-death.

No workflow edit. The plan's S3b row listed a ci.yml --static step; decision D4(a) says it is redundant because guard_tree.sh already runs every tracked check_*.sh bare. So no-arg is the gate — a guard hiding behind --static would print usage, exit 2, and show up as a RED row for a guard that never ran. Verified: guard_tree.sh --dry-run --no-cargo lists it, and check_guards_are_wired.sh passes.

The contract's static half is restored (S3a dropped it because the guard did not exist yet — plan D2). Obligation ids are unchanged.

Deliberately left for S3c

The effective-config publication in serve/mod.rs (a0269f3), cuda_fallback_or_refuse in chat_generate_session_02.rs (5b5116d), all of run_entry.rs, and the matching contract clauses. Also left out: #3041's blobs for three files that would revert main's later ShardedSafeTensors, arch-refusal and parity_per_op work.

Gate at the final commit: apr-cli --lib 7252 passed / 0 failed, the falsifier 5/5, clippy -D warnings clean, fmt clean, the static guard 10/10, pv validate 0 errors, check_no_claim_literals ratchet 1 removed.

Refs #3041

no-close: #3041 stays open until S3c and S4 land; it is closed with a pointer then, per the plan.

ont-delta: resolves REG-OB-004 — the static-guard half (zero cfg!(feature=cuda|wgpu) backend reads outside registry.rs) leaves non_goals and is discharged by REG-F-003 via scripts/check_backend_registry.sh --static, named by the new binding_registry.static_guard row

🤖 Generated with Claude Code

noahgift and others added 2 commits September 16, 2026 07:05
…registry, and a forced accelerator never downgrades to cpu (#3041)

Slice S3a of docs/audits/pr-3041-split-plan.md, cut fresh from origin/main; #3041 is not merged or rebased.

apr_cli::registry (declared #[path] from commands_enum.rs, not lib.rs, whose
include! tree carries pre-existing over-threshold functions the complexity hook
would charge): a Request becomes a Resolved or a refusal over trueno::registry.
Not compiled => FeatureDisabled (9); compiled but not Ready on this host =>
BackendUnavailable (14, new); only the default may fall to cpu. Purely additive:
no call site changes behaviour in this slice.

Falsifier tests/backend_refusal_case_table.rs 5/5 PASS. Mutation: both not-ready
branches of resolve_in returning cpu_resolved instead of Err turns
a_forced_accelerator_with_none_ready_refuses_and_never_downgrades and
every_backend_value_is_resolvable_on_every_fixture_and_forced_gpu_is_never_cpu
RED (observed); restored clean.

Contract REG-OB-004 + REG-F-003 + the two resolution bindings; pv validate 0
errors with the in-tree pv 0.67.0. The static-guard half of the original hunk is
NOT claimed here: check_backend_registry.sh is S3b and is not in this tree.

Wiring: ci/explicit-test-commands.d/400-apr-cli-backend-refusal-case-table.cmd
(free ordinal) and the regenerated scripts/tree_reader_tests.txt row. Removing
either turns check_tree_reader_tests.sh RED in both directions (observed).

Pmat-Ticket: PMAT-3041

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…registry, and a static guard keeps cfg! backend reads at zero (#3041)

Slice S3b of docs/audits/pr-3041-split-plan.md, stacked on S3a; #3041 is not merged
or rebased. S3a was additive — this is where behaviour moves.

Call sites. `apr run` (dispatch.rs run_preflight), `apr chat` (dispatch_analysis.rs),
`apr serve` (serve/mod.rs), bench compute_class/provenance, finetune wgpu_available,
lib.rs emit_version_json, serve list_devices/cli_build_features and
handler_gpu_completion now ask crate::registry instead of cfg!(feature=cuda|wgpu):
the decision becomes a fact about the HOST, not about what was compiled. The census
under crates/apr-cli/src goes 19 code reads -> 0 (the one survivor is prose in
registry.rs). dispatch.rs also carries 99589f9/#3040 decompositions of
dispatch_runtime_commands, dispatch_diagnostic_commands and help_producer_truth::resolve
(behaviour-preserving; the same tests are the oracle).

Guard. scripts/check_backend_registry.sh, 10/10 rows, both polarities. Ported off
ripgrep to grep -rnE per plan decision D4b — no scripts/check_*.sh on main invokes rg
and guard-runner-labels provisions none, so the rg form would have been an env-death
inside guard_tree. NO-ARG IS THE GATE, not --static: guard_tree.sh runs every tracked
check_*.sh BARE, so a gate hiding behind a flag would print usage, exit 2, and be a RED
row for a guard that never ran. Wiring is therefore guard_tree itself (verified: it is
a `run:` row of --dry-run --no-cargo, and check_guards_are_wired PASSes) — no workflow
edit. Row 10 is the real mutation: cfg!(any(feature=cuda,wgpu)) back in a COPY of the
real crates/apr-cli/src turns --static RED naming accel.rs. bashrs 0 errors.

Contract. The static half of REG-OB-004 / REG-F-003 that S3a dropped under decision D2
is restored now that the guard exists, ids unchanged; the effective-config half stays
out — it is S3c code and nothing here discharges it. pv validate 0 errors.

Tests for the switched paths, which had none on either side of the split:
accel::ensure_available_for and request_from_asked (cpu/default never refused in any
spelling; --gpu beats --no-gpu and --backend cpu, honoured or refused but never quietly
cpu) and dispatch::run_preflight (the effective_no_gpu GH-326 decision). The
three-surface scan stopped accepting the needle `accel::ensure_available`, which is a
SUBSTRING of `ensure_available_for` and so passed identically before and after the
switch; with the needle named per surface, reverting apr chat to the old spelling turns
every_accelerator_surface_calls_the_refusal RED (observed, rc 101) and restoring it
GREEN.

#3041 parked the pre-R-0b refusal text in accel::legacy_refusal, unreferenced, under
#[allow(dead_code)] — the lint that would have reported it. Dropped: registry::not_compiled
owns that message and is reached.

Left for S3c: serve/mod.rs a0269f3 (effective-config set_backend_resolution),
chat_generate_session_02 5b5116d (cuda_fallback_or_refuse), run_entry.rs.

Pmat-Ticket: PMAT-3041

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@noahgift noahgift added this to the 0.68.0 milestone Sep 16, 2026
@noahgift
noahgift enabled auto-merge September 16, 2026 06:02
@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown

§13.11 rung 1 — quorum shadow verdict

S13-SHADOW pr=3344 head=6d67d2b7dce087c4f2f7de44420f911243659ba9 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.

…s rows S3b moved

S3b carries S3a's 6-line module declaration at the top of commands_enum.rs (+6
for all 42 distinct cited lines, 64 tokens) and, in dispatch_analysis.rs,
replaces the 4-line `accel::ensure_available(...)` call in the `apr chat` arm
with the 1-line `ensure_available_for(...)` (-3 below line 1676). 13 cited
lines in that file: 12 sit above the edit and do not move; one, :1699, sits
below it and moves to :1696.

Every token is re-pointed through a line-level diff (merge-base 7ee0eca ->
branch, difflib.SequenceMatcher over lines) and accepted ONLY where the cited
line's TEXT is byte-identical on both sides. No row was re-audited by hand, none
was dropped, and the file was not re-serialised: normalising every
`commands_enum.rs:NNN` and `dispatch_analysis.rs:NNN` token to a constant makes
the before and after byte-identical. 838 lines before and after.

HONEST NOTE, for the audit and not for this commit to fix: the row
`apr chat ... (ACCELERATOR_GUARD crates/apr-cli/src/dispatch_analysis.rs:1699)`
cites a line whose text is `            runs,` -- a field of the bench arm, not
an accelerator guard -- and it already did so at the merge base. This commit
moves that citation mechanically to the same text at :1696; it does not invent a
new target. The guard `apr chat` actually calls now lives at ~:1668. Re-aiming
that row is a re-audit, not a re-point, and is left for one.

  G2.1 freshness  PASS  78 cited evidence files, 2 changed by this branch
  G2.2 PASS (no row lost, 837 comparand rows) G2.3/G2.5/G2.6/G2.4 PASS

Pmat-Ticket: PMAT-3041
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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