fix(#742): clear the residual workspace lint warnings — per instance, with a reason each; and write the _SUCCEEDS/_FAILS convention down - #786
Conversation
… with a reason each Measured on a48760b with a COLD `cargo check --workspace --all-targets --locked` (warnings are deduplicated across incremental builds, so a warm build under-reports): 7 warnings, all of them in `lib test` targets. After: 1, and that one is deferred behind an open PR. Every instance was triaged as the issue asks — genuinely dead (delete), a symptom of wrong wiring (fix the wiring), or deliberate scaffolding (narrow per-item allow). No blanket `allow` was added, at any scope. Two of the seven turned out to be the "wired up wrong" case: - crates/eqoxide-core/src/game_state.rs:2042 `dead_code`, `Ev::BuffUnknown`'s field. BOTH the state under test and the reference model hardcoded slot 1 and discarded the variant's payload, so the property test's alphabet could not express "an unresolvable buff in a slot other than the one the rest of the sequence acts on" — a `BuffUnknown(2)` symbol would have been silently identical in effect to `BuffUnknown(1)` while reading as extra coverage. The slot now comes from the event on both sides, and `BuffUnknown(2)` joins the alphabet (13 -> 14 symbols, 2197 -> 2744 orderings). MUTATION-CHECKED: hardcoding the state-under-test call back to slot 1 fails on [Fly(false), BuffUnknown(2), BuffOff(1)]. `LevitateState` itself needed no change — the defect was in the test's vocabulary. - crates/eqoxide-nav/src/traversability.rs:681,726 `dead_code`, `lintel_corridor` / `low_wall_corridor`. #567 moved the tests that consume these to `tests/walker_sim.rs` (they step the real `movement::CharacterController`, which this crate cannot depend on) and left unused copies behind. The copies are deleted; the geometry in walker_sim.rs is byte-identical, so no coverage moves. The surviving test's doc pointed at them ("the lintel fixture above", "`..._low_wall_...` below") — false since #567 — and now names the walker_sim.rs tests that actually pin the behaviour. - crates/eqoxide-nav/src/steering.rs:823 `dead_code`, `Run::x_min`/`x_max`. `Run`'s doc says the whole-run and settled extents "measure different things, and both are recorded rather than one standing in for the other", but nothing read the whole-run pair. Now printed beside the settled band, deliberately NOT asserted: the transient's width is a diagnostic and the test's only claim is about the settled cycle. - src/model.rs:323 `unused_imports`, `MockProbe`; src/model.rs:454 `dead_code`, `MockModel::plan_radius`. Genuine leftovers. Every consumer already binds a `MockProbe` by inference from `MockModel::probe()`, and no test ever overrode the planning radius; the `plan_radius` FIELD stays live with its 1.0 default. DEFERRED (not touched — `crates/eqoxide-nav/src/walker.rs` is owned by open PR #774): crates/eqoxide-nav/src/walker.rs:2032 `dead_code`, `fn pad_scene`. A one-line alias over `pad_scene_leaves(false)` that no caller uses; a delete, once #774 merges. Convention decision (#742's second question): the `_SUCCEEDS`/`_FAILS` naming is now WRITTEN DOWN in docs/dev-workflow.md rather than re-litigated per PR. The code half of that choice is already in the tree — all four instances carry a narrow per-function `#[allow(non_snake_case)]` (#738 added movement.rs's pair, #755 added asset_sync.rs's while #742 was being written), so no code change was needed and none was made. Out of scope, untouched: .github/workflows/test.yml toolchain pinning. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HQVEpaaKeXsZcW9VT2roeV
Independent review — PR #786 (#742 lint hygiene)Verdict: APPROVED. I re-derived every load-bearing claim rather than reading the PR body as fact. Everything checked What I measured (executed, not read)
Verified by inspection (not full independent re-execution)
Took on the author's word (not re-verified)
No findings that block mergeNothing here rises to a request-changes finding. The one real gap found (the citation/span guard's Squash subject: Squash body: use the branch's single commit body as-is ( |
Closes #742 — partially: 6 of the 7 measured warnings are fixed here; the 7th is in a file an open PR owns and is deferred behind it (details below). Plus the convention decision the issue asks for.
Before/after warning table
Both sides rebuilt from scratch —
cargo cleanfirst, thencargo check --workspace --all-targets --locked. Warnings are deduplicated by cargo across incremental builds, so a warm build under-reports; neither figure below is warm, and neither reuses the issue's numbers.Before (main
a48760b): 7. After (this branch): 1.file:linecrates/eqoxide-core/src/game_state.rs:2042:90dead_code— field0ofEv::BuffUnknownsrc/model.rs:323:34unused_imports—MockProbeMockProbeby inference fromMockModel::probe(); nothing ever wrote the type's name.src/model.rs:454:23dead_code—MockModel::plan_radiusrunhands it tofind_path_ex) with its documented1.0default; only the never-used override is gone.crates/eqoxide-nav/src/steering.rs:823:9dead_code—Run::x_min,Run::x_maxcrates/eqoxide-nav/src/traversability.rs:681:8dead_code—fn lintel_corridorcrates/eqoxide-nav/src/traversability.rs:726:8dead_code—fn low_wall_corridorcrates/eqoxide-nav/src/walker.rs:2032:8dead_code—fn pad_sceneNo
allowwas added at any scope — not per-item, not per-module, not per-crate. Each instance resolved to a delete or a real fix, so none was needed.Why 7 and not the issue's 8 — reconciled by measurement, not arithmetic
The issue's 8 was measured at merge-base
d977706. Two commits have moved it since, and both are checkable:644ba2c) added the narrow per-function#[allow(non_snake_case)]to bothsrc/asset_sync.rstest names while lint hygiene: the residual workspace warnings after #730, and the _SUCCEEDS/_FAILS naming convention decision #742 was being written.git log -S"allow(non_snake_case)" -- src/asset_sync.rsreturns exactly that commit. So thenon_snake_casepair is already gone frommain; nothing in this PR touches it.24b84cb) introducedRun::x_min/x_maxinsteering.rs.git show d977706:crates/eqoxide-nav/src/steering.rs | grep -c x_min→0. That is whyeqoxide-navreads 4 here against the issue's 3.8 − 2 + 1 = 7. ✓
The three that were not just noise
Ev::BuffUnknown's discarded payload (#1) — the test's vocabulary lied. The arm read:Both the state under test and the reference model hardcoded slot 1 and dropped the variant's payload, while every sibling arm (
BuffOn(s),BuffOff(s),BuffKnownOther(s)) passes its slot through. The alphabet therefore could not express "an unresolvable buff in a slot other than the one the rest of the sequence acts on": aBuffUnknown(2)symbol would be byte-identical in effect toBuffUnknown(1)— silently — while reading in the source as extra coverage. The slot now comes from the event on both sides, andBuffUnknown(2)joins the alphabet (13 → 14 symbols, 2197 → 2744 orderings).I want to be exact about what this is:
LevitateStateitself needed no change and none was made. This was a defect in the test's vocabulary, not in the product. It is not a #343-shaped honesty bug (see below).lintel_corridor/low_wall_corridor(#5, #6) — orphaned by #567, and the surviving doc still pointed at them. #567 moved the tests that consume these fixtures intotests/walker_sim.rs(they step the realmovement::CharacterController, whicheqoxide-navcannot depend on) but left the fixtures behind intraversability.rs, unused. The geometry inwalker_sim.rsis byte-identical, so deleting the orphans moves no coverage —planner_never_routes_under_a_lintel_the_walker_collides_withandplanner_never_routes_over_a_low_wall_the_walker_cant_stepare alive and untouched.The part worth flagging: the surviving test's doc comment in
traversability.rssaid "the lintel fixture above catches the behaviour" and "..._low_wall_...below pins the behaviour". Both cross-references have been false since #567 — they pointed at a dead copy and at a test that is no longer in the file. Both now name thetests/walker_sim.rstests that actually pin the behaviour. That is a docs-honesty fix riding along with the lint fix, and it is the reason I did not simply delete the two functions and stop.Run::x_min/x_max(#4) — computed, then dropped.Run's doc says the whole-run and settled extents "measure different things, and both are recorded rather than one standing in for the other" — the #727 round-5 correction that exists specifically to stop the transient and the settled band being conflated. But nothing read the whole-run pair, so the transient it protects was invisible in the output. They are now printed beside the settled band, and deliberately not asserted: the transient's width is a diagnostic, and this test's only claim is about the settled cycle. Observed output (-p eqoxide-nav --lib -- ..._a_few_frames_wide --nocapture):Collision list — what I deliberately did not touch
Derived from
gh pr list --state open+git diff --name-only origin/main...origin/<branch>for every open PR, then cross-checked against every live worktree'sHEADand working tree.crates/eqoxide-nav/src/walker.rs:2032:8—dead_code,fn pad_scenefix-766-nav-local)That is the only collision.
game_state.rs,model.rs,steering.rs,traversability.rsanddev-workflow.mdare in no open PR's diff and in no live worktree's uncommitted changes.For whoever picks up the deferred one after #774 merges:
pad_sceneis a one-line aliasfn pad_scene() -> Collision { pad_scene_leaves(false) }with no callers anywhere in the tree — every consumer callspad_scene_leavesdirectly. It looks like a plain delete. I did not delete it and did not compile-verify that deletion, so treat that as a reading, not a measurement.Note on the name trap: there are two
asset_sync.rs. This PR touches neither — not rootsrc/asset_sync.rs(its convention work was already done by #755) and notcrates/eqoxide-ipc/src/asset_sync.rs(owned elsewhere).Convention decision: write it down, do not add more code
The issue offers two defensible options and asks for one. I picked write the convention down, in
docs/dev-workflow.mdunder Testing.The reason is that the code half is already in the tree and I would have been writing a no-op. All four instances already carry a narrow per-function
#[allow(non_snake_case)]: #730/PR #738 addedsrc/movement.rs's pair, and #731/PR #755 addedsrc/asset_sync.rs's pair (644ba2c) while #742 was being written. The issue's "add the same narrowallowto the two newasset_sync.rsfunctions" was therefore already satisfied by another PR before I started — measured, not assumed:grep -n "allow(non_snake_case)"returnssrc/movement.rs:1694,1758andsrc/asset_sync.rs:1399,1415. So "add the allow" had nothing left to do, and "write it down" was the option with content.The written rule endorses exactly what #742 and #738's reviewer recommended, and records why rather than just what: per-function only, never module or crate scope, because a wide
allowalso silences every accidentalnon_snake_casein that scope — a typo'dfn myTest, a stray capitalised local — which is the same "the warning you meant to keep is lost with the ones you meant to suppress" failure that #723/#730 exist to close. It also records the requirement that each instance keep a comment naming the load-bearing word, since all four already do.I did not also add code, per the issue's "pick one".
Honesty-bug triage — none of the #343 shape found
The issue asks whether any
dead_codeis an observable an agent can read with no live writer. No, and this is measurable rather than argued: cargo attributed all 7 warnings tolib testtargets, andcargo check --workspace --all-targetsreported zero warnings against any non-test target. Every one of the 7 sits inside a#[cfg(test)]module — verified per hunk:game_state.rs#[cfg(test)]at 2018,steering.rs#[cfg(test)] mod cursor_resync_testsat 690,traversability.rs#[cfg(test)] mod testsat 644,model.rs#[cfg(test)] mod mockat 330 and the#[cfg(test)]re-export. None is reachable over the HTTP API, so none can report a confident falsehood to a driving agent.No separate issue is filed. The two "wired up wrong" instances (#1, and the stale cross-references behind #5/#6) are both test-internal, both trivial, and both in files no open PR owns, so per the brief they are fixed here rather than handed off.
Verification
Tiers 1–3 of the hierarchy; tier 4 (live run) deliberately skipped, and it is not a gap: the entire diff is
#[cfg(test)]code plus one Markdown file, so there is no production behaviour to observe in a client. (Verified by locating each hunk's enclosing#[cfg(test)], as listed above. I did not verify binary identity of the release artifact — that is the one claim here I am making from inspection rather than measurement.)Tier 3, mutation-checked (
-p eqoxide-core --lib -- levitate_state_is_exactly_the_union_of_its_two_channels):BuffUnknown(2)to the alphabet, arm unfixedbuff_slot_changed(1, ...), reference left onspanicked at game_state.rs:2103: levitate answer() mismatch after [Fly(false), BuffUnknown(2), BuffOff(1)] (fly=false slots={} unresolved={2})md5sumidentical (4ed54fd1998efba92534665f1181b11f)So the fixed arm plus the new symbol detect a slot-identity regression that neither could detect before — the coverage is real, not nominal.
Full workspace suite —
cargo test --workspace --locked --no-fail-fast, both sides, cold. Five figures:maina48760b (baseline)Finishedline`test` profile [unoptimized + debuginfo] target(s) in 49m 15s`test` profile [unoptimized + debuginfo] target(s) in 36m 58stest result:lines / expectedNs?Header-vs-summary parity holds on both sides (50 = 50), so no binary died mid-run. Test counts are identical across the two sides, which is the expected shape: this PR adds no test and removes none — the new
BuffUnknown(2)symbol lives inside an existing test, and the deleted fixtures were functions, not tests. The wall-clock difference is builder contention (load average 42–93 on a 6-core box across the two runs), not a signal.The warning tables above were independently reproduced by these test runs, which is a second command agreeing with the first:
cargo test --workspaceemitted the same 7-->locations onmainand exactly 1 (walker.rs:2032) on this branch.What I could not establish
pad_sceneis truly a safe delete. Read-only reading says yes (one-line alias, no callers). Not deleted, not compiled, not tested — deferred behind PR fix(#766): retirenav_localwith the goal — a zone change no longer publishes the previous zone's fine-tier verdict #774.#[cfg(test)]by inspection; I did not build both sides in release and compare, so "no production behaviour changed" rests on that inspection.steering.rsis correct. It is a diagnostic and nothing asserts it; I observed one value and did not validate it against an independent measurement.eqoxide-navwarning the fix(#730): deny the f32-fallback regression in eqoxide-ui, allow the two deliberate non_snake_case test names #738 reviewer's "3" excluded. I resolved this by datingx_min's introduction to24b84cb, but I did not rebuild atd977706to confirm the reviewer's set item-by-item..github/workflows/test.yml,dtolnay/rust-toolchain@stable, no MSRV) — explicitly out of scope, untouched, and I surfaced nothing new about it.🤖 Generated with Claude Code
https://claude.ai/code/session_01HQVEpaaKeXsZcW9VT2roeV