gitignore-bare-pattern-shadows-source-directory
Solution written to ~/SOLUTION.md and verified end-to-end in /tmp/repro.
Root cause: A .gitignore line with no slash — e.g. canopyd — is a bare pattern that matches a file or directory of that name at any depth. So the root build artifact ./canopyd and the source directory cmd/canopyd/ both match. Tracked files keep working (Git never ignores tracked files), so the breakage stays hidden until a new file is added under that directory. Explicit git add cmd/canopyd/<new>.go then exits 1; git add . silently omits it.
Fix: Anchor the artifact pattern to the tree root with a leading slash:
- canopyd
+ /canopyd
bin/
bin/ is fine as-is (trailing slash intentionally matches a directory at any depth).
Verified probes (exit codes measured directly, no pipes):
- Pre-fix: git check-ignore -v cmd/canopyd/newfile.go → match, rc=0; git add → rc=1.
- Post-fix: check-ignore → no match, rc=1; git add → rc=0 (staged).
- Unchanged behavior: canopyd still matches /canopyd; bin/canopyd still matches bin/ (using --no-index, since committed files are normally treated as never-ignored).
The document includes a full reproduction script, exact expected outputs, and the --no-index rationale.
# Evidence - Problem class: gitignore-bare-pattern-shadows-source-directory - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-17T21:27:49.355Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "A .gitignore line that names a build artifact by bare name (e.g. `canopyd` for a `go build` output at the repo root) also matches a DIRECTORY with the same basename anywhere in the tree, so `cmd/canopyd/` becomes ignored: every tracked file keeps working (tracked files win), but any NEW file added under that directory makes plain `git add <path>` exit 1, and `git check-ignore -v <path>` reports the artifact line. The failure is silent until someone adds a new file, and it is usually first seen as a commit that omits a file. Fix: anchor the pattern to the tree root (`/canopyd`). Verify with BOTH probes: pre-fix `git check-ignore -v cmd/canopyd/<new>.go` matches (rc=0) and `git add` exits 1; post-fix check-ignore returns no match (rc=1) and the add succeeds (rc=0), while `git check-ignore -v canopyd` still matches `/canopyd` and `bin/canopyd` still matches `bin/`. Use a real throwaway file for the add probe and measure the exit code WITHOUT a pipe (a pipe reports head/sed status, masking the refusal).", "environment": "", "language": "git", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "gitignore-bare-pattern-shadows-source-directory", "provider": "openrouter", "solved_at": "2026-09-17T21:27:49.356Z", "version": ""}Solution written to ~/SOLUTION.md and verified end-to-end in /tmp/repro.
Root cause: A .gitignore line with no slash — e.g. canopyd — is a bare pattern that matches a file or directory of that name at any depth. So the root build artifact ./canopyd and the source directory cmd/canopyd/ both match. Tracked files keep working (Git never ignores tracked files), so the breakage stays hidden until a new file is added under that directory. Explicit git add cmd/canopyd/<new>.go then exits 1; git add . silently omits it.
Fix: Anchor the artifact pattern to the tree root with a leading slash:
- canopyd
+ /canopyd
bin/
bin/ is fine as-is (trailing slash intentionally matches a directory at any depth).
Verified probes (exit codes measured directly, no pipes):
- Pre-fix: git check-ignore -v cmd/canopyd/newfile.go → match, rc=0; git add → rc=1.
- Post-fix: check-ignore → no match, rc=1; git add → rc=0 (staged).
- Unchanged behavior: canopyd still matches /canopyd; bin/canopyd still matches bin/ (using --no-index, since committed files are normally treated as never-ignored).
The document includes a full reproduction script, exact expected outputs, and the --no-index rationale.
# Evidence - Problem class: gitignore-bare-pattern-shadows-source-directory - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-17T21:27:49.355Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "A .gitignore line that names a build artifact by bare name (e.g. `canopyd` for a `go build` output at the repo root) also matches a DIRECTORY with the same basename anywhere in the tree, so `cmd/canopyd/` becomes ignored: every tracked file keeps working (tracked files win), but any NEW file added under that directory makes plain `git add <path>` exit 1, and `git check-ignore -v <path>` reports the artifact line. The failure is silent until someone adds a new file, and it is usually first seen as a commit that omits a file. Fix: anchor the pattern to the tree root (`/canopyd`). Verify with BOTH probes: pre-fix `git check-ignore -v cmd/canopyd/<new>.go` matches (rc=0) and `git add` exits 1; post-fix check-ignore returns no match (rc=1) and the add succeeds (rc=0), while `git check-ignore -v canopyd` still matches `/canopyd` and `bin/canopyd` still matches `bin/`. Use a real throwaway file for the add probe and measure the exit code WITHOUT a pipe (a pipe reports head/sed status, masking the refusal).", "environment": "", "language": "git", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "gitignore-bare-pattern-shadows-source-directory", "provider": "openrouter", "solved_at": "2026-09-17T21:27:49.356Z", "version": ""}