kibi-cli 2.21.0 → 2.22.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.
Files changed (164) hide show
  1. package/dist/cli-operation-metadata.d.ts +1 -1
  2. package/dist/cli-operation-metadata.js +1 -1
  3. package/dist/cli-register-foundation.d.ts.map +1 -1
  4. package/dist/cli-register-foundation.js +1 -0
  5. package/dist/commands/check.d.ts +0 -1
  6. package/dist/commands/check.d.ts.map +1 -1
  7. package/dist/commands/check.js +47 -111
  8. package/dist/commands/doctor.d.ts.map +1 -1
  9. package/dist/commands/doctor.js +107 -5
  10. package/dist/commands/init-helpers.d.ts +14 -1
  11. package/dist/commands/init-helpers.d.ts.map +1 -1
  12. package/dist/commands/init-helpers.js +49 -10
  13. package/dist/commands/init.d.ts +1 -0
  14. package/dist/commands/init.d.ts.map +1 -1
  15. package/dist/commands/init.js +27 -4
  16. package/dist/commands/legacy-storage-migration.d.ts +46 -1
  17. package/dist/commands/legacy-storage-migration.d.ts.map +1 -1
  18. package/dist/commands/legacy-storage-migration.js +244 -9
  19. package/dist/commands/migrate.d.ts.map +1 -1
  20. package/dist/commands/migrate.js +150 -166
  21. package/dist/commands/sync/manifest.d.ts.map +1 -1
  22. package/dist/commands/sync/manifest.js +9 -0
  23. package/dist/commands/sync/persistence.d.ts.map +1 -1
  24. package/dist/commands/sync/persistence.js +4 -0
  25. package/dist/decision-firmness.d.ts +39 -0
  26. package/dist/decision-firmness.d.ts.map +1 -0
  27. package/dist/decision-firmness.js +115 -0
  28. package/dist/extractors/markdown.d.ts +2 -0
  29. package/dist/extractors/markdown.d.ts.map +1 -1
  30. package/dist/extractors/markdown.js +14 -0
  31. package/dist/extractors/symbols-coordinator.js +1 -0
  32. package/dist/intent-search.d.ts.map +1 -1
  33. package/dist/intent-search.js +28 -6
  34. package/dist/operations/migration/inventory-rederive.d.ts +40 -1
  35. package/dist/operations/migration/inventory-rederive.d.ts.map +1 -1
  36. package/dist/operations/migration/inventory-rederive.js +99 -8
  37. package/dist/operations/migration/requirement-status.d.ts +25 -0
  38. package/dist/operations/migration/requirement-status.d.ts.map +1 -0
  39. package/dist/operations/migration/requirement-status.js +105 -0
  40. package/dist/operations/migration/schema6.d.ts +27 -0
  41. package/dist/operations/migration/schema6.d.ts.map +1 -1
  42. package/dist/operations/migration/schema6.js +308 -7
  43. package/dist/operations/migration/supersedes-reason.d.ts +26 -0
  44. package/dist/operations/migration/supersedes-reason.d.ts.map +1 -0
  45. package/dist/operations/migration/supersedes-reason.js +69 -0
  46. package/dist/operations/migration/symbol-legacy-links.d.ts +51 -0
  47. package/dist/operations/migration/symbol-legacy-links.d.ts.map +1 -0
  48. package/dist/operations/migration/symbol-legacy-links.js +319 -0
  49. package/dist/operations/modeling/predicate-applyplan.d.ts.map +1 -1
  50. package/dist/operations/modeling/predicate-applyplan.js +10 -2
  51. package/dist/operations/modeling/predicate-loader.d.ts.map +1 -1
  52. package/dist/operations/modeling/predicate-loader.js +11 -0
  53. package/dist/operations/modeling/predicate-types.d.ts +32 -1
  54. package/dist/operations/modeling/predicate-types.d.ts.map +1 -1
  55. package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
  56. package/dist/operations/modeling/suggest-predicates.js +175 -35
  57. package/dist/operations/mutation/context-warning.d.ts +12 -2
  58. package/dist/operations/mutation/context-warning.d.ts.map +1 -1
  59. package/dist/operations/mutation/context-warning.js +6 -6
  60. package/dist/operations/mutation/delete.d.ts +5 -1
  61. package/dist/operations/mutation/delete.d.ts.map +1 -1
  62. package/dist/operations/mutation/delete.js +223 -17
  63. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  64. package/dist/operations/mutation/serialization.js +1 -0
  65. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  66. package/dist/operations/mutation/source-authoring.js +130 -35
  67. package/dist/operations/mutation/types.d.ts +39 -1
  68. package/dist/operations/mutation/types.d.ts.map +1 -1
  69. package/dist/operations/mutation/upsert.d.ts +17 -2
  70. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  71. package/dist/operations/mutation/upsert.js +82 -13
  72. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  73. package/dist/operations/mutation/validate-upsert.js +40 -8
  74. package/dist/operations/planning/apply-plan.d.ts +6 -1
  75. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  76. package/dist/operations/planning/apply-plan.js +26 -5
  77. package/dist/public/impact/diagnostics.d.ts.map +1 -1
  78. package/dist/public/impact/diagnostics.js +24 -14
  79. package/dist/public/operations/catalog.d.ts +14 -5
  80. package/dist/public/operations/catalog.d.ts.map +1 -1
  81. package/dist/public/operations/check-executor.d.ts.map +1 -1
  82. package/dist/public/operations/check-executor.js +6 -0
  83. package/dist/public/operations/contracts.d.ts.map +1 -1
  84. package/dist/public/operations/contracts.js +35 -2
  85. package/dist/public/operations/decision-firmness.d.ts +34 -0
  86. package/dist/public/operations/decision-firmness.d.ts.map +1 -0
  87. package/dist/public/operations/decision-firmness.js +216 -0
  88. package/dist/public/operations/discovery-executors.d.ts +2 -0
  89. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  90. package/dist/public/operations/discovery-executors.js +25 -4
  91. package/dist/public/operations/migration-plan.d.ts +2 -0
  92. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  93. package/dist/public/operations/migration-plan.js +101 -16
  94. package/dist/public/operations/result-envelope.d.ts.map +1 -1
  95. package/dist/public/operations/result-envelope.js +27 -1
  96. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  97. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  98. package/dist/public/operations/specs/check-rules.generated.js +6 -1
  99. package/dist/public/operations/specs/check.d.ts +1 -1
  100. package/dist/public/operations/specs/mutation-schemas.d.ts +5 -0
  101. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  102. package/dist/public/operations/specs/mutation-schemas.js +5 -0
  103. package/dist/public/operations/specs/mutation.d.ts +6 -2
  104. package/dist/public/operations/specs/mutation.d.ts.map +1 -1
  105. package/dist/public/operations/specs/mutation.js +6 -2
  106. package/dist/public/operations/specs/planning.d.ts +2 -2
  107. package/dist/public/operations/specs/planning.js +2 -2
  108. package/dist/public/operations/specs/upsert.d.ts +5 -0
  109. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  110. package/dist/public/operations/symbol-granularity-check.d.ts +18 -0
  111. package/dist/public/operations/symbol-granularity-check.d.ts.map +1 -0
  112. package/dist/public/operations/symbol-granularity-check.js +175 -0
  113. package/dist/public/schemas/entity.d.ts.map +1 -1
  114. package/dist/public/schemas/entity.js +11 -0
  115. package/dist/public/skills/kibi-traceability/SKILL.md +6 -4
  116. package/dist/public/skills/kibi-usage/SKILL.md +50 -10
  117. package/dist/public/skills/kibi-usage/resources/source-authoring.md +4 -2
  118. package/dist/public/symbol-granularity.d.ts +17 -0
  119. package/dist/public/symbol-granularity.d.ts.map +1 -1
  120. package/dist/public/symbol-granularity.js +21 -0
  121. package/dist/relationships/shards.d.ts +10 -0
  122. package/dist/relationships/shards.d.ts.map +1 -1
  123. package/dist/relationships/shards.js +27 -11
  124. package/dist/schemas/entity.schema.json +28 -0
  125. package/dist/search-answer.d.ts +31 -2
  126. package/dist/search-answer.d.ts.map +1 -1
  127. package/dist/search-answer.js +115 -17
  128. package/dist/traceability/evidence-model.d.ts +7 -3
  129. package/dist/traceability/evidence-model.d.ts.map +1 -1
  130. package/dist/traceability/staged-symbols-manifest.js +6 -5
  131. package/dist/traceability/validate.d.ts +14 -1
  132. package/dist/traceability/validate.d.ts.map +1 -1
  133. package/dist/traceability/validate.js +41 -0
  134. package/dist/types/entities.d.ts +4 -0
  135. package/dist/types/entities.d.ts.map +1 -1
  136. package/dist/utils/kb-manifest.d.ts +6 -0
  137. package/dist/utils/kb-manifest.d.ts.map +1 -1
  138. package/dist/utils/kb-manifest.js +6 -0
  139. package/dist/utils/rule-registry.generated.d.ts +26 -0
  140. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  141. package/dist/utils/rule-registry.generated.js +31 -0
  142. package/dist/utils/schema-version.d.ts +1 -1
  143. package/dist/utils/schema-version.d.ts.map +1 -1
  144. package/dist/utils/schema-version.js +3 -1
  145. package/package.json +3 -3
  146. package/schema/entities.pl +6 -0
  147. package/src/public/impact/diagnostics.ts +29 -17
  148. package/src/public/operations/check-executor.ts +13 -0
  149. package/src/public/operations/contracts.ts +39 -2
  150. package/src/public/operations/decision-firmness.ts +280 -0
  151. package/src/public/operations/discovery-executors.ts +29 -4
  152. package/src/public/operations/migration-plan.ts +100 -19
  153. package/src/public/operations/result-envelope.ts +34 -1
  154. package/src/public/operations/specs/check-rules.generated.ts +6 -1
  155. package/src/public/operations/specs/mutation-schemas.ts +6 -0
  156. package/src/public/operations/specs/mutation.ts +7 -2
  157. package/src/public/operations/specs/planning.ts +2 -2
  158. package/src/public/operations/symbol-granularity-check.ts +233 -0
  159. package/src/public/schemas/entity.ts +12 -0
  160. package/src/public/skills/kibi-traceability/SKILL.md +6 -4
  161. package/src/public/skills/kibi-usage/SKILL.md +50 -10
  162. package/src/public/skills/kibi-usage/resources/source-authoring.md +4 -2
  163. package/src/public/symbol-granularity.ts +37 -0
  164. package/src/schemas/entity.schema.json +28 -0
@@ -0,0 +1,105 @@
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 path from "node:path";
19
+ import { planInventoryRederivation, } from "./inventory-rederive.js";
20
+ import { listLaneMarkdownFiles, readText, readTopLevelField, sliceFrontmatter, withTopLevelField, writeFileAtomically, } from "./kb-sources.js";
21
+ /**
22
+ * Requirement statuses outside the current vocabulary (`req-status-vocabulary`).
23
+ *
24
+ * A requirement with ADR vocabulary such as `status: accepted` compiles, but
25
+ * it is not a current requirement: the proof ladder skips it and the
26
+ * ingestion boundary does not validate its semantic inventory, so inventory
27
+ * drift stays hidden until someone maps the status. Which current status a
28
+ * legacy one means is a semantic choice, so the mapping is only suggested;
29
+ * the latent drift is computed as if the suggestion were applied.
30
+ */
31
+ /** Statuses `kibi check` accepts on a requirement (canonical and legacy). */
32
+ const REQUIREMENT_STATUSES = new Set([
33
+ "open",
34
+ "in_progress",
35
+ "closed",
36
+ "active",
37
+ "approved",
38
+ ]);
39
+ /**
40
+ * Suggested current status for ADR or lifecycle vocabulary found on
41
+ * requirements: decided or still-proposed intent stays `open`; retired
42
+ * intent is `closed`.
43
+ */
44
+ // implements REQ-cli-schema-migration
45
+ export const SUGGESTED_REQUIREMENT_STATUS = {
46
+ accepted: "open",
47
+ proposed: "open",
48
+ draft: "open",
49
+ deprecated: "closed",
50
+ superseded: "closed",
51
+ rejected: "closed",
52
+ };
53
+ function statusOf(content) {
54
+ const slice = sliceFrontmatter(content);
55
+ return slice === null ? undefined : readTopLevelField(slice.text, "status");
56
+ }
57
+ function idOf(content) {
58
+ const slice = sliceFrontmatter(content);
59
+ return slice === null ? undefined : readTopLevelField(slice.text, "id");
60
+ }
61
+ /** Every requirement whose authored status is outside the vocabulary. */
62
+ // implements REQ-cli-schema-migration
63
+ export function planRequirementStatusMappings(workspaceRoot) {
64
+ const findings = [];
65
+ for (const file of listLaneMarkdownFiles(workspaceRoot, ["requirements"])) {
66
+ const content = readText(file.absolutePath);
67
+ if (content === null)
68
+ continue;
69
+ const status = statusOf(content);
70
+ if (typeof status !== "string" || REQUIREMENT_STATUSES.has(status))
71
+ continue;
72
+ const id = idOf(content);
73
+ const requirementId = typeof id === "string" && id.length > 0
74
+ ? id
75
+ : path.basename(file.relativePath, ".md");
76
+ const suggestedStatus = SUGGESTED_REQUIREMENT_STATUS[status] ?? null;
77
+ findings.push({
78
+ requirementId,
79
+ path: file.relativePath,
80
+ status,
81
+ suggestedStatus,
82
+ latentDrift: suggestedStatus === null
83
+ ? null
84
+ : (planInventoryRederivation(workspaceRoot, requirementId, {
85
+ status: suggestedStatus,
86
+ }).find((plan) => plan.requirementId === requirementId) ?? null),
87
+ });
88
+ }
89
+ return findings.sort((left, right) => left.requirementId.localeCompare(right.requirementId));
90
+ }
91
+ /**
92
+ * Set the status of one requirement from `from` to `to`, replacing only its
93
+ * `status` line. Refuses when the authored status is no longer `from`.
94
+ */
95
+ // implements REQ-cli-schema-migration
96
+ export function applyRequirementStatusMapping(workspaceRoot, relativePath, from, to) {
97
+ const absolute = path.join(workspaceRoot, relativePath);
98
+ const content = readText(absolute);
99
+ if (content === null || statusOf(content) !== from)
100
+ throw new Error(`${relativePath} no longer has status ${from}; rerun kibi migrate and approve the new plan.`);
101
+ const next = withTopLevelField(content, "status", to);
102
+ if (next === null)
103
+ throw new Error(`${relativePath}: status could not be set to ${to} without changing other frontmatter fields; set it by hand.`);
104
+ writeFileAtomically(absolute, next);
105
+ }
@@ -4,14 +4,31 @@ 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. */
10
12
  export declare const SEMANTIC_INVENTORY_REVIEW_CODE = "semantic_inventory_review";
13
+ /**
14
+ * Review, applied only when approved by id: re-derive a drifted inventory and
15
+ * drop the grounding links that no longer ground a modeled claim.
16
+ */
17
+ export declare const SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE = "semantic_inventory_rederive_drop_grounding";
18
+ /** Review, applied only when approved by id: map a legacy requirement status. */
19
+ export declare const REQ_STATUS_VOCABULARY_MAP_CODE = "req_status_vocabulary_map";
11
20
  /** Automatic: stamp `origin: {kind: migration}` on authored entities. */
12
21
  export declare const ENTITY_ORIGIN_BACKFILL_CODE = "entity_origin_backfill";
13
22
  export declare const ENTITY_ORIGIN_BACKFILL_ACTION_ID = "entity-origin-backfill";
14
23
  export { CLOSE_SUPERSEDED_REQUIREMENTS_CODE, MIGRATION_SYNC_ACTION_ID, MIGRATION_SYNC_CODE, SOURCE_PATH_REWRITE_CODE, };
24
+ /**
25
+ * One action per requirement whose status is outside the vocabulary: a
26
+ * review (the target status is a semantic choice) carrying the suggested
27
+ * mapping and the inventory drift the requirement shows once mapped. With a
28
+ * suggestion it is executable when approved by id; the re-derivation of the
29
+ * latent drift depends on it.
30
+ */
31
+ export declare function requirementStatusActions(workspaceRoot: string): MigrationAction[];
15
32
  /**
16
33
  * Exceptions without approved_by, read from authored sources so the list is
17
34
  * available before the KB compiles.
@@ -49,6 +66,11 @@ export declare function buildLifecycleRepairActions(workspaceRoot: string): {
49
66
  actions: MigrationAction[];
50
67
  sourceRewriteActionIds: string[];
51
68
  };
69
+ /**
70
+ * The automatic legacy-link pass over `.kb/symbols.yaml`, bound to the
71
+ * manifest bytes it was planned from; null when no link needs a mark.
72
+ */
73
+ export declare function symbolLegacyLinkAction(workspaceRoot: string): MigrationAction | null;
52
74
  /** The sync that recompiles sources rewritten by earlier actions. */
53
75
  export declare function migrationSyncAction(dependsOn: readonly string[]): MigrationAction;
54
76
  type ApplyContext = Readonly<{
@@ -57,5 +79,10 @@ type ApplyContext = Readonly<{
57
79
  }>;
58
80
  /** Execute one automatic action produced by this module. */
59
81
  export declare function applySchema6MigrationAction(action: MigrationAction, context: ApplyContext): Promise<void>;
82
+ /**
83
+ * Review actions Kibi can execute, but only when a person approves them by
84
+ * id (`--approved-action`): `--apply-safe` selects automatic actions alone.
85
+ */
86
+ export declare const SCHEMA6_APPROVABLE_REVIEW_CODES: ReadonlySet<string>;
60
87
  export declare const SCHEMA6_AUTOMATIC_CODES: ReadonlySet<string>;
61
88
  //# sourceMappingURL=schema6.d.ts.map
@@ -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;AAoD1D,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;;;GAGG;AAEH,eAAO,MAAM,+CAA+C,+CACd,CAAC;AAC/C,iFAAiF;AAEjF,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;AAgLF;;;;;;GAMG;AAEH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,GACpB,eAAe,EAAE,CAqEnB;AAyBD;;;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,CAgN3B;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;;;GAGG;AAEH,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,GACpB,eAAe,GAAG,IAAI,CAqBxB;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,CAgHf;AAED;;;GAGG;AAEH,eAAO,MAAM,+BAA+B,EAAE,WAAW,CAAC,MAAM,CAK9D,CAAC;AAGH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAWtD,CAAC"}
@@ -21,24 +21,39 @@ import { migrationAction, } from "../../public/operations/migration-plan.js";
21
21
  import { CLOSE_SUPERSEDED_REQUIREMENTS_ACTION_ID, CLOSE_SUPERSEDED_REQUIREMENTS_CODE, MIGRATION_SYNC_ACTION_ID, MIGRATION_SYNC_CODE, SOURCE_PATH_REWRITE_ACTION_ID, SOURCE_PATH_REWRITE_CODE, closeSupersededRequirementsActionInput, exceptionUnapprovedActionInput, migrationSyncActionInput, sourcePathReviewActionInput, sourcePathRewriteActionInput, supersessionCycleReviewActionInput, } from "../../public/operations/schema6-check-actions.js";
22
22
  import { readAllShards } from "../../relationships/shards.js";
23
23
  import { CONTEXT_MISSING_TAG_CODE, SEMANTIC_TEXT_PIN_CODE, applyContextMissingTags, applySemanticTextPins, countByType, planContextMissingTags, planSemanticTextPins, } from "./entity-body-context.js";
24
- import { applyInventoryRederivation, planInventoryRederivation, } from "./inventory-rederive.js";
24
+ import { applyInventoryRederivation, applyInventoryRederivationDroppingGrounding, planInventoryRederivation, } from "./inventory-rederive.js";
25
25
  import { listLaneMarkdownFiles } from "./kb-sources.js";
26
26
  import { applyOriginBackfill, planOriginBackfill } from "./origin-backfill.js";
27
27
  import { POLARITY_VALUE_BACKFILL_CODE, applyPolarityValueBackfill, planPolarityValueBackfill, } from "./polarity-values.js";
28
+ import { applyRequirementStatusMapping, planRequirementStatusMappings, } from "./requirement-status.js";
28
29
  import { applySourcePathRepairs, findSourceRepairs, plannedSourcePathRepairs, } from "./source-paths.js";
29
30
  import { applySupersededClosures, planSupersededClosures, } from "./superseded-closure.js";
31
+ import { SUPERSEDES_REASON_ACKNOWLEDGE_CODE, applySupersedesReasonAcknowledgement, planSupersedesReasonAcknowledgement, } from "./supersedes-reason.js";
32
+ import { SYMBOL_LEGACY_LINK_MARK_ACTION_ID, SYMBOL_LEGACY_LINK_MARK_CODE, applySymbolLegacyLinks, planSymbolLegacyLinks, } from "./symbol-legacy-links.js";
30
33
  /** The KB schema generation that introduced entity `origin`. */
31
34
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
32
35
  export const ORIGIN_SCHEMA_VERSION = 6;
33
36
  /** The KB schema generation that requires body context on current entities. */
34
37
  // implements REQ-kb-entity-body-context, REQ-cli-schema-migration
35
38
  export const BODY_CONTEXT_SCHEMA_VERSION = 8;
39
+ /** The KB schema generation that adds decision firmness. */
40
+ // implements REQ-kb-decision-firmness, REQ-cli-schema-migration
41
+ export const DECISION_FIRMNESS_SCHEMA_VERSION = 9;
36
42
  /** Automatic: re-derive a drifted inventory with the current advisor. */
37
43
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
38
44
  export const SEMANTIC_INVENTORY_REDERIVE_CODE = "semantic_inventory_rederive";
39
45
  /** Review: a drifted inventory Kibi cannot re-derive safely. */
40
46
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
41
47
  export const SEMANTIC_INVENTORY_REVIEW_CODE = "semantic_inventory_review";
48
+ /**
49
+ * Review, applied only when approved by id: re-derive a drifted inventory and
50
+ * drop the grounding links that no longer ground a modeled claim.
51
+ */
52
+ // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
53
+ export const SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE = "semantic_inventory_rederive_drop_grounding";
54
+ /** Review, applied only when approved by id: map a legacy requirement status. */
55
+ // implements REQ-cli-schema-migration
56
+ export const REQ_STATUS_VOCABULARY_MAP_CODE = "req_status_vocabulary_map";
42
57
  /** Automatic: stamp `origin: {kind: migration}` on authored entities. */
43
58
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
44
59
  export const ENTITY_ORIGIN_BACKFILL_CODE = "entity_origin_backfill";
@@ -52,15 +67,33 @@ const CURRENT_REQUIREMENT_STATUSES = new Set([
52
67
  "active",
53
68
  "approved",
54
69
  ]);
55
- function rederiveAction(plan) {
70
+ function rederiveAction(plan, after) {
56
71
  const changed = plan.changes.filter((change) => change.change !== "kept");
72
+ const id = `semantic-inventory-rederive-${plan.requirementId}`;
57
73
  return migrationAction({
58
- id: `semantic-inventory-rederive-${plan.requirementId}`,
74
+ id,
59
75
  code: SEMANTIC_INVENTORY_REDERIVE_CODE,
60
76
  category: "semantic",
61
- safety: "automatic",
62
- autoApplicable: true,
63
- invocation: { kind: "cli", command_argv: ["kibi", "migrate", "--yes"] },
77
+ ...(after === undefined
78
+ ? {
79
+ safety: "automatic",
80
+ autoApplicable: true,
81
+ invocation: {
82
+ kind: "cli",
83
+ command_argv: ["kibi", "migrate", "--yes"],
84
+ },
85
+ }
86
+ : {
87
+ safety: "review",
88
+ autoApplicable: false,
89
+ invocation: {
90
+ kind: "cli",
91
+ command_argv: approvalArgv([after.actionId, id]),
92
+ },
93
+ dependsOn: [after.actionId],
94
+ dispositionRequired: true,
95
+ allowedDispositions: ["fixed", "deferred"],
96
+ }),
64
97
  affectedEntityIds: [plan.requirementId],
65
98
  affectedFiles: [plan.path],
66
99
  postconditions: [
@@ -77,9 +110,23 @@ function rederiveAction(plan) {
77
110
  changes: changed,
78
111
  contractHash: plan.contractHash,
79
112
  rule: "Claims whose claim_key and claim_text still match keep their status and grounding; new or changed claims are unresolved, never modeled.",
113
+ ...(after === undefined
114
+ ? {}
115
+ : {
116
+ afterStatus: after.status,
117
+ note: `This drift shows once the requirement has status ${after.status}; approve it together with ${after.actionId}.`,
118
+ }),
80
119
  },
81
120
  });
82
121
  }
122
+ function approvalArgv(ids) {
123
+ return [
124
+ "kibi",
125
+ "migrate",
126
+ "--apply-safe",
127
+ ...ids.flatMap((id) => ["--approved-action", id]),
128
+ ];
129
+ }
83
130
  function reviewAction(plan) {
84
131
  return migrationAction({
85
132
  id: `semantic-inventory-review-${plan.requirementId}`,
@@ -88,7 +135,7 @@ function reviewAction(plan) {
88
135
  safety: "review",
89
136
  invocation: {
90
137
  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.`,
138
+ 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.${plan.rederivableByDroppingGrounding ? ` Or approve semantic-inventory-rederive-drop-grounding-${plan.requirementId}, which writes that contract and removes exactly the listed orphaned grounding links.` : ""} 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
139
  },
93
140
  affectedEntityIds: [plan.requirementId],
94
141
  affectedFiles: [plan.path],
@@ -99,9 +146,151 @@ function reviewAction(plan) {
99
146
  reasons: plan.reasons,
100
147
  summary: plan.summary,
101
148
  changes: plan.changes.filter((change) => change.change !== "kept"),
149
+ contract: plan.contract,
150
+ contractHash: plan.contractHash,
102
151
  },
103
152
  });
104
153
  }
154
+ /**
155
+ * The explicit alternative to a manual inventory fix: write the re-derived
156
+ * contract and remove the orphaned grounding links from the requirement's
157
+ * front matter. It drops modeled logic, so it is a review action that
158
+ * `--apply-safe` never selects on its own; approving its id runs it.
159
+ */
160
+ function dropGroundingAction(plan, after) {
161
+ const id = `semantic-inventory-rederive-drop-grounding-${plan.requirementId}`;
162
+ const drops = plan.orphanedGrounding.map(({ type, target, claimKey }) => ({
163
+ type,
164
+ target,
165
+ claimKey,
166
+ }));
167
+ return migrationAction({
168
+ id,
169
+ code: SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE,
170
+ category: "semantic",
171
+ safety: "review",
172
+ autoApplicable: false,
173
+ invocation: {
174
+ kind: "cli",
175
+ command_argv: approvalArgv(after === undefined ? [id] : [after.actionId, id]),
176
+ },
177
+ dependsOn: after === undefined ? [] : [after.actionId],
178
+ affectedEntityIds: [plan.requirementId],
179
+ affectedFiles: [plan.path],
180
+ postconditions: [
181
+ {
182
+ check: "proposition-complete-ingestion",
183
+ entityId: plan.requirementId,
184
+ errors: 0,
185
+ },
186
+ ],
187
+ dispositionRequired: true,
188
+ allowedDispositions: ["fixed", "deferred"],
189
+ evidence: {
190
+ reason: `Re-derive the semantic inventory of ${plan.requirementId} and drop the ${drops.length} grounding link(s) that no longer ground a modeled claim, so kibi sync accepts it. The modeled logic those links carried is removed from the requirement (the facts themselves stay); re-ground the claims later with kibi model if they still matter.`,
191
+ approve: `kibi migrate --apply-safe --approved-plan-hash <this plan's planHash>${after === undefined ? "" : ` --approved-action ${after.actionId}`} --approved-action ${id}`,
192
+ ...(after === undefined ? {} : { afterStatus: after.status }),
193
+ droppedGrounding: drops,
194
+ summary: plan.summary,
195
+ changes: plan.changes.filter((change) => change.change !== "kept"),
196
+ contract: plan.contract,
197
+ contractHash: plan.contractHash,
198
+ ...(after === undefined
199
+ ? { alternativeTo: `semantic-inventory-review-${plan.requirementId}` }
200
+ : {}),
201
+ },
202
+ });
203
+ }
204
+ /** The grounding links an approved drop-grounding action lists. */
205
+ function plannedDrops(action) {
206
+ return plannedRecords(action.evidence.droppedGrounding).flatMap(({ type, target }) => typeof type === "string" && typeof target === "string"
207
+ ? [{ type, target }]
208
+ : []);
209
+ }
210
+ /**
211
+ * One action per requirement whose status is outside the vocabulary: a
212
+ * review (the target status is a semantic choice) carrying the suggested
213
+ * mapping and the inventory drift the requirement shows once mapped. With a
214
+ * suggestion it is executable when approved by id; the re-derivation of the
215
+ * latent drift depends on it.
216
+ */
217
+ // implements REQ-cli-schema-migration, REQ-kibi-proposition-complete-ingestion
218
+ export function requirementStatusActions(workspaceRoot) {
219
+ const actions = [];
220
+ for (const finding of planRequirementStatusMappings(workspaceRoot)) {
221
+ const id = `req-status-vocabulary-map-${finding.requirementId}`;
222
+ const drift = finding.latentDrift;
223
+ const target = finding.suggestedStatus;
224
+ actions.push(migrationAction({
225
+ id,
226
+ code: REQ_STATUS_VOCABULARY_MAP_CODE,
227
+ category: "schema",
228
+ safety: "review",
229
+ autoApplicable: false,
230
+ invocation: target === null
231
+ ? {
232
+ kind: "review",
233
+ instruction: `${finding.requirementId} (${finding.path}) has status ${finding.status}, which is not a requirement status, so it is skipped by the proof ladder and its semantic inventory is never validated. Set status to open, in_progress or closed (legacy: active, approved) in the file, or use proof_exempt to park it, then rerun kibi migrate.`,
234
+ }
235
+ : { kind: "cli", command_argv: approvalArgv([id]) },
236
+ affectedEntityIds: [finding.requirementId],
237
+ affectedFiles: [finding.path],
238
+ postconditions: [{ rule: "req-status-vocabulary", findings: 0 }],
239
+ dispositionRequired: true,
240
+ allowedDispositions: ["fixed", "deferred"],
241
+ evidence: {
242
+ reason: `Status ${finding.status} is ADR or lifecycle vocabulary, not a requirement status: the requirement is skipped by the proof ladder and kibi sync never validates its semantic inventory.`,
243
+ status: finding.status,
244
+ suggestedStatus: target,
245
+ ...(target === null
246
+ ? {}
247
+ : {
248
+ mapping: `${finding.status} -> ${target}`,
249
+ approve: `kibi migrate --apply-safe --approved-plan-hash <this plan's planHash> --approved-action ${id}`,
250
+ choice: "The target status is a semantic choice; to pick another one, set it in the file by hand instead of approving this action.",
251
+ }),
252
+ latentDrift: drift === null
253
+ ? null
254
+ : {
255
+ ingestionErrors: drift.errors,
256
+ safe: drift.safe,
257
+ reasons: drift.reasons,
258
+ summary: drift.summary,
259
+ contractHash: drift.contractHash,
260
+ orphanedGrounding: drift.orphanedGrounding,
261
+ ...(drift.safe
262
+ ? {
263
+ rederiveAction: `semantic-inventory-rederive-${finding.requirementId}`,
264
+ }
265
+ : drift.rederivableByDroppingGrounding
266
+ ? {
267
+ rederiveAction: `semantic-inventory-rederive-drop-grounding-${finding.requirementId}`,
268
+ }
269
+ : {
270
+ note: "After the mapping, kibi sync rejects this requirement until its inventory is fixed by hand; rerun kibi migrate for the semantic_inventory_review action.",
271
+ }),
272
+ },
273
+ },
274
+ }));
275
+ if (target === null || drift === null)
276
+ continue;
277
+ const after = { actionId: id, status: target };
278
+ if (drift.safe)
279
+ actions.push(rederiveAction(drift, after));
280
+ else if (drift.rederivableByDroppingGrounding)
281
+ actions.push(dropGroundingAction(drift, after));
282
+ }
283
+ return actions;
284
+ }
285
+ /** The status mapping an approved req_status_vocabulary_map action lists. */
286
+ function plannedStatusMapping(action) {
287
+ const path = action.affectedFiles[0];
288
+ const from = action.evidence.status;
289
+ const to = action.evidence.suggestedStatus;
290
+ if (path === undefined || typeof from !== "string" || typeof to !== "string")
291
+ throw new Error("Requirement status mapping names no file or target status; set the status by hand.");
292
+ return { path, from, to };
293
+ }
105
294
  /**
106
295
  * Exceptions without approved_by, read from authored sources so the list is
107
296
  * available before the KB compiles.
@@ -249,13 +438,50 @@ export function buildSchema6MigrationFragment(input) {
249
438
  }));
250
439
  }
251
440
  }
441
+ // Schema 9: acknowledge supersedes recorded before they had to explain
442
+ // themselves. Manifest only; no source changes and no reason is written.
443
+ if (input.currentSchemaVersion === null ||
444
+ input.currentSchemaVersion < DECISION_FIRMNESS_SCHEMA_VERSION) {
445
+ const unexplained = planSupersedesReasonAcknowledgement(input.workspaceRoot);
446
+ if (unexplained.length > 0) {
447
+ const id = "supersedes-reason-acknowledge";
448
+ // Not a source rewrite, but the schema upgrade and the store sync
449
+ // must wait for it like one: the bumped schema blocks without it.
450
+ sourceRewriteActionIds.push(id);
451
+ actions.push(migrationAction({
452
+ id,
453
+ code: SUPERSEDES_REASON_ACKNOWLEDGE_CODE,
454
+ category: "schema",
455
+ safety: "automatic",
456
+ autoApplicable: true,
457
+ invocation: {
458
+ kind: "cli",
459
+ command_argv: ["kibi", "migrate", "--yes"],
460
+ },
461
+ affectedEntityIds: unexplained.map((row) => row.id),
462
+ affectedFiles: [".kb/manifest.json"],
463
+ postconditions: [{ rule: "supersedes-reason-missing", findings: 0 }],
464
+ evidence: {
465
+ 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.",
466
+ count: unexplained.length,
467
+ byType: countByType(unexplained),
468
+ preserves: "every authored source file",
469
+ },
470
+ }));
471
+ }
472
+ }
252
473
  const drift = planInventoryRederivation(input.workspaceRoot);
253
474
  for (const plan of drift) {
254
475
  const action = plan.safe ? rederiveAction(plan) : reviewAction(plan);
255
476
  actions.push(action);
256
477
  if (plan.safe)
257
478
  sourceRewriteActionIds.push(action.id);
479
+ if (!plan.safe && plan.rederivableByDroppingGrounding)
480
+ actions.push(dropGroundingAction(plan));
258
481
  }
482
+ // Requirements with a status outside the vocabulary: mapping is a review,
483
+ // and their latent drift is re-derived only after an approved mapping.
484
+ actions.push(...requirementStatusActions(input.workspaceRoot));
259
485
  if (drift.some((plan) => !plan.safe)) {
260
486
  diagnostics.push(`${drift.filter((plan) => !plan.safe).length} requirement inventory(ies) need a manual fix before kibi sync succeeds; see the semantic_inventory_review actions.`);
261
487
  }
@@ -308,6 +534,13 @@ export function buildSchema6MigrationFragment(input) {
308
534
  const lifecycle = buildLifecycleRepairActions(input.workspaceRoot);
309
535
  actions.push(...lifecycle.actions);
310
536
  sourceRewriteActionIds.push(...lifecycle.sourceRewriteActionIds);
537
+ // Coarse symbol links the staged gate would block are marked at any schema
538
+ // version, by the gate's own rule.
539
+ const legacyLinks = symbolLegacyLinkAction(input.workspaceRoot);
540
+ if (legacyLinks !== null) {
541
+ actions.push(legacyLinks);
542
+ sourceRewriteActionIds.push(legacyLinks.id);
543
+ }
311
544
  return { actions, sourceRewriteActionIds, diagnostics };
312
545
  }
313
546
  /**
@@ -348,6 +581,33 @@ export function buildLifecycleRepairActions(workspaceRoot) {
348
581
  }
349
582
  return { actions, sourceRewriteActionIds };
350
583
  }
584
+ /**
585
+ * The automatic legacy-link pass over `.kb/symbols.yaml`, bound to the
586
+ * manifest bytes it was planned from; null when no link needs a mark.
587
+ */
588
+ // implements REQ-cli-schema-migration, REQ-symbol-behavioral-anchors
589
+ export function symbolLegacyLinkAction(workspaceRoot) {
590
+ const plan = planSymbolLegacyLinks(workspaceRoot);
591
+ if (plan.targets.length === 0)
592
+ return null;
593
+ return migrationAction({
594
+ id: SYMBOL_LEGACY_LINK_MARK_ACTION_ID,
595
+ code: SYMBOL_LEGACY_LINK_MARK_CODE,
596
+ category: "symbol",
597
+ safety: "automatic",
598
+ autoApplicable: true,
599
+ invocation: { kind: "cli", command_argv: ["kibi", "migrate", "--yes"] },
600
+ affectedEntityIds: plan.targets.map((target) => target.id),
601
+ affectedFiles: [plan.manifestPath],
602
+ postconditions: [{ rule: "symbol_granularity_violation", findings: 0 }],
603
+ evidence: {
604
+ reason: "These symbols link a source file coarsely while it declares narrower behavioral symbols, so the staged check (kibi check --staged) blocks the next commit that touches them. Each gets granularity_reason: legacy-link (accepted legacy granularity); no link moves and no other field changes.",
605
+ count: plan.targets.length,
606
+ manifestHash: plan.manifestHash,
607
+ symbols: plan.targets,
608
+ },
609
+ });
610
+ }
351
611
  /** The sync that recompiles sources rewritten by earlier actions. */
352
612
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
353
613
  export function migrationSyncAction(dependsOn) {
@@ -397,6 +657,10 @@ export async function applySchema6MigrationAction(action, context) {
397
657
  applyContextMissingTags(context.workspaceRoot);
398
658
  return;
399
659
  }
660
+ case SUPERSEDES_REASON_ACKNOWLEDGE_CODE: {
661
+ applySupersedesReasonAcknowledgement(context.workspaceRoot);
662
+ return;
663
+ }
400
664
  case SEMANTIC_INVENTORY_REDERIVE_CODE: {
401
665
  const requirementId = action.affectedEntityIds[0];
402
666
  if (requirementId === undefined)
@@ -407,9 +671,33 @@ export async function applySchema6MigrationAction(action, context) {
407
671
  applyInventoryRederivation(context.workspaceRoot, requirementId, contractHash);
408
672
  return;
409
673
  }
674
+ case REQ_STATUS_VOCABULARY_MAP_CODE: {
675
+ const mapping = plannedStatusMapping(action);
676
+ applyRequirementStatusMapping(context.workspaceRoot, mapping.path, mapping.from, mapping.to);
677
+ return;
678
+ }
679
+ case SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE: {
680
+ const requirementId = action.affectedEntityIds[0];
681
+ const contractHash = action.evidence.contractHash;
682
+ if (requirementId === undefined || typeof contractHash !== "string")
683
+ throw new Error("Inventory re-derivation names no requirement or contract hash.");
684
+ applyInventoryRederivationDroppingGrounding(context.workspaceRoot, requirementId, contractHash, plannedDrops(action));
685
+ return;
686
+ }
410
687
  case ENTITY_ORIGIN_BACKFILL_CODE:
411
688
  applyOriginBackfill(context.workspaceRoot, context.clock().toISOString());
412
689
  return;
690
+ case SYMBOL_LEGACY_LINK_MARK_CODE: {
691
+ const result = applySymbolLegacyLinks(context.workspaceRoot, {
692
+ ...(typeof action.evidence.manifestHash === "string"
693
+ ? { expectedHash: action.evidence.manifestHash }
694
+ : {}),
695
+ expectedIds: action.affectedEntityIds,
696
+ });
697
+ if (result.unmarked.length > 0)
698
+ throw new Error(`Could not mark ${result.unmarked.join(", ")} as legacy-link in place; add granularity_reason: legacy-link to them by hand.`);
699
+ return;
700
+ }
413
701
  case CLOSE_SUPERSEDED_REQUIREMENTS_CODE: {
414
702
  const result = applySupersededClosures(context.workspaceRoot, new Set(action.affectedEntityIds));
415
703
  if (result.skipped.length > 0)
@@ -435,14 +723,27 @@ export async function applySchema6MigrationAction(action, context) {
435
723
  throw new Error(`Migration action '${action.code}' has no schema 6 executor.`);
436
724
  }
437
725
  }
726
+ /**
727
+ * Review actions Kibi can execute, but only when a person approves them by
728
+ * id (`--approved-action`): `--apply-safe` selects automatic actions alone.
729
+ */
730
+ // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration, REQ-agent-guided-migration-orchestration
731
+ export const SCHEMA6_APPROVABLE_REVIEW_CODES = new Set([
732
+ SEMANTIC_INVENTORY_REDERIVE_DROP_GROUNDING_CODE,
733
+ REQ_STATUS_VOCABULARY_MAP_CODE,
734
+ // A re-derivation that waits on an approved status mapping.
735
+ SEMANTIC_INVENTORY_REDERIVE_CODE,
736
+ ]);
438
737
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
439
738
  export const SCHEMA6_AUTOMATIC_CODES = new Set([
440
739
  POLARITY_VALUE_BACKFILL_CODE,
441
740
  SEMANTIC_TEXT_PIN_CODE,
442
741
  CONTEXT_MISSING_TAG_CODE,
742
+ SUPERSEDES_REASON_ACKNOWLEDGE_CODE,
443
743
  SEMANTIC_INVENTORY_REDERIVE_CODE,
444
744
  ENTITY_ORIGIN_BACKFILL_CODE,
445
745
  CLOSE_SUPERSEDED_REQUIREMENTS_CODE,
446
746
  SOURCE_PATH_REWRITE_CODE,
747
+ SYMBOL_LEGACY_LINK_MARK_CODE,
447
748
  MIGRATION_SYNC_CODE,
448
749
  ]);
@@ -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"}