Repository navigation
fix(cost): price a CopyPlan by its footprint, not by a raised Copy row (#364, #363) - #424
Conversation
Repository rules reviewRepository rules review (edcf71fafb91f949553fb3f7d6df94af6a0d6e04...f893cabd4fe32503e5020ae59d8ee7c5ab3f520e) Verdict: pass Findings: - [warn] llm-skipped (External LLM Review) <unknown>: External LLM review was skipped External LLM review is permanently disabled; deterministic checks only. |
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fineCI run Reviewed head: |
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fine
Reviewed head: |
c4ba103 to
87d0237
Compare
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fine
Reviewed head: |
70444ad to
c7cdf20
Compare
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fine
Reviewed head: |
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and finenone Not checked: Rust tests, mutations, and benchmarks were not executed here; the reproduction outcomes above are source-traced, not runtime measurements. Reviewed head: |
`CopyPlan` priced every copy at the `Copy` row (0.171 ns per element on `x86_64-avx512`), which is the L2-resident contiguous rate. A working set past the class's L2 cache whose traversal touches a new cache line per element pays about 3.0 ns per element there, so the row under-priced a 512x512 transposing copy by 6-19x and the width rule picked a width for a job that much smaller. `compile` now records the span of each side, and the plan forms its footprint in bytes at replay, each side at its own element size (the one fact `compile` cannot know), so this stays a compile-time plan property with no probing. The crate-internal `copy_ns_per_element_for_footprint` answers the beyond-L2 copy rate past the class's 1 MiB L2 and the row at every other size, and the plan's rate is the one every scheduling decision asks at: the width of the replay that is not tiled (`for_len_at_rate`) and both the fork gate and the recursive splitter of the tiled replay of #422 (`is_parallel_at_rate`, `mapreduce_threaded_at_rate`). A caller's budget is not narrowed for the tiled replay, so only the decision to fork changes. A plan that is one unit-stride run (reversed included) keeps the row at every footprint: a streamed contiguous copy measures 0.176-0.177 ns per element at 2 and 16 MiB, i.e. the row within 4%. Contiguous callers' widths therefore do not move, and the row itself is not raised: raising it to 0.500 (the withdrawn head) also leaves 3.09 / 0.500 = 6.18x of error on the acceptance case. Acceptance: the plan estimates 3.0 ns per element against the 3.09-3.24 the 512x512 serial case measures on the host of #363 (criterion: a factor of two). `UpdatePlan`, the gather plans and the plan-free `replay_*_raw` entries keep the row. Four tests carry the change, two of them executed (worker installs through `threadteam`'s ledger for the untiled replay, recorded splitter leaves for the tiled one) and one per mutation the last review asked for: pinning the rate to the row fails the two executed tests and the acceptance test, and dropping the reversed-run exemption fails the reversed one. `docs/worklogs/2026-11-09-issue-364-copy-plan-footprint.md` carries the measurements, the red-then-green runs, the mutations and the residual (including what is not calibrated).
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fine
Reviewed head: |
9ce8387 to
246e89b
Compare
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fine
Reviewed head: |
…and correct the harness budget (#364 review)
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and finenone Not run here: Rust tests, mutation commands, or benchmarks; the reproductions above are source-traced, not execution results. Reviewed head: |
… forwarding on every host (#364 review) - `is_contiguous_run` reads the fused axes in replay order (axis 0 fastest). A dense reversed buffer of rank two or more is walked with its largest stride fastest, because fusion sorts by signed destination stride. It is no longer exempt: it is priced as the strided walk it is. The fusion sort itself is unchanged. - `CopyPlan::replay_on(host, ..)` / `ns_per_element_on(host)` make the class injectable. The forwarding tests replay at `X86_64Avx512` with a `Generic` control instead of returning early on classes without a beyond-L2 rate. - New `the_contiguous_exemption_is_the_walk_the_replay_takes` records the replay's visits and checks the exemption against them. It replaces `a_reversed_dense_buffer_keeps_the_copy_row`. - New `a_transposing_plan_past_l2_asks_for_the_width_of_its_measured_time` checks #364's budget-96 criterion against `width_for(measured, 1)` on the 512 and 1024 rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and finenone Not checked: AVX-512 performance or a fresh full-workspace matrix; the changed scheduler’s performance remains unverified. Reviewed head: |
… tiled placement (#364 review) The transposing layouts take the tiled replay, which keeps the caller's budget. Its splitter records 96 leaves at budget 96 for 512^2 and 1024^2. The test only compares `for_len_at_rate` at the plan's rate with `width_for(measured, 1)`, so it is renamed to say that. The worklog now records the tiled placement as not meeting #364's criterion, and as an open item. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fine
Validation limit: no source rebuild, fresh mutation run, or hardware performance measurement was performed. Reviewed head: |
`CopyPlan` priced every copy at the `Copy` row (0.171 ns per element on `x86_64-avx512`), which is the L2-resident contiguous rate. A working set past the class's L2 cache whose traversal touches a new cache line per element pays about 3.0 ns per element there, so the row under-priced a 512x512 transposing copy by 6-19x and the width rule picked a width for a job that much smaller. `compile` now records the span of each side, and the plan forms its footprint in bytes at replay, each side at its own element size (the one fact `compile` cannot know), so this stays a compile-time plan property with no probing. The crate-internal `copy_ns_per_element_for_footprint` answers the beyond-L2 copy rate past the class's 1 MiB L2 and the row at every other size, and the plan's rate is the one every scheduling decision asks at: the width of the replay that is not tiled (`for_len_at_rate`) and both the fork gate and the recursive splitter of the tiled replay of #422 (`is_parallel_at_rate`, `mapreduce_threaded_at_rate`). A caller's budget is not narrowed for the tiled replay, so only the decision to fork changes. A plan that is one unit-stride run (reversed included) keeps the row at every footprint: a streamed contiguous copy measures 0.176-0.177 ns per element at 2 and 16 MiB, i.e. the row within 4%. Contiguous callers' widths therefore do not move, and the row itself is not raised: raising it to 0.500 (the withdrawn head) also leaves 3.09 / 0.500 = 6.18x of error on the acceptance case. Acceptance: the plan estimates 3.0 ns per element against the 3.09-3.24 the 512x512 serial case measures on the host of #363 (criterion: a factor of two). `UpdatePlan`, the gather plans and the plan-free `replay_*_raw` entries keep the row. Four tests carry the change, two of them executed (worker installs through `threadteam`'s ledger for the untiled replay, recorded splitter leaves for the tiled one) and one per mutation the last review asked for: pinning the rate to the row fails the two executed tests and the acceptance test, and dropping the reversed-run exemption fails the reversed one. `docs/worklogs/2026-11-09-issue-364-copy-plan-footprint.md` carries the measurements, the red-then-green runs, the mutations and the residual (including what is not calibrated).
…and correct the harness budget (#364 review)
… forwarding on every host (#364 review) - `is_contiguous_run` reads the fused axes in replay order (axis 0 fastest). A dense reversed buffer of rank two or more is walked with its largest stride fastest, because fusion sorts by signed destination stride. It is no longer exempt: it is priced as the strided walk it is. The fusion sort itself is unchanged. - `CopyPlan::replay_on(host, ..)` / `ns_per_element_on(host)` make the class injectable. The forwarding tests replay at `X86_64Avx512` with a `Generic` control instead of returning early on classes without a beyond-L2 rate. - New `the_contiguous_exemption_is_the_walk_the_replay_takes` records the replay's visits and checks the exemption against them. It replaces `a_reversed_dense_buffer_keeps_the_copy_row`. - New `a_transposing_plan_past_l2_asks_for_the_width_of_its_measured_time` checks #364's budget-96 criterion against `width_for(measured, 1)` on the 512 and 1024 rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… tiled placement (#364 review) The transposing layouts take the tiled replay, which keeps the caller's budget. Its splitter records 96 leaves at budget 96 for 512^2 and 1024^2. The test only compares `for_len_at_rate` at the plan's rate with `width_for(measured, 1)`, so it is renamed to say that. The worklog now records the tiled placement as not meeting #364's criterion, and as an open item. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e what the harness checks - `a_transposing_plan_rate_past_l2_gives_the_width_of_its_measured_time` now replays both rows against the 96-slot token and records the splitter's leaves: 96 for both, i.e. the tiled placement asks for the budget, not for the width its rate wants. That gap is strided-rs#430; the test's doc says so instead of claiming the criterion on the tiled path. - The benchmark section of the worklog claimed its two endpoint asserts would catch a wrong traversal; a constant 1.5 fill passes a copy that skips the interior or ignores the transpose. The claim is removed and the residual says correctness is carried by the unit tests. - The untiled extreme (rank-1, stride 256) is 9.6-12.7 ns per element under a co-tenant; the 'under-prices, not over' direction is withdrawn because a contended sample cannot establish the uncontended value.
The branch was rebased onto main so that #429's spilled-traversal tiling and the plan's own rate meet in one replay: the tiles now come from PairTraversal::tiles, and the rate the untiled replay prices itself at is threaded through the inline, spilled-inline and spilled-raw arms.
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fine
Not checked: full local gates and parallel-performance comparisons; local Reviewed head: |
…r the published harness (#364 review) - `replay_spilled_tiled` gated at the `Copy` row: a rank-above-inline plan whose tiles the model applies to the compressed axes forked on the inline path and stayed serial on the spilled one. Its outer gate and its splitter now take `ns_per_element` like the inline path. The rate is threaded from `replay_fused`'s spilled arm. - `a_spilled_tiled_plan_past_l2_prices_its_splitter_at_its_own_rate` (dims [4;9], dst strides ascending powers of four, src reversed) installs a worker at the plan rate and none when priced for a class without a beyond-L2 rate. Reverting the gate to `is_parallel(KernelClass::Copy, ..)` fails it ('the spilled splitter did not fork'). - The worklog's harness snippet lost the brace that closes `plan_case`'s repetition loop during the previous edit; `rustfmt --emit stdout` now parses the fenced block. The residual no longer asserts an underpricing ratio from co-tenant samples.
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fine
Reviewed head: |
|
Parallel Host: Harness (committed to neither tree; let plan = CopyPlan::compile(dims, dst_strides, src_strides).unwrap();
for rep in 0..45 {
let src_ref = RawStridedRef::new(&src, dims, src_strides, 0).unwrap();
let mut dst_mut = RawStridedMut::new(&mut dst, dims, dst_strides, 0).unwrap();
let start = Instant::now();
plan.execute(&mut dst_mut, &src_ref, exec.reborrow()).unwrap();
let elapsed = start.elapsed();
if rep >= 4 { samples.push(elapsed.as_secs_f64() * 1e9 / total as f64); }
}
// outside the clock: every logical element against the strided oracle, with src[i] = i + 0.5
The 1t tiled row is where the largest ratio appears, and the base's own spread (2.290-2.398, Residual: not a quiet-host measurement (load 3.3-3.7 from other users), and a 4-slot budget |
…d that exists (#364 review)
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changes
Unverified claims
Checked and fine
Not checked: native AVX-512 parallel timings; scheduling performance remains unverified. The local test rerun was not completed within the verification worker’s budget. Reviewed head: |
GPT-6.1-sol adversarial reviewCRITICAL: none Critical (must not merge)none Needs changesnone Unverified claims
Checked and fine
Reviewed head: |
Rebuild of this branch: it implements #364 item 2 instead of raising the
Copyrow. The withdrawn head raisedcopy_ns_per_element_of(X86_64Avx512)from 0.171 to 0.500, which #364 item 3 forbids, which still left3.09 / 0.500 = 6.18xof error on its own acceptance case, and which moved the widths of thestrided_perm::copy_intoengine. No row of the class table moves here:strided-perm/is byte-identical tomain.Head
f893cab: the branch was rebased ontomainafter #429 landed, so it carries one merge commit (a2a28f1); worklog indocs/worklogs/2026-11-09-issue-364-copy-plan-footprint.md.What it does
CopyPlan::compilenow records the reach of each side (1 + sum((dim - 1) * |stride|)), and the replay forms the plan's working set in bytes asdst_span * size_of::<D>() + src_span * size_of::<S>()— each side at its own element size, each operand counted once. The element size is the one factcompilecannot know; there is no runtime probing, so this stays a compile-time plan property.cost::copy_ns_per_element_for_footprint(crate-internal) answers the class's beyond-L2 copy rate past the class's 1 MiB L2 and the row otherwise. Onx86_64-avx512that rate is 3.0 ns per element. A plan whose replay walks it as one unit-stride run (reversed-1runs included) keeps the row at every footprint, which is what #364 item 3 asks: contiguous callers' widths do not move. "Walks" is literal:is_contiguous_runreads the fused axes in the order both replays walk them (axis 0 fastest), not in an order the layout would allow.Dense reversed buffers: option (a), the exemption follows the replay's order
A dense reversed buffer of rank two or more (
[-1, -512]over[512, 512], or the spilled rank-9[-1, -4, ..., -65536]) is not one run in the replay: fusion sorts by signed destination stride (strided-basic/src/raw_ops.rs:175-180), so it walks-512/-65536fastest (raw_ops.rs:632,raw_ops.rs:730). The previous head exempted it by matching strides in ascending magnitude. It is now priced as the strided walk it actually is (CopyPlan::is_contiguous_run,strided-basic/src/copy_plan.rs:314).I chose this over (b), re-sorting fusion by sign group and magnitude so that the buffer becomes one run, because that sort is not the plan's own.
fuse_pair_traversal/fuse_pair_layoutalso feedUpdatePlan, both gather plans andcopy_scale_raw/copy_scale_conj_raw/axpy_raw/axpy_conj_raw(raw_ops.rs:271,898,929,960,991,gather_plan.rs:1084,1453). (b) would therefore change the visit order of every one of those families, and with it the accumulation order ofaxpy_rawover a non-injective destination. That is a traversal change with its own benchmark obligation (REPOSITORY_RULES § Performance), not a costing change for #364. The walk itself ismain's and is left as it is; it is listed as a residual in the worklog (sec. 6).The plan's rate is the one every scheduling decision asks at: the width of the replay that is not tiled (
for_len_at_rate) and both the fork gate and every node of the recursive splitter of the tiled replay of #422 (is_parallel_at_rate,threading::mapreduce_threaded_at_rate) instead ofKernelClass::Copy. A budget is not narrowed for the tiled replay, so a caller's width stays the caller's and only the decision to fork moves.UpdatePlan, both gather plans and the plan-freereplay_*_rawentries keep the row. The host class is a parameter of the privateCopyPlan::replay_on/ns_per_element_on(replaypassesHostClass::detect()), so the tests can name it. #364's item 1 (a per-segment term) is not in this change.Acceptance (#364: 512x512 transposing f64, serial, factor of about 2)
#364's scheduling criterion is the width at budget 96 within one step of
width_for(measured_serial, 1)on the transposing rows. A test now checks it for the width rule at the plan's rate (for_len_at_rate;a_transposing_plan_rate_past_l2_gives_the_width_of_its_measured_time). It uses thex86_64-avx512dispatch costs and a root token dispatching from outside the pool. The measured values are #364's Xeon 9242 table, quoted.width_for(measured)The tiled placement does not meet it. These transposing layouts take the tiled replay of #422, which does not narrow the budget (
copy_plan.rsreplay_tiledhandsexecto the splitter unnarrowed, as onmain). Replayed throughreplay_on(X86_64Avx512, ..)with a 96-thread pool at budget 96, the splitter records 96 leaves for both 512² and 1024² (1 install;max_live21 and 17 on this Mac). The plan-width column above is therefore the width rule's answer, not the participant count of the replay these layouts take. Narrowing the tiled replay to that width would change #422's scheduling without a measurement, so it is not done here; that gap is strided-rs#430. The test now executes that replay for both rows against a 96-slot token and asserts the leaf count, so the numbers above are a measurement rather than a claim. The spilled tiled branch (rank above the inline limit) now forwards the same rate to its outer gate and splitter, which it did not before this commit;a_spilled_tiled_plan_past_l2_prices_its_splitter_at_its_own_ratecovers it and fails when the rate is dropped.The rows that fit L2 keep the row and stay 2.7–7.8x low on today's measurements (9.1–9.3x on the pre-#422 numbers of the withdrawn worklog, quoted). Those rows are #364 item 1, not item 2; raising the row would still miss the criterion (
3.09/0.500 = 6.18x,1.56/0.500 = 3.12x) while moving every contiguous caller's width.The calibration is of the tiled transposing path. The replay that is not tiled is not calibrated row by row: a rank-1 run at stride 256 (one element per 2 KiB) measured 9.8 ns per element while a co-tenant process shared the measured CPU set. A contended sample cannot establish the uncontended value, so this is recorded as an observation and no direction or ratio is claimed for the gap; a run long enough to fill a cache line was not measured. The "up to 3x high" bound of the earlier revision had no measurement behind it and is withdrawn.
Performance
Parallel
CopyPlan: measured on an AVX-512 host.EVO-X2(Ryzen AI MAX+ 395, Zen 5, 32 threads),public
CopyPlan::execute, medians of 41 repetitions after 4 warmups, three runs per tree, fulloutput validated against the strided oracle outside the clock:
edcf71ff893cabHost load was 3.3-3.7 throughout (other users), and the base's own 1t spread is 4.7%, so the run
resolves no single-digit difference; it does show no move outside the host's noise in any cell and
none at all in the untiled cell (which stays serial at 4 slots, as pricing it at 3.0 predicts).
A quiet-host 8+ slot run and a spilled-tiled parallel row remain unmeasured.
The tables below are serial
CopyPlanand the unchangedstrided_perm::copy_intoengine.strided_perm::copy_into, before (main) and after (this commit), same harness and placementMedian of 41 warm repetitions, budget 16, measured process pinned to cpus 0-7,16-23 (one L3 domain), observer on 8-15,24-31; nanoseconds per element, microseconds in brackets.
b2358fb1417eb5(row 0.500)copy_intois main's within run-to-run noise (0.315–0.320, 0.151–0.156 over five runs), and its width is main's by construction (the file is unchanged). The withdrawn head's worklog recorded 5.00 → 6.16 us (+23.2%) at 128x128 and 0.70 → 0.90 us (+28.6%) at 4096 for this engine; those two rows did not reproduce here on either tree — with the host's default dispatch costs the engine's first section costs 9.7 us (theOutsiderow) against its 2.8 us estimate, so it stays at width 1 and the row cannot reach its width. At sizes where it does reach the width (512x512: width 6 → 10, 1024x1024: 11 → 16), the row moves it and the time moves in both directions, which is why #364 item 3 says not to move the row.CopyPlan::executeserial,n x nf64, ns per element, measured here today: 512x512 2.421/2.423/2.429 (this commit) against 2.411/2.418/2.425/2.757 (main) and 7.340/7.397/7.665 (withdrawn head); contiguous 0.175–0.177 in all three.Red then green (this round, review of
08895fd)Run on Apple M-series (
aarch64-apple), 2026-11-09. Full logs were kept; the lines below are copied out of them.NEEDS 1, the exemption against the actual walk.
the_contiguous_exemption_is_the_walk_the_replay_takesreplays seven layouts serially. Itsapplyclosure records each (destination slot, source slot) visit, and the test assertsis_contiguous_run() == (the recorded walk is one unit-step run per side), plus the price onx86_64-avx512(row when it streams, 3.0 when it does not). The layouts are dense forward, reversed rank 1, dense reversed, dense reversed spilled, forward into reversed, mixed signs, and transpose, all past L2. Against08895fd'sis_contiguous_run:With the walk-order check:
NEEDS 2, forwarding tests that cannot skip. Mutation: the rate handed to
replay_fusedis pinned toKernelClass::Copy.ns_per_element(). On08895fd, on this host, both forwarding tests return early and count as passes:They now replay through
replay_on(HostClass::X86_64Avx512, ..), with the same plan atHostClass::Genericas a control that must not fork. They also assert that the row of either class does not pay the pool's fork. Same mutation, same host:The acceptance test
a_strided_plan_past_l2_prices_itself_above_the_contiguous_rowno longer branches onHostClass::detect()either. It namesX86_64Avx512, and every class without a beyond-L2 rate.Footprint branch removed (
copy_ns_per_element_for_footprintanswers the row): five tests fail, among them the new width test:Restored, all green (below). The mutation records of the earlier rounds (1a/1b/2/3) are in the worklog, sec. 5; they were run on the Zen 5 host against the earlier revision.
Verification
Parallel
CopyPlanscheduling (the rate, the fork gate, and the tiled splitter) has no performance evidence: the appendix harness runs every plan withExec::serial(), so its timings cannot exclude a regression from the changed scheduling estimate. This is stated as unverified, not as measured.Run on head
5354bb4(and, after the test rename ind176872,cargo test --workspaceagain: 78 binaries, passed=1146 failed=0; both clippy runs exit 0), Apple M-series. Those runs predate the rebase througha2a28f1and the laterf893cab; forf893cabthe evidence is hosted CI only — every required check completed green. No local run of that exact head is quoted.Counts are summed over every
test result:line of the whole, unfiltered log (awk '/^test result:/ {p+=$4; f+=$6}').Not measured: a hosted GPU gate (no CUDA code in this change) and the reporting Xeon Platinum 9242 of #363 (not available here; its table enters as quoted constants).
The worklog's appendix carries the harness source, the exact commands, the
Exec::serial()/Exec::new(pool, 16)configuration and every run with its load average, so each number above can be re-run and re-checked.review: gpt-6.1-sol needs-changes (round 4,
08895fd): both NEEDS were real and are fixed in5354bb4. (1) The dense-reversed exemption now follows the replay's walk order, option (a) above, with an executed walk-recording test. (2) The forwarding tests name the host class and fail under the forwarding mutation on every host. Of the two UNVERIFIED items, the budget-96 width comparison is now a test of the width rule (512/1024 met, 256 not met), and parallelCopyPlanperformance is stated as not measured, with the reason.review: gpt-6.1-sol needs-changes (round 3) — all three items are fixed in
246e89b: the tiled test now requires more than one splitter leaf and at least one worker install (mutation 2 above, the splitter handed the row while the outer gate keeps the rate, fails with1 leaf/leaves and 0 worker install(s)),strided-basic/src/cost.rs's module doc now states that both the tiled gate and the splitter ask at the plan's rate, and the worklog's mutation record now shows the runs that actually happened (1a/1b/2/3) plus the calibration appendix.review: gpt-6.1-sol needs-changes (round 2) — both NEEDS were real and are fixed in
70444ad: the plan's rate now reaches the tiled replay's fork gate and recursive splitter (is_parallel_at_rate,mapreduce_threaded_at_rate), and the regression tests now execute the plan and count workers/leaves, with a reversed run whose footprint is 2 MiB (2 mutations shown above failing). Both UNVERIFIED items are addressed by narrowing the claim to the tiled path (the untiled/spilled rows are stated as not calibrated, with the one indicative measurement labelled) and by the host-independent AVX-512 test. Round 1's findings (footprint counted both operands twice; reversed runs re-priced; a needless public function on the permutation crate; a tautological width pin; unsupported numeric bounds) are also fixed.review: gpt-6.1-sol needs-changes (round 5,
5354bb4). The NEEDS was real: the budget-96 test checkedfor_len_at_rate, which the tiled replay these layouts take does not use (96 leaves at budget 96, reproduced). The test is renamed to the claim it supports, and the body and worklog now state that the tiled placement does not meet #364's criterion (open decision, above). UNVERIFIED: parallelCopyPlanperformance is still not measured (stated above). The untiled-underpricing ratio rests on co-tenant runs only and is unverified as a ratio. Hosted CI for the new head is pending at the time of writing.