@saasontools/strauss-kb 0.1.20 → 0.1.21
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 +5 -7
- package/dist/{chunk-XDH6J6CH.js → chunk-VXWN62HT.js} +2 -2
- package/dist/{chunk-EXZQZJU2.js → chunk-WVJULVGY.js} +2 -2
- package/dist/{chunk-QQLPJO4R.js → chunk-XBZ7G5R5.js} +78 -49
- package/dist/chunk-XBZ7G5R5.js.map +1 -0
- package/dist/cli-main.cjs +75 -48
- package/dist/cli-main.cjs.map +1 -1
- package/dist/cli-main.js +2 -2
- package/dist/index.cjs +77 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -3
- package/dist/mcp-main.cjs +75 -48
- package/dist/mcp-main.cjs.map +1 -1
- package/dist/mcp-main.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-QQLPJO4R.js.map +0 -1
- /package/dist/{chunk-XDH6J6CH.js.map → chunk-VXWN62HT.js.map} +0 -0
- /package/dist/{chunk-EXZQZJU2.js.map → chunk-WVJULVGY.js.map} +0 -0
package/dist/cli-main.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -434,6 +434,8 @@ var Fault = /* @__PURE__ */ ((Fault2) => {
|
|
|
434
434
|
var ErrorTypes = /* @__PURE__ */ ((ErrorTypes2) => {
|
|
435
435
|
ErrorTypes2["KbRecordAlreadyExists"] = "KbRecordAlreadyExists";
|
|
436
436
|
ErrorTypes2["KbClassifyInput"] = "KbClassifyInput";
|
|
437
|
+
ErrorTypes2["KbFlagConflict"] = "KbFlagConflict";
|
|
438
|
+
ErrorTypes2["KbInvalidActor"] = "KbInvalidActor";
|
|
437
439
|
ErrorTypes2["KbInvalidConceptId"] = "KbInvalidConceptId";
|
|
438
440
|
ErrorTypes2["KbMatchInput"] = "KbMatchInput";
|
|
439
441
|
ErrorTypes2["KbMissingFlagValue"] = "KbMissingFlagValue";
|
|
@@ -534,6 +536,38 @@ var KbSelfVerificationError = class extends BaseError {
|
|
|
534
536
|
actor;
|
|
535
537
|
generatedBy;
|
|
536
538
|
};
|
|
539
|
+
var KbInvalidActorError = class extends BaseError {
|
|
540
|
+
constructor(actor, reason) {
|
|
541
|
+
super({
|
|
542
|
+
message: `kb: actor ${JSON.stringify(actor)} ${reason} \u2014 set STRAUSS_KB_ACTOR, e.g. human:alice or agent:reviewer`,
|
|
543
|
+
errorType: "KbInvalidActor" /* KbInvalidActor */,
|
|
544
|
+
code: 400,
|
|
545
|
+
fault: "User" /* User */,
|
|
546
|
+
retriable: false,
|
|
547
|
+
reportToUser: true,
|
|
548
|
+
details: { actor, reason, action: "refused" }
|
|
549
|
+
});
|
|
550
|
+
this.actor = actor;
|
|
551
|
+
this.reason = reason;
|
|
552
|
+
}
|
|
553
|
+
actor;
|
|
554
|
+
reason;
|
|
555
|
+
};
|
|
556
|
+
var KbFlagConflictError = class extends BaseError {
|
|
557
|
+
constructor(flags) {
|
|
558
|
+
super({
|
|
559
|
+
message: `kb: ${flags.join(" and ")} cannot be combined`,
|
|
560
|
+
errorType: "KbFlagConflict" /* KbFlagConflict */,
|
|
561
|
+
code: 400,
|
|
562
|
+
fault: "User" /* User */,
|
|
563
|
+
retriable: false,
|
|
564
|
+
reportToUser: true,
|
|
565
|
+
details: { flags }
|
|
566
|
+
});
|
|
567
|
+
this.flags = flags;
|
|
568
|
+
}
|
|
569
|
+
flags;
|
|
570
|
+
};
|
|
537
571
|
var KbPackBudgetExceededError = class extends BaseError {
|
|
538
572
|
constructor(recordCount, approxTokens2, budgetTokens, excluded) {
|
|
539
573
|
super({
|
|
@@ -3361,6 +3395,7 @@ var KbStore = class {
|
|
|
3361
3395
|
* its contents.
|
|
3362
3396
|
*/
|
|
3363
3397
|
async write(bundlePath2, input, actor = "unknown") {
|
|
3398
|
+
assertActor(actor);
|
|
3364
3399
|
if (!KB_SLUG_PATTERN.test(input.slug)) {
|
|
3365
3400
|
throw new KbInvalidConceptIdError("slug must be kebab-case", {
|
|
3366
3401
|
slug: input.slug
|
|
@@ -3462,6 +3497,7 @@ var KbStore = class {
|
|
|
3462
3497
|
* timeouts.
|
|
3463
3498
|
*/
|
|
3464
3499
|
async setStatus(bundlePath2, conceptId2, status, actor = "unknown") {
|
|
3500
|
+
assertActor(actor);
|
|
3465
3501
|
return this.mutate(
|
|
3466
3502
|
bundlePath2,
|
|
3467
3503
|
conceptId2,
|
|
@@ -3480,6 +3516,7 @@ var KbStore = class {
|
|
|
3480
3516
|
* the frontmatter must not be published back out under an actor stamp.
|
|
3481
3517
|
*/
|
|
3482
3518
|
async updateAnchors(bundlePath2, conceptId2, anchors, actor = "unknown") {
|
|
3519
|
+
assertActor(actor);
|
|
3483
3520
|
const checked = anchors.map((anchor) => kbAnchorWriteSchema.parse(anchor));
|
|
3484
3521
|
return this.mutate(
|
|
3485
3522
|
bundlePath2,
|
|
@@ -3500,6 +3537,7 @@ var KbStore = class {
|
|
|
3500
3537
|
* logs what it publishes.
|
|
3501
3538
|
*/
|
|
3502
3539
|
async verify(bundlePath2, conceptId2, note, actor = "unknown", at2 = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
3540
|
+
assertActor(actor, { named: true });
|
|
3503
3541
|
const event = kbVerifiedEventSchema.parse({ by: actor, at: at2, note });
|
|
3504
3542
|
const existing = await this.read(bundlePath2, conceptId2);
|
|
3505
3543
|
if (!existing) throw new KbRecordNotFoundError(conceptId2);
|
|
@@ -3530,6 +3568,7 @@ var KbStore = class {
|
|
|
3530
3568
|
* in normal use, and validation drops to catching hand-edits.
|
|
3531
3569
|
*/
|
|
3532
3570
|
async supersede(bundlePath2, conceptId2, replacementId, actor = "unknown") {
|
|
3571
|
+
assertActor(actor);
|
|
3533
3572
|
const replacement = await this.read(bundlePath2, replacementId);
|
|
3534
3573
|
if (!replacement) throw new KbRecordNotFoundError(replacementId);
|
|
3535
3574
|
const superseded = await this.markSuperseded(
|
|
@@ -3553,6 +3592,7 @@ var KbStore = class {
|
|
|
3553
3592
|
}
|
|
3554
3593
|
/** Resolves an open question, stamping who answered and when. */
|
|
3555
3594
|
async answer(bundlePath2, conceptId2, answer, actor = "unknown", at2 = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
3595
|
+
assertActor(actor);
|
|
3556
3596
|
return this.mutate(
|
|
3557
3597
|
bundlePath2,
|
|
3558
3598
|
conceptId2,
|
|
@@ -3579,6 +3619,7 @@ ${answer}
|
|
|
3579
3619
|
* terminal status since the caller listed it is reported, not removed.
|
|
3580
3620
|
*/
|
|
3581
3621
|
async deleteRecord(bundlePath2, conceptId2, expected, actor = "unknown") {
|
|
3622
|
+
assertActor(actor);
|
|
3582
3623
|
const target = this.recordPath(bundlePath2, conceptId2);
|
|
3583
3624
|
const witness = await this.read(bundlePath2, conceptId2);
|
|
3584
3625
|
if (!witness) throw new KbRecordNotFoundError(conceptId2);
|
|
@@ -3882,6 +3923,7 @@ ${answer}
|
|
|
3882
3923
|
* base too, where nothing was written.
|
|
3883
3924
|
*/
|
|
3884
3925
|
async note(bundlePath2, entry) {
|
|
3926
|
+
assertActor(entry.by);
|
|
3885
3927
|
await this.record(this.root(bundlePath2), entry);
|
|
3886
3928
|
}
|
|
3887
3929
|
/**
|
|
@@ -4139,6 +4181,15 @@ function normalizeActor(id) {
|
|
|
4139
4181
|
if (colon === -1) return id.toLowerCase();
|
|
4140
4182
|
return id.slice(0, colon + 1).toLowerCase() + id.slice(colon + 1);
|
|
4141
4183
|
}
|
|
4184
|
+
var KB_ACTOR_PATTERN = /^[A-Za-z][\w-]*(?::[\p{L}\p{M}\p{N}_.@+/-]+)?$/u;
|
|
4185
|
+
function assertActor(actor, { named = false } = {}) {
|
|
4186
|
+
if (!KB_ACTOR_PATTERN.test(actor)) {
|
|
4187
|
+
throw new KbInvalidActorError(actor, "is not kind or kind:name");
|
|
4188
|
+
}
|
|
4189
|
+
if (named && normalizeActor(actor) === "unknown") {
|
|
4190
|
+
throw new KbInvalidActorError(actor, "cannot verify: name who checked");
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4142
4193
|
|
|
4143
4194
|
// src/compose.ts
|
|
4144
4195
|
var import_zod4 = require("zod");
|
|
@@ -5639,19 +5690,11 @@ function argvPositional(argv, ...names) {
|
|
|
5639
5690
|
}
|
|
5640
5691
|
|
|
5641
5692
|
// src/commands/anchor-resolve.ts
|
|
5642
|
-
function resolverSummary(results) {
|
|
5643
|
-
const names = [
|
|
5644
|
-
...new Set(
|
|
5645
|
-
results.flatMap((entry) => entry.resolver ? [entry.resolver] : [])
|
|
5646
|
-
)
|
|
5647
|
-
].sort();
|
|
5648
|
-
return names.length ? `${names.join(" + ")} resolver` : "whole-file";
|
|
5649
|
-
}
|
|
5650
5693
|
var anchorResolveCommand = define({
|
|
5651
5694
|
name: "anchor-resolve",
|
|
5652
5695
|
tool: "kb_anchor_resolve",
|
|
5653
|
-
usage: "anchor-resolve <concept-id> [--repo-root <path>] [--offline] [--rebaseline] [--restamp]",
|
|
5654
|
-
description: "Resolve a record's anchors: stamp a hash onto anchors that lack one, report drift where the code moved. An anchor naming another repository is read from that remote through a bare cache; --offline uses the cache only.
|
|
5696
|
+
usage: "anchor-resolve <concept-id> [--repo-root <path>] [--offline] [--rebaseline] [--restamp] [--check]",
|
|
5697
|
+
description: "Resolve a record's anchors: stamp a hash onto anchors that lack one, report drift where the code moved. An anchor naming another repository is read from that remote through a bare cache; --offline uses the cache only. Never writes verified[]; a judgment is kb_verify. Exits non-zero on drift.",
|
|
5655
5698
|
input: import_zod9.z.object({
|
|
5656
5699
|
bundlePath,
|
|
5657
5700
|
conceptId,
|
|
@@ -5664,6 +5707,9 @@ var anchorResolveCommand = define({
|
|
|
5664
5707
|
),
|
|
5665
5708
|
restamp: import_zod9.z.boolean().optional().describe(
|
|
5666
5709
|
"Refresh `resolved_at` on anchors that already match. Off by default, so a green run writes nothing."
|
|
5710
|
+
),
|
|
5711
|
+
check: import_zod9.z.boolean().optional().describe(
|
|
5712
|
+
"Resolve and report only: no hash, no `resolved_at`, no log entry."
|
|
5667
5713
|
)
|
|
5668
5714
|
}),
|
|
5669
5715
|
fromArgv: (argv, path) => ({
|
|
@@ -5672,9 +5718,24 @@ var anchorResolveCommand = define({
|
|
|
5672
5718
|
repoRoot: argvFlag(argv, "--repo-root"),
|
|
5673
5719
|
offline: argv.includes("--offline"),
|
|
5674
5720
|
rebaseline: argv.includes("--rebaseline"),
|
|
5675
|
-
restamp: argv.includes("--restamp")
|
|
5721
|
+
restamp: argv.includes("--restamp"),
|
|
5722
|
+
check: argv.includes("--check")
|
|
5676
5723
|
}),
|
|
5677
|
-
run: async ({ store, actor, now }, {
|
|
5724
|
+
run: async ({ store, actor, now }, {
|
|
5725
|
+
bundlePath: path,
|
|
5726
|
+
conceptId: id,
|
|
5727
|
+
repoRoot,
|
|
5728
|
+
offline,
|
|
5729
|
+
rebaseline,
|
|
5730
|
+
restamp,
|
|
5731
|
+
check
|
|
5732
|
+
}) => {
|
|
5733
|
+
if (check && (rebaseline || restamp)) {
|
|
5734
|
+
throw new KbFlagConflictError([
|
|
5735
|
+
"check",
|
|
5736
|
+
rebaseline ? "rebaseline" : "restamp"
|
|
5737
|
+
]);
|
|
5738
|
+
}
|
|
5678
5739
|
const root = repoRoot ?? process.cwd();
|
|
5679
5740
|
const record = await store.read(path, id);
|
|
5680
5741
|
if (!record) throw new KbRecordNotFoundError(id);
|
|
@@ -5683,7 +5744,6 @@ var anchorResolveCommand = define({
|
|
|
5683
5744
|
return {
|
|
5684
5745
|
conceptId: id,
|
|
5685
5746
|
results: [],
|
|
5686
|
-
verified: false,
|
|
5687
5747
|
note: "record has no anchors"
|
|
5688
5748
|
};
|
|
5689
5749
|
}
|
|
@@ -5741,7 +5801,7 @@ var anchorResolveCommand = define({
|
|
|
5741
5801
|
if (!anchor.hash) {
|
|
5742
5802
|
results.push({
|
|
5743
5803
|
...base2,
|
|
5744
|
-
state: "stamped",
|
|
5804
|
+
state: check ? "unstamped" : "stamped",
|
|
5745
5805
|
currentHash: stampedHash,
|
|
5746
5806
|
hashKind: stampedKind,
|
|
5747
5807
|
...producedBy ? { resolver: producedBy } : {}
|
|
@@ -5793,7 +5853,7 @@ var anchorResolveCommand = define({
|
|
|
5793
5853
|
if (refresh) dirty = true;
|
|
5794
5854
|
}
|
|
5795
5855
|
let frozen = false;
|
|
5796
|
-
if (dirty) {
|
|
5856
|
+
if (dirty && !check) {
|
|
5797
5857
|
try {
|
|
5798
5858
|
await assertBaseNotFrozen(process.cwd(), path);
|
|
5799
5859
|
} catch (error) {
|
|
@@ -5808,42 +5868,11 @@ var anchorResolveCommand = define({
|
|
|
5808
5868
|
const unreachable = results.filter(
|
|
5809
5869
|
(entry) => isUncheckedReason(entry.reason)
|
|
5810
5870
|
).length;
|
|
5811
|
-
const checked = results.length - unreachable;
|
|
5812
5871
|
const matches3 = results.filter((entry) => entry.state === "match").length;
|
|
5813
|
-
const note = `${matches3}/${
|
|
5814
|
-
const clean = checked > 0 && matches3 === checked && unreachable === 0;
|
|
5815
|
-
if (clean) {
|
|
5816
|
-
try {
|
|
5817
|
-
await store.verify(
|
|
5818
|
-
path,
|
|
5819
|
-
id,
|
|
5820
|
-
`anchor-resolve: ${note} (${resolverSummary(results)})`,
|
|
5821
|
-
actor,
|
|
5822
|
-
now()
|
|
5823
|
-
);
|
|
5824
|
-
} catch (error) {
|
|
5825
|
-
if (!(error instanceof KbSelfVerificationError)) throw error;
|
|
5826
|
-
return {
|
|
5827
|
-
conceptId: id,
|
|
5828
|
-
results,
|
|
5829
|
-
verified: false,
|
|
5830
|
-
verifyRefused: "self-verification",
|
|
5831
|
-
...frozenNote,
|
|
5832
|
-
...hintNote
|
|
5833
|
-
};
|
|
5834
|
-
}
|
|
5835
|
-
return {
|
|
5836
|
-
conceptId: id,
|
|
5837
|
-
results,
|
|
5838
|
-
verified: true,
|
|
5839
|
-
...frozenNote,
|
|
5840
|
-
...hintNote
|
|
5841
|
-
};
|
|
5842
|
-
}
|
|
5872
|
+
const note = `${matches3}/${results.length - unreachable} anchors match, ${unreachable} unreachable`;
|
|
5843
5873
|
return {
|
|
5844
5874
|
conceptId: id,
|
|
5845
5875
|
results,
|
|
5846
|
-
verified: false,
|
|
5847
5876
|
...unreachable ? { note } : {},
|
|
5848
5877
|
...frozenNote,
|
|
5849
5878
|
...hintNote
|
|
@@ -8632,7 +8661,7 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
|
8632
8661
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
8633
8662
|
|
|
8634
8663
|
// src/version.ts
|
|
8635
|
-
var VERSION = true ? "0.1.
|
|
8664
|
+
var VERSION = true ? "0.1.21" : "0.0.0-dev";
|
|
8636
8665
|
|
|
8637
8666
|
// src/mcp.ts
|
|
8638
8667
|
function createKbMcpServer() {
|