Skip to content

kb-retrieve ignores the content targets that kb check enforces #824

Description

@williamthorsen

Problem

kb-retrieve defines "a note" differently from kb check and kb-curate. The recall helper runs ripgrep with hardcoded globs (*.md, !.kb/**) over the whole KB root, ignoring the KB's configured targets/exclude. As a result it:

  • surfaces non-note markdown under the root (README.md, CHANGELOG.md) that the targets glob would exclude;
  • recalls notes under excluded paths (e.g. a draft) that kb check omits;
  • returns a different note set than kb check/kb-curate for the same KB — the split that made the kb-add writes assertions to the KB root instead of content/assertions/ #816 misplacement hard to notice.

Context

kb check and kb-curate enumerate notes through enumerateNotes, which applies the KB's targets/exclude globs (default content/**/*.md) as picomatch predicates (dot:false) against each file's KB-root-relative path. kb-retrieve shares none of that logic; it re-derives scope with an ad-hoc ripgrep glob. One concept ("a note") with two definitions is the root cause, and it keeps drifting until the definition is centralized.

The asymmetry with kb-add is intentional and stays: a writer is the authority on placement and hardcodes content/assertions/, whereas a reader must honor whatever the KB declares its note set to be.

Proposed solution

Centralize the targets/exclude note-set definition in one shared predicate, and have kb-retrieve apply it.

  • Extract a createNoteScopeMatcher(config) helper in @codeassembly/kb that builds the targets/exclude picomatch predicates once and exposes isTarget/isExcluded/isNote. enumerateNotes consumes it so enumeration and recall share one definition.
  • kb-retrieve loads each in-scope KB's config and post-filters ripgrep's hits through isNote(relativePath), keeping ripgrep's existing root-level *.md search.

Apply the same predicate kb check uses — not a re-implementation of the globs in ripgrep's own matcher. Routing the definition through a second glob engine would reintroduce the very divergence this fixes (picomatch and ripgrep are different dialects), so picomatch stays the single authority and ripgrep only prunes to *.md.

Recall inherits ripgrep's default gitignore handling: a gitignored note under the targets is not recalled, whereas enumerateNotes is git-agnostic and would enumerate it. This residual divergence is accepted and intentional — it is empty for committed KBs, and teaching the filesystem-walk enumerator to consult git (KBs need not be git repos) is out of scope.

Acceptance criteria

Must have

  • The targets/exclude note-set definition is shared between kb check's enumeration and kb-retrieve — one source of truth, not duplicated.
  • kb-retrieve recalls only notes matching the KB's configured targets/exclude — the same definition kb check uses — not every markdown file under the root.
  • kb-retrieve does not recall non-note markdown under the root or under excluded paths.
  • New or modified behavior is covered by tests.

Should have

  • kb-retrieve's SKILL.md states that recall honors the KB's configured targets/exclude note set.

Metadata

Metadata

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions