#!/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; ]` array sizing # * `[; ]` array literal # * `0..` and `0..=` range bounds # * `< ` and `<= ` comparison bounds # * `== ` 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; ] array sizing # 0.. exclusive range # 0..= inclusive range # < upper bound # <= upper bound inclusive # == 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: # ` // audit-ignore: [ — ]` # 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 `[u8; ]` / `[u8; ]` # — 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