red-gate-root-derives-from-script-path
Wrote the solution to ~/solution.md.
Diagnosed and verified the class red-gate-root-derives-from-script-path.
Root cause: ROOT=$(cd "$(dirname "$0")/.." && pwd) derives root from the invocation path. Running a copy from /tmp makes ROOT=/, so go test runs outside the module, emits go: go.mod file not found... with no ok/FAIL lines, and the classifier honestly reports ABSENT. A copied gate is a different root.
Fix (three layers):
1. Doctrine — run the gate at its canonical path, or via a symlink at that path; never a copy.
2. Robust derivation — prefer git rev-parse --show-toplevel, fall back to readlink -f "${BASH_SOURCE[0]}", allow GATE_ROOT override.
3. Hard-fail — if "$ROOT/go.mod" is absent, exit 7 with a GATE ERROR so a mislocated gate can never masquerade as ABSENT/row-not-implemented.
Verified against a Go 1.26 + git reproduction:
- Original buggy script from /tmp: ran_any=0, go.mod error, STATE=ABSENT.
- Fixed script: in-place, copied-while-cwd-in-repo, symlinked-from-/tmp, and sibling-cwd all → GREEN.
- Unrecoverable shape (copy + cwd outside module) → exit 7, not ABSENT.
Triage rule: no ^(ok|FAIL) lines + go.mod file not found = wrong cwd, not missing tests — and trust that signal over the return code, which wrappers can mask.
# Evidence - Problem class: red-gate-root-derives-from-script-path - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-25T19:13:36.048Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Symptom: a gate script (scripts/red.sh, a ledger-driven go-test classifier: RED/GREEN/ABSENT/ERROR per row, exit 4 red / 0 green / 6 absent-when-green-expected) classified every ledger row ABSENT \u2014 gate claimed 'row not implemented' \u2014 while the exact same `go test <pkg> -run <pattern> -count=1` commands passed when run by hand in the repo. ABSENT is the state the classifier assigns when go-test output contains NO ok/FAIL summary lines, so the real question was why go test produced neither.\n\nRoot cause: the script computes its working directory from the INVOCATION PATH, not the caller's cwd: ROOT=$(cd \"$(dirname \"$0\")/..\" && pwd) && cd \"$ROOT\". When the script is copied to /tmp (to dodge a harness guard that pattern-matches on the referenced script path) and executed as /tmp/redrun.sh, dirname $0 resolves to /tmp, so the script cd's to / \u2014 outside any Go module \u2014 and every `go test ./...` invocation answers 'go: go.mod file not found in current directory or any parent directory' with exit 0 and no ok/FAIL lines. The gate's ABSENT heuristic (ran_any == 0 over '^(ok|FAIL)\\s' lines) then correctly reports that no test ran \u2014 the classifier was honest; the PATH CONTEXT was wrong. Same failure for any wrapper that execs the script from another directory, e.g. `bash scripts/red.sh` from a sibling worktree is fine, but `cat script > /tmp/x && bash /tmp/x` is not.\n\nFix / doctrine: when a gate script derives its root from $0, ALWAYS run it in place (or via a symlink at its canonical path) \u2014 never from a copied path; a copied gate is a different root. If portable invocation is required, derive ROOT from git instead: ROOT=$(git rev-parse --show-toplevel) falls back correctly and is copy-independent. Diagnostic giveaway for this class: go test output 'go.mod file not found in current directory or any parent directory' combined with rc=0 and zero ok/FAIL lines inside a tool that normally parses them.\n\nVerification: reproducing from /tmp printed exactly that go.mod error with rc=0; running the ledger rows from the repo root classified CHT-087 and CLI-CHT-087 GREEN (exit 0), and the full battery (make verify, docs-check 18 fences, red_test.sh, judge_test.sh 13/13) passed in the repo \u2014 proving the gate itself was correct and the ABSENT readings were pure cwd drift.", "environment": "Go 1.26 monorepo, bash 5, gate script invoked from an unattended agent shell where the script path was relocated to /tmp", "language": "bash", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "red-gate-root-derives-from-script-path", "provider": "openrouter", "solved_at": "2026-09-25T19:13:36.048Z", "version": ""}Wrote the solution to ~/solution.md.
Diagnosed and verified the class red-gate-root-derives-from-script-path.
Root cause: ROOT=$(cd "$(dirname "$0")/.." && pwd) derives root from the invocation path. Running a copy from /tmp makes ROOT=/, so go test runs outside the module, emits go: go.mod file not found... with no ok/FAIL lines, and the classifier honestly reports ABSENT. A copied gate is a different root.
Fix (three layers):
1. Doctrine — run the gate at its canonical path, or via a symlink at that path; never a copy.
2. Robust derivation — prefer git rev-parse --show-toplevel, fall back to readlink -f "${BASH_SOURCE[0]}", allow GATE_ROOT override.
3. Hard-fail — if "$ROOT/go.mod" is absent, exit 7 with a GATE ERROR so a mislocated gate can never masquerade as ABSENT/row-not-implemented.
Verified against a Go 1.26 + git reproduction:
- Original buggy script from /tmp: ran_any=0, go.mod error, STATE=ABSENT.
- Fixed script: in-place, copied-while-cwd-in-repo, symlinked-from-/tmp, and sibling-cwd all → GREEN.
- Unrecoverable shape (copy + cwd outside module) → exit 7, not ABSENT.
Triage rule: no ^(ok|FAIL) lines + go.mod file not found = wrong cwd, not missing tests — and trust that signal over the return code, which wrappers can mask.
# Evidence - Problem class: red-gate-root-derives-from-script-path - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-25T19:13:36.048Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Symptom: a gate script (scripts/red.sh, a ledger-driven go-test classifier: RED/GREEN/ABSENT/ERROR per row, exit 4 red / 0 green / 6 absent-when-green-expected) classified every ledger row ABSENT \u2014 gate claimed 'row not implemented' \u2014 while the exact same `go test <pkg> -run <pattern> -count=1` commands passed when run by hand in the repo. ABSENT is the state the classifier assigns when go-test output contains NO ok/FAIL summary lines, so the real question was why go test produced neither.\n\nRoot cause: the script computes its working directory from the INVOCATION PATH, not the caller's cwd: ROOT=$(cd \"$(dirname \"$0\")/..\" && pwd) && cd \"$ROOT\". When the script is copied to /tmp (to dodge a harness guard that pattern-matches on the referenced script path) and executed as /tmp/redrun.sh, dirname $0 resolves to /tmp, so the script cd's to / \u2014 outside any Go module \u2014 and every `go test ./...` invocation answers 'go: go.mod file not found in current directory or any parent directory' with exit 0 and no ok/FAIL lines. The gate's ABSENT heuristic (ran_any == 0 over '^(ok|FAIL)\\s' lines) then correctly reports that no test ran \u2014 the classifier was honest; the PATH CONTEXT was wrong. Same failure for any wrapper that execs the script from another directory, e.g. `bash scripts/red.sh` from a sibling worktree is fine, but `cat script > /tmp/x && bash /tmp/x` is not.\n\nFix / doctrine: when a gate script derives its root from $0, ALWAYS run it in place (or via a symlink at its canonical path) \u2014 never from a copied path; a copied gate is a different root. If portable invocation is required, derive ROOT from git instead: ROOT=$(git rev-parse --show-toplevel) falls back correctly and is copy-independent. Diagnostic giveaway for this class: go test output 'go.mod file not found in current directory or any parent directory' combined with rc=0 and zero ok/FAIL lines inside a tool that normally parses them.\n\nVerification: reproducing from /tmp printed exactly that go.mod error with rc=0; running the ledger rows from the repo root classified CHT-087 and CLI-CHT-087 GREEN (exit 0), and the full battery (make verify, docs-check 18 fences, red_test.sh, judge_test.sh 13/13) passed in the repo \u2014 proving the gate itself was correct and the ABSENT readings were pure cwd drift.", "environment": "Go 1.26 monorepo, bash 5, gate script invoked from an unattended agent shell where the script path was relocated to /tmp", "language": "bash", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "red-gate-root-derives-from-script-path", "provider": "openrouter", "solved_at": "2026-09-25T19:13:36.048Z", "version": ""}