@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.
- package/README.md +101 -96
- package/bin/kb.js +2 -4
- package/dist/esm/check/check.d.ts +14 -12
- package/dist/esm/check/check.js +41 -1
- package/dist/esm/check/enumerate.d.ts +13 -16
- package/dist/esm/check/glob-segments.d.ts +1 -1
- package/dist/esm/check/resolve-foreign-stores.d.ts +25 -0
- package/dist/esm/check/resolve-foreign-stores.js +50 -0
- package/dist/esm/cli/commands/check.d.ts +4 -10
- package/dist/esm/cli/commands/check.js +8 -3
- package/dist/esm/cli/commands/create.d.ts +3 -7
- package/dist/esm/cli/commands/create.js +1 -1
- package/dist/esm/cli/commands/scaffold.d.ts +5 -9
- package/dist/esm/cli/commands/scaffold.js +5 -5
- package/dist/esm/cli/commands/set-default.d.ts +1 -5
- package/dist/esm/cli/commands/set-default.js +1 -1
- package/dist/esm/cli/commands/taxonomy.d.ts +5 -10
- package/dist/esm/cli/commands/taxonomy.js +10 -9
- package/dist/esm/cli/format.d.ts +8 -10
- package/dist/esm/cli/resolve-store.d.ts +8 -8
- package/dist/esm/cli/run.d.ts +4 -6
- package/dist/esm/cli/run.js +1 -1
- package/dist/esm/cli/select-kb-prompt.d.ts +6 -5
- package/dist/esm/cli/select-kb-prompt.js +1 -1
- package/dist/esm/cli/targeting/resolve-changed-paths.d.ts +3 -3
- package/dist/esm/cli/targeting/select-notes.d.ts +2 -2
- package/dist/esm/config/config-schema.d.ts +24 -6
- package/dist/esm/config/config-schema.js +9 -0
- package/dist/esm/config/index.d.ts +1 -1
- package/dist/esm/config/index.js +1 -1
- package/dist/esm/config/kb-loader-error.d.ts +3 -3
- package/dist/esm/config/load-config.d.ts +3 -3
- package/dist/esm/config/load-config.js +2 -1
- package/dist/esm/config/note-scope.d.ts +7 -7
- package/dist/esm/create/create.d.ts +8 -8
- package/dist/esm/discovery/kb-registry-schema.d.ts +0 -2
- package/dist/esm/discovery/load-registry.d.ts +7 -9
- package/dist/esm/discovery/load-registry.js +1 -1
- package/dist/esm/discovery/register-store.d.ts +3 -4
- package/dist/esm/discovery/register-store.js +2 -2
- package/dist/esm/discovery/registry-document.d.ts +2 -2
- package/dist/esm/discovery/set-default-kb.d.ts +5 -5
- package/dist/esm/discovery/set-default-kb.js +3 -3
- package/dist/esm/filesystem/exists.d.ts +4 -4
- package/dist/esm/frontmatter/parse-note.d.ts +3 -3
- package/dist/esm/git/list-git-scope.d.ts +7 -7
- package/dist/esm/git/run-git.d.ts +2 -2
- package/dist/esm/layout/store-layout.d.ts +5 -5
- package/dist/esm/lints/paths.d.ts +1 -1
- package/dist/esm/lints/paths.js +1 -1
- package/dist/esm/lints/tag-alias.d.ts +1 -1
- package/dist/esm/lints/tag-alias.js +1 -1
- package/dist/esm/lints/taxonomy.d.ts +9 -8
- package/dist/esm/lints/taxonomy.js +2 -2
- package/dist/esm/note-io/field-validators.d.ts +1 -1
- package/dist/esm/note-io/read-note.d.ts +2 -2
- package/dist/esm/note-io/write-note.d.ts +3 -6
- package/dist/esm/records/event.d.ts +3 -3
- package/dist/esm/scaffold/render-seeds.d.ts +3 -3
- package/dist/esm/scaffold/render-seeds.js +5 -3
- package/dist/esm/scaffold/scaffold.d.ts +7 -8
- package/dist/esm/tags/load-aliases.d.ts +3 -4
- package/dist/esm/taxonomy/domain-paths.d.ts +6 -6
- package/dist/esm/taxonomy/load-taxonomy.d.ts +3 -3
- package/dist/esm/taxonomy/load-taxonomy.js +2 -2
- package/dist/esm/taxonomy/taxonomy-schema.d.ts +5 -6
- package/dist/esm/taxonomy/write-taxonomy.d.ts +7 -8
- package/dist/esm/type-guards.d.ts +1 -1
- package/dist/esm/types.d.ts +6 -9
- package/dist/esm/vault-integrity/build-vault-index.d.ts +3 -4
- package/dist/esm/vault-integrity/check-vault-integrity.d.ts +46 -12
- package/dist/esm/vault-integrity/check-vault-integrity.js +59 -20
- package/dist/esm/vault-integrity/index.d.ts +2 -2
- package/dist/esm/vault-integrity/index.js +2 -2
- package/dist/esm/vault-integrity/wikilink-parse.d.ts +45 -19
- package/dist/esm/vault-integrity/wikilink-parse.js +37 -9
- 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
|
|
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
|
|
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,
|
|
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
|
-
*
|
|
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
|
-
*
|
|
43
|
-
*
|
|
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
|
-
*
|
|
43
|
+
* with no git, keeps what the walk alone found.
|
|
46
44
|
*
|
|
47
|
-
* Notes with malformed or absent frontmatter are kept
|
|
48
|
-
* returns an empty field map rather than throwing, so they remain valid wikilink targets. A note that cannot be
|
|
49
|
-
* or a directory that cannot be listed, is skipped with a `kb:` stderr warning rather than aborting the walk.
|
|
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
|
|
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
|
-
|
|
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
|
-
*
|
|
14
|
-
* `
|
|
15
|
-
*
|
|
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
|
|
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({
|
|
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
|
-
|
|
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:
|
|
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`
|
|
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,
|
|
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
|
-
|
|
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
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
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
|
|
10
|
-
created before a given file existed can acquire it. An existing file is
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
8
|
-
* taxonomy drift. A store the registry marks `readonly` is refused
|
|
9
|
-
* `.kb/config.yaml` or `.kb/taxonomy.yaml
|
|
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
|
|
14
|
-
taxonomy can be introduced to a populated store without
|
|
15
|
-
as undeclared. Every folder
|
|
16
|
-
ancestors, under "provisional:" with no
|
|
17
|
-
|
|
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
|
|
23
|
-
Without it, a store that already has a taxonomy is
|
|
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
|
|
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,
|
package/dist/esm/cli/format.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Finding } from '../types.js';
|
|
2
|
-
/** A resolved store's identity,
|
|
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
|
|
24
|
-
* `<severity> <rule> (line N): message`. A clean run (notes checked, no findings) prints
|
|
25
|
-
* checked)`; a run that checked nothing prints a zero-match line worded for its `scope` (naming
|
|
26
|
-
* a whole-vault run, and a scope-appropriate line for a targeted one) without the `✓`, since no
|
|
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
|
|
29
|
-
* zero-match line then heads the report instead of replacing it:
|
|
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
|
|
13
|
-
* (`tryLoadKbRegistry` with `projectDir: cwd`, so project-local `.agents/kb.yaml` entries
|
|
14
|
-
*
|
|
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:
|
|
18
|
-
* and a read-only command ignores it. It is kept off {@link StoreRef}, which
|
|
19
|
-
* discovered store is cross-referenced against the registry by path, so a vault marked readonly is reported
|
|
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;
|
package/dist/esm/cli/run.d.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { type CommandOutput } from './commands/check.js';
|
|
2
2
|
import type { SelectKbPrompt } from './select-kb-prompt.js';
|
|
3
|
-
|
|
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.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
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[];
|
package/dist/esm/cli/run.js
CHANGED
|
@@ -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
|
|
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.
|
|
13
|
-
* stays free of terminal I/O and remains directly testable; the real implementation is
|
|
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,
|
|
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.
|
|
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)
|
|
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
|
-
*
|
|
15
|
-
* when the store is the repository root, correct when it is nested. A git failure (unknown ref, not a
|
|
16
|
-
* returns `{ ok: false }` for the caller to
|
|
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
|
|
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
|
|
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[];
|