Audit script (audit-rust-consts.sh) scans Rust src/examples for numeric
literals mirroring structural kernel-side consts (N_ACTIONS, Q_N_ATOMS,
HIDDEN_DIM, MAX_UNITS, BOOK_LEVELS). Closes the layer-3 gap noted in
feedback_use_consts_not_literals_for_structural_dims:
Layer 1: kernel `#define` allowlist → audit-isv
Layer 2: Rust `pub const` canonical → exists (e.g. N_ACTIONS in rl/common.rs)
Layer 3: Rust literals mirroring (2) → audit-rust-consts (this commit)
Honors `// audit-ignore: <SYMBOL>` per-line markers and skips `[u8; N]`
byte-buffer patterns (high false-positive class — almost always I/O
scratch, not structural dims).
Cleanup driven by first run (19 real flags, no grandfathering):
* New canonical: `BOOK_LEVELS` in `ml-alpha/src/cfc/snap_features.rs`
(10 book levels = same place as `Mbp10RawInput` struct)
* `ml-backtesting/src/lob/mod.rs`: redefine as `pub use` re-export from
ml-alpha (single source of truth; ml-backtesting depends on ml-alpha
via `Mbp10RawInput` already)
* 19 sites switched literal `10` → `BOOK_LEVELS`:
- snap_features.rs:44-47 (struct fields)
- data/loader.rs:872-876, 960 (Mbp10Snapshot → Mbp10RawInput convert)
- data/aggregation.rs:161 (level-wise aggregation loop)
- trainer/perception.rs:2750-2756, 6272-6278, 6686-6690, 7247-7253
(snapshot → batch staging loops)
- tests/lob_sim_fuzz.rs:21, lob_sim_integrated_fuzz.rs:22 (duplicate
const → use ml_backtesting::lob::BOOK_LEVELS)
* 5 sites marked `// audit-ignore: BOOK_LEVELS — <reason>`:
- harness.rs:572,574,594 (conviction-bucket histograms, 10 ≠ depth)
- multi_horizon_labels.rs:489,557,564 (10-element test price vecs)
Re-run after fixes: 0 suspect literals flagged. PASS.
130 lines
4.9 KiB
Bash
Executable File
130 lines
4.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# audit-rust-consts.sh — catch Rust literals that mirror kernel-side
|
|
# structural dimensions but should reference the const, per
|
|
# `feedback_use_consts_not_literals_for_structural_dims`.
|
|
#
|
|
# Reads scripts/audit-manifest/rust-consts.txt which maps SYMBOL=VALUE
|
|
# pairs. For each pair, greps `crates/*/src/` and `crates/*/examples/`
|
|
# for the VALUE appearing in suspect contexts:
|
|
# * `[T; <value>]` array sizing
|
|
# * `[<expr>; <value>]` array literal
|
|
# * `0..<value>` and `0..=<value>` range bounds
|
|
# * `< <value>` and `<= <value>` comparison bounds
|
|
# * `== <value>` equality on usize-likely lhs
|
|
#
|
|
# Flags occurrences in files that do NOT also reference the SYMBOL
|
|
# by name — suggests the literal could/should be the const reference.
|
|
#
|
|
# Heuristic: false positives possible (e.g., `[u8; 4]` for 4-byte
|
|
# arrays unrelated to MAX_UNITS). Manifest can be tuned per-project;
|
|
# the audit's job is to RAISE flags for human review, not auto-fix.
|
|
#
|
|
# Exit codes:
|
|
# 0 — zero suspect literals found
|
|
# 1 — one or more suspect literals found
|
|
# 2 — usage / setup error
|
|
|
|
set -uo pipefail
|
|
|
|
ROOT=$(git rev-parse --show-toplevel)
|
|
MANIFEST="$ROOT/scripts/audit-manifest/rust-consts.txt"
|
|
SCAN_DIRS=(
|
|
"$ROOT/crates/ml-alpha/src"
|
|
"$ROOT/crates/ml-alpha/examples"
|
|
"$ROOT/crates/ml-backtesting/src"
|
|
)
|
|
|
|
if [[ ! -f "$MANIFEST" ]]; then
|
|
echo "ERROR: manifest not found: $MANIFEST" >&2
|
|
exit 2
|
|
fi
|
|
|
|
mapfile -t entries < <(grep -vE '^\s*(#|$)' "$MANIFEST")
|
|
|
|
if [[ ${#entries[@]} -eq 0 ]]; then
|
|
echo "audit-rust-consts: manifest empty — nothing to audit. PASS."
|
|
exit 0
|
|
fi
|
|
|
|
violations=0
|
|
flagged=0
|
|
|
|
echo "audit-rust-consts: scanning ${#entries[@]} const(s)..."
|
|
|
|
for entry in "${entries[@]}"; do
|
|
symbol="${entry%%=*}"
|
|
value="${entry##*=}"
|
|
if [[ -z "$symbol" || -z "$value" || "$symbol" == "$value" ]]; then
|
|
echo "ERROR: malformed manifest entry: '$entry' (expected SYMBOL=VALUE)" >&2
|
|
exit 2
|
|
fi
|
|
# Patterns that suggest mirroring the const value:
|
|
# [T; <value>] array sizing
|
|
# 0..<value> exclusive range
|
|
# 0..=<value> inclusive range
|
|
# < <value> upper bound
|
|
# <= <value> upper bound inclusive
|
|
# == <value> equality vs usize-likely
|
|
#
|
|
# Combined into one extended regex. Word boundary `\b` on the value
|
|
# to avoid `11` matching inside `1100`. The patterns INCLUDE typical
|
|
# spacing variants.
|
|
pat="(\\[[^]]+;[[:space:]]*${value}[[:space:]]*\\]|0\\.\\.=?${value}\\b|<[[:space:]]*${value}\\b|<=[[:space:]]*${value}\\b|==[[:space:]]*${value}\\b)"
|
|
|
|
for dir in "${SCAN_DIRS[@]}"; do
|
|
[[ ! -d "$dir" ]] && continue
|
|
# Find .rs files containing the suspect pattern.
|
|
while IFS= read -r match_file; do
|
|
[[ -z "$match_file" ]] && continue
|
|
# If file already references the symbol by name, no flag.
|
|
if grep -qE "\\b${symbol}\\b" "$match_file"; then
|
|
continue
|
|
fi
|
|
# Otherwise flag with line excerpts.
|
|
while IFS=: read -r lineno text; do
|
|
# Strip leading whitespace from the excerpt for compact output.
|
|
excerpt="$(echo "$text" | sed -E 's/^[[:space:]]+//;s/[[:space:]]+$//')"
|
|
# Skip obvious false positives in this file context that aren't
|
|
# caught by the file-level filter: `// ... 11 ...` in pure
|
|
# comments that happen to match. Cheap check: skip lines that
|
|
# are entirely comment.
|
|
if [[ "$excerpt" =~ ^// ]]; then
|
|
continue
|
|
fi
|
|
# Explicit per-line ignore marker. Format:
|
|
# `<code> // audit-ignore: <SYMBOL>[ — <reason>]`
|
|
# Use sparingly — prefer fixing the literal. Reason is required
|
|
# so future readers know WHY the literal stays.
|
|
if echo "$excerpt" | grep -qE "//[[:space:]]*audit-ignore:[[:space:]]*${symbol}\\b"; then
|
|
continue
|
|
fi
|
|
# Skip byte-buffer patterns `[<num>u8; <value>]` / `[u8; <value>]`
|
|
# — these are almost always I/O scratch buffers (e.g., u32 decode),
|
|
# not structural-dim arrays. False-positive class is too noisy to
|
|
# require per-site ignore markers.
|
|
if [[ "$excerpt" =~ \[(0?u8|u8)\;[[:space:]]*${value}[[:space:]]*\] ]]; then
|
|
continue
|
|
fi
|
|
echo " FLAG ${match_file}:${lineno} ($symbol=$value) — $excerpt"
|
|
flagged=$((flagged + 1))
|
|
done < <(grep -nE "$pat" "$match_file" 2>/dev/null || true)
|
|
done < <(grep -rlE "$pat" "$dir" --include='*.rs' 2>/dev/null || true)
|
|
done
|
|
done
|
|
|
|
echo
|
|
echo "audit-rust-consts: $flagged suspect literal(s) flagged"
|
|
|
|
if [[ $flagged -gt 0 ]]; then
|
|
echo
|
|
echo "Per feedback_use_consts_not_literals_for_structural_dims:"
|
|
echo " if these literals mirror a structural const, replace with the const reference."
|
|
echo " if they're unrelated (false positive), confirm by inspection."
|
|
echo " False positives can be excluded by ensuring the file imports + uses"
|
|
echo " the const by name elsewhere (audit then skips that file)."
|
|
exit 1
|
|
fi
|
|
|
|
echo "audit-rust-consts: PASS"
|
|
exit 0
|