diff --git a/scripts/check-naming-and-style.sh b/scripts/check-naming-and-style.sh index 4cad6abd..f357f65c 100755 --- a/scripts/check-naming-and-style.sh +++ b/scripts/check-naming-and-style.sh @@ -34,16 +34,51 @@ EXCLUDES=( --exclude-dir=bundle --exclude-dir=dist-subpath --exclude-dir=.git + # Visual Studio's local state, gitignored. CopilotSnapshots keeps a full + # per-edit copy of touched source files, so every real finding is reported + # again once per snapshot - hundreds of duplicates that bury the actual + # hits and make the scan take minutes instead of seconds. + --exclude-dir=.vs --exclude-dir=versions --exclude-dir=staticdocs # Local, gitignored scratch notes (see .gitignore devnotes/). Not product # source, never committed, and free to hold pasted logs full of em-dashes # and arrows - grep does not consult .gitignore, so exclude it explicitly. --exclude-dir=devnotes - --exclude=findings.sarif - --exclude=report.md + # .NET build output. The agent projects emit vendored runtime DLLs and + # generated *.nuget.g.props/.targets under bin/ and obj/; both are full of + # bytes nobody here wrote. Same failure as the .vs case above: thousands of + # hits that bury every real finding and make the gate unreadable, so it + # stops being run at all. + --exclude-dir=bin + --exclude-dir=obj + --exclude-dir=publish + --exclude-dir=dev-bin + # Data, not source: exported CSVs carry vendor mojibake and backups are + # snapshots of a moment. Neither is something a convention applies to. + --exclude-dir=exports + --exclude-dir=backups ) +# DO NOT ADD --exclude= TO THE ARRAY ABOVE. +# +# In this grep build a single file-level --exclude silently CANCELS EVERY +# --include filter on the same command. Bisected: with only --exclude-dir flags +# a shorthand scan restricted to --include='*.py' returns 0 markdown hits; add +# any one --exclude and the same scan returns 1142. Directory excludes are +# unaffected - it is specifically the file form. +# +# This is not theoretical, it was live: --exclude=findings.sarif and +# --exclude=report.md sat in this array and had been quietly disabling the +# include lists for every check that used them. That is why the shorthand check +# reported .md, .ps1, .cs, .json and .gitignore hits when its flags say it only +# ever looks at .py/.vue/.js/.ts, and why the gate accumulated thousands of +# unactionable findings that made it unreadable enough to be ignored. +# +# To skip a FILE, filter it out of the pipeline afterwards (see drop_scratch and +# the post-filters on the ADR-015 check) or exclude the directory holding it. +# Binaries are handled by grep -I on the scan itself. + # Root-level gitignored scratch: review writeups and chat handoffs, free to hold # pasted logs full of em-dashes and arrows. grep does not consult .gitignore, so # it has to be dropped here. @@ -54,6 +89,15 @@ EXCLUDES=( # that nothing would report. This drops only the path we mean. drop_scratch() { grep -v '^\./devnotes/' || true; } +# Generated scan output, replacing the --exclude=findings.sarif and +# --exclude=report.md that used to live in EXCLUDES. Same intent, but as a +# post-filter, because the flag form cancelled every --include on the command +# (see the warning above the EXCLUDES array). Also drops .env, which is local +# configuration rather than source. +drop_generated() { + grep -vP '^\./(.*/)?(findings\.sarif|report\.md|\.env):' || true +} + INCLUDES_CODE=( --include='*.py' --include='*.vue' @@ -77,7 +121,11 @@ INCLUDES_ALL=( # and did, including in files this repo's own convention forbids them in. # Markdown, JSON and YAML are now covered too. echo "==> Checking for non-ASCII characters..." -NON_ASCII=$(grep -rPn '[^\x00-\x7F]' "${EXCLUDES[@]}" "${INCLUDES_ALL[@]}" . 2>/dev/null | drop_scratch || true) +# -I skips binary files. Without it grep reports "Binary file X matches" for any +# archive or compiled artifact that slips past the excludes, which is noise no +# author can act on: there is no line to fix. The excludes above are the primary +# defence; this is the backstop for whatever they miss. +NON_ASCII=$(grep -rPnI '[^\x00-\x7F]' "${EXCLUDES[@]}" "${INCLUDES_ALL[@]}" . 2>/dev/null | drop_scratch | drop_generated || true) if [ -n "$NON_ASCII" ]; then echo "FAIL: non-ASCII characters found (em-dashes, smart quotes, arrows, emojis):" echo "$NON_ASCII" @@ -92,6 +140,8 @@ echo "==> Checking for banned shorthand (standalone)..." for word in cfg ctx mgr req res; do HITS=$(grep -rPn "(^|[^a-zA-Z0-9_])${word}([^a-zA-Z0-9_]|\$)" "${EXCLUDES[@]}" --include='*.py' --include='*.vue' --include='*.js' --include='*.ts' . 2>/dev/null \ | grep -vP "(^|[^a-zA-Z0-9_])(request_obj|response_obj)" \ + | drop_scratch \ + | drop_generated \ || true) if [ -n "$HITS" ]; then echo "FAIL: banned shorthand '$word' (standalone) found:"