From 42f82520523c8a8d3f16f5547f3a1075e395c80f Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 6 Sep 2026 15:03:51 +0000 Subject: [PATCH 1/4] Close the last 31 clippy findings so the newly-ungated -D warnings gate passes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `main` went red the moment #146 turned the suite on: `Clippy (deny warnings)` failed. Measured with the workspace command rather than guessed — 31 findings across 10 files, and the first one was mine. ## The blocker was a miss in my own #145 sweep error: redundant reference in `assert!` argument --> crates/pampa/tests/integration/test_treesitter_coverage.rs:469:9 #145's commit message says it fixed this exact lint at "19 sites", including line 73 of this very file. It missed line 469 in the same file. The gate that #146 turned on caught it — which is the gate doing its job on its first run. ## The other 30, and why almost none of them are deleted 27 are dead_code in cockpit-server; 3 are real quality findings. Deleting unwired surface is a product decision, so the code is preserved and annotated instead. Two agents' findings make that the right call rather than the timid one: - The five `resolve_garmin_*` functions and `mime_from_path` DO have call sites — inside `#[cfg(feature = "embed-cockpit")]`. Feature-gating artifact, not abandoned code. - Every unread field in openai.rs is OpenAI wire schema: the structs derive Deserialize and the fields must exist for client payloads to parse. A field that exists to satisfy an external protocol is not dead weight. ## expect vs allow is measured, not stylistic The first pass used `#[expect(dead_code)]` throughout, for its self-cleaning property: it warns if the item later becomes used. The central gate then reported 18 x "this lint expectation is unfulfilled". The cause is structural. Those 18 items ARE used — under `#[cfg(test)]` or a feature gate. `--all-targets` compiles such a file more than once, so the item is dead in one compilation and alive in another, and no single `expect` can hold in both. Those 18 became `#[allow]`, each reason recording why. The 13 that are dead in every target keep `expect`, so it still self-cleans where it can. `default_distance_table`, `jsonrpc` and `mime_from_path` sit in the same files as items that flipped, and correctly did not flip. ## The three real fixes - osm_features: `assert!(GEOMETRY_CITY_BUDGET > GEOMETRY_OVERVIEW_BUDGET)` in a test compared two `const`s, so it could never fail at run time — the vacuous assertion this repo's own falsifiability rule names, sitting feet from a comment reading "Anti-vacuity test". Promoted to `const _: () = assert!(...)` at module scope: reordering the budgets now fails the BUILD, not one test. Strictly stronger, and the test's two `assert_eq!` calls are untouched. - osm_features: `decode_tile_bin`'s nested-tuple return type factored into `Point` / `DecodedShape` / `DecodedTile`. Signature only; body byte-identical. - osint_gotham: `BasinPlan` was private while `pub fn osint_node_rows` exposes it. Widened to `pub(crate)` to match the function's real reachability — not to `pub`. ## Verification cargo clippy --workspace --all-targets --profile ci -- -D warnings 0 warnings, 0 errors cargo fmt --all -- --check clean Both are CI's own commands. Every edit was written by hand via scoped agents on disjoint files; `clippy --fix` was not used, per the same reasoning as #145 — its unused_* machinery deletes code the author may still want, which is exactly the decision being deferred here. The full test suite was NOT run locally: linking the workspace's test binaries exhausts this sandbox's disk (it hit 1.3 GB free and was stopped). What that does and does not cover: `clippy --all-targets` compiles every test target, so everything type-checks; the one change touching a test body is the const-assert promotion, and a false `const _` assert is a compile error, so its invariant is proven by the build. The remaining edits are annotations, a visibility widening, type aliases, and a `{:?}` argument where `Debug for &T` forwards to `T`. CI runs the tests. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01AGVLyRZNEKKBSfBDJfbY3V --- crates/cockpit-server/src/codebook.rs | 28 +++ crates/cockpit-server/src/graph_engine.rs | 8 + crates/cockpit-server/src/main.rs | 28 +++ crates/cockpit-server/src/openai.rs | 164 ++++++++++++++++++ crates/cockpit-server/src/osint_gotham.rs | 2 +- .../src/osm_artifact_manager.rs | 8 + crates/cockpit-server/src/osm_features.rs | 24 ++- crates/cockpit-server/src/osm_tiles.rs | 8 + crates/cockpit-server/src/scene_player.rs | 8 + .../integration/test_treesitter_coverage.rs | 2 +- 10 files changed, 271 insertions(+), 9 deletions(-) diff --git a/crates/cockpit-server/src/codebook.rs b/crates/cockpit-server/src/codebook.rs index 5bab8f929..d7f5cacfa 100644 --- a/crates/cockpit-server/src/codebook.rs +++ b/crates/cockpit-server/src/codebook.rs @@ -17,6 +17,10 @@ use std::hash::{Hash, Hasher}; /// /// Both this crate and `lance-graph`'s thinking engine assume the same /// codebook width when exchanging `u16` indices. Keep in sync. +#[allow( + dead_code, + reason = "codebook token-index surface (Cypher identifier extraction -> stable u16 index); built out but no call site wires it yet; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] pub const CODEBOOK_SIZE: usize = 4096; /// Synthetic placeholder distance table for `ThinkingEngine::new`. @@ -31,11 +35,19 @@ pub const CODEBOOK_SIZE: usize = 4096; /// /// Cost: 4096 × 4096 × 1 byte = 16 MB. Allocated once per cockpit-server /// boot (per SSE connection in the current handler). +#[expect( + dead_code, + reason = "codebook token-index surface; PHASE 2A stub distance table for ThinkingEngine::new, built out but no call site wires it yet" +)] pub fn default_distance_table() -> Vec { vec![0u8; CODEBOOK_SIZE * CODEBOOK_SIZE] } /// Cypher keywords excluded from identifier extraction. +#[allow( + dead_code, + reason = "codebook token-index surface; keyword exclusion list for extract_cypher_identifiers, built out but no call site wires it yet; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] const CYPHER_KEYWORDS: &[&str] = &[ "MATCH", "RETURN", "WHERE", "CREATE", "MERGE", "SET", "DELETE", "AS", "AND", "OR", "NOT", "NULL", "TRUE", "FALSE", "OPTIONAL", "WITH", "UNWIND", "ORDER", "BY", "ASC", "DESC", "LIMIT", @@ -43,6 +55,10 @@ const CYPHER_KEYWORDS: &[&str] = &[ ]; /// Maximum identifiers returned by [`extract_cypher_identifiers`] per call. +#[allow( + dead_code, + reason = "codebook token-index surface; per-call cap for extract_cypher_identifiers, built out but no call site wires it yet; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] const MAX_IDENTIFIERS_PER_CALL: usize = 32; /// Map a token to a stable `u16` codebook index in `[0, CODEBOOK_SIZE)`. @@ -51,6 +67,10 @@ const MAX_IDENTIFIERS_PER_CALL: usize = 32; /// deterministic within a single process run; callers must not rely on /// stability across Rust toolchain versions, since `DefaultHasher` is not /// guaranteed stable across releases. +#[allow( + dead_code, + reason = "codebook token-index surface; stable token->u16 index mapping, built out but no call site wires it yet; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] pub fn token_to_index(token: &str) -> u16 { let mut hasher = DefaultHasher::new(); token.hash(&mut hasher); @@ -63,6 +83,10 @@ pub fn token_to_index(token: &str) -> u16 { /// Preserves first-occurrence order: if two distinct tokens hash to the same /// index, both appear once in input order, but duplicate tokens collapse to /// a single index in the output. +#[allow( + dead_code, + reason = "codebook token-index surface; batch token->indices dedup helper, built out but no call site wires it yet; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] pub fn tokens_to_indices(tokens: &[&str]) -> Vec { let mut seen: HashSet<&str> = HashSet::with_capacity(tokens.len()); let mut out: Vec = Vec::with_capacity(tokens.len()); @@ -80,6 +104,10 @@ pub fn tokens_to_indices(tokens: &[&str]) -> Vec { /// start with an ASCII letter and have length >= 2, drops Cypher keywords /// (case-insensitive), deduplicates while preserving first-occurrence /// order, and caps the output at [`MAX_IDENTIFIERS_PER_CALL`] entries. +#[allow( + dead_code, + reason = "codebook token-index surface; Cypher identifier extraction for the scene player/shader stream, built out but no call site wires it yet; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] pub fn extract_cypher_identifiers(content: &str) -> Vec { let mut seen: HashSet = HashSet::new(); let mut out: Vec = Vec::new(); diff --git a/crates/cockpit-server/src/graph_engine.rs b/crates/cockpit-server/src/graph_engine.rs index 811fc6e8b..0c7b9c953 100644 --- a/crates/cockpit-server/src/graph_engine.rs +++ b/crates/cockpit-server/src/graph_engine.rs @@ -107,10 +107,18 @@ pub struct GraphEdge { impl GraphEdge { /// Convenience: legacy `truth_f` accessor for in-process consumers. + #[expect( + dead_code, + reason = "legacy accessor for in-process consumers; the wire Serialize impl reads self.truth.frequency/.confidence directly, so nothing calls this yet" + )] pub fn truth_f(&self) -> f32 { self.truth.frequency } /// Convenience: legacy `truth_c` accessor for in-process consumers. + #[expect( + dead_code, + reason = "legacy accessor for in-process consumers; the wire Serialize impl reads self.truth.frequency/.confidence directly, so nothing calls this yet" + )] pub fn truth_c(&self) -> f32 { self.truth.confidence } diff --git a/crates/cockpit-server/src/main.rs b/crates/cockpit-server/src/main.rs index 927816376..05706dd4d 100644 --- a/crates/cockpit-server/src/main.rs +++ b/crates/cockpit-server/src/main.rs @@ -149,6 +149,10 @@ struct SseEvent { #[derive(Debug, Deserialize)] struct McpRequest { + #[expect( + dead_code, + reason = "part of the JSON-RPC 2.0 envelope; required for serde to parse incoming requests per the wire schema, but the value itself is never consulted" + )] jsonrpc: String, id: serde_json::Value, method: String, @@ -523,6 +527,10 @@ async fn shutdown_signal() { /// filename for a known slug, `None` for unknown/malformed ones. Slugs are /// lowercase `[a-z0-9-]` — anything else is rejected before the map lookup /// (no path traversal into the dist). +#[allow( + dead_code, + reason = "Garmin terrain-scene resolution surface; only call sites are under cfg(feature = \"embed-cockpit\") and cfg(test), so a default build sees no reference; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] fn resolve_garmin_map(manifest_json: &str, map_key: &str, location: &str) -> Option { if location.is_empty() || !location @@ -535,6 +543,10 @@ fn resolve_garmin_map(manifest_json: &str, map_key: &str, location: &str) -> Opt v.get(map_key)?.get(location)?.as_str().map(String::from) } +#[allow( + dead_code, + reason = "Garmin terrain-scene resolution surface; only call sites are under cfg(feature = \"embed-cockpit\") and cfg(test), so a default build sees no reference; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] fn resolve_garmin_scene(manifest_json: &str, location: &str) -> Option { resolve_garmin_map(manifest_json, "garmin_scenes", location) } @@ -542,6 +554,10 @@ fn resolve_garmin_scene(manifest_json: &str, location: &str) -> Option { /// Resolve a `/garmin-drape/:location` slug through the manifest's `garmin_drapes` /// map — the DRP1 vector overlay (roads / trails / rivers) that drapes onto the /// `garmin_scenes` terrain of the same slug. Absent = the scene has no drape. +#[allow( + dead_code, + reason = "Garmin terrain-scene resolution surface; only call sites are under cfg(feature = \"embed-cockpit\") and cfg(test), so a default build sees no reference; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] fn resolve_garmin_drape(manifest_json: &str, location: &str) -> Option { resolve_garmin_map(manifest_json, "garmin_drapes", location) } @@ -549,11 +565,19 @@ fn resolve_garmin_drape(manifest_json: &str, location: &str) -> Option { /// Resolve a `/garmin-contours/:location` slug through the manifest's /// `garmin_contours` map — the DRP1 topo-line overlay that drapes onto the /// `garmin_scenes` terrain of the same slug. Absent = the scene has no contours. +#[allow( + dead_code, + reason = "Garmin terrain-scene resolution surface; only call sites are under cfg(feature = \"embed-cockpit\") and cfg(test), so a default build sees no reference; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] fn resolve_garmin_contours(manifest_json: &str, location: &str) -> Option { resolve_garmin_map(manifest_json, "garmin_contours", location) } /// List the available scene slugs (for the self-documenting 404). +#[allow( + dead_code, + reason = "Garmin terrain-scene resolution surface; only call sites are under cfg(feature = \"embed-cockpit\") and cfg(test), so a default build sees no reference; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] fn garmin_scene_slugs(manifest_json: &str) -> Vec { serde_json::from_str::(manifest_json) .ok() @@ -746,6 +770,10 @@ async fn static_handler(uri: axum::http::Uri) -> Response { (StatusCode::NOT_FOUND, "Not found").into_response() } +#[expect( + dead_code, + reason = "MIME lookup utility; sole call site is inside the cfg(feature = \"embed-cockpit\") static_handler block" +)] fn mime_from_path(path: &str) -> &'static str { if path.ends_with(".html") { "text/html; charset=utf-8" diff --git a/crates/cockpit-server/src/openai.rs b/crates/cockpit-server/src/openai.rs index f4fed68e5..929dce2bf 100644 --- a/crates/cockpit-server/src/openai.rs +++ b/crates/cockpit-server/src/openai.rs @@ -59,19 +59,75 @@ struct ModelListResponse { #[derive(Deserialize)] pub struct CompletionReq { pub model: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub prompt: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub max_tokens: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub temperature: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub top_p: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub n: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub stream: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub logprobs: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub echo: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub stop: Option>, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub presence_penalty: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub frequency_penalty: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub seed: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub suffix: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub user: Option, } @@ -99,18 +155,70 @@ struct CompletionChoice { pub struct ChatCompletionReq { pub model: Option, pub messages: Vec, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub max_tokens: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub temperature: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub top_p: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub n: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub stream: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub stop: Option>, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub presence_penalty: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub frequency_penalty: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub seed: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub user: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub tools: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub tool_choice: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub response_format: Option, } @@ -118,8 +226,20 @@ pub struct ChatCompletionReq { pub struct ChatMessageReq { pub role: String, pub content: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub name: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub tool_calls: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub tool_call_id: Option, } @@ -152,9 +272,21 @@ struct ChatMessageObj { #[derive(Deserialize)] pub struct EmbeddingReq { pub model: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub input: serde_json::Value, // string, array of strings, or token IDs + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub encoding_format: Option, pub dimensions: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub user: Option, } @@ -177,13 +309,37 @@ struct EmbeddingObj { #[derive(Deserialize)] pub struct ImageGenReq { + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub model: Option, pub prompt: String, pub n: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub size: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub response_format: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub quality: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub style: Option, + #[expect( + dead_code, + reason = "OpenAI-compatible request DTO field; part of the wire schema and must deserialize, but this server does not read it" + )] pub user: Option, } @@ -210,11 +366,19 @@ struct UsageObj { } #[derive(Serialize)] +#[expect( + dead_code, + reason = "typed OpenAI error DTO; every error path in this file builds its body ad hoc via serde_json::json! instead, so nothing constructs this type" +)] struct ErrorResp { error: ErrorObj, } #[derive(Serialize)] +#[expect( + dead_code, + reason = "typed OpenAI error DTO; every error path in this file builds its body ad hoc via serde_json::json! instead, so nothing constructs this type" +)] struct ErrorObj { message: String, r#type: String, diff --git a/crates/cockpit-server/src/osint_gotham.rs b/crates/cockpit-server/src/osint_gotham.rs index 629a8d816..5019e94fb 100644 --- a/crates/cockpit-server/src/osint_gotham.rs +++ b/crates/cockpit-server/src/osint_gotham.rs @@ -562,7 +562,7 @@ fn is_version_token(tok: &str) -> bool { /// The deterministic basin plan: every node → an 8-bit basin byte /// `(theme << 4) | anchor`, plus the inverse map basin → anchor entity id (for /// hub labels). -struct BasinPlan { +pub(crate) struct BasinPlan { /// node id → basin byte. node_basin: HashMap, /// node id → theme stem (for hub labels / props). diff --git a/crates/cockpit-server/src/osm_artifact_manager.rs b/crates/cockpit-server/src/osm_artifact_manager.rs index 6f532a809..fa71f79c2 100644 --- a/crates/cockpit-server/src/osm_artifact_manager.rs +++ b/crates/cockpit-server/src/osm_artifact_manager.rs @@ -90,6 +90,10 @@ impl OsmArtifactManager { /// Atomically replace the lifecycle snapshot. A caller holding an /// `Arc` from a prior `current()` keeps observing the old /// value — this call never mutates through an existing `Arc`. + #[allow( + dead_code, + reason = "hydration write path for Phase C, which has not landed yet; exercised only by this module's tests today; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" + )] pub fn publish_lifecycle(&self, next: Lifecycle) { self.lifecycle.store(Arc::new(next)); } @@ -98,6 +102,10 @@ impl OsmArtifactManager { /// guarantee as `publish_lifecycle`, and `None` is a valid publication /// (Phase C uses it to retract content whose lifecycle moved to /// `absent`/`CandidateFailed` with no prior active version). + #[allow( + dead_code, + reason = "hydration write path for Phase C, which has not landed yet; exercised only by this module's tests today; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" + )] pub fn publish_artifact(&self, next: Option>) { self.artifact.store(next); } diff --git a/crates/cockpit-server/src/osm_features.rs b/crates/cockpit-server/src/osm_features.rs index 4bfdb8a3a..b76624126 100644 --- a/crates/cockpit-server/src/osm_features.rs +++ b/crates/cockpit-server/src/osm_features.rs @@ -155,6 +155,10 @@ fn row_budget(z: u32) -> usize { /// Take every `stride`-th row so a decimated tile stays spatially /// representative. Split out from `query_tile` so the *selection* rule can be /// falsified at any budget, without a fixture the size of a real overview tile. +#[allow( + dead_code, + reason = "only called from #[cfg(test)] callers; unused in a non-test build; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] fn stride_for(total: usize, budget: usize) -> usize { total.div_ceil(budget).max(1) } @@ -1247,6 +1251,12 @@ fn simplify_cells_raw( /// untouched — dots are points, geometry is the map. const GEOMETRY_OVERVIEW_BUDGET: usize = 12_000; const GEOMETRY_CITY_BUDGET: usize = CITY_ROW_CEILING; +// Compile-time invariant: reordering these two budgets must fail the BUILD, +// not one test. (A runtime assert! on two consts can never fire.) +const _: () = assert!( + GEOMETRY_CITY_BUDGET > GEOMETRY_OVERVIEW_BUDGET, + "a city tile must be allowed more shapes than an overview tile" +); /// Below this on-screen extent a shape has no resolvable outline, and drawing /// one is worse than drawing nothing. /// @@ -2241,9 +2251,13 @@ mod tests { /// Decode `OSM1` bytes back into shapes — an independent reader for the /// round-trip test below, written from the format DOC, not from the /// encoder's code, so a shared misunderstanding can't self-certify. - fn decode_tile_bin( - buf: &[u8], - ) -> Option<(u32, u32, u32, u32, Vec<(u32, u8, bool, Vec<(f32, f32)>)>)> { + /// A decoded vertex: (x, y) in z32-cell-scaled units — never lon/lat. + type Point = (f32, f32); + /// One decoded shape record: (index, class wire code, closed, vertices). + type DecodedShape = (u32, u8, bool, Vec); + /// A fully decoded OSM1 tile: (total, sampled, count, malformed, shapes). + type DecodedTile = (u32, u32, u32, u32, Vec); + fn decode_tile_bin(buf: &[u8]) -> Option { let rd_u32 = |at: usize| u32::from_le_bytes(buf[at..at + 4].try_into().unwrap()); if buf.len() < 20 || rd_u32(0) != 0x314D_534F { return None; @@ -2371,10 +2385,6 @@ mod tests { GEOMETRY_OVERVIEW_BUDGET ); assert_eq!(geometry_row_budget(CITY_ZOOM_FLOOR), GEOMETRY_CITY_BUDGET); - assert!( - GEOMETRY_CITY_BUDGET > GEOMETRY_OVERVIEW_BUDGET, - "a city tile must be allowed more shapes than an overview tile" - ); } /// Anti-vacuity test (per the plan's Phase-1 requirement): two real, diff --git a/crates/cockpit-server/src/osm_tiles.rs b/crates/cockpit-server/src/osm_tiles.rs index 17f4bdfcd..820518141 100644 --- a/crates/cockpit-server/src/osm_tiles.rs +++ b/crates/cockpit-server/src/osm_tiles.rs @@ -89,12 +89,20 @@ pub fn lonlat_to_tile(lon: f64, lat: f64, z: u32) -> (u32, u32) { /// Delegates to the substrate's `morton64`, which interleaves the full 32-bit /// lanes the 4-tier key needs. #[must_use] +#[allow( + dead_code, + reason = "Morton interleave/deinterleave pair; only callers are under cfg(test), so a non-test build sees no reference; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] pub fn morton_interleave(x: u32, y: u32) -> u64 { osm_soa_bake::tms::morton64(x, y) } /// Inverse of [`morton_interleave`]. #[must_use] +#[allow( + dead_code, + reason = "Morton interleave/deinterleave pair; only callers are under cfg(test), so a non-test build sees no reference; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" +)] pub fn morton_deinterleave(code: u64) -> (u32, u32) { osm_soa_bake::tms::demorton64(code) } diff --git a/crates/cockpit-server/src/scene_player.rs b/crates/cockpit-server/src/scene_player.rs index d47e2466d..7075a7517 100644 --- a/crates/cockpit-server/src/scene_player.rs +++ b/crates/cockpit-server/src/scene_player.rs @@ -38,8 +38,16 @@ use lance_graph::parser::parse_cypher_query; #[derive(Clone, Debug)] pub struct CypherStream { /// Provenance label ("AriGraph" for graph-derived perturbations). + #[allow( + dead_code, + reason = "provenance field carried on the DTO for downstream consumers; no reader in this crate yet; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" + )] pub source: &'static str, pub codebook_indices: Vec, + #[allow( + dead_code, + reason = "provenance field carried on the DTO for downstream consumers; no reader in this crate yet; allow not expect — used under cfg(test)/feature, so no expectation holds in every --all-targets compilation" + )] pub timestamp: u64, } diff --git a/crates/pampa/tests/integration/test_treesitter_coverage.rs b/crates/pampa/tests/integration/test_treesitter_coverage.rs index 20f7eee50..c68db0d7e 100644 --- a/crates/pampa/tests/integration/test_treesitter_coverage.rs +++ b/crates/pampa/tests/integration/test_treesitter_coverage.rs @@ -466,7 +466,7 @@ fn test_example_list() { assert!( matches!(&pandoc.blocks[0], Block::OrderedList(_)), "Expected OrderedList, got {:?}", - &pandoc.blocks[0] + pandoc.blocks[0] ); if let Block::OrderedList(list) = &pandoc.blocks[0] { From 8d06983598322cf15bad0ea62dd8966909d55ffe Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 6 Sep 2026 15:36:30 +0000 Subject: [PATCH 2/4] =?UTF-8?q?Restore=20the=20header=20import=20that=20#1?= =?UTF-8?q?45=20removed=20=E2=80=94=20it=20broke=20the=20embed-cockpit=20b?= =?UTF-8?q?uild?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CodeRabbit flagged `mime_from_path`'s `#[expect(dead_code)]` as unfulfilled under `--features embed-cockpit`. It was right, and chasing it found something bigger sitting underneath: with that feature enabled, cockpit-server did not compile at all. ## The regression, and it is mine `25f4b940` (the #145 lint sweep) removed `use axum::http::{StatusCode, header}` down to `StatusCode` alone. `header::CONTENT_TYPE` is used at five sites — 614, 670, 712, 745, 757 — and every one of them is inside a `#[cfg(feature = "embed-cockpit")]` block. In a default build those blocks are compiled out, so the import genuinely looks unused and clippy said so. I removed it. With the feature on: error[E0433]: cannot find module or crate `header` x5 CI never enables `embed-cockpit`, so nothing caught it. The Dockerfile does (`cargo build -p cockpit-server --features embed-cockpit`), so this has been broken on the production build path since #145 merged. Fix: restore the import gated to match its usage, rather than merging it back into the braced form that caused the problem — a single `use` cannot be half-gated: use axum::http::StatusCode; // both configurations #[cfg(feature = "embed-cockpit")] use axum::http::header; // only where it is used ## The lint finding that led here `mime_from_path` keeps its annotation but as `#[allow]`, not `#[expect]`: with the feature enabled `static_handler` calls it, so no expectation holds in every configuration. Same structural rule this PR already applied to 18 other items — I simply failed to apply it here, because my gate only ever ran the default feature set. That was the real hole: the classification was sound, the measurement behind it was too narrow. main.rs now carries 1 `expect` (the `jsonrpc` wire field, dead in every configuration) and 6 `allow`. ## Verification — both configurations this time default, workspace, -D warnings 0 findings --features embed-cockpit, cockpit-server 0 errors cargo fmt --all -- --check clean The feature build needs `cockpit/dist` to exist for `include_dir!`; a stub was created locally to verify and removed afterwards (it is gitignored either way). ## Deliberately NOT fixed here The feature build still reports 6 style warnings — 3 `needless_return`, 3 `collapsible_if`, at main.rs 629/668/678/710/720/755 — in code that until this commit could not be compiled, so nothing had ever linted it. They block neither CI (which does not enable the feature) nor `cargo build`. Left alone because the `needless_return` fix turns on cfg-dependent tail-expression semantics: those `return`s are only redundant because the paired `cfg(not(...))` block disappears, and getting that wrong would re-break the build path this commit repairs. Worth its own change, not a drive-by on a lint PR. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01AGVLyRZNEKKBSfBDJfbY3V --- crates/cockpit-server/src/main.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/cockpit-server/src/main.rs b/crates/cockpit-server/src/main.rs index 05706dd4d..249a00029 100644 --- a/crates/cockpit-server/src/main.rs +++ b/crates/cockpit-server/src/main.rs @@ -18,6 +18,8 @@ use std::time::Duration; use axum::extract::State; use axum::http::StatusCode; +#[cfg(feature = "embed-cockpit")] +use axum::http::header; use axum::response::sse::{Event, Sse}; use axum::response::{Html, IntoResponse, Response}; use axum::routing::{get, post}; @@ -770,9 +772,9 @@ async fn static_handler(uri: axum::http::Uri) -> Response { (StatusCode::NOT_FOUND, "Not found").into_response() } -#[expect( +#[allow( dead_code, - reason = "MIME lookup utility; sole call site is inside the cfg(feature = \"embed-cockpit\") static_handler block" + reason = "MIME lookup utility; sole call site is inside the cfg(feature = \"embed-cockpit\") static_handler block; allow not expect — with that feature enabled the call exists, so no expectation holds in every configuration" )] fn mime_from_path(path: &str) -> &'static str { if path.ends_with(".html") { From 6863f22cc5c18f744f73f5ed2e39a9b4c365d4fb Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 6 Sep 2026 17:58:57 +0000 Subject: [PATCH 3/4] cockpit-server: gate posix_fadvise to Linux/Android, not cfg(unix) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit macOS CI failed to compile cockpit-server: error[E0425]: cannot find function `posix_fadvise` in crate `libc` error[E0425]: cannot find value `POSIX_FADV_DONTNEED` in crate `libc` error: could not compile `cockpit-server` (bin "q2-cockpit") `advise_dontneed` in osm_slab_hydrate.rs was gated `#[cfg(unix)]` with a `#[cfg(not(unix))]` no-op beside it. `posix_fadvise` is a Linux/Android extension, not POSIX-universal — Apple's libc does not declare it — so `cfg(unix)` reads as "has fadvise" and is not. The function's own doc comment stated the wrong premise ("No portable equivalent exists ... on non-Unix targets"), which is what made the gate look correct. This is the SECOND instance of this exact defect today. The first was in lance-graph (AdaWorldAPI/lance-graph#1208, merged); q2 carries its own independent copy in this file. Fixing lance-graph's did not fix this one, and the macOS job moved from failing in `lance-graph-hydrate` to failing here — same error, different crate. Fix (identical to #1208): gate both arms on the OS that actually has the call, and record the rule in the doc comment so the gate is not re-widened by intuition. Both arms still bump the `#[cfg(test)]` FADVISE_ATTEMPTED counter, so the reachability test is unaffected on either platform. Verification — red-then-green on the REAL CI target (macos-latest is Apple Silicon), compiling the gate pair against the real `libc` crate: new gate, aarch64-apple-darwin compiles OK new gate, x86_64-unknown-linux-gnu compiles OK OLD cfg(unix) control, aarch64-darwin reproduces both E0425s exactly Plus a two-sided `#![no_std]` cfg probe on the pinned 1.98.1 toolchain: x86_64/aarch64-apple-darwin exclude the Linux arm; x86_64-unknown-linux-gnu selects it. `cargo fmt -p cockpit-server -- --check` clean. NOT verified here: a full `cargo check -p cockpit-server` in either configuration. This sandbox cannot build that dependency tree (lance + datafusion + deno exhaust the disk), and cross-compiling it for darwin additionally needs a C toolchain for `ring`. The change is three cfg attributes and a doc comment, and the gate pair itself is compile-proven above against real libc on both targets. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01AGVLyRZNEKKBSfBDJfbY3V --- crates/cockpit-server/src/osm_slab_hydrate.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/crates/cockpit-server/src/osm_slab_hydrate.rs b/crates/cockpit-server/src/osm_slab_hydrate.rs index d0d51f710..544b17a3c 100644 --- a/crates/cockpit-server/src/osm_slab_hydrate.rs +++ b/crates/cockpit-server/src/osm_slab_hydrate.rs @@ -729,9 +729,14 @@ static FADVISE_ATTEMPTED: std::sync::atomic::AtomicUsize = std::sync::atomic::At /// Advise the kernel it can drop `f`'s pages from the page cache now that /// we're done reading it. /// -/// No portable equivalent exists for this on non-Unix targets (see -/// `.claude/rules/cross-platform.md`), so it is a documented no-op there — -/// this is memory hygiene, not correctness, so a silent no-op is fine. +/// `posix_fadvise` is a **Linux/Android extension, not POSIX-universal** — +/// Apple's libc does not declare it, so `cfg(unix)` reads as "has fadvise" +/// and is not. Gating this on `cfg(unix)` broke the macOS build outright +/// with "E0425: cannot find function posix_fadvise in crate libc"; see +/// `.claude/rules/cross-platform.md`. Every other target takes the +/// documented no-op below — this is memory hygiene, not correctness, so a +/// silent no-op is fine. **Widen this gate only to targets whose libc +/// actually declares the call.** /// /// Deliberately untestable via RSS or cgroup memory accounting, same as /// `osm_lance.rs`'s `release_after_write`: `/proc/self/statm` cannot see @@ -743,7 +748,7 @@ static FADVISE_ATTEMPTED: std::sync::atomic::AtomicUsize = std::sync::atomic::At /// silently skipped or removed, which a counter catches and an RSS /// measurement cannot (see the falsifiability rule: a test that cannot /// fail when the guard is deleted is not a test of the guard). -#[cfg(unix)] +#[cfg(any(target_os = "linux", target_os = "android"))] fn advise_dontneed(f: &std::fs::File) { #[cfg(test)] FADVISE_ATTEMPTED.fetch_add(1, std::sync::atomic::Ordering::Relaxed); @@ -762,7 +767,7 @@ fn advise_dontneed(f: &std::fs::File) { } } -#[cfg(not(unix))] +#[cfg(not(any(target_os = "linux", target_os = "android")))] fn advise_dontneed(_f: &std::fs::File) { #[cfg(test)] FADVISE_ATTEMPTED.fetch_add(1, std::sync::atomic::Ordering::Relaxed); From a2118cfe0db038c7a27083a211db8abc3c44f39b Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 6 Sep 2026 18:07:30 +0000 Subject: [PATCH 4/4] cockpit-server: annotate the two cgroup parsers dead on non-Linux targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit macOS CI, on the previous commit's head: error: function `parse_cgroup_current` is never used error: function `parse_cgroup_max` is never used error: could not compile `cockpit-server` (bin "q2-cockpit") NOT caused by that commit — revealed by it. Both functions are ungated, and their only non-test callers sit inside `read_cgroup_memory`'s `#[cfg(target_os = "linux")]` arm, so on macOS they have been dead since they were written. The crate previously died at the `posix_fadvise` E0425 before dead-code analysis ever ran, so nothing reported it. That is the same peel-back this whole PR arc has been: each fix lets the build reach the next thing that was never checked. The fix is the rule this PR already established 18 times: `#[allow]`, not `#[expect]`, because the item is alive in one compilation and dead in another — here across TARGETS rather than across features, but the same reason applies. `expect` would fire "unfulfilled" on Linux, where both functions genuinely are used. Each carries a reason naming the asymmetry. Nothing is deleted: these parse cgroup v2 memory accounting and are exercised by six tests in this module on every platform. Swept for the same defect rather than fixing only what CI named. This crate has exactly three platform gates: osm_artifact_manager.rs read_cgroup_memory cfg(target_os = "linux") osm_lance.rs advise_dontneed cfg(unix) osm_slab_hydrate.rs advise_dontneed cfg(any(linux, android)) The latter two define BOTH arms, so nothing becomes dead through them. `read_cgroup_memory` itself and both `CgroupMemory` fields are read ungated from main.rs, so they stay alive on macOS; the two parsers were the only casualties. `osm_lance.rs`'s `cfg(unix)` is CORRECT and deliberately left alone: it calls `memmap2::Mmap::advise`, i.e. `madvise`, which is genuinely POSIX-wide and present on macOS. The naming is backwards from intuition — `posix_fadvise` is the Linux-only one despite its name; `madvise` is the portable one. Narrowing that gate would have been a regression. Outside cockpit-server every platform gate in the workspace is `cfg(unix)`, which is TRUE on macOS, so none of them can produce macOS-only dead code. Verification: `cargo fmt -p cockpit-server -- --check` clean. A full `cargo check -p cockpit-server` is not possible in this sandbox (lance + datafusion + deno exhaust the disk; darwin cross additionally needs a C toolchain for `ring`), and `allow(dead_code)` cannot itself fail a build — it can only suppress. The risk this carries is that it suppresses too little, which CI reports, not too much. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01AGVLyRZNEKKBSfBDJfbY3V --- crates/cockpit-server/src/osm_artifact_manager.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/cockpit-server/src/osm_artifact_manager.rs b/crates/cockpit-server/src/osm_artifact_manager.rs index fa71f79c2..503df1b27 100644 --- a/crates/cockpit-server/src/osm_artifact_manager.rs +++ b/crates/cockpit-server/src/osm_artifact_manager.rs @@ -135,6 +135,10 @@ pub struct CgroupMemory { } /// Parse `memory.current`'s content: a bare decimal integer. +#[allow( + dead_code, + reason = "read only by `read_cgroup_memory`'s cfg(target_os = \"linux\") arm and by this module's tests; dead on every non-Linux target, so allow not expect — no single expectation holds across targets" +)] #[must_use] pub fn parse_cgroup_current(raw: &str) -> Option { raw.trim().parse().ok() @@ -144,6 +148,10 @@ pub fn parse_cgroup_current(raw: &str) -> Option { /// string `max` meaning "no limit" (represented here as `None`, same as an /// unreadable file — see [`CgroupMemory::max_bytes`] for how to tell them /// apart). +#[allow( + dead_code, + reason = "read only by `read_cgroup_memory`'s cfg(target_os = \"linux\") arm and by this module's tests; dead on every non-Linux target, so allow not expect — no single expectation holds across targets" +)] #[must_use] pub fn parse_cgroup_max(raw: &str) -> Option { let trimmed = raw.trim();