fix(b-0260): make reindexer recursive — scan memory/ subdirectories#3109
Merged
Conversation
Closes B-0260 final slice.
Root cause: `collectEntries` in `reindex-memory-md.ts` called
`readdir(targetDir)` without recursion. Files in subdirectories
(e.g. `memory/observed-phenomena/`) had valid YAML frontmatter but
were silently excluded from the generated index. The parity validator
(`tools/memory/validate-memory-parity.ts`) flagged them as
`gap-no-frontmatter`, which was a misleading diagnosis — the actual
cause was `gap-subdirectory-not-scanned`.
## Changes
tools/memory/reindex-memory-md.ts
Extracted `collectEntriesRecursive` helper that uses
`readdir({ withFileTypes: true })` to distinguish files from
directories and recurse. Subdirectory entries use a path relative
to `baseDir` (e.g., `observed-phenomena/file.md`) — correct as
both a markdown link target in MEMORY.md and as a parity-validator
lookup key. Added `relative` import from `node:path`.
tools/memory/reindex-memory-md.test.ts
Two new tests: "scans subdirectories recursively" and "uses
subdir-relative path for subdirectory entries". All 20 tests pass.
tools/memory/testdata/subdir/gamma_2026_05_14.md
New test fixture: a memory file in a subdirectory, used by the
new recursive-scanning tests.
## Parity result after fix
Old-index entries: 672
Unique files: 672
Covered (ok): 672 ← was 670 (2 gaps)
No-frontmatter gap: 0 ← was 2
Missing (loss): 0
Full parity: all old-index files are covered by the generated index.
## B-0260 acceptance criteria
✅ MEMORY.md is generated by tooling, not hand-edited
✅ Entry coverage parity verified: 672/672 covered
✅ Zero missing entries (no coverage loss)
✅ No intentional behavior changes requiring follow-up issues
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes B-0260 by making the memory reindexer recursive so files in memory/ subdirectories (e.g., memory/observed-phenomena/) are included in MEMORY.md. Resolves the final 2 parity gaps (672/672 covered).
Changes:
- Replaces non-recursive
collectEntrieswith acollectEntriesRecursivehelper usingreaddir({ withFileTypes: true }), storingfilenameas a path relative tobaseDir. - Adds 2 tests covering recursive discovery and subdir-relative filename.
- Marks B-0260 closed (backlog row + regenerated
docs/BACKLOG.md) and updatesMEMORY.mdheap-count footer (1103 → 1130).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tools/memory/reindex-memory-md.ts | Recursive scan + relative-path filename for entries. |
| tools/memory/reindex-memory-md.test.ts | Adds two tests for recursive subdir scanning. |
| tools/memory/testdata/subdir/gamma_2026_05_14.md | Test fixture under a subdir. |
| memory/MEMORY.md | Footer heap-count updated to reflect new total. |
| docs/backlog/P1/B-0260-...md | Status → closed with closure notes. |
| docs/BACKLOG.md | Regenerated index entry checkbox for B-0260. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 895b51c111
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Normalize relative() output to forward slashes so subdirectory entries are portable across OS (Windows path\\file.md -> path/file.md). Fixes parity validator mismatches on non-POSIX hosts per Codex review. Also add blank line before acceptance-criteria list to satisfy MD032. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
collectEntriesinreindex-memory-md.tsused non-recursivereaddir, silently excluding files inmemory/subdirectories (e.g.memory/observed-phenomena/). Both affected files had valid YAML frontmatter — the parity validator'sgap-no-frontmatterlabel was a misleading diagnosis; the true cause wasgap-subdirectory-not-scanned.collectEntriesRecursivehelper usingreaddir({ withFileTypes: true }), recursing into subdirs and storing paths relative tobaseDir(e.g.observed-phenomena/file.md) — correct for both MEMORY.md markdown links and the parity-validator lookup set.scans subdirectories recursively,uses subdir-relative path for subdirectory entries). All 20/20 tests pass.Parity result
B-0260 acceptance criteria
memory/MEMORY.mdgenerated by tooling, not hand-editedBuild gate
Test plan
bun test tools/memory/reindex-memory-md.test.ts— all 20 passbun tools/memory/validate-memory-parity.ts— full parity confirmeddotnet build -c Release— 0 warnings, 0 errorsclosedwith closure notes[x])🤖 Generated with Claude Code