You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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;
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/excludepicomatch 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.
Problem
kb-retrievedefines "a note" differently fromkb checkandkb-curate. The recall helper runs ripgrep with hardcoded globs (*.md,!.kb/**) over the whole KB root, ignoring the KB's configuredtargets/exclude. As a result it:README.md,CHANGELOG.md) that thetargetsglob would exclude;excluded paths (e.g. a draft) thatkb checkomits;kb check/kb-curatefor 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 checkandkb-curateenumerate notes throughenumerateNotes, which applies the KB'stargets/excludeglobs (defaultcontent/**/*.md) aspicomatchpredicates (dot:false) against each file's KB-root-relative path.kb-retrieveshares 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-addis intentional and stays: a writer is the authority on placement and hardcodescontent/assertions/, whereas a reader must honor whatever the KB declares its note set to be.Proposed solution
Centralize the
targets/excludenote-set definition in one shared predicate, and havekb-retrieveapply it.createNoteScopeMatcher(config)helper in@codeassembly/kbthat builds thetargets/excludepicomatchpredicates once and exposesisTarget/isExcluded/isNote.enumerateNotesconsumes it so enumeration and recall share one definition.kb-retrieveloads each in-scope KB's config and post-filters ripgrep's hits throughisNote(relativePath), keeping ripgrep's existing root-level*.mdsearch.Apply the same predicate
kb checkuses — 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
enumerateNotesis 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
targets/excludenote-set definition is shared betweenkb check's enumeration andkb-retrieve— one source of truth, not duplicated.kb-retrieverecalls only notes matching the KB's configuredtargets/exclude— the same definitionkb checkuses — not every markdown file under the root.kb-retrievedoes not recall non-note markdown under the root or underexcluded paths.Should have
kb-retrieve's SKILL.md states that recall honors the KB's configuredtargets/excludenote set.