kibi-cli 2.21.2 → 2.22.1

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 (113) hide show
  1. package/dist/cli-register-foundation.d.ts.map +1 -1
  2. package/dist/cli-register-foundation.js +1 -0
  3. package/dist/commands/check.d.ts +0 -1
  4. package/dist/commands/check.d.ts.map +1 -1
  5. package/dist/commands/check.js +47 -111
  6. package/dist/commands/doctor.d.ts.map +1 -1
  7. package/dist/commands/doctor.js +108 -6
  8. package/dist/commands/init-helpers.d.ts +16 -2
  9. package/dist/commands/init-helpers.d.ts.map +1 -1
  10. package/dist/commands/init-helpers.js +52 -10
  11. package/dist/commands/init.d.ts +1 -0
  12. package/dist/commands/init.d.ts.map +1 -1
  13. package/dist/commands/init.js +12 -1
  14. package/dist/commands/legacy-storage-migration.d.ts +46 -1
  15. package/dist/commands/legacy-storage-migration.d.ts.map +1 -1
  16. package/dist/commands/legacy-storage-migration.js +219 -9
  17. package/dist/commands/migrate.d.ts +37 -0
  18. package/dist/commands/migrate.d.ts.map +1 -1
  19. package/dist/commands/migrate.js +72 -188
  20. package/dist/commands/sync/manifest.d.ts.map +1 -1
  21. package/dist/commands/sync/manifest.js +9 -0
  22. package/dist/extractors/symbols-coordinator.js +1 -0
  23. package/dist/intent-search.d.ts.map +1 -1
  24. package/dist/intent-search.js +28 -6
  25. package/dist/operations/migration/inventory-rederive.d.ts +40 -1
  26. package/dist/operations/migration/inventory-rederive.d.ts.map +1 -1
  27. package/dist/operations/migration/inventory-rederive.js +99 -8
  28. package/dist/operations/migration/requirement-status.d.ts +25 -0
  29. package/dist/operations/migration/requirement-status.d.ts.map +1 -0
  30. package/dist/operations/migration/requirement-status.js +105 -0
  31. package/dist/operations/migration/schema6.d.ts +25 -0
  32. package/dist/operations/migration/schema6.d.ts.map +1 -1
  33. package/dist/operations/migration/schema6.js +265 -7
  34. package/dist/operations/migration/symbol-legacy-links.d.ts +51 -0
  35. package/dist/operations/migration/symbol-legacy-links.d.ts.map +1 -0
  36. package/dist/operations/migration/symbol-legacy-links.js +319 -0
  37. package/dist/operations/mutation/context-warning.d.ts +12 -2
  38. package/dist/operations/mutation/context-warning.d.ts.map +1 -1
  39. package/dist/operations/mutation/context-warning.js +6 -6
  40. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  41. package/dist/operations/mutation/source-authoring.js +130 -35
  42. package/dist/operations/mutation/types.d.ts +2 -1
  43. package/dist/operations/mutation/types.d.ts.map +1 -1
  44. package/dist/operations/mutation/upsert.d.ts +17 -2
  45. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  46. package/dist/operations/mutation/upsert.js +28 -11
  47. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  48. package/dist/operations/mutation/validate-upsert.js +40 -8
  49. package/dist/operations/mutation/validation.d.ts.map +1 -1
  50. package/dist/operations/mutation/validation.js +43 -1
  51. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  52. package/dist/operations/planning/apply-plan.js +34 -10
  53. package/dist/operations/semantic-advisor/ingestion-boundary.d.ts.map +1 -1
  54. package/dist/operations/semantic-advisor/ingestion-boundary.js +25 -1
  55. package/dist/operations/semantic-advisor/stored-ledger-drift.d.ts +19 -0
  56. package/dist/operations/semantic-advisor/stored-ledger-drift.d.ts.map +1 -0
  57. package/dist/operations/semantic-advisor/stored-ledger-drift.js +78 -0
  58. package/dist/public/impact/diagnostics.d.ts.map +1 -1
  59. package/dist/public/impact/diagnostics.js +24 -14
  60. package/dist/public/operations/catalog.d.ts +3 -3
  61. package/dist/public/operations/check-executor.d.ts.map +1 -1
  62. package/dist/public/operations/check-executor.js +3 -0
  63. package/dist/public/operations/contracts.d.ts.map +1 -1
  64. package/dist/public/operations/contracts.js +6 -1
  65. package/dist/public/operations/decision-firmness.d.ts +3 -1
  66. package/dist/public/operations/decision-firmness.d.ts.map +1 -1
  67. package/dist/public/operations/decision-firmness.js +13 -3
  68. package/dist/public/operations/discovery-executors.d.ts +2 -0
  69. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  70. package/dist/public/operations/discovery-executors.js +24 -2
  71. package/dist/public/operations/migration-plan.d.ts +15 -0
  72. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  73. package/dist/public/operations/migration-plan.js +130 -17
  74. package/dist/public/operations/result-envelope.d.ts.map +1 -1
  75. package/dist/public/operations/result-envelope.js +27 -1
  76. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  77. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  78. package/dist/public/operations/specs/check-rules.generated.js +2 -1
  79. package/dist/public/operations/specs/check.d.ts +1 -1
  80. package/dist/public/operations/specs/planning.d.ts +2 -2
  81. package/dist/public/operations/specs/planning.js +2 -2
  82. package/dist/public/operations/specs/semantic.d.ts.map +1 -1
  83. package/dist/public/operations/specs/semantic.js +26 -1
  84. package/dist/public/operations/symbol-granularity-check.d.ts +18 -0
  85. package/dist/public/operations/symbol-granularity-check.d.ts.map +1 -0
  86. package/dist/public/operations/symbol-granularity-check.js +175 -0
  87. package/dist/public/skills/kibi-usage/SKILL.md +8 -3
  88. package/dist/public/symbol-granularity.d.ts +17 -0
  89. package/dist/public/symbol-granularity.d.ts.map +1 -1
  90. package/dist/public/symbol-granularity.js +21 -0
  91. package/dist/traceability/evidence-model.d.ts +7 -3
  92. package/dist/traceability/evidence-model.d.ts.map +1 -1
  93. package/dist/traceability/staged-symbols-manifest.js +6 -5
  94. package/dist/traceability/validate.d.ts +14 -1
  95. package/dist/traceability/validate.d.ts.map +1 -1
  96. package/dist/traceability/validate.js +41 -0
  97. package/dist/utils/rule-registry.generated.d.ts +5 -0
  98. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  99. package/dist/utils/rule-registry.generated.js +6 -0
  100. package/package.json +3 -3
  101. package/src/public/impact/diagnostics.ts +29 -17
  102. package/src/public/operations/check-executor.ts +7 -0
  103. package/src/public/operations/contracts.ts +6 -1
  104. package/src/public/operations/decision-firmness.ts +18 -2
  105. package/src/public/operations/discovery-executors.ts +28 -2
  106. package/src/public/operations/migration-plan.ts +147 -20
  107. package/src/public/operations/result-envelope.ts +34 -1
  108. package/src/public/operations/specs/check-rules.generated.ts +2 -1
  109. package/src/public/operations/specs/planning.ts +2 -2
  110. package/src/public/operations/specs/semantic.ts +37 -2
  111. package/src/public/operations/symbol-granularity-check.ts +233 -0
  112. package/src/public/skills/kibi-usage/SKILL.md +8 -3
  113. package/src/public/symbol-granularity.ts +37 -0
@@ -21,13 +21,15 @@ 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";
30
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";
31
33
  /** The KB schema generation that introduced entity `origin`. */
32
34
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
33
35
  export const ORIGIN_SCHEMA_VERSION = 6;
@@ -43,6 +45,15 @@ export const SEMANTIC_INVENTORY_REDERIVE_CODE = "semantic_inventory_rederive";
43
45
  /** Review: a drifted inventory Kibi cannot re-derive safely. */
44
46
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
45
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";
46
57
  /** Automatic: stamp `origin: {kind: migration}` on authored entities. */
47
58
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
48
59
  export const ENTITY_ORIGIN_BACKFILL_CODE = "entity_origin_backfill";
@@ -56,15 +67,33 @@ const CURRENT_REQUIREMENT_STATUSES = new Set([
56
67
  "active",
57
68
  "approved",
58
69
  ]);
59
- function rederiveAction(plan) {
70
+ function rederiveAction(plan, after) {
60
71
  const changed = plan.changes.filter((change) => change.change !== "kept");
72
+ const id = `semantic-inventory-rederive-${plan.requirementId}`;
61
73
  return migrationAction({
62
- id: `semantic-inventory-rederive-${plan.requirementId}`,
74
+ id,
63
75
  code: SEMANTIC_INVENTORY_REDERIVE_CODE,
64
76
  category: "semantic",
65
- safety: "automatic",
66
- autoApplicable: true,
67
- 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
+ }),
68
97
  affectedEntityIds: [plan.requirementId],
69
98
  affectedFiles: [plan.path],
70
99
  postconditions: [
@@ -81,9 +110,23 @@ function rederiveAction(plan) {
81
110
  changes: changed,
82
111
  contractHash: plan.contractHash,
83
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
+ }),
84
119
  },
85
120
  });
86
121
  }
122
+ function approvalArgv(ids) {
123
+ return [
124
+ "kibi",
125
+ "migrate",
126
+ "--apply-safe",
127
+ ...ids.flatMap((id) => ["--approved-action", id]),
128
+ ];
129
+ }
87
130
  function reviewAction(plan) {
88
131
  return migrationAction({
89
132
  id: `semantic-inventory-review-${plan.requirementId}`,
@@ -92,7 +135,7 @@ function reviewAction(plan) {
92
135
  safety: "review",
93
136
  invocation: {
94
137
  kind: "review",
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>}.`,
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>}.`,
96
139
  },
97
140
  affectedEntityIds: [plan.requirementId],
98
141
  affectedFiles: [plan.path],
@@ -108,6 +151,146 @@ function reviewAction(plan) {
108
151
  },
109
152
  });
110
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
+ }
111
294
  /**
112
295
  * Exceptions without approved_by, read from authored sources so the list is
113
296
  * available before the KB compiles.
@@ -293,7 +476,12 @@ export function buildSchema6MigrationFragment(input) {
293
476
  actions.push(action);
294
477
  if (plan.safe)
295
478
  sourceRewriteActionIds.push(action.id);
479
+ if (!plan.safe && plan.rederivableByDroppingGrounding)
480
+ actions.push(dropGroundingAction(plan));
296
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));
297
485
  if (drift.some((plan) => !plan.safe)) {
298
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.`);
299
487
  }
@@ -346,6 +534,13 @@ export function buildSchema6MigrationFragment(input) {
346
534
  const lifecycle = buildLifecycleRepairActions(input.workspaceRoot);
347
535
  actions.push(...lifecycle.actions);
348
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
+ }
349
544
  return { actions, sourceRewriteActionIds, diagnostics };
350
545
  }
351
546
  /**
@@ -386,6 +581,33 @@ export function buildLifecycleRepairActions(workspaceRoot) {
386
581
  }
387
582
  return { actions, sourceRewriteActionIds };
388
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
+ }
389
611
  /** The sync that recompiles sources rewritten by earlier actions. */
390
612
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
391
613
  export function migrationSyncAction(dependsOn) {
@@ -449,9 +671,33 @@ export async function applySchema6MigrationAction(action, context) {
449
671
  applyInventoryRederivation(context.workspaceRoot, requirementId, contractHash);
450
672
  return;
451
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
+ }
452
687
  case ENTITY_ORIGIN_BACKFILL_CODE:
453
688
  applyOriginBackfill(context.workspaceRoot, context.clock().toISOString());
454
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
+ }
455
701
  case CLOSE_SUPERSEDED_REQUIREMENTS_CODE: {
456
702
  const result = applySupersededClosures(context.workspaceRoot, new Set(action.affectedEntityIds));
457
703
  if (result.skipped.length > 0)
@@ -477,6 +723,17 @@ export async function applySchema6MigrationAction(action, context) {
477
723
  throw new Error(`Migration action '${action.code}' has no schema 6 executor.`);
478
724
  }
479
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
+ ]);
480
737
  // implements REQ-kibi-schema6-migration, REQ-cli-schema-migration
481
738
  export const SCHEMA6_AUTOMATIC_CODES = new Set([
482
739
  POLARITY_VALUE_BACKFILL_CODE,
@@ -487,5 +744,6 @@ export const SCHEMA6_AUTOMATIC_CODES = new Set([
487
744
  ENTITY_ORIGIN_BACKFILL_CODE,
488
745
  CLOSE_SUPERSEDED_REQUIREMENTS_CODE,
489
746
  SOURCE_PATH_REWRITE_CODE,
747
+ SYMBOL_LEGACY_LINK_MARK_CODE,
490
748
  MIGRATION_SYNC_CODE,
491
749
  ]);
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Mark the coarse traceability links of a symbols manifest
3
+ * `granularity_reason: legacy-link`.
4
+ *
5
+ * A link is coarse by the staged granularity gate's own rule
6
+ * (`coarseLinkBehavioralNames`): the source declares behavioral symbols
7
+ * narrower than the manifest symbol, so `kibi check --staged` would block the
8
+ * first commit that touches it. The pass is idempotent and independent of
9
+ * the schema version: it marks whatever the current rule calls coarse and
10
+ * has no reason yet, and a second run finds nothing.
11
+ */
12
+ /** Automatic migration action code of the legacy-link pass. */
13
+ export declare const SYMBOL_LEGACY_LINK_MARK_CODE = "symbol_legacy_link_mark";
14
+ export declare const SYMBOL_LEGACY_LINK_MARK_ACTION_ID = "symbol-legacy-link-mark";
15
+ /** One coarse link the pass marks. */
16
+ export type LegacyLinkTarget = Readonly<{
17
+ id: string;
18
+ title: string;
19
+ sourceFile: string;
20
+ /** The narrower behavioral symbols that make the link coarse. */
21
+ granularSymbols: readonly string[];
22
+ }>;
23
+ export type LegacyLinkPlan = Readonly<{
24
+ /** Workspace-relative manifest path. */
25
+ manifestPath: string;
26
+ /** SHA-256 of the manifest bytes the plan was read from; null when absent. */
27
+ manifestHash: string | null;
28
+ targets: readonly LegacyLinkTarget[];
29
+ }>;
30
+ /**
31
+ * The coarse links of `manifestPath` (default `.kb/symbols.yaml`) that carry
32
+ * no granularity_reason yet. Read-only.
33
+ */
34
+ export declare function planSymbolLegacyLinks(workspaceRoot: string, manifestPath?: string): LegacyLinkPlan;
35
+ /**
36
+ * Mark the coarse links found by `planSymbolLegacyLinks`. With
37
+ * `expectedHash` (a migration plan's evidence), the manifest must still hold
38
+ * the bytes the plan was read from; a manifest whose planned links are all
39
+ * marked already is left alone, so the pass is idempotent. Returns the ids
40
+ * marked, and the planned ones that could not be marked in place (an entry
41
+ * whose `id` is not its first key, for example).
42
+ */
43
+ export declare function applySymbolLegacyLinks(workspaceRoot: string, options?: {
44
+ manifestPath?: string;
45
+ expectedHash?: string;
46
+ expectedIds?: readonly string[];
47
+ }): {
48
+ marked: string[];
49
+ unmarked: string[];
50
+ };
51
+ //# sourceMappingURL=symbol-legacy-links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbol-legacy-links.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/symbol-legacy-links.ts"],"names":[],"mappings":"AAmCA;;;;;;;;;;GAUG;AAEH,+DAA+D;AAE/D,eAAO,MAAM,4BAA4B,4BAA4B,CAAC;AAEtE,eAAO,MAAM,iCAAiC,4BAA4B,CAAC;AAE3E,sCAAsC;AAEtC,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC,CAAC;AAGH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,wCAAwC;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACtC,CAAC,CAAC;AAkHH;;;GAGG;AAEH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,MAAM,EACrB,YAAY,GAAE,MAAiC,GAC9C,cAAc,CAwDhB;AAoED;;;;;;;GAOG;AAEH,wBAAgB,sBAAsB,CACpC,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,GACL;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAoC1C"}