fix(vectorstore): walk and read the brain through brainfs (#157, slice 3) #166

Merged
mathias merged 3 commits from fix/vectorstore-root-157 into main 2026-10-04 06:35:17 +00:00
3 Commits
Author SHA1 Message Date
mathiasandClaude Opus 5.5 31071bc9b1 fix(brainfs): check every component of the walk root (#157)
CI / Lint / Test / Vet (pull_request) Successful in 41s
CI / Mirror to GitHub (pull_request) Skipped
Review round 2 on PR #166: Lstat on the walk root checks only its last
component, so search with Wing+Hall (root wiki/<wing>/<hall>) walked a
symlinked <wing> whose target had a real <hall> directory.

WalkRegular now Lstats every prefix of the root and requires each to be
a real directory. New brainfs and search (Wing+Hall) tests; the Wing-only
search test is renamed to say what it covers.

The doc now records the accepted residual: a directory swapped for a
symlink between listing and read is still followed; os.Root keeps the
read inside the brain but not inside the walk root.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:16:50 +02:00
mathiasandClaude Opus 5.5 66b6cf8a77 fix(brainfs): refuse a symlinked walk root (#157)
CI / Lint / Test / Vet (pull_request) Successful in 40s
CI / Mirror to GitHub (pull_request) Skipped
Review round 1 on PR #166: fs.WalkDir stats its root with a follow, and
os.Root allows a symlink that stays inside the brain, so knowledge -> .
aliased raw/, sessions/ and root files into the embeddings (and a
wiki/<w> -> .. root into search results). On main, filepath.WalkDir
Lstat'ed the root and did not descend.

- WalkRegular Lstats its root and requires a real directory; anything
  else goes to onErr as ErrNotRegular and nothing is yielded.
- Sync skips a missing scan root via bfs.Lstat before walking, and every
  other walk error, including a symlinked root, aborts before the delete
  pass. This removes the unpinned rel == sub special case.
- Search warns and skips a symlinked root (new test).
- Test renamed to TestSyncRefusesSymlinkedNotesAndSurvivesSwapRaces.
- wrapAfterStat comment: brainfs tests must not use t.Parallel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:11:16 +02:00
mathiasandClaude Opus 5.5 74a9621ba6 fix(vectorstore): walk and read the brain through brainfs (#157, slice 3)
CI / Lint / Test / Vet (pull_request) Successful in 40s
CI / Mirror to GitHub (pull_request) Skipped
Sync walked wiki/ and knowledge/ with filepath.WalkDir and read each .md
with os.ReadFile. A symlinked note (Syncthing syncs symlinks) had its
target embedded into pgvector and served by semantic search; a FIFO
stalled the sync. The walk and read now go through brainfs: regular
files only, type checked on the opened handle.

- Chunks already embedded from a symlinked note are deleted on the next
  sync, because the note is no longer seen.
- A walk error still aborts Sync before the delete pass, so an unreadable
  subdir does not delete chunks of files that exist. A missing scan dir
  is skipped as before.
- brainfs gains Lstat, used for the mtime staleness check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:02:16 +02:00