kibi-cli 2.20.0 → 2.21.2

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.
Files changed (126) hide show
  1. package/dist/cli-operation-metadata.d.ts +1 -1
  2. package/dist/cli-operation-metadata.js +1 -1
  3. package/dist/commands/doctor.js +13 -1
  4. package/dist/commands/init.d.ts.map +1 -1
  5. package/dist/commands/init.js +15 -3
  6. package/dist/commands/legacy-storage-migration.d.ts.map +1 -1
  7. package/dist/commands/legacy-storage-migration.js +26 -1
  8. package/dist/commands/migrate.d.ts +2 -0
  9. package/dist/commands/migrate.d.ts.map +1 -1
  10. package/dist/commands/migrate.js +155 -11
  11. package/dist/commands/sync/discovery.d.ts.map +1 -1
  12. package/dist/commands/sync/discovery.js +14 -2
  13. package/dist/commands/sync/persistence.d.ts.map +1 -1
  14. package/dist/commands/sync/persistence.js +4 -0
  15. package/dist/decision-firmness.d.ts +39 -0
  16. package/dist/decision-firmness.d.ts.map +1 -0
  17. package/dist/decision-firmness.js +115 -0
  18. package/dist/extractors/markdown.d.ts +2 -0
  19. package/dist/extractors/markdown.d.ts.map +1 -1
  20. package/dist/extractors/markdown.js +16 -1
  21. package/dist/operations/migration/kb-sources.d.ts +5 -1
  22. package/dist/operations/migration/kb-sources.d.ts.map +1 -1
  23. package/dist/operations/migration/kb-sources.js +28 -1
  24. package/dist/operations/migration/schema6.d.ts +2 -0
  25. package/dist/operations/migration/schema6.d.ts.map +1 -1
  26. package/dist/operations/migration/schema6.js +44 -1
  27. package/dist/operations/migration/supersedes-reason.d.ts +26 -0
  28. package/dist/operations/migration/supersedes-reason.d.ts.map +1 -0
  29. package/dist/operations/migration/supersedes-reason.js +69 -0
  30. package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
  31. package/dist/operations/modeling/predicate-applyplan.js +10 -2
  32. package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
  33. package/dist/operations/modeling/predicate-loader.js +11 -0
  34. package/dist/operations/modeling/predicate-types.d.ts +32 -1
  35. package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
  36. package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
  37. package/dist/operations/modeling/suggest-predicates.js +175 -35
  38. package/dist/operations/mutation/delete.d.ts +5 -1
  39. package/dist/operations/mutation/delete.d.ts.map +1 -1
  40. package/dist/operations/mutation/delete.js +223 -17
  41. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  42. package/dist/operations/mutation/serialization.js +1 -0
  43. package/dist/operations/mutation/source-authoring.d.ts +8 -0
  44. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  45. package/dist/operations/mutation/source-authoring.js +33 -0
  46. package/dist/operations/mutation/types.d.ts +37 -0
  47. package/dist/operations/mutation/types.d.ts.map +1 -1
  48. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  49. package/dist/operations/mutation/upsert.js +54 -2
  50. package/dist/operations/mutation/validation.d.ts.map +1 -1
  51. package/dist/operations/mutation/validation.js +2 -1
  52. package/dist/operations/planning/apply-plan.d.ts +6 -1
  53. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  54. package/dist/operations/planning/apply-plan.js +8 -2
  55. package/dist/operations/semantic-advisor/clauses.d.ts +9 -0
  56. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  57. package/dist/operations/semantic-advisor/clauses.js +24 -0
  58. package/dist/public/operations/catalog.d.ts +14 -5
  59. package/dist/public/operations/catalog.d.ts.map +1 -1
  60. package/dist/public/operations/check-executor.d.ts.map +1 -1
  61. package/dist/public/operations/check-executor.js +3 -0
  62. package/dist/public/operations/contracts.d.ts.map +1 -1
  63. package/dist/public/operations/contracts.js +29 -1
  64. package/dist/public/operations/decision-firmness.d.ts +34 -0
  65. package/dist/public/operations/decision-firmness.d.ts.map +1 -0
  66. package/dist/public/operations/decision-firmness.js +216 -0
  67. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  68. package/dist/public/operations/discovery-executors.js +16 -2
  69. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  70. package/dist/public/operations/migration-plan.js +37 -7
  71. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  72. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  73. package/dist/public/operations/specs/check-rules.generated.js +5 -1
  74. package/dist/public/operations/specs/check.d.ts +1 -1
  75. package/dist/public/operations/specs/mutation-schemas.d.ts +7 -2
  76. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  77. package/dist/public/operations/specs/mutation-schemas.js +13 -17
  78. package/dist/public/operations/specs/mutation.d.ts +6 -2
  79. package/dist/public/operations/specs/mutation.d.ts.map +1 -1
  80. package/dist/public/operations/specs/mutation.js +6 -2
  81. package/dist/public/operations/specs/upsert.d.ts +7 -2
  82. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  83. package/dist/public/schemas/entity.d.ts.map +1 -1
  84. package/dist/public/schemas/entity.js +13 -13
  85. package/dist/public/skills/kibi-traceability/SKILL.md +6 -4
  86. package/dist/public/skills/kibi-usage/SKILL.md +52 -10
  87. package/dist/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
  88. package/dist/public/skills/kibi-usage/resources/source-authoring.md +4 -2
  89. package/dist/public/skills/kibi-usage/resources/ui-requirements.md +2 -2
  90. package/dist/public/skills/kibi-usage/resources/workflows.md +1 -1
  91. package/dist/relationships/shards.d.ts +10 -0
  92. package/dist/relationships/shards.d.ts.map +1 -1
  93. package/dist/relationships/shards.js +27 -11
  94. package/dist/schemas/entity.schema.json +30 -25
  95. package/dist/search-answer.d.ts +31 -2
  96. package/dist/search-answer.d.ts.map +1 -1
  97. package/dist/search-answer.js +115 -17
  98. package/dist/types/entities.d.ts +4 -0
  99. package/dist/types/entities.d.ts.map +1 -1
  100. package/dist/utils/kb-manifest.d.ts +6 -0
  101. package/dist/utils/kb-manifest.d.ts.map +1 -1
  102. package/dist/utils/kb-manifest.js +6 -0
  103. package/dist/utils/rule-registry.generated.d.ts +21 -0
  104. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  105. package/dist/utils/rule-registry.generated.js +25 -0
  106. package/dist/utils/schema-version.d.ts +1 -1
  107. package/dist/utils/schema-version.d.ts.map +1 -1
  108. package/dist/utils/schema-version.js +3 -1
  109. package/package.json +2 -2
  110. package/schema/entities.pl +6 -0
  111. package/src/public/operations/check-executor.ts +6 -0
  112. package/src/public/operations/contracts.ts +33 -1
  113. package/src/public/operations/decision-firmness.ts +280 -0
  114. package/src/public/operations/discovery-executors.ts +17 -2
  115. package/src/public/operations/migration-plan.ts +41 -9
  116. package/src/public/operations/specs/check-rules.generated.ts +5 -1
  117. package/src/public/operations/specs/mutation-schemas.ts +14 -17
  118. package/src/public/operations/specs/mutation.ts +7 -2
  119. package/src/public/schemas/entity.ts +14 -13
  120. package/src/public/skills/kibi-traceability/SKILL.md +6 -4
  121. package/src/public/skills/kibi-usage/SKILL.md +52 -10
  122. package/src/public/skills/kibi-usage/resources/fact-lanes.md +1 -1
  123. package/src/public/skills/kibi-usage/resources/source-authoring.md +4 -2
  124. package/src/public/skills/kibi-usage/resources/ui-requirements.md +2 -2
  125. package/src/public/skills/kibi-usage/resources/workflows.md +1 -1
  126. package/src/schemas/entity.schema.json +30 -25
@@ -0,0 +1,115 @@
1
+ /*
2
+ Kibi — repo-local, per-branch, queryable long-term memory for software projects
3
+ Copyright (C) 2026 Piotr Franczyk
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Affero General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Affero General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Affero General Public License
16
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ /**
19
+ * Decision firmness: how firmly a requirement or ADR was decided, which tells
20
+ * a later agent whether it may supersede the decision on evidence or must ask
21
+ * a human first. This module is the one place that knows the values, the
22
+ * default and what a supersede must explain, so extraction, checks, search,
23
+ * query and migration agree.
24
+ */
25
+ import { parseBodySections } from "./entity-body-context.js";
26
+ /** Firmness values, firmest first. */
27
+ // implements REQ-kb-decision-firmness
28
+ export const FIRMNESS_VALUES = ["firm", "default", "exploratory"];
29
+ /** The firmness of a decision that does not state one. */
30
+ // implements REQ-kb-decision-firmness
31
+ export const DEFAULT_FIRMNESS = "default";
32
+ /** Entity types that carry firmness. */
33
+ // implements REQ-kb-decision-firmness
34
+ export const FIRMNESS_TYPES = ["req", "adr"];
35
+ /** A supersede must explain itself under a heading starting with this. */
36
+ // implements REQ-kb-decision-firmness
37
+ export const WHY_THIS_CHANGED_HEADING = "Why this changed";
38
+ /** The explanation needs at least this many words of prose. */
39
+ // implements REQ-kb-decision-firmness
40
+ export const MIN_WHY_CHANGED_WORDS = 12;
41
+ const WHY_THIS_CHANGED = /^why\s+this\s+changed\b/i;
42
+ /**
43
+ * How the manifest records one acknowledged supersede edge. Edges, not ids,
44
+ * are acknowledged, so a supersede added later to the same entity still has
45
+ * to explain itself.
46
+ */
47
+ // implements REQ-kb-decision-firmness
48
+ export function supersedeAcknowledgement(from, to) {
49
+ return `${from} -> ${to}`;
50
+ }
51
+ // implements REQ-kb-decision-firmness
52
+ export function isFirmness(value) {
53
+ return (typeof value === "string" &&
54
+ FIRMNESS_VALUES.includes(value));
55
+ }
56
+ // implements REQ-kb-decision-firmness
57
+ export function carriesFirmness(type) {
58
+ return (typeof type === "string" &&
59
+ FIRMNESS_TYPES.includes(type));
60
+ }
61
+ /**
62
+ * The firmness a decision is read with: the authored value, else `default`.
63
+ * Undefined for types that carry no firmness.
64
+ */
65
+ // implements REQ-kb-decision-firmness
66
+ export function effectiveFirmness(type, value) {
67
+ if (!carriesFirmness(type))
68
+ return undefined;
69
+ return isFirmness(value) ? value : DEFAULT_FIRMNESS;
70
+ }
71
+ /**
72
+ * The reference that makes a firm decision traceable to a human's words:
73
+ * `origin.ref`, or `approval_ref` on a requirement.
74
+ */
75
+ // implements REQ-kb-decision-firmness
76
+ export function firmnessRef(entity) {
77
+ const origin = entity.origin;
78
+ if (origin !== null && typeof origin === "object") {
79
+ const ref = origin.ref;
80
+ if (typeof ref === "string" && ref.trim() !== "")
81
+ return ref.trim();
82
+ }
83
+ if (entity.type === "req" &&
84
+ typeof entity.approval_ref === "string" &&
85
+ entity.approval_ref.trim() !== "") {
86
+ return entity.approval_ref.trim();
87
+ }
88
+ return undefined;
89
+ }
90
+ function wordCount(text) {
91
+ return text.split(/\s+/).filter((word) => /[\p{L}\p{N}]/u.test(word)).length;
92
+ }
93
+ /**
94
+ * Words of prose under the body's "Why this changed" heading (nested
95
+ * headings included), or 0 when the body has no such section.
96
+ */
97
+ // implements REQ-kb-decision-firmness
98
+ export function whyThisChangedWords(body) {
99
+ const sections = parseBodySections(body);
100
+ let level = null;
101
+ let words = 0;
102
+ for (const section of sections) {
103
+ if (level !== null && section.level > 0 && section.level <= level) {
104
+ level = null;
105
+ }
106
+ if (level === null &&
107
+ section.level > 0 &&
108
+ WHY_THIS_CHANGED.test(section.heading.replace(/^[*_`\s]+/, ""))) {
109
+ level = section.level;
110
+ }
111
+ if (level !== null)
112
+ words += wordCount(section.text);
113
+ }
114
+ return words;
115
+ }
@@ -1,3 +1,4 @@
1
+ import { type Firmness } from "../decision-firmness.js";
1
2
  import { type EntityOrigin } from "../public/entity-origin.js";
2
3
  import { type ProofBinding, type ProofContract } from "../public/proof-protocol.js";
3
4
  import { type ProofReceipt } from "../public/proof-receipt.js";
@@ -15,6 +16,7 @@ export interface ExtractedEntity {
15
16
  severity?: string;
16
17
  text_ref?: string;
17
18
  origin?: EntityOrigin;
19
+ firmness?: Firmness;
18
20
  semantic_text?: string;
19
21
  logic_claims?: string[];
20
22
  semantic_clauses?: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/extractors/markdown.ts"],"names":[],"mappings":"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"}
@@ -19,8 +19,9 @@ import { createHash } from "node:crypto";
19
19
  import { readFileSync } from "node:fs";
20
20
  import Ajv from "ajv";
21
21
  import { load as yamlLoad } from "js-yaml";
22
+ import { FIRMNESS_VALUES, carriesFirmness, isFirmness, } from "../decision-firmness.js";
22
23
  import { withoutContextSections } from "../entity-body-context.js";
23
- import { semanticClaimKey } from "../operations/semantic-advisor/clauses.js";
24
+ import { deriveFactClaimKey, semanticClaimKey, } from "../operations/semantic-advisor/clauses.js";
24
25
  import { normalizeEntityOrigin, } from "../public/entity-origin.js";
25
26
  import { PROOF_BINDINGS_SCHEMA, PROOF_CONTRACT_SCHEMA, } from "../public/proof-protocol.js";
26
27
  import { proofReceiptHistoryErrors, } from "../public/proof-receipt.js";
@@ -511,6 +512,19 @@ function extractFromMarkdownContent(content, filePath) {
511
512
  }
512
513
  entity.rationale = data.rationale;
513
514
  }
515
+ // implements REQ-kb-decision-firmness
516
+ // How firmly a requirement or ADR was decided; absent reads as default.
517
+ if (data.firmness !== undefined) {
518
+ if (!carriesFirmness(type) || !isFirmness(data.firmness)) {
519
+ throw new FrontmatterError(carriesFirmness(type)
520
+ ? `Invalid firmness; expected one of ${FIRMNESS_VALUES.join(", ")}`
521
+ : "firmness is only allowed on type: req or adr", filePath, {
522
+ classification: "Invalid Firmness",
523
+ hint: "Use firm only for a rule a human stated (with origin.ref to their words), default for a delegated or agent choice, exploratory for a flagged guess; remove the field from other entity types.",
524
+ });
525
+ }
526
+ entity.firmness = data.firmness;
527
+ }
514
528
  if (type === "req" && Array.isArray(data.exempts_claims)) {
515
529
  entity.exempts_claims = data.exempts_claims.filter((value) => typeof value === "string");
516
530
  }
@@ -671,6 +685,7 @@ function extractFromMarkdownContent(content, filePath) {
671
685
  hint: "Fix the entity fields so they match the public schema.",
672
686
  });
673
687
  }
688
+ deriveFactClaimKey(entity);
674
689
  if (entity.type === "fact" &&
675
690
  entity.claim_key !== undefined &&
676
691
  entity.claim_text !== undefined) {
@@ -47,7 +47,11 @@ export declare function withTopLevelField(content: string, key: string, value: s
47
47
  * change (the key gone, every other key parsing identically).
48
48
  */
49
49
  export declare function withoutTopLevelField(content: string, key: string): string | null;
50
- /** Replace a file's bytes atomically. */
50
+ /**
51
+ * Replace a file's bytes atomically. A migration rewrite of an untracked
52
+ * `.kb/` source also rebinds its pending-source receipt, so the next sync
53
+ * reads the rewritten file instead of refusing it as hash drift.
54
+ */
51
55
  export declare function writeFileAtomically(filePath: string, content: string): void;
52
56
  export declare function readText(filePath: string): string | null;
53
57
  //# sourceMappingURL=kb-sources.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"kb-sources.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/kb-sources.ts"],"names":[],"mappings":"AA8BA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,yBAAyB,CAAC;AAEjC,yEAAyE;AAEzE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAuBH,0EAA0E;AAE1E,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,KAAK,GAAE,SAAS,UAAU,EAAiB,GAC1C,gBAAgB,EAAE,CAkBpB;AAED,6DAA6D;AAE7D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,IAAI,GAAG,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH;;;;;GAKG;AAEH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAczE;AAUD;;;;;GAKG;AAEH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAe3E;AAeD;;;;;GAKG;AAEH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAyBf;AAQD;;;;;;GAMG;AAEH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,IAAI,CAsBf;AAED,yCAAyC;AAEzC,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAK3E;AAGD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMxD"}
1
+ {"version":3,"file":"kb-sources.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/kb-sources.ts"],"names":[],"mappings":"AA+BA,OAAO,EAEL,KAAK,UAAU,EAEhB,MAAM,yBAAyB,CAAC;AAGjC,yEAAyE;AAEzE,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,IAAI,EAAE,UAAU,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AAuBH,0EAA0E;AAE1E,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,KAAK,GAAE,SAAS,UAAU,EAAiB,GAC1C,gBAAgB,EAAE,CAkBpB;AAED,6DAA6D;AAE7D,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,IAAI,GAAG,MAAM,CAAC;CACpB,CAAC,CAAC;AAEH;;;;;GAKG;AAEH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAczE;AAUD;;;;;GAKG;AAEH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAe3E;AAeD;;;;;GAKG;AAEH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAyBf;AAQD;;;;;;GAMG;AAEH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,MAAM,GAAG,IAAI,CAsBf;AAID;;;;GAIG;AAEH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAY3E;AAqBD,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMxD"}
@@ -15,11 +15,13 @@
15
15
  You should have received a copy of the GNU Affero General Public License
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
+ import { createHash } from "node:crypto";
18
19
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync, } from "node:fs";
19
20
  import path from "node:path";
20
21
  import { isDeepStrictEqual } from "node:util";
21
22
  import { load as loadYaml } from "js-yaml";
22
23
  import { ENTITY_LANES, KB_PATHS, } from "../../utils/kb-paths.js";
24
+ import { republishPendingSourceReceipt } from "../mutation/source-authoring.js";
23
25
  function walkMarkdown(directory, files) {
24
26
  let entries;
25
27
  try {
@@ -214,13 +216,38 @@ export function withoutTopLevelField(content, key) {
214
216
  }
215
217
  return match === null ? content : `${slice.prefix}${text}${slice.suffix}`;
216
218
  }
217
- /** Replace a file's bytes atomically. */
219
+ const KB_ROOT_DIRNAME = ".kb";
220
+ /**
221
+ * Replace a file's bytes atomically. A migration rewrite of an untracked
222
+ * `.kb/` source also rebinds its pending-source receipt, so the next sync
223
+ * reads the rewritten file instead of refusing it as hash drift.
224
+ */
218
225
  // implements REQ-cli-schema-migration
219
226
  export function writeFileAtomically(filePath, content) {
220
227
  mkdirSync(path.dirname(filePath), { recursive: true });
221
228
  const tempPath = `${filePath}.kibi-migrate-${process.pid}-${Date.now()}`;
222
229
  writeFileSync(tempPath, content, "utf8");
223
230
  renameSync(tempPath, filePath);
231
+ const source = kbSourceLocation(filePath);
232
+ if (source === null)
233
+ return;
234
+ republishPendingSourceReceipt(source.workspaceRoot, source.relativePath, createHash("sha256").update(content, "utf8").digest("hex"));
235
+ }
236
+ /**
237
+ * The workspace root and workspace-relative path of a file under `.kb/`, or
238
+ * `null` for a file outside any knowledge root.
239
+ */
240
+ function kbSourceLocation(filePath) {
241
+ const absolute = path.resolve(filePath);
242
+ const segments = absolute.split(path.sep);
243
+ const index = segments.lastIndexOf(KB_ROOT_DIRNAME);
244
+ if (index <= 0)
245
+ return null;
246
+ const workspaceRoot = segments.slice(0, index).join(path.sep) || path.sep;
247
+ return {
248
+ workspaceRoot,
249
+ relativePath: segments.slice(index).join("/"),
250
+ };
224
251
  }
225
252
  // implements REQ-cli-schema-migration
226
253
  export function readText(filePath) {
@@ -4,6 +4,8 @@ import { CLOSE_SUPERSEDED_REQUIREMENTS_CODE, MIGRATION_SYNC_ACTION_ID, MIGRATION
4
4
  export declare const ORIGIN_SCHEMA_VERSION = 6;
5
5
  /** The KB schema generation that requires body context on current entities. */
6
6
  export declare const BODY_CONTEXT_SCHEMA_VERSION = 8;
7
+ /** The KB schema generation that adds decision firmness. */
8
+ export declare const DECISION_FIRMNESS_SCHEMA_VERSION = 9;
7
9
  /** Automatic: re-derive a drifted inventory with the current advisor. */
8
10
  export declare const SEMANTIC_INVENTORY_REDERIVE_CODE = "semantic_inventory_rederive";
9
11
  /** Review: a drifted inventory Kibi cannot re-derive safely. */
@@ -1 +1 @@
1
- {"version":3,"file":"schema6.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/schema6.ts"],"names":[],"mappings":"AAuBA,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAEL,kCAAkC,EAClC,wBAAwB,EACxB,mBAAmB,EAEnB,wBAAwB,EAOzB,MAAM,kDAAkD,CAAC;AAoC1D,gEAAgE;AAEhE,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,+EAA+E;AAE/E,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,yEAAyE;AAEzE,eAAO,MAAM,gCAAgC,gCAAgC,CAAC;AAC9E,gEAAgE;AAEhE,eAAO,MAAM,8BAA8B,8BAA8B,CAAC;AAC1E,yEAAyE;AAEzE,eAAO,MAAM,2BAA2B,2BAA2B,CAAC;AAEpE,eAAO,MAAM,gCAAgC,2BAA2B,CAAC;AACzE,OAAO,EACL,kCAAkC,EAClC,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,GACzB,CAAC;AAsEF;;;GAGG;AAEH,wBAAgB,+BAA+B,CAC7C,aAAa,EAAE,MAAM,GACpB,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAsDnE;AAGD,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,uDAAuD;IACvD,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC,CAAC,CAAC;AAEH;;;;;;GAMG;AAEH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,wBAAwB,CA6J3B;AAED;;;;;;GAMG;AAEH,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG;IAClE,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC,CAoCA;AAED,qEAAqE;AAErE,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,eAAe,CAEjB;AA0CD,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC,CAAC;AAEH,4DAA4D;AAE5D,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAsEf;AAGD,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAStD,CAAC"}
1
+ {"version":3,"file":"schema6.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/schema6.ts"],"names":[],"mappings":"AAuBA,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAEL,kCAAkC,EAClC,wBAAwB,EACxB,mBAAmB,EAEnB,wBAAwB,EAOzB,MAAM,kDAAkD,CAAC;AAyC1D,gEAAgE;AAEhE,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,+EAA+E;AAE/E,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,4DAA4D;AAE5D,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAElD,yEAAyE;AAEzE,eAAO,MAAM,gCAAgC,gCAAgC,CAAC;AAC9E,gEAAgE;AAEhE,eAAO,MAAM,8BAA8B,8BAA8B,CAAC;AAC1E,yEAAyE;AAEzE,eAAO,MAAM,2BAA2B,2BAA2B,CAAC;AAEpE,eAAO,MAAM,gCAAgC,2BAA2B,CAAC;AACzE,OAAO,EACL,kCAAkC,EAClC,wBAAwB,EACxB,mBAAmB,EACnB,wBAAwB,GACzB,CAAC;AAwEF;;;GAGG;AAEH,wBAAgB,+BAA+B,CAC7C,aAAa,EAAE,MAAM,GACpB,KAAK,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAsDnE;AAGD,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,uDAAuD;IACvD,sBAAsB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC,CAAC,CAAC;AAEH;;;;;;GAMG;AAEH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,aAAa,EAAE,MAAM,CAAC;IACtB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,GAAG,wBAAwB,CAoM3B;AAED;;;;;;GAMG;AAEH,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG;IAClE,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC,CAoCA;AAED,qEAAqE;AAErE,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,eAAe,CAEjB;AA0CD,KAAK,YAAY,GAAG,QAAQ,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC,CAAC;AAEH,4DAA4D;AAE5D,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CA0Ef;AAGD,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAUtD,CAAC"}
@@ -27,12 +27,16 @@ import { applyOriginBackfill, planOriginBackfill } from "./origin-backfill.js";
27
27
  import { POLARITY_VALUE_BACKFILL_CODE, applyPolarityValueBackfill, planPolarityValueBackfill, } from "./polarity-values.js";
28
28
  import { applySourcePathRepairs, findSourceRepairs, plannedSourcePathRepairs, } from "./source-paths.js";
29
29
  import { applySupersededClosures, planSupersededClosures, } from "./superseded-closure.js";
30
+ import { SUPERSEDES_REASON_ACKNOWLEDGE_CODE, applySupersedesReasonAcknowledgement, planSupersedesReasonAcknowledgement, } from "./supersedes-reason.js";
30
31
  /** The KB schema generation that introduced entity `origin`. */
31
32
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
32
33
  export const ORIGIN_SCHEMA_VERSION = 6;
33
34
  /** The KB schema generation that requires body context on current entities. */
34
35
  // implements REQ-kb-entity-body-context, REQ-cli-schema-migration
35
36
  export const BODY_CONTEXT_SCHEMA_VERSION = 8;
37
+ /** The KB schema generation that adds decision firmness. */
38
+ // implements REQ-kb-decision-firmness, REQ-cli-schema-migration
39
+ export const DECISION_FIRMNESS_SCHEMA_VERSION = 9;
36
40
  /** Automatic: re-derive a drifted inventory with the current advisor. */
37
41
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
38
42
  export const SEMANTIC_INVENTORY_REDERIVE_CODE = "semantic_inventory_rederive";
@@ -88,7 +92,7 @@ function reviewAction(plan) {
88
92
  safety: "review",
89
93
  invocation: {
90
94
  kind: "review",
91
- instruction: `${plan.requirementId} (${plan.path}) no longer matches the current semantic advisor and cannot be re-derived automatically: ${plan.reasons.join("; ")}. Fix it by hand: run \`kibi model --input -\` with {"mode":"analyze","payload":{"type":"req","id":"${plan.requirementId}","properties":<the requirement's current properties>}} to get the current inventory; re-ground or remove each listed grounding link (kb_delete with the relationship) so modeled claims and requires_* links match one to one; kb_upsert the requirement with the returned semantic_inventory, logic_claims and semantic_source_hash (keep modeled only for claims that still have a grounding fact with the same claim_key); then run kibi sync.`,
95
+ instruction: `${plan.requirementId} (${plan.path}) no longer matches the current semantic advisor and cannot be re-derived automatically: ${plan.reasons.join("; ")}. Fix it in ${plan.path} itself: kibi sync rejects this requirement, so store-backed tools (kb_upsert, kb_delete) cannot see it until it compiles. In its front matter, write the re-derived contract from this action's evidence.contract (semantic_inventory, logic_claims, semantic_source_hash and their version fields), then make modeled claims and requires_* links match one to one: re-ground or remove each listed grounding link, and keep a claim modeled only while a grounding fact with the same claim_key remains. Run kibi sync to confirm. To see how the advisor reads the prose, run \`kibi model --input -\` with {"mode":"analyze","type":"req","id":"${plan.requirementId}","text":<the requirement's semantic_text, or its statement when it has none>}.`,
92
96
  },
93
97
  affectedEntityIds: [plan.requirementId],
94
98
  affectedFiles: [plan.path],
@@ -99,6 +103,8 @@ function reviewAction(plan) {
99
103
  reasons: plan.reasons,
100
104
  summary: plan.summary,
101
105
  changes: plan.changes.filter((change) => change.change !== "kept"),
106
+ contract: plan.contract,
107
+ contractHash: plan.contractHash,
102
108
  },
103
109
  });
104
110
  }
@@ -249,6 +255,38 @@ export function buildSchema6MigrationFragment(input) {
249
255
  }));
250
256
  }
251
257
  }
258
+ // Schema 9: acknowledge supersedes recorded before they had to explain
259
+ // themselves. Manifest only; no source changes and no reason is written.
260
+ if (input.currentSchemaVersion === null ||
261
+ input.currentSchemaVersion < DECISION_FIRMNESS_SCHEMA_VERSION) {
262
+ const unexplained = planSupersedesReasonAcknowledgement(input.workspaceRoot);
263
+ if (unexplained.length > 0) {
264
+ const id = "supersedes-reason-acknowledge";
265
+ // Not a source rewrite, but the schema upgrade and the store sync
266
+ // must wait for it like one: the bumped schema blocks without it.
267
+ sourceRewriteActionIds.push(id);
268
+ actions.push(migrationAction({
269
+ id,
270
+ code: SUPERSEDES_REASON_ACKNOWLEDGE_CODE,
271
+ category: "schema",
272
+ safety: "automatic",
273
+ autoApplicable: true,
274
+ invocation: {
275
+ kind: "cli",
276
+ command_argv: ["kibi", "migrate", "--yes"],
277
+ },
278
+ affectedEntityIds: unexplained.map((row) => row.id),
279
+ affectedFiles: [".kb/manifest.json"],
280
+ postconditions: [{ rule: "supersedes-reason-missing", findings: 0 }],
281
+ evidence: {
282
+ reason: "Schema 9 blocks a current requirement or ADR that supersedes another without a 'Why this changed' section. Existing ones are acknowledged in the manifest (counted by supersedes-reason-acknowledged); no reason is invented.",
283
+ count: unexplained.length,
284
+ byType: countByType(unexplained),
285
+ preserves: "every authored source file",
286
+ },
287
+ }));
288
+ }
289
+ }
252
290
  const drift = planInventoryRederivation(input.workspaceRoot);
253
291
  for (const plan of drift) {
254
292
  const action = plan.safe ? rederiveAction(plan) : reviewAction(plan);
@@ -397,6 +435,10 @@ export async function applySchema6MigrationAction(action, context) {
397
435
  applyContextMissingTags(context.workspaceRoot);
398
436
  return;
399
437
  }
438
+ case SUPERSEDES_REASON_ACKNOWLEDGE_CODE: {
439
+ applySupersedesReasonAcknowledgement(context.workspaceRoot);
440
+ return;
441
+ }
400
442
  case SEMANTIC_INVENTORY_REDERIVE_CODE: {
401
443
  const requirementId = action.affectedEntityIds[0];
402
444
  if (requirementId === undefined)
@@ -440,6 +482,7 @@ export const SCHEMA6_AUTOMATIC_CODES = new Set([
440
482
  POLARITY_VALUE_BACKFILL_CODE,
441
483
  SEMANTIC_TEXT_PIN_CODE,
442
484
  CONTEXT_MISSING_TAG_CODE,
485
+ SUPERSEDES_REASON_ACKNOWLEDGE_CODE,
443
486
  SEMANTIC_INVENTORY_REDERIVE_CODE,
444
487
  ENTITY_ORIGIN_BACKFILL_CODE,
445
488
  CLOSE_SUPERSEDED_REQUIREMENTS_CODE,
@@ -0,0 +1,26 @@
1
+ /** Migration action code for the schema 9 acknowledgement. */
2
+ export declare const SUPERSEDES_REASON_ACKNOWLEDGE_CODE = "supersedes_reason_acknowledge";
3
+ /** One superseding decision the migration acknowledges. */
4
+ export type SupersedesReasonTarget = Readonly<{
5
+ id: string;
6
+ type: string;
7
+ path: string;
8
+ /** The supersede edges to acknowledge, as the manifest records them. */
9
+ edges: readonly string[];
10
+ }>;
11
+ /**
12
+ * Superseding requirements and ADRs without a "Why this changed" section
13
+ * whose supersede edges the manifest does not acknowledge yet, retired ones
14
+ * included. Nothing in the sources changes: no reason is written, the
15
+ * manifest only records that these edges predate the rule. Read-only.
16
+ */
17
+ export declare function planSupersedesReasonAcknowledgement(workspaceRoot: string): SupersedesReasonTarget[];
18
+ /** The manifest list with the targets' edges added, sorted and unique. */
19
+ export declare function mergeSupersedesAcknowledgements(existing: readonly string[] | undefined, targets: readonly SupersedesReasonTarget[]): string[];
20
+ /**
21
+ * Record the acknowledged edges in the manifest; returns how many entities
22
+ * were acknowledged. Without a manifest there is no schema to upgrade from,
23
+ * so it refuses rather than report an acknowledgement it did not write.
24
+ */
25
+ export declare function applySupersedesReasonAcknowledgement(workspaceRoot: string): number;
26
+ //# sourceMappingURL=supersedes-reason.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supersedes-reason.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/supersedes-reason.ts"],"names":[],"mappings":"AA0BA,8DAA8D;AAE9D,eAAO,MAAM,kCAAkC,kCACd,CAAC;AAElC,2DAA2D;AAE3D,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B,CAAC,CAAC;AAEH;;;;;GAKG;AAEH,wBAAgB,mCAAmC,CACjD,aAAa,EAAE,MAAM,GACpB,sBAAsB,EAAE,CAgB1B;AAED,0EAA0E;AAE1E,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EACvC,OAAO,EAAE,SAAS,sBAAsB,EAAE,GACzC,MAAM,EAAE,CAIV;AAED;;;;GAIG;AAEH,wBAAgB,oCAAoC,CAClD,aAAa,EAAE,MAAM,GACpB,MAAM,CAiBR"}
@@ -0,0 +1,69 @@
1
+ /*
2
+ Kibi — repo-local, per-branch, queryable long-term memory for software projects
3
+ Copyright (C) 2026 Piotr Franczyk
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Affero General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Affero General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Affero General Public License
16
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ import { authoredSupersedes, listDecisionEntities, supersedeAcknowledgements, unexplainedSupersedes, } from "../../public/operations/decision-firmness.js";
19
+ import { readKbManifest, writeKbManifest } from "../../utils/kb-manifest.js";
20
+ /** Migration action code for the schema 9 acknowledgement. */
21
+ // implements REQ-kb-decision-firmness, REQ-cli-schema-migration
22
+ export const SUPERSEDES_REASON_ACKNOWLEDGE_CODE = "supersedes_reason_acknowledge";
23
+ /**
24
+ * Superseding requirements and ADRs without a "Why this changed" section
25
+ * whose supersede edges the manifest does not acknowledge yet, retired ones
26
+ * included. Nothing in the sources changes: no reason is written, the
27
+ * manifest only records that these edges predate the rule. Read-only.
28
+ */
29
+ // implements REQ-kb-decision-firmness, REQ-cli-schema-migration
30
+ export function planSupersedesReasonAcknowledgement(workspaceRoot) {
31
+ const entities = listDecisionEntities(workspaceRoot);
32
+ const known = new Set(readKbManifest(workspaceRoot)?.supersedesReasonAcknowledged ?? []);
33
+ const edges = authoredSupersedes(workspaceRoot, entities);
34
+ return unexplainedSupersedes(entities, edges)
35
+ .map((entity) => ({
36
+ id: entity.id,
37
+ type: entity.type,
38
+ path: entity.path,
39
+ edges: supersedeAcknowledgements(entity.id, edges).filter((edge) => !known.has(edge)),
40
+ }))
41
+ .filter((target) => target.edges.length > 0);
42
+ }
43
+ /** The manifest list with the targets' edges added, sorted and unique. */
44
+ // implements REQ-kb-decision-firmness
45
+ export function mergeSupersedesAcknowledgements(existing, targets) {
46
+ return [
47
+ ...new Set([...(existing ?? []), ...targets.flatMap((t) => t.edges)]),
48
+ ].sort();
49
+ }
50
+ /**
51
+ * Record the acknowledged edges in the manifest; returns how many entities
52
+ * were acknowledged. Without a manifest there is no schema to upgrade from,
53
+ * so it refuses rather than report an acknowledgement it did not write.
54
+ */
55
+ // implements REQ-kb-decision-firmness, REQ-cli-schema-migration
56
+ export function applySupersedesReasonAcknowledgement(workspaceRoot) {
57
+ const targets = planSupersedesReasonAcknowledgement(workspaceRoot);
58
+ if (targets.length === 0)
59
+ return 0;
60
+ const manifest = readKbManifest(workspaceRoot);
61
+ if (manifest === null) {
62
+ throw new Error("Cannot acknowledge existing supersedes without .kb/manifest.json; run 'kibi migrate --yes', which writes the manifest and the acknowledgement together.");
63
+ }
64
+ writeKbManifest(workspaceRoot, {
65
+ ...manifest,
66
+ supersedesReasonAcknowledged: mergeSupersedesAcknowledgements(manifest.supersedesReasonAcknowledged, targets),
67
+ });
68
+ return targets.length;
69
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"predicate-applyplan.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-applyplan.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAEV,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAQ9B,wBAAgB,eAAe,CAC7B,MAAM,EAAE,wBAAwB,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,gBAAgB,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EACvD,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,EAChC,WAAW,CAAC,EAAE;IACZ,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,GACA,mBAAmB,CAuLrB;AAGD,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,mBAAmB,EAC/B,IAAI,EAAE,qBAAqB,GAC1B,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA0ChC;AAGD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,SAAS,CAAC,EAAE,MAAM,EAClB,mBAAmB,GAAE,SAAS,MAAM,EAAO,GAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAuBhC;AAoBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,qBAAqB,GAC1B,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAwBhC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,0BAA0B,CAoE5B"}
1
+ {"version":3,"file":"predicate-applyplan.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-applyplan.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAEV,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAQ9B,wBAAgB,eAAe,CAC7B,MAAM,EAAE,wBAAwB,EAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,gBAAgB,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EACvD,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,EAChC,WAAW,CAAC,EAAE;IACZ,WAAW,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC,GACA,mBAAmB,CAuLrB;AAGD,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,mBAAmB,EAC/B,IAAI,EAAE,qBAAqB,GAC1B,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAkDhC;AAGD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,SAAS,CAAC,EAAE,MAAM,EAClB,mBAAmB,GAAE,SAAS,MAAM,EAAO,GAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAuBhC;AAoBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,qBAAqB,GAC1B,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAwBhC;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,0BAA0B,CAoE5B"}
@@ -1,4 +1,4 @@
1
- import { semanticClaimKey } from "../semantic-advisor/clauses.js";
1
+ import { normalizeSemanticClause, semanticClaimKey, } from "../semantic-advisor/clauses.js";
2
2
  import { exactLauncherPredicateArgs } from "../semantic-advisor/predicate-rules-launcher.js";
3
3
  import { aggregateBindingProvenance, bindingCanBeApplied, classifyBinding, isGenericPlaceholder, isParticipantArgumentType, } from "./predicate-bindings.js";
4
4
  import { inferArgs } from "./predicate-inference.js";
@@ -190,11 +190,19 @@ export function buildPredicateApplyPlan(suggestion, args) {
190
190
  ? { subject_key: suggestion.subject_key }
191
191
  : {}),
192
192
  predicate_name: suggestion.predicate_name,
193
+ // The schema's namespace, so the fact conforms to the project
194
+ // schema it was planned from rather than to default:<name>.
195
+ ...(suggestion.schema.predicate_namespace
196
+ ? { predicate_namespace: suggestion.schema.predicate_namespace }
197
+ : {}),
193
198
  predicate_args: suggestion.predicate_args,
194
199
  canonical_key: suggestion.canonical_key,
195
200
  polarity: suggestion.polarity,
196
201
  claim_key: claimKey,
197
- claim_text: args.text.trim(),
202
+ // The ledger stores the clause without its sentence punctuation, and
203
+ // the proof compares the fact's claim_text with the ledger entry
204
+ // verbatim, so the fact quotes the same normalised clause.
205
+ claim_text: normalizeSemanticClause(args.text),
198
206
  },
199
207
  relationships: [],
200
208
  },
@@ -1 +1 @@
1
- {"version":3,"file":"predicate-loader.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAK3E,OAAO,KAAK,EACV,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAI9B,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAExE;AAGD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,IAAI,CACxE,wBAAwB,EACxB,UAAU,CACX,GAAG;IACF,WAAW,EAAE,mBAAmB,CAAC;CAClC,CA6BA;AAGD,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,sBAAsB,EAAE,OAAO,EAC/B,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAwBrC;AAGD,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,wBAAwB,EAAE,CA0D5B;AAGD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,mBAAmB,GAAG,SAAS,CAOjC;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAQpD"}
1
+ {"version":3,"file":"predicate-loader.d.ts","sourceRoot":"","sources":["../../../src/operations/modeling/predicate-loader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAK3E,OAAO,KAAK,EACV,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAI9B,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAExE;AAGD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,wBAAwB,GAAG,IAAI,CACxE,wBAAwB,EACxB,UAAU,CACX,GAAG;IACF,WAAW,EAAE,mBAAmB,CAAC;CAClC,CAgCA;AAGD,wBAAsB,4BAA4B,CAChD,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,sBAAsB,EAAE,OAAO,EAC/B,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAwBrC;AAGD,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,wBAAwB,EAAE,CAoE5B;AAGD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,mBAAmB,GAAG,SAAS,CAOjC;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAQpD"}
@@ -10,6 +10,9 @@ export function schemaForCandidate(schema) {
10
10
  return {
11
11
  id: schema.id,
12
12
  predicate_name: schema.predicate_name,
13
+ ...(schema.predicate_namespace
14
+ ? { predicate_namespace: schema.predicate_namespace }
15
+ : {}),
13
16
  title: schema.title,
14
17
  description: schema.description,
15
18
  argument_names: schema.argument_names,
@@ -67,10 +70,18 @@ export function predicateSchemaFromEntity(entity) {
67
70
  const argumentDescriptions = stringArray(entity.argument_descriptions);
68
71
  const keyArguments = stringArray(entity.key_arguments);
69
72
  const vocabulary = predicateVocabularyFromEntity(entity);
73
+ // A project schema's namespace is part of the predicate signature the
74
+ // conformance rule checks, so a planned fact has to carry it.
75
+ const predicateNamespace = normalizeOptionalString(typeof entity.predicate_namespace === "string"
76
+ ? entity.predicate_namespace
77
+ : undefined);
70
78
  return [
71
79
  {
72
80
  id: String(entity.id ?? hashId("FACT-SCHEMA", [predicateName])),
73
81
  predicate_name: predicateName,
82
+ ...(predicateNamespace && predicateNamespace !== "default"
83
+ ? { predicate_namespace: predicateNamespace }
84
+ : {}),
74
85
  title: String(entity.title ?? predicateName),
75
86
  description: String(entity.description ??
76
87
  `Project-local ${predicateName} predicate schema.`),
@@ -6,6 +6,8 @@ export interface PredicateUsageHints {
6
6
  export interface PredicateSchemaCandidate {
7
7
  id: string;
8
8
  predicate_name: string;
9
+ /** The schema's predicate_namespace; absent for the default namespace. */
10
+ predicate_namespace?: string;
9
11
  title: string;
10
12
  description: string;
11
13
  argument_names: string[];
@@ -128,7 +130,30 @@ export interface ExistingClaimGrounding {
128
130
  };
129
131
  factId: string;
130
132
  factKind: string | null;
133
+ /** The stored claim_key of the grounding fact. */
131
134
  claimKey: string;
135
+ /** The stored canonical_key of the grounding fact (predicate facts), else null. */
136
+ canonicalKey: string | null;
137
+ /**
138
+ * How the fact was recognised as grounding this claim: the same claim_key
139
+ * (the same proposition text), or the same canonical_key as the recommended
140
+ * candidate (the same predicate tuple stated in other words).
141
+ */
142
+ matchedBy: "claim_key" | "canonical_key";
143
+ }
144
+ /**
145
+ * A stored decision-predicate fact of a current requirement that agrees with
146
+ * the recommended candidate on every key argument and decides the opposite,
147
+ * found when no hash-bound plan carried the contradiction analysis.
148
+ */
149
+ export interface CandidateDecisionConflict {
150
+ requirementId: string;
151
+ factId: string;
152
+ /** The stored fact's effective decision. */
153
+ effect: string;
154
+ /** The candidate's effective decision. */
155
+ proposedEffect: string;
156
+ canonicalKey: string;
132
157
  }
133
158
  export interface SuggestPredicatesResult {
134
159
  content: Array<{
@@ -143,7 +168,7 @@ export interface SuggestPredicatesResult {
143
168
  requirementId: string | null;
144
169
  subject: string;
145
170
  candidates: PredicateSuggestion[];
146
- recommendedAction: "apply_requires_predicate" | "provide_argument_bindings" | "resolve_schema_reference" | "record_ontology_gap" | "review_nonlogical" | "replace_grounding";
171
+ recommendedAction: "apply_requires_predicate" | "provide_argument_bindings" | "resolve_schema_reference" | "record_ontology_gap" | "review_nonlogical" | "replace_grounding" | "extend_requirement" | "keep_existing_grounding";
147
172
  recommendedPredicateSchema: RecommendedPredicateSchema | null;
148
173
  applyPlan: Array<Record<string, unknown>>;
149
174
  relationshipPlan: Record<string, unknown> | null;
@@ -156,6 +181,12 @@ export interface SuggestPredicatesResult {
156
181
  /** The planned predicate fact id a requires_predicate link must target (never a candidate id). */
157
182
  relationshipTarget?: string | null;
158
183
  existingGrounding?: ExistingClaimGrounding[];
184
+ /**
185
+ * Stored decision facts of current requirements that contradict the
186
+ * recommended candidate on its key arguments; empty when a plan carried
187
+ * the contradiction analysis or no complete candidate was found.
188
+ */
189
+ decisionConflicts?: CandidateDecisionConflict[];
159
190
  replacementPlan?: Record<string, unknown> | null;
160
191
  /** On provide_argument_bindings: one hint per unbound argument of the recommended candidate. */
161
192
  bindingHints?: BindingHint[];