kibi-cli 2.22.1 → 2.23.0
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/cli-register-foundation.d.ts.map +1 -1
- package/dist/cli-register-foundation.js +1 -0
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +51 -3
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +28 -0
- package/dist/commands/migrate.d.ts +10 -0
- package/dist/commands/migrate.d.ts.map +1 -1
- package/dist/commands/migrate.js +58 -9
- package/dist/commands/sync.d.ts.map +1 -1
- package/dist/commands/sync.js +15 -1
- package/dist/extractors/markdown.d.ts.map +1 -1
- package/dist/extractors/markdown.js +37 -35
- package/dist/intent-search.d.ts.map +1 -1
- package/dist/intent-search.js +32 -4
- package/dist/operations/bootstrap/activation.d.ts +7 -1
- package/dist/operations/bootstrap/activation.d.ts.map +1 -1
- package/dist/operations/bootstrap/activation.js +27 -2
- package/dist/operations/bootstrap/generate.d.ts.map +1 -1
- package/dist/operations/bootstrap/generate.js +56 -16
- package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
- package/dist/operations/bootstrap/guidance-actions.js +14 -2
- package/dist/operations/bootstrap/guidance.d.ts.map +1 -1
- package/dist/operations/bootstrap/guidance.js +6 -2
- package/dist/operations/bootstrap/presentation.d.ts.map +1 -1
- package/dist/operations/bootstrap/presentation.js +75 -9
- package/dist/operations/bootstrap/types.d.ts +6 -0
- package/dist/operations/bootstrap/types.d.ts.map +1 -1
- package/dist/operations/migration/kb-sources.d.ts +8 -5
- package/dist/operations/migration/kb-sources.d.ts.map +1 -1
- package/dist/operations/migration/kb-sources.js +50 -14
- package/dist/operations/migration/schema6.d.ts.map +1 -1
- package/dist/operations/migration/schema6.js +11 -2
- package/dist/operations/migration/source-paths.d.ts +18 -1
- package/dist/operations/migration/source-paths.d.ts.map +1 -1
- package/dist/operations/migration/source-paths.js +111 -16
- package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
- package/dist/operations/modeling/suggest-predicates.js +22 -7
- package/dist/operations/mutation/requirement-semantics.d.ts +16 -0
- package/dist/operations/mutation/requirement-semantics.d.ts.map +1 -1
- package/dist/operations/mutation/requirement-semantics.js +50 -0
- package/dist/operations/mutation/strict-fact.js +1 -1
- package/dist/operations/mutation/upsert.d.ts.map +1 -1
- package/dist/operations/mutation/upsert.js +2 -1
- package/dist/operations/planning/apply-plan.d.ts.map +1 -1
- package/dist/operations/planning/apply-plan.js +22 -2
- package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
- package/dist/operations/semantic-advisor/analyze-prose.js +49 -17
- package/dist/public/impact/analyzer.d.ts.map +1 -1
- package/dist/public/impact/analyzer.js +7 -1
- package/dist/public/impact/diagnostics.d.ts.map +1 -1
- package/dist/public/impact/diagnostics.js +16 -3
- package/dist/public/impact/types.d.ts +2 -0
- package/dist/public/impact/types.d.ts.map +1 -1
- package/dist/public/operations/catalog.d.ts +7 -2
- package/dist/public/operations/catalog.d.ts.map +1 -1
- package/dist/public/operations/check-executor.d.ts.map +1 -1
- package/dist/public/operations/check-executor.js +10 -3
- package/dist/public/operations/check-helpers.d.ts +10 -0
- package/dist/public/operations/check-helpers.d.ts.map +1 -1
- package/dist/public/operations/check-helpers.js +54 -0
- package/dist/public/operations/contracts.d.ts.map +1 -1
- package/dist/public/operations/contracts.js +1 -0
- package/dist/public/operations/discovery-executors.d.ts +18 -0
- package/dist/public/operations/discovery-executors.d.ts.map +1 -1
- package/dist/public/operations/discovery-executors.js +62 -3
- package/dist/public/operations/schema6-check-actions.d.ts +4 -0
- package/dist/public/operations/schema6-check-actions.d.ts.map +1 -1
- package/dist/public/operations/schema6-check-actions.js +39 -2
- package/dist/public/operations/source-path-dangling.d.ts +1 -1
- package/dist/public/operations/source-path-dangling.d.ts.map +1 -1
- package/dist/public/operations/source-path-dangling.js +11 -2
- package/dist/public/operations/specs/composite.d.ts +1 -1
- package/dist/public/operations/specs/discovery.d.ts +5 -0
- package/dist/public/operations/specs/discovery.d.ts.map +1 -1
- package/dist/public/operations/specs/discovery.js +5 -0
- package/dist/public/operations/specs/planning.d.ts +1 -1
- package/dist/public/operations/specs/planning.js +1 -1
- package/dist/public/operations/specs/reporting.d.ts.map +1 -1
- package/dist/public/operations/specs/reporting.js +6 -4
- package/dist/public/operations/specs/semantic.d.ts +1 -1
- package/dist/public/operations/specs/semantic.d.ts.map +1 -1
- package/dist/public/operations/specs/semantic.js +4 -2
- package/dist/public/skills/kibi-bootstrap/SKILL.md +3 -2
- package/dist/public/skills/kibi-usage/SKILL.md +6 -3
- package/dist/public/skills/kibi-usage/resources/workflows.md +3 -1
- package/dist/search-answer.d.ts +14 -0
- package/dist/search-answer.d.ts.map +1 -1
- package/dist/search-answer.js +42 -4
- package/dist/traceability/git-change-snapshot.d.ts +46 -0
- package/dist/traceability/git-change-snapshot.d.ts.map +1 -1
- package/dist/traceability/git-change-snapshot.js +187 -3
- package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
- package/dist/traceability/staged-diagnostics.js +5 -6
- package/dist/traceability/staged-inventory-drift.d.ts +24 -0
- package/dist/traceability/staged-inventory-drift.d.ts.map +1 -0
- package/dist/traceability/staged-inventory-drift.js +84 -0
- package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
- package/dist/traceability/staged-symbols-manifest.js +1 -2
- package/dist/utils/content-freshness.d.ts +9 -0
- package/dist/utils/content-freshness.d.ts.map +1 -1
- package/dist/utils/content-freshness.js +33 -0
- package/dist/utils/merge-driver-setup.d.ts +10 -0
- package/dist/utils/merge-driver-setup.d.ts.map +1 -0
- package/dist/utils/merge-driver-setup.js +69 -0
- package/dist/utils/rule-registry.generated.d.ts +1 -1
- package/dist/utils/rule-registry.generated.js +1 -1
- package/package.json +2 -2
- package/src/public/impact/analyzer.ts +13 -1
- package/src/public/impact/diagnostics.ts +20 -3
- package/src/public/impact/types.ts +2 -0
- package/src/public/operations/check-executor.ts +16 -4
- package/src/public/operations/check-helpers.ts +65 -0
- package/src/public/operations/contracts.ts +1 -0
- package/src/public/operations/discovery-executors.ts +97 -3
- package/src/public/operations/schema6-check-actions.ts +43 -2
- package/src/public/operations/source-path-dangling.ts +12 -2
- package/src/public/operations/specs/discovery.ts +6 -0
- package/src/public/operations/specs/planning.ts +1 -1
- package/src/public/operations/specs/reporting.ts +6 -4
- package/src/public/operations/specs/semantic.ts +4 -2
- package/src/public/skills/kibi-bootstrap/SKILL.md +3 -2
- package/src/public/skills/kibi-usage/SKILL.md +6 -3
- package/src/public/skills/kibi-usage/resources/workflows.md +3 -1
|
@@ -568,6 +568,9 @@ export function buildLifecycleRepairActions(workspaceRoot) {
|
|
|
568
568
|
continue;
|
|
569
569
|
actions.push(migrationAction(sourcePathReviewActionInput({
|
|
570
570
|
entityId: repair.entityId,
|
|
571
|
+
...(repair.field === "text_ref"
|
|
572
|
+
? { field: "text_ref" }
|
|
573
|
+
: {}),
|
|
571
574
|
value: repair.value,
|
|
572
575
|
file: repair.file,
|
|
573
576
|
reason: repair.refused,
|
|
@@ -622,12 +625,18 @@ function plannedRecords(value) {
|
|
|
622
625
|
// implements REQ-kibi-schema6-migration
|
|
623
626
|
function plannedRepairs(action) {
|
|
624
627
|
const rewrites = [];
|
|
625
|
-
for (const { entityId, file, from, to } of plannedRecords(action.evidence.rewrites)) {
|
|
628
|
+
for (const { entityId, file, field, from, to } of plannedRecords(action.evidence.rewrites)) {
|
|
626
629
|
if (typeof entityId === "string" &&
|
|
627
630
|
typeof file === "string" &&
|
|
628
631
|
typeof from === "string" &&
|
|
629
632
|
typeof to === "string") {
|
|
630
|
-
rewrites.push({
|
|
633
|
+
rewrites.push({
|
|
634
|
+
entityId,
|
|
635
|
+
file,
|
|
636
|
+
...(field === "text_ref" ? { field } : {}),
|
|
637
|
+
from,
|
|
638
|
+
to,
|
|
639
|
+
});
|
|
631
640
|
}
|
|
632
641
|
}
|
|
633
642
|
const removals = [];
|
|
@@ -10,10 +10,23 @@
|
|
|
10
10
|
* names the entity's own file or nothing Kibi can map is removed. A value
|
|
11
11
|
* naming another existing workspace path, an entity id or an http(s) URL is
|
|
12
12
|
* provenance and stays.
|
|
13
|
+
*
|
|
14
|
+
* `text_ref` points at independent evidence, so it is never dead data, but
|
|
15
|
+
* the same pre-canonical paths survive in it. A `text_ref` value shaped
|
|
16
|
+
* like one workspace file path (no spaces, a directory and an extension)
|
|
17
|
+
* that names nothing is dangling too: a moved knowledge file is rewritten
|
|
18
|
+
* to its `.kb/` path, and anything else needs a person, because Kibi cannot
|
|
19
|
+
* tell what evidence it meant. Prose, entity ids, URLs and lists in
|
|
20
|
+
* `text_ref` are not paths and are never judged.
|
|
13
21
|
*/
|
|
14
|
-
/**
|
|
22
|
+
/** The authored frontmatter fields that name workspace files. */
|
|
23
|
+
export type SourceField = "source" | "text_ref";
|
|
24
|
+
/** One authored `source` or `text_ref` value and the entity file that carries it. */
|
|
15
25
|
export type AuthoredSourceRef = Readonly<{
|
|
16
26
|
entityId: string;
|
|
27
|
+
field: SourceField;
|
|
28
|
+
/** A `text_ref` that is its requirement's semantic source: rewriting it changes the inventory hash. */
|
|
29
|
+
semanticSource?: boolean;
|
|
17
30
|
/** Workspace-relative, `/`-separated path of the entity's own file. */
|
|
18
31
|
file: string;
|
|
19
32
|
value: unknown;
|
|
@@ -52,6 +65,8 @@ export type SourceRepair = AuthoredSourceRef & Readonly<{
|
|
|
52
65
|
/** Why the value cannot be edited safely; a person must edit it. */
|
|
53
66
|
refused?: string;
|
|
54
67
|
}>;
|
|
68
|
+
/** Whether a `text_ref` value reads as one workspace file path. */
|
|
69
|
+
export declare function isPathShapedTextRef(value: unknown): boolean;
|
|
55
70
|
/** An authored value as plain text, the form plans record and compare. */
|
|
56
71
|
export declare function shownSourceValue(value: unknown): string;
|
|
57
72
|
/**
|
|
@@ -93,6 +108,8 @@ export declare function findSourceRepairs(workspaceRoot: string): SourceRepair[]
|
|
|
93
108
|
export type SourcePathRewrite = Readonly<{
|
|
94
109
|
entityId: string;
|
|
95
110
|
file: string;
|
|
111
|
+
/** The field rewritten; absent means `source`. */
|
|
112
|
+
field?: "text_ref";
|
|
96
113
|
from: string;
|
|
97
114
|
to: string;
|
|
98
115
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-paths.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/source-paths.ts"],"names":[],"mappings":"AA+BA
|
|
1
|
+
{"version":3,"file":"source-paths.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/source-paths.ts"],"names":[],"mappings":"AA+BA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,iEAAiE;AAEjE,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,qFAAqF;AAErF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,WAAW,CAAC;IACnB,uGAAuG;IACvG,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,uEAAuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC,CAAC;AAGH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,IAAI,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACnC,sDAAsD;IACtD,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAChC,CAAC,CAAC;AAGH,MAAM,MAAM,gBAAgB,GACxB,QAAQ,CAAC;IAAE,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAA;CAAE,CAAC;AAC3D,kGAAkG;GAChG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAAC,GAC7C,QAAQ,CAAC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAErD,6DAA6D;AAE7D,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,UAAU,CAAC;AAEtD,oEAAoE;AAEpE,MAAM,MAAM,SAAS,GACjB,QAAQ,CAAC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GACzC,QAAQ,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAAC;AAE9D,4EAA4E;AAE5E,MAAM,MAAM,YAAY,GAAG,iBAAiB,GAC1C,QAAQ,CAAC;IACP,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,EAAE,SAAS,CAAC;IACf,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAqBL,mEAAmE;AAEnE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM3D;AAYD,0EAA0E;AAE1E,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AAEH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,kBAAkB,CAqD7E;AAID;;;;;;;;GAQG;AAEH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,QAAQ,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;IAC1C,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC,GACD,gBAAgB,CAqClB;AAED,2DAA2D;AAE3D,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,GACpB,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAenC;AAgHD;;;;GAIG;AAEH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,EAAE,CAKzE;AAED;;;;GAIG;AAEH,wBAAgB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,EAAE,CAEvE;AAGD,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC,CAAC;AAGH,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,mBAAmB,CAAC;CAC7B,CAAC,CAAC;AAGH,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACvC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACxC,CAAC,CAAC;AAGH,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,SAAS,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACxC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACtC,OAAO,EAAE,SAAS,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAC;CAChE,CAAC,CAAC;AAgBH;;;GAGG;AAEH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,YAAY,EAAE,GAC/B,wBAAwB,CAU1B;AAwBD;;;;;;;GAOG;AAEH,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,wBAAwB,GACjC,sBAAsB,CAsDxB"}
|
|
@@ -23,6 +23,21 @@ const URL_PATTERN = /^https?:\/\/\S+$/i;
|
|
|
23
23
|
const LEGACY_ROOT = "documentation/";
|
|
24
24
|
const SYMBOL_ID_LINE = /^[ \t]*-?[ \t]*id[ \t]*:[ \t]*(.+?)[ \t]*$/gm;
|
|
25
25
|
const SOURCE_EDIT_REFUSED = "the source field spans several lines, or editing it would change other frontmatter fields";
|
|
26
|
+
const TEXT_REF_EDIT_REFUSED = "the text_ref field spans several lines, or editing it would change other frontmatter fields";
|
|
27
|
+
const TEXT_REF_UNMAPPED = "no file under .kb/ matches it, so Kibi cannot tell what evidence it meant";
|
|
28
|
+
const TEXT_REF_SEMANTIC_SOURCE = "text_ref is this requirement's semantic source, so changing it changes its semantic inventory hash; re-derive the inventory after editing it";
|
|
29
|
+
/** One workspace file path: a directory, a file name with an extension, no spaces. */
|
|
30
|
+
const FILE_PATH_SHAPE = /^(?:\.\/)?[^\s;,:]+\/[^\s;,:/]+\.[A-Za-z0-9]+(?:#\S*)?$/;
|
|
31
|
+
function editRefusedReason(field) {
|
|
32
|
+
return field === "text_ref" ? TEXT_REF_EDIT_REFUSED : SOURCE_EDIT_REFUSED;
|
|
33
|
+
}
|
|
34
|
+
/** Whether a `text_ref` value reads as one workspace file path. */
|
|
35
|
+
// implements REQ-core-validation-rules, REQ-kibi-kb-lifecycle-integrity
|
|
36
|
+
export function isPathShapedTextRef(value) {
|
|
37
|
+
return (typeof value === "string" &&
|
|
38
|
+
!URL_PATTERN.test(value.trim()) &&
|
|
39
|
+
FILE_PATH_SHAPE.test(value.trim()));
|
|
40
|
+
}
|
|
26
41
|
function scalarText(value) {
|
|
27
42
|
if (typeof value === "string")
|
|
28
43
|
return value.trim();
|
|
@@ -58,11 +73,33 @@ export function scanAuthoredSources(workspaceRoot) {
|
|
|
58
73
|
path.basename(file.relativePath, ".md");
|
|
59
74
|
entityIds.add(id);
|
|
60
75
|
const value = readTopLevelField(slice.text, "source");
|
|
61
|
-
if (value
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
76
|
+
if (value !== undefined &&
|
|
77
|
+
value !== null &&
|
|
78
|
+
!(typeof value === "string" && value.trim() === "")) {
|
|
79
|
+
refs.push({
|
|
80
|
+
entityId: id,
|
|
81
|
+
field: "source",
|
|
82
|
+
file: file.relativePath,
|
|
83
|
+
value,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
const textRef = readTopLevelField(slice.text, "text_ref");
|
|
87
|
+
if (isPathShapedTextRef(textRef)) {
|
|
88
|
+
const declared = readTopLevelField(slice.text, "semantic_source_field");
|
|
89
|
+
const requirement = readTopLevelField(slice.text, "type") === "req" ||
|
|
90
|
+
file.relativePath.startsWith(`${KB_PATHS.lanes.requirements}/`);
|
|
91
|
+
const semanticSource = declared === "text_ref" ||
|
|
92
|
+
(requirement &&
|
|
93
|
+
declared === undefined &&
|
|
94
|
+
readTopLevelField(slice.text, "semantic_text") === undefined);
|
|
95
|
+
refs.push({
|
|
96
|
+
entityId: id,
|
|
97
|
+
field: "text_ref",
|
|
98
|
+
...(semanticSource ? { semanticSource } : {}),
|
|
99
|
+
file: file.relativePath,
|
|
100
|
+
value: textRef,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
66
103
|
}
|
|
67
104
|
const symbols = readText(path.join(workspaceRoot, KB_PATHS.symbolsManifest));
|
|
68
105
|
if (symbols !== null) {
|
|
@@ -148,6 +185,34 @@ export function workspacePathExists(workspaceRoot) {
|
|
|
148
185
|
};
|
|
149
186
|
}
|
|
150
187
|
function repairFor(ref, resolution) {
|
|
188
|
+
if (ref.field === "text_ref") {
|
|
189
|
+
// A text_ref naming its own existing file is evidence, not redundancy.
|
|
190
|
+
if (resolution.kind === "self" && resolution.resolves)
|
|
191
|
+
return undefined;
|
|
192
|
+
if (resolution.kind !== "dangling" && resolution.kind !== "self") {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
// A pre-canonical spelling of the entity's own file moved with it.
|
|
196
|
+
const rewrite = resolution.kind === "dangling" ? resolution.rewrite : ref.file;
|
|
197
|
+
if (ref.semanticSource === true) {
|
|
198
|
+
return {
|
|
199
|
+
...ref,
|
|
200
|
+
dangling: true,
|
|
201
|
+
fix: rewrite !== undefined
|
|
202
|
+
? { kind: "rewrite", to: rewrite }
|
|
203
|
+
: { kind: "remove", reason: "dangling" },
|
|
204
|
+
refused: TEXT_REF_SEMANTIC_SOURCE,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return rewrite !== undefined
|
|
208
|
+
? { ...ref, dangling: true, fix: { kind: "rewrite", to: rewrite } }
|
|
209
|
+
: {
|
|
210
|
+
...ref,
|
|
211
|
+
dangling: true,
|
|
212
|
+
fix: { kind: "remove", reason: "dangling" },
|
|
213
|
+
refused: TEXT_REF_UNMAPPED,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
151
216
|
if (resolution.kind === "self") {
|
|
152
217
|
return {
|
|
153
218
|
...ref,
|
|
@@ -165,10 +230,10 @@ function repairFor(ref, resolution) {
|
|
|
165
230
|
: { kind: "remove", reason: "dangling" },
|
|
166
231
|
};
|
|
167
232
|
}
|
|
168
|
-
function editedContent(content, fix) {
|
|
233
|
+
function editedContent(content, field, fix) {
|
|
169
234
|
return fix.kind === "rewrite"
|
|
170
|
-
? withTopLevelField(content,
|
|
171
|
-
: withoutTopLevelField(content,
|
|
235
|
+
? withTopLevelField(content, field, fix.to)
|
|
236
|
+
: withoutTopLevelField(content, field);
|
|
172
237
|
}
|
|
173
238
|
/** Every repairable source value, sorted by entity id. Read-only. */
|
|
174
239
|
function classifySources(workspaceRoot) {
|
|
@@ -186,20 +251,24 @@ function classifySources(workspaceRoot) {
|
|
|
186
251
|
repairs.push(repair);
|
|
187
252
|
}
|
|
188
253
|
return repairs.sort((left, right) => left.entityId.localeCompare(right.entityId) ||
|
|
189
|
-
left.file.localeCompare(right.file)
|
|
254
|
+
left.file.localeCompare(right.file) ||
|
|
255
|
+
left.field.localeCompare(right.field));
|
|
190
256
|
}
|
|
191
257
|
/** Mark the repairs whose edit would not read back as exactly that change. */
|
|
192
258
|
function withEditability(workspaceRoot, repairs) {
|
|
193
259
|
return repairs.map((repair) => {
|
|
260
|
+
if (repair.refused !== undefined)
|
|
261
|
+
return repair;
|
|
194
262
|
const content = readText(path.join(workspaceRoot, repair.file));
|
|
195
|
-
if (content !== null &&
|
|
263
|
+
if (content !== null &&
|
|
264
|
+
editedContent(content, repair.field, repair.fix) !== null) {
|
|
196
265
|
return repair;
|
|
197
266
|
}
|
|
198
267
|
return {
|
|
199
268
|
...repair,
|
|
200
269
|
refused: content === null
|
|
201
270
|
? "the entity file cannot be read"
|
|
202
|
-
:
|
|
271
|
+
: editRefusedReason(repair.field),
|
|
203
272
|
};
|
|
204
273
|
});
|
|
205
274
|
}
|
|
@@ -225,6 +294,7 @@ function plannedRepair(repair) {
|
|
|
225
294
|
const base = {
|
|
226
295
|
entityId: repair.entityId,
|
|
227
296
|
file: repair.file,
|
|
297
|
+
...(repair.field === "text_ref" ? { field: "text_ref" } : {}),
|
|
228
298
|
from: shownSourceValue(repair.value),
|
|
229
299
|
};
|
|
230
300
|
return repair.fix.kind === "rewrite"
|
|
@@ -250,8 +320,18 @@ export function plannedSourcePathRepairs(repairs) {
|
|
|
250
320
|
}
|
|
251
321
|
return { rewrites, removals };
|
|
252
322
|
}
|
|
323
|
+
function plannedField(repair) {
|
|
324
|
+
return "field" in repair && repair.field === "text_ref"
|
|
325
|
+
? "text_ref"
|
|
326
|
+
: "source";
|
|
327
|
+
}
|
|
328
|
+
function plannedKey(file, field) {
|
|
329
|
+
return `${field}\0${file}`;
|
|
330
|
+
}
|
|
253
331
|
function samePlannedRepair(left, right) {
|
|
254
|
-
if (left.entityId !== right.entityId ||
|
|
332
|
+
if (left.entityId !== right.entityId ||
|
|
333
|
+
left.from !== right.from ||
|
|
334
|
+
plannedField(left) !== plannedField(right)) {
|
|
255
335
|
return false;
|
|
256
336
|
}
|
|
257
337
|
if ("to" in left)
|
|
@@ -271,16 +351,26 @@ export function applySourcePathRepairs(workspaceRoot, planned) {
|
|
|
271
351
|
const wanted = planned === undefined
|
|
272
352
|
? undefined
|
|
273
353
|
: new Map([...planned.rewrites, ...planned.removals].map((repair) => [
|
|
274
|
-
repair.file,
|
|
354
|
+
plannedKey(repair.file, plannedField(repair)),
|
|
275
355
|
repair,
|
|
276
356
|
]));
|
|
277
357
|
const rewritten = [];
|
|
278
358
|
const removed = [];
|
|
279
359
|
const skipped = [];
|
|
280
360
|
for (const repair of classifySources(workspaceRoot)) {
|
|
361
|
+
// A text_ref Kibi cannot map needs a person; never remove it.
|
|
362
|
+
if (repair.refused !== undefined) {
|
|
363
|
+
if (wanted === undefined) {
|
|
364
|
+
skipped.push({
|
|
365
|
+
file: repair.file,
|
|
366
|
+
reason: `text_ref '${shownSourceValue(repair.value)}': ${repair.refused}`,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
281
371
|
const current = plannedRepair(repair);
|
|
282
372
|
if (wanted !== undefined) {
|
|
283
|
-
const plan = wanted.get(repair.file);
|
|
373
|
+
const plan = wanted.get(plannedKey(repair.file, repair.field));
|
|
284
374
|
if (plan === undefined)
|
|
285
375
|
continue;
|
|
286
376
|
if (!samePlannedRepair(plan, current)) {
|
|
@@ -293,9 +383,14 @@ export function applySourcePathRepairs(workspaceRoot, planned) {
|
|
|
293
383
|
}
|
|
294
384
|
const absolute = path.join(workspaceRoot, repair.file);
|
|
295
385
|
const content = readText(absolute);
|
|
296
|
-
const next = content === null
|
|
386
|
+
const next = content === null
|
|
387
|
+
? null
|
|
388
|
+
: editedContent(content, repair.field, repair.fix);
|
|
297
389
|
if (next === null) {
|
|
298
|
-
skipped.push({
|
|
390
|
+
skipped.push({
|
|
391
|
+
file: repair.file,
|
|
392
|
+
reason: editRefusedReason(repair.field),
|
|
393
|
+
});
|
|
299
394
|
continue;
|
|
300
395
|
}
|
|
301
396
|
writeFileAtomically(absolute, next);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"suggest-predicates.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/suggest-predicates.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACX,MAAM,0CAA0C,CAAC;AA2BlD,OAAO,KAAK,EAIV,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AA+H9B,wBAAgB,sCAAsC,CACpD,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,qBAAqB,GAAG,gBAAgB,CAAC,EACzE,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,qBAAqB,GAAG,gBAAgB,CAAC,GACzE,MAAM,CAIR;AAED,wBAAgB,2CAA2C,CACzD,IAAI,EAAE,IAAI,CACR,mBAAmB,EACnB,qBAAqB,GAAG,OAAO,GAAG,gBAAgB,CACnD,EACD,KAAK,EAAE,IAAI,CACT,mBAAmB,EACnB,qBAAqB,GAAG,OAAO,GAAG,gBAAgB,CACnD,GACA,MAAM,CAKR;AA+ID,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,IAAI,EAAE,qBAAqB,EAC3B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,uBAAuB,CAAC,
|
|
1
|
+
{"version":3,"file":"suggest-predicates.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/suggest-predicates.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACX,MAAM,0CAA0C,CAAC;AA2BlD,OAAO,KAAK,EAIV,mBAAmB,EACnB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,sBAAsB,CAAC;AAG9B,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AA+H9B,wBAAgB,sCAAsC,CACpD,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,qBAAqB,GAAG,gBAAgB,CAAC,EACzE,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,qBAAqB,GAAG,gBAAgB,CAAC,GACzE,MAAM,CAIR;AAED,wBAAgB,2CAA2C,CACzD,IAAI,EAAE,IAAI,CACR,mBAAmB,EACnB,qBAAqB,GAAG,OAAO,GAAG,gBAAgB,CACnD,EACD,KAAK,EAAE,IAAI,CACT,mBAAmB,EACnB,qBAAqB,GAAG,OAAO,GAAG,gBAAgB,CACnD,GACA,MAAM,CAKR;AA+ID,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,IAAI,EAAE,qBAAqB,EAC3B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,uBAAuB,CAAC,CA8ZlC;AA+WD,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,qBAAqB,EAC3B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,uBAAuB,CAAC,CAElC"}
|
|
@@ -409,8 +409,19 @@ export async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
409
409
|
? buildGapApplyPlan(text, args)
|
|
410
410
|
: [];
|
|
411
411
|
const plannedFactId = typeof predicatePlan[0]?.id === "string" ? predicatePlan[0].id : null;
|
|
412
|
+
// The manifest the relationship plan calls "merged" starts from what the
|
|
413
|
+
// stored requirement already declares, so an agent that passes no
|
|
414
|
+
// existingLogicClaims is not handed a manifest that drops its other
|
|
415
|
+
// clauses.
|
|
416
|
+
const existingLogicClaims = Array.from(new Set([
|
|
417
|
+
...(storedRequirement !== null &&
|
|
418
|
+
Array.isArray(storedRequirement.logic_claims)
|
|
419
|
+
? storedRequirement.logic_claims.filter((claim) => typeof claim === "string")
|
|
420
|
+
: []),
|
|
421
|
+
...(args.existingLogicClaims ?? []),
|
|
422
|
+
]));
|
|
412
423
|
const relationshipPlan = completeCandidate && !alreadyGrounded && !ledgerMissing
|
|
413
|
-
? buildRelationshipPlan(plannedFactId ?? "", args.requirementId, text,
|
|
424
|
+
? buildRelationshipPlan(plannedFactId ?? "", args.requirementId, text, existingLogicClaims)
|
|
414
425
|
: null;
|
|
415
426
|
const replacementPlan = alreadyGrounded &&
|
|
416
427
|
!keepExistingGrounding &&
|
|
@@ -471,7 +482,7 @@ export async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
471
482
|
: alreadyGrounded
|
|
472
483
|
? "No predicate candidate passed the semantic applicability gate; keep the existing grounding and record the ontology-gap observation in applyPlan so the missing schema stays visible."
|
|
473
484
|
: "No predicate candidate passed the semantic applicability gate; record an ontology gap and review the generated schema draft instead of silently writing prose.");
|
|
474
|
-
const logicClaims = Array.from(new Set([...
|
|
485
|
+
const logicClaims = Array.from(new Set([...existingLogicClaims, claimKey]));
|
|
475
486
|
const plan = relationshipPlan !== null && plannedFactId !== null && args.requirementId
|
|
476
487
|
? await groundingPlan(prolog, context, {
|
|
477
488
|
requirementId: args.requirementId,
|
|
@@ -486,17 +497,21 @@ export async function handleKbSuggestPredicates(prolog, args, context) {
|
|
|
486
497
|
: null;
|
|
487
498
|
// Without a plan nothing ran the contradiction analysis, so the decision
|
|
488
499
|
// conflicts a complete candidate would introduce are looked up directly.
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
args.requirementId
|
|
500
|
+
// A claim analyzed without a requirement asks the same question ("what
|
|
501
|
+
// would this decision conflict with?"), so it gets the same lookup.
|
|
502
|
+
const decisionConflicts = plan === null && completeCandidate !== undefined && !keepExistingGrounding
|
|
493
503
|
? await candidateDecisionConflicts(prolog, completeCandidate, warnings)
|
|
494
504
|
: [];
|
|
495
505
|
for (const conflict of decisionConflicts) {
|
|
496
506
|
warnings.push(`The proposed ${conflict.canonicalKey} (${conflict.proposedEffect}) contradicts ${conflict.factId} (${conflict.effect}) under ${conflict.requirementId}${conflict.requirementId === args.requirementId ? ", the requirement this claim would ground" : ""}: both decide ${completeCandidate?.predicate_name} on the same key arguments. kb_upsert refuses a grounding link that introduces this conflict; supersede or close the conflicting requirement, or correct the decision, before applying.`);
|
|
497
507
|
}
|
|
508
|
+
const conflictSummary = decisionConflicts.length > 0
|
|
509
|
+
? ` It would contradict ${decisionConflicts
|
|
510
|
+
.map((conflict) => `${conflict.factId} (${conflict.effect}) under ${conflict.requirementId}`)
|
|
511
|
+
.join(", ")}: see decisionConflicts before applying anything.`
|
|
512
|
+
: "";
|
|
498
513
|
return {
|
|
499
|
-
content: [{ type: "text", text: textSummary }],
|
|
514
|
+
content: [{ type: "text", text: textSummary + conflictSummary }],
|
|
500
515
|
structuredContent: {
|
|
501
516
|
text,
|
|
502
517
|
claimKey,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { PrologPort } from "../../public/operations/runtime-types.js";
|
|
2
|
+
import { type SemanticRelationship } from "../semantic-advisor/ingestion-boundary.js";
|
|
2
3
|
import { type StoredEntityLookup } from "./stored-entity.js";
|
|
3
4
|
import type { StagedUpsertState, UpsertInput } from "./types.js";
|
|
4
5
|
/**
|
|
@@ -13,4 +14,19 @@ import type { StagedUpsertState, UpsertInput } from "./types.js";
|
|
|
13
14
|
* changes the prose is validated exactly as given.
|
|
14
15
|
*/
|
|
15
16
|
export declare function withStoredRequirementSemantics(input: UpsertInput, prolog: Pick<PrologPort, "query">, staged?: StagedUpsertState, lookup?: StoredEntityLookup): Promise<UpsertInput>;
|
|
17
|
+
/**
|
|
18
|
+
* An update to a stored requirement is judged as its authored file will read
|
|
19
|
+
* afterwards: the stored status, prose and proposition ledger with the
|
|
20
|
+
* payload's fields on top (the source writer keeps every front matter key the
|
|
21
|
+
* payload leaves out and states the stored `semantic_text`). A payload such
|
|
22
|
+
* as `{status: "closed"}` passes the check on its own fields, yet the file it
|
|
23
|
+
* leaves is a current requirement whose prose has no inventory, which sync
|
|
24
|
+
* then refuses. Such a write is refused here with the error sync would give.
|
|
25
|
+
*
|
|
26
|
+
* A requirement that was already current with the same prose and no complete
|
|
27
|
+
* inventory is legacy content sync keeps accepting, so a write that changes
|
|
28
|
+
* neither keeps working. A write that makes the requirement current, or
|
|
29
|
+
* changes the prose sync checks, must carry the complete inventory.
|
|
30
|
+
*/
|
|
31
|
+
export declare function assertStoredRequirementBoundary(input: UpsertInput, relationships: readonly SemanticRelationship[], prolog: Pick<PrologPort, "query">, staged?: StagedUpsertState, lookup?: StoredEntityLookup): Promise<void>;
|
|
16
32
|
//# sourceMappingURL=requirement-semantics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requirement-semantics.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/requirement-semantics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"requirement-semantics.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/requirement-semantics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAE3E,OAAO,EAEL,KAAK,oBAAoB,EAE1B,MAAM,2CAA2C,CAAC;AACnD,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAwCjE;;;;;;;;;;GAUG;AACH,wBAAsB,8BAA8B,CAClD,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,EACjC,MAAM,CAAC,EAAE,iBAAiB,EAC1B,MAAM,GAAE,kBAAqE,GAC5E,OAAO,CAAC,WAAW,CAAC,CA6BtB;AAuBD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,+BAA+B,CACnD,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,SAAS,oBAAoB,EAAE,EAC9C,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,EACjC,MAAM,CAAC,EAAE,iBAAiB,EAC1B,MAAM,GAAE,kBAAqE,GAC5E,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { analyzeSemanticAdvisorInput } from "../semantic-advisor/analyze-prose.js";
|
|
2
|
+
import { validateSemanticInventoryBoundary, } from "../semantic-advisor/ingestion-boundary.js";
|
|
1
3
|
import { storedEntityLookup, } from "./stored-entity.js";
|
|
2
4
|
/** The fields that make up a requirement's proposition ledger. */
|
|
3
5
|
const SEMANTIC_CONTRACT_FIELDS = [
|
|
@@ -62,3 +64,51 @@ export async function withStoredRequirementSemantics(input, prolog, staged, look
|
|
|
62
64
|
return input;
|
|
63
65
|
return { ...input, properties: { ...preserved, ...properties } };
|
|
64
66
|
}
|
|
67
|
+
/** Stored fields that decide how sync reads a requirement's propositions. */
|
|
68
|
+
const BOUNDARY_FIELDS = [
|
|
69
|
+
"status",
|
|
70
|
+
"title",
|
|
71
|
+
"text_ref",
|
|
72
|
+
...SEMANTIC_CONTRACT_FIELDS,
|
|
73
|
+
];
|
|
74
|
+
function boundaryOf(input, properties, relationships) {
|
|
75
|
+
const payload = { type: input.type, id: input.id, properties };
|
|
76
|
+
const { receipt } = analyzeSemanticAdvisorInput({
|
|
77
|
+
payload: { ...payload, relationships },
|
|
78
|
+
});
|
|
79
|
+
return validateSemanticInventoryBoundary(payload, relationships, receipt);
|
|
80
|
+
}
|
|
81
|
+
// implements REQ-kibi-upsert-preserves-requirement-semantics, REQ-kibi-proposition-complete-ingestion
|
|
82
|
+
/**
|
|
83
|
+
* An update to a stored requirement is judged as its authored file will read
|
|
84
|
+
* afterwards: the stored status, prose and proposition ledger with the
|
|
85
|
+
* payload's fields on top (the source writer keeps every front matter key the
|
|
86
|
+
* payload leaves out and states the stored `semantic_text`). A payload such
|
|
87
|
+
* as `{status: "closed"}` passes the check on its own fields, yet the file it
|
|
88
|
+
* leaves is a current requirement whose prose has no inventory, which sync
|
|
89
|
+
* then refuses. Such a write is refused here with the error sync would give.
|
|
90
|
+
*
|
|
91
|
+
* A requirement that was already current with the same prose and no complete
|
|
92
|
+
* inventory is legacy content sync keeps accepting, so a write that changes
|
|
93
|
+
* neither keeps working. A write that makes the requirement current, or
|
|
94
|
+
* changes the prose sync checks, must carry the complete inventory.
|
|
95
|
+
*/
|
|
96
|
+
export async function assertStoredRequirementBoundary(input, relationships, prolog, staged, lookup = storedEntityLookup(prolog, input.id, input.type)) {
|
|
97
|
+
if (input.type !== "req")
|
|
98
|
+
return;
|
|
99
|
+
const stored = await storedRequirement(input.id, lookup, staged);
|
|
100
|
+
if (stored === undefined)
|
|
101
|
+
return;
|
|
102
|
+
const before = {};
|
|
103
|
+
for (const field of BOUNDARY_FIELDS) {
|
|
104
|
+
if (stored[field] !== undefined)
|
|
105
|
+
before[field] = stored[field];
|
|
106
|
+
}
|
|
107
|
+
const after = boundaryOf(input, { ...before, ...(input.properties ?? {}) }, relationships);
|
|
108
|
+
if (after.errors.length === 0)
|
|
109
|
+
return;
|
|
110
|
+
const previous = boundaryOf(input, before, relationships);
|
|
111
|
+
if (previous.applicable && previous.sourceHash === after.sourceHash)
|
|
112
|
+
return;
|
|
113
|
+
throw new Error(`Proposition-complete ingestion failed: ${input.id} would be written as a current requirement without a complete proposition inventory (${after.errors.join("; ")}). Run kb_model mode analyze (CLI: semantic-advisor) with id '${input.id}' and its complete semantic_text, then send the returned inventory contract (semantic_inventory, semantic_inventory_version, semantic_source_field, semantic_source_hash, logic_claims) in this kb_upsert, or retire the requirement through a superseding one instead.`);
|
|
114
|
+
}
|
|
@@ -90,7 +90,7 @@ export function factKindShapeHints(entity) {
|
|
|
90
90
|
if (missing.length !== 0)
|
|
91
91
|
return [
|
|
92
92
|
`fact_kind 'predicate' requires ${missing.join(", ")}.`,
|
|
93
|
-
"Next action: call
|
|
93
|
+
"Next action: call kb_model with mode predicates (CLI: kibi suggest-predicates) and apply its planned fact instead of hand-writing ontology predicate facts.",
|
|
94
94
|
];
|
|
95
95
|
return [];
|
|
96
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/upsert.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAexE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/upsert.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAexE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AA4B3E,OAAO,EACL,KAAK,kBAAkB,EAExB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,EACX,aAAa,EACb,eAAe,EAChB,MAAM,YAAY,CAAC;AAsEpB,wBAAgB,gCAAgC,CAC9C,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,MAAM,GAChB,IAAI,CAkBN;AAwCD,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,iBAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,aAAa,EAAE,SAAS,iBAAiB,EAAE,EAC3C,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,iBAAiB,EAC1B,MAAM,CAAC,EAAE,kBAAkB,GAC1B,OAAO,CAAC,SAAS,iBAAiB,EAAE,CAAC,CA8BvC;AAmCD,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,kEAAkE;IAClE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;CACrC,CAAC,CAAC;AAGH,uFAAuF;AACvF,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,CAAC,CAAC;AAGH;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,WAAW,GAAG;IACrB,QAAQ,CAAC,aAAa,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACtD,GACA,sBAAsB,CASxB;AAGD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,aAAa,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACrD,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;CAC3C,CAAC,CAAC;AAGH;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,gBAAgB,CAAC,CAiF3B;AAgDD,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C;;;;;;OAMG;IAEH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CACxC,CAAC,CAAC;AAyBH,wBAAsB,aAAa,CACjC,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,gBAAgB,EACzB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,CA2hBzC"}
|
|
@@ -19,7 +19,7 @@ import { resolveUpsertOrigin } from "./origin.js";
|
|
|
19
19
|
import { planRecoveryNotes, settlePendingPlanApplyJournals, withPlanRecoveryNotes, } from "./plan-apply-journal.js";
|
|
20
20
|
import { assertPredicateArgumentVocabulary } from "./predicate-vocabulary-guard.js";
|
|
21
21
|
import { existingRelationships, validateLiveRelationshipTargets, validateRelationshipSources, validateStrictLanePairing, validateSupersedesSourceHistory, } from "./relationships.js";
|
|
22
|
-
import { withStoredRequirementSemantics } from "./requirement-semantics.js";
|
|
22
|
+
import { assertStoredRequirementBoundary, withStoredRequirementSemantics, } from "./requirement-semantics.js";
|
|
23
23
|
import { MutationRollbackFailureError, MutationSaga } from "./saga.js";
|
|
24
24
|
import { readFileTimes, restoreFileTimes, writePendingSourceReceipt, writeSourceForUpsert, } from "./source-authoring.js";
|
|
25
25
|
import { storedEntityLookup, } from "./stored-entity.js";
|
|
@@ -244,6 +244,7 @@ export async function validateUpsertForCommit(payload, context, options = {}) {
|
|
|
244
244
|
await validateLiveRelationshipTargets(prolog, validated.entity, validated.relationships, staged);
|
|
245
245
|
await validateSupersedesSourceHistory(prolog, validated.entity, validated.relationships, context.workspaceRoot, undefined, staged);
|
|
246
246
|
const semantic = analyzeUpsertSemantics({ ...input, relationships });
|
|
247
|
+
await assertStoredRequirementBoundary(input, relationships, prolog, staged, lookup);
|
|
247
248
|
await assertLogicalGroundingClaimKeys(prolog, { ...input, relationships }, relationships, staged);
|
|
248
249
|
await assertPredicateArgumentVocabulary(prolog, validated.entity, staged);
|
|
249
250
|
// The origin the write records is added last: none of the checks above
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply-plan.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/apply-plan.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAEV,gBAAgB,EAGjB,MAAM,0CAA0C,CAAC;AASlD,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,uBAAuB,CAAC;AAiE/B,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,eAAO,MAAM,yBAAyB,EAAG,2BAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"apply-plan.d.ts","sourceRoot":"","sources":["../../../src/operations/planning/apply-plan.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAEV,gBAAgB,EAGjB,MAAM,0CAA0C,CAAC;AASlD,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,uBAAuB,CAAC;AAiE/B,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,eAAO,MAAM,yBAAyB,EAAG,2BAAoC,CAAC;AAqI9E,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,IAAI,CAMN;AAED,wBAAgB,mCAAmC,CACjD,SAAS,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EAAE,EACnE,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,GAC3B,IAAI,CAaN;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,SAAS,cAAoB,GAC5B,eAAe,EAAE,CA2CnB;AAi1BD;;;;;;GAMG;AAEH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAiCf;AAyqDD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB;AACzB;;;GAGG;AACH,WAAW,GAAE,MAAM,IAAsB,GACxC,OAAO,CAAC;IACT,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,iBAAiB,EAAE,eAAe,CAAC;CACpC,CAAC,CAmDD"}
|
|
@@ -84,13 +84,33 @@ function asUpsert(step) {
|
|
|
84
84
|
...(document !== undefined ? { document } : {}),
|
|
85
85
|
};
|
|
86
86
|
}
|
|
87
|
+
// implements REQ-kibi-change-to-proof-plan-compiler-v2
|
|
88
|
+
/**
|
|
89
|
+
* Why a plan that is not ready cannot be applied, with the remedy for its
|
|
90
|
+
* status. The leading sentence stays the same for every status.
|
|
91
|
+
*/
|
|
92
|
+
function notReadyPlanMessage(prefix, status) {
|
|
93
|
+
const base = `${prefix}: only ready plans may be applied; this plan's status is '${String(status)}'.`;
|
|
94
|
+
switch (status) {
|
|
95
|
+
case "needs_resolution":
|
|
96
|
+
return `${base} Resolve its ontology_gap and missing propositions first (model each with kb_model mode requirement or predicates, then call kb_compile_intent again and apply the ready plan it returns), and fix any step its diagnostics name. Or write the requirement with kb_upsert carrying the plan's inventory contract, with the unmodeled propositions kept as status ontology_gap entries, as the kibi-usage skill describes.`;
|
|
97
|
+
case "blocked":
|
|
98
|
+
return prefix === "Apply plan failed"
|
|
99
|
+
? `${base} Its contradiction analysis found a conflict with a current requirement: resolve the contradiction first (supersede or change the conflicting requirement, or change the intent), then compile again.`
|
|
100
|
+
: `${base} Resolve what its diagnostics name, then plan the bootstrap again.`;
|
|
101
|
+
case "needs_context":
|
|
102
|
+
return `${base} Supply the bootstrap context it asks for, then plan the bootstrap again.`;
|
|
103
|
+
default:
|
|
104
|
+
return `${base} Compile or plan again and apply the plan it returns once its status is 'ready'.`;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
87
107
|
function validateCompilePlanShape(args) {
|
|
88
108
|
if (!isRecord(args.plan))
|
|
89
109
|
throw new Error("Apply plan failed: plan must be an object");
|
|
90
110
|
if (args.plan.version !== "kibi.compile-plan.v1")
|
|
91
111
|
throw new Error("Apply plan failed: unsupported plan version");
|
|
92
112
|
if (args.plan.status !== "ready")
|
|
93
|
-
throw new Error("Apply plan failed
|
|
113
|
+
throw new Error(notReadyPlanMessage("Apply plan failed", args.plan.status));
|
|
94
114
|
if (!/^[a-f0-9]{64}$/i.test(args.approvedPlanHash))
|
|
95
115
|
throw new Error("Apply plan failed: approvedPlanHash must be a SHA-256 hash");
|
|
96
116
|
if (args.approvedPlanHash !== args.plan.planHash)
|
|
@@ -163,7 +183,7 @@ export function orderBootstrapActions(actions, completed = new Set()) {
|
|
|
163
183
|
function validateBootstrapPlanShape(args) {
|
|
164
184
|
const { plan } = args;
|
|
165
185
|
if (plan.status !== "ready")
|
|
166
|
-
throw new Error("Bootstrap apply failed
|
|
186
|
+
throw new Error(notReadyPlanMessage("Bootstrap apply failed", plan.status));
|
|
167
187
|
if (!/^[a-f0-9]{64}$/i.test(args.approvedPlanHash))
|
|
168
188
|
throw new Error("Bootstrap apply failed: approvedPlanHash must be SHA-256");
|
|
169
189
|
if (args.approvedPlanHash !== plan.planHash)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-prose.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/analyze-prose.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"analyze-prose.d.ts","sourceRoot":"","sources":["../../../src/operations/semantic-advisor/analyze-prose.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAiBxD,OAAO,KAAK,EACV,6BAA6B,EAC7B,oBAAoB,EAWrB,MAAM,YAAY,CAAC;AAEpB,eAAO,MAAM,wBAAwB,wBAAwB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAI1D;AA4gBD,OAAO,EAAE,eAAe,EAAE,CAAC;AAwX3B,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,oBAAoB,GAC1B,6BAA6B,CAgE/B"}
|