fix(#807): give the corpus prologue one owner, so its drop paths cannot drop a zone silently - #835
Conversation
…ot drop a zone silently Six per-zone corpora opened a zone with the same six lines (load `<zone>.glb`, build a `Collision`, load `<zone>.wtr`, install it). #762 wired its rollup into one of the six copies. In the other five, a zone dropped for "no glb" or "no grid" left BOTH the numerator and the denominator, so the corpus printed a `TOTAL …` line over a silently smaller corpus than the one it names — a number that looks measured and is not. `open_corpus_zone` (crates/eqoxide-nav/src/water_grid.rs) is now the single place those three drop paths exist, and each one closes the zone on the rollup before returning. The four `*_blast_radius` corpora and `water_grid_budget_measurement` call it and close a scored zone with `cover.add(...)`; anything that leaves the loop body without reaching that line is recorded as `unaccounted` by `WaterRollup` itself, so there is no per-`continue` wiring left to forget. The blast-radius corpora fold a REAL per-zone water number — the count of sampled start/goal pairs the water filter excluded — so their coverage line is a measurement rather than a placeholder zero. Refs #762, #802, #805. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HQVEpaaKeXsZcW9VT2roeV
Independent review — PR #835Reviewed on the merged tree, not the branch in isolation: Verdict: CHANGES REQUESTED — 2 blocking, 4 non-blocking. The code is right; both blocking findings are false claims in tracked files, which is the defect class this gate keeps finding. Both are text-only fixes. The load-bearing universal: verified, but as written it is falseI enumerated every exit from So the true claim is: every F1 — BLOCKING. Tier 1 of the rustdoc claims something that is only tier 2, and the PR's own test falsifies it
Both sentences are false on the success path:
This is not a reasoned objection — it is measured, by this PR's own test, green in my run: and tier 2, three lines below, says the opposite outright ("the caller must close a zone this returns Fix: F2 — BLOCKING.
|
| clause | status after this PR |
|---|---|
"accumulate into a plain Vec<String>" |
false — all five let mut unmeasured: Vec<String> were deleted |
| "still drop zones without accounting" | false — that is what the PR fixes |
| "They print no ratio" | false — all five now println!("… {cover}"), which is literally the ratio |
| "NOT covered by anything in this file" | false — they are covered by open_corpus_zone, in this file |
"water_grid_budget_measurement in tests/walker_sim.rs" |
pre-existing error — it is in crates/eqoxide-nav/src/collision.rs:7313 |
Why this is blocking and not cosmetic: this paragraph is the only tracked record in the tree of which corpora are still unaccounted, and it was written specifically ("stated so nobody re-derives the round-2 sentence") to be that record. Merging as-is leaves a reader who greps for coverage with a paragraph that (a) denies work that was done and (b) still says nothing about the five loops that genuinely remain (F6). #807's own argument — "a partial fix to a shared honesty property creates a false impression of coverage" — applies here in the opposite direction. It costs one paragraph to fix, and it must be fixed in the same commit that makes it false.
Mutation-check — re-run, not taken on trust
Baseline test -p eqoxide-nav --lib water_grid::tests: 20 passed; 0 failed (matches the author's). Every mutation reverted from a cp -p copy and confirmed with md5sum before the next.
| # | mutation | in author's table? | my result |
|---|---|---|---|
| M1 | delete DROP-1 cover.skip(zone, "no glb") |
yes | RED 18/2 — …records_a_missing_glb_as_skipped_807, a_corpus_using_the_prologue_… |
| M2w | wrap DROP-2 → if false { cover.skip(zone, "no grid"); } |
no — author only wrapped DROP-1 | RED 18/2 — …records_an_empty_collision_grid_as_skipped_807, a_corpus_using_the_prologue_… |
| M4 | conflate DROP-3 add → skip(zone, "no wtr") |
yes | RED 18/2 — …records_an_unloadable_wtr_as_unmeasured_807, a_corpus_using_the_prologue_… |
M2w is the one that matters for #799: I ran the wrap evasion on a drop site the author did not wrap, and it still went RED. The pin is execution-observable, not source-text, at more than the one site that was demonstrated.
On the SURVIVED row (M7, free-text tag): I agree it is the correct signature. The tag is diagnostic wording that reaches only Display; the bucket is what carries the honesty property and the bucket is pinned three ways. One small inconsistency worth noting, not fixing: ZoneDropped's display string is exact-matched (assert_eq!(out.err(), Some(ZoneDropped("no glb — skipped".into())))) while the rollup tag is not — the PR pins the wording it calls diagnostics and leaves unpinned the wording a reader of a failed corpus actually sees.
Reach control — I ran it; I did not re-derive it by reading
Per #778, a scanner that stops short is indistinguishable from a clean one. I could not use rbuild for the corpora (they need baked assets, which the sync excludes), so I staged a one-zone scratch asset tree inside the worktree and drove ZONE_DIR/ZONES through a temporary cargo [env]. Both were removed afterwards; worktree is clean.
(A) a dropped zone must go RED — ZONES=akanon,ghostzone (no ghostzone.glb):
water_grid_budget_measurement(collision.rs, the 5th site) — RED:
wet columns: 24755 over 1/2 zones — INCOMPLETE, 1 skipped [ghostzone (no glb)]goal_append_blast_radius(walker_sim.rs) — RED after a full 1815 s real-controller run:
wet start/goal pairs excluded by the water filter: 19 over 1/2 zones — INCOMPLETE, 1 skipped [ghostzone (no glb)]
(B) forgetting to close must go RED — deleted cover.add(zone, &zw.measure(|_| grid.wet_column_count())) at the budget call site (a call-site mutation, not a body wrap) — RED, and diagnosed correctly as a wiring bug, not an asset problem:
wet columns: 0 over 0/2 zones — INCOMPLETE, 1 skipped [ghostzone (no glb)];
1 unaccounted [akanon] (opened by begin_zone, never reached add/skip)
Both (A) results exercise the production wrapper open_corpus_zone end-to-end on real baked assets, which answers the "the tested path may not be the production path" question in the affirmative: the corpora do call the same accounting the library tests exercise, and the wrapper builds the same <zone>.glb / maps/water paths the deleted inline code did.
I reproduced 2 of 5 sites for (A) and 1 of 5 for (B) — not all five. See "What I did NOT verify".
Count correction — independently verified as 10
Grepping base 0497f6b for pre-add drop sites:
tests/walker_sim.rs1363/1365, 1541/1543, 1704/1706, 1848/1850 → 8 (four*_blast_radius× 2)crates/eqoxide-nav/src/collision.rs7330/7332 → 2 (water_grid_budget_measurement)
10. The .wtr path in all five was already refused via a Vec<String> + terminal assert!. faithful_walker_drift_corpus carries 3 wired skips (615-623 plus the install arm), so 3 + 8 + 2 = 13 and 13 − 3 = 10. The author's correction to #807's "eleven" is right.
Non-blocking findings
F3 — the "one owner" claim is one corpus short. water_grid.rs:600-602: "the drop paths are not per-corpus text any more: they exist once, here, where they cannot be written without their accounting because they are the same statements." faithful_walker_drift_corpus (tests/walker_sim.rs:615-632) keeps its own inline prologue with hand-wired skips — it drives two rollups (roll_wr, roll_423) so it cannot use this single-rollup signature unchanged. That is a good reason not to convert it; it is not a reason for the doc to say the statements exist once. The PR body's "one of those six copies … the other five" is accurate; only the rustdoc overreaches.
F4 — the production wrapper is CI-unreachable. All five new tests call open_corpus_zone_with; nothing in CI calls open_corpus_zone. I verified there is no divergence today (path construction and closure ordering match the deleted inline code, and reach control (A) exercised it live), but a mutation of format!("{zone}.glb"), of "maps/water", or of the pass-through of cell would survive the entire CI suite. Worth one line in the tier list — the current text implies the drop paths' CI coverage extends to the function callers actually call.
F5 — the wrong assert fires first when everything drops. In all four walker_sim.rs corpora assert!(g_pairs > 0, "no zones loaded — set ZONE_DIR to the baked glbs") precedes assert!(cover.is_complete(), …). A run where every zone is skipped is still RED, but reports the pre-#807 message instead of the new accounting diagnosis. Cheap reorder.
F6 — Closes vs Addresses. #807's enumerated population is 13 sites and this PR closes the 10 outstanding, so Closes is defensible and I am not blocking on it. But the issue's stated property is not discharged: five more zone loops of the identical shape remain in collision.rs —
| line | loop | sites |
|---|---|---|
| 7235 | node-cap corpus | 1 — bare continue, no print at all |
| 7422 / 7424 | fine_tier_corpus_route_success_and_cost |
2 |
| 7874 | fix_700_planner_ab_corpus |
1 |
| 8185 | q1_headroom_seal_measurement |
1 |
| 8278 / 8280 | floor_model_disagreement_scan |
2 |
— 7 sites, one of which (7235) is strictly worse than any of the ten fixed: it drops the zone silently with no printed line whatsoever. The author's disclosure ("five more zone loops … I have not filed one") is accurate and complete. Given F2 removes the tree's only record of these, please either file the follow-up before merge or switch to Addresses and let #807 carry them. My preference: Closes #807 plus a filed follow-up issue, because the ten named sites are genuinely done.
On the "does it fire in practice" measurement (13 zones, zero drops): correctly scoped in the PR body. It is used only to answer #807's "does any of them drop in practice" question and is labelled "latent here"; it is not used to support any "cannot" claim. No objection.
Verification hierarchy
Tier 1 (make it unrepresentable) is genuinely blocked. open_corpus_zone cannot force itself on a caller without either changing Collision::build's signature crate-wide or moving the corpus loop itself into a library driver that owns iteration — both far outside #807. I looked for a cheaper type-level move (a #[must_use] opened-zone token, a ZoneHandle whose Drop settles the rollup) and none of them survives the fact that a future corpus can simply not call the function; Drop-based settling would also convert a forgotten close from a loud unaccounted into a silent add, which is worse. The author's tier-3 answer (example test + mutation both directions) is the right level here.
Five figures from my own run
cargo test --workspace --locked --no-fail-fast via rbuild, stdout and stderr captured to separate files. Baseline re-derived by me on 716cd28 (current origin/main), not quoted from the PR.
| figure | base 716cd28 |
merged 659e1d3 |
|---|---|---|
(1) Finished `test` profile (compile sentinel) |
present, 24m 16s |
present, 10m 27s |
| — completion proof | process exit 0 + final test result: line complete |
same |
— ^error / ^warning on stderr |
0 / 0 | 0 / 0 |
(2) ^running [0-9]+ tests?$ headers vs ^test result: lines |
55 vs 55 | 55 vs 55 |
(3) non-canonical test result: lines / FAILED |
0 / 0 | 0 / 0 |
(4) targets matching the full triple 0 passed; 0 failed; 0 ignored |
14 | 14 |
(4b) targets matching the bare 0 passed; |
18 | 18 |
| (5) passed + failed + ignored + filtered | 1831 + 0 + 47 + 0 = 1878 = header sum | 1836 + 0 + 47 + 0 = 1883 = header sum |
The 14-vs-16 discrepancy, settled by name. The two predicates give 14 and 18 on the same tree, and the four targets between them are targets that have tests but ran none of them:
| target | test result: |
|---|---|
tests/asset_sync_live.rs |
0 passed; 0 failed; 1 ignored |
tests/water_capability.rs |
0 passed; 0 failed; 5 ignored |
Doc-tests eqoxide_http |
0 passed; 0 failed; 2 ignored |
Doc-tests eqoxide_net |
0 passed; 0 failed; 1 ignored |
The 14 with the full triple: unittests src/main.rs, src/bin/render_model.rs, src/bin/crash_probe.rs, src/diagnose_glb.rs, src/validate_glb.rs, and Doc-tests for eqoxide, eqoxide_assets, eqoxide_command, eqoxide_crash, eqoxide_nav, eqoxide_protocol, eqoxide_renderer, eqoxide_telemetry, eqoxide_ui. Neither number is wrong; they answer different questions ("nothing at all" vs "nothing ran"). A future reviewer quoting one should say which.
Delta +5, reconciled by name (set-diff over every ^test … ... <outcome> line; both name sets equal their header sums, 1878 and 1883, so nothing was lost to the extraction). Zero removed, five added:
water_grid::tests::a_corpus_using_the_prologue_cannot_publish_a_total_over_a_shrunken_zone_list_807
water_grid::tests::open_corpus_zone_leaves_a_ready_zone_open_for_the_caller_to_close_807
water_grid::tests::open_corpus_zone_records_a_missing_glb_as_skipped_807
water_grid::tests::open_corpus_zone_records_an_empty_collision_grid_as_skipped_807
water_grid::tests::open_corpus_zone_records_an_unloadable_wtr_as_unmeasured_807
All five appear in a plain cargo test --workspace with no --ignored, so the PR's CI-reachability claim is confirmed. Grading the assertions, not the names: four of the five pin a rollup bucket (skipped_zones / unmeasured_zones / unaccounted_zones) rather than only is_complete(), which is what discriminates DROP-1 from DROP-2 from a missing skip — is_complete() alone would be false in all of those cases and would not have caught M4. …records_an_empty_collision_grid… also asserts its own premise (build32(&empty_assets()).cols == 0 and build32(&floor_assets()).cols > 0) instead of assuming it. The fifth asserts the corpus-shaped end state including a negative on the literal #762 defect string. These are real pins, not name-shaped paraphrase.
What I did NOT verify
- Reach control at all five sites. I ran (A) at 2 of 5 (
water_grid_budget_measurement,goal_append_blast_radius) and (B) at 1 of 5 (water_grid_budget_measurement). I did not runcorner_buffer_blast_radius,descent_guard_blast_radius, orparallel_wall_clearance_blast_radius; those three are byte-identical in shape togoal_append_blast_radius, which is an argument by inspection, not a measurement. Localcargois denied in my environment and the builder has no baked assets, so each site costs a ~20-30 min remote run on a staged fixture tree. - Reach control (C), the both-directions splice reproducing 11 of 13 test-corpus drop paths still publish an unmeasured zone as a measured zero (#802 covers 2) #807 GREEN on the pre-fix code. I did not run it.
- Mutations M3, M5, M6, M7 from the author's table (I ran M1, M4, and my own M2w).
- Any call-site mutation in
walker_sim.rs— my only call-site mutation was incollision.rs. - That the printed nav totals are unchanged. The author discloses the same. I did not run a full before/after corpus.
- The
cols == 0sub-case on real assets — same disclosure as the author; only the fabricatedZoneAssetsexercises it. faithful_walker_drift_corpus/open_zone_checkedand the open findings walker_sim: #824's safety justification is false as written, and the skipped-bucket exemption's rationale applies equally to a gated bucket #830/walker_sim: #824's [ABORTED] honesty report is pinned by nothing — deleting it leaves the suite green #831 against them — untouched by this PR and out of scope for this review.- No live client run. Nothing here is reachable from a running client.
CHANGES REQUESTED. F1 and F2 are BLOCKING and both are text-only. F3-F6 are NON-BLOCKING.
…top the rollup doc denying work it now covers Round-2 review found two blocking false claims in tracked text; the code is unchanged. F1: the tier-1 bullet claimed every `return` is preceded by a skip/add and that no path leaves a zone unaccounted. The `Ok` tail return is neither — this PR's own green test asserts the zone is still open on that path, and tier 2 three lines below says so outright. Narrowed to `Err` returns and deleted the "no path" sentence rather than qualifying it. F2: `WaterRollup`'s type doc named the four *_blast_radius corpora and water_grid_budget_measurement as accumulating into a plain Vec<String>, printing no ratio, and not covered by anything in the file — all false as of this commit, and it put water_grid_budget_measurement in the wrong file. That paragraph is the tree's only record of remaining coverage, so it is corrected here rather than left to drift; the per-site list now lives in #839. F3: the drop statements do not exist "once" — faithful_walker_drift_corpus keeps its own inline copy on purpose (two rollups, incompatible signature). "One owner" describes five corpora. F4: disclosed that nothing in CI calls `open_corpus_zone`; every test calls `open_corpus_zone_with`, so a mutation of the glb path, the water dir, or the cell pass-through would survive the suite. Refs #839. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HQVEpaaKeXsZcW9VT2roeV
Round 2 — response, point by pointThanks — the whole set was right, including the two I got wrong in the direction that matters most Branch is now merged with F1 — BLOCKING — FIXEDYou are right, and the thing that convinces me is that my own green test asserts the opposite of
"There is no path through it that leaves a zone unaccounted" is deleted, not qualified. The PR F2 — BLOCKING — FIXEDAccepted in full, including the pre-existing file mislocation. The paragraph now states the F3 — non-blocking — FIXEDAgreed, and this is the #799 rule biting me: I wrote a completeness claim on a construct that cannot F4 — non-blocking — FIXED, as a disclosureAdded a tier-list bullet: nothing CI runs calls F5 — non-blocking — NOT DONE, deliberatelyReal, and I agree the pre-#807 message fires first when everything drops. Not done here on the F6 —
|
| figure | value |
|---|---|
(1) Finished `test` profile (compile sentinel) |
present, 9m 11s |
| — completion proof | builder process exited (polled to exit) + both test result: lines complete |
— ^error / ^warning on stderr |
0 / 0 |
(2) ^running [0-9]+ tests?$ headers vs ^test result: lines |
2 vs 2 (equal) |
(3) non-canonical test result: lines / FAILED occurrences |
0 / 0 |
(4) targets matching the full triple ^test result: ok\. 0 passed; 0 failed; 0 ignored |
1 — Doc-tests eqoxide_nav |
| (5) passed + failed + ignored + filtered | 243 + 0 + 16 + 0 = 259 = header sum |
Delta zero, as expected for a text-only round. Baseline is the round-1 branch build of the same
two targets, extracted from that run's own logs by pairing target order with result order:
| target | round 1 | round 2 |
|---|---|---|
unittests crates/eqoxide-nav/src/lib.rs |
243 passed; 0 failed; 16 ignored |
243 passed; 0 failed; 16 ignored |
Doc-tests eqoxide_nav |
0 passed; 0 failed; 0 ignored |
0 passed; 0 failed; 0 ignored |
No doctest created or destroyed by the rustdoc edits, which was the specific risk in editing ///
blocks rather than // ones.
Not verified this round
- The mutation table and reach control were not re-run. Justification is that the diff is
//////text plus the PR body; the executable delta is zero and the figures above show it. - Everything in the PR body's existing "NOT verified, and not claimed" section still stands
unchanged.
Independent review — round 2 (head
|
| # | figure | value |
|---|---|---|
| (1) | Finished `test` profile compile sentinel |
present (24m 53s) — 0 ^error, 0 ^warning in either stream |
| (2) | ^running [0-9]+ tests?$ headers vs ^test result: lines |
2 vs 2 — equal, no lost binary |
| (3) | non-canonical test result: lines / FAILED |
0 / 0 |
| (4) | targets with nothing to run, predicate ^test result: ok\. 0 passed; 0 failed; 0 ignored |
1 — bare 0 passed; also 1, no divergence at this scope. By name: Doc-tests eqoxide_nav |
| (5) | passed + failed + ignored + filtered vs header sum | 243 + 0 + 16 + 0 = 259 = header sum (running 259 tests + running 0 tests) |
I re-derived these from my own logs rather than quoting the author's; they agree exactly with the
author's 243/0/16/0 = 259. All five …_807 tests are present and ok, including
open_corpus_zone_leaves_a_ready_zone_open_for_the_caller_to_close_807. The sentinel is a compile
marker, not a run-completion marker — completion is figure (2).
I did not re-run the workspace suite, the mutation table, or the reach control. I relied on the
verified text-only premise in section 0 to justify that.
What I did NOT verify this round
- The workspace-wide figures (I ran
-p eqoxide-navonly). Round 1's workspace run on the pre-merge
head stands; the merge brought indfa11ba, whose contents I did not independently test. - Whether
fine_tier_corpus_route_success_and_costkeeps aVec<String> unmeasured. Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839 says
two of the five do; I found the accumulator infix_700_planner_ab_corpusbut not in
fine_tier_corpus_route_success_and_cost— I read its body and saw onlylet zones: Vec<String>
and two unrelated asserts. That may be an inaccuracy in Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839, not in this PR, and it is not
this PR's to fix. Flagging it so it is not inherited as fact. - The mutation table and reach control at this head — not re-run, by the premise above.
- Anything about walker_sim: #824's safety justification is false as written, and the skipped-bucket exemption's rationale applies equally to a gated bucket #830 / walker_sim: #824's [ABORTED] honesty report is pinned by nothing — deleting it leaves the suite green #831 beyond confirming they are open and do not allege an unaccounted drop.
Disposition
- F1 — discharged. * F2 — discharged as blocking; two non-blocking clause fixes above.
- F3 — discharged (one non-blocking word). * F4 — discharged.
- Reach-control characterisation — accurate; not a finding.
- F5 / F6 — out of scope by ruling, tracked on Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839. Not reopened.
No blocking findings remain. APPROVE.
…ulate nothing", and an unclaimable "correct" All three are the reviewer's own replacement wording, used verbatim. 1. "the only lever is that a loop chooses to open its zones through open_corpus_zone" was falsified three lines later by this same doc: hand-wiring begin_zone/add/skip is a second lever and faithful_walker_drift_corpus uses it today. 2. "still accumulate nothing and drop zones on a bare continue" is false of fix_700_planner_ab_corpus, which keeps a Vec<String> unmeasured at collision.rs:7862 and refuses on it at :7918-7922. 3. "That copy is wired and correct" -> "wired and accounted". #830 and #831 are open agent-honesty issues against faithful_walker_drift_corpus. Neither alleges an unaccounted drop path, so "accounted" is exactly what is claimable there; unqualified "correct" is not. No numbers from #839 are restated in tracked text, so its correction from 7 to 10 sites falsifies nothing here. Refs #839. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HQVEpaaKeXsZcW9VT2roeV
Round 3 — three edits, plus one consequence of the #839 correctionCommit 1. "accumulate nothing" → your wording, verbatim. You are right that
2. the false "only" → your wording, verbatim. This one is worth naming for what it is: the
3. "wired and correct" → "wired and accounted". Agreed, and the distinction is the point of this No intra-doc link target changed (edit 2 keeps the existing The #839 correction, reconciledRe-read #839 including the correction. Nothing in tracked text depended on the old numbers — The PR body did depend on them, in two places, and I corrected it (this is the fourth edit,
I also added a short note in the PR body recording why the number moved — the tally had been taken One phrasing note, since I used your wording verbatim as instructed: "bare |
…cted the clause after it "drop zones on a bare `continue`" was meant as UNACCOUNTED (no skip/add before it), which is true of all ten remaining sites. But the conventional reading of "bare" is "a `continue` with nothing else", and under that reading the clause contradicts the next one: "some printing nothing at all" would be redundant and would imply the rest are not bare. `without opening them here` already carries the whole meaning, so the word adds nothing and costs an ambiguity. Without it the sentence is true under both readings. Refs #839. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HQVEpaaKeXsZcW9VT2roeV
Round 4 — one wordCommit
I had meant "bare" as unaccounted, which is true of all ten remaining sites; the conventional Doc-only, one line, no link target touched — no test run, no re-review. PR body unchanged. |
Closes #807.
Round 2 — review response (text only; no executable change)
Round 1 review found the code right and both blocking findings were false sentences in tracked
files. Fixed in
water_grid.rs, doc/comment only:return… is preceded by askip/add" and "there is no paththrough it that leaves a zone unaccounted". The
Oktail return is a return, is not preceded byeither, and leaves the zone open — falsified by this PR's own green test. Narrowed to
Errreturns; the "no path" sentence is deleted, not qualified. Same correction applied to the headline
below.
WaterRollup's type doc still described the five corpora this PR converts as droppingzones into a plain
Vec<String>with no ratio and "NOT covered by anything in this file". Allfour clauses were false after this PR, and it mislocated
water_grid_budget_measurementintests/walker_sim.rswhen it lives incrates/eqoxide-nav/src/collision.rs. Rewritten to saywhat is actually still uncovered and to point at Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839 for the list rather than restate a tally
that will drift.
faithful_walker_drift_corpuskeeps its own inline copy (deliberately — it drives two rollups and cannot use this single-rollup
signature). "One owner" now says five corpora, not six.
open_corpus_zone; everynew test calls
open_corpus_zone_with. A mutation offormat!("{zone}.glb"),"maps/water", orthe
cellpass-through would survive the whole suite. Disclosure, not a new assert.Closes #807kept (the ten enumerated sites are done); Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839 filed and cited for theten that remain (see the note below — Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839's own count was corrected from 7 to 10 after filing).
Not done, per the orchestrator's scope ruling: F5 (assert ordering in the four corpora — a code
change, now #839's secondary item); converting any of the five remaining
collision.rsloops(#839's whole job); the
ZoneDroppeddisplay-string inconsistency the reviewer flagged andexplicitly did not ask to be fixed; any tier-1 type-level move (the reviewer looked and concluded
correctly that
Drop-based settling would turn a loudunaccountedinto a silentadd).The mutation table and reach control below were not re-run: nothing executable changed. Test
figures for round 2 are at the bottom.
What was wrong
Five corpora each carried their own byte-identical copy of the zone-open prologue:
Both
continues leave the loop body without telling anybody. The corpus then prints aTOTALover whatever zones happened to survive, and passes. A run over 1 of 2 zones is indistinguishable
from a run over 2 of 2 — the number looks measured and is not. #802 wired the two sites in
faithful_walker_drift_corpus; the rest were left as "same shape, do it later".What this changes
One owner for the prologue, in the crate:
eqoxide_nav::water_grid::open_corpus_zone(+
open_corpus_zone_with, the closure-injected variant so the drop paths are testable with nobaked assets). It takes
&mut WaterRollupand returnsResult<(Collision, ZoneWater), ZoneDropped>.Every
Errreturn in it is preceded by askipor anadd, so a caller that ignores theErrvalue entirely still cannot lose the zone. The
Oktail return deliberately leaves the zone open —closing it is the caller's obligation, a forgotten close lands in
unaccounted, andopen_corpus_zone_leaves_a_ready_zone_open_for_the_caller_to_close_807pins exactly that. The five corpora now call it and close each opened zonewith a real per-zone water number, then assert
cover.is_complete().Ten inline drop sites became three, and those three are inside a library function that CI compiles
and five new non-
#[ignore]d tests exercise. CI could not previously reach any of them — thecorpora are all
#[ignore]d and asset-gated, and CI passes no--ignored(#777/#799).The rollup total is a real measurement, not a placeholder: the blast-radius corpora fold the count
of start/goal pairs their water filter actually excluded; the budget corpus folds
wet_column_count().Correction to the issue text
#807 says "eleven remain unaccounted". Re-derived on the base: it is ten. #802 round 3 landed a
third
skipinfaithful_walker_drift_corpusafter the reviewer took the 13/2 count. 13 = 3(faithful) + 8 (four blast-radius x 2) + 2 (budget corpus). This PR closes the 10.
Test figures
Base
0497f6band this branch,cargo test --workspace --locked --no-fail-fast, both from logs Iread (not from the exit code):
0497f6bFinished `test` profilecompile sentinel23m 20s); 0^error, 0^warning6m 36s); 0^error, 0^warningrunning N tests?headers vstest result:linestest result:lines0 passed; 0 failed; 0 ignoredDelta +5, reconciled by name (set-diff of every
^test … ... <outcome>line in both logs;zero removed):
Mutation table — library (3 drop sites, 3 REDs)
Baseline
20 passed; 0 failed. Every mutation reverted from acp -pcopy and re-verified withmd5sum -c(allOK) before the next.cover.skip(zone, "no glb")…records_a_missing_glb_as_skipped_807,a_corpus_using_the_prologue_…cover.skip(zone, "no grid")…records_an_empty_collision_grid_as_skipped_807,a_corpus_using_the_prologue_…cover.add(zone, &zw.tally())…records_an_unloadable_wtr_as_unmeasured_807,a_corpus_using_the_prologue_…add→skip(zone, "no wtr").wtrmust land inunmeasured, notskippedcover.begin_zone(zone)WaterRolluppanicswith no zone open(fail-closed)if false { cover.skip(…); }"no glb"→"glb absent"M6 is the reason this is a type-and-execution fix rather than a source-text scanner: none of the
seven evasions in #799 apply, because nothing here reads source.
Reach control — 5 real call sites, on real baked assets
Debug builds only. Small
ZONES=/PAIRS=subsets against a one-zone scratch asset dir.(A) a zone that drops must now go RED.
ZONES=<real>,ghostzone(ghostzone has no.glb):goal_append_blast_radiuscovers 1/2 … skipped: ["ghostzone"]corner_buffer_blast_radiusdescent_guard_blast_radiusparallel_wall_clearance_blast_radiuswater_grid_budget_measurementmeasured 1/2 … skipped: ["ghostzone"]5 sites → 5 REDs.
(B) forgetting to close a zone must go RED too (this is the obligation the function cannot
discharge for the caller). Deleted each corpus's loop-tail
cover.add(zone, …)one at a time:goal_append_blast_radiuscorner_buffer_blast_radiusdescent_guard_blast_radiusparallel_wall_clearance_blast_radiusunaccounted: ["<zone>"]water_grid_budget_measurementunaccounted: ["<zone>"]5 sites → 5 REDs, each diagnosed as
unaccounted (left the loop body without reaching add or skip — a corpus WIRING bug, not an asset problem), not as a missing asset.(C) both-directions control — the defect, reproduced. Spliced the base's version of
parallel_wall_clearance_blast_radiusback over mine (call site only) and re-ran the exact (A)input. Output:
GREEN, with a
TOTALpublished over half the named corpus. That is #807.#807's two open questions, measured
"Are all remaining paths the same shape?" — Yes. Read all five: identical two conditions in
identical position, both before the water check, all ten correctly classified as
skip(the watercheck never ran, so
unmeasuredwould be a lie). The third path (.wtrdid not load) is adifferent bucket (
unmeasured) and was already accounted by #762; it is folded into the samefunction to keep the three tiers in one place.
"Does any of them currently drop a zone in practice?" — Measured on a machine with a complete
asset set: no, all default-corpus zones load.
water_grid_budget_measurementover its 3default zones reported
wet columns: 18468 (over 3/3 zones); the walker_sim corpora over their 10default zones reported
(over 10/10 zones). Nono glb, nocols == 0, no unreadable.wtrin13 distinct zones. The paths are latent here — which is exactly why they were invisible. They
fire on a partial asset dir, which is the normal state of a dev box (#802's own review measured
that).
NOT verified, and not claimed
CI still never runs these corpora. They are
#[ignore]d and asset-gated and CI passes no--ignored(The merge gate cannot see asset-gated pins: #[ignore]'d tests carry load-bearing evidence CI never runs #777/Source-scan call-site pins prove a call is written, not reached (#721 A2b, #773 E1b/E2, #791 round 1) #799). What CI now runs is the five library tests over the three drop paths.Nothing in this PR makes the corpora themselves CI-visible.
A future corpus can still open a zone by hand. The prologue is a function you have to call,
not a type you cannot avoid; someone can still write
let Ok(za) = … else { continue }inline. Idid not find a way to make that unrepresentable without changing
Collision::build's signaturefor every caller in the crate, which is far outside this issue. The function's rustdoc states
this explicitly in a three-tier "Guaranteed / Guaranteed by
WaterRollup/ NOT guaranteed" listrather than implying more coverage than exists.
ZoneDropped's free-text content is not pinned (M7 SURVIVED, deliberately).Not fixed, and outside 11 of 13 test-corpus drop paths still publish an unmeasured zone as a measured zero (#802 covers 2) #807's enumeration: Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839. Five more zone loops in
collision.rs(10 sites) still drop zones on a
continuewith no accounting — the node-cap corpus,fine_tier_corpus_route_success_and_cost, the#700planner A/B, and the two#375seal/disagreement corpora. Four of those ten print no line at all, which is strictly worse
than any of the ten this PR fixes. 11 of 13 test-corpus drop paths still publish an unmeasured zone as a measured zero (#802 covers 2) #807 does not enumerate them, so
Closes #807stands for theten it does name; Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839 now carries the remaining list and the per-line table. This PR does not
touch them.
Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839 was filed saying 7 sites; its author corrected it to 10 across 5 loops after this PR's
reviewer found the tally had been taken with a grep (
cols == 0 { continue) that could only matchthe bare form and so missed two printing
cols == 0drops. The "four silent" figure is unchanged.The rustdoc deliberately defers the tally to Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839 rather than restating it, which is why that
correction did not falsify anything in the tree.
Assert ordering, also Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839. In the four
*_blast_radiuscorporaassert!(g_pairs > 0, …)still precedes
assert!(cover.is_complete(), …), so a run where every zone drops is RED withthe pre-11 of 13 test-corpus drop paths still publish an unmeasured zone as a measured zero (#802 covers 2) #807 message rather than the new accounting diagnosis. Real, cheap, and deliberately not
done here — it is a code change in four test functions and is tracked as Seven more zone loops in collision.rs drop zones out of a printed corpus total without accounting (four silently) #839's secondary item.
walker_sim: #824's safety justification is false as written, and the skipped-bucket exemption's rationale applies equally to a gated bucket #830 / walker_sim: #824's [ABORTED] honesty report is pinned by nothing — deleting it leaves the suite green #831 are untouched. They are against
faithful_walker_drift_corpus/open_zone_checkedintests/walker_sim.rs; this PR does not modify those lines or thatfunction.
No live client run. This is corpus-harness accounting; nothing here is reachable from a
running client.
Reach control (A)/(B) used one real zone plus a synthetic missing one, not the full default
corpus, and
PAIRSwas reduced. That measures the accounting, not the nav numbers; the navnumbers the corpora print are unchanged by this PR only insofar as the sampling code is untouched
— I did not re-run a full before/after corpus to prove the printed nav totals are bit-identical.
The
cols == 0sub-case has never been observed on real assets here; it is covered only by afabricated empty
ZoneAssetsin the library test.