@saasontools/strauss-kb 0.1.6 → 0.1.8
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 +111 -6
- package/dist/{chunk-V7TRZ2ER.js → chunk-MGPYUZOM.js} +32 -11
- package/dist/chunk-MGPYUZOM.js.map +1 -0
- package/dist/{chunk-PNSRTKYN.js → chunk-YJK7KGHN.js} +743 -131
- package/dist/chunk-YJK7KGHN.js.map +1 -0
- package/dist/{chunk-BVF7X5VO.js → chunk-YYX6CX6V.js} +5 -4
- package/dist/chunk-YYX6CX6V.js.map +1 -0
- package/dist/cli-main.cjs +757 -149
- package/dist/cli-main.cjs.map +1 -1
- package/dist/cli-main.js +2 -2
- package/dist/index.cjs +743 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +181 -8
- package/dist/index.d.ts +181 -8
- package/dist/index.js +29 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-main.cjs +730 -142
- package/dist/mcp-main.cjs.map +1 -1
- package/dist/mcp-main.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-BVF7X5VO.js.map +0 -1
- package/dist/chunk-PNSRTKYN.js.map +0 -1
- package/dist/chunk-V7TRZ2ER.js.map +0 -1
package/README.md
CHANGED
|
@@ -216,12 +216,16 @@ strauss-kb [--bundle PATH] <command> [args]
|
|
|
216
216
|
answer <concept-id> <answer...> Resolve an open question and append the answer.
|
|
217
217
|
verify <concept-id> --note <text> Append a verified[] event — who checked, when, and what the check found.
|
|
218
218
|
load [type] [--budget N | --all] Hand over the whole base, each record with its standing.
|
|
219
|
+
pack <conceptId> [--hops N] [--max-nodes N] [--budget N]
|
|
220
|
+
The bounded neighbourhood around one record, every cut named.
|
|
219
221
|
query <text...> Search; every match arrives flagged with its standing.
|
|
220
222
|
trace <concept-id> [edges...] How a position was arrived at, as a timeline.
|
|
221
223
|
list [type] Every record, optionally narrowed to one type.
|
|
222
224
|
index The index, rebuilt if it disagrees with the records.
|
|
223
225
|
log What touched what, and when.
|
|
224
226
|
validate Cross-record checks. Exits 1 when it reports a problem.
|
|
227
|
+
doctor [--expiring-days N] [--unverified-days N] [--aging-days N] [--strict]
|
|
228
|
+
Health sweep: what expired, went unconfirmed, aged, or was orphaned.
|
|
225
229
|
schema JSON Schema for the format.
|
|
226
230
|
types The twelve types, their sections and initial status.
|
|
227
231
|
pin [bundle-path] [flags] Pin a base. --mode, --profiles, --frozen; --local/--user pick the layer.
|
|
@@ -231,13 +235,20 @@ strauss-kb [--bundle PATH] <command> [args]
|
|
|
231
235
|
sync-instructions <file> Plant the context block between sentinels in an instruction file.
|
|
232
236
|
|
|
233
237
|
--bundle PATH defaults to ./.strauss/kb
|
|
238
|
+
--json the machine shape, where a command prints a table
|
|
239
|
+
-- everything after it is text, not flags
|
|
234
240
|
STRAUSS_KB_ACTOR names the writer in the log
|
|
235
241
|
```
|
|
236
242
|
|
|
237
|
-
Results go to stdout as JSON — `index`
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
243
|
+
Results go to stdout as JSON — `index` and `pack` are markdown, which is what
|
|
244
|
+
they are, and `doctor` prints a table unless `--json` asks for the object
|
|
245
|
+
behind it. `--json` is refused rather than ignored on the commands that have
|
|
246
|
+
only one form, since a flag that quietly does nothing reads as one that
|
|
247
|
+
worked; `--` ends flag parsing, for the verbs that end in free prose. Errors
|
|
248
|
+
go to stderr and exit 1. `validate` and `doctor --strict` are the commands
|
|
249
|
+
whose exit code is not just "did it run": a check that reports a problem
|
|
250
|
+
succeeded as a command and failed as a check, so it exits 1 with its findings
|
|
251
|
+
on stdout.
|
|
241
252
|
|
|
242
253
|
```bash
|
|
243
254
|
strauss-kb --bundle .strauss/kb write fact <<'JSON'
|
|
@@ -258,8 +269,9 @@ strauss-kb validate || echo "problems above"
|
|
|
258
269
|
|
|
259
270
|
`strauss-kb-mcp` speaks stdio and takes no API key and no required environment.
|
|
260
271
|
Every CLI verb is a tool: `kb_write`, `kb_write_decision`, `kb_no_decision`,
|
|
261
|
-
`kb_status`, `kb_supersede`, `kb_answer`, `kb_verify`, `kb_load`, `kb_query`,
|
|
262
|
-
`kb_trace`, `kb_list`, `kb_index`, `kb_log`, `kb_validate`, `
|
|
272
|
+
`kb_status`, `kb_supersede`, `kb_answer`, `kb_verify`, `kb_load`, `kb_pack`, `kb_query`,
|
|
273
|
+
`kb_trace`, `kb_list`, `kb_index`, `kb_log`, `kb_validate`, `kb_doctor`,
|
|
274
|
+
`kb_schema`, `kb_types`,
|
|
263
275
|
`kb_pin`, `kb_unpin`, `kb_pins`, `kb_context`. Most tools take a `bundlePath`;
|
|
264
276
|
`kb_schema` and `kb_types` describe the format rather than any one base, and
|
|
265
277
|
`kb_pins` and `kb_context` read the workspace pin manifests instead. The one
|
|
@@ -362,6 +374,22 @@ setting to reach for by default. A reader that does not actually need every
|
|
|
362
374
|
record is better served by a narrower `type` filter or a `query` than by
|
|
363
375
|
turning the guardrail off.
|
|
364
376
|
|
|
377
|
+
**Pack is the middle rung.** Under budget, load the base whole — perfect
|
|
378
|
+
recall beats any ranking. Over budget, when the work centres on a record you
|
|
379
|
+
can name, `pack` hands over that record's bounded neighbourhood instead:
|
|
380
|
+
everything within `--hops` of the root, walked over the base's edges — body
|
|
381
|
+
links (a `relatedConceptIds` entry is stored as one), supersession in both
|
|
382
|
+
directions, shared code anchors, and shared sources — ranked and cut to
|
|
383
|
+
`--max-nodes`. Standing travels with it: superseded neighbours arrive as the
|
|
384
|
+
same name, replacement and date stubs `load` emits. Every record the cut
|
|
385
|
+
dropped is named under Excluded, because a named gap is knowable and a silent
|
|
386
|
+
one is not, and past its own token budget `pack` refuses exactly as `load`
|
|
387
|
+
does — naming what was already cut, so the caller can narrow the walk or
|
|
388
|
+
raise the ceiling. Below the header, the only place a timestamp appears, the
|
|
389
|
+
output is byte-identical across runs over an unchanged base: two packs diff,
|
|
390
|
+
and a changed byte means changed knowledge. With neither a budget problem nor
|
|
391
|
+
a root record in hand, the question is a point lookup, and that is `query`.
|
|
392
|
+
|
|
365
393
|
**Flag, never filter.** `query` returns every hit with its standing, because a
|
|
366
394
|
filtered result set is invisible — the caller cannot tell it missed anything.
|
|
367
395
|
The single exception is narrow: a superseded record is dropped only when its
|
|
@@ -382,6 +410,83 @@ fact; a missing replacement is `broken-chain` with no head — the case that nee
|
|
|
382
410
|
the most care, because returning the stale record unmarked looks exactly like
|
|
383
411
|
success.
|
|
384
412
|
|
|
413
|
+
## Health
|
|
414
|
+
|
|
415
|
+
`doctor` sweeps a whole base and reports what has decayed. It is read-only —
|
|
416
|
+
nothing is re-dated, re-verified, superseded, or deleted — because every
|
|
417
|
+
finding is a judgment somebody has to make: whether a claim still holds, which
|
|
418
|
+
question is worth answering, which island to link or drop.
|
|
419
|
+
|
|
420
|
+
It exists because decay is invisible from inside a single record. A stale
|
|
421
|
+
record reads exactly like a live one, a question nobody answered reads exactly
|
|
422
|
+
like one nobody asked, and a record nothing links to is reachable only by
|
|
423
|
+
someone who already knows it is there. `validate` is the narrower neighbour:
|
|
424
|
+
it asks only whether pointers between records agree.
|
|
425
|
+
|
|
426
|
+
| Check | Reports |
|
|
427
|
+
| ---------------------- | ------------------------------------------------------------------------------ |
|
|
428
|
+
| `expired` | `stale_after` is in the past — or is not a readable date, which is no better. |
|
|
429
|
+
| `expiring` | `stale_after` falls inside the next `--expiring-days` (30). |
|
|
430
|
+
| `unverified` | `verified[]` is empty and the record is over `--unverified-days` (90) old. |
|
|
431
|
+
| `aging` | Still `open` or `proposed` after `--aging-days` (90). |
|
|
432
|
+
| `orphaned` | No other record links to it, by body link or supersession. |
|
|
433
|
+
| `broken-supersession` | A chain that does not resolve: no replacement, a missing one, a cycle, a fork. |
|
|
434
|
+
| `superseded-but-cited` | A record that still holds, whose body links to one that does not. |
|
|
435
|
+
|
|
436
|
+
The last check's name is for its common case: a rejected target counts too, and
|
|
437
|
+
is the worse half — a superseded record at least names its replacement, while a
|
|
438
|
+
rejected one is a well-formed assertion of what someone decided _not_ to do,
|
|
439
|
+
cited by a record the reader trusts.
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
strauss-kb doctor # the table
|
|
443
|
+
strauss-kb doctor --json # the object behind it
|
|
444
|
+
strauss-kb doctor --strict # exit 1 if anything has expired
|
|
445
|
+
strauss-kb doctor --unverified-days 30 # a stricter confirmation window
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
All seven groups are reported even when empty. A check that found nothing and
|
|
449
|
+
a check that never ran look identical in a report that only lists findings,
|
|
450
|
+
which is the whole value of a sweep.
|
|
451
|
+
|
|
452
|
+
Judgments the checks make, worth knowing before reading a report:
|
|
453
|
+
|
|
454
|
+
- **Superseded and rejected records sit out the freshness checks.** A replaced
|
|
455
|
+
record whose date has passed needs no repair, and reporting it would bury the
|
|
456
|
+
records that do. They stay in the graph checks, where standing is not the
|
|
457
|
+
question.
|
|
458
|
+
- **A date-only `stale_after` expires at UTC midnight.** `2026-09-01` parses as
|
|
459
|
+
`2026-09-01T00:00:00Z`, so a record goes stale at the start of its date: a
|
|
460
|
+
sweep run at exactly that instant still calls it expiring, and one a minute
|
|
461
|
+
later calls it expired. That is `adjudicate`'s comparison rather than a
|
|
462
|
+
second one — two readings of the same field disagreeing about the day would
|
|
463
|
+
be worse than either.
|
|
464
|
+
- **Age is read from `generated.at`, exclusively.** A record carrying no
|
|
465
|
+
timestamp is not reported as aging or unverified — without a start there is
|
|
466
|
+
no duration, and inventing one would flag every foreign record as overdue
|
|
467
|
+
(adjudication still warns `unverified` on it at read time). Exactly N days
|
|
468
|
+
old is not yet "older than N".
|
|
469
|
+
- **`orphaned` counts incoming links only, and reads supersession one way.** A
|
|
470
|
+
record that cites five others and is cited by none is precisely the island:
|
|
471
|
+
reachable if you already know it exists. The replacement references what it
|
|
472
|
+
replaced, never the reverse — taken symmetrically, a dead record would vouch
|
|
473
|
+
for its own replacement and an old→new pair nothing else touches would rescue
|
|
474
|
+
itself. Shared anchors and shared sources are co-location rather than
|
|
475
|
+
reference, so they do not rescue a record either.
|
|
476
|
+
- **A record citing the one it replaced is not superseded-but-cited.** That
|
|
477
|
+
link is the history working as designed, and reporting it would put a finding
|
|
478
|
+
on every correctly performed supersession.
|
|
479
|
+
- **A replacement pointer is checked whatever the status says.** The store
|
|
480
|
+
writes `strauss_status` and `strauss_superseded_by` in one mutation, so a
|
|
481
|
+
record left `accepted` while naming a replacement was hand-edited — and
|
|
482
|
+
adjudication reads it as current no matter what the pointer says, which is
|
|
483
|
+
what makes it worth naming.
|
|
484
|
+
|
|
485
|
+
`--strict` gates on expiry alone. The other six report debt a reader decides
|
|
486
|
+
about; an expired record is the base itself saying it would stop standing
|
|
487
|
+
behind something, which is the one finding a pipeline can act on without a
|
|
488
|
+
judgment call.
|
|
489
|
+
|
|
385
490
|
## Living in an agent session
|
|
386
491
|
|
|
387
492
|
Long sessions lose a knowledge base twice over: attention decays, and
|
|
@@ -2,20 +2,35 @@ import {
|
|
|
2
2
|
KB_COMMANDS,
|
|
3
3
|
KB_COMMANDS_BY_NAME,
|
|
4
4
|
KB_DIR,
|
|
5
|
-
KbStore
|
|
6
|
-
|
|
5
|
+
KbStore,
|
|
6
|
+
VERSION
|
|
7
|
+
} from "./chunk-YJK7KGHN.js";
|
|
7
8
|
|
|
8
9
|
// src/cli.ts
|
|
9
10
|
import { join } from "path";
|
|
10
11
|
async function runKbCli(argv) {
|
|
11
|
-
const {
|
|
12
|
-
const
|
|
12
|
+
const { flags, literal } = takeLiteral(argv);
|
|
13
|
+
const { bundle, rest: withFlags } = takeBundle(flags);
|
|
14
|
+
const name = withFlags[0] ?? "";
|
|
13
15
|
if (!name || name === "-h" || name === "--help") {
|
|
14
16
|
process.stdout.write(usage());
|
|
15
17
|
return;
|
|
16
18
|
}
|
|
19
|
+
if (name === "--version" || name === "-v") {
|
|
20
|
+
process.stdout.write(`${VERSION}
|
|
21
|
+
`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
17
24
|
const command = KB_COMMANDS_BY_NAME.get(name);
|
|
18
25
|
if (!command) die(`unknown command ${name}`);
|
|
26
|
+
const json = withFlags.includes("--json");
|
|
27
|
+
if (json && !command.render) {
|
|
28
|
+
die(`${name} takes no --json: its result is already the machine shape`);
|
|
29
|
+
}
|
|
30
|
+
const rest = [
|
|
31
|
+
...json ? withFlags.filter((argument) => argument !== "--json") : withFlags,
|
|
32
|
+
...literal
|
|
33
|
+
];
|
|
19
34
|
const raw = await command.fromArgv(rest, bundle, readStdin);
|
|
20
35
|
const parsed = command.input.safeParse(raw);
|
|
21
36
|
if (!parsed.success) {
|
|
@@ -35,13 +50,16 @@ async function runKbCli(argv) {
|
|
|
35
50
|
},
|
|
36
51
|
parsed.data
|
|
37
52
|
);
|
|
38
|
-
if (command.failsWhen?.(result)) process.exitCode = 1;
|
|
53
|
+
if (command.failsWhen?.(result, parsed.data)) process.exitCode = 1;
|
|
39
54
|
if (result === "") return;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
`
|
|
43
|
-
|
|
44
|
-
|
|
55
|
+
const text = command.render && !json ? command.render(result) : typeof result === "string" ? result : JSON.stringify(result, null, 2);
|
|
56
|
+
process.stdout.write(text.endsWith("\n") ? text : `${text}
|
|
57
|
+
`);
|
|
58
|
+
}
|
|
59
|
+
function takeLiteral(argv) {
|
|
60
|
+
const at = argv.indexOf("--");
|
|
61
|
+
if (at === -1) return { flags: argv, literal: [] };
|
|
62
|
+
return { flags: argv.slice(0, at), literal: argv.slice(at + 1) };
|
|
45
63
|
}
|
|
46
64
|
function takeBundle(argv) {
|
|
47
65
|
const at = argv.indexOf("--bundle");
|
|
@@ -83,6 +101,9 @@ function usage() {
|
|
|
83
101
|
),
|
|
84
102
|
"",
|
|
85
103
|
` --bundle PATH defaults to ./${KB_DIR}`,
|
|
104
|
+
" --json the machine shape, where a command prints a table",
|
|
105
|
+
" -- everything after it is text, not flags",
|
|
106
|
+
" --version the installed package version",
|
|
86
107
|
" STRAUSS_KB_ACTOR names the writer in the log",
|
|
87
108
|
""
|
|
88
109
|
].join("\n");
|
|
@@ -91,4 +112,4 @@ function usage() {
|
|
|
91
112
|
export {
|
|
92
113
|
runKbCli
|
|
93
114
|
};
|
|
94
|
-
//# sourceMappingURL=chunk-
|
|
115
|
+
//# sourceMappingURL=chunk-MGPYUZOM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["/**\n * strauss-kb — a knowledge base's command line.\n *\n * A dispatcher over `KB_COMMANDS`, which the MCP server also projects. Nothing\n * command-specific lives here beyond turning argv into the object both\n * surfaces pass.\n */\nimport { join } from \"node:path\";\nimport { KB_COMMANDS, KB_COMMANDS_BY_NAME } from \"./commands/index.js\";\nimport { KB_DIR, KbStore } from \"./kb-store.js\";\nimport { VERSION } from \"./version.js\";\n\nexport async function runKbCli(argv: string[]): Promise<void> {\n const { flags, literal } = takeLiteral(argv);\n const { bundle, rest: withFlags } = takeBundle(flags);\n const name = withFlags[0] ?? \"\";\n\n if (!name || name === \"-h\" || name === \"--help\") {\n process.stdout.write(usage());\n return;\n }\n\n // The plugin in front of this CLI updates from a marketplace while the CLI\n // updates from npm, and neither prompts for the other. Answering \"which one\n // is installed\" is what makes that skew diagnosable instead of mysterious.\n if (name === \"--version\" || name === \"-v\") {\n process.stdout.write(`${VERSION}\\n`);\n return;\n }\n\n const command = KB_COMMANDS_BY_NAME.get(name);\n if (!command) die(`unknown command ${name}`);\n\n // Output shape, not an argument: stripped before the command sees argv, so a\n // positional adapter never has to know the flag exists. Refused rather than\n // ignored where a command has only one form — a flag that silently does\n // nothing teaches a caller that it worked.\n const json = withFlags.includes(\"--json\");\n if (json && !command.render) {\n die(`${name} takes no --json: its result is already the machine shape`);\n }\n const rest = [\n ...(json\n ? withFlags.filter((argument) => argument !== \"--json\")\n : withFlags),\n ...literal,\n ];\n\n const raw = await command.fromArgv(rest, bundle, readStdin);\n const parsed = command.input.safeParse(raw);\n if (!parsed.success) {\n die(\n `${name}: ${parsed.error.issues\n .map((issue) => `${issue.path.join(\".\") || \"(root)\"}: ${issue.message}`)\n .join(\"; \")}`,\n );\n }\n\n const store = new KbStore({\n warn: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n });\n const result = await command.run(\n {\n store,\n actor: process.env.STRAUSS_KB_ACTOR ?? \"unknown\",\n now: () => new Date().toISOString(),\n },\n parsed.data,\n );\n\n // A check reporting a problem succeeded as a command and failed as a check;\n // the command says which, rather than the dispatcher knowing their names.\n if (command.failsWhen?.(result, parsed.data)) process.exitCode = 1;\n // An empty string is deliberate silence — `context` with nothing pinned\n // runs from hooks at every session start, and even a bare newline is noise\n // injected into a fresh context.\n if (result === \"\") return;\n const text =\n command.render && !json\n ? command.render(result)\n : typeof result === \"string\"\n ? result\n : JSON.stringify(result, null, 2);\n process.stdout.write(text.endsWith(\"\\n\") ? text : `${text}\\n`);\n}\n\n/**\n * Everything after a bare `--` is text, never flags.\n *\n * Several verbs end in free prose — `no-decision`, `answer`, `query` — and a\n * reason that happens to contain `--json` or `--bundle` would otherwise lose a\n * word to the flag scan, or two. The sentinel is the usual escape, and the\n * token itself is dropped while the order of everything else is kept, so the\n * positional adapters still index the same way.\n */\nfunction takeLiteral(argv: string[]): { flags: string[]; literal: string[] } {\n const at = argv.indexOf(\"--\");\n if (at === -1) return { flags: argv, literal: [] };\n return { flags: argv.slice(0, at), literal: argv.slice(at + 1) };\n}\n\n/**\n * `--bundle` addresses a base directly; without it the command works on the\n * one under the current directory. A base belongs to whatever prompted it, so\n * the default cannot be the only option.\n */\nfunction takeBundle(argv: string[]): { bundle: string; rest: string[] } {\n const at = argv.indexOf(\"--bundle\");\n if (at === -1) {\n return { bundle: join(process.cwd(), KB_DIR), rest: argv };\n }\n const bundle = argv[at + 1];\n if (!bundle) die(\"--bundle requires a path\");\n return { bundle, rest: [...argv.slice(0, at), ...argv.slice(at + 2)] };\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let text = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => (text += chunk));\n process.stdin.on(\"end\", () => resolve(text));\n process.stdin.on(\"error\", reject);\n });\n}\n\nfunction die(message: string): never {\n process.stderr.write(`strauss-kb: error: ${message}\\n`);\n process.exit(1);\n}\n\n/** First sentence, capped — the full text is what an MCP client shows. */\nfunction summarise(description: string): string {\n const first = description.split(\"\\n\")[0] ?? \"\";\n const sentence = first.includes(\". \")\n ? `${first.slice(0, first.indexOf(\". \"))}.`\n : first;\n return sentence.length > 78 ? `${sentence.slice(0, 75)}…` : sentence;\n}\n\nfunction usage(): string {\n const width = Math.max(...KB_COMMANDS.map((command) => command.usage.length));\n return [\n \"strauss-kb — knowledge base commands\",\n \"\",\n \"Usage: strauss-kb [--bundle PATH] <command> [args]\",\n \"\",\n ...KB_COMMANDS.map(\n (command) =>\n ` ${command.usage.padEnd(width)} ${summarise(command.description)}`,\n ),\n \"\",\n ` --bundle PATH defaults to ./${KB_DIR}`,\n \" --json the machine shape, where a command prints a table\",\n \" -- everything after it is text, not flags\",\n \" --version the installed package version\",\n \" STRAUSS_KB_ACTOR names the writer in the log\",\n \"\",\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":[]}
|