@saasontools/strauss-kb 0.1.3 → 0.1.4
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 +25 -1
- package/dist/{chunk-HYNAEAPM.js → chunk-EDH43Z7J.js} +67 -13
- package/dist/chunk-EDH43Z7J.js.map +1 -0
- package/dist/{chunk-FSI4Q2FD.js → chunk-TS26G7TL.js} +2 -2
- package/dist/{chunk-QLTB77W4.js → chunk-Y5C7Z2HG.js} +2 -2
- package/dist/cli-main.cjs +66 -12
- package/dist/cli-main.cjs.map +1 -1
- package/dist/cli-main.js +2 -2
- package/dist/index.cjs +66 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +3 -3
- package/dist/mcp-main.cjs +66 -12
- package/dist/mcp-main.cjs.map +1 -1
- package/dist/mcp-main.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-HYNAEAPM.js.map +0 -1
- /package/dist/{chunk-FSI4Q2FD.js.map → chunk-TS26G7TL.js.map} +0 -0
- /package/dist/{chunk-QLTB77W4.js.map → chunk-Y5C7Z2HG.js.map} +0 -0
package/dist/cli-main.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -270,7 +270,7 @@ var KbRecordAlreadyExistsError = class extends BaseError {
|
|
|
270
270
|
fault: "User" /* User */,
|
|
271
271
|
retriable: false,
|
|
272
272
|
reportToUser: true,
|
|
273
|
-
details: { conceptId: conceptId2 }
|
|
273
|
+
details: { conceptId: conceptId2, action: "refused" }
|
|
274
274
|
});
|
|
275
275
|
this.conceptId = conceptId2;
|
|
276
276
|
}
|
|
@@ -675,13 +675,27 @@ var KbStore = class {
|
|
|
675
675
|
conceptId: conceptId2,
|
|
676
676
|
by: actor
|
|
677
677
|
});
|
|
678
|
+
const targets = new Set(frontmatter.strauss_supersedes ?? []);
|
|
679
|
+
targets.delete(conceptId2);
|
|
680
|
+
const supersededIds = [];
|
|
681
|
+
for (const old of targets) {
|
|
682
|
+
if (await this.markSupersededRetrying(bundlePath2, old, conceptId2, actor)) {
|
|
683
|
+
supersededIds.push(old);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
678
686
|
this.logger.info?.({
|
|
679
687
|
operation: "kb.write",
|
|
680
688
|
bundlePath: root,
|
|
681
689
|
conceptId: conceptId2,
|
|
682
690
|
anchors: frontmatter.strauss_anchors?.length ?? 0
|
|
683
691
|
});
|
|
684
|
-
return {
|
|
692
|
+
return {
|
|
693
|
+
conceptId: conceptId2,
|
|
694
|
+
frontmatter,
|
|
695
|
+
body: input.body,
|
|
696
|
+
action: supersededIds.length ? "superseded-prior" : "created",
|
|
697
|
+
supersededIds
|
|
698
|
+
};
|
|
685
699
|
}
|
|
686
700
|
/** One record by concept id, or null when it does not exist. */
|
|
687
701
|
async read(bundlePath2, conceptId2) {
|
|
@@ -745,15 +759,11 @@ var KbStore = class {
|
|
|
745
759
|
async supersede(bundlePath2, conceptId2, replacementId, actor = "unknown") {
|
|
746
760
|
const replacement = await this.read(bundlePath2, replacementId);
|
|
747
761
|
if (!replacement) throw new KbRecordNotFoundError(replacementId);
|
|
748
|
-
const superseded = await this.
|
|
762
|
+
const superseded = await this.markSuperseded(
|
|
749
763
|
bundlePath2,
|
|
750
764
|
conceptId2,
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
strauss_status: "superseded",
|
|
754
|
-
strauss_superseded_by: replacementId
|
|
755
|
-
}),
|
|
756
|
-
{ operation: "supersede", by: actor, target: replacementId }
|
|
765
|
+
replacementId,
|
|
766
|
+
actor
|
|
757
767
|
);
|
|
758
768
|
await this.mutate(
|
|
759
769
|
bundlePath2,
|
|
@@ -917,6 +927,42 @@ ${answer}
|
|
|
917
927
|
}
|
|
918
928
|
return result;
|
|
919
929
|
}
|
|
930
|
+
/**
|
|
931
|
+
* `markSuperseded`, tolerant of the two ways it legitimately doesn't land:
|
|
932
|
+
* a missing target (a broken link, legal per compose.ts) or a CAS conflict
|
|
933
|
+
* from a concurrent writer touching the same target. A conflict is retried
|
|
934
|
+
* a bounded number of times — each attempt re-reads the target fresh — and
|
|
935
|
+
* on the last, `false` reports "not marked" rather than throwing: the
|
|
936
|
+
* caller's own record is already published, so failing here would leave
|
|
937
|
+
* that publish unreported instead of undone. kb_validate's existing
|
|
938
|
+
* "not marked superseded" check is what surfaces the residue.
|
|
939
|
+
*/
|
|
940
|
+
async markSupersededRetrying(bundlePath2, conceptId2, replacementId, actor, retries = 3) {
|
|
941
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
942
|
+
try {
|
|
943
|
+
await this.markSuperseded(bundlePath2, conceptId2, replacementId, actor);
|
|
944
|
+
return true;
|
|
945
|
+
} catch (error) {
|
|
946
|
+
if (error instanceof KbRecordNotFoundError) return false;
|
|
947
|
+
if (!(error instanceof KbWriteConflictError)) throw error;
|
|
948
|
+
if (attempt === retries) return false;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
/** The one-directional half of `supersede`: marks `conceptId` superseded. */
|
|
954
|
+
async markSuperseded(bundlePath2, conceptId2, replacementId, actor) {
|
|
955
|
+
return this.mutate(
|
|
956
|
+
bundlePath2,
|
|
957
|
+
conceptId2,
|
|
958
|
+
(frontmatter) => ({
|
|
959
|
+
...frontmatter,
|
|
960
|
+
strauss_status: "superseded",
|
|
961
|
+
strauss_superseded_by: replacementId
|
|
962
|
+
}),
|
|
963
|
+
{ operation: "supersede", by: actor, target: replacementId }
|
|
964
|
+
);
|
|
965
|
+
}
|
|
920
966
|
async mutate(bundlePath2, conceptId2, change, entry, changeBody = (body) => body) {
|
|
921
967
|
const target = this.recordPath(bundlePath2, conceptId2);
|
|
922
968
|
const before = await (0, import_promises2.readFile)(target, "utf8").catch(() => null);
|
|
@@ -1133,7 +1179,7 @@ var composeInputSchema = import_zod3.z.object({
|
|
|
1133
1179
|
/** Concept ids this record relates to; rendered as body links. */
|
|
1134
1180
|
relatedConceptIds: import_zod3.z.array(kbConceptIdSchema).optional(),
|
|
1135
1181
|
/** Concept ids this record replaces. The store settles the backlinks. */
|
|
1136
|
-
supersedes: import_zod3.z.array(kbConceptIdSchema).optional(),
|
|
1182
|
+
supersedes: import_zod3.z.array(kbConceptIdSchema).max(32).optional(),
|
|
1137
1183
|
materiality: import_zod3.z.enum(KB_MATERIALITIES).optional(),
|
|
1138
1184
|
confidence: import_zod3.z.enum(KB_CONFIDENCES).optional(),
|
|
1139
1185
|
owner: import_zod3.z.string().min(1).optional()
|
|
@@ -2375,7 +2421,11 @@ var writeCommand = define({
|
|
|
2375
2421
|
composeRecord(type, input, actor, now()),
|
|
2376
2422
|
actor
|
|
2377
2423
|
);
|
|
2378
|
-
return {
|
|
2424
|
+
return {
|
|
2425
|
+
conceptId: record.conceptId,
|
|
2426
|
+
action: record.action,
|
|
2427
|
+
supersededIds: record.supersededIds
|
|
2428
|
+
};
|
|
2379
2429
|
}
|
|
2380
2430
|
});
|
|
2381
2431
|
|
|
@@ -2405,7 +2455,11 @@ var writeDecisionCommand = define({
|
|
|
2405
2455
|
composeDecisionRecord(input, actor, now()),
|
|
2406
2456
|
actor
|
|
2407
2457
|
);
|
|
2408
|
-
return {
|
|
2458
|
+
return {
|
|
2459
|
+
conceptId: record.conceptId,
|
|
2460
|
+
action: record.action,
|
|
2461
|
+
supersededIds: record.supersededIds
|
|
2462
|
+
};
|
|
2409
2463
|
}
|
|
2410
2464
|
});
|
|
2411
2465
|
|