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
@@ -3,7 +3,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { InputError, OperationError } from "../../cli-errors.js";
5
5
  import { parseEntityFromList, parseListOfLists, toPrologAtom, } from "../../prolog/codec.js";
6
- import { listShards, readAllShards, readShard, removeRelationshipsFromShards, renderShardWithout, } from "../../relationships/shards.js";
6
+ import { listShards, planRelationshipShardRemovals, readAllShards, readShard, removeRelationshipsFromShards, renderShardWithout, } from "../../relationships/shards.js";
7
7
  import { resolveBranchAttachment } from "../../utils/branch-resolver.js";
8
8
  import { buildEntityDeleteAuditGoal } from "./audit.js";
9
9
  import { planRecoveryNotes, settlePendingPlanApplyJournals, withPlanRecoveryNotes, } from "./plan-apply-journal.js";
@@ -48,9 +48,74 @@ function fileHash(pathname) {
48
48
  return null;
49
49
  return createHash("sha256").update(readFileSync(pathname)).digest("hex");
50
50
  }
51
+ /** Effects a dry run or plan-only result leaves to a later call. */
52
+ const PLAN_ONLY_SKIPPED_EFFECTS = ["kb-write", "workspace-write"];
53
+ const DRY_RUN_FIELDS = {
54
+ dryRun: true,
55
+ outcome: "dry_run",
56
+ skippedEffects: PLAN_ONLY_SKIPPED_EFFECTS,
57
+ };
58
+ function sha256(text) {
59
+ return createHash("sha256").update(text).digest("hex");
60
+ }
61
+ // implements REQ-011
62
+ /**
63
+ * The relationship delete a preflight-clean call would perform: the shard and
64
+ * authored-source writes with their hashes and the compiled edges it would
65
+ * retract. Nothing is written and the compiled store is not touched.
66
+ */
67
+ function relationshipDeleteDryRun(shardRoot, preflight, liveByKey, sourcePatches, workspaceRoot) {
68
+ const planned = planRelationshipShardRemovals(shardRoot, preflight);
69
+ const sourceWrites = [];
70
+ for (const [shardPath, body] of planned.bodies) {
71
+ const before = readFileSync(shardPath, "utf8");
72
+ if (before === body)
73
+ continue;
74
+ sourceWrites.push({
75
+ path: path.relative(workspaceRoot, shardPath).replaceAll("\\", "/"),
76
+ mode: "write",
77
+ beforeHash: sha256(before),
78
+ afterHash: sha256(body),
79
+ created: false,
80
+ });
81
+ }
82
+ for (const [relative, patch] of sourcePatches) {
83
+ sourceWrites.push({
84
+ path: relative,
85
+ mode: "write",
86
+ beforeHash: sha256(patch.before),
87
+ afterHash: sha256(patch.after),
88
+ created: false,
89
+ });
90
+ }
91
+ const compiledEdges = preflight.filter((selector) => liveByKey.get(`${selector.type}\0${selector.from}\0${selector.to}`) ===
92
+ true).length;
93
+ return {
94
+ deleted: 0,
95
+ relationships_deleted: 0,
96
+ skipped: 0,
97
+ errors: [],
98
+ error_codes: [],
99
+ relationship_results: preflight.map((selector, index) => ({
100
+ ...selector,
101
+ deleted: false,
102
+ shard_records_removed: planned.removals[index]?.removed ?? false,
103
+ compiled_edge_retracted: liveByKey.get(`${selector.type}\0${selector.from}\0${selector.to}`) ===
104
+ true,
105
+ })),
106
+ wouldDelete: {
107
+ entities: 0,
108
+ relationships: preflight.length,
109
+ compiledEdges,
110
+ },
111
+ sync_required: planned.bodies.size > 0 || sourcePatches.size > 0,
112
+ sourceWrites,
113
+ ...DRY_RUN_FIELDS,
114
+ };
115
+ }
51
116
  // implements REQ-011
52
117
  // covered_by TEST-cli-source-relationship-parity-unit
53
- async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted = () => undefined) {
118
+ async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted = () => undefined, options = {}) {
54
119
  const prolog = requireProlog(context);
55
120
  const allowed = new Set(RELATIONSHIP_TYPES);
56
121
  const errors = [];
@@ -164,7 +229,11 @@ async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted
164
229
  errors,
165
230
  error_codes: errorCodes,
166
231
  relationship_results: [],
232
+ ...(options.dryRun === true ? DRY_RUN_FIELDS : {}),
167
233
  };
234
+ if (options.dryRun === true) {
235
+ return relationshipDeleteDryRun(shardRoot, preflight, liveByKey, sourcePatches, context.workspaceRoot);
236
+ }
168
237
  // Keep byte-level before-images for rollback. Re-serializing parsed records
169
238
  // would silently discard comments, ordering, and CST trivia from unrelated
170
239
  // shard records after a later compiled-store failure.
@@ -314,9 +383,9 @@ async function executeRelationshipDeleteUnlocked(selectors, context, onCommitted
314
383
  ...(sourceWrites.length > 0 ? { sourceWrites } : {}),
315
384
  };
316
385
  }
317
- export async function executeRelationshipDelete(selectors, context, onCommitted = () => undefined) {
386
+ export async function executeRelationshipDelete(selectors, context, onCommitted = () => undefined, options = {}) {
318
387
  if (!context.fs || context.sourceMutationLockHeld === true)
319
- return executeRelationshipDeleteUnlocked(selectors, context, onCommitted);
388
+ return executeRelationshipDeleteUnlocked(selectors, context, onCommitted, options);
320
389
  const lock = await acquireWorkspaceMutationLock(context.workspaceRoot);
321
390
  let operationFailure;
322
391
  let committed = false;
@@ -324,8 +393,8 @@ export async function executeRelationshipDelete(selectors, context, onCommitted
324
393
  const result = await executeRelationshipDeleteUnlocked(selectors, context, () => {
325
394
  committed = true;
326
395
  onCommitted();
327
- });
328
- committed = true;
396
+ }, options);
397
+ committed = options.dryRun !== true;
329
398
  return result;
330
399
  }
331
400
  catch (error) {
@@ -337,6 +406,91 @@ export async function executeRelationshipDelete(selectors, context, onCommitted
337
406
  releaseWorkspaceMutationLock(lock, operationFailure, committed);
338
407
  }
339
408
  }
409
+ // implements REQ-kibi-operation-interface-parity
410
+ /** The kb_apply_plan call that applies a returned deletion plan unmodified. */
411
+ function applyDeletionPlanNextAction(plan) {
412
+ return {
413
+ operation: "kb_apply_plan",
414
+ input: { plan, approvedPlanHash: plan.planHash },
415
+ reason: `Review deletionPlan, then apply it unmodified to delete ${plan.entityIds.join(", ")} (or call kb_delete again with the same ids and approvedPlanHash).`,
416
+ required: true,
417
+ };
418
+ }
419
+ // implements REQ-kibi-operation-interface-parity
420
+ /** Requirements evolve append-only: point at the supersession upsert. */
421
+ function supersessionNextAction(requirementIds) {
422
+ return {
423
+ operation: "kb_upsert",
424
+ input: {
425
+ type: "req",
426
+ id: "<REQ-replacement-id>",
427
+ relationships: requirementIds.map((id) => ({
428
+ type: "supersedes",
429
+ from: "<REQ-replacement-id>",
430
+ to: id,
431
+ })),
432
+ },
433
+ reason: `Authored requirements are not deleted. Upsert a replacement requirement linked with supersedes to ${requirementIds.join(", ")}, then upsert each superseded requirement with status closed.`,
434
+ required: true,
435
+ };
436
+ }
437
+ // implements REQ-kibi-operation-interface-parity
438
+ /**
439
+ * Apply a freshly computed authored-entity deletion plan in the same call
440
+ * when the caller approved its hash. The plan goes through kb_apply_plan's
441
+ * own validation, journal and recovery path; a stale or different approval
442
+ * fails before anything is written.
443
+ */
444
+ async function applyApprovedDeletionPlan(plan, approvedPlanHash, planErrors, context, onCommitted, reported) {
445
+ if (approvedPlanHash.toLowerCase() !== plan.planHash) {
446
+ throw new InputError("DELETE_PLAN_HASH_MISMATCH", `kb_delete: approvedPlanHash ${approvedPlanHash.slice(0, 12)} does not match the current deletion plan ${plan.planHash.slice(0, 12)} for ${plan.entityIds.join(", ")}. The ids or their sources changed since that plan was returned. Call kb_delete without approvedPlanHash, review the new plan, and approve its planHash. Nothing was written.`);
447
+ }
448
+ if (plan.supersessionRequired) {
449
+ throw new InputError("REQUIREMENT_SUPERSESSION_REQUIRED", "kb_delete: authored requirements evolve through a new requirement linked with supersedes; a deletion plan that requires supersession cannot be approved. Nothing was written.");
450
+ }
451
+ if (planErrors.length > 0) {
452
+ throw new InputError("VALIDATION_FAILED", `kb_delete: approvedPlanHash applies a plan only when every requested id is in it. Remove or fix: ${planErrors.join("; ")} Nothing was written.`);
453
+ }
454
+ // apply-plan imports this module; load it lazily to keep the cycle out of
455
+ // module initialization.
456
+ const { executeApplyPlan } = await import("../planning/apply-plan.js");
457
+ const applied = await executeApplyPlan({ plan, approvedPlanHash: plan.planHash },
458
+ // executeDelete already holds the workspace lock (or runs without fs).
459
+ { ...context, sourceMutationLockHeld: true }, onCommitted);
460
+ const result = applied.structuredContent;
461
+ const deleted = typeof result.deleted === "number" ? result.deleted : 0;
462
+ const repairs = result.status === "committed_with_repairs";
463
+ const payload = {
464
+ deleted,
465
+ skipped: plan.entityIds.length - deleted,
466
+ errors: [],
467
+ outcome: "plan_applied",
468
+ planHash: plan.planHash,
469
+ sourcePaths: Array.isArray(result.sourcePaths)
470
+ ? result.sourcePaths
471
+ : [],
472
+ ...(typeof result.recoveryJournalId === "string"
473
+ ? { recoveryJournalId: result.recoveryJournalId }
474
+ : {}),
475
+ ...(repairs
476
+ ? {
477
+ status: "committed_with_repairs",
478
+ nextActions: Array.isArray(result.nextActions)
479
+ ? result.nextActions
480
+ : [],
481
+ }
482
+ : {}),
483
+ };
484
+ return {
485
+ content: [
486
+ {
487
+ type: "text",
488
+ text: reported(`Applied deletion plan ${plan.planHash.slice(0, 12)}: deleted ${deleted} entities.${repairs ? " Compiled retraction needs repair; follow nextActions." : ""}`),
489
+ },
490
+ ],
491
+ structuredContent: payload,
492
+ };
493
+ }
340
494
  export async function executeDelete(input, context) {
341
495
  const branchAttachment = context.branchAttachment ?? resolveBranchAttachment(context.workspaceRoot);
342
496
  if ("error" in branchAttachment) {
@@ -362,19 +516,29 @@ export async function executeDelete(input, context) {
362
516
  }
363
517
  const ids = input.ids ?? [];
364
518
  const relationships = input.relationships ?? [];
519
+ const dryRun = input.dryRun === true;
520
+ const approvedPlanHash = input.approvedPlanHash;
365
521
  if ((ids.length === 0) === (relationships.length === 0))
366
522
  throw new Error("Delete requires exactly one non-empty input: ids or relationships");
523
+ if (approvedPlanHash !== undefined) {
524
+ if (dryRun)
525
+ throw new InputError("VALIDATION_FAILED", "kb_delete: dryRun and approvedPlanHash cannot be combined. Omit approvedPlanHash to preview the deletion plan, or omit dryRun to apply it.");
526
+ if (relationships.length > 0)
527
+ throw new InputError("VALIDATION_FAILED", "kb_delete: approvedPlanHash applies only to an authored-entity deletion plan (ids). Relationship deletes apply directly; use dryRun:true to preview them.");
528
+ }
367
529
  if (relationships.length > 0) {
368
530
  if (relationships.some((value) => !isSelector(value)))
369
531
  throw new Error("Each relationship selector requires non-empty type, from, and to strings");
370
532
  const payload = await executeRelationshipDelete(relationships, { ...context, sourceMutationLockHeld: true }, () => {
371
533
  committed = true;
372
- });
534
+ }, { dryRun });
373
535
  return {
374
536
  content: [
375
537
  {
376
538
  type: "text",
377
- text: reported(`Deleted ${payload.relationships_deleted ?? 0} relationships. Skipped ${payload.skipped}.${payload.sync_required ? " Run kibi sync to reconcile the relationship shard." : ""}`),
539
+ text: reported(dryRun
540
+ ? `Dry run: would delete ${payload.wouldDelete?.relationships ?? 0} relationships. Skipped ${payload.skipped}. Nothing was written.`
541
+ : `Deleted ${payload.relationships_deleted ?? 0} relationships. Skipped ${payload.skipped}.${payload.sync_required ? " Run kibi sync to reconcile the relationship shard." : ""}`),
378
542
  },
379
543
  ],
380
544
  structuredContent: payload,
@@ -383,6 +547,8 @@ export async function executeDelete(input, context) {
383
547
  const errors = [];
384
548
  const goals = [];
385
549
  const authoredIds = [];
550
+ // Resolved ids that a direct delete would retract (non-authored source).
551
+ const directIds = [];
386
552
  const authoredRequirementIds = [];
387
553
  const sourceHashes = {};
388
554
  // Keep the original body for rollback, while applying each deletion to the
@@ -451,6 +617,8 @@ export async function executeDelete(input, context) {
451
617
  }
452
618
  }
453
619
  }
620
+ if (!sourceIsAuthored(source))
621
+ directIds.push(id);
454
622
  goals.push(buildEntityDeleteAuditGoal(entity));
455
623
  }
456
624
  if (authoredIds.length > 0 && context.sourcePlanApplication !== true) {
@@ -496,23 +664,61 @@ export async function executeDelete(input, context) {
496
664
  const planHash = createHash("sha256")
497
665
  .update(JSON.stringify(planBody))
498
666
  .digest("hex");
667
+ const deletionPlan = { ...planBody, planHash };
668
+ // A plan covers only authored ids; any other resolved id in the same
669
+ // call is left for a separate direct delete.
670
+ const planErrors = [
671
+ ...errors,
672
+ ...directIds.map((id) => `Entity ${id} was not deleted: this call returned an authored-entity deletion plan. Delete ${id} in a separate kb_delete call.`),
673
+ ];
674
+ if (approvedPlanHash !== undefined) {
675
+ return await applyApprovedDeletionPlan(deletionPlan, approvedPlanHash, planErrors, { ...context, branchAttachment, prolog }, () => {
676
+ committed = true;
677
+ }, reported);
678
+ }
499
679
  const payload = {
500
680
  deleted: 0,
501
- skipped: authoredIds.length,
502
- errors: [
503
- supersessionRequired
504
- ? "Authored requirements require an explicit supersession plan; no direct delete is performed."
505
- : "Authored entity deletion returns a hash-bound plan for kb_apply_plan.",
506
- ],
507
- deletionPlan: { ...planBody, planHash },
681
+ skipped: authoredIds.length + planErrors.length,
682
+ errors: planErrors,
683
+ outcome: supersessionRequired
684
+ ? "supersession_required"
685
+ : "plan_returned",
686
+ deletionPlan,
687
+ nextActions: supersessionRequired
688
+ ? [supersessionNextAction(authoredRequirementIds)]
689
+ : [applyDeletionPlanNextAction(deletionPlan)],
508
690
  // Only kb_apply_plan writes; this call returns the plan.
509
- skippedEffects: ["kb-write", "workspace-write"],
691
+ skippedEffects: PLAN_ONLY_SKIPPED_EFFECTS,
692
+ ...(dryRun ? { dryRun: true } : {}),
693
+ };
694
+ return {
695
+ content: [
696
+ {
697
+ type: "text",
698
+ text: reported(supersessionRequired
699
+ ? `Authored requirements ${authoredRequirementIds.join(", ")} cannot be deleted: supersede them with kb_upsert (supersedes) and close them instead. Nothing was written.`
700
+ : `Returned deletion plan ${planHash.slice(0, 12)} for ${authoredIds.join(", ")}. Nothing was written; apply it with kb_apply_plan (nextActions[0].input), or call kb_delete again with approvedPlanHash.`),
701
+ },
702
+ ],
703
+ structuredContent: payload,
704
+ };
705
+ }
706
+ if (approvedPlanHash !== undefined &&
707
+ context.sourcePlanApplication !== true)
708
+ throw new InputError("VALIDATION_FAILED", `kb_delete: approvedPlanHash was given but ${ids.join(", ")} produced no authored-entity deletion plan to approve. Omit approvedPlanHash to delete these ids directly.`);
709
+ if (dryRun) {
710
+ const payload = {
711
+ deleted: 0,
712
+ skipped: errors.length,
713
+ errors,
714
+ wouldDelete: { entities: goals.length, ids: directIds },
715
+ ...DRY_RUN_FIELDS,
510
716
  };
511
717
  return {
512
718
  content: [
513
719
  {
514
720
  type: "text",
515
- text: reported(`Deletion plan ${planHash.slice(0, 12)} must be applied through kb_apply_plan.`),
721
+ text: reported(`Dry run: would delete ${goals.length} entities. Skipped ${errors.length}. Nothing was written.${errors.length > 0 ? ` Errors: ${errors.join("; ")}` : ""}`),
516
722
  },
517
723
  ],
518
724
  structuredContent: payload,
@@ -1 +1 @@
1
- {"version":3,"file":"serialization.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/serialization.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAwDpD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,MAAM,CAMR;AAGD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAOxE;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBtD"}
1
+ {"version":3,"file":"serialization.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/serialization.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAyDpD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,MAAM,CAMR;AAGD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAOxE;AAGD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBtD"}
@@ -13,6 +13,7 @@ const ATOM_FIELDS = [
13
13
  "value_type",
14
14
  "polarity",
15
15
  "expects",
16
+ "firmness",
16
17
  ];
17
18
  const STRING_FIELDS = [
18
19
  "id",
@@ -1 +1 @@
1
- {"version":3,"file":"source-authoring.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/source-authoring.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"source-authoring.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/source-authoring.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@ import fs from "node:fs";
5
5
  import path from "node:path";
6
6
  import { isDeepStrictEqual } from "node:util";
7
7
  import { dump as dumpYaml, load as loadYaml } from "js-yaml";
8
- import { parseDocument, stringify } from "yaml";
8
+ import { isCollection, isMap, isNode, isScalar, parseDocument, stringify, } from "yaml";
9
9
  import { OperationError } from "../../cli-errors.js";
10
10
  import { requirementSemanticText } from "../../extractors/markdown.js";
11
11
  import { canonicalFilesystemPath } from "../../utils/canonical-path.js";
@@ -169,22 +169,32 @@ export function normalizeAuthoredSourcePath(workspaceRoot, source) {
169
169
  .relative(path.resolve(workspaceRoot), resolveContainedSourcePath(workspaceRoot, relative))
170
170
  .replaceAll(path.sep, "/");
171
171
  }
172
- function bodyAndFrontmatter(content) {
172
+ /** The raw front matter block of a Markdown document, split at its fences. */
173
+ function frontmatterBlock(content) {
173
174
  if (!content.startsWith("---"))
174
- return { frontmatter: {}, body: content };
175
+ return undefined;
175
176
  const firstEnd = content.indexOf("\n", 3);
176
177
  if (firstEnd < 0)
177
- return { frontmatter: {}, body: content };
178
+ return undefined;
178
179
  const marker = content.indexOf("\n---", firstEnd);
179
180
  if (marker < 0)
181
+ return undefined;
182
+ return {
183
+ opening: content.slice(0, firstEnd + 1),
184
+ raw: content.slice(firstEnd + 1, marker),
185
+ body: content.slice(marker + "\n---".length),
186
+ };
187
+ }
188
+ function bodyAndFrontmatter(content) {
189
+ const block = frontmatterBlock(content);
190
+ if (block === undefined)
180
191
  return { frontmatter: {}, body: content };
181
- const raw = content.slice(firstEnd + 1, marker);
182
- const parsed = loadYaml(raw);
192
+ const parsed = loadYaml(block.raw);
183
193
  return {
184
194
  frontmatter: parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)
185
195
  ? parsed
186
196
  : {},
187
- body: content.slice(marker + "\n---".length),
197
+ body: block.body,
188
198
  };
189
199
  }
190
200
  /**
@@ -238,6 +248,105 @@ function sourcePath(context, input, entity, existing) {
238
248
  }
239
249
  return resolveContainedSourcePath(context.workspaceRoot, relative);
240
250
  }
251
+ /**
252
+ * Front matter keys an upsert never writes: runtime provenance/timestamps
253
+ * belong to the compiled entity, not to the authored source artifact, and
254
+ * relationships live in `links`/shards. Keeping them out also makes the
255
+ * source diff deterministic across CLI and MCP transports.
256
+ */
257
+ const UNAUTHORED_FRONTMATTER_KEYS = new Set([
258
+ "id",
259
+ "type",
260
+ "source",
261
+ "links",
262
+ "relationships",
263
+ "created_at",
264
+ "updated_at",
265
+ ]);
266
+ /** The front matter values an upsert of `entity` sets, in write order. */
267
+ function entityFrontmatterUpdates(entity, existing, body) {
268
+ const updates = Object.fromEntries(Object.entries(entity).filter(([key, value]) => value !== undefined && !UNAUTHORED_FRONTMATTER_KEYS.has(key)));
269
+ updates.id = entity.id;
270
+ if (updates.title === undefined && existing.title === undefined) {
271
+ updates.title = entity.id;
272
+ }
273
+ updates.type = entity.type;
274
+ // The checked meaning is always stated, never derived from a body that now
275
+ // also carries context sections.
276
+ const semanticText = updates.semantic_text ?? existing.semantic_text;
277
+ if (entity.type === "req" &&
278
+ (typeof semanticText !== "string" || semanticText.trim() === "")) {
279
+ const derived = requirementSemanticText(body);
280
+ if (derived !== "")
281
+ updates.semantic_text = derived;
282
+ }
283
+ return updates;
284
+ }
285
+ /**
286
+ * Apply `updates` to an existing front matter block without re-serializing
287
+ * it: only keys whose value actually changes are rewritten (or appended), so
288
+ * every untouched key keeps its authored bytes (quoting, timestamps, flow
289
+ * lists, indentation, comments). Returns undefined when the block is not a
290
+ * plain block mapping that can be patched in place.
291
+ */
292
+ // implements REQ-core-persistence
293
+ function patchFrontmatter(raw, loaded, updates) {
294
+ const doc = parseDocument(raw);
295
+ if (doc.errors.length > 0)
296
+ return undefined;
297
+ const contents = doc.contents;
298
+ if (contents === null && raw.trim() !== "")
299
+ return undefined;
300
+ if (contents !== null && (!isMap(contents) || contents.flow)) {
301
+ return undefined;
302
+ }
303
+ const pairs = contents === null ? [] : contents.items;
304
+ const current = (doc.toJS() ?? {});
305
+ const edits = [];
306
+ const appended = [];
307
+ for (const [key, value] of Object.entries(updates)) {
308
+ const pair = pairs.find((candidate) => isScalar(candidate.key) && String(candidate.key.value) === key);
309
+ if (pair !== undefined &&
310
+ (isDeepStrictEqual(current[key], value) ||
311
+ isDeepStrictEqual(loaded[key], value))) {
312
+ continue;
313
+ }
314
+ const valueNode = pair?.value;
315
+ const flow = isCollection(valueNode) && valueNode.flow === true;
316
+ const text = dumpYaml({ [key]: value }, {
317
+ noRefs: true,
318
+ lineWidth: -1,
319
+ sortKeys: false,
320
+ ...(flow ? { flowLevel: 1 } : {}),
321
+ }).replace(/\n$/, "");
322
+ if (pair === undefined) {
323
+ appended.push(text);
324
+ continue;
325
+ }
326
+ const keyRange = isScalar(pair.key) ? pair.key.range : undefined;
327
+ if (!keyRange)
328
+ return undefined;
329
+ const start = keyRange[0];
330
+ let end = isNode(valueNode) && valueNode.range ? valueNode.range[1] : keyRange[2];
331
+ // `key:` with no value: replace through the end of the key's line.
332
+ if (end <= keyRange[1]) {
333
+ const lineEnd = raw.indexOf("\n", keyRange[1]);
334
+ end = lineEnd < 0 ? raw.length : lineEnd;
335
+ }
336
+ while (end > start && /[\r\n]/.test(raw[end - 1] ?? ""))
337
+ end -= 1;
338
+ edits.push({ start, end, text });
339
+ }
340
+ let patched = raw;
341
+ for (const edit of edits.sort((left, right) => right.start - left.start)) {
342
+ patched = `${patched.slice(0, edit.start)}${edit.text}${patched.slice(edit.end)}`;
343
+ }
344
+ if (appended.length > 0) {
345
+ const separator = patched === "" || patched.endsWith("\n") ? "" : "\n";
346
+ patched = `${patched}${separator}${appended.join("\n")}`;
347
+ }
348
+ return patched;
349
+ }
241
350
  function renderEntityDocument(input, entity, existingContent) {
242
351
  const existing = existingContent
243
352
  ? bodyAndFrontmatter(existingContent)
@@ -249,35 +358,21 @@ function renderEntityDocument(input, entity, existingContent) {
249
358
  : input.type === "req"
250
359
  ? `${String(entity.semantic_text ?? "").trim()}\n`
251
360
  : "\n";
252
- const frontmatter = {
253
- ...existing.frontmatter,
254
- ...Object.fromEntries(Object.entries(entity).filter(([key]) =>
255
- // Runtime provenance/timestamps belong to the compiled entity, not to
256
- // the authored source artifact. Keeping them out also makes the source
257
- // diff deterministic across CLI and MCP transports.
258
- ![
259
- "id",
260
- "type",
261
- "source",
262
- "links",
263
- "relationships",
264
- "created_at",
265
- "updated_at",
266
- ].includes(key))),
267
- };
268
- frontmatter.id = entity.id;
269
- frontmatter.title ??= entity.id;
270
- frontmatter.type = entity.type;
271
- // The checked meaning is always stated, never derived from a body that now
272
- // also carries context sections.
273
- if (entity.type === "req" &&
274
- (typeof frontmatter.semantic_text !== "string" ||
275
- frontmatter.semantic_text.trim() === "")) {
276
- const derived = requirementSemanticText(body);
277
- if (derived !== "")
278
- frontmatter.semantic_text = derived;
361
+ const updates = entityFrontmatterUpdates(entity, existing.frontmatter, body);
362
+ const bodySuffix = `${body.startsWith("\n") ? "" : "\n"}${body}`;
363
+ // An existing document keeps its authored front matter bytes; only the
364
+ // keys this upsert changes are rewritten.
365
+ const block = existingContent !== undefined
366
+ ? frontmatterBlock(existingContent)
367
+ : undefined;
368
+ if (block !== undefined) {
369
+ const patched = patchFrontmatter(block.raw, existing.frontmatter, updates);
370
+ if (patched !== undefined) {
371
+ return `${block.opening}${patched}\n---${bodySuffix}`;
372
+ }
279
373
  }
280
- return `---\n${dumpYaml(frontmatter, { noRefs: true, lineWidth: -1, sortKeys: false })}---${body.startsWith("\n") ? "" : "\n"}${body}`;
374
+ const frontmatter = { ...existing.frontmatter, ...updates };
375
+ return `---\n${dumpYaml(frontmatter, { noRefs: true, lineWidth: -1, sortKeys: false })}---${bodySuffix}`;
281
376
  }
282
377
  /** Generated coordinate fields belong exclusively to `.kb/symbol-coordinates.yaml`. */
283
378
  // implements REQ-generated-coordinate-persistence
@@ -52,7 +52,14 @@ export type UpsertPayload = {
52
52
  readonly updated: number;
53
53
  readonly relationships_created: number;
54
54
  readonly warnings: readonly string[];
55
- readonly semanticAdvisor: SemanticAdvisorReceipt;
55
+ /** The requirement semantic advisor receipt; absent for other entity types. */
56
+ readonly semanticAdvisor?: SemanticAdvisorReceipt;
57
+ /**
58
+ * For a fact that carries claim_text: the stored claim_key, derived from
59
+ * claim_text when the payload did not supply it, so the writer learns the
60
+ * grounding key without a kb_query.
61
+ */
62
+ readonly claimKey?: string;
56
63
  readonly status?: "committed_with_repairs";
57
64
  readonly effectFailures?: readonly {
58
65
  readonly kind: string;
@@ -119,8 +126,17 @@ export type DeleteInput = {
119
126
  readonly to: string;
120
127
  }[];
121
128
  readonly _requestId?: string;
129
+ /** Applies the authored-entity deletion plan whose planHash this is. */
122
130
  readonly approvedPlanHash?: string;
131
+ /** Preview the delete without writing sources or the compiled store. */
132
+ readonly dryRun?: boolean;
123
133
  };
134
+ /**
135
+ * What a kb_delete call did when it was not a direct delete: returned an
136
+ * authored-entity deletion plan, refused a requirement that must be
137
+ * superseded, applied an approved plan, or previewed a dry run.
138
+ */
139
+ export type DeleteOutcome = "plan_returned" | "supersession_required" | "plan_applied" | "dry_run";
124
140
  export type DeletePayload = {
125
141
  readonly deleted: number;
126
142
  readonly relationships_deleted?: number;
@@ -131,6 +147,28 @@ export type DeletePayload = {
131
147
  readonly sync_required?: boolean;
132
148
  /** Declared effects this call did not perform, such as a plan-only result. */
133
149
  readonly skippedEffects?: readonly string[];
150
+ /** Absent on a direct delete. */
151
+ readonly outcome?: DeleteOutcome;
152
+ readonly dryRun?: true;
153
+ /** Dry run only: what a commit would delete. */
154
+ readonly wouldDelete?: Readonly<{
155
+ readonly entities: number;
156
+ readonly ids?: readonly string[];
157
+ readonly relationships?: number;
158
+ readonly compiledEdges?: number;
159
+ }>;
160
+ /** Applied plan only: the plan hash and the source files it changed. */
161
+ readonly planHash?: string;
162
+ readonly sourcePaths?: readonly string[];
163
+ readonly recoveryJournalId?: string;
164
+ readonly status?: "committed_with_repairs";
165
+ readonly nextActions?: readonly Readonly<{
166
+ readonly operation: string;
167
+ readonly input: unknown;
168
+ readonly reason: string;
169
+ readonly required: boolean;
170
+ readonly detail?: string;
171
+ }>[];
134
172
  readonly sourceWrites?: readonly {
135
173
  readonly path: string;
136
174
  readonly mode?: "write" | "delete";
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/operations/mutation/types.ts"],"names":[],"mappings":"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"}