diff --git a/.claude/skills/pr-process/SKILL.md b/.claude/skills/pr-process/SKILL.md index ee79b3310..bbc0da74e 100644 --- a/.claude/skills/pr-process/SKILL.md +++ b/.claude/skills/pr-process/SKILL.md @@ -123,6 +123,21 @@ always an autoload-order issue (see `CLAUDE.md` → GDScript conventions → Autoload parse-order rule) — fix the ordering, don't just rebuild the cache to mask it locally (the same error resurfaces post-merge). +**Scope, so you don't over-trust it:** `godot-cold-parse` only ever sees +scripts on the **startup path** — autoloads and the main scene chain. That is +exactly right for the registration-ORDER bug it exists to catch, and far +narrower than the name suggests: it reports `clean` for a syntactically +broken UI script or test file that startup never loads (verified 2026-07-27 +by breaking one of each). It also filters `"Cannot infer the type"`, which +hid a genuinely unparseable file for five months. + +**"Does every script parse?" is a different question, and the pre-push hook +now answers it** — `tooling/godot-parse-sweep` opens all ~226 project scripts +and blocks the push on any that don't, running *before* the test suite so a +parse failure costs 4s instead of 135s. It is enforced by the gate, so do +**not** run it here as well (`team-patterns.md`: don't duplicate the push +gate). Run it manually only when you want that answer early. + Any lines it reports are new errors introduced by this branch. Fix them before pushing. diff --git a/.config/hooks/pre-push b/.config/hooks/pre-push index 26ead3511..f3e234f0e 100755 --- a/.config/hooks/pre-push +++ b/.config/hooks/pre-push @@ -75,6 +75,29 @@ if [ "$CLIENT_CHANGED" -gt 0 ] && command -v gdformat >/dev/null 2>&1 && [ -d "$ fi fi +# --- GDScript parse sweep — blocking, and deliberately BEFORE the suite --- +# Every project .gd must parse. ~3.7s against the suite's ~135s, and it runs +# first because that ordering makes failures CHEAPER, not the gate slower: a +# script that does not parse is now caught in 4s instead of after two minutes +# of tests that could never have covered it. A clean push pays 3.7s; a broken +# one saves over two minutes. +# +# Not redundant with the suite. gdUnit4 reports the suites that DID load as a +# clean pass, so a file that fails to parse reads as success (guarded now in +# tests/run-godot, but only for test files). This covers all 226 scripts, +# including the ~half of the codebase no test ever loads. It is also the only +# gate that covers them at all: godot-cold-parse is skill-only (never invoked +# by this hook) and sees only the startup path regardless. +if [ "$CLIENT_CHANGED" -gt 0 ] && [ -x "$REPO_ROOT/tooling/godot-parse-sweep" ]; then + echo "pre-push: sweeping GDScript parse (tooling/godot-parse-sweep)..." + if ! "$REPO_ROOT/tooling/godot-parse-sweep"; then + echo "pre-push: parse sweep FAILED — a script does not parse" + ERRORS=$((ERRORS + 1)) + else + echo "pre-push: parse sweep — OK" + fi +fi + # --- Godot client test suite (gdUnit4) — blocking (T-1065) --- # The push gate is the only automatic verification (no CI). The suite is # ~100s, 300s-capped, and was made fully green by the T-973 debt clearance;