Tooling: add scripts/verify.sh — one pre-commit gate (clean build 0-warnings + full tests + scope check); fix incremental-build trap that hid CS8601 (2026-08-29)
This commit is contained in:
@@ -54,6 +54,7 @@ toast service has no actions) — parked; running-app verification of rename + d
|
|||||||
- **Good Dog Rule:** ONE integration test per change; no feature branches pre-1.0.
|
- **Good Dog Rule:** ONE integration test per change; no feature branches pre-1.0.
|
||||||
- **Scope Lock:** declared list below; run `scripts/scope-check.sh` before committing.
|
- **Scope Lock:** declared list below; run `scripts/scope-check.sh` before committing.
|
||||||
- **Every feature change ships memory updates in the SAME commit** — `TASKS.md` status + this file.
|
- **Every feature change ships memory updates in the SAME commit** — `TASKS.md` status + this file.
|
||||||
|
- **Pre-commit gate:** run `./scripts/verify.sh <scope...>` — clean build (0 warnings) + full tests + scope check. Do NOT trust an incremental build's "0 warnings".
|
||||||
- No `CODING.md`; conventions live in `AGENTS.md` + `ai.md`.
|
- No `CODING.md`; conventions live in `AGENTS.md` + `ai.md`.
|
||||||
|
|
||||||
## Commit scope (declared)
|
## Commit scope (declared)
|
||||||
|
|||||||
@@ -87,6 +87,13 @@ collaboration, not autonomous code generation.
|
|||||||
"/mnt/c/Program Files/dotnet/dotnet.exe" run
|
"/mnt/c/Program Files/dotnet/dotnet.exe" run
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Pre-commit gate (write it down — I forgot once):** ALWAYS run
|
||||||
|
`./scripts/verify.sh "<file1>" "<file2>" ...` (declared scope) before committing. It forces a
|
||||||
|
**clean** build (0 warnings), the full test suite (passes only the 2 known pre-existing `[FAIL]`s), and
|
||||||
|
the scope check in one shot. An **incremental** build can report `0 Warning(s)` while skipping
|
||||||
|
recompiles — that's how `CS8601` slipped past on 2026-08-29. Never claim 0 warnings from anything but
|
||||||
|
`verify.sh`'s clean build.
|
||||||
|
|
||||||
`EnableWindowsTargeting=true` in `ytLive.csproj` lets a cold restore work from WSL, but a Linux
|
`EnableWindowsTargeting=true` in `ytLive.csproj` lets a cold restore work from WSL, but a Linux
|
||||||
`dotnet run`/`build` re-downloads 100M+ of `windowsdesktop.app.*` packs into the Linux NuGet cache
|
`dotnet run`/`build` re-downloads 100M+ of `windowsdesktop.app.*` packs into the Linux NuGet cache
|
||||||
(which lacks them) over the slow 9p `/mnt/c` bridge — twice, because the WPF `_wpftmp` generated
|
(which lacks them) over the slow 9p `/mnt/c` bridge — twice, because the WPF `_wpftmp` generated
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# verify.sh — One gate before committing: clean build (0 warnings) + full test run + scope check.
|
||||||
|
# Usage: ./scripts/verify.sh "file1.cs" "file2.cs" ...
|
||||||
|
#
|
||||||
|
# Why a clean build? An incremental build SKIPS recompiling unchanged projects, so a
|
||||||
|
# "0 Warning(s)" from an incremental build can be a lie (CS8601 slipped past this way on
|
||||||
|
# 2026-08-29). This script forces a full rebuild so the 0-warning claim is only ever made
|
||||||
|
# against fresh compiler output.
|
||||||
|
#
|
||||||
|
# Requires WINDOWS dotnet (never Linux dotnet — it re-downloads the windowsdesktop packs
|
||||||
|
# over the slow 9p bridge; see ai.md -> Run). Reads the Windows path from the WSL mount.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DOTNET="/mnt/c/Program Files/dotnet/dotnet.exe"
|
||||||
|
[ -x "$DOTNET" ] || { echo "❌ Windows dotnet not found at $DOTNET"; exit 1; }
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
ROOTWIN="$(wslpath -w "$ROOT")"
|
||||||
|
|
||||||
|
echo "══ 1/3 CLEAN BUILD (expect 0 warnings) ══"
|
||||||
|
"$DOTNET" clean "$ROOTWIN\\ytLive.csproj" > /dev/null
|
||||||
|
OUT="$("$DOTNET" build "$ROOTWIN\\ytLive.csproj" 2>&1)"
|
||||||
|
if echo "$OUT" | grep -qI ": warning"; then
|
||||||
|
echo "✗ WARNINGS FOUND:"
|
||||||
|
echo "$OUT" | grep -iE ": warning" | sort -u
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "$OUT" | grep -E "Build succeeded" || { echo "$OUT" | tail -5; exit 1; }
|
||||||
|
echo "✓ Build clean, 0 warnings."
|
||||||
|
|
||||||
|
echo "══ 2/3 TEST SUITE ══"
|
||||||
|
TESTDLL="$ROOTWIN\\ytLive.Tests\\bin\\Debug\\net8.0-windows10.0.19041.0\\ytLive.Tests.dll"
|
||||||
|
"$DOTNET" build "$ROOTWIN\\ytLive.Tests\\ytLive.Tests.csproj" > /dev/null
|
||||||
|
set +e
|
||||||
|
RUN_RAW="$("$DOTNET" vstest "$TESTDLL" 2>&1)"
|
||||||
|
TEST_EXIT=$?
|
||||||
|
set -e
|
||||||
|
echo "$RUN_RAW" | grep -iE "Passed!|Failed!" | tail -1
|
||||||
|
|
||||||
|
# Known pre-existing failures (see HANDOFF.md: do not chase). Anything beyond
|
||||||
|
# these is a real regression and fails the gate.
|
||||||
|
FAILS="$(echo "$RUN_RAW" | grep -iE "\[FAIL\]" || true)"
|
||||||
|
KNOWN=$(echo "$FAILS" | grep -cE "Mix_HonorsProviderGains_AndGameMute_KillsTheLoopback|Round_Clip_Corner_Is_Grabbable_And_Shape_Is_Circle" || true)
|
||||||
|
echo "$FAILS" | sort -u || true
|
||||||
|
|
||||||
|
if [ "$TEST_EXIT" -ne 0 ] && [ "$KNOWN" -eq 0 ]; then
|
||||||
|
echo "✗ TEST FAILURES that are NOT the known pre-existing pair — investigate."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ "$TEST_EXIT" -ne 0 ]; then
|
||||||
|
echo "⚠ Test exit=$TEST_EXIT but only the 2 known pre-existing failures present (OK)."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "══ 3/3 SCOPE CHECK ══"
|
||||||
|
"$ROOT/scripts/scope-check.sh" "$@"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✓ All gates passed — safe to commit."
|
||||||
Reference in New Issue
Block a user