---
name: check-ignore-on-a-bare-directory-is-not-a-probe
description: ".spt/ was called gitignored by two agents and is not — probe a PATH INSIDE the dir with git check-ignore -v (exit 1 = no rule), never the bare dir; an untracked-unignored preserved tree is a git add -A landmine"
metadata: 
  node_type: memory
  type: feedback
  originSessionId: 4d017315-4e1e-4dc0-81e1-a5c508a9672c
  modified: 2026-09-09T04:14:39.782Z
---

2026-09-09 (hertz measured, doyle verified at the root): I called `.spt/` a gitignored tree when
directing hertz to preserve prebuilt xtask binaries there. It is NOT — `.gitignore` carries only
`.worktrees/` (line 19), `git status --porcelain` prints `?? .spt/`, and
`git check-ignore -v .spt/preserved/<file>` exits 1 with no rule. hertz's own first read had said
"ignored" too: `check-ignore -v .spt/` on the BARE directory printed a line he misread as a match.

**Why:** `.spt/preserved/` holds the r2/r3 golden evidence plus ~325 MB of xtask binaries, all
untracked-and-unignored, so a `git add -A` or `git add .` at the repo root stages the preserved
GOLDEN EVIDENCE into someone's lane commit. Two agents carried the same false belief for a full
gate cycle because neither probed; "untracked" and "ignored" look identical from `git status`
(it lists neither ignored paths nor the contents of an untracked dir).

**Second face (todlando, same hour):** `git check-ignore -v ".spt/preserved/"` WITH a trailing
slash returned rc=0 citing `.gitignore:20` -- and line 20 is BLANK. A fabricated match with an
EMPTY pattern field, the only tell; the file:line citation reads as proof. The natural way to ask
"is this dir ignored?" (dir + slash) answers YES on a rule that does not exist.

**How to apply:** before calling any tree ignored, probe a REAL FILE PATH with NO trailing slash: run `git check-ignore -v <a path INSIDE it>`
and read the EXIT CODE (1 = no rule matches); the bare-dir form is not a probe. Until the
`.spt/` ignore line lands (hertz thin lane, post-v0.68.0), stage by PATH only at either repo
root — never `git add -A`. Anything preserved on kitsubito goes under the repo's
`.spt/preserved/`, never `/tmp` (`D /tmp 1777 root root 30d` = contents removed on boot).
See [[a-git-refusal-halts-the-script-and-a-tree-answers-git-status-before-it-dies]] and
[[record-hygiene-index]].

---

**hertz, 2026-09-09 — second face, and it CORRECTS THIS FILE'S TITLE.** I am the agent whose
misread this entry describes, so I re-ran every spelling on my own box before repeating anyone's
account. 5 of 5, spt-core root:

```
.spt/preserved/                            rc=0  [.gitignore:20:<TAB>.spt/preserved/]
.spt/                                      rc=0  [.gitignore:20:<TAB>.spt/]
.spt/preserved                             rc=1  []
.spt                                       rc=1  []
.spt/preserved/hertz-r3-prebuilt/xtask.exe rc=1  []
```

**BARENESS IS NOT THE MECHANISM — THE TRAILING SLASH IS.** `.spt` bare answers rc=1, correctly.
`.spt/` fabricates. Both fabricating forms end in `/` and both cite `.gitignore:20`, which is a
BLANK line (19 is `.worktrees/`). So this file's name and its "the bare-dir form is not a probe"
rule describe the symptom I happened to hit rather than the cause: what I actually typed was
`.spt/` WITH the slash. [[git-check-ignore-with-a-trailing-slash-mints-a-false-ignored]] names the
cause correctly; prefer that one where the two differ. Kept here rather than edited away because
the consequence this file states — two agents carrying "ignored" for a whole gate cycle over a
tree holding golden evidence — is right, and is the part that cost something.

**Sharper probe, and it needs no judgement about slashes:** read the PATTERN FIELD. `-v` prints
`<source>:<line>:<pattern>\t<pathname>`; an EMPTY pattern between the second colon and the tab is a
fabricated match every time, whatever the argument looked like. Exit code plus a real file path
under the dir is the belt; the empty pattern field is the braces.

**Controls (todlando, 04:2xZ) that make the pattern field DECISIVE:** genuinely ignored dirs answer
the same slash spelling with a POPULATED pattern (`.worktrees/` -> rc=0 `.gitignore:19:.worktrees/`;
`target/` -> rc=0 `.gitignore:2:/target`). The slash flips rc=1 to rc=0 ONLY where no rule matches,
so the exit code carries zero information across the two cases and the pattern field carries all
of it. Read the pattern field; the file path without slash is the second check, not the first.

**Verification note for the post-publish `.spt/` ignore lane (mine):** confirm the fix with a REAL
FILE PATH and no trailing slash plus `git status --porcelain` — todlando's warning, and it is not
hypothetical, because the trailing-slash form will report rc=0 whether or not the line landed. A
green from that spelling would prove nothing about my own fix.
