-
A — Const work-width / derived-const-generic (HIGH). A const-generic parameter encoding a width derived from another width: fn f<W, const N: usize> where N == W::U128_LIMBS; <const N, const M, const LW>; a call passing { <_ as BigInt>::U128_LIMBS } or { 2*N } as a const-generic argument. FORBIDDEN — wider work widths come from ComputeInt buffers, never a const param. Grep: const LW, U128_LIMBS }, , { , * N>, + 1 }. NOT a defect — the level's OWN defining const(s) (the "BigRule", docs/ARCHITECTURE.md → "Const generics — the BigRule"): a dispatch taking exactly its level's consts — int-unary <N>, int-binary <Nthis, Nother>, dec-unary <N, S>, dec-binary <Nthis, Sthis, Nother, Sother> — and no others is the NORM, never a violation (the caller holds them in its types: inferred, not derived; taking them unused at the entry is fine). Flag ONLY a const BEYOND that set (derived / work-width). Metadata test: dispatch MAY freely inspect the values passed to it (limb lengths, magnitude, sign — the ByValue/ByShape matcher's job, never a violation); it must NOT need external metadata — any const/type/context beyond its level consts + the operands themselves. Needing outside info to choose/run → defect. Sanctioned exception: int::policy::div_rem is intentionally slice-based / non-generic (division has no const-width axis — independent runtime operand lengths it reads off its own slices); do NOT flag it for lacking the binary consts. Also flag the inverse caller-side smell: a call site forced to manufacture a const / create a type / specialise to call a policy — the policy signature is wrong, not the caller.
-
B — Build-max on a concrete-N path (HIGH — the recurring one). Any concrete-N site (an algorithm kernel, a decimal policy/kernel — anywhere Int<N>: ComputeInt is reachable) that sizes a wider-than-N work buffer with anything other than the normal per-N ComputeInt methods. The REQUIRED form is one of the clean limb-multiple constructors — two families, each in u64 and u128 element form (docs/ARCHITECTURE.md → "Work-width scratch", the two-family vocabulary):
- plain
X·N: single_u64/single_u128 (N / ⌈N/2⌉), double_u64/double_u128 (2N / N), quad_u64/quad_u128 (4N / 2N);
- buffered (+
⌈N/2⌉ headroom): single_buffered_u64 (N + 2), double_buffered_u64 (2N + ⌈N/2⌉ ≈ 2.5N), quad_buffered_u64 (4N + ⌈N/2⌉ ≈ 4.5N) and their _u128 siblings.
A buffer is named by a multiple of N, never by the function that wants it (no per-function type like LimbBufDivU128 — [[feedback_computeint_buffers_general_not_function_named]]). Adding a higher multiple (e.g. 8N) when an algorithm needs it is expected, not a defect. These methods are the stable-Rust stand-in for generic_const_exprs: each concrete-N impl states the exact computed size for that width, so no nightly feature and no signature-level const is needed.
FLAG as a defect any of these on a concrete-N path: a frozen literal ([0u64; 288], [0u128; 144], [0u8; 256*64], …); a MAX_WORK_N/max_n_limbs(k)-derived size; OR the build-max blanket itself — the MAX_SINGLE_LIMBS / MAX_DOUBLE_LIMBS / MAX_QUADRUPLE_LIMBS / MAX_U128_LIMB consts and the max_single_limbs() / max_double_limbs() / max_quadruple_limbs() / max_u128_limb() constructors. A MAX_* on a concrete-N path is the build-max blanket leaking onto a tier that can size itself exactly (rule 6). Remediation: replace with the matching Int::<N>::*_limbs() method (e.g. a [0u64; 288] 2N product → Int::<N>::double_limbs()); see docs/ARCHITECTURE.md → "Work-width scratch — exact ComputeInt, never build-max". Grep: MAX_SINGLE_LIMBS|MAX_DOUBLE_LIMBS|MAX_QUADRUPLE_LIMBS|MAX_U128_LIMB|max_(single|double|quadruple)_limbs|max_u128_limb|MAX_WORK_N|max_n_limbs|\[0u(64|128); (288|144|[0-9]), then for each check whether the enclosing fn has a concrete N / Int<N>: ComputeInt in scope (→ defect) or is one of the legitimate blanket exceptions below.
The build-max blanket is correct on really just one structurally-N-less path: the blanket Int<N> / / % operators and BigInt methods (can't carry ComputeInt — ComputeInt: BigInt would cycle), and even those are cold + escapable (route to the scratchless const shift-subtract div_rem), so the blanket's target is zero. const fn paths that genuinely can't reach ComputeInt should still use a MAX_WORK_N-derived size, not a frozen literal (LOW). These are NOT exceptions — a concrete N/SCALE is in scope, so flag any MAX_* use in them: Display/int_fmt (N is the monomorphised width at impl<const N> Display for Int<N>; Display is not a BigInt supertrait, so where Int<N>: ComputeInt + single_limbs() is sound); newton_reciprocal (buffer lengths are (work width, divide exponent); the exponent derives from the const SCALE the decimal dispatch carries — size per (width, SCALE) threaded from dispatch, not the frozen MAX_*_U64 literals); widen_mul/seed_bridge/every kernel.
-
C — Per-tier pollution (MED/HIGH). Per-decimal-tier types, per-width macro-generated arithmetic, per-tier algorithm copies or per-tier macro arms duplicating algorithm logic (rules 1–2). One generic Int<N>, one generic algorithm file per function.
-
D — Layering (MED/LOW). Scratch OR output allocation inside a policy/ file (a policy only classifies + chooses, it allocates nothing); an algorithm fn calling a method on its OWN type instead of a kernel; a decimal algo calling a decimal method on its own value; an algorithm not living in a named algos/<fn>/ file. (docs/ARCHITECTURE.md → Layering direction.)
-
E — Superseded duplicates & orphan cruft (MED/LOW). NOT "delete unwired algorithms". Per docs/ARCHITECTURE.md → "Keeping the alternatives", algorithms are NEVER deleted — an unwired kernel, a candidate awaiting a bench/policy seam, a reference baseline, or a today-loser is a KEPT alternative; "unwired / reached only by its own tests" is its EXPECTED state, not a defect. So do NOT recommend deleting algorithm kernels (sum_sq_comba, cbrt_native_fast_b, *_native_direct, the schoolbook variants, the parked div_knuth_u128_limb pilot — all KEEP). What this class DOES flag: (1) a superseded duplicate — the obsolete shape of an algorithm a migration replaced in place (e.g. a const-work-width fn f<W, const N> left behind after it became fn f<W: ComputeInt>); (2) genuinely-orphan non-algorithm cruft (an unused const/helper/import that implements no algorithm). For each candidate, apply the architecture's test — distinct algorithm/shape that could win under other conditions (KEEP) vs leftover old signature of something now canonical (remove) — and default to KEEP when unsure.
-
F — Policy hygiene (LOW). A select threshold that looks unvalidated/inherited or makes an arm unreachable (e.g. a threshold set so an algorithm never engages); a ByValue/ByShape arm that can never fire; an "override" arm whose dispatch calls the identical kernel as the arm it overrides (inert). Cross-check [[feedback_validate_selects_with_compare_all]].
-
G — Matcher bypass / hardcoded engine (HIGH/MED — the audit's KNOWN blind spot, miss it at your peril). A type method, algorithm fn, or decimal kernel that calls a specific engine/kernel DIRECTLY when a policy matcher exists for that operation (policy::<fn>::dispatch / its classify) — hardcoding ONE algorithm and bypassing the matcher's choice. The tell: the call names a concrete engine (div_knuth_into, mul_schoolbook, a *_newton) instead of routing through the operation's dispatch. This is the inverse of Class D's "calls a method on its own type" — here the caller dives below the matcher to a leaf, so the matcher's whole job (choose the algorithm) is silently pre-empted. It is compliant ONLY if the matcher provably resolves to that one engine for every shape the caller can present — a FRAGILE, time-limited claim: the instant a new Algorithm arm is added that the matcher would pick for some of those shapes, the direct call never reaches it and the new engine is dead for that caller (a routing regression no test catches — golden is engine-blind, the bench only sees what is wired). So when a bypass is "justified" by "this is the matcher's identical choice", FLAG it anyway — quote the justification and note it MUST be re-verified whenever an engine joins that policy. Real instance the agents MISSED (the reason this class exists): src/algos/rem/rem_int_layer.rs and src/algos/div/div_widen_scale.rs call div_knuth_into directly (legitimately, for exact ComputeInt scratch) — sound while Knuth was the sole wide divide engine, a violation the moment a LimbSize u128 engine arm joined int::policy::div_rem. Remediation: route the caller through the matcher's verdict (matcher exposes classify/dispatch; caller acts on it), keeping any exact-scratch need met via algo-owned ComputeInt buffers, never by hardcoding the engine. Grep src/algos/** + type-method impls for direct calls to named engines/kernels (div_knuth, div_knuth_into, mul_schoolbook, mul_karatsuba, *_newton, bz_*, *_into); for each, check whether a policy::<that-op> exists with more than one reachable Algorithm arm for the caller's shapes (→ flag) — and treat any "identical choice" comment as a defect marker, not a clearance.
-
H — Hand-rolled seed bypassing the seed library (MED). A Newton/root estimate (sqrt/cbrt) computed INLINE in a kernel instead of sourced from the shared seed library src/algo_x_support/seed.rs (sqrt_seed / cbrt_seed / sqrt_seed_u128). The library is the ONE home for seeds — it carries the feature-based optimization (std hardware-f64 bootstrap ~53 bits → ~1–2 Newton iters; no_std pure-integer 2^⌈bits/2⌉/2^⌈bits/3⌉) AND the guaranteed-over-estimate correction (odd-shift SQRT_2 + round-up) that keeps the downward Newton loop off the catastrophic linear x-=1 floor-walk. An inline seed is a defect TWO ways: a pure-integer-only inline seed forfeits the std f64 fast-bootstrap on every build; an un-corrected inline f64 seed risks the floor-walk + breaks determinism. The tell: a kernel computing 1u128 << (bits/2), (x as f64).sqrt()/.cbrt(), 2^ceil(bits/N), or any local seed just before a Newton/loop averaging step, without calling algo_x_support::seed. Grep src/** (excluding algo_x_support/seed.rs itself) for as f64).sqrt|as f64).cbrt|div_ceil\(2\)|div_ceil\(3\)|<< .*bits near a Newton averaging step; for each, check it routes through the seed library (→ OK) or rolls its own (→ flag). Remediation: route through the library; if the seed itself needs work, fix it IN the library (all callers benefit), never inline. (See docs/ARCHITECTURE.md → "Seeds — the shared seed library".) KNOWN inline-seed sites to consolidate: src/algos/cbrt/cbrt_native_fast_d57.rs, src/algos/support/mg_divide.rs.
-
I — Single-cell fit / neighbour-coverage gap (MED — CORE RULE, owner-mandated 2026-05-27). A perf fix, select arm, or value/scale gate fitted to the single benched (width, scale) cell where a regression surfaced, instead of placed across the continuous correct-side region so its neighbours get the same treatment. Fitting to one scale/width means the neighbours (adjacent scales AND adjacent widths) don't get the boost — or worse, cliff at the boundary. bbc only SAMPLES the surface ({0, 30, S/2, S-1} per width, and only some widths per op), so a gate snapped to a sampled point leaves the unsampled band uncovered. The static tells: a point-range arm (SCALE == 19, 19..=19, (4, 75..=75)) or a single-N carve-out whose bound coincides with a known bbc cell; a threshold/gate introduced or moved to exactly a benched value with no continuous range either side; a comment that JUSTIFIES an arm by citing ONE bbc cell ("fixes exp_D76_s75", "the s19 regression") — treat that comment as a defect marker, not a clearance, exactly like Class G's "identical choice". FLAG it and note it must be re-placed at the bisected true crossover covering the whole region, with the straddling + immediate-neighbour cells (adjacent scales and widths) validated — never just the bbc grid points. Remediation: widen the arm to the continuous win-region (a range, not a point); state the gate as a condition correct at EVERY scale/width in its region. Exempt: a blanket-generic fix with NO gate (lifts every cell unconditionally) and a genuinely point-correct mathematical carve-out (e.g. an exact-power pin at a single value) — the risk is specific to GATED perf fixes. Cross-ref [[feedback_validate_selects_with_compare_all]] + the coordinator-perf-multiagent / policy-mapper holistic-rectangle rule. (Correctness is not at risk — both arms are bit-identical via the validity wall — so this is an INVISIBLE perf miss, which is why the auditor must catch it statically.)
-
J — Heap allocation on the compute path (HIGH — absolute invariant). ANY heap allocation reachable from a runtime value computation: Vec, Box, Rc, Arc, VecDeque, String, to_vec(), vec![…], collect::<Vec<_>>(), a Box::new, or any alloc::* / std::collections use on the path. The crate is pure stack (docs/ARCHITECTURE.md → "Two absolute invariants: no heap, no state"): every working buffer is an inline [u64; …]/[u128; …] (sized via ComputeInt), every wider-than-N width comes from a ComputeInt associated-type buffer or const-init static, never the heap. No "tolerated" heap — flag every site HIGH, including the known historical defects: _wide-support = ["alloc"] in Cargo.toml, decl_table_cache!'s Vec lookup tables, and newton_reciprocal's Vec buffers. Remediation: inline stack array / ComputeInt buffer / const-init static table. Grep: Vec<|vec!\[|\.to_vec\(|Box<|Box::new|Rc<|Arc<|VecDeque|collect::<|alloc::|extern crate alloc|"alloc". NOT a defect: Vec/String confined to #[cfg(test)], benches, build scripts, or doc examples (off the runtime path); a &[T] slice or inline [T; K] (no allocation).
-
K — Mutable / shared state — a cache anywhere (HIGH — absolute invariant). ANY state carried between calls or shared mutably: thread_local!, static mut, static holding interior mutability (RefCell/Cell/Mutex/RwLock/OnceCell/OnceLock/Lazy/atomics) used as a cache or accumulator, a lazy_static!/once_cell memo, or any per-call memoization/precompute-cache. The crate is stateless → Send/Sync/re-entrant for free (docs/ARCHITECTURE.md → "Two absolute invariants"); a function must be a pure function of its inputs and recompute each call. The flagship instance: NewtonReciprocal::cache (src/algos/support/newton_reciprocal.rs) — thread_local! + Vec precompute cache, BOTH defects (heap and state) — DELETE, do not relocate into a static. The line every audit must hold is WHEN the value is produced, not whether it is stored: a compile-time const/const fn/static table baked into the binary (immutable, computed at build time, never written at run time) is fine and encouraged — that is read-only data, not a cache. FORBIDDEN is a value computed at run time on first use and kept for later calls (memoization). The test: "is it computed at compile time (OK), or populated at run time / does its content depend on prior calls (defect)?" A write-once-at-compile-time static [T; K] is fine; a static/thread_local! written on first call is not. Remediation for a runtime cache: lift the precompute to compile time (a const/const fn table) where the value is fixed, else recompute on the stack each call — never relocate it into a mutable static. Grep: thread_local!|static mut|RefCell|Cell<|Mutex<|RwLock<|OnceCell|OnceLock|Lazy<|lazy_static|AtomicU|\.cache|memoi|precompute.*cache; for each, confirm it's immutable const data (OK) vs a mutable/memoizing cache (flag HIGH).
-
L — Constant-table lookup by runtime w instead of const SCALE (MED — const-fold miss, invisible). The per-scale constant table (src/consts/table.rs) exposes TWO lookups: by_scale (keyed on the const scale — a const fn evaluated in const context, folds to the single entry per monomorphisation: the NORM) and by_working_scale (keyed on the runtime working-scale u32 w — does NOT const-fold). by_working_scale is sanctioned ONLY on the rare Ziv-escalation path (w != SCALE + GUARD), where the scale is genuinely runtime. FLAG any by_working_scale (or equivalent runtime-w-keyed constant lookup) on a path where the const SCALE was in scope — it silently defeats const-fold (the constant is selected/recomputed at run time instead of baked), reintroducing the exact wide-transcendental cost the table exists to remove. Like Class I this is an INVISIBLE perf miss (correctness unaffected — same value either way), so it must be caught statically. The tell: a consts::*_by_working_scale(...) / runtime-w table call in a kernel/accessor that has a const SCALE generic, outside the documented w != SCALE+GUARD fallback branch. Remediation: route through by_scale keyed on the const scale; reserve by_working_scale for the escalation fallback only. Grep: by_working_scale|consts::.*\bw\b.
-
Encoding (LOW). UTF-8→Latin-1 mojibake (─, doubled blank lines) in source — re-save as UTF-8.
ARCHITECTURE AUDITOR (read-only) for decimal_scaled, CWD <repo>. Produce a categorized report of architecture violations + dead/stale code. HARD RULES: only Grep/Glob/Read; NO Edit/Write to any source/config; NO git; NO cargo. The ONE write allowed: research/<date>_architecture_audit.md. No background jobs, no subagents, finish this run.
FIRST read CLAUDE.md (ARCHITECTURE CONSTITUTION rules 1–6), docs/ARCHITECTURE.md (layering + policy shape + <const N>/<const N, const M> convention), and src/int/types/compute_int.rs (the ComputeInt buffers + MAX_* blankets — THE mechanism for wider-than-N widths).
THEN scan all of src/ (and Cargo.toml) for the defect classes A, B, C, D, E, F, G, H, I, J, K + encoding (see the architectural-review skill for each class's detector greps and rule). Classes J and K are ABSOLUTE invariants (docs/ARCHITECTURE.md → "Two absolute invariants: no heap, no state"), flag every instance HIGH: Class J — ANY heap allocation on the compute path (Vec, vec![], .to_vec(), Box, Rc, Arc, collect::<Vec>, alloc::, extern crate alloc, the "alloc" feature) — the crate is pure stack, every buffer inline [u64;…]/ComputeInt/const-static; the known sites are _wide-support = ["alloc"], decl_table_cache!, newton_reciprocal. Class K — ANY mutable/shared state used as a cache (thread_local!, static mut, RefCell/Cell/Mutex/OnceCell/atomics as a cache, any memoization/precompute cache) — the crate is stateless, every fn a pure fn of its inputs; flagship = NewtonReciprocal::cache (DELETE, do not relocate). For BOTH, an immutable static/const lookup table of fixed constants is NOT a defect — only mutable state / heap is; the test is "is it ever written, or does content depend on prior calls?" (J/K test: heap → flag; immutable read-only data → OK). Class I (CORE RULE): a perf fix / select arm / gate fitted to the SINGLE benched (width, scale) cell instead of the continuous correct-side region — a point-range arm (SCALE == 19, 19..=19, (4, 75..=75)), a single-N carve-out matching a bbc cell, or a comment justifying an arm by citing ONE bbc cell ("fixes exp_D76_s75"); fitting to one scale/width means neighbours (adjacent scales AND widths) miss the boost or cliff at the boundary. Treat the citing-comment as a defect marker; remediation = widen to the bisected true crossover covering the whole region. Class H: a kernel that hand-rolls a sqrt/cbrt Newton seed inline (1u128 << bits/2, (x as f64).sqrt()/.cbrt(), 2^ceil(bits/N)) instead of sourcing from the shared seed library algo_x_support::seed (sqrt_seed/cbrt_seed/sqrt_seed_u128) — forfeits the std f64 fast-bootstrap and/or risks the linear floor-walk. Class B is the recurring one: every concrete-N site must size wider-than-N scratch with Int::<N>::single_limbs()/double_limbs()/quad_limbs()/u128_limbs() — NOT a frozen literal, NOT MAX_WORK_N/max_n_limbs, NOT the MAX_SINGLE/DOUBLE/QUADRUPLE_LIMBS/MAX_U128_LIMB consts or max_*_limbs() constructors (those are blanket-only). Class G is the known blind spot: a caller (decimal/algo/type-method) that calls a NAMED engine/kernel directly (div_knuth_into, mul_schoolbook, *_newton, *_into) when a policy::<that-op> matcher with >1 reachable Algorithm arm exists — bypassing the matcher's choice; treat any "matcher's identical choice" comment as a defect marker, not a clearance. For each: file:line — description — rule broken — severity — remediation. Respect the "NOT a violation" list (don't false-positive the ByValue variant, the slice divide engine, the compute_int blankets, const fn literal paths). For Class E, algorithms are NEVER deleted (kept alternatives per "Keeping the alternatives") — flag ONLY superseded duplicate shapes (post-migration leftovers) and non-algorithm orphan cruft; default KEEP.
DELIVERABLE: write the report (a summary table at top: class → count → highest severity, then grouped findings), then return a concise summary (counts per class + the HIGH items with file:line).
When in doubt, prefer flagging with a clear "MIGHT be intentional — verify" note over silently passing.