@saasontools/strauss-kb 0.1.5 → 0.1.7
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 +50 -3
- package/dist/{chunk-KQMGKSPZ.js → chunk-GKCG4P3L.js} +10 -3
- package/dist/chunk-GKCG4P3L.js.map +1 -0
- package/dist/{chunk-FZIMFPGR.js → chunk-GKUQOJEK.js} +436 -76
- package/dist/chunk-GKUQOJEK.js.map +1 -0
- package/dist/{chunk-VOJ6D6OX.js → chunk-LCQKARFK.js} +5 -4
- package/dist/chunk-LCQKARFK.js.map +1 -0
- package/dist/cli-main.cjs +438 -85
- package/dist/cli-main.cjs.map +1 -1
- package/dist/cli-main.js +2 -2
- package/dist/index.cjs +452 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +136 -7
- package/dist/index.d.ts +136 -7
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-main.cjs +433 -86
- package/dist/mcp-main.cjs.map +1 -1
- package/dist/mcp-main.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-FZIMFPGR.js.map +0 -1
- package/dist/chunk-KQMGKSPZ.js.map +0 -1
- package/dist/chunk-VOJ6D6OX.js.map +0 -1
package/README.md
CHANGED
|
@@ -88,6 +88,24 @@ concepts. `type` is the only key OKF requires; `title`, `description`,
|
|
|
88
88
|
OKF's. Unknown keys are preserved rather than stripped, as OKF requires of
|
|
89
89
|
consumers.
|
|
90
90
|
|
|
91
|
+
`verified` is the record's append-only trail of checks. Each entry is OKF's
|
|
92
|
+
actor stamp — `{ by, at }` — and the entries this package's `verify` writes add
|
|
93
|
+
a `note`: what the check actually found, not just that one happened. The `note`
|
|
94
|
+
is a strauss extension key on the entries this tool writes, not an OKF
|
|
95
|
+
requirement on the array, so noteless entries a foreign producer wrote remain
|
|
96
|
+
readable, and prior entries are spread forward untouched rather than reshaped.
|
|
97
|
+
|
|
98
|
+
Who may append is the point. A verifier whose actor equals the record's
|
|
99
|
+
`generated.by` — compared case-insensitively over the whole actor, so case
|
|
100
|
+
drift cannot mint a distinct verifier identity — is refused unless the actor
|
|
101
|
+
is `human:`-prefixed: trust that can be self-granted is not trust, and a
|
|
102
|
+
generator re-reading its own output is not an independent check. The refusal
|
|
103
|
+
is recorded in the log as `verify:refused`, so an audit sees the attempt as
|
|
104
|
+
well as the rule. The `human:` prefix itself is an honor-system label — actor
|
|
105
|
+
identity is self-declared through `STRAUSS_KB_ACTOR`, not an authenticated
|
|
106
|
+
identity claim — which is worth knowing when deciding how much weight a
|
|
107
|
+
human-verified event carries.
|
|
108
|
+
|
|
91
109
|
Anything prefixed `strauss_` is this package's extension, namespaced so a later
|
|
92
110
|
OKF version defining the same name cannot collide:
|
|
93
111
|
|
|
@@ -196,7 +214,10 @@ strauss-kb [--bundle PATH] <command> [args]
|
|
|
196
214
|
status <concept-id> <status> Move a record's status, compare-and-swap.
|
|
197
215
|
supersede <concept-id> <replacement-id> Mark a record superseded, linking both directions.
|
|
198
216
|
answer <concept-id> <answer...> Resolve an open question and append the answer.
|
|
217
|
+
verify <concept-id> --note <text> Append a verified[] event — who checked, when, and what the check found.
|
|
199
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.
|
|
200
221
|
query <text...> Search; every match arrives flagged with its standing.
|
|
201
222
|
trace <concept-id> [edges...] How a position was arrived at, as a timeline.
|
|
202
223
|
list [type] Every record, optionally narrowed to one type.
|
|
@@ -215,7 +236,8 @@ strauss-kb [--bundle PATH] <command> [args]
|
|
|
215
236
|
STRAUSS_KB_ACTOR names the writer in the log
|
|
216
237
|
```
|
|
217
238
|
|
|
218
|
-
Results go to stdout as JSON — `index`
|
|
239
|
+
Results go to stdout as JSON — `index` and `pack` are markdown, which is what
|
|
240
|
+
they are. Errors
|
|
219
241
|
go to stderr and exit 1. `validate` is the one command whose exit code is not
|
|
220
242
|
just "did it run": a check that reports a problem succeeded as a command and
|
|
221
243
|
failed as a check, so it exits 1 with its findings on stdout.
|
|
@@ -239,8 +261,8 @@ strauss-kb validate || echo "problems above"
|
|
|
239
261
|
|
|
240
262
|
`strauss-kb-mcp` speaks stdio and takes no API key and no required environment.
|
|
241
263
|
Every CLI verb is a tool: `kb_write`, `kb_write_decision`, `kb_no_decision`,
|
|
242
|
-
`kb_status`, `kb_supersede`, `kb_answer`, `kb_load`, `
|
|
243
|
-
`kb_list`, `kb_index`, `kb_log`, `kb_validate`, `kb_schema`, `kb_types`,
|
|
264
|
+
`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`, `kb_schema`, `kb_types`,
|
|
244
266
|
`kb_pin`, `kb_unpin`, `kb_pins`, `kb_context`. Most tools take a `bundlePath`;
|
|
245
267
|
`kb_schema` and `kb_types` describe the format rather than any one base, and
|
|
246
268
|
`kb_pins` and `kb_context` read the workspace pin manifests instead. The one
|
|
@@ -299,6 +321,15 @@ problem:
|
|
|
299
321
|
| Standing | `strauss_status`, the supersession chain | is this still what we hold? |
|
|
300
322
|
| Freshness | `stale_after`, `verified[]` | has anyone confirmed it lately? |
|
|
301
323
|
|
|
324
|
+
Freshness is tiered by who did the confirming. OKF's spec (§5.3) defines the
|
|
325
|
+
trust tiers from the verifying actor's prefix: an empty `verified[]` is
|
|
326
|
+
unverified, an agent-prefixed verifier makes the record machine-confirmed, and
|
|
327
|
+
a `human:`-prefixed verifier makes it human-reviewed. Of that ladder, today's
|
|
328
|
+
adjudication reports only the first rung — the warning it attaches when
|
|
329
|
+
`verified[]` is empty; reporting the full tier is upcoming tooling. When it
|
|
330
|
+
lands, the tier will be derived from the events at read time, never stored, so
|
|
331
|
+
it cannot drift from the trail that justifies it.
|
|
332
|
+
|
|
302
333
|
**Load before you search.** These bases run to a few thousand tokens — twenty
|
|
303
334
|
records measured at about 3,000 — so the first thing to try is taking all of it.
|
|
304
335
|
On nine questions whose wording appears in no record, a reader holding the whole
|
|
@@ -334,6 +365,22 @@ setting to reach for by default. A reader that does not actually need every
|
|
|
334
365
|
record is better served by a narrower `type` filter or a `query` than by
|
|
335
366
|
turning the guardrail off.
|
|
336
367
|
|
|
368
|
+
**Pack is the middle rung.** Under budget, load the base whole — perfect
|
|
369
|
+
recall beats any ranking. Over budget, when the work centres on a record you
|
|
370
|
+
can name, `pack` hands over that record's bounded neighbourhood instead:
|
|
371
|
+
everything within `--hops` of the root, walked over the base's edges — body
|
|
372
|
+
links (a `relatedConceptIds` entry is stored as one), supersession in both
|
|
373
|
+
directions, shared code anchors, and shared sources — ranked and cut to
|
|
374
|
+
`--max-nodes`. Standing travels with it: superseded neighbours arrive as the
|
|
375
|
+
same name, replacement and date stubs `load` emits. Every record the cut
|
|
376
|
+
dropped is named under Excluded, because a named gap is knowable and a silent
|
|
377
|
+
one is not, and past its own token budget `pack` refuses exactly as `load`
|
|
378
|
+
does — naming what was already cut, so the caller can narrow the walk or
|
|
379
|
+
raise the ceiling. Below the header, the only place a timestamp appears, the
|
|
380
|
+
output is byte-identical across runs over an unchanged base: two packs diff,
|
|
381
|
+
and a changed byte means changed knowledge. With neither a budget problem nor
|
|
382
|
+
a root record in hand, the question is a point lookup, and that is `query`.
|
|
383
|
+
|
|
337
384
|
**Flag, never filter.** `query` returns every hit with its standing, because a
|
|
338
385
|
filtered result set is invisible — the caller cannot tell it missed anything.
|
|
339
386
|
The single exception is narrow: a superseded record is dropped only when its
|
|
@@ -2,8 +2,9 @@ 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-GKUQOJEK.js";
|
|
7
8
|
|
|
8
9
|
// src/cli.ts
|
|
9
10
|
import { join } from "path";
|
|
@@ -14,6 +15,11 @@ async function runKbCli(argv) {
|
|
|
14
15
|
process.stdout.write(usage());
|
|
15
16
|
return;
|
|
16
17
|
}
|
|
18
|
+
if (name === "--version" || name === "-v") {
|
|
19
|
+
process.stdout.write(`${VERSION}
|
|
20
|
+
`);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
17
23
|
const command = KB_COMMANDS_BY_NAME.get(name);
|
|
18
24
|
if (!command) die(`unknown command ${name}`);
|
|
19
25
|
const raw = await command.fromArgv(rest, bundle, readStdin);
|
|
@@ -83,6 +89,7 @@ function usage() {
|
|
|
83
89
|
),
|
|
84
90
|
"",
|
|
85
91
|
` --bundle PATH defaults to ./${KB_DIR}`,
|
|
92
|
+
" --version the installed package version",
|
|
86
93
|
" STRAUSS_KB_ACTOR names the writer in the log",
|
|
87
94
|
""
|
|
88
95
|
].join("\n");
|
|
@@ -91,4 +98,4 @@ function usage() {
|
|
|
91
98
|
export {
|
|
92
99
|
runKbCli
|
|
93
100
|
};
|
|
94
|
-
//# sourceMappingURL=chunk-
|
|
101
|
+
//# sourceMappingURL=chunk-GKCG4P3L.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 { bundle, rest } = takeBundle(argv);\n const name = rest[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 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)) 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 process.stdout.write(\n typeof result === \"string\"\n ? result.endsWith(\"\\n\")\n ? result\n : `${result}\\n`\n : `${JSON.stringify(result, null, 2)}\\n`,\n );\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 \" --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":[]}
|