@saasontools/strauss-kb 0.1.13 → 0.1.14

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.
@@ -4,7 +4,7 @@ import {
4
4
  KB_DIR,
5
5
  KbStore,
6
6
  VERSION
7
- } from "./chunk-XALWG3EZ.js";
7
+ } from "./chunk-43KALLFU.js";
8
8
 
9
9
  // src/cli.ts
10
10
  import { join } from "path";
@@ -112,4 +112,4 @@ function usage() {
112
112
  export {
113
113
  runKbCli
114
114
  };
115
- //# sourceMappingURL=chunk-ZICKDZGY.js.map
115
+ //# sourceMappingURL=chunk-MBXNCZ4V.js.map
@@ -2,7 +2,7 @@ import {
2
2
  KB_COMMANDS,
3
3
  KbStore,
4
4
  VERSION
5
- } from "./chunk-XALWG3EZ.js";
5
+ } from "./chunk-43KALLFU.js";
6
6
 
7
7
  // src/mcp.ts
8
8
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -46,4 +46,4 @@ export {
46
46
  createKbMcpServer,
47
47
  runKbMcpServer
48
48
  };
49
- //# sourceMappingURL=chunk-WZODZNR6.js.map
49
+ //# sourceMappingURL=chunk-PYA5E7FL.js.map
package/dist/cli-main.cjs CHANGED
@@ -1534,7 +1534,7 @@ var answerCommand = define({
1534
1534
  name: "answer",
1535
1535
  tool: "kb_answer",
1536
1536
  usage: "answer <concept-id> <answer...>",
1537
- description: "Resolve an open question: sets the status, stamps who answered and when, and appends an Answer section. If the answer overturns an assumption or a decision, that is a supersession \u2014 do it explicitly.",
1537
+ description: "Resolve an open question: set status, stamp who and when, append an Answer section. If the answer overturns a decision or assumption, supersede that record explicitly.",
1538
1538
  input: import_zod7.z.object({ bundlePath, conceptId, answer: import_zod7.z.string().min(1) }),
1539
1539
  fromArgv: (argv, path) => ({
1540
1540
  bundlePath: path,
@@ -2043,7 +2043,7 @@ var contextCommand = define({
2043
2043
  name: "context",
2044
2044
  tool: "kb_context",
2045
2045
  usage: "context [--profile NAME] [--budget N] [--full-under N] [--format json] [--event NAME]",
2046
- description: "The pinned-base index block, for injection at every context birth \u2014 startup, clear, resume, and after compaction. An index, not the content: concept ids, titles and standing, with the bodies left behind kb_load at the point of use. Emits nothing when nothing is pinned. Refuses with the list of bases and their sizes rather than truncating past its budget. Budgets resolve most-specific-first: explicit flags, then the workspace manifests' `context` tables (per profile, over their `default`), then the built-in profile (session-start, compact, turn), then package defaults \u2014 so a repo tunes its own numbers in .strauss/kb-pins.json without touching hook commands. Like kb_schema and kb_types this takes no bundlePath \u2014 it reads the workspace pin manifests, because which bases a session should see is workspace state, not a property of one base.",
2046
+ description: "Index block of pinned bases (ids, titles, standing) for injection at context birth. Takes no bundlePath \u2014 reads the workspace pin manifests. Empty when nothing is pinned; refuses over budget rather than truncating. Budget precedence: flags, then the manifest `context[profile]` over `context.default`, then the built-in profile, then package defaults.",
2047
2047
  input: import_zod10.z.object({
2048
2048
  budgetTokens: import_zod10.z.number().int().positive().optional().describe(
2049
2049
  "Ceiling on the whole emitted block; past it the command refuses with a list of bases rather than truncating. Defaults to 4000."
@@ -2657,7 +2657,7 @@ var listCommand = define({
2657
2657
  name: "list",
2658
2658
  tool: "kb_list",
2659
2659
  usage: "list [type]",
2660
- description: "Every record, optionally narrowed to one type. Use kb_query when you have a question; this is for enumerating.",
2660
+ description: "Every record, optionally one type. For enumerating; use kb_query for a question.",
2661
2661
  input: import_zod13.z.object({ bundlePath, type: import_zod13.z.enum(KB_RECORD_TYPES).optional() }),
2662
2662
  fromArgv: (argv, path) => ({ bundlePath: path, type: argv[1] }),
2663
2663
  run: async ({ store }, { bundlePath: path, type }) => (await store.list(path, type)).map((record) => ({
@@ -2675,7 +2675,7 @@ var loadCommand = define({
2675
2675
  name: "load",
2676
2676
  tool: "kb_load",
2677
2677
  usage: "load [type] [--budget N | --all] [--repo-root PATH]",
2678
- description: "Loads the whole knowledge base at once, each record with its standing. Superseded records arrive as stubs; rejected and open records arrive whole. Refuses past the token budget \u2014 call kb_catalog, kb_pack on it; `all` bypasses the budget. Never read record files directly. Cache-stable; `digest` is the base's content stamp \u2014 hooks use it to tell you when to reload.",
2678
+ description: "Load the whole base, each record with its standing \u2014 call it first, at the point of use, since compaction drops it. Superseded records arrive as stubs; kb_trace has the history. Over budget it refuses: kb_catalog, then kb_pack, or narrow with `type`; `all` bypasses. Never read record files directly \u2014 only kb_* tools resolve supersession. `digest` stamps the base's content, so hooks know when to reload.",
2679
2679
  input: import_zod14.z.object({
2680
2680
  bundlePath,
2681
2681
  type: import_zod14.z.enum(KB_RECORD_TYPES).optional(),
@@ -2727,7 +2727,7 @@ var logCommand = define({
2727
2727
  name: "log",
2728
2728
  tool: "kb_log",
2729
2729
  usage: "log",
2730
- description: "What touched what, and when. The only artifact here that cannot be reconstructed from the records, so malformed lines are reported rather than repaired.",
2730
+ description: "Who touched what, and when. Append-only; malformed lines are reported, never repaired.",
2731
2731
  input: import_zod15.z.object({ bundlePath }),
2732
2732
  fromArgv: (_argv, path) => ({ bundlePath: path }),
2733
2733
  run: ({ store }, { bundlePath: path }) => store.readLog(path)
@@ -2739,7 +2739,7 @@ var noDecisionCommand = define({
2739
2739
  name: "no-decision",
2740
2740
  tool: "kb_no_decision",
2741
2741
  usage: "no-decision <reason...>",
2742
- description: 'Claim in one sentence that there was nothing to decide. Gating on "did you write a decision?" rewards writing a junk one; gating on "did you answer?" does not, so silence has to be expressible. Idempotent \u2014 restating it is not a collision.',
2742
+ description: "Record in one sentence that a piece of work had nothing to decide. Idempotent.",
2743
2743
  input: import_zod16.z.object({ bundlePath, reason: import_zod16.z.string().min(1) }),
2744
2744
  fromArgv: (argv, path) => ({
2745
2745
  bundlePath: path,
@@ -2762,7 +2762,7 @@ var packCommand = define({
2762
2762
  name: "pack",
2763
2763
  tool: "kb_pack",
2764
2764
  usage: "pack <conceptId> [--hops N] [--max-nodes N] [--budget N]",
2765
- description: "The bounded neighbourhood around one record: everything within `hops` of the root, ranked and cut to `maxNodes`, with every cut record named under Excluded \u2014 a named gap is knowable, a silent one is not. Prefer this over kb_load when the base is too large to hold whole and the work centres on one record; prefer it over kb_query when the question needs the governed neighbourhood \u2014 what was settled and what binds near this record \u2014 rather than a lookup by wording. Superseded records arrive as name, replacement and date stubs exactly as kb_load emits them: their bodies no longer hold, and kb_trace has the history. Refuses outright rather than truncating when the pack would exceed its token budget \u2014 a partial pack is indistinguishable from a complete one \u2014 reporting the record count and every already-cut id so the caller can lower hops or maxNodes, or raise the budget. The header carries the bundle, root, budget and a timestamp; everything below the header is byte-identical across runs over an unchanged base, so two packs can be diffed and a changed byte means changed knowledge. This tool (with kb_load, kb_query and kb_trace) is the only supported way to read a base; a raw file read bypasses supersession resolution and returns replaced records as if current.",
2765
+ description: "Bounded neighbourhood around one record: within `hops`, ranked, cut to `maxNodes`, with every cut record named under Excluded. Use when the base is over kb_load's budget and the work centres on a record you can name. Refuses over budget rather than truncating. Everything below the header is byte-stable across runs. Resolves supersession like kb_load.",
2766
2766
  input: import_zod17.z.object({
2767
2767
  bundlePath,
2768
2768
  conceptId,
@@ -2862,7 +2862,7 @@ var pinCommand = define({
2862
2862
  name: "pin",
2863
2863
  tool: "kb_pin",
2864
2864
  usage: "pin [bundle-path] [--mode full|index] [--profiles a,b] [--local|--user] [--frozen|--unfreeze]",
2865
- description: "Pin a base into a workspace pin manifest, so `context` surfaces it at every context birth. Three layers, nearest wins: the committed project manifest (.strauss/kb-pins.json, the default), `--local` (.strauss/kb-pins.local.json, personal and gitignored), and `--user` (~/.strauss/kb-pins.json, every workspace). Idempotent \u2014 re-pinning changes nothing unless --mode, --profiles, or --frozen/--unfreeze are given, which update just those fields. `--mode full` preloads the whole base into the block regardless of the full-under threshold; `--mode index` never upgrades. `--profiles` scopes the pin to named context profiles. `--frozen` marks the base concluded: write commands against it refuse and `context` labels it read-only. A path with no records yet succeeds with a warning; bases are routinely pinned before they are populated. Pins are workspace state: the pinned base itself is never touched.",
2865
+ description: "Pin a base into a workspace manifest so kb_context surfaces it. Layers, nearest wins: project `.strauss/kb-pins.json` (default), `--local` (personal, gitignored), `--user` (`~/.strauss`). Idempotent; `--mode full|index`, `--profiles`, `--frozen`/`--unfreeze` update only those fields. A path with no records pins with a warning. Never touches the base itself.",
2866
2866
  input: import_zod18.z.object({
2867
2867
  bundlePath,
2868
2868
  mode: import_zod18.z.enum(["full", "index"]).optional().describe(
@@ -2906,7 +2906,7 @@ var pinsCommand = define({
2906
2906
  name: "pins",
2907
2907
  tool: "kb_pins",
2908
2908
  usage: "pins",
2909
- description: "Every pinned base across the manifest layers, each with its layer and whether it currently resolves to readable records. Reads the workspace manifests rather than any one base, like kb_context.",
2909
+ description: "Every pinned base across the manifest layers, with its layer and whether it resolves to records. Takes no bundlePath.",
2910
2910
  input: import_zod19.z.object({}),
2911
2911
  fromArgv: () => ({}),
2912
2912
  run: ({ store }) => listPins(store, process.cwd())
@@ -2960,7 +2960,7 @@ var readIndexCommand = define({
2960
2960
  name: "index",
2961
2961
  tool: "kb_index",
2962
2962
  usage: "index",
2963
- description: "The index, rebuilt if it disagrees with the records. One call gives the whole shape of the base: title, type, status, and description per record. The cheap re-orientation call after compaction or deep in a long session \u2014 a few hundred tokens; call it (or kb_context, when bases are pinned) first, then kb_load or fetch by concept id.",
2963
+ description: "The index \u2014 title, type, status, description per record \u2014 rebuilt if stale. Cheapest re-orientation after compaction: call it (or kb_context) first, then kb_load or fetch by id.",
2964
2964
  input: import_zod21.z.object({ bundlePath }),
2965
2965
  fromArgv: (_argv, path) => ({ bundlePath: path }),
2966
2966
  run: ({ store }, { bundlePath: path }) => store.readIndex(path)
@@ -3040,7 +3040,7 @@ var schemaCommand = define({
3040
3040
  name: "schema",
3041
3041
  tool: "kb_schema",
3042
3042
  usage: "schema",
3043
- description: "JSON Schema for the frontmatter, the write input, and log entries \u2014 generated from the code that enforces them, so it cannot drift from what a write will accept.",
3043
+ description: "JSON Schema for frontmatter, write input, and log entries, generated from the enforcing code.",
3044
3044
  input: import_zod24.z.object({}),
3045
3045
  fromArgv: () => ({}),
3046
3046
  run: () => Promise.resolve(kbJsonSchemas())
@@ -3052,7 +3052,7 @@ var statusCommand = define({
3052
3052
  name: "status",
3053
3053
  tool: "kb_status",
3054
3054
  usage: "status <concept-id> <status>",
3055
- description: "Move a record's status, leaving everything else alone. Uses a compare-and-swap, so a concurrent change fails loudly rather than being overwritten.",
3055
+ description: "Move a record's status. Compare-and-swap: a concurrent change fails instead of being overwritten.",
3056
3056
  input: import_zod25.z.object({
3057
3057
  bundlePath,
3058
3058
  conceptId,
@@ -3076,7 +3076,7 @@ var supersedeCommand = define({
3076
3076
  name: "supersede",
3077
3077
  tool: "kb_supersede",
3078
3078
  usage: "supersede <concept-id> <replacement-id>",
3079
- description: "Mark a record superseded by another, linking both directions. Use this rather than editing a record whose meaning changed \u2014 a record that quietly becomes something else invalidates every reference to it, and the earlier understanding is what a later trace needs.",
3079
+ description: "Mark a record superseded by another, linked in both directions. Use instead of editing a record whose meaning changed.",
3080
3080
  input: import_zod26.z.object({ bundlePath, conceptId, replacementId: conceptId }),
3081
3081
  fromArgv: (argv, path) => ({
3082
3082
  bundlePath: path,
@@ -3095,7 +3095,7 @@ var import_zod27 = require("zod");
3095
3095
  var syncInstructionsCommand = define({
3096
3096
  name: "sync-instructions",
3097
3097
  usage: "sync-instructions <file> [--profile NAME] [--budget N] [--full-under N]",
3098
- description: "Idempotently plant the `context` block between sentinel comments in an instruction file (AGENTS.md, CLAUDE.md), creating the block when absent and leaving everything outside the sentinels alone. CLI-only: this is file plumbing for runtimes whose instruction files are re-read where their conversations are not, not an agent capability \u2014 the capability is kb_context.",
3098
+ description: "CLI-only: plant the kb_context block between sentinel comments in AGENTS.md or CLAUDE.md, idempotently.",
3099
3099
  input: import_zod27.z.object({
3100
3100
  file: import_zod27.z.string().min(1).describe("The instruction file to edit in place."),
3101
3101
  budgetTokens: import_zod27.z.number().int().positive().optional(),
@@ -3181,7 +3181,7 @@ var traceCommand = define({
3181
3181
  name: "trace",
3182
3182
  tool: "kb_trace",
3183
3183
  usage: "trace <concept-id> [edges...]",
3184
- description: 'How a position was arrived at, as a timeline ordered by when each record was written. Deliberately includes rejected, draft, and superseded records \u2014 in a history those are the content, not noise. Follows supersession, shared code anchors, and shared sources. Use when the question is "why is this the way it is" rather than "what do we hold now". This tool (with kb_load and kb_query) is the only supported way to read a base; a raw file read bypasses supersession resolution and returns replaced records as if current.',
3184
+ description: 'Timeline of how a position was reached, ordered by write time, following supersession, shared anchors and shared sources. Includes rejected, draft and superseded records \u2014 in a history they are the content. For "why is it like this"; kb_load answers "what holds now".',
3185
3185
  input: import_zod28.z.object({
3186
3186
  bundlePath,
3187
3187
  conceptId,
@@ -3225,7 +3225,7 @@ var unpinCommand = define({
3225
3225
  name: "unpin",
3226
3226
  tool: "kb_unpin",
3227
3227
  usage: "unpin [bundle-path]",
3228
- description: "Remove a base from every pin manifest layer that holds it \u2014 project, local, and user \u2014 because unpinned means gone, not still injected from another file. Reports which layers were touched.",
3228
+ description: "Remove a base from every manifest layer that holds it. Reports the layers touched.",
3229
3229
  input: import_zod30.z.object({ bundlePath }),
3230
3230
  fromArgv: (argv, path) => ({ bundlePath: argv[1] ?? path }),
3231
3231
  run: (_ctx, { bundlePath: path }) => unpinBase(process.cwd(), path)
@@ -3253,7 +3253,7 @@ var verifyCommand = define({
3253
3253
  name: "verify",
3254
3254
  tool: "kb_verify",
3255
3255
  usage: "verify <concept-id> --note <text>",
3256
- description: "Append one verified[] event \u2014 who checked the record, when, and what the check found. Appends only; prior events are never rewritten. A record's own generator is refused unless the actor is human: re-reading your own output is not an independent check.",
3256
+ description: "Append a verified[] event: who checked, when, and what was found. Append-only. A record's own generator is refused unless the actor is `human:`-prefixed.",
3257
3257
  input: import_zod32.z.object({
3258
3258
  bundlePath,
3259
3259
  conceptId,
@@ -3282,15 +3282,7 @@ var writeCommand = define({
3282
3282
  name: "write",
3283
3283
  tool: "kb_write",
3284
3284
  usage: "write <type> < record.json",
3285
- description: [
3286
- "Write one record. Search first \u2014 the same knowledge filed twice under different slugs is how a base rots, and a duplicate concept id is rejected rather than overwritten. Call kb_types for the sections each type accepts.",
3287
- "",
3288
- "Judgment the tool cannot enforce for you:",
3289
- "- An unsourced claim is an `assumption` record with assumption: true, never a `fact` with a vague source. The distinction is what lets a later reader separate what was established from what was guessed.",
3290
- "- When two records conflict, say so in a `risk`, an `open-question`, or a superseding `decision`. Quietly picking a winner destroys the disagreement, which is usually the useful part.",
3291
- "- Prefer a new record over overloading an existing one, and keep each short. A record nobody finishes reading is not durable memory.",
3292
- "- Records are never deleted; supersede instead, so the earlier reasoning stays inspectable."
3293
- ].join("\n"),
3285
+ description: "Write one record. Search first \u2014 a duplicate concept id is rejected, not overwritten; kb_types lists each type's sections. An unsourced claim is an `assumption` with assumption: true, never a vague `fact`. Conflicting records get a `risk`, `open-question`, or superseding `decision`. Prefer a new short record over overloading one. Never delete; supersede.",
3294
3286
  input: import_zod33.z.object({
3295
3287
  bundlePath,
3296
3288
  type: import_zod33.z.enum(KB_RECORD_TYPES),
@@ -3322,14 +3314,7 @@ var writeDecisionCommand = define({
3322
3314
  name: "write-decision",
3323
3315
  tool: "kb_write_decision",
3324
3316
  usage: "write-decision < decision.json",
3325
- description: [
3326
- "Write a decision. Takes `alternative` and `impact` as fields rather than free sections, because what was rejected is the part a later reader cannot reconstruct from the code \u2014 a heading is too easy to leave empty.",
3327
- "",
3328
- "What belongs in one:",
3329
- '- Record a decision when a later reader would otherwise "simplify" the constraint away. If the diff already answers the question, there is nothing here to write.',
3330
- "- `alternative` is what you turned down and why, not a list of everything considered.",
3331
- "- A reference to material you read goes in `sources`; a reference to code goes in `anchors`; a reference to another record goes in `relatedConceptIds`."
3332
- ].join("\n"),
3317
+ description: "Write a decision, with `alternative` (what was rejected and why) and `impact` as fields. Record one when a later reader would otherwise simplify the constraint away; skip when the diff already answers it. `sources` for material read, `anchors` for code, `relatedConceptIds` for records.",
3333
3318
  input: import_zod34.z.object({ bundlePath, input: decisionInputSchema }),
3334
3319
  fromArgv: async (_argv, path, stdin) => ({
3335
3320
  bundlePath: path,
@@ -4453,7 +4438,7 @@ function bundleDigest(records, superseded) {
4453
4438
  }
4454
4439
 
4455
4440
  // src/version.ts
4456
- var VERSION = true ? "0.1.13" : "0.0.0-dev";
4441
+ var VERSION = true ? "0.1.14" : "0.0.0-dev";
4457
4442
 
4458
4443
  // src/cli.ts
4459
4444
  async function runKbCli(argv) {