@williamthorsen/kb 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +101 -96
  2. package/bin/kb.js +2 -4
  3. package/dist/esm/check/check.d.ts +14 -12
  4. package/dist/esm/check/check.js +41 -1
  5. package/dist/esm/check/enumerate.d.ts +13 -16
  6. package/dist/esm/check/glob-segments.d.ts +1 -1
  7. package/dist/esm/check/resolve-foreign-stores.d.ts +25 -0
  8. package/dist/esm/check/resolve-foreign-stores.js +50 -0
  9. package/dist/esm/cli/commands/check.d.ts +4 -10
  10. package/dist/esm/cli/commands/check.js +8 -3
  11. package/dist/esm/cli/commands/create.d.ts +3 -7
  12. package/dist/esm/cli/commands/create.js +1 -1
  13. package/dist/esm/cli/commands/scaffold.d.ts +5 -9
  14. package/dist/esm/cli/commands/scaffold.js +5 -5
  15. package/dist/esm/cli/commands/set-default.d.ts +1 -5
  16. package/dist/esm/cli/commands/set-default.js +1 -1
  17. package/dist/esm/cli/commands/taxonomy.d.ts +5 -10
  18. package/dist/esm/cli/commands/taxonomy.js +10 -9
  19. package/dist/esm/cli/format.d.ts +8 -10
  20. package/dist/esm/cli/resolve-store.d.ts +8 -8
  21. package/dist/esm/cli/run.d.ts +4 -6
  22. package/dist/esm/cli/run.js +1 -1
  23. package/dist/esm/cli/select-kb-prompt.d.ts +6 -5
  24. package/dist/esm/cli/select-kb-prompt.js +1 -1
  25. package/dist/esm/cli/targeting/resolve-changed-paths.d.ts +3 -3
  26. package/dist/esm/cli/targeting/select-notes.d.ts +2 -2
  27. package/dist/esm/config/config-schema.d.ts +24 -6
  28. package/dist/esm/config/config-schema.js +9 -0
  29. package/dist/esm/config/index.d.ts +1 -1
  30. package/dist/esm/config/index.js +1 -1
  31. package/dist/esm/config/kb-loader-error.d.ts +3 -3
  32. package/dist/esm/config/load-config.d.ts +3 -3
  33. package/dist/esm/config/load-config.js +2 -1
  34. package/dist/esm/config/note-scope.d.ts +7 -7
  35. package/dist/esm/create/create.d.ts +8 -8
  36. package/dist/esm/discovery/kb-registry-schema.d.ts +0 -2
  37. package/dist/esm/discovery/load-registry.d.ts +7 -9
  38. package/dist/esm/discovery/load-registry.js +1 -1
  39. package/dist/esm/discovery/register-store.d.ts +3 -4
  40. package/dist/esm/discovery/register-store.js +2 -2
  41. package/dist/esm/discovery/registry-document.d.ts +2 -2
  42. package/dist/esm/discovery/set-default-kb.d.ts +5 -5
  43. package/dist/esm/discovery/set-default-kb.js +3 -3
  44. package/dist/esm/filesystem/exists.d.ts +4 -4
  45. package/dist/esm/frontmatter/parse-note.d.ts +3 -3
  46. package/dist/esm/git/list-git-scope.d.ts +7 -7
  47. package/dist/esm/git/run-git.d.ts +2 -2
  48. package/dist/esm/layout/store-layout.d.ts +5 -5
  49. package/dist/esm/lints/paths.d.ts +1 -1
  50. package/dist/esm/lints/paths.js +1 -1
  51. package/dist/esm/lints/tag-alias.d.ts +1 -1
  52. package/dist/esm/lints/tag-alias.js +1 -1
  53. package/dist/esm/lints/taxonomy.d.ts +9 -8
  54. package/dist/esm/lints/taxonomy.js +2 -2
  55. package/dist/esm/note-io/field-validators.d.ts +1 -1
  56. package/dist/esm/note-io/read-note.d.ts +2 -2
  57. package/dist/esm/note-io/write-note.d.ts +3 -6
  58. package/dist/esm/records/event.d.ts +3 -3
  59. package/dist/esm/scaffold/render-seeds.d.ts +3 -3
  60. package/dist/esm/scaffold/render-seeds.js +5 -3
  61. package/dist/esm/scaffold/scaffold.d.ts +7 -8
  62. package/dist/esm/tags/load-aliases.d.ts +3 -4
  63. package/dist/esm/taxonomy/domain-paths.d.ts +6 -6
  64. package/dist/esm/taxonomy/load-taxonomy.d.ts +3 -3
  65. package/dist/esm/taxonomy/load-taxonomy.js +2 -2
  66. package/dist/esm/taxonomy/taxonomy-schema.d.ts +5 -6
  67. package/dist/esm/taxonomy/write-taxonomy.d.ts +7 -8
  68. package/dist/esm/type-guards.d.ts +1 -1
  69. package/dist/esm/types.d.ts +6 -9
  70. package/dist/esm/vault-integrity/build-vault-index.d.ts +3 -4
  71. package/dist/esm/vault-integrity/check-vault-integrity.d.ts +46 -12
  72. package/dist/esm/vault-integrity/check-vault-integrity.js +59 -20
  73. package/dist/esm/vault-integrity/index.d.ts +2 -2
  74. package/dist/esm/vault-integrity/index.js +2 -2
  75. package/dist/esm/vault-integrity/wikilink-parse.d.ts +45 -19
  76. package/dist/esm/vault-integrity/wikilink-parse.js +37 -9
  77. package/package.json +6 -6
@@ -1,10 +1,7 @@
1
1
  import type { KbConfig } from '../config/config-schema.js';
2
- /**
3
- * A note reduced to the fields the check pipeline and curate consume: its paths, its frontmatter field map, its body
4
- * and body-start line (for file-absolute link lines), its full content (for the paths lint), and any parse error.
5
- */
2
+ /** A note read and parsed once, so that every check in a run shares the result. */
6
3
  export interface EnumeratedNote {
7
- /** Absolute path the note was read from. */
4
+ /** Absolute path from which the note was read. */
8
5
  path: string;
9
6
  /** The note's path relative to the KB root, slash-separated. */
10
7
  relativePath: string;
@@ -22,9 +19,10 @@ export interface EnumeratedNote {
22
19
  /**
23
20
  * Walks a KB root and returns the KB-root-relative path of every note {@link enumerateNotes} selects, opening none of
24
21
  * them. Scope selection runs through the same matcher and the same pruning, so a caller that needs only the note set's
25
- * shape which folders hold notes, and how many sees exactly what the check pipeline admits.
22
+ * shape (which folders contain notes, and how many) sees exactly what the check pipeline admits.
26
23
  *
27
- * A note whose content cannot be read still contributes its path here, where `enumerateNotes` drops it with a warning.
24
+ * A note whose content cannot be read still contributes its path here, whereas `enumerateNotes` drops it with a
25
+ * warning.
28
26
  */
29
27
  export declare function enumerateNotePaths(input: {
30
28
  kbRoot: string;
@@ -34,20 +32,19 @@ export declare function enumerateNotePaths(input: {
34
32
  * Walks a KB root and parses every note whose KB-root-relative path matches a `config.targets` glob and no
35
33
  * `config.exclude` glob into an {@link EnumeratedNote}.
36
34
  *
37
- * Matching uses `picomatch` with `dot:false`, so dot-prefixed directories (`.kb`, `.git`, `.agents`) are excluded
35
+ * Because matching uses `picomatch` with `dot:false`, dot-prefixed directories (`.kb`, `.git`, `.agents`) are excluded
38
36
  * implicitly without naming them in `exclude`. The walk prunes the tree to each target's leading literal segment
39
37
  * (`content/**` descends only into `content/`); a target with no leading literal (e.g. `**\/*.md`) falls back to a
40
- * full walk. Excludes are honored during descent so an excluded subtree is never entered.
38
+ * full walk. Excludes are honored during descent so that an excluded subtree is never entered.
41
39
  *
42
- * Where the store sits in a git working tree, scope narrows further to what git accounts for: tracked notes plus
43
- * untracked ones that no ignore rule covers. A note that the repository ignores is therefore neither enumerated nor available
40
+ * If the store is in a git working tree, the enumeration keeps only the notes that git tracks and the untracked
41
+ * notes that no ignore rule covers. A note that the repository ignores is therefore neither enumerated nor available
44
42
  * as a wikilink target, so a link pointing at one resolves to nothing. A store outside a working tree, or a machine
45
- * carrying no git, keeps the walk's own scope.
43
+ * with no git, keeps what the walk alone found.
46
44
  *
47
- * Notes with malformed or absent frontmatter are kept `readNoteContent` records the parse error in `error` and
48
- * returns an empty field map rather than throwing, so they remain valid wikilink targets. A note that cannot be read,
49
- * or a directory that cannot be listed, is skipped with a `kb:` stderr warning rather than aborting the walk. Each
50
- * note's `path` is absolute; `relativePath` is the slash-separated path from the KB root.
45
+ * Notes with malformed or absent frontmatter are kept: `readNoteContent` records the parse error in `error` and
46
+ * returns an empty field map rather than throwing, so that they remain valid wikilink targets. A note that cannot be
47
+ * read, or a directory that cannot be listed, is skipped with a `kb:` stderr warning rather than aborting the walk.
51
48
  */
52
49
  export declare function enumerateNotes(input: {
53
50
  kbRoot: string;
@@ -3,6 +3,6 @@ export declare function isGlobSegment(segment: string): boolean;
3
3
  /**
4
4
  * Returns the leading run of literal (non-glob) segments of a slash-separated pattern, slash-joined. A pattern whose
5
5
  * first segment is a glob yields the empty string; a fully literal pattern yields itself. Locates the deepest concrete
6
- * path a glob is anchored to, e.g. `content/notes/**` yields `content/notes`.
6
+ * path to which a glob is anchored, e.g. `content/notes/**` yields `content/notes`.
7
7
  */
8
8
  export declare function leadingLiteralPrefix(pattern: string): string;
@@ -0,0 +1,25 @@
1
+ import { type StoreVisibility } from '../config/config-schema.js';
2
+ import type { KbRegistry } from '../types.js';
3
+ import type { ForeignStore } from '../vault-integrity/check-vault-integrity.js';
4
+ /**
5
+ * Collects the distinct store names that a note set's wikilinks qualify, so that a check run consults only the stores
6
+ * that its own links name. It reads {@link scanWikilinks}, the same walk that later evaluates the links, so a
7
+ * store-shaped prefix inside a code sample selects no store and the two cannot disagree on what counts as a qualified
8
+ * link.
9
+ */
10
+ export declare function collectStorePrefixes(notes: readonly {
11
+ body: string;
12
+ }[]): Set<string>;
13
+ /**
14
+ * Resolves each store name that a run's links qualify against the merged registry, reading only note paths and each
15
+ * store's own `.kb/config.yaml`: A foreign store is enumerated under its own `targets`/`exclude` and its own
16
+ * repository's ignore rules, as it would be under its own check run, and no foreign note is opened.
17
+ *
18
+ * A store that cannot be read (absent from this machine, or with a config file that will not load) resolves
19
+ * `unavailable` rather than throwing, so that one unrelated store cannot fail the run.
20
+ */
21
+ export declare function resolveForeignStores(input: {
22
+ prefixes: Iterable<string>;
23
+ registry: KbRegistry;
24
+ sourceVisibility: StoreVisibility;
25
+ }): Promise<Map<string, ForeignStore>>;
@@ -0,0 +1,50 @@
1
+ import { stat } from 'node:fs/promises';
2
+ import { describeError } from '@williamthorsen/toolbelt.errors';
3
+ import { isAtLeastAsShareable } from "../config/config-schema.js";
4
+ import { loadKbConfig } from "../config/load-config.js";
5
+ import { resolveKbDir } from "../layout/index.js";
6
+ import { buildVaultIndex } from "../vault-integrity/build-vault-index.js";
7
+ import { scanWikilinks } from "../vault-integrity/wikilink-parse.js";
8
+ import { enumerateNotePaths } from "./enumerate.js";
9
+ export function collectStorePrefixes(notes) {
10
+ const prefixes = new Set();
11
+ for (const note of notes) {
12
+ for (const { store } of scanWikilinks(note.body)) {
13
+ if (store !== undefined)
14
+ prefixes.add(store);
15
+ }
16
+ }
17
+ return prefixes;
18
+ }
19
+ export async function resolveForeignStores(input) {
20
+ const resolved = new Map();
21
+ for (const prefix of input.prefixes) {
22
+ resolved.set(prefix, await resolveOne(prefix, input.registry, input.sourceVisibility));
23
+ }
24
+ return resolved;
25
+ }
26
+ async function resolveOne(prefix, registry, sourceVisibility) {
27
+ const entry = registry.entries.find((candidate) => candidate.name === prefix);
28
+ if (entry === undefined)
29
+ return { status: 'unknown' };
30
+ try {
31
+ const stats = await stat(entry.path);
32
+ if (!stats.isDirectory())
33
+ return { status: 'unavailable', reason: `${entry.path} is not a directory` };
34
+ }
35
+ catch (error) {
36
+ return { status: 'unavailable', reason: `${entry.path} could not be read: ${describeError(error)}` };
37
+ }
38
+ let config;
39
+ try {
40
+ config = await loadKbConfig({ kbRoot: { path: entry.path, kbDir: resolveKbDir(entry.path) } });
41
+ }
42
+ catch (error) {
43
+ return { status: 'unavailable', reason: describeError(error) };
44
+ }
45
+ if (!isAtLeastAsShareable({ source: sourceVisibility, target: config.visibility })) {
46
+ return { status: 'disallowed', visibility: config.visibility };
47
+ }
48
+ const paths = await enumerateNotePaths({ kbRoot: entry.path, config });
49
+ return { status: 'resolved', index: buildVaultIndex(paths.map((path) => ({ path }))) };
50
+ }
@@ -1,32 +1,26 @@
1
- /** The outcome of a command run: the exit code plus the streams to write. */
2
1
  export interface CommandOutput {
3
2
  /** Process exit code: 0 clean, 1 error-severity findings, 2 usage/config error. */
4
3
  exitCode: 0 | 1 | 2;
5
4
  stdout: string;
6
5
  stderr: string;
7
6
  }
8
- /** Usage text for `kb check`. */
9
- export declare const CHECK_HELP = "Usage: kb check [paths...] [options]\n\nValidate notes in a knowledge base against its tag aliases and cross-note\nlink and path rules. With no path arguments, every note is checked.\nCross-note rules always resolve against the whole vault.\n\nTargeting (mutually exclusive):\n [paths...] Check only the notes matching the given glob patterns, files,\n or directories. Quote globs so kb expands them itself. A\n directory checks every note beneath it. A path that matches no\n note is a usage error unless it names a real non-note.\n --vs <ref> Check only the notes changed between the working tree and the\n merge-base of <ref> and HEAD: follows renames, includes\n uncommitted edits, excludes deletions.\n\nOptions:\n --kb <name> Check the named store from the kb.yaml registry. Without it,\n the nearest ancestor .kb/ directory is used.\n --json Emit a JSON report instead of human-readable output.\n -h, --help Show this help.\n\nExit codes:\n 0 no error-severity findings in the checked notes (warnings allowed)\n 1 one or more error-severity findings in the checked notes\n 2 usage error, unresolvable store or --vs ref, a path matching no note, or\n malformed config or aliases\n";
7
+ export declare const CHECK_HELP = "Usage: kb check [paths...] [options]\n\nValidate notes in a knowledge base against its tag aliases and cross-note\nlink and path rules. With no path arguments, every note is checked.\nCross-note rules always resolve against the whole store; a [[store:Target]]\nlink resolves against the store named by its prefix in the kb.yaml registry.\n\nTargeting (mutually exclusive):\n [paths...] Check only the notes matching the given glob patterns, files,\n or directories. Quote globs so that kb expands them itself. A\n directory checks every note beneath it. A path that matches no\n note is a usage error unless it names a real non-note.\n --vs <ref> Check only the notes changed between the working tree and the\n merge-base of <ref> and HEAD: follows renames, includes\n uncommitted edits, excludes deletions.\n\nOptions:\n --kb <name> Check the named store from the kb.yaml registry. Without it,\n the nearest ancestor .kb/ directory is used.\n --json Emit a JSON report instead of human-readable output.\n -h, --help Show this help.\n\nExit codes:\n 0 no error-severity findings in the checked notes (warnings allowed)\n 1 one or more error-severity findings in the checked notes\n 2 usage error, unresolvable store or --vs ref, a path matching no note, or\n malformed config or aliases\n";
10
8
  /**
11
9
  * Runs `kb check`: parses options, resolves the store, runs the shared `check`, and formats the report.
12
10
  *
13
- * Store resolution composes the package's own exports inline `findKbRoot` for the default ancestor-walk and
14
- * `tryLoadKbRegistry` for an explicit `--kb <name>`. The lookup is read-only, so a store's registry `readonly` flag
15
- * is ignored. A malformed `.kb/config.yaml`/`tag-aliases.yaml` surfaces as a `KbLoaderError` from `check`, which maps
16
- * to exit 2; any other error from `check` propagates to the caller as a real crash.
11
+ * The command writes nothing to the store, so it ignores the registry's `readonly` flag. `check` throws a
12
+ * `KbLoaderError` for a structural defect in a store file that it loads, and the command maps that error to exit 2;
13
+ * any other error from `check` propagates to the caller as a real crash.
17
14
  */
18
15
  export declare function runCheck(input: {
19
16
  argv: readonly string[];
20
17
  cwd: string;
21
18
  home?: string;
22
19
  }): Promise<CommandOutput>;
23
- /** Parsed `kb check` options. */
24
20
  interface CheckOptions {
25
21
  /** Explicit store name from `--kb`, or `null` for ancestor-walk discovery. */
26
22
  kb: string | null;
27
- /** Whether `--json` was supplied. */
28
23
  json: boolean;
29
- /** Whether `--help`/`-h` was supplied. */
30
24
  help: boolean;
31
25
  /** Positional glob/path/directory arguments selecting which notes to check; empty for a whole-vault run. */
32
26
  patterns: string[];
@@ -10,11 +10,12 @@ export const CHECK_HELP = `Usage: kb check [paths...] [options]
10
10
 
11
11
  Validate notes in a knowledge base against its tag aliases and cross-note
12
12
  link and path rules. With no path arguments, every note is checked.
13
- Cross-note rules always resolve against the whole vault.
13
+ Cross-note rules always resolve against the whole store; a [[store:Target]]
14
+ link resolves against the store named by its prefix in the kb.yaml registry.
14
15
 
15
16
  Targeting (mutually exclusive):
16
17
  [paths...] Check only the notes matching the given glob patterns, files,
17
- or directories. Quote globs so kb expands them itself. A
18
+ or directories. Quote globs so that kb expands them itself. A
18
19
  directory checks every note beneath it. A path that matches no
19
20
  note is a usage error unless it names a real non-note.
20
21
  --vs <ref> Check only the notes changed between the working tree and the
@@ -55,7 +56,11 @@ export async function runCheck(input) {
55
56
  const store = resolved.store;
56
57
  let result;
57
58
  try {
58
- result = await check({ kbRoot: store.path });
59
+ result = await check({
60
+ kbRoot: store.path,
61
+ cwd: input.cwd,
62
+ ...(input.home !== undefined && { home: input.home }),
63
+ });
59
64
  }
60
65
  catch (error) {
61
66
  if (isKbLoaderError(error)) {
@@ -1,13 +1,12 @@
1
1
  import type { SelectKbPrompt } from '../select-kb-prompt.js';
2
2
  import type { CommandOutput } from './check.js';
3
- /** Usage text for `kb create`. */
4
- export declare const CREATE_HELP = "Usage: kb create [options]\n\nScaffold a new knowledge base in the current directory and register it in the user-global kb.yaml registry.\n\nRegistering leaves the registry's entries in alphabetical order, preserving its comments and formatting.\n\nWhen the registry has no default knowledge base, the new store becomes the default.\nIf other knowledge bases are already registered, you are prompted to choose one (or set it later with \"kb set-default\").\n\nCreates:\n .editorconfig editor and formatter settings (width, indent, line endings)\n .kb/config.yaml check configuration (commented; defaults apply)\n .kb/tag-aliases.yaml tag-alias map (empty)\n .prettierrc.yaml formatting configuration (commented)\n content/, content/events/\n\nOptions:\n --description <text> Description for the registry entry; cannot be combined with --no-register.\n --name <name> Registry name for the store. Defaults to the directory name.\n --no-register Scaffold without writing the kb.yaml registry entry.\n -h, --help Show this help.\n\nExit codes:\n 0 store created\n 2 usage error, an existing .kb/ in the directory, or an already-registered name\n";
3
+ export declare const CREATE_HELP = "Usage: kb create [options]\n\nScaffold a new knowledge base in the current directory and register it in the user-global kb.yaml registry.\n\nRegistering leaves the registry's entries in alphabetical order, preserving its comments and formatting.\n\nWhen the registry has no default knowledge base, the new store becomes the default.\nIf other knowledge bases are already registered, the command prompts for a choice (or \"kb set-default\" sets one later).\n\nCreates:\n .editorconfig editor and formatter settings (width, indent, line endings)\n .kb/config.yaml check configuration (commented; defaults apply)\n .kb/tag-aliases.yaml tag-alias map (empty)\n .prettierrc.yaml formatting configuration (commented)\n content/, content/events/\n\nOptions:\n --description <text> Description for the registry entry; cannot be combined with --no-register.\n --name <name> Registry name for the store. Defaults to the directory name.\n --no-register Scaffold without writing the kb.yaml registry entry.\n -h, --help Show this help.\n\nExit codes:\n 0 store created\n 2 usage error, an existing .kb/ in the directory, or an already-registered name\n";
5
4
  /**
6
5
  * Runs `kb create`: parses options, scaffolds a store in `cwd`, and (unless `--no-register`) registers it in the
7
- * user-global `~/.agents/kb.yaml`. After registering, it ensures a default knowledge base: the new store becomes the
6
+ * user-global `~/.agents/kb.yaml`. After registering, it ensures a default knowledge base: The new store becomes the
8
7
  * default when none is set and it is the only KB; when other KBs already exist with no default, it delegates to
9
8
  * `kb set-default`'s picker (or, with no `selectKb` on a non-interactive stdin, points the user there). A precondition
10
- * failure from `create` an existing `.kb/` or an already-registered name maps to exit 2; a genuine I/O error
9
+ * failure from `create` (an existing `.kb/` or an already-registered name) maps to exit 2; a genuine I/O error
11
10
  * propagates to the caller.
12
11
  */
13
12
  export declare function runCreate(input: {
@@ -16,15 +15,12 @@ export declare function runCreate(input: {
16
15
  home?: string;
17
16
  selectKb?: SelectKbPrompt;
18
17
  }): Promise<CommandOutput>;
19
- /** Parsed `kb create` options. */
20
18
  interface CreateOptions {
21
19
  /** Description from `--description`, or `null` to write the entry without one. */
22
20
  description: string | null;
23
21
  /** Explicit registry name from `--name`, or `null` to default to the directory name. */
24
22
  name: string | null;
25
- /** Whether `--no-register` was supplied. */
26
23
  noRegister: boolean;
27
- /** Whether `--help`/`-h` was supplied. */
28
24
  help: boolean;
29
25
  }
30
26
  /**
@@ -11,7 +11,7 @@ Scaffold a new knowledge base in the current directory and register it in the us
11
11
  Registering leaves the registry's entries in alphabetical order, preserving its comments and formatting.
12
12
 
13
13
  When the registry has no default knowledge base, the new store becomes the default.
14
- If other knowledge bases are already registered, you are prompted to choose one (or set it later with "kb set-default").
14
+ If other knowledge bases are already registered, the command prompts for a choice (or "kb set-default" sets one later).
15
15
 
16
16
  Creates:
17
17
  .editorconfig editor and formatter settings (width, indent, line endings)
@@ -1,23 +1,19 @@
1
1
  import type { CommandOutput } from './check.js';
2
- /** Usage text for `kb scaffold`. */
3
- export declare const SCAFFOLD_HELP = "Usage: kb scaffold [options]\n\nWrite into an existing knowledge base any canonical file that it lacks, so a store\ncreated before a given file existed can acquire it. An existing file is left\nuntouched unless --force is given.\n\nWrites:\n .editorconfig editor and formatter settings (width, indent, line endings)\n .kb/config.yaml check configuration (commented; defaults apply)\n .kb/tag-aliases.yaml tag-alias map (empty)\n .prettierrc.yaml formatting configuration (commented)\n content/, content/events/\n\n.kb/taxonomy.yaml is not part of this set: \"kb taxonomy init\" derives it from\nthe notes that the store already holds. Use \"kb create\" to make a new store.\n\nOptions:\n --force Replace an existing canonical file with a fresh seed. A\n directory has no content to replace and is left as it is.\n --kb <name> Use the named store from the kb.yaml registry. Without it, the\n nearest ancestor .kb/ directory is used.\n -h, --help Show this help.\n\nExit codes:\n 0 every canonical file is present, whether it was written or already there\n 2 usage error, unresolvable store, a store marked readonly in kb.yaml, or a\n resolved path holding no .kb/\n";
2
+ export declare const SCAFFOLD_HELP = "Usage: kb scaffold [options]\n\nWrite into an existing knowledge base any canonical file that it lacks, so that\na store created before a given file existed can acquire it. An existing file is\nleft untouched unless --force is given.\n\nWrites:\n .editorconfig editor and formatter settings (width, indent, line endings)\n .kb/config.yaml check configuration (commented; defaults apply)\n .kb/tag-aliases.yaml tag-alias map (empty)\n .prettierrc.yaml formatting configuration (commented)\n content/, content/events/\n\n.kb/taxonomy.yaml is not part of this set: \"kb taxonomy init\" derives it from\nthe notes that the store already contains. Use \"kb create\" to make a new store.\n\nOptions:\n --force Replace an existing canonical file with a fresh seed. A\n directory has no content to replace and is left as it is.\n --kb <name> Use the named store from the kb.yaml registry. Without it, the\n nearest ancestor .kb/ directory is used.\n -h, --help Show this help.\n\nExit codes:\n 0 every canonical file is present, whether it was written or already there\n 2 usage error, unresolvable store, a store marked readonly in kb.yaml, or a\n resolved path containing no .kb/\n";
4
3
  /**
5
- * Runs `kb scaffold`: parses options, resolves the store, and writes the canonical files it lacks.
4
+ * Runs `kb scaffold`: parses options, resolves the store, and writes the canonical files that it lacks.
6
5
  *
7
- * Store resolution matches `kb check`. A store the registry marks `readonly` is refused, as `kb taxonomy init` does.
8
- * A resolved path holding no `.kb/` is refused too: the command back-fills a store rather than creating one, and a
9
- * registry entry names a path without proving a store is there.
6
+ * A store that the registry marks `readonly` is refused. A resolved path containing no `.kb/` is refused too: The
7
+ * command back-fills a store rather than creating one, and a registry entry names a path without proving a store is
8
+ * there.
10
9
  */
11
10
  export declare function runScaffold(input: {
12
11
  argv: readonly string[];
13
12
  cwd: string;
14
13
  home?: string;
15
14
  }): Promise<CommandOutput>;
16
- /** Parsed `kb scaffold` options. */
17
15
  interface ScaffoldOptions {
18
- /** Whether `--force` was supplied. */
19
16
  force: boolean;
20
- /** Whether `--help`/`-h` was supplied. */
21
17
  help: boolean;
22
18
  /** Explicit store name from `--kb`, or `null` for ancestor-walk discovery. */
23
19
  kb: string | null;
@@ -6,9 +6,9 @@ import { takeInlineValue, takeValue } from "../parse-flag-value.js";
6
6
  import { resolveStore } from "../resolve-store.js";
7
7
  export const SCAFFOLD_HELP = `Usage: kb scaffold [options]
8
8
 
9
- Write into an existing knowledge base any canonical file that it lacks, so a store
10
- created before a given file existed can acquire it. An existing file is left
11
- untouched unless --force is given.
9
+ Write into an existing knowledge base any canonical file that it lacks, so that
10
+ a store created before a given file existed can acquire it. An existing file is
11
+ left untouched unless --force is given.
12
12
 
13
13
  Writes:
14
14
  .editorconfig editor and formatter settings (width, indent, line endings)
@@ -18,7 +18,7 @@ Writes:
18
18
  content/, content/events/
19
19
 
20
20
  .kb/taxonomy.yaml is not part of this set: "kb taxonomy init" derives it from
21
- the notes that the store already holds. Use "kb create" to make a new store.
21
+ the notes that the store already contains. Use "kb create" to make a new store.
22
22
 
23
23
  Options:
24
24
  --force Replace an existing canonical file with a fresh seed. A
@@ -30,7 +30,7 @@ Options:
30
30
  Exit codes:
31
31
  0 every canonical file is present, whether it was written or already there
32
32
  2 usage error, unresolvable store, a store marked readonly in kb.yaml, or a
33
- resolved path holding no ${KB_DIR}/
33
+ resolved path containing no ${KB_DIR}/
34
34
  `;
35
35
  export async function runScaffold(input) {
36
36
  let options;
@@ -1,7 +1,6 @@
1
1
  import type { SelectKbPrompt } from '../select-kb-prompt.js';
2
2
  import type { CommandOutput } from './check.js';
3
- /** Usage text for `kb set-default`. */
4
- export declare const SET_DEFAULT_HELP = "Usage: kb set-default [name] [options]\n\nSet, clear, or interactively choose the user-global default knowledge base \u2014\nthe top-level default_kb pointer in ~/.agents/kb.yaml.\n\n kb set-default <name> Set default_kb to the named registered KB.\n kb set-default --none Clear default_kb.\n kb set-default List the registered KBs and prompt for a choice\n (including a \"(none)\" option to clear).\n\nOptions:\n --none Clear the default knowledge base.\n -h, --help Show this help.\n\nExit codes:\n 0 default set or cleared, or the selection was cancelled\n 2 usage error, an unregistered name, no registered KBs, or no name supplied\n when stdin is not interactive\n";
3
+ export declare const SET_DEFAULT_HELP = "Usage: kb set-default [name] [options]\n\nSet, clear, or interactively choose the user-global default knowledge base:\nthe top-level default_kb pointer in ~/.agents/kb.yaml.\n\n kb set-default <name> Set default_kb to the named registered KB.\n kb set-default --none Clear default_kb.\n kb set-default List the registered KBs and prompt for a choice\n (including a \"(none)\" option to clear).\n\nOptions:\n --none Clear the default knowledge base.\n -h, --help Show this help.\n\nExit codes:\n 0 default set or cleared, or the selection was cancelled\n 2 usage error, an unregistered name, no registered KBs, or no name supplied\n when stdin is not interactive\n";
5
4
  /**
6
5
  * Runs `kb set-default`: sets, clears, or interactively selects the user-global `default_kb`. Resolution reads the
7
6
  * user-global registry only (no project overlay), so the chosen default resolves in every project context. The picker
@@ -13,13 +12,10 @@ export declare function runSetDefault(input: {
13
12
  home?: string;
14
13
  selectKb?: SelectKbPrompt;
15
14
  }): Promise<CommandOutput>;
16
- /** Parsed `kb set-default` options. */
17
15
  interface SetDefaultOptions {
18
16
  /** The positional KB name, or `null` when none was supplied (interactive form). */
19
17
  name: string | null;
20
- /** Whether `--none` was supplied. */
21
18
  none: boolean;
22
- /** Whether `--help`/`-h` was supplied. */
23
19
  help: boolean;
24
20
  }
25
21
  /**
@@ -5,7 +5,7 @@ import { tryLoadKbRegistry } from "../../discovery/load-registry.js";
5
5
  import { clearDefaultKb, setDefaultKb } from "../../discovery/set-default-kb.js";
6
6
  export const SET_DEFAULT_HELP = `Usage: kb set-default [name] [options]
7
7
 
8
- Set, clear, or interactively choose the user-global default knowledge base
8
+ Set, clear, or interactively choose the user-global default knowledge base:
9
9
  the top-level default_kb pointer in ~/.agents/kb.yaml.
10
10
 
11
11
  kb set-default <name> Set default_kb to the named registered KB.
@@ -1,12 +1,11 @@
1
1
  import type { CommandOutput } from './check.js';
2
- /** Usage text for `kb taxonomy`. */
3
- export declare const TAXONOMY_HELP = "Usage: kb taxonomy init [options]\n\nDerive a starting taxonomy from the notes a knowledge base already holds, so a\ntaxonomy can be introduced to a populated store without every folder reporting\nas undeclared. Every folder holding notes is declared, along with each of its\nancestors, under \"provisional:\" with no description: the command cannot invent\ndescriptions, and provisional already means \"declared, not yet reviewed\".\n\nOptions:\n --kb <name> Use the named store from the kb.yaml registry. Without it, the\n nearest ancestor .kb/ directory is used.\n --merge Add only the domains an existing taxonomy does not declare.\n Without it, a store that already has a taxonomy is left\n untouched.\n -h, --help Show this help.\n\nExit codes:\n 0 the taxonomy was written, or already declared every derived domain\n 2 usage error, unresolvable store, a store marked readonly in kb.yaml,\n malformed config or taxonomy, or an existing taxonomy without --merge\n";
2
+ export declare const TAXONOMY_HELP = "Usage: kb taxonomy init [options]\n\nDerive a starting taxonomy from the notes that a knowledge base already\ncontains, so that a taxonomy can be introduced to a populated store without\nevery folder reporting as undeclared. Every folder containing notes is\ndeclared, along with each of its ancestors, under \"provisional:\" with no\ndescription: The command cannot invent descriptions, and provisional already\nmeans \"declared, not yet reviewed\".\n\nOptions:\n --kb <name> Use the named store from the kb.yaml registry. Without it, the\n nearest ancestor .kb/ directory is used.\n --merge Add only the domains that an existing taxonomy does not\n declare. Without it, a store that already has a taxonomy is\n left untouched.\n -h, --help Show this help.\n\nExit codes:\n 0 the taxonomy was written, or already declared every derived domain\n 2 usage error, unresolvable store, a store marked readonly in kb.yaml,\n malformed config or taxonomy, or an existing taxonomy without --merge\n";
4
3
  /**
5
- * Runs `kb taxonomy`: parses options, resolves the store, derives the domains its notes imply, and declares them.
4
+ * Runs `kb taxonomy`: parses options, resolves the store, derives the domains implied by its notes, and declares them.
6
5
  *
7
- * The derivation reads the same enumeration `kb check` does, so a store back-filled by this command reports no
8
- * taxonomy drift. A store the registry marks `readonly` is refused, matching `kb-curate --apply`. A malformed
9
- * `.kb/config.yaml` or `.kb/taxonomy.yaml` surfaces as a `KbLoaderError` and maps to exit 2; any other error
6
+ * The derivation reads the same enumeration as `kb check`, so a store back-filled by this command reports no
7
+ * taxonomy drift. A store that the registry marks `readonly` is refused. The loaders throw a `KbLoaderError` for a
8
+ * malformed `.kb/config.yaml` or `.kb/taxonomy.yaml`, and the command maps that error to exit 2; any other error
10
9
  * propagates to the caller as a real crash.
11
10
  */
12
11
  export declare function runTaxonomy(input: {
@@ -14,15 +13,11 @@ export declare function runTaxonomy(input: {
14
13
  cwd: string;
15
14
  home?: string;
16
15
  }): Promise<CommandOutput>;
17
- /** Parsed `kb taxonomy` options. */
18
16
  interface TaxonomyOptions {
19
- /** The subcommand to run, or `null` when none was given. */
20
17
  subcommand: 'init' | null;
21
18
  /** Explicit store name from `--kb`, or `null` for ancestor-walk discovery. */
22
19
  kb: string | null;
23
- /** Whether `--merge` was supplied. */
24
20
  merge: boolean;
25
- /** Whether `--help`/`-h` was supplied. */
26
21
  help: boolean;
27
22
  }
28
23
  /**
@@ -10,18 +10,19 @@ import { takeInlineValue, takeValue } from "../parse-flag-value.js";
10
10
  import { resolveStore } from "../resolve-store.js";
11
11
  export const TAXONOMY_HELP = `Usage: kb taxonomy init [options]
12
12
 
13
- Derive a starting taxonomy from the notes a knowledge base already holds, so a
14
- taxonomy can be introduced to a populated store without every folder reporting
15
- as undeclared. Every folder holding notes is declared, along with each of its
16
- ancestors, under "provisional:" with no description: the command cannot invent
17
- descriptions, and provisional already means "declared, not yet reviewed".
13
+ Derive a starting taxonomy from the notes that a knowledge base already
14
+ contains, so that a taxonomy can be introduced to a populated store without
15
+ every folder reporting as undeclared. Every folder containing notes is
16
+ declared, along with each of its ancestors, under "provisional:" with no
17
+ description: The command cannot invent descriptions, and provisional already
18
+ means "declared, not yet reviewed".
18
19
 
19
20
  Options:
20
21
  --kb <name> Use the named store from the kb.yaml registry. Without it, the
21
22
  nearest ancestor .kb/ directory is used.
22
- --merge Add only the domains an existing taxonomy does not declare.
23
- Without it, a store that already has a taxonomy is left
24
- untouched.
23
+ --merge Add only the domains that an existing taxonomy does not
24
+ declare. Without it, a store that already has a taxonomy is
25
+ left untouched.
25
26
  -h, --help Show this help.
26
27
 
27
28
  Exit codes:
@@ -117,7 +118,7 @@ async function initTaxonomy(input) {
117
118
  const notes = await enumerateNotes({ kbRoot: kbRoot.path, config });
118
119
  const domains = deriveDomains(notes.map((note) => note.relativePath));
119
120
  if (domains.length === 0) {
120
- return { exitCode: 0, stdout: `no assertion folders hold notes; ${TAXONOMY_FILE} not written\n`, stderr: '' };
121
+ return { exitCode: 0, stdout: `no assertion folders contain notes; ${TAXONOMY_FILE} not written\n`, stderr: '' };
121
122
  }
122
123
  const { added } = await writeTaxonomy({
123
124
  kbRoot,
@@ -1,5 +1,5 @@
1
1
  import type { Finding } from '../types.js';
2
- /** A resolved store's identity, surfaced in both human and JSON output. */
2
+ /** A resolved store's identity, shown in both human and JSON output. */
3
3
  export interface StoreRef {
4
4
  /** The store's display name, or `null` for a `.kb/`-discovered store with no registry entry. */
5
5
  name: string | null;
@@ -10,23 +10,21 @@ export interface StoreRef {
10
10
  export interface CheckSummary {
11
11
  /** Notes enumerated and checked. */
12
12
  notes: number;
13
- /** Total findings. */
14
13
  total: number;
15
- /** Findings with `severity: 'error'`. */
16
14
  errors: number;
17
- /** Findings with `severity: 'warning'`. */
18
15
  warnings: number;
19
16
  }
20
17
  /** Which selection produced a report, controlling the wording of the zero-match line. */
21
18
  export type CheckScope = 'vault' | 'patterns' | 'vs';
22
19
  /**
23
- * Renders the default human output. Findings are grouped by file in path order, each line reading
24
- * `<severity> <rule> (line N): message`. A clean run (notes checked, no findings) prints `✓ no findings (N notes
25
- * checked)`; a run that checked nothing prints a zero-match line worded for its `scope` (naming the config targets for
26
- * a whole-vault run, and a scope-appropriate line for a targeted one) without the `✓`, since no check ran.
20
+ * Renders the default human output. Findings are grouped by file, in the order in which each file first appears, each
21
+ * line reading `<severity> <rule> (line N): message`. A clean run (notes checked, no findings) prints
22
+ * `✓ no findings (N notes checked)`; a run that checked nothing prints a zero-match line worded for its `scope` (naming
23
+ * the config targets for a whole-vault run, and a scope-appropriate line for a targeted one) without the `✓`, since no
24
+ * check ran.
27
25
  *
28
- * A run can check no notes and still carry vault-scoped findings, which describe the store rather than any note. The
29
- * zero-match line then heads the report instead of replacing it: it explains why no note was checked, and the findings
26
+ * A run can check no notes and still include vault-scoped findings, which describe the store rather than any note. The
27
+ * zero-match line then heads the report instead of replacing it: It explains why no note was checked, and the findings
30
28
  * follow.
31
29
  */
32
30
  export declare function formatHuman(input: {
@@ -9,15 +9,15 @@ export type ResolveStoreOutcome = {
9
9
  message: string;
10
10
  };
11
11
  /**
12
- * Resolves the store a command runs against. An explicit `--kb <name>` is looked up in the merged registry
13
- * (`tryLoadKbRegistry` with `projectDir: cwd`, so project-local `.agents/kb.yaml` entries join the user-global
14
- * registry); without a flag, the nearest ancestor `.kb/` directory is used. An unknown `--kb` name or a missing `.kb/`
15
- * fails for exit 2.
12
+ * Resolves the store against which a command runs. An explicit `--kb <name>` is looked up in the merged registry
13
+ * (`tryLoadKbRegistry` with `projectDir: cwd`, so the registry includes project-local `.agents/kb.yaml` entries as
14
+ * well as user-global ones); without a flag, the nearest ancestor `.kb/` directory is used. An unknown `--kb` name or
15
+ * a missing `.kb/` fails for exit 2.
16
16
  *
17
- * The registry's `readonly` flag is reported rather than enforced: a command that writes into the store refuses on it,
18
- * and a read-only command ignores it. It is kept off {@link StoreRef}, which carries the identity a report renders. A
19
- * discovered store is cross-referenced against the registry by path, so a vault marked readonly is reported as such
20
- * however it was named; one with no registry entry has no metadata to consult and is reported writable.
17
+ * The registry's `readonly` flag is reported rather than enforced: A command that writes into the store refuses on it,
18
+ * and a read-only command ignores it. It is kept off {@link StoreRef}, which contains the identity that a report
19
+ * renders. A discovered store is cross-referenced against the registry by path, so a vault marked readonly is reported
20
+ * as such however it was named; one with no registry entry has no metadata to consult and is reported writable.
21
21
  */
22
22
  export declare function resolveStore(input: {
23
23
  explicitKb: string | null;
@@ -1,13 +1,11 @@
1
1
  import { type CommandOutput } from './commands/check.js';
2
2
  import type { SelectKbPrompt } from './select-kb-prompt.js';
3
- /** Top-level usage text for the `kb` bin. */
4
- export declare const HELP = "Usage: kb <command> [options]\n\nCommands:\n check Validate a knowledge base, optionally scoped to selected notes.\n create Scaffold a new knowledge base and register it in the kb.yaml registry.\n scaffold Write into an existing knowledge base any canonical file that it lacks.\n set-default Set, clear, or choose the default knowledge base.\n taxonomy Derive a knowledge base's taxonomy from the notes it already holds.\n\nRun \"kb <command> --help\" for command options.\n";
3
+ export declare const HELP = "Usage: kb <command> [options]\n\nCommands:\n check Validate a knowledge base, optionally scoped to selected notes.\n create Scaffold a new knowledge base and register it in the kb.yaml registry.\n scaffold Write into an existing knowledge base any canonical file that it lacks.\n set-default Set, clear, or choose the default knowledge base.\n taxonomy Derive a knowledge base's taxonomy from the notes that it already contains.\n\nRun \"kb <command> --help\" for command options.\n";
5
4
  /**
6
5
  * Dispatches a `kb` subcommand and returns its {@link CommandOutput} without touching `process`, so tests drive the
7
- * command directly. `check`, `create`, `scaffold`, `set-default`, and `taxonomy` are the subcommands; a bare
8
- * invocation or `--help`/`-h` prints top-level usage (exit 0), and an unknown command prints usage to stderr (exit 2).
9
- * The optional `selectKb` picker is forwarded to `set-default`'s interactive form and to `create`'s ambiguous
10
- * default-KB prompt; `cli/index.ts` supplies it only when stdin is a TTY.
6
+ * command directly. A bare invocation or `--help`/`-h` prints top-level usage (exit 0), and an unknown command prints
7
+ * usage to stderr (exit 2). The optional `selectKb` picker is forwarded to `set-default`'s interactive form and to
8
+ * `create`'s ambiguous default-KB prompt.
11
9
  */
12
10
  export declare function run(input: {
13
11
  argv: readonly string[];
@@ -10,7 +10,7 @@ Commands:
10
10
  create Scaffold a new knowledge base and register it in the kb.yaml registry.
11
11
  scaffold Write into an existing knowledge base any canonical file that it lacks.
12
12
  set-default Set, clear, or choose the default knowledge base.
13
- taxonomy Derive a knowledge base's taxonomy from the notes it already holds.
13
+ taxonomy Derive a knowledge base's taxonomy from the notes that it already contains.
14
14
 
15
15
  Run "kb <command> --help" for command options.
16
16
  `;
@@ -9,8 +9,9 @@ export type SelectKbChoice = {
9
9
  kind: 'cancel';
10
10
  };
11
11
  /**
12
- * Presents the registered KBs and resolves the user's choice. Injected into `runSetDefault` so the dispatcher itself
13
- * stays free of terminal I/O and remains directly testable; the real implementation is {@link readlineSelectKbPrompt}.
12
+ * Presents the registered KBs and resolves the user's choice. A command takes it as an injected dependency, so that the
13
+ * command stays free of terminal I/O and remains directly testable; the real implementation is
14
+ * {@link readlineSelectKbPrompt}.
14
15
  */
15
16
  export type SelectKbPrompt = (input: {
16
17
  entries: readonly KbRegistryEntry[];
@@ -18,7 +19,8 @@ export type SelectKbPrompt = (input: {
18
19
  }) => Promise<SelectKbChoice>;
19
20
  /**
20
21
  * Renders the numbered selection list: each registered KB (marking the current default) followed by a trailing
21
- * `(none)` option numbered `entries.length + 1`. When no default is set, `(none)` carries the current marker instead.
22
+ * `(none)` option numbered `entries.length + 1`. When no default is set, the current marker appears on `(none)`
23
+ * instead.
22
24
  */
23
25
  export declare function formatKbSelection(entries: readonly KbRegistryEntry[], currentDefaultName?: string): string;
24
26
  /**
@@ -28,7 +30,6 @@ export declare function formatKbSelection(entries: readonly KbRegistryEntry[], c
28
30
  export declare function parseSelection(answer: string, kbCount: number): SelectKbChoice | null;
29
31
  /**
30
32
  * A readline-backed {@link SelectKbPrompt}: it prints the selection list, reads a line, and re-prompts until the answer
31
- * resolves to a choice. This is the feature's sole interactive seam — `cli/index.ts` supplies it only when stdin is a
32
- * TTY, and other commands (e.g. `kb create`) can reuse it for their own interactive default-KB selection.
33
+ * resolves to a choice.
33
34
  */
34
35
  export declare const readlineSelectKbPrompt: SelectKbPrompt;
@@ -7,7 +7,7 @@ export function formatKbSelection(entries, currentDefaultName) {
7
7
  lines.push(` ${String(index + 1)}) ${entry.name}${suffix}`);
8
8
  }
9
9
  const noneSuffix = currentDefaultName === undefined ? ' (current)' : '';
10
- lines.push(` ${String(entries.length + 1)}) (none) no default${noneSuffix}`);
10
+ lines.push(` ${String(entries.length + 1)}) (none): no default${noneSuffix}`);
11
11
  return `${lines.join('\n')}\n`;
12
12
  }
13
13
  export function parseSelection(answer, kbCount) {
@@ -11,9 +11,9 @@ export type ChangedPathsResult = {
11
11
  *
12
12
  * The change set is `git diff` of the working tree against `merge-base(ref, HEAD)` with `--diff-filter=AMR`, so it
13
13
  * follows renames (reporting the destination), includes uncommitted edits to tracked files, and excludes deletions.
14
- * Git emits toplevel-relative paths and resolves symlinks, so each path is rebased onto the real store root — a no-op
15
- * when the store is the repository root, correct when it is nested. A git failure (unknown ref, not a repository)
16
- * returns `{ ok: false }` for the caller to surface as a usage error rather than throwing.
14
+ * Because git emits toplevel-relative paths and resolves symlinks, the function rebases each path onto the real store
15
+ * root: a no-op when the store is the repository root, correct when it is nested. A git failure (unknown ref, not a
16
+ * repository) returns `{ ok: false }` for the caller to report as a usage error rather than throwing.
17
17
  */
18
18
  export declare function resolveChangedPaths(input: {
19
19
  storeRoot: string;
@@ -3,7 +3,7 @@ import type { EnumeratedNote } from '../../check/enumerate.js';
3
3
  export interface SelectionResult {
4
4
  /** Notes matched by at least one pattern, in enumeration order, deduplicated. */
5
5
  selected: EnumeratedNote[];
6
- /** Patterns that matched no validatable note and are backed by no real on-disk path likely typos. */
6
+ /** Patterns that matched no validatable note and are backed by no real on-disk path: likely typos. */
7
7
  unmatched: string[];
8
8
  }
9
9
  /**
@@ -14,7 +14,7 @@ export interface SelectionResult {
14
14
  * `targets`/`exclude` filtering is inherited and a quoted glob behaves the same as a shell-expanded one. A bare
15
15
  * directory expands to its subtree. A pattern matching no note is reported in `unmatched` unless a real on-disk path
16
16
  * backs it (a non-validatable file such as a README, an excluded subtree, or an empty directory), in which case it is
17
- * dropped silently distinguishing a typo from a legitimately out-of-scope target.
17
+ * dropped silently, which distinguishes a typo from a legitimately out-of-scope target.
18
18
  */
19
19
  export declare function selectNotes(input: {
20
20
  notes: readonly EnumeratedNote[];