@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.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  runKbCli
3
- } from "./chunk-ZICKDZGY.js";
3
+ } from "./chunk-MBXNCZ4V.js";
4
4
  import {
5
5
  createKbMcpServer,
6
6
  runKbMcpServer
7
- } from "./chunk-WZODZNR6.js";
7
+ } from "./chunk-PYA5E7FL.js";
8
8
  import {
9
9
  BaseError,
10
10
  CONTEXT_BEGIN,
@@ -114,7 +114,7 @@ import {
114
114
  trace,
115
115
  unpinBase,
116
116
  validateBundle
117
- } from "./chunk-XALWG3EZ.js";
117
+ } from "./chunk-43KALLFU.js";
118
118
 
119
119
  // src/match-diff.ts
120
120
  function matchToDiff(files, records, options = {}) {
package/dist/mcp-main.cjs CHANGED
@@ -1535,7 +1535,7 @@ var answerCommand = define({
1535
1535
  name: "answer",
1536
1536
  tool: "kb_answer",
1537
1537
  usage: "answer <concept-id> <answer...>",
1538
- 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.",
1538
+ 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.",
1539
1539
  input: import_zod7.z.object({ bundlePath, conceptId, answer: import_zod7.z.string().min(1) }),
1540
1540
  fromArgv: (argv, path) => ({
1541
1541
  bundlePath: path,
@@ -2044,7 +2044,7 @@ var contextCommand = define({
2044
2044
  name: "context",
2045
2045
  tool: "kb_context",
2046
2046
  usage: "context [--profile NAME] [--budget N] [--full-under N] [--format json] [--event NAME]",
2047
- 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.",
2047
+ 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.",
2048
2048
  input: import_zod10.z.object({
2049
2049
  budgetTokens: import_zod10.z.number().int().positive().optional().describe(
2050
2050
  "Ceiling on the whole emitted block; past it the command refuses with a list of bases rather than truncating. Defaults to 4000."
@@ -2658,7 +2658,7 @@ var listCommand = define({
2658
2658
  name: "list",
2659
2659
  tool: "kb_list",
2660
2660
  usage: "list [type]",
2661
- description: "Every record, optionally narrowed to one type. Use kb_query when you have a question; this is for enumerating.",
2661
+ description: "Every record, optionally one type. For enumerating; use kb_query for a question.",
2662
2662
  input: import_zod13.z.object({ bundlePath, type: import_zod13.z.enum(KB_RECORD_TYPES).optional() }),
2663
2663
  fromArgv: (argv, path) => ({ bundlePath: path, type: argv[1] }),
2664
2664
  run: async ({ store }, { bundlePath: path, type }) => (await store.list(path, type)).map((record) => ({
@@ -2676,7 +2676,7 @@ var loadCommand = define({
2676
2676
  name: "load",
2677
2677
  tool: "kb_load",
2678
2678
  usage: "load [type] [--budget N | --all] [--repo-root PATH]",
2679
- 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.",
2679
+ 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.",
2680
2680
  input: import_zod14.z.object({
2681
2681
  bundlePath,
2682
2682
  type: import_zod14.z.enum(KB_RECORD_TYPES).optional(),
@@ -2728,7 +2728,7 @@ var logCommand = define({
2728
2728
  name: "log",
2729
2729
  tool: "kb_log",
2730
2730
  usage: "log",
2731
- 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.",
2731
+ description: "Who touched what, and when. Append-only; malformed lines are reported, never repaired.",
2732
2732
  input: import_zod15.z.object({ bundlePath }),
2733
2733
  fromArgv: (_argv, path) => ({ bundlePath: path }),
2734
2734
  run: ({ store }, { bundlePath: path }) => store.readLog(path)
@@ -2740,7 +2740,7 @@ var noDecisionCommand = define({
2740
2740
  name: "no-decision",
2741
2741
  tool: "kb_no_decision",
2742
2742
  usage: "no-decision <reason...>",
2743
- 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.',
2743
+ description: "Record in one sentence that a piece of work had nothing to decide. Idempotent.",
2744
2744
  input: import_zod16.z.object({ bundlePath, reason: import_zod16.z.string().min(1) }),
2745
2745
  fromArgv: (argv, path) => ({
2746
2746
  bundlePath: path,
@@ -2763,7 +2763,7 @@ var packCommand = define({
2763
2763
  name: "pack",
2764
2764
  tool: "kb_pack",
2765
2765
  usage: "pack <conceptId> [--hops N] [--max-nodes N] [--budget N]",
2766
- 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.",
2766
+ 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.",
2767
2767
  input: import_zod17.z.object({
2768
2768
  bundlePath,
2769
2769
  conceptId,
@@ -2863,7 +2863,7 @@ var pinCommand = define({
2863
2863
  name: "pin",
2864
2864
  tool: "kb_pin",
2865
2865
  usage: "pin [bundle-path] [--mode full|index] [--profiles a,b] [--local|--user] [--frozen|--unfreeze]",
2866
- 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.",
2866
+ 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.",
2867
2867
  input: import_zod18.z.object({
2868
2868
  bundlePath,
2869
2869
  mode: import_zod18.z.enum(["full", "index"]).optional().describe(
@@ -2907,7 +2907,7 @@ var pinsCommand = define({
2907
2907
  name: "pins",
2908
2908
  tool: "kb_pins",
2909
2909
  usage: "pins",
2910
- 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.",
2910
+ description: "Every pinned base across the manifest layers, with its layer and whether it resolves to records. Takes no bundlePath.",
2911
2911
  input: import_zod19.z.object({}),
2912
2912
  fromArgv: () => ({}),
2913
2913
  run: ({ store }) => listPins(store, process.cwd())
@@ -2961,7 +2961,7 @@ var readIndexCommand = define({
2961
2961
  name: "index",
2962
2962
  tool: "kb_index",
2963
2963
  usage: "index",
2964
- 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.",
2964
+ 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.",
2965
2965
  input: import_zod21.z.object({ bundlePath }),
2966
2966
  fromArgv: (_argv, path) => ({ bundlePath: path }),
2967
2967
  run: ({ store }, { bundlePath: path }) => store.readIndex(path)
@@ -3041,7 +3041,7 @@ var schemaCommand = define({
3041
3041
  name: "schema",
3042
3042
  tool: "kb_schema",
3043
3043
  usage: "schema",
3044
- 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.",
3044
+ description: "JSON Schema for frontmatter, write input, and log entries, generated from the enforcing code.",
3045
3045
  input: import_zod24.z.object({}),
3046
3046
  fromArgv: () => ({}),
3047
3047
  run: () => Promise.resolve(kbJsonSchemas())
@@ -3053,7 +3053,7 @@ var statusCommand = define({
3053
3053
  name: "status",
3054
3054
  tool: "kb_status",
3055
3055
  usage: "status <concept-id> <status>",
3056
- 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.",
3056
+ description: "Move a record's status. Compare-and-swap: a concurrent change fails instead of being overwritten.",
3057
3057
  input: import_zod25.z.object({
3058
3058
  bundlePath,
3059
3059
  conceptId,
@@ -3077,7 +3077,7 @@ var supersedeCommand = define({
3077
3077
  name: "supersede",
3078
3078
  tool: "kb_supersede",
3079
3079
  usage: "supersede <concept-id> <replacement-id>",
3080
- 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.",
3080
+ description: "Mark a record superseded by another, linked in both directions. Use instead of editing a record whose meaning changed.",
3081
3081
  input: import_zod26.z.object({ bundlePath, conceptId, replacementId: conceptId }),
3082
3082
  fromArgv: (argv, path) => ({
3083
3083
  bundlePath: path,
@@ -3096,7 +3096,7 @@ var import_zod27 = require("zod");
3096
3096
  var syncInstructionsCommand = define({
3097
3097
  name: "sync-instructions",
3098
3098
  usage: "sync-instructions <file> [--profile NAME] [--budget N] [--full-under N]",
3099
- 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.",
3099
+ description: "CLI-only: plant the kb_context block between sentinel comments in AGENTS.md or CLAUDE.md, idempotently.",
3100
3100
  input: import_zod27.z.object({
3101
3101
  file: import_zod27.z.string().min(1).describe("The instruction file to edit in place."),
3102
3102
  budgetTokens: import_zod27.z.number().int().positive().optional(),
@@ -3182,7 +3182,7 @@ var traceCommand = define({
3182
3182
  name: "trace",
3183
3183
  tool: "kb_trace",
3184
3184
  usage: "trace <concept-id> [edges...]",
3185
- 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.',
3185
+ 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".',
3186
3186
  input: import_zod28.z.object({
3187
3187
  bundlePath,
3188
3188
  conceptId,
@@ -3226,7 +3226,7 @@ var unpinCommand = define({
3226
3226
  name: "unpin",
3227
3227
  tool: "kb_unpin",
3228
3228
  usage: "unpin [bundle-path]",
3229
- 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.",
3229
+ description: "Remove a base from every manifest layer that holds it. Reports the layers touched.",
3230
3230
  input: import_zod30.z.object({ bundlePath }),
3231
3231
  fromArgv: (argv, path) => ({ bundlePath: argv[1] ?? path }),
3232
3232
  run: (_ctx, { bundlePath: path }) => unpinBase(process.cwd(), path)
@@ -3254,7 +3254,7 @@ var verifyCommand = define({
3254
3254
  name: "verify",
3255
3255
  tool: "kb_verify",
3256
3256
  usage: "verify <concept-id> --note <text>",
3257
- 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.",
3257
+ 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.",
3258
3258
  input: import_zod32.z.object({
3259
3259
  bundlePath,
3260
3260
  conceptId,
@@ -3283,15 +3283,7 @@ var writeCommand = define({
3283
3283
  name: "write",
3284
3284
  tool: "kb_write",
3285
3285
  usage: "write <type> < record.json",
3286
- description: [
3287
- "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.",
3288
- "",
3289
- "Judgment the tool cannot enforce for you:",
3290
- "- 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.",
3291
- "- 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.",
3292
- "- Prefer a new record over overloading an existing one, and keep each short. A record nobody finishes reading is not durable memory.",
3293
- "- Records are never deleted; supersede instead, so the earlier reasoning stays inspectable."
3294
- ].join("\n"),
3286
+ 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.",
3295
3287
  input: import_zod33.z.object({
3296
3288
  bundlePath,
3297
3289
  type: import_zod33.z.enum(KB_RECORD_TYPES),
@@ -3323,14 +3315,7 @@ var writeDecisionCommand = define({
3323
3315
  name: "write-decision",
3324
3316
  tool: "kb_write_decision",
3325
3317
  usage: "write-decision < decision.json",
3326
- description: [
3327
- "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.",
3328
- "",
3329
- "What belongs in one:",
3330
- '- 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.',
3331
- "- `alternative` is what you turned down and why, not a list of everything considered.",
3332
- "- A reference to material you read goes in `sources`; a reference to code goes in `anchors`; a reference to another record goes in `relatedConceptIds`."
3333
- ].join("\n"),
3318
+ 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.",
3334
3319
  input: import_zod34.z.object({ bundlePath, input: decisionInputSchema }),
3335
3320
  fromArgv: async (_argv, path, stdin) => ({
3336
3321
  bundlePath: path,
@@ -4454,7 +4439,7 @@ function bundleDigest(records, superseded) {
4454
4439
  }
4455
4440
 
4456
4441
  // src/version.ts
4457
- var VERSION = true ? "0.1.13" : "0.0.0-dev";
4442
+ var VERSION = true ? "0.1.14" : "0.0.0-dev";
4458
4443
 
4459
4444
  // src/mcp.ts
4460
4445
  function createKbMcpServer() {