@williamthorsen/kb 0.6.2 → 0.7.0

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 (76) hide show
  1. package/README.md +120 -7
  2. package/dist/esm/check/check.d.ts +24 -0
  3. package/dist/esm/check/enumerate.d.ts +37 -0
  4. package/dist/esm/check/enumerate.js +12 -4
  5. package/dist/esm/check/glob-segments.d.ts +6 -0
  6. package/dist/esm/cli/commands/check.d.ts +22 -0
  7. package/dist/esm/cli/commands/create.d.ts +19 -1
  8. package/dist/esm/cli/commands/create.js +2 -0
  9. package/dist/esm/cli/commands/scaffold.d.ts +30 -0
  10. package/dist/esm/cli/commands/scaffold.js +108 -0
  11. package/dist/esm/cli/commands/set-default.d.ts +15 -0
  12. package/dist/esm/cli/commands/taxonomy.d.ts +18 -0
  13. package/dist/esm/cli/format.d.ts +21 -0
  14. package/dist/esm/cli/parse-flag-value.d.ts +5 -0
  15. package/dist/esm/cli/resolve-store.d.ts +12 -0
  16. package/dist/esm/cli/run.d.ts +9 -1
  17. package/dist/esm/cli/run.js +5 -0
  18. package/dist/esm/cli/select-kb-prompt.d.ts +18 -0
  19. package/dist/esm/cli/targeting/resolve-changed-paths.d.ts +10 -0
  20. package/dist/esm/cli/targeting/resolve-changed-paths.js +7 -33
  21. package/dist/esm/cli/targeting/select-notes.d.ts +13 -0
  22. package/dist/esm/cli/targeting/select-notes.js +4 -3
  23. package/dist/esm/config/config-schema.d.ts +12 -0
  24. package/dist/esm/config/kb-loader-error.d.ts +8 -0
  25. package/dist/esm/config/load-config.d.ts +7 -0
  26. package/dist/esm/config/note-scope.d.ts +13 -0
  27. package/dist/esm/create/create.d.ts +25 -0
  28. package/dist/esm/create/create.js +8 -12
  29. package/dist/esm/create/index.d.ts +0 -1
  30. package/dist/esm/create/index.js +0 -1
  31. package/dist/esm/discovery/find-kb-root.d.ts +4 -0
  32. package/dist/esm/discovery/kb-registry-schema.d.ts +4 -0
  33. package/dist/esm/discovery/load-registry.d.ts +23 -0
  34. package/dist/esm/discovery/register-store.d.ts +11 -0
  35. package/dist/esm/discovery/registry-document.d.ts +5 -0
  36. package/dist/esm/discovery/set-default-kb.d.ts +12 -0
  37. package/dist/esm/filesystem/exists.d.ts +13 -0
  38. package/dist/esm/filesystem/write-atomic.d.ts +5 -0
  39. package/dist/esm/frontmatter/parse-note.d.ts +9 -0
  40. package/dist/esm/git/list-git-scope.d.ts +15 -0
  41. package/dist/esm/git/list-git-scope.js +22 -0
  42. package/dist/esm/git/run-git.d.ts +17 -0
  43. package/dist/esm/git/run-git.js +22 -0
  44. package/dist/esm/layout/index.d.ts +1 -1
  45. package/dist/esm/layout/index.js +1 -1
  46. package/dist/esm/layout/store-layout.d.ts +20 -0
  47. package/dist/esm/layout/store-layout.js +2 -0
  48. package/dist/esm/lints/paths.d.ts +7 -0
  49. package/dist/esm/lints/tag-alias.d.ts +6 -0
  50. package/dist/esm/lints/taxonomy.d.ts +15 -0
  51. package/dist/esm/note-io/field-validators.d.ts +9 -0
  52. package/dist/esm/note-io/read-note.d.ts +7 -0
  53. package/dist/esm/note-io/write-note.d.ts +9 -0
  54. package/dist/esm/note-io/yaml-fields.d.ts +5 -0
  55. package/dist/esm/records/assertion.d.ts +4 -0
  56. package/dist/esm/records/event.d.ts +12 -0
  57. package/dist/esm/scaffold/index.d.ts +2 -0
  58. package/dist/esm/scaffold/index.js +2 -0
  59. package/dist/esm/scaffold/render-seeds.d.ts +16 -0
  60. package/dist/esm/scaffold/render-seeds.js +63 -0
  61. package/dist/esm/scaffold/scaffold.d.ts +23 -0
  62. package/dist/esm/scaffold/scaffold.js +35 -0
  63. package/dist/esm/tags/canonicalize.d.ts +8 -0
  64. package/dist/esm/tags/load-aliases.d.ts +10 -0
  65. package/dist/esm/taxonomy/domain-paths.d.ts +10 -0
  66. package/dist/esm/taxonomy/load-taxonomy.d.ts +8 -0
  67. package/dist/esm/taxonomy/taxonomy-schema.d.ts +19 -0
  68. package/dist/esm/taxonomy/write-taxonomy.d.ts +20 -0
  69. package/dist/esm/type-guards.d.ts +13 -0
  70. package/dist/esm/types.d.ts +41 -0
  71. package/dist/esm/vault-integrity/build-vault-index.d.ts +11 -0
  72. package/dist/esm/vault-integrity/check-vault-integrity.d.ts +13 -0
  73. package/dist/esm/vault-integrity/wikilink-parse.d.ts +22 -0
  74. package/package.json +9 -3
  75. package/dist/esm/create/render-seeds.d.ts +0 -2
  76. package/dist/esm/create/render-seeds.js +0 -29
@@ -1,51 +1,92 @@
1
+ /** A knowledge-base root: the directory holding a `.kb/`, and that `.kb/` itself. */
1
2
  export interface KbRoot {
3
+ /** Absolute path to the directory containing the `.kb/` folder. */
2
4
  path: string;
5
+ /** Absolute path to the `.kb/` directory itself. */
3
6
  kbDir: string;
4
7
  }
8
+ /** A single knowledge base declared in a `kb.yaml` registry, normalized in memory. */
5
9
  export interface KbRegistryEntry {
10
+ /** The KB's name, lifted from the `kbs` map key. */
6
11
  name: string;
12
+ /** Absolute path to the KB's root directory (tilde expanded, relative resolved). */
7
13
  path: string;
14
+ /** Optional human-readable description. */
8
15
  description?: string;
16
+ /** Whether the KB is read-only. */
9
17
  readonly?: boolean;
18
+ /** Which registry the entry came from. */
10
19
  source: 'user' | 'project';
11
20
  }
21
+ /** The merged, normalized KB registry. */
12
22
  export interface KbRegistry {
23
+ /** All KB entries, user entries merged with project overrides. */
13
24
  entries: KbRegistryEntry[];
25
+ /** The entry named by `default_kb`, resolved against `entries`; absent when `default_kb` is unset. */
14
26
  defaultKb?: KbRegistryEntry;
27
+ /** Absolute paths of the registry files that contributed entries. */
15
28
  sources: {
16
29
  user?: string;
17
30
  project?: string;
18
31
  };
19
32
  }
33
+ /** Strongly-typed frontmatter for a note. */
20
34
  export interface Frontmatter {
21
35
  title: string;
36
+ /** The stored record-type discriminant (e.g. `assertion`, `event`). */
22
37
  recordType: string;
38
+ /** Second-precision UTC timestamp (`YYYY-MM-DDTHH:MM:SSZ`); bare legacy `YYYY-MM-DD` dates remain valid. */
23
39
  created: string;
40
+ /** Second-precision UTC timestamp (`YYYY-MM-DDTHH:MM:SSZ`); bare legacy `YYYY-MM-DD` dates remain valid. */
24
41
  updated: string;
25
42
  tags: string[];
43
+ /** Optional and unknown fields, preserved through round-trip in insertion order. */
26
44
  extra: Record<string, unknown>;
27
45
  }
46
+ /** The raw frontmatter slice plus parse diagnostics, kept so rules can report at source line numbers. */
28
47
  export interface FrontmatterRaw {
48
+ /** The YAML text between the opening and closing `---` fences. */
29
49
  text: string;
50
+ /** 1-based line of the opening `---` fence. */
30
51
  startLine: number;
52
+ /** 1-based line of the closing `---` fence. */
31
53
  endLine: number;
54
+ /** YAML parse error message, if the block could not be parsed. */
32
55
  parseError?: string;
33
56
  }
57
+ /** A note parsed into frontmatter and body. */
34
58
  export interface ParsedNote {
59
+ /** Path or label the note was parsed from. */
35
60
  path: string;
61
+ /** The full original note content. */
36
62
  content: string;
63
+ /** Typed frontmatter, or `null` when no frontmatter block is present or it failed to parse. */
37
64
  frontmatter: Frontmatter | null;
65
+ /** Raw frontmatter slice and diagnostics, or `null` when no `---` block is present. */
38
66
  frontmatterRaw: FrontmatterRaw | null;
67
+ /** The note body (everything after the closing `---`). */
39
68
  body: string;
69
+ /** 1-based line where the body begins. */
40
70
  bodyStartLine: number;
41
71
  }
72
+ /** Severity of a validation finding. */
42
73
  export type FindingSeverity = 'error' | 'warning';
74
+ /** A single validation finding produced by a rule. */
43
75
  export interface Finding {
76
+ /** Path or label the finding applies to: a note, or the store file that declares the rule's subject. */
44
77
  path: string;
78
+ /**
79
+ * What the finding describes, defaulting to `note` when absent. A note-scoped finding is dropped when a run's
80
+ * selection excludes its note; a vault-scoped one describes the store itself, so it survives every selection,
81
+ * including one matching no notes at all.
82
+ */
45
83
  scope?: 'note' | 'vault';
84
+ /** 1-based source line number, when known. */
46
85
  line?: number;
86
+ /** Rule code, e.g. `frontmatter.required`. */
47
87
  rule: string;
48
88
  severity: FindingSeverity;
49
89
  message: string;
50
90
  }
91
+ /** A lowercase-keyed map from tag alias to its canonical form. */
51
92
  export type AliasMap = ReadonlyMap<string, string>;
@@ -1,4 +1,15 @@
1
+ /**
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.
5
+ */
1
6
  export type VaultIndex = ReadonlyMap<string, ReadonlySet<string>>;
7
+ /**
8
+ * 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
11
+ * vault-relative or absolute.
12
+ */
2
13
  export declare function buildVaultIndex(notes: readonly {
3
14
  path: string;
4
15
  }[]): VaultIndex;
@@ -1,7 +1,20 @@
1
1
  import type { Finding } from '../types.js';
2
+ /** A note reduced to what vault integrity inspects: its path, its body, and the file line the body begins on. */
2
3
  export interface VaultIntegrityNote {
4
+ /** Path or label the note was read from; used as the index value and the finding path. */
3
5
  path: string;
6
+ /** The note body (everything after the frontmatter block). */
4
7
  body: string;
8
+ /** 1-based file line where the body begins, so link findings report file-absolute lines. */
5
9
  bodyStartLine: number;
6
10
  }
11
+ /**
12
+ * Checks whole-vault integrity over a type-blind note set: unresolved `[[link]]` targets and basename collisions.
13
+ * Projects no records and reads no frontmatter — a note is just its path and body.
14
+ *
15
+ * A `[[Target]]` whose basename resolves to zero notes is an error (`wikilinks.unresolved`), reported at its
16
+ * file-absolute line. A basename shared by two or more notes is a single vault-wide warning (`wikilinks.basename`),
17
+ * reported once per basename independent of whether any link references it. An ambiguous link (a basename that several
18
+ * notes share) is not flagged per-link — the vault-wide basename warning subsumes it.
19
+ */
7
20
  export declare function checkVaultIntegrity(notes: readonly VaultIntegrityNote[]): Finding[];
@@ -1,7 +1,29 @@
1
+ /**
2
+ * Match `[[Target]]` and `![[Target]]` (embeds). A backslash-escaped `\[[…]]` is excluded. Scan the body so that
3
+ * frontmatter wikilink-looking text (e.g. inside a description) is not flagged.
4
+ */
1
5
  export declare const WIKILINK: RegExp;
6
+ /** Counts the newlines in `text` before byte offset `upTo`, used to locate a match's source line. */
2
7
  export declare function countNewlines(text: string, upTo: number): number;
8
+ /**
9
+ * Strips `|alias` and `#anchor` from a wikilink inner string and returns the target. Returns `null` for intra-doc
10
+ * links like `[[#heading]]`, which carry no target.
11
+ */
3
12
  export declare function extractTarget(inner: string): string | null;
13
+ /** Whether a target carries a known non-Markdown extension (an embed the vault index cannot resolve). */
4
14
  export declare function hasNonMarkdownExtension(target: string): boolean;
15
+ /** Reduces a wikilink target to the basename key the vault index is keyed on (drops any directory prefix and `.md`). */
5
16
  export declare function lookupKey(target: string): string;
17
+ /**
18
+ * Replaces the content of fenced code blocks with spaces so wikilink-shaped text inside code (e.g., a bash
19
+ * `[[ -n "$x" ]]` conditional) is not flagged. Offsets and line counts are preserved by substituting same-length
20
+ * whitespace.
21
+ */
6
22
  export declare function maskFencedCode(body: string): string;
23
+ /**
24
+ * Replaces inline backtick spans (e.g., TOML `[[plugins]]` mentioned in prose) with same-length whitespace so
25
+ * wikilink-shaped text inside inline code is not flagged. Matches single or multi-backtick runs whose content
26
+ * contains no backticks or newlines — the common case; complex spans with embedded backticks fall through and are
27
+ * still parsed for wikilinks.
28
+ */
7
29
  export declare function maskInlineCode(body: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/kb",
3
- "version": "0.6.2",
3
+ "version": "0.7.0",
4
4
  "description": "Knowledge-base foundation: discovery, config, frontmatter parsing, records, tags, and vault-integrity checks",
5
5
  "keywords": [
6
6
  "frontmatter",
@@ -72,6 +72,11 @@
72
72
  "types": "./dist/esm/records/index.d.ts",
73
73
  "import": "./dist/esm/records/index.js"
74
74
  },
75
+ "./scaffold": {
76
+ "source": "./src/scaffold/index.ts",
77
+ "types": "./dist/esm/scaffold/index.d.ts",
78
+ "import": "./dist/esm/scaffold/index.js"
79
+ },
75
80
  "./tags": {
76
81
  "source": "./src/tags/index.ts",
77
82
  "types": "./dist/esm/tags/index.d.ts",
@@ -97,15 +102,16 @@
97
102
  "dist"
98
103
  ],
99
104
  "dependencies": {
100
- "@williamthorsen/toolbelt.errors": "0.6.3",
105
+ "@williamthorsen/toolbelt.errors": "0.7.0",
101
106
  "picomatch": "4.0.7",
102
107
  "yaml": "2.9.0",
103
- "zod": "4.4.3"
108
+ "zod": "4.5.4"
104
109
  },
105
110
  "devDependencies": {
106
111
  "@types/node": "24.13.3",
107
112
  "@types/picomatch": "4.0.3",
108
113
  "eslint": "10.9.1",
114
+ "prettier": "3.9.6",
109
115
  "vitest": "4.1.11"
110
116
  },
111
117
  "engines": {
@@ -1,2 +0,0 @@
1
- export declare function renderAliasesSeed(): string;
2
- export declare function renderConfigSeed(): string;
@@ -1,29 +0,0 @@
1
- import { stringify } from 'yaml';
2
- import { defaultKbConfig } from "../config/config-schema.js";
3
- const ALIASES_HEADER = `# Tag aliases for this knowledge store.
4
- #
5
- # Map each canonical tag to the aliases that should resolve to it, for example:
6
- # aliases:
7
- # typescript: [ts, type-script]
8
- # The \`aliases:\` key is required even when empty.
9
- `;
10
- const CONFIG_HEADER = `# Check configuration for this knowledge store.
11
- #
12
- # Both keys are optional and fall back to the defaults shown below; an absent file uses these defaults too. Uncomment
13
- # and edit to override. \`targets\` selects which notes \`kb check\` enumerates and \`exclude\` removes matches;
14
- # patterns are slash-separated and relative to the store root.
15
- #
16
- `;
17
- export function renderAliasesSeed() {
18
- return `${ALIASES_HEADER}aliases: {}\n`;
19
- }
20
- export function renderConfigSeed() {
21
- return `${CONFIG_HEADER}${commentBlock(stringify(defaultKbConfig))}\n`;
22
- }
23
- function commentBlock(text) {
24
- return text
25
- .trimEnd()
26
- .split('\n')
27
- .map((line) => (line === '' ? '#' : `# ${line}`))
28
- .join('\n');
29
- }