batch-1: nine collision-free CI/guard PRs as ONE queue entry (#3250 #3253 #3257 #3267 #3272 #3285 #3288 #3289 #3290) - #3295
Merged
Merged
Conversation
…since APR-MONO
ALD-002 should be valid: "Failed to read ../../examples/ald/data_table_virtualized.yaml:
No such file or directory (os error 2)"
Every row in tests/examples.rs (27) and tests/prs_examples.rs (7) failed, all on
one cause. The examples are in the SIBLING crate,
crates/aprender-present/examples/{ald,apr,charts,dashboards,edge_cases,prs}/.
examples.rs `Path::new("../../examples/...")` -- two levels up from
crates/aprender-present-yaml/ is the repository ROOT, and CWD
is whatever the runner chose. Both wrong.
prs_examples.rs already anchored on CARGO_MANIFEST_DIR and then walked
`.parent().parent().join("examples").join("prs")` -- to the
same repository root. The CWD-independence was right and the
DESTINATION was wrong, which is why it looks deliberate.
`CARGO_MANIFEST_DIR` + `../aprender-present/examples` rather than a corrected
`../`: it resolves at COMPILE time against the crate being built, so no working
directory can break it and it survives the next move. One helper per file, 27 + 3
call sites.
Proved: pointing the helper back at `../../examples` turns all 27 rows red again;
restoring it turns them green. aprender-present-yaml now 205 lib + 27 + 17 + 7
pass, clippy -D warnings clean.
HOW THIS WAS FOUND, because it is the more useful half. Nothing in this repo runs
integration targets: ci.yml's workspace-test is `--workspace --lib` plus one
explicit `--test` list, and `make coverage` -- the only other full run -- is also
`--lib`. So I ran the whole surface once, on this box:
cargo nextest run --workspace --lib --tests --no-fail-fast
(GPU crates excluded, as the full tier excludes them)
Summary [1141.178s] 98621 tests run: 98584 passed, 37 failed, 329 skipped
19 minutes, and about 18,000 tests that CI has never executed. The 37 failures
are FIVE binaries, not a swamp:
aprender-present-yaml::examples 27 <- this commit
aprender-present-yaml::prs_examples 7 <- this commit
apr-format::golden_fixtures 1 <- #3248
aprender-mcp::falsify_mcp_008 1 <- #3238
aprender-cgp::falsify (doctor_speed_real) 1 <- open
That reframes #3239: the dark surface is cheap to run and has three distinct
defects left, two of which are already in flight.
Not wired here. ci.yml's --test chain is held by #3245 and #3248 this cycle and
only one PR may edit that line; a third would conflict with both. The wiring for
these two targets goes in after they land.
Pmat-Ticket: PMAT-1098
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
FALSIFY-CGP-061 FAILED: doctor took 2665ms Measured during a full `--lib --tests` sweep of the workspace — the box was running 98,621 tests in parallel. 2665 against a 2500 ms limit is a 6.6% miss that says nothing about `cgp doctor` and everything about the load. It is the LAST of the 37 failures that sweep found, and the one blocking #3249's hard-failing nightly. Raising the limit is the "clever ratio rewrite" that once blocked all nine open PRs. The fix is to stop asserting duration where duration cannot be measured. FIXED ONE, FOUND SIX. The test that failed was the entry point, not the scope: tests/falsify.rs:457 doctor < 2500 ms <- the one that failed tests/falsify.rs:583 profile < 31 s <- same file, simply not unlucky yet tests/integration.rs:39 doctor < 30 s src/doctor.rs:406 checks < 2 s } src/analysis/diff.rs:344 < 100 ms } IN src/ -- these are #[cfg(test)] src/metrics/export.rs:70 < 100 ms } units, so they run in --workspace } --lib: the REQUIRED workspace-test, } on every PR and every merge group A 100 ms assertion on a shared runner is a coin flip, and two of them have been sitting in a required check. `scripts/check_no_timing_in_required.sh` exists for exactly this — its header says "policy is what failed the other eleven times" — but its registry covers `check_*.sh` GUARDS. It has never been able to see a Rust target, so nobody has ever counted these. `timing-gate`, off by default, is that registry for Rust: nothing enables it, so a timing row cannot reach a required check by accident. Arm it where duration is measurable — a dedicated unloaded runner at release time — not in CI's default set and not in #3249's nightly full surface. GATED, NOT DELETED, proved by mutation rather than asserted: limit -> 0, WITH --features timing-gate FAILED (1 failed) the assertion is live limit -> 0, WITHOUT the feature ok compiled out restored ok Also in CGP-061, a second defect in the same row: assert!(stdout.contains("RTX 4090") || stdout.contains("GPU")); That asserts the RUNNER's hardware — the class fixed in #3210 across four sibling rows — and passes here only because this box happens to have a 4090. What CGP-061 owes is that `doctor` reached a VERDICT about the device and printed it, so that is what it now asserts: non-empty output, and a decision among GPU/CUDA/device/no GPU/not available. aprender-cgp: 121 lib + 3 falsify pass, clippy -D warnings clean. Not fixed here, filed separately: the same regex over the workspace finds ~70 duration assertions in `crates/*/src/` and 36 more in `crates/*/tests/`, across 12 crates. This commit fixes the one crate that actually failed. Refs #3239 Pmat-Ticket: PMAT-1098 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ly — 43 errors under --no-default-features
cargo check --workspace --no-default-features
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `tokio`
... 43 errors, every one in aprender-distribute
Found while measuring what APR-RELEASE-001 T-1's `ci / deep` would actually cost.
T-1 names `--no-default-features` as one of its clauses, and that clause has
never run in CI: `grep -rc no-default-features .github/workflows/*.yml` finds ONE
hit and it is a Windows BUILD flag in nightly.yml. #3176 is the standing ticket.
`default = ["cpu"]` and `cpu = ["tokio", "num_cpus"]`, so --no-default-features
drops tokio while the source still names it in four files.
TOKIO, NOT `cpu`, AND THAT IS A DELIBERATE DEPARTURE FROM THE TICKET. #3176 says
"the fix is `#[cfg(feature = "cpu")]` on the affected modules ... not adding
tokio as a hard dependency". The second half is right and is followed. The first
half is not quite: `cpu` is only one of SIX features that pull tokio in — `cpu`,
`remote`, `checkpoint`, `tui`, `serverless`, `microvm`. Gating on `cpu` would
leave `--no-default-features --features remote` with tokio PRESENT and the
modules that need it compiled OUT: one broken configuration traded for another.
Cargo creates an implicit `tokio` feature for an optional dependency, and it is
true exactly when some feature brought tokio in. That is the predicate the code
actually depends on, so that is the gate.
What is gated, and why each:
executor::cpu the ONLY executor module that was not already feature-gated,
and the one needing tokio::process::Command / AsyncReadExt /
timeout. Its five siblings (gpu, microvm, remote, tls, simd)
are all gated; this makes it consistent rather than special.
messaging tokio throughout
scheduler tokio throughout
Pool, PoolBuilder and their impls, and the imports they need
the crate's high-level API is async to its core --
tokio::sync::RwLock, tokio::task::JoinSet, tokio::time::sleep,
and a CpuExecutor that spawns processes through tokio. There is
no meaningful tokio-free Pool to preserve, so the whole surface
is gated with the runtime it requires rather than half-gated
into something that compiles and cannot run.
Verified in every direction, because a gate that breaks the normal path is worse
than the defect:
cargo check -p aprender-distribute --no-default-features 0 errors (was 43)
cargo check -p aprender-distribute 0 errors
cargo check -p aprender-distribute --all-features 0 errors
cargo test -p aprender-distribute --lib 84 passed
clippy -D warnings, all three feature sets 0 errors
cargo check --workspace --no-default-features 0 errors <- the T-1 clause
Load-bearing, proved by mutation rather than asserted: removing the gate on
`executor::cpu` alone puts --no-default-features back to 10 errors; restoring it
returns 0.
Closes #3176
Pmat-Ticket: PMAT-1098
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…scade (#3179) `--features cuda` has not compiled since APR-MONO. Three gaps, each verified by reading the tree rather than inferred: 1. `trueno_gpu::driver::PinnedBuffer` and `GpuBuffer::copy_{from,to}_pinned_async` do not exist and never did in this monorepo — `git log -S PinnedBuffer -- crates/aprender-gpu/` is empty. Only synchronous pageable copies exist. 2. src/gpu/batch/mod.rs:610 launches the entry point `lz4_compress_warp_shuffle` with 32 threads and `shared_mem: 0`. No kernel of that name exists. The one that does, `lz4_compress_warp`, is documented as 128 threads per block with shared memory. 3. `Lz4WarpDecompressKernel::build_ptx` is a STUB whose entire body is `ctx.label("L_exit")`. There is no GPU LZ4 decompressor in this workspace. So this is not one API away from working: it is wired to a kernel ABI removed at consolidation, and its decompressor does not exist. DECIDED BY QUORUM, two rounds. Round 1 (3 agy lanes) voted 2/3 to rewrite the path on the pageable API so it would compile. Facts 1-3 above were verified AFTER that vote, so round 2 put them to three fresh lanes: all three overturned round 1, unanimous that making a dead path compile to turn a matrix cell green is theater. Round 2 split 2/1 between deleting the path and this option. I took the minority option and the reason is a fact neither deleting lane had: this crate's DEFAULT build is green, and `gpu/batch` is live, compiling, public API that `gpu/hybrid.rs` uses. Only the cuda-gated arms are dead. Both deleting lanes argued from "a dark, unused feature"; the module is neither. Deleting it would remove live public types (`GpuBatchCompressor`, `BatchResult`, `BatchDecompressResult`, `GpuBatchConfig`) for no gain, which neither lane actually argued for. One of them said outright that this option "best serves someone who later wants to finish the GPU path". So: one `compile_error!` naming all three gaps, with the real gate moved to a private `__cuda-linked` feature (13+2 sites in batch/mod.rs, 7 in hybrid.rs) so the refusal is the ONLY diagnostic and nothing is deleted. This is the same shape already used in this tree for aprender-simulate's `z3-proofs` and aprender-core's `showcase-profile`. `--features cuda` now prints one named error instead of an unresolved-import cascade; the two selections stay RED in the nightly matrix, but red WITH A REASON, which is the honest state until a real decompress kernel exists. Default builds of both crates are clean, aprender-zram-core --lib is 411/411, and clippy is clean. Refs #3179, #3262 Pmat-Ticket: PMAT-1098 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…py of the tree `make gate` went red on a clean branch with 1107 "NEW unprovable claims", every one of them pointing at an innocent roadmap row. The claims were real rows — read twice. `.claude/worktrees/` is agy's throwaway lane workspace: a full checkout, roadmap.yaml included, created per review lane and left behind when a lane dies. It is in `.git/info/exclude`, so nothing under it can ever reach the tree CI gates. But this guard's universe deliberately includes UNTRACKED files — that is the hole it was written to close (#2512, an untracked file is exactly how a new uncited claim arrives) — so it walked straight into the lane checkouts and counted every entry twice. The arithmetic says it plainly: completed claims 2266 before, 1133 after. Exactly half. Universe 46 roadmap files before, 23 after. NEW 1107 -> 0. check_complexity_ratchet.sh:149 already prunes `*/.claude/worktrees/*`. That lesson was paid for once and never propagated; this guard is the second place it was needed. The prune is applied in `is_candidate` rather than only in the walk, so the `git ls-files` half of the universe is covered by the same rule, and the walk skips descending into what was measured as 66 registered lane worktrees. This does not widen any hole: a path under `.claude/worktrees/` is in `.git/info/exclude` and cannot be committed, so it can never be part of the tree this guard gates. Case-table row ships with the fix: a fixture roadmap planted at `.claude/worktrees/lane-deadbeef/docs/roadmaps/roadmap.yaml` with a completed-and-uncited entry must contribute 0 records. It reads `want 0 got 1` without the prune. Pmat-Ticket: PMAT-3226 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ry night — the matcher cannot see a YAML-quoted name
Five scheduled lanes are red. This is the one whose cause is entirely inside the
guard rather than in the thing it guards.
FAIL: manifest names a step this workflow does not run:
Test-tier decision case table (BSE-17): quick/full/reuse, drift is ENV
The step is there. guards-nightly.yml line 158:
- name: "Test-tier decision case table (BSE-17): quick/full/reuse, drift is ENV"
The inline check matched the BARE spelling:
grep -Fq -- "- name: $name" .github/workflows/guards-nightly.yml
A step name containing a colon-space MUST be quoted in YAML, and this one contains
`(BSE-17): quick`. So the matcher looked for `- name: Test-tier...` while the file
said `- name: "Test-tier...`, and the lane has been red ever since that name was
quoted — reporting a step that runs on every nightly as one the workflow does not
run. A guard that names a real step as missing is worse than no guard: it teaches
the reader to skip the lane.
EXTRACTED rather than patched in place. Logic inside a `run:` block cannot be
unit-tested and cannot carry a case table, which is why a one-character class of
defect survived in it. scripts/check_guards_nightly_manifest.sh now matches on the
PARSED name, so all three YAML quotings of one string are one step.
Case table, 7 rows, both directions:
bare name parsed ok
DOUBLE-quoted name unquoted (the defect) ok
single-quoted name unquoted ok
trailing whitespace stripped ok
manifest fully covered -> exit 0
a genuinely absent step -> exit 1 <- still fails; not made permissive
vacuity floor, <5 entries parsed -> exit 1
Against the real tree: `ok 7 manifest entries, every one a step in this workflow`.
Mutation: appending one bogus entry turns it RED again, so the fix widened the
matcher without disarming it.
The self-test found a defect in its OWN HARNESS first: invoking `step_names` through
`bash -c 'source ...'` re-ran this file's dispatch and returned nothing, so four
rows failed while the parser was correct. A broken harness reporting a working
parser as broken is the same error as the one being fixed, in the other direction.
Wiring: `guard_tree.sh --dry-run` reports it `wired-elsewhere guards-nightly.yml`
and check_guards_are_wired.sh exits 0. bashrs 7.4.1: 0 errors.
check_roadmap_sorted.sh caught the roadmap entry inserted at a stale slot — main
gained PMAT-3228/3229 while this branch was being written, so "after 3222" was no
longer sorted. Re-inserted among its numeric peers.
ont-delta: none — a CI guard fix; it adds no entity, shape, verdict reason or
resolves target of its own.
Pmat-Ticket: PMAT-3234
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…xample — needs-feature
examples-nightly is one of five red scheduled lanes. Its verdict is currently not a
trustworthy signal about whether examples work, which is the exact property
APR-RELEASE-001 §4.2 and T-1 want to depend on.
Run 34826552378, 980 example targets:
summary pass=602 fail=22 timeout=6 needs-args=30 needs-hardware=2 needs-data=318
The 28 fail+timeout rows, classified by what the output actually says:
6 the example is not built with the feature it needs <- NOT broken
2 needs a network peer (192.168.50.100:9000) <- NOT broken
1 needs a TTY ("No such device or address") <- NOT broken
6 timeout at 180 s (buggy_server, brick_computer ...) <- servers by design?
13 remainder
So a quarter of the lane's red is a MISSING LABEL, not a defect. This commit takes the
6:
aprender-db::compressed_kv This example requires the 'compression' feature.
aprender-rag::compressed_index This example requires the 'compression' feature.
aprender-rag::semantic_embeddings This example requires the 'embeddings' feature.
aprender-distribute::tensor_example Error: This example requires the 'tensor' feature.
...
and cargo's own refusal, which says it differently:
target `gpu_info` in package `aprender-zram-core` requires the features: cuda
This follows the precedent this file set for `needs-data` on 2026-09-12 (173 rows), and
obeys the rule its own header states: "one turns a real defect into a skip, so each
addition belongs in the selftest."
LIKE needs-hardware, NOT like needs-args. A needs-feature row is a SKIP that must be
re-run WITH the feature before a release verdict. A green lane on a default-feature
host must never be readable as "the compression example works" — which is why the row
cites the line that classified it.
THE REGEX SHIPS BOTH POLARITIES, because a skip class can only ever turn a `fail` into
a non-failure:
MUST match This example requires the 'compression' feature.
Error: This example requires the 'tensor' feature.
... requires the features: cuda
MUST NOT match thread 'main' panicked at src/main.rs:11:39
error[E0432]: unresolved import `trueno_gpu::driver::PinnedBuffer`
Error: Os { code: 6, kind: Uncategorized }
assertion failed: left == right
feature is required for this operation <- the deciding near-miss
Mutation, both directions:
regex matching nothing -> selftest RED
regex widened to "feature" -> selftest RED
shipped regex -> green
The harness caught its own staleness too: a completeness assertion hardcoded "one of the
six classes" and went red on the seventh. Updated rather than widened — the assertion is
what stops a row being written with no class at all.
NOT touched here, because they are separate causes and deserve their own triage: the 2
network rows, the 1 TTY row, the 6 timeouts, and the 13 remaining. One of those 13,
`aprender-zram-core::gpu_info`, is already owned by #3267 — which found that
`trueno_gpu::driver::PinnedBuffer` "does not exist and never did in this monorepo".
bashrs 7.4.1: 0 errors. selftest: all rows passed.
ont-delta: none — a classification fix in a CI harness; it adds no entity, shape,
verdict reason or resolves target of its own.
Pmat-Ticket: PMAT-3235
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… — the classifier existed and this lane did not call it
Silicon Nightly is red. Its failing step is named
SIMD and numeric paths (x86_64, widest vectors)
which, on an ML framework, reads as arch-specific numerical incorrectness. It is not.
3511 tests passed; the job died afterwards on:
error: could not parse/generate dep info at:
.../target/release/deps/arrow_ipc-b83c0a68418506db.d
A dep-info file vanished while cargo was writing it. That is a HOST fault, it is
already classified, and it is already fixture-tested in this repository: #3241 built
scripts/cargo_step.sh for precisely this, after mdBook CI reported the same error as
"a book that does not build". Its case table carries the row
W2 dep-info ENOENT is ENV
MEASURED COVERAGE OF THAT CLASSIFIER, main @ a0634f7:
cargo invocation lines across all workflows 75
routed through cargo_step.sh 5 (book.yml, and only book.yml)
So the instrument covers 7% of the surface, and the lane that just died is in the
other 93%. `scripts/cargo_classify.sh` has said ENV-or-CODE since #2712/#2822 and six
check_*.sh guards source it; a cargo command running as a BARE workflow step has no
arm at all. That is the shape #3241's own header describes, fixed for one lane rather
than for the class.
This routes both legs of silicon-nightly — x86_64-cpu and aarch64-cuda-sm121, four
cargo invocations — through it, and adds the self-test caller to each job first,
because a classifier nothing proves is the same theater as no classifier (book.yml's
pattern, and what check_guards_are_wired.sh requires of any script shipping a
--self-test).
IT DOES NOT MAKE THE LANE GREEN, and must not. cargo_step.sh's own contract: "ENV
still exits NON-ZERO -- a gate that goes green on 'we could not measure' is the defect
it exists to name." What changes is the CLAIM: a host fault stops reading as a SIMD
defect, so nobody spends a morning on AVX-512 correctness because a file disappeared.
A defect I introduced and caught before pushing, worth recording because the fix
looked right: the first pass used a naive string replace, and the SECOND replacement
matched the continuation line INSIDE the wrapper the first had just created —
double-wrapping the x86_64 leg while leaving aarch64 raw. Redone by line position.
The job-name derivation was wrong too, labelling the x86_64 steps `coverage:` (a real
sibling job in this file), corrected after checking which job each line actually sits
in rather than trusting the first answer.
Guards: check_workflow_cargo_packages.sh 0, check_workflow_env_defined.sh 0,
cargo_step.sh --self-test 0. YAML parses, 4 jobs.
The other four red nightlies are separate causes: guards-nightly (#3285),
examples-nightly (#3288), Coverage Nightly, CUDA Nightly (PP-26).
ont-delta: none — a CI classification fix; it adds no entity, shape, verdict reason or
resolves target of its own.
Pmat-Ticket: PMAT-3236
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…n-immune Coverage Nightly has been red every night. #3227 fixed the test it was named for (a lock in apr_serve_tests.rs) and landed 02:19Z; the 08:18Z run on a1a19c4 — which CONTAINS that fix — failed on a different one: thread 'benchmark::tests::test_decompression_faster_than_compression' panicked at crates/aprender-zram-core/src/benchmark.rs:522:9 test result: FAILED. 403 passed; 1 failed WHY THE OBVIOUS DEFENCE DID NOT WORK. This test is ALREADY a same-process ratio, which is the shape its neighbour test_f058_entropy_overhead_minimal was rewritten into and which that comment explains: "load-immune because both measurements are taken in the same process, microseconds apart, under whatever load exists". Load-immune is not instrumentation-immune, and they are different axes. `cargo llvm-cov`'s overhead scales with the number of instrumented branches EXECUTED, and the compress and decompress paths do not execute the same number. So under coverage this ratio measures instrumentation density, not the algorithm — no amount of same-process-ness helps, because the distortion is not noise, it is systematic and asymmetric. The ratio had already been widened once for exactly this reason ("In debug builds with coverage instrumentation, decompression may be slower", 0.25) and the lane failed on it anyway. Widening again is the treadmill f058's own comment names: "the number it measures is how loaded the machine is." SO: assert where the number means something, report where it does not. #[cfg(coverage)] print the two rates; assert only that BOTH paths produced a rate, which stays true under instrumentation and still catches a zero #[cfg(not(coverage))] the 0.25 ratio, unchanged `cargo llvm-cov` compiles with `--cfg=coverage` — verified, not assumed: $ cargo llvm-cov show-env __CARGO_LLVM_COV_RUSTC_WRAPPER_RUSTFLAGS='-Cinstrument-coverage--cfg=coverage' so this is a compile-time split, not a runtime guess at whether we are instrumented. PROVEN, because a passing test does not say which branch ran: without the cfg 0 "informational" lines -> the ASSERT branch ran with --cfg=coverage 1 "informational" line -> the REPORT branch ran mutation 0.25 -> 1000.0, no cfg -> FAILED The third row is the one that matters: the assertion is still load-bearing where it is kept, so this narrows the claim rather than deleting the test. This is the third pattern in this file, beside f058's ratio rewrite and F053's report-don't-assert, and the distinction between them is the finding: f058 defends against LOAD, F053 gives up on an ABSOLUTE bound, and this one gives up on a RATIO only where the instrument distorts it. fmt clean, clippy -D warnings 0 errors, roadmap additive (reserialised=0). ont-delta: none — a test-assertion fix; it adds no entity, shape, verdict reason or resolves target of its own. Pmat-Ticket: PMAT-3237 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Third time tonight. My insertion helper rejoins entry blocks with an added newline, re-serialising the entry ABOVE the insertion without any field changing — PMAT-980 (#2874). The remedy is the one check_roadmap_diff_additive.sh names. Pmat-Ticket: PMAT-3234 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Third time tonight. My insertion helper rejoins entry blocks with an added newline, re-serialising the entry ABOVE the insertion without any field changing — PMAT-980 (#2874). The remedy is the one check_roadmap_diff_additive.sh names. Pmat-Ticket: PMAT-3235 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Third time tonight. My insertion helper rejoins entry blocks with an added newline, re-serialising the entry ABOVE the insertion without any field changing — PMAT-980 (#2874). The remedy is the one check_roadmap_diff_additive.sh names. Pmat-Ticket: PMAT-3236 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Pmat-Ticket: PMAT-3231
This was referenced Sep 15, 2026
This was referenced Sep 15, 2026
Closed
|
§13.11 rung 1 — quorum shadow verdict Shadow mode: this records a verdict and merges nothing. A refusal |
… semantically Nine branches each inserted their roadmap entry at the correct slot RELATIVE TO MAIN AT THE TIME. main then gained PMAT-3228 and PMAT-3229, so merging #3272 placed PMAT-3226 after them by textual context: 3222, 3228, 3229, 3226. check_roadmap_sorted.sh is RED on the merged tree and GREEN on all nine branches individually. This is the class of defect a batch surfaces and per-PR CI cannot: each input is sorted, the union is not. Pmat-Ticket: PMAT-3231
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Sep 15, 2026
noahgift
enabled auto-merge
September 15, 2026 07:49
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Sep 15, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Sep 15, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Sep 15, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Nine PRs, one queue entry. #3250 #3253 #3257 #3267 #3272 #3285 #3288 #3289 #3290.
Why
42 open PRs against a drain of 8.8/day. A successful
merge_groupCI run is median78 min with
max_entries_to_merge = 1, so nine separate entries is ~12 h of queuefor 623 insertions across 22 files. As one entry it is 78 minutes.
The root cause is in #3294: one finding → one PR, while discovery here is by sweep.
ci.ymlfires only on PRs targetingmain— by design, so that stacking is cheap.This is that design being used.
Selection — not arbitrary
The nine were chosen by measured file disjointness, not by size or theme. Of the 42
open PRs, 24 collide with at least one other on a real file (62 colliding pairs);
18 collide with nobody. These nine are drawn from that 18, so the merge cannot
conflict by construction — and did not:
docs/roadmaps/roadmap.yamlanddocs/audits/impl-estimates.jsonlwere excluded fromthe disjointness test, since every PR writes them. The roadmap merged additively anyway:
Note this is where
merge=roadmapworks — it is registered per-invocation locally(
git -c merge.roadmap.driver=…). Inside GitHub's merge queue that config does notexist and the driver is inert, which is #3294 Why 4 and the reason nine entries would
have collided there while one does not.
Verification on the combined tree
cargo fmt --all -- --checkcargo check -p aprender-cgp --lib --testscargo check -p aprender-distribute --lib --testscargo check -p aprender-zram-core --lib --testscargo check -p aprender-present-yaml --lib --testscheck_roadmap_diff_additive.shreserialised=0check_guards_nightly_manifest.sh --self-testEach member was green on
gateandworkspace-testindividually; this re-runs theparts that can differ on the merged tree.
What each member does
aprender-distributeused tokio unconditionally behind an optional featurecudafeature says why it cannot build instead of a cascadeguards-nightlyRED naming a step that runs every night (real cause: the matcher read raw YAML)needs-featureclass, refs #3182Closes #3185
no-close: the other members reference #3182 and #2822, which stay open — each fixes the
misclassification, not the underlying class. See their rows above.
The nine source PRs will be closed as superseded by this one, branches retained.
🤖 Generated with Claude Code