@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.cjs
CHANGED
|
@@ -2348,6 +2348,38 @@ var KbSelfVerificationError = class extends BaseError {
|
|
|
2348
2348
|
actor;
|
|
2349
2349
|
generatedBy;
|
|
2350
2350
|
};
|
|
2351
|
+
var KbInvalidActorError = class extends BaseError {
|
|
2352
|
+
constructor(actor, reason) {
|
|
2353
|
+
super({
|
|
2354
|
+
message: `kb: actor ${JSON.stringify(actor)} ${reason} \u2014 set STRAUSS_KB_ACTOR, e.g. human:alice or agent:reviewer`,
|
|
2355
|
+
errorType: "KbInvalidActor" /* KbInvalidActor */,
|
|
2356
|
+
code: 400,
|
|
2357
|
+
fault: "User" /* User */,
|
|
2358
|
+
retriable: false,
|
|
2359
|
+
reportToUser: true,
|
|
2360
|
+
details: { actor, reason, action: "refused" }
|
|
2361
|
+
});
|
|
2362
|
+
this.actor = actor;
|
|
2363
|
+
this.reason = reason;
|
|
2364
|
+
}
|
|
2365
|
+
actor;
|
|
2366
|
+
reason;
|
|
2367
|
+
};
|
|
2368
|
+
var KbFlagConflictError = class extends BaseError {
|
|
2369
|
+
constructor(flags) {
|
|
2370
|
+
super({
|
|
2371
|
+
message: `kb: ${flags.join(" and ")} cannot be combined`,
|
|
2372
|
+
errorType: "KbFlagConflict" /* KbFlagConflict */,
|
|
2373
|
+
code: 400,
|
|
2374
|
+
fault: "User" /* User */,
|
|
2375
|
+
retriable: false,
|
|
2376
|
+
reportToUser: true,
|
|
2377
|
+
details: { flags }
|
|
2378
|
+
});
|
|
2379
|
+
this.flags = flags;
|
|
2380
|
+
}
|
|
2381
|
+
flags;
|
|
2382
|
+
};
|
|
2351
2383
|
var KbPackBudgetExceededError = class extends BaseError {
|
|
2352
2384
|
constructor(recordCount, approxTokens2, budgetTokens, excluded) {
|
|
2353
2385
|
super({
|
|
@@ -2891,19 +2923,11 @@ function argvPositional(argv, ...names) {
|
|
|
2891
2923
|
}
|
|
2892
2924
|
|
|
2893
2925
|
// src/commands/anchor-resolve.ts
|
|
2894
|
-
function resolverSummary(results) {
|
|
2895
|
-
const names = [
|
|
2896
|
-
...new Set(
|
|
2897
|
-
results.flatMap((entry) => entry.resolver ? [entry.resolver] : [])
|
|
2898
|
-
)
|
|
2899
|
-
].sort();
|
|
2900
|
-
return names.length ? `${names.join(" + ")} resolver` : "whole-file";
|
|
2901
|
-
}
|
|
2902
2926
|
var anchorResolveCommand = define({
|
|
2903
2927
|
name: "anchor-resolve",
|
|
2904
2928
|
tool: "kb_anchor_resolve",
|
|
2905
|
-
usage: "anchor-resolve <concept-id> [--repo-root <path>] [--offline] [--rebaseline] [--restamp]",
|
|
2906
|
-
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.
|
|
2929
|
+
usage: "anchor-resolve <concept-id> [--repo-root <path>] [--offline] [--rebaseline] [--restamp] [--check]",
|
|
2930
|
+
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.",
|
|
2907
2931
|
input: import_zod7.z.object({
|
|
2908
2932
|
bundlePath,
|
|
2909
2933
|
conceptId,
|
|
@@ -2916,6 +2940,9 @@ var anchorResolveCommand = define({
|
|
|
2916
2940
|
),
|
|
2917
2941
|
restamp: import_zod7.z.boolean().optional().describe(
|
|
2918
2942
|
"Refresh `resolved_at` on anchors that already match. Off by default, so a green run writes nothing."
|
|
2943
|
+
),
|
|
2944
|
+
check: import_zod7.z.boolean().optional().describe(
|
|
2945
|
+
"Resolve and report only: no hash, no `resolved_at`, no log entry."
|
|
2919
2946
|
)
|
|
2920
2947
|
}),
|
|
2921
2948
|
fromArgv: (argv, path) => ({
|
|
@@ -2924,9 +2951,24 @@ var anchorResolveCommand = define({
|
|
|
2924
2951
|
repoRoot: argvFlag(argv, "--repo-root"),
|
|
2925
2952
|
offline: argv.includes("--offline"),
|
|
2926
2953
|
rebaseline: argv.includes("--rebaseline"),
|
|
2927
|
-
restamp: argv.includes("--restamp")
|
|
2954
|
+
restamp: argv.includes("--restamp"),
|
|
2955
|
+
check: argv.includes("--check")
|
|
2928
2956
|
}),
|
|
2929
|
-
run: async ({ store, actor, now }, {
|
|
2957
|
+
run: async ({ store, actor, now }, {
|
|
2958
|
+
bundlePath: path,
|
|
2959
|
+
conceptId: id,
|
|
2960
|
+
repoRoot,
|
|
2961
|
+
offline,
|
|
2962
|
+
rebaseline,
|
|
2963
|
+
restamp,
|
|
2964
|
+
check
|
|
2965
|
+
}) => {
|
|
2966
|
+
if (check && (rebaseline || restamp)) {
|
|
2967
|
+
throw new KbFlagConflictError([
|
|
2968
|
+
"check",
|
|
2969
|
+
rebaseline ? "rebaseline" : "restamp"
|
|
2970
|
+
]);
|
|
2971
|
+
}
|
|
2930
2972
|
const root = repoRoot ?? process.cwd();
|
|
2931
2973
|
const record = await store.read(path, id);
|
|
2932
2974
|
if (!record) throw new KbRecordNotFoundError(id);
|
|
@@ -2935,7 +2977,6 @@ var anchorResolveCommand = define({
|
|
|
2935
2977
|
return {
|
|
2936
2978
|
conceptId: id,
|
|
2937
2979
|
results: [],
|
|
2938
|
-
verified: false,
|
|
2939
2980
|
note: "record has no anchors"
|
|
2940
2981
|
};
|
|
2941
2982
|
}
|
|
@@ -2993,7 +3034,7 @@ var anchorResolveCommand = define({
|
|
|
2993
3034
|
if (!anchor.hash) {
|
|
2994
3035
|
results.push({
|
|
2995
3036
|
...base2,
|
|
2996
|
-
state: "stamped",
|
|
3037
|
+
state: check ? "unstamped" : "stamped",
|
|
2997
3038
|
currentHash: stampedHash,
|
|
2998
3039
|
hashKind: stampedKind,
|
|
2999
3040
|
...producedBy ? { resolver: producedBy } : {}
|
|
@@ -3045,7 +3086,7 @@ var anchorResolveCommand = define({
|
|
|
3045
3086
|
if (refresh) dirty = true;
|
|
3046
3087
|
}
|
|
3047
3088
|
let frozen = false;
|
|
3048
|
-
if (dirty) {
|
|
3089
|
+
if (dirty && !check) {
|
|
3049
3090
|
try {
|
|
3050
3091
|
await assertBaseNotFrozen(process.cwd(), path);
|
|
3051
3092
|
} catch (error) {
|
|
@@ -3060,42 +3101,11 @@ var anchorResolveCommand = define({
|
|
|
3060
3101
|
const unreachable = results.filter(
|
|
3061
3102
|
(entry) => isUncheckedReason(entry.reason)
|
|
3062
3103
|
).length;
|
|
3063
|
-
const checked = results.length - unreachable;
|
|
3064
3104
|
const matches3 = results.filter((entry) => entry.state === "match").length;
|
|
3065
|
-
const note = `${matches3}/${
|
|
3066
|
-
const clean = checked > 0 && matches3 === checked && unreachable === 0;
|
|
3067
|
-
if (clean) {
|
|
3068
|
-
try {
|
|
3069
|
-
await store.verify(
|
|
3070
|
-
path,
|
|
3071
|
-
id,
|
|
3072
|
-
`anchor-resolve: ${note} (${resolverSummary(results)})`,
|
|
3073
|
-
actor,
|
|
3074
|
-
now()
|
|
3075
|
-
);
|
|
3076
|
-
} catch (error) {
|
|
3077
|
-
if (!(error instanceof KbSelfVerificationError)) throw error;
|
|
3078
|
-
return {
|
|
3079
|
-
conceptId: id,
|
|
3080
|
-
results,
|
|
3081
|
-
verified: false,
|
|
3082
|
-
verifyRefused: "self-verification",
|
|
3083
|
-
...frozenNote,
|
|
3084
|
-
...hintNote
|
|
3085
|
-
};
|
|
3086
|
-
}
|
|
3087
|
-
return {
|
|
3088
|
-
conceptId: id,
|
|
3089
|
-
results,
|
|
3090
|
-
verified: true,
|
|
3091
|
-
...frozenNote,
|
|
3092
|
-
...hintNote
|
|
3093
|
-
};
|
|
3094
|
-
}
|
|
3105
|
+
const note = `${matches3}/${results.length - unreachable} anchors match, ${unreachable} unreachable`;
|
|
3095
3106
|
return {
|
|
3096
3107
|
conceptId: id,
|
|
3097
3108
|
results,
|
|
3098
|
-
verified: false,
|
|
3099
3109
|
...unreachable ? { note } : {},
|
|
3100
3110
|
...frozenNote,
|
|
3101
3111
|
...hintNote
|
|
@@ -7652,6 +7662,7 @@ var KbStore = class {
|
|
|
7652
7662
|
* its contents.
|
|
7653
7663
|
*/
|
|
7654
7664
|
async write(bundlePath2, input, actor = "unknown") {
|
|
7665
|
+
assertActor(actor);
|
|
7655
7666
|
if (!KB_SLUG_PATTERN.test(input.slug)) {
|
|
7656
7667
|
throw new KbInvalidConceptIdError("slug must be kebab-case", {
|
|
7657
7668
|
slug: input.slug
|
|
@@ -7753,6 +7764,7 @@ var KbStore = class {
|
|
|
7753
7764
|
* timeouts.
|
|
7754
7765
|
*/
|
|
7755
7766
|
async setStatus(bundlePath2, conceptId2, status, actor = "unknown") {
|
|
7767
|
+
assertActor(actor);
|
|
7756
7768
|
return this.mutate(
|
|
7757
7769
|
bundlePath2,
|
|
7758
7770
|
conceptId2,
|
|
@@ -7771,6 +7783,7 @@ var KbStore = class {
|
|
|
7771
7783
|
* the frontmatter must not be published back out under an actor stamp.
|
|
7772
7784
|
*/
|
|
7773
7785
|
async updateAnchors(bundlePath2, conceptId2, anchors, actor = "unknown") {
|
|
7786
|
+
assertActor(actor);
|
|
7774
7787
|
const checked = anchors.map((anchor) => kbAnchorWriteSchema.parse(anchor));
|
|
7775
7788
|
return this.mutate(
|
|
7776
7789
|
bundlePath2,
|
|
@@ -7791,6 +7804,7 @@ var KbStore = class {
|
|
|
7791
7804
|
* logs what it publishes.
|
|
7792
7805
|
*/
|
|
7793
7806
|
async verify(bundlePath2, conceptId2, note, actor = "unknown", at2 = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
7807
|
+
assertActor(actor, { named: true });
|
|
7794
7808
|
const event = kbVerifiedEventSchema.parse({ by: actor, at: at2, note });
|
|
7795
7809
|
const existing = await this.read(bundlePath2, conceptId2);
|
|
7796
7810
|
if (!existing) throw new KbRecordNotFoundError(conceptId2);
|
|
@@ -7821,6 +7835,7 @@ var KbStore = class {
|
|
|
7821
7835
|
* in normal use, and validation drops to catching hand-edits.
|
|
7822
7836
|
*/
|
|
7823
7837
|
async supersede(bundlePath2, conceptId2, replacementId, actor = "unknown") {
|
|
7838
|
+
assertActor(actor);
|
|
7824
7839
|
const replacement = await this.read(bundlePath2, replacementId);
|
|
7825
7840
|
if (!replacement) throw new KbRecordNotFoundError(replacementId);
|
|
7826
7841
|
const superseded = await this.markSuperseded(
|
|
@@ -7844,6 +7859,7 @@ var KbStore = class {
|
|
|
7844
7859
|
}
|
|
7845
7860
|
/** Resolves an open question, stamping who answered and when. */
|
|
7846
7861
|
async answer(bundlePath2, conceptId2, answer, actor = "unknown", at2 = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
7862
|
+
assertActor(actor);
|
|
7847
7863
|
return this.mutate(
|
|
7848
7864
|
bundlePath2,
|
|
7849
7865
|
conceptId2,
|
|
@@ -7870,6 +7886,7 @@ ${answer}
|
|
|
7870
7886
|
* terminal status since the caller listed it is reported, not removed.
|
|
7871
7887
|
*/
|
|
7872
7888
|
async deleteRecord(bundlePath2, conceptId2, expected, actor = "unknown") {
|
|
7889
|
+
assertActor(actor);
|
|
7873
7890
|
const target = this.recordPath(bundlePath2, conceptId2);
|
|
7874
7891
|
const witness = await this.read(bundlePath2, conceptId2);
|
|
7875
7892
|
if (!witness) throw new KbRecordNotFoundError(conceptId2);
|
|
@@ -8173,6 +8190,7 @@ ${answer}
|
|
|
8173
8190
|
* base too, where nothing was written.
|
|
8174
8191
|
*/
|
|
8175
8192
|
async note(bundlePath2, entry) {
|
|
8193
|
+
assertActor(entry.by);
|
|
8176
8194
|
await this.record(this.root(bundlePath2), entry);
|
|
8177
8195
|
}
|
|
8178
8196
|
/**
|
|
@@ -8430,9 +8448,18 @@ function normalizeActor(id) {
|
|
|
8430
8448
|
if (colon === -1) return id.toLowerCase();
|
|
8431
8449
|
return id.slice(0, colon + 1).toLowerCase() + id.slice(colon + 1);
|
|
8432
8450
|
}
|
|
8451
|
+
var KB_ACTOR_PATTERN = /^[A-Za-z][\w-]*(?::[\p{L}\p{M}\p{N}_.@+/-]+)?$/u;
|
|
8452
|
+
function assertActor(actor, { named = false } = {}) {
|
|
8453
|
+
if (!KB_ACTOR_PATTERN.test(actor)) {
|
|
8454
|
+
throw new KbInvalidActorError(actor, "is not kind or kind:name");
|
|
8455
|
+
}
|
|
8456
|
+
if (named && normalizeActor(actor) === "unknown") {
|
|
8457
|
+
throw new KbInvalidActorError(actor, "cannot verify: name who checked");
|
|
8458
|
+
}
|
|
8459
|
+
}
|
|
8433
8460
|
|
|
8434
8461
|
// src/version.ts
|
|
8435
|
-
var VERSION = true ? "0.1.
|
|
8462
|
+
var VERSION = true ? "0.1.21" : "0.0.0-dev";
|
|
8436
8463
|
|
|
8437
8464
|
// src/cli.ts
|
|
8438
8465
|
async function runKbCli(argv) {
|