@williamthorsen/kb 0.8.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 (69) hide show
  1. package/README.md +66 -82
  2. package/bin/kb.js +2 -4
  3. package/dist/esm/check/check.d.ts +9 -17
  4. package/dist/esm/check/enumerate.d.ts +12 -15
  5. package/dist/esm/check/glob-segments.d.ts +1 -1
  6. package/dist/esm/check/resolve-foreign-stores.d.ts +9 -8
  7. package/dist/esm/cli/commands/check.d.ts +4 -10
  8. package/dist/esm/cli/commands/check.js +2 -2
  9. package/dist/esm/cli/commands/create.d.ts +3 -7
  10. package/dist/esm/cli/commands/create.js +1 -1
  11. package/dist/esm/cli/commands/scaffold.d.ts +5 -9
  12. package/dist/esm/cli/commands/scaffold.js +5 -5
  13. package/dist/esm/cli/commands/set-default.d.ts +1 -5
  14. package/dist/esm/cli/commands/set-default.js +1 -1
  15. package/dist/esm/cli/commands/taxonomy.d.ts +5 -10
  16. package/dist/esm/cli/commands/taxonomy.js +10 -9
  17. package/dist/esm/cli/format.d.ts +8 -10
  18. package/dist/esm/cli/resolve-store.d.ts +8 -8
  19. package/dist/esm/cli/run.d.ts +4 -6
  20. package/dist/esm/cli/run.js +1 -1
  21. package/dist/esm/cli/select-kb-prompt.d.ts +6 -5
  22. package/dist/esm/cli/select-kb-prompt.js +1 -1
  23. package/dist/esm/cli/targeting/resolve-changed-paths.d.ts +3 -3
  24. package/dist/esm/cli/targeting/select-notes.d.ts +2 -2
  25. package/dist/esm/config/config-schema.d.ts +10 -9
  26. package/dist/esm/config/kb-loader-error.d.ts +3 -3
  27. package/dist/esm/config/load-config.d.ts +2 -2
  28. package/dist/esm/config/load-config.js +1 -1
  29. package/dist/esm/config/note-scope.d.ts +7 -7
  30. package/dist/esm/create/create.d.ts +8 -8
  31. package/dist/esm/discovery/kb-registry-schema.d.ts +0 -2
  32. package/dist/esm/discovery/load-registry.d.ts +7 -9
  33. package/dist/esm/discovery/load-registry.js +1 -1
  34. package/dist/esm/discovery/register-store.d.ts +3 -4
  35. package/dist/esm/discovery/register-store.js +2 -2
  36. package/dist/esm/discovery/registry-document.d.ts +2 -2
  37. package/dist/esm/discovery/set-default-kb.d.ts +5 -5
  38. package/dist/esm/discovery/set-default-kb.js +3 -3
  39. package/dist/esm/filesystem/exists.d.ts +4 -4
  40. package/dist/esm/frontmatter/parse-note.d.ts +3 -3
  41. package/dist/esm/git/list-git-scope.d.ts +6 -6
  42. package/dist/esm/git/run-git.d.ts +2 -2
  43. package/dist/esm/layout/store-layout.d.ts +5 -5
  44. package/dist/esm/lints/paths.d.ts +1 -1
  45. package/dist/esm/lints/paths.js +1 -1
  46. package/dist/esm/lints/tag-alias.d.ts +1 -1
  47. package/dist/esm/lints/tag-alias.js +1 -1
  48. package/dist/esm/lints/taxonomy.d.ts +9 -8
  49. package/dist/esm/lints/taxonomy.js +2 -2
  50. package/dist/esm/note-io/field-validators.d.ts +1 -1
  51. package/dist/esm/note-io/read-note.d.ts +2 -2
  52. package/dist/esm/note-io/write-note.d.ts +3 -6
  53. package/dist/esm/records/event.d.ts +3 -3
  54. package/dist/esm/scaffold/render-seeds.d.ts +3 -3
  55. package/dist/esm/scaffold/render-seeds.js +2 -2
  56. package/dist/esm/scaffold/scaffold.d.ts +7 -8
  57. package/dist/esm/tags/load-aliases.d.ts +3 -4
  58. package/dist/esm/taxonomy/domain-paths.d.ts +6 -6
  59. package/dist/esm/taxonomy/load-taxonomy.d.ts +3 -3
  60. package/dist/esm/taxonomy/load-taxonomy.js +2 -2
  61. package/dist/esm/taxonomy/taxonomy-schema.d.ts +5 -6
  62. package/dist/esm/taxonomy/write-taxonomy.d.ts +7 -8
  63. package/dist/esm/type-guards.d.ts +1 -1
  64. package/dist/esm/types.d.ts +6 -9
  65. package/dist/esm/vault-integrity/build-vault-index.d.ts +3 -4
  66. package/dist/esm/vault-integrity/check-vault-integrity.d.ts +13 -13
  67. package/dist/esm/vault-integrity/check-vault-integrity.js +1 -1
  68. package/dist/esm/vault-integrity/wikilink-parse.d.ts +21 -16
  69. package/package.json +5 -5
@@ -1,4 +1,4 @@
1
- /** A knowledge-base root: the directory holding a `.kb/`, and that `.kb/` itself. */
1
+ /** A knowledge-base root: the directory containing a `.kb/`, and that `.kb/` itself. */
2
2
  export interface KbRoot {
3
3
  /** Absolute path to the directory containing the `.kb/` folder. */
4
4
  path: string;
@@ -7,13 +7,11 @@ export interface KbRoot {
7
7
  }
8
8
  /** A single knowledge base declared in a `kb.yaml` registry, normalized in memory. */
9
9
  export interface KbRegistryEntry {
10
- /** The KB's name, lifted from the `kbs` map key. */
10
+ /** The KB's name, taken from the `kbs` map key. */
11
11
  name: string;
12
12
  /** Absolute path to the KB's root directory (tilde expanded, relative resolved). */
13
13
  path: string;
14
- /** Optional human-readable description. */
15
14
  description?: string;
16
- /** Whether the KB is read-only. */
17
15
  readonly?: boolean;
18
16
  /** Which registry the entry came from. */
19
17
  source: 'user' | 'project';
@@ -43,7 +41,7 @@ export interface Frontmatter {
43
41
  /** Optional and unknown fields, preserved through round-trip in insertion order. */
44
42
  extra: Record<string, unknown>;
45
43
  }
46
- /** The raw frontmatter slice plus parse diagnostics, kept so rules can report at source line numbers. */
44
+ /** The raw frontmatter slice plus parse diagnostics, kept so that rules can report at source line numbers. */
47
45
  export interface FrontmatterRaw {
48
46
  /** The YAML text between the opening and closing `---` fences. */
49
47
  text: string;
@@ -56,7 +54,7 @@ export interface FrontmatterRaw {
56
54
  }
57
55
  /** A note parsed into frontmatter and body. */
58
56
  export interface ParsedNote {
59
- /** Path or label the note was parsed from. */
57
+ /** Path or label from which the note was parsed. */
60
58
  path: string;
61
59
  /** The full original note content. */
62
60
  content: string;
@@ -69,11 +67,10 @@ export interface ParsedNote {
69
67
  /** 1-based line where the body begins. */
70
68
  bodyStartLine: number;
71
69
  }
72
- /** Severity of a validation finding. */
73
70
  export type FindingSeverity = 'error' | 'warning';
74
71
  /** A single validation finding produced by a rule. */
75
72
  export interface Finding {
76
- /** Path or label the finding applies to: a note, or the store file that declares the rule's subject. */
73
+ /** Path or label to which the finding applies: a note, or the store file that declares the rule's subject. */
77
74
  path: string;
78
75
  /**
79
76
  * What the finding describes, defaulting to `note` when absent. A note-scoped finding is dropped when a run's
@@ -83,7 +80,7 @@ export interface Finding {
83
80
  scope?: 'note' | 'vault';
84
81
  /** 1-based source line number, when known. */
85
82
  line?: number;
86
- /** Rule code, e.g. `frontmatter.required`. */
83
+ /** Rule code, e.g. `wikilinks.basename`. */
87
84
  rule: string;
88
85
  severity: FindingSeverity;
89
86
  message: string;
@@ -1,13 +1,12 @@
1
1
  /**
2
2
  * A vault-wide lookup from a note basename (without the `.md` extension) to the set of note paths that share it. A
3
- * single-path entry resolves a wikilink unambiguously; a multi-path entry is a basename collision. Consumed by the
4
- * vault-integrity checks and by curate's wikilink rewriter.
3
+ * single-path entry resolves a wikilink unambiguously; a multi-path entry is a basename collision.
5
4
  */
6
5
  export type VaultIndex = ReadonlyMap<string, ReadonlySet<string>>;
7
6
  /**
8
7
  * Builds a basename → set-of-paths index from a set of notes, mapping each note's `.md` basename (sans extension) to
9
- * the note paths that share it. Reads only each note's `path`, so it is type-blind it needs no frontmatter or record
10
- * projection. A note's `path` is used verbatim as the index value, so callers control whether entries are
8
+ * the note paths that share it. Reads only each note's `path`, so it is type-blind: It needs no frontmatter or record
9
+ * projection. Because a note's `path` is used verbatim as the index value, callers control whether entries are
11
10
  * vault-relative or absolute.
12
11
  */
13
12
  export declare function buildVaultIndex(notes: readonly {
@@ -3,19 +3,19 @@ import type { Finding } from '../types.js';
3
3
  import { type VaultIndex } from './build-vault-index.js';
4
4
  /**
5
5
  * Checks whole-vault integrity over a type-blind note set: unresolved `[[link]]` targets and basename collisions.
6
- * Projects no records and reads no frontmatter a note is just its path and body.
6
+ * Projects no records and reads no frontmatter: A note is just its path and body.
7
7
  *
8
8
  * A `[[Target]]` whose basename resolves to zero notes is an error (`wikilinks.unresolved`), reported at its
9
9
  * file-absolute line. A basename shared by two or more notes is a single vault-wide warning (`wikilinks.basename`),
10
10
  * reported once per basename independent of whether any link references it. An ambiguous link (a basename that several
11
- * notes share) is not flagged per-link the vault-wide basename warning subsumes it.
11
+ * notes share) is not flagged per-link: The vault-wide basename warning subsumes it.
12
12
  *
13
- * A `[[store:Target]]` resolves against `options.foreignStores` instead, and never joins this store's own basename
14
- * index, so the basename warning stays store-scoped. Without `options`, a qualified target is treated as a bare one,
15
- * which is the behavior every caller had before cross-store resolution existed.
13
+ * A `[[store:Target]]` resolves against `options.foreignStores` instead, and is never added to this store's own
14
+ * basename index, so the basename warning stays store-scoped. Without `options`, a qualified target is treated as a
15
+ * bare one.
16
16
  */
17
17
  export declare function checkVaultIntegrity(notes: readonly VaultIntegrityNote[], options?: VaultIntegrityOptions): Finding[];
18
- /** What a check run found when it looked up a store one of its links names. */
18
+ /** What a check run found when it looked up a store named by one of its links. */
19
19
  export type ForeignStore =
20
20
  /** The name matches no entry in the merged registry. */
21
21
  {
@@ -26,29 +26,29 @@ export type ForeignStore =
26
26
  status: 'unavailable';
27
27
  reason: string;
28
28
  }
29
- /** The store is less shareable than the source, so a link into it would widen disclosure. */
29
+ /** Because the store is less shareable than the source, a link into it would widen disclosure. */
30
30
  | {
31
31
  status: 'disallowed';
32
32
  visibility: StoreVisibility;
33
33
  }
34
- /** The store was read; `index` holds its basenames. */
34
+ /** The store was read; `index` contains its basenames. */
35
35
  | {
36
36
  status: 'resolved';
37
37
  index: VaultIndex;
38
38
  };
39
- /** A note reduced to what vault integrity inspects: its path, its body, and the file line the body begins on. */
39
+ /** A note reduced to what vault integrity inspects. */
40
40
  export interface VaultIntegrityNote {
41
- /** Path or label the note was read from; used as the index value and the finding path. */
41
+ /** Path or label from which the note was read; used as the index value and the finding path. */
42
42
  path: string;
43
43
  /** The note body (everything after the frontmatter block). */
44
44
  body: string;
45
- /** 1-based file line where the body begins, so link findings report file-absolute lines. */
45
+ /** 1-based file line where the body begins, so that link findings report file-absolute lines. */
46
46
  bodyStartLine: number;
47
47
  }
48
48
  /** What a run needs to evaluate a store-qualified link. */
49
49
  export interface VaultIntegrityOptions {
50
- /** What the run found for each store name its links qualify, keyed by that name. */
50
+ /** What the run found for each store name that qualifies one of its links, keyed by that name. */
51
51
  foreignStores: ReadonlyMap<string, ForeignStore>;
52
- /** The visibility of the store being checked, which decides the direction a qualified link may take. */
52
+ /** The visibility of the store being checked, which decides the direction that a qualified link may take. */
53
53
  sourceVisibility: StoreVisibility;
54
54
  }
@@ -43,7 +43,7 @@ function describeForeignDefect(store, target, options) {
43
43
  return {
44
44
  rule: 'wikilinks.disallowed-store',
45
45
  severity: 'error',
46
- message: `${link} targets "${store}", a ${foreignStore.visibility} store, which a ${options.sourceVisibility} store may not link into: the link discloses the target's title`,
46
+ message: `${link} targets "${store}", a ${foreignStore.visibility} store, which a ${options.sourceVisibility} store may not link into: The link discloses the target's title`,
47
47
  };
48
48
  }
49
49
  const resolved = foreignStore.index.get(lookupKey(target));
@@ -1,20 +1,25 @@
1
- /** Counts the newlines in `text` before byte offset `upTo`, used to locate a match's source line. */
1
+ /** Counts the newlines in `text` before string index `upTo`, used to locate a match's source line. */
2
2
  export declare function countNewlines(text: string, upTo: number): number;
3
3
  /**
4
4
  * Strips `|alias` and `#anchor` from a wikilink inner string and returns the target. Returns `null` for intra-doc
5
- * links like `[[#heading]]`, which carry no target.
5
+ * links like `[[#heading]]`, which have no target.
6
6
  */
7
7
  export declare function extractTarget(inner: string): string | null;
8
- /** Reduces a wikilink target to the basename key the vault index is keyed on (drops any directory prefix and `.md`). */
8
+ /**
9
+ * Reduces a wikilink target to the basename key on which the vault index is keyed (drops any directory prefix and
10
+ * `.md`).
11
+ */
9
12
  export declare function lookupKey(target: string): string;
10
- /** A wikilink target separated into the store it names, where it names one, and the target within that store. */
13
+ /** A wikilink target separated into the store that it names, when it names one, and the target within that store. */
11
14
  export interface QualifiedTarget {
12
- /** The store the link names, or `undefined` when the target is store-local. */
15
+ /** The store named by the link, or `undefined` when the target is store-local. */
13
16
  store?: string;
14
17
  /** The target with any store qualifier removed. */
15
18
  target: string;
16
19
  }
17
- /** One wikilink a body scan accepted, with its target already split into an optional store qualifier and a target. */
20
+ /**
21
+ * One wikilink accepted by a body scan, with its target already split into an optional store qualifier and a target.
22
+ */
18
23
  export interface ScannedWikilink {
19
24
  /** The whole matched link, including any `!` embed prefix. */
20
25
  match: string;
@@ -22,28 +27,28 @@ export interface ScannedWikilink {
22
27
  inner: string;
23
28
  /** Offset of the match within the body. */
24
29
  offset: number;
25
- /** The store the link names, or `undefined` when the target is store-local. */
30
+ /** The store named by the link, or `undefined` when the target is store-local. */
26
31
  store?: string;
27
32
  /** The target within that store, with alias, anchor, and any store qualifier stripped. */
28
33
  target: string;
29
34
  }
30
35
  /**
31
- * Walks a note body and yields every wikilink that carries a resolvable target: fenced and inline code are masked
36
+ * Scans a note body and yields every wikilink that has a resolvable target: fenced and inline code are masked
32
37
  * first, and backslash-escaped links, intra-doc anchors, and non-Markdown embeds are skipped. This is the single
33
38
  * definition of what counts as a link and what its target is, so a consumer that detects links and one that rewrites
34
39
  * them cannot drift apart on either question.
35
40
  *
36
- * `offset` indexes the body as passed in. Masking substitutes same-length whitespace, which this function asserts, so
37
- * a consumer may slice the unmasked body at the offsets yielded here. It also leaves every newline where it was, so a
38
- * consumer may count lines in the unmasked body at those offsets; nothing asserts that at runtime, so a masker that
39
- * moved a newline while keeping the length would shift reported line numbers rather than fail.
41
+ * `offset` indexes the body as passed in. Because masking substitutes same-length whitespace, which this function
42
+ * asserts, a consumer may slice the unmasked body at the offsets yielded here. It also leaves every newline where it
43
+ * was, which lets a consumer count lines in the unmasked body at those offsets. Nothing asserts that at runtime, so a
44
+ * masker that moved a newline while keeping the length would shift reported line numbers rather than fail.
40
45
  */
41
46
  export declare function scanWikilinks(body: string): Generator<ScannedWikilink>;
42
47
  /**
43
- * Separates a leading `store:` qualifier from a wikilink target, so `fde:Note title` names the note `Note title` in
44
- * the store `fde`. A qualifier is recognized only when the text before the first colon is non-empty and carries no
45
- * whitespace and no `/`, and something follows the colon; every other target passes through store-local, which leaves
46
- * a title that happens to contain a colon resolving as it always has.
48
+ * Separates a leading `store:` qualifier from a wikilink target: `fde:Note title` names the note `Note title` in the
49
+ * store `fde`. A qualifier is recognized only when the text before the first colon is non-empty and contains no
50
+ * whitespace and no `/`, and something follows the colon. Every other target stays store-local: A title such as
51
+ * `Release notes: v2` resolves within this store.
47
52
  *
48
53
  * Call it on the output of {@link extractTarget}, which has already stripped any alias and anchor.
49
54
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/kb",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Knowledge-base foundation: discovery, config, frontmatter parsing, records, tags, and vault-integrity checks",
5
5
  "keywords": [
6
6
  "frontmatter",
@@ -102,13 +102,13 @@
102
102
  "dist"
103
103
  ],
104
104
  "dependencies": {
105
- "@williamthorsen/toolbelt.errors": "0.7.0",
105
+ "@williamthorsen/toolbelt.errors": "0.8.1",
106
106
  "picomatch": "4.0.7",
107
- "yaml": "2.9.0",
108
- "zod": "4.5.4"
107
+ "yaml": "2.9.1",
108
+ "zod": "4.6.5"
109
109
  },
110
110
  "devDependencies": {
111
- "@types/node": "24.13.3",
111
+ "@types/node": "24.13.4",
112
112
  "@types/picomatch": "4.0.3",
113
113
  "eslint": "10.10.0",
114
114
  "prettier": "3.9.6",