@saasontools/strauss-kb 0.1.5 → 0.1.6
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 +30 -2
- package/dist/{chunk-VOJ6D6OX.js → chunk-BVF7X5VO.js} +2 -2
- package/dist/{chunk-FZIMFPGR.js → chunk-PNSRTKYN.js} +102 -6
- package/dist/chunk-PNSRTKYN.js.map +1 -0
- package/dist/{chunk-KQMGKSPZ.js → chunk-V7TRZ2ER.js} +2 -2
- package/dist/cli-main.cjs +98 -5
- package/dist/cli-main.cjs.map +1 -1
- package/dist/cli-main.js +2 -2
- package/dist/index.cjs +103 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-main.cjs +98 -5
- 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-VOJ6D6OX.js.map → chunk-BVF7X5VO.js.map} +0 -0
- /package/dist/{chunk-KQMGKSPZ.js.map → chunk-V7TRZ2ER.js.map} +0 -0
package/dist/cli-main.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -52,6 +52,7 @@ __export(index_exports, {
|
|
|
52
52
|
KbPinsMalformedError: () => KbPinsMalformedError,
|
|
53
53
|
KbRecordAlreadyExistsError: () => KbRecordAlreadyExistsError,
|
|
54
54
|
KbRecordNotFoundError: () => KbRecordNotFoundError,
|
|
55
|
+
KbSelfVerificationError: () => KbSelfVerificationError,
|
|
55
56
|
KbStore: () => KbStore,
|
|
56
57
|
KbWriteConflictError: () => KbWriteConflictError,
|
|
57
58
|
LOG_FILE: () => LOG_FILE,
|
|
@@ -82,6 +83,7 @@ __export(index_exports, {
|
|
|
82
83
|
kbLogEntrySchema: () => kbLogEntrySchema,
|
|
83
84
|
kbRecordFrontmatterSchema: () => kbRecordFrontmatterSchema,
|
|
84
85
|
kbSourceSchema: () => kbSourceSchema,
|
|
86
|
+
kbVerifiedEventSchema: () => kbVerifiedEventSchema,
|
|
85
87
|
listPins: () => listPins,
|
|
86
88
|
loadQmd: () => loadQmd,
|
|
87
89
|
matchToDiff: () => matchToDiff,
|
|
@@ -154,6 +156,11 @@ var kbActorStampSchema = import_zod.z.object({
|
|
|
154
156
|
by: import_zod.z.string().min(1),
|
|
155
157
|
at: import_zod.z.string().min(1)
|
|
156
158
|
}).passthrough();
|
|
159
|
+
var kbVerifiedEventSchema = kbActorStampSchema.extend({
|
|
160
|
+
note: import_zod.z.string().refine((s) => s.trim().length > 0, {
|
|
161
|
+
message: "note must say what the check found"
|
|
162
|
+
})
|
|
163
|
+
});
|
|
157
164
|
var kbAnchorSchema = import_zod.z.object({
|
|
158
165
|
file: import_zod.z.string().min(1),
|
|
159
166
|
symbol: import_zod.z.string().min(1).optional()
|
|
@@ -238,6 +245,7 @@ var ErrorTypes = /* @__PURE__ */ ((ErrorTypes2) => {
|
|
|
238
245
|
ErrorTypes2["KbRecordAlreadyExists"] = "KbRecordAlreadyExists";
|
|
239
246
|
ErrorTypes2["KbInvalidConceptId"] = "KbInvalidConceptId";
|
|
240
247
|
ErrorTypes2["KbRecordNotFound"] = "KbRecordNotFound";
|
|
248
|
+
ErrorTypes2["KbSelfVerification"] = "KbSelfVerification";
|
|
241
249
|
ErrorTypes2["KbWriteConflict"] = "KbWriteConflict";
|
|
242
250
|
return ErrorTypes2;
|
|
243
251
|
})(ErrorTypes || {});
|
|
@@ -306,6 +314,25 @@ var KbWriteConflictError = class extends BaseError {
|
|
|
306
314
|
}
|
|
307
315
|
conceptId;
|
|
308
316
|
};
|
|
317
|
+
var KbSelfVerificationError = class extends BaseError {
|
|
318
|
+
constructor(conceptId2, actor, generatedBy) {
|
|
319
|
+
super({
|
|
320
|
+
message: `kb: ${conceptId2} was generated by ${generatedBy}, and a record's generator cannot verify it \u2014 only a human or a different actor can`,
|
|
321
|
+
errorType: "KbSelfVerification" /* KbSelfVerification */,
|
|
322
|
+
code: 400,
|
|
323
|
+
fault: "User" /* User */,
|
|
324
|
+
retriable: false,
|
|
325
|
+
reportToUser: true,
|
|
326
|
+
details: { conceptId: conceptId2, actor, generatedBy, action: "refused" }
|
|
327
|
+
});
|
|
328
|
+
this.conceptId = conceptId2;
|
|
329
|
+
this.actor = actor;
|
|
330
|
+
this.generatedBy = generatedBy;
|
|
331
|
+
}
|
|
332
|
+
conceptId;
|
|
333
|
+
actor;
|
|
334
|
+
generatedBy;
|
|
335
|
+
};
|
|
309
336
|
var KbInvalidConceptIdError = class extends BaseError {
|
|
310
337
|
constructor(message, details) {
|
|
311
338
|
super({
|
|
@@ -749,6 +776,40 @@ var KbStore = class {
|
|
|
749
776
|
{ operation: `status:${status}`, by: actor }
|
|
750
777
|
);
|
|
751
778
|
}
|
|
779
|
+
/**
|
|
780
|
+
* Appends one `verified[]` event: who checked the record, when, and what the
|
|
781
|
+
* check found. Append-only — prior events are history, and are spread into
|
|
782
|
+
* the new array untouched rather than reshaped through the write schema.
|
|
783
|
+
*
|
|
784
|
+
* A record's generator cannot verify its own record unless the actor is
|
|
785
|
+
* human: the generator re-reading its own output is not an independent
|
|
786
|
+
* check. The rule runs before the mutation so a refusal never publishes,
|
|
787
|
+
* and the refusal is logged under its own operation name — `mutate` only
|
|
788
|
+
* logs what it publishes.
|
|
789
|
+
*/
|
|
790
|
+
async verify(bundlePath2, conceptId2, note, actor = "unknown", at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
791
|
+
const event = kbVerifiedEventSchema.parse({ by: actor, at, note });
|
|
792
|
+
const existing = await this.read(bundlePath2, conceptId2);
|
|
793
|
+
if (!existing) throw new KbRecordNotFoundError(conceptId2);
|
|
794
|
+
const generatedBy = existing.frontmatter.generated?.by;
|
|
795
|
+
if (generatedBy !== void 0 && actor.toLowerCase() === generatedBy.toLowerCase() && !normalizeActor(actor).startsWith("human:")) {
|
|
796
|
+
await this.record(this.root(bundlePath2), {
|
|
797
|
+
operation: "verify:refused",
|
|
798
|
+
conceptId: conceptId2,
|
|
799
|
+
by: actor
|
|
800
|
+
});
|
|
801
|
+
throw new KbSelfVerificationError(conceptId2, actor, generatedBy);
|
|
802
|
+
}
|
|
803
|
+
return this.mutate(
|
|
804
|
+
bundlePath2,
|
|
805
|
+
conceptId2,
|
|
806
|
+
(frontmatter) => ({
|
|
807
|
+
...frontmatter,
|
|
808
|
+
verified: [...frontmatter.verified ?? [], event]
|
|
809
|
+
}),
|
|
810
|
+
{ operation: "verify", by: actor }
|
|
811
|
+
);
|
|
812
|
+
}
|
|
752
813
|
/**
|
|
753
814
|
* Marks `conceptId` superseded by `replacementId`, and links both directions.
|
|
754
815
|
*
|
|
@@ -1083,6 +1144,11 @@ function matches(record, needle) {
|
|
|
1083
1144
|
(field) => field?.toLowerCase().includes(needle)
|
|
1084
1145
|
);
|
|
1085
1146
|
}
|
|
1147
|
+
function normalizeActor(id) {
|
|
1148
|
+
const colon = id.indexOf(":");
|
|
1149
|
+
if (colon === -1) return id.toLowerCase();
|
|
1150
|
+
return id.slice(0, colon + 1).toLowerCase() + id.slice(colon + 1);
|
|
1151
|
+
}
|
|
1086
1152
|
function digest(contents) {
|
|
1087
1153
|
return (0, import_node_crypto.createHash)("sha256").update(contents).digest("hex");
|
|
1088
1154
|
}
|
|
@@ -2400,8 +2466,37 @@ var validateCommand = define({
|
|
|
2400
2466
|
failsWhen: (result) => Array.isArray(result) && result.length > 0
|
|
2401
2467
|
});
|
|
2402
2468
|
|
|
2403
|
-
// src/commands/
|
|
2469
|
+
// src/commands/verify.ts
|
|
2404
2470
|
var import_zod26 = require("zod");
|
|
2471
|
+
var verifyCommand = define({
|
|
2472
|
+
name: "verify",
|
|
2473
|
+
tool: "kb_verify",
|
|
2474
|
+
usage: "verify <concept-id> --note <text>",
|
|
2475
|
+
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.",
|
|
2476
|
+
input: import_zod26.z.object({
|
|
2477
|
+
bundlePath,
|
|
2478
|
+
conceptId,
|
|
2479
|
+
note: import_zod26.z.string().refine((s) => s.trim().length > 0, {
|
|
2480
|
+
message: "note must say what the check found"
|
|
2481
|
+
})
|
|
2482
|
+
}),
|
|
2483
|
+
fromArgv: (argv, path) => ({
|
|
2484
|
+
bundlePath: path,
|
|
2485
|
+
conceptId: argv[1],
|
|
2486
|
+
note: argvFlag(argv, "--note")
|
|
2487
|
+
}),
|
|
2488
|
+
run: async ({ store, actor, now }, { bundlePath: path, conceptId: id, note }) => {
|
|
2489
|
+
await assertBaseNotFrozen(process.cwd(), path);
|
|
2490
|
+
const record = await store.verify(path, id, note, actor, now());
|
|
2491
|
+
return {
|
|
2492
|
+
conceptId: record.conceptId,
|
|
2493
|
+
verified: record.frontmatter.verified?.length ?? 0
|
|
2494
|
+
};
|
|
2495
|
+
}
|
|
2496
|
+
});
|
|
2497
|
+
|
|
2498
|
+
// src/commands/write.ts
|
|
2499
|
+
var import_zod27 = require("zod");
|
|
2405
2500
|
var writeCommand = define({
|
|
2406
2501
|
name: "write",
|
|
2407
2502
|
tool: "kb_write",
|
|
@@ -2415,9 +2510,9 @@ var writeCommand = define({
|
|
|
2415
2510
|
"- Prefer a new record over overloading an existing one, and keep each short. A record nobody finishes reading is not durable memory.",
|
|
2416
2511
|
"- Records are never deleted; supersede instead, so the earlier reasoning stays inspectable."
|
|
2417
2512
|
].join("\n"),
|
|
2418
|
-
input:
|
|
2513
|
+
input: import_zod27.z.object({
|
|
2419
2514
|
bundlePath,
|
|
2420
|
-
type:
|
|
2515
|
+
type: import_zod27.z.enum(KB_RECORD_TYPES),
|
|
2421
2516
|
input: composeInputSchema
|
|
2422
2517
|
}),
|
|
2423
2518
|
fromArgv: async (argv, path, stdin) => ({
|
|
@@ -2441,7 +2536,7 @@ var writeCommand = define({
|
|
|
2441
2536
|
});
|
|
2442
2537
|
|
|
2443
2538
|
// src/commands/write-decision.ts
|
|
2444
|
-
var
|
|
2539
|
+
var import_zod28 = require("zod");
|
|
2445
2540
|
var writeDecisionCommand = define({
|
|
2446
2541
|
name: "write-decision",
|
|
2447
2542
|
tool: "kb_write_decision",
|
|
@@ -2454,7 +2549,7 @@ var writeDecisionCommand = define({
|
|
|
2454
2549
|
"- `alternative` is what you turned down and why, not a list of everything considered.",
|
|
2455
2550
|
"- A reference to material you read goes in `sources`; a reference to code goes in `anchors`; a reference to another record goes in `relatedConceptIds`."
|
|
2456
2551
|
].join("\n"),
|
|
2457
|
-
input:
|
|
2552
|
+
input: import_zod28.z.object({ bundlePath, input: decisionInputSchema }),
|
|
2458
2553
|
fromArgv: async (_argv, path, stdin) => ({
|
|
2459
2554
|
bundlePath: path,
|
|
2460
2555
|
input: JSON.parse(await stdin())
|
|
@@ -2482,6 +2577,7 @@ var KB_COMMANDS = [
|
|
|
2482
2577
|
statusCommand,
|
|
2483
2578
|
supersedeCommand,
|
|
2484
2579
|
answerCommand,
|
|
2580
|
+
verifyCommand,
|
|
2485
2581
|
loadCommand,
|
|
2486
2582
|
queryCommand,
|
|
2487
2583
|
traceCommand,
|
|
@@ -2645,6 +2741,7 @@ function usage() {
|
|
|
2645
2741
|
KbPinsMalformedError,
|
|
2646
2742
|
KbRecordAlreadyExistsError,
|
|
2647
2743
|
KbRecordNotFoundError,
|
|
2744
|
+
KbSelfVerificationError,
|
|
2648
2745
|
KbStore,
|
|
2649
2746
|
KbWriteConflictError,
|
|
2650
2747
|
LOG_FILE,
|
|
@@ -2675,6 +2772,7 @@ function usage() {
|
|
|
2675
2772
|
kbLogEntrySchema,
|
|
2676
2773
|
kbRecordFrontmatterSchema,
|
|
2677
2774
|
kbSourceSchema,
|
|
2775
|
+
kbVerifiedEventSchema,
|
|
2678
2776
|
listPins,
|
|
2679
2777
|
loadQmd,
|
|
2680
2778
|
matchToDiff,
|