Second layer under #2560's --include-gitignored: a realpath'd ceiling at the
staging dir's parent pushes any git-enumerating collector off the git fast
path (which sees zero files under ~/.gstack's ignore-everything root) onto
its plain FS walk, even on gbrain builds whose flag semantics drift. Ceiling
is realpath'd because git compares canonicalized directories during
discovery — a staging dir reached through a symlink (macOS /var ->
/private/var, symlinked $GSTACK_HOME) otherwise never matches.
Behavioral tests prove discovery stops at the ceiling from the staging dir,
including through a symlinked path, using git itself — no gbrain required.
Mechanism ported from time-attack/gstack (GStack 2).
Co-authored-by: Sina Matian <sina@time-attack.dev>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gstack-artifacts-init writes an ignore-everything .gitignore (a bare `*`,
headed "Do not edit") at the root of ~/.gstack. The memory ingest stages
pages into ~/.gstack/.staging-ingest-<pid>-<ts>/, which is inside that
repo, and gbrain's markdown collector honours .gitignore. The collector
therefore matches every staged file against `*` and collects zero.
The failure is silent. gbrain import exits 0 having imported nothing while
the ingest prints `written: N` from the STAGED count rather than the
imported count, so a run that indexes nothing looks identical to a healthy
one and the memory corpus quietly stops growing.
Reproduction, using git's own ignore machinery (no gbrain needed):
git init .
mkdir -p .staging-ingest-12345/learnings
echo x > .staging-ingest-12345/learnings/page.md
printf '*\n' > .gitignore
git ls-files --others --exclude-standard # -> empty
Passing --include-gitignored makes the import independent of whatever
.gitignore sits above the staging directory. Adding a negation to the
generated .gitignore is the alternative, but that file is gstack-owned and
marked "Do not edit", so any regeneration silently reintroduces the bug.
Adds a regression pin in the shape of memory-ingest-no-put_page.test.ts,
plus a behavioural test for the collision itself. Both source pins fail
against the unpatched file.