@saasontools/strauss-kb 0.1.7 → 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 +91 -5
- package/dist/{chunk-GKCG4P3L.js → chunk-MGPYUZOM.js} +24 -10
- package/dist/chunk-MGPYUZOM.js.map +1 -0
- package/dist/{chunk-GKUQOJEK.js → chunk-YJK7KGHN.js} +502 -154
- package/dist/chunk-YJK7KGHN.js.map +1 -0
- package/dist/{chunk-LCQKARFK.js → chunk-YYX6CX6V.js} +2 -2
- package/dist/cli-main.cjs +545 -197
- package/dist/cli-main.cjs.map +1 -1
- package/dist/cli-main.js +2 -2
- package/dist/index.cjs +440 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -2
- package/dist/index.d.ts +78 -2
- package/dist/index.js +13 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-main.cjs +523 -189
- package/dist/mcp-main.cjs.map +1 -1
- package/dist/mcp-main.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-GKCG4P3L.js.map +0 -1
- package/dist/chunk-GKUQOJEK.js.map +0 -1
- /package/dist/{chunk-LCQKARFK.js.map → chunk-YYX6CX6V.js.map} +0 -0
package/README.md
CHANGED
|
@@ -224,6 +224,8 @@ strauss-kb [--bundle PATH] <command> [args]
|
|
|
224
224
|
index The index, rebuilt if it disagrees with the records.
|
|
225
225
|
log What touched what, and when.
|
|
226
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.
|
|
227
229
|
schema JSON Schema for the format.
|
|
228
230
|
types The twelve types, their sections and initial status.
|
|
229
231
|
pin [bundle-path] [flags] Pin a base. --mode, --profiles, --frozen; --local/--user pick the layer.
|
|
@@ -233,14 +235,20 @@ strauss-kb [--bundle PATH] <command> [args]
|
|
|
233
235
|
sync-instructions <file> Plant the context block between sentinels in an instruction file.
|
|
234
236
|
|
|
235
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
|
|
236
240
|
STRAUSS_KB_ACTOR names the writer in the log
|
|
237
241
|
```
|
|
238
242
|
|
|
239
243
|
Results go to stdout as JSON — `index` and `pack` are markdown, which is what
|
|
240
|
-
they are
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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.
|
|
244
252
|
|
|
245
253
|
```bash
|
|
246
254
|
strauss-kb --bundle .strauss/kb write fact <<'JSON'
|
|
@@ -262,7 +270,8 @@ strauss-kb validate || echo "problems above"
|
|
|
262
270
|
`strauss-kb-mcp` speaks stdio and takes no API key and no required environment.
|
|
263
271
|
Every CLI verb is a tool: `kb_write`, `kb_write_decision`, `kb_no_decision`,
|
|
264
272
|
`kb_status`, `kb_supersede`, `kb_answer`, `kb_verify`, `kb_load`, `kb_pack`, `kb_query`,
|
|
265
|
-
`kb_trace`, `kb_list`, `kb_index`, `kb_log`, `kb_validate`, `
|
|
273
|
+
`kb_trace`, `kb_list`, `kb_index`, `kb_log`, `kb_validate`, `kb_doctor`,
|
|
274
|
+
`kb_schema`, `kb_types`,
|
|
266
275
|
`kb_pin`, `kb_unpin`, `kb_pins`, `kb_context`. Most tools take a `bundlePath`;
|
|
267
276
|
`kb_schema` and `kb_types` describe the format rather than any one base, and
|
|
268
277
|
`kb_pins` and `kb_context` read the workspace pin manifests instead. The one
|
|
@@ -401,6 +410,83 @@ fact; a missing replacement is `broken-chain` with no head — the case that nee
|
|
|
401
410
|
the most care, because returning the stale record unmarked looks exactly like
|
|
402
411
|
success.
|
|
403
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
|
+
|
|
404
490
|
## Living in an agent session
|
|
405
491
|
|
|
406
492
|
Long sessions lose a knowledge base twice over: attention decays, and
|
|
@@ -4,13 +4,14 @@ import {
|
|
|
4
4
|
KB_DIR,
|
|
5
5
|
KbStore,
|
|
6
6
|
VERSION
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-YJK7KGHN.js";
|
|
8
8
|
|
|
9
9
|
// src/cli.ts
|
|
10
10
|
import { join } from "path";
|
|
11
11
|
async function runKbCli(argv) {
|
|
12
|
-
const {
|
|
13
|
-
const
|
|
12
|
+
const { flags, literal } = takeLiteral(argv);
|
|
13
|
+
const { bundle, rest: withFlags } = takeBundle(flags);
|
|
14
|
+
const name = withFlags[0] ?? "";
|
|
14
15
|
if (!name || name === "-h" || name === "--help") {
|
|
15
16
|
process.stdout.write(usage());
|
|
16
17
|
return;
|
|
@@ -22,6 +23,14 @@ async function runKbCli(argv) {
|
|
|
22
23
|
}
|
|
23
24
|
const command = KB_COMMANDS_BY_NAME.get(name);
|
|
24
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
|
+
];
|
|
25
34
|
const raw = await command.fromArgv(rest, bundle, readStdin);
|
|
26
35
|
const parsed = command.input.safeParse(raw);
|
|
27
36
|
if (!parsed.success) {
|
|
@@ -41,13 +50,16 @@ async function runKbCli(argv) {
|
|
|
41
50
|
},
|
|
42
51
|
parsed.data
|
|
43
52
|
);
|
|
44
|
-
if (command.failsWhen?.(result)) process.exitCode = 1;
|
|
53
|
+
if (command.failsWhen?.(result, parsed.data)) process.exitCode = 1;
|
|
45
54
|
if (result === "") return;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
`
|
|
49
|
-
|
|
50
|
-
|
|
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) };
|
|
51
63
|
}
|
|
52
64
|
function takeBundle(argv) {
|
|
53
65
|
const at = argv.indexOf("--bundle");
|
|
@@ -89,6 +101,8 @@ function usage() {
|
|
|
89
101
|
),
|
|
90
102
|
"",
|
|
91
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",
|
|
92
106
|
" --version the installed package version",
|
|
93
107
|
" STRAUSS_KB_ACTOR names the writer in the log",
|
|
94
108
|
""
|
|
@@ -98,4 +112,4 @@ function usage() {
|
|
|
98
112
|
export {
|
|
99
113
|
runKbCli
|
|
100
114
|
};
|
|
101
|
-
//# 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":[]}
|