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
@@ -15,15 +15,13 @@
15
15
  * You should have received a copy of the GNU Affero General Public License
16
16
  * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
- import { execFileSync } from "node:child_process";
19
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
18
+ import { existsSync, mkdirSync, renameSync, writeFileSync, } from "node:fs";
20
19
  import * as path from "node:path";
21
- import { load as parseYAML } from "js-yaml";
22
20
  import { applySafeInventoryRederivations, planInventoryRederivation, } from "../operations/migration/inventory-rederive.js";
23
21
  import { applyOriginBackfill, planOriginBackfill, } from "../operations/migration/origin-backfill.js";
24
22
  import { applySourcePathRepairs, findSourceRepairs, } from "../operations/migration/source-paths.js";
25
23
  import { applySupersededClosures, planSupersededClosures, } from "../operations/migration/superseded-closure.js";
26
- import { extractSymbolsFromStagedFile } from "../traceability/symbol-extract.js";
24
+ import { applySymbolLegacyLinks, planSymbolLegacyLinks, } from "../operations/migration/symbol-legacy-links.js";
27
25
  import { resolveBranchAttachment } from "../utils/branch-resolver.js";
28
26
  import { defaultKbManifest, readKbManifest, readKbManifestStatus, writeKbManifest, } from "../utils/kb-manifest.js";
29
27
  import { CANONICAL_ENTITY_PATHS } from "../utils/kb-paths.js";
@@ -151,7 +149,7 @@ function buildMigrationAuditRecord(args) {
151
149
  sourcePathsRewritten: args.sourcePathsRewritten,
152
150
  sourcePathsRemoved: args.sourcePathsRemoved,
153
151
  toVersion: LATEST_KB_SCHEMA_VERSION,
154
- warning: args.warning,
152
+ preMigrationWarning: args.preMigrationWarning,
155
153
  steps: args.steps,
156
154
  };
157
155
  }
@@ -162,137 +160,25 @@ function normalizeSemanticAdvisorBackfill(value) {
162
160
  ? value
163
161
  : null;
164
162
  }
165
- const TRACEABILITY_RELATIONSHIP_TYPES = new Set([
166
- "implements",
167
- "covered_by",
168
- "executable_for",
169
- ]);
170
- function hasTraceabilityRelationship(symbol) {
171
- if (Array.isArray(symbol.links) && symbol.links.length > 0) {
172
- return true;
173
- }
174
- if (!Array.isArray(symbol.relationships)) {
175
- return false;
176
- }
177
- return symbol.relationships.some((relationship) => {
178
- if (relationship === null ||
179
- typeof relationship !== "object" ||
180
- Array.isArray(relationship)) {
181
- return false;
182
- }
183
- const type = relationship.type;
184
- return (typeof type === "string" && TRACEABILITY_RELATIONSHIP_TYPES.has(type));
185
- });
186
- }
187
- function getGranularNames(cwd, sourceFile) {
188
- const absolutePath = path.isAbsolute(sourceFile)
189
- ? sourceFile
190
- : path.join(cwd, sourceFile);
191
- if (!existsSync(absolutePath)) {
192
- return new Set();
193
- }
194
- const symbols = extractSymbolsFromStagedFile({
195
- path: sourceFile,
196
- status: "M",
197
- hunkRanges: [{ start: 1, end: Number.MAX_SAFE_INTEGER }],
198
- content: readFileSync(absolutePath, "utf8"),
199
- });
200
- return new Set(symbols.map((symbol) => symbol.name));
201
- }
202
- function addLegacyReasonsToManifestText(content, symbolIds) {
203
- if (symbolIds.size === 0)
204
- return content;
205
- const lines = content.split("\n");
206
- const output = [];
207
- let activeId = null;
208
- let activeHasReason = false;
209
- let activePropertyIndent = "";
210
- const flushLegacyReason = () => {
211
- if (activeId !== null &&
212
- symbolIds.has(activeId) &&
213
- !activeHasReason &&
214
- activePropertyIndent.length > 0) {
215
- output.push(`${activePropertyIndent}granularity_reason: legacy-link`);
216
- activeHasReason = true;
217
- }
218
- };
219
- for (const line of lines) {
220
- const idMatch = line.match(/^(\s*)-\s+id:\s+(.+)\s*$/);
221
- if (idMatch) {
222
- flushLegacyReason();
223
- activeId = idMatch[2]?.trim() ?? null;
224
- activeHasReason = false;
225
- activePropertyIndent = `${idMatch[1] ?? ""} `;
226
- }
227
- if (activeId !== null && /^\s+granularity_reason:\s+/.test(line)) {
228
- activeHasReason = true;
229
- }
230
- if (activeId !== null &&
231
- symbolIds.has(activeId) &&
232
- !activeHasReason &&
233
- /^\s+status:\s+/.test(line)) {
234
- const indent = line.match(/^\s*/)?.[0] ?? "";
235
- output.push(`${indent}granularity_reason: legacy-link`);
236
- activeHasReason = true;
237
- }
238
- output.push(line);
239
- }
240
- flushLegacyReason();
241
- return output.join("\n");
242
- }
243
- function migrateSymbolGranularity(options) {
244
- const manifestPath = options.manifestPath ??
245
- path.join(options.cwd, CANONICAL_ENTITY_PATHS.symbols);
246
- if (!existsSync(manifestPath)) {
247
- return { count: 0, manifestPath };
248
- }
249
- const manifestContent = readFileSync(manifestPath, "utf8");
250
- const parsed = parseYAML(manifestContent);
251
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
252
- return { count: 0, manifestPath };
253
- }
254
- const manifest = parsed;
255
- if (!Array.isArray(manifest.symbols)) {
256
- return { count: 0, manifestPath };
257
- }
258
- let count = 0;
259
- const migratedSymbolIds = new Set();
260
- const granularNamesByFile = new Map();
261
- for (const symbol of manifest.symbols) {
262
- if (symbol === null ||
263
- typeof symbol !== "object" ||
264
- Array.isArray(symbol)) {
265
- continue;
266
- }
267
- const record = symbol;
268
- if (typeof record.sourceFile !== "string")
269
- continue;
270
- if (typeof record.title !== "string")
271
- continue;
272
- if (typeof record.id !== "string")
273
- continue;
274
- if (record.granularity_reason !== undefined)
275
- continue;
276
- if (!hasTraceabilityRelationship(record))
277
- continue;
278
- let granularNames = granularNamesByFile.get(record.sourceFile);
279
- if (granularNames === undefined) {
280
- granularNames = getGranularNames(options.cwd, record.sourceFile);
281
- granularNamesByFile.set(record.sourceFile, granularNames);
282
- }
283
- if (granularNames.size === 0 || granularNames.has(record.title)) {
284
- continue;
285
- }
286
- count += 1;
287
- if (!options.dryRun) {
288
- record.granularity_reason = "legacy-link";
289
- migratedSymbolIds.add(record.id);
290
- }
291
- }
292
- if (count > 0 && !options.dryRun) {
293
- writeTextAtomically(manifestPath, addLegacyReasonsToManifestText(manifestContent, migratedSymbolIds));
294
- }
295
- return { count, manifestPath };
163
+ /**
164
+ * Mark the coarse symbol links the staged granularity gate would block as
165
+ * legacy-link. Runs at any schema version: the rule can call a link coarse
166
+ * that an older run (or a KB that skipped the schema 2 step) left unmarked.
167
+ */
168
+ // implements REQ-cli-schema-migration, REQ-symbol-behavioral-anchors
169
+ function markLegacySymbolLinks(cwd, dryRun, manifestPath) {
170
+ if (dryRun) {
171
+ const count = planSymbolLegacyLinks(cwd, manifestPath).targets.length;
172
+ if (count > 0)
173
+ console.log(`dry run: would mark ${count} coarse symbol link(s) as legacy-link (granularity_reason), so the staged check accepts them.`);
174
+ return count;
175
+ }
176
+ const { marked, unmarked } = applySymbolLegacyLinks(cwd);
177
+ if (marked.length > 0)
178
+ console.log(`Marked ${marked.length} existing coarse symbol link(s) as legacy-link.`);
179
+ if (unmarked.length > 0)
180
+ printWarning(`Could not mark ${unmarked.join(", ")} as legacy-link in place; add granularity_reason: legacy-link to them in ${CANONICAL_ENTITY_PATHS.symbols} by hand.`);
181
+ return marked.length;
296
182
  }
297
183
  function describeRederivation(plan) {
298
184
  const { keptModeled, roleChanges, newlyUnresolved, downgradedModeled } = plan.summary;
@@ -300,7 +186,7 @@ function describeRederivation(plan) {
300
186
  }
301
187
  function printManualRederivations(plans) {
302
188
  for (const plan of plans) {
303
- printWarning(`${plan.requirementId} (${plan.path}) no longer matches the current semantic advisor and needs a manual fix: ${plan.reasons.join("; ")}. Run 'kibi migrate --format json' for the exact repair steps.`);
189
+ printWarning(`${plan.requirementId} (${plan.path}) no longer matches the current semantic advisor and needs a manual fix: ${plan.reasons.join("; ")}. Run 'kibi migrate --format json' for the exact repair steps.${plan.rederivableByDroppingGrounding ? ` Or approve semantic-inventory-rederive-drop-grounding-${plan.requirementId} with --apply-safe --approved-action to drop the ${plan.orphanedGrounding.length} orphaned grounding link(s).` : ""}`);
304
190
  }
305
191
  }
306
192
  /**
@@ -456,7 +342,9 @@ export async function migrateCommand(options = {}) {
456
342
  const configStatus = getSchemaVersionStatus(normalizedVersion === null
457
343
  ? undefined
458
344
  : { schemaVersion: normalizedVersion });
459
- const needsStorageMigration = storagePlan.moves.length > 0 || storagePlan.legacyConfig !== "absent";
345
+ const needsStorageMigration = storagePlan.moves.length > 0 ||
346
+ storagePlan.removals.length > 0 ||
347
+ storagePlan.legacyConfig !== "absent";
460
348
  const needsSchemaUpgrade = configStatus.needsMigration || normalizedVersion === null;
461
349
  const migrationWarning = manifestStatus.state === "invalid" || manifestStatus.state === "future"
462
350
  ? manifestStatus.warning
@@ -489,7 +377,9 @@ export async function migrateCommand(options = {}) {
489
377
  // and lifecycle findings block kibi check at any version.
490
378
  const drift = rederiveDriftedInventories(cwd, options.dryRun === true);
491
379
  const lifecycle = repairLifecycleFindings(cwd, options.dryRun === true);
380
+ const legacyLinks = markLegacySymbolLinks(cwd, options.dryRun === true);
492
381
  const rewroteSources = polarityCount > 0 ||
382
+ legacyLinks > 0 ||
493
383
  drift.rederived.length > 0 ||
494
384
  lifecycle.closed > 0 ||
495
385
  lifecycle.rewritten > 0 ||
@@ -513,7 +403,6 @@ export async function migrateCommand(options = {}) {
513
403
  }
514
404
  const fromVersionLabel = formatSchemaVersion(currentVersion, normalizedVersion);
515
405
  const migrationSteps = migrationStepsFor(configStatus.currentVersion);
516
- const symbolGranularityStep = migrationSteps.some((step) => step.id === "symbol-granularity-v2");
517
406
  const semanticBackfillStep = migrationSteps.some((step) => step.id === "semantic-backfill-v4");
518
407
  const originBackfillStep = migrationSteps.some((step) => step.id === "entity-origin-v6");
519
408
  const { planPolarityValueBackfill, applyPolarityValueBackfill } = await import("../operations/migration/polarity-values.js");
@@ -548,21 +437,17 @@ export async function migrateCommand(options = {}) {
548
437
  console.log(` ${move.from} -> ${move.to}`);
549
438
  }
550
439
  }
440
+ if (storagePlan.removals.length > 0) {
441
+ console.log(`dry run: would remove ${storagePlan.removals.length} legacy cop(ies) identical to their .kb/ file:`);
442
+ for (const removal of storagePlan.removals) {
443
+ console.log(` ${removal.path} (same as ${removal.duplicateOf})`);
444
+ }
445
+ }
551
446
  if (storagePlan.legacyConfig !== "absent") {
552
447
  console.log("dry run: would retire legacy .kb/config.json after moving knowledge into .kb/.");
553
448
  }
554
449
  console.log(`dry run: would set schemaVersion from ${fromVersionLabel} to ${LATEST_KB_SCHEMA_VERSION} in .kb/manifest.json.`);
555
- if (symbolGranularityStep) {
556
- const symbolsSource = storagePlan.moves.find((move) => move.to === CANONICAL_ENTITY_PATHS.symbols)?.from ?? CANONICAL_ENTITY_PATHS.symbols;
557
- const preview = migrateSymbolGranularity({
558
- cwd,
559
- dryRun: true,
560
- manifestPath: path.join(cwd, symbolsSource),
561
- });
562
- if (preview.count > 0) {
563
- console.log(`dry run: would mark ${preview.count} legacy coarse symbol link(s) as legacy-link.`);
564
- }
565
- }
450
+ markLegacySymbolLinks(cwd, true, storagePlan.moves.find((move) => move.to === CANONICAL_ENTITY_PATHS.symbols)?.from);
566
451
  if (originBackfillStep) {
567
452
  const backfill = planOriginBackfill(cwd);
568
453
  if (backfill.targets.length > 0) {
@@ -581,20 +466,18 @@ export async function migrateCommand(options = {}) {
581
466
  const storageResult = applyLegacyStorageMigration(cwd, storagePlan);
582
467
  if (storageResult.movedFiles.length > 0) {
583
468
  console.log(`Moved ${storageResult.movedFiles.length} knowledge file(s) into the canonical .kb/ layout.`);
584
- const untracked = untrackedFiles(cwd, storageResult.movedFiles);
469
+ const untracked = storageResult.untrackedMovedFiles.length;
585
470
  if (untracked > 0)
586
- printWarning(`${untracked} moved file(s) are not tracked by Git yet, and kibi sync compiles only tracked sources: until you stage them (git add .kb, plus the removals under the legacy folders) the KB compiles without them and plans report them as missing.`);
471
+ printWarning(`${untracked} moved file(s) are not tracked by Git yet. Kibi recorded a pending-source receipt for each, so kibi sync compiles them now; stage them before you commit (git add .kb, plus the removals under the legacy folders). Each receipt retires once Git tracks its file.`);
472
+ }
473
+ if (storageResult.removedFiles.length > 0) {
474
+ console.log(`Removed ${storageResult.removedFiles.length} legacy cop(ies) identical to their .kb/ file: ${storageResult.removedFiles.join(", ")}.`);
587
475
  }
588
476
  if (storageResult.retiredLegacyConfig) {
589
477
  console.log("Retired legacy .kb/config.json.");
590
478
  }
591
479
  }
592
- const symbolGranularityMigration = symbolGranularityStep
593
- ? migrateSymbolGranularity({
594
- cwd,
595
- dryRun: options.yes !== true,
596
- })
597
- : { count: 0 };
480
+ const legacyLinksMarked = markLegacySymbolLinks(cwd, false);
598
481
  const semanticAdvisorBackfill = normalizeSemanticAdvisorBackfill(readKbManifest(cwd)?.semanticAdvisorBackfill) ??
599
482
  normalizeSemanticAdvisorBackfill(storagePlan.semanticAdvisorBackfill) ??
600
483
  (semanticBackfillStep || needsStorageMigration
@@ -651,24 +534,22 @@ export async function migrateCommand(options = {}) {
651
534
  });
652
535
  if (supersedesUnexplained.length > 0)
653
536
  console.log(`Acknowledged ${supersedesUnexplained.length} supersede(s) recorded without a 'Why this changed' section; new supersedes must explain themselves.`);
654
- writeJsonAtomically(auditPath, buildMigrationAuditRecord({
537
+ const auditRecord = buildMigrationAuditRecord({
655
538
  branch,
656
539
  manifestPath: KB_MANIFEST_RELATIVE,
657
540
  fromVersion: configStatus.currentVersion,
658
541
  migratedAt,
659
542
  semanticAdvisorBackfill,
660
- symbolGranularityLegacyLinks: symbolGranularityMigration.count,
543
+ symbolGranularityLegacyLinks: legacyLinksMarked,
661
544
  entityOriginBackfill: originBackfill.written.length + originBackfill.previouslyStamped,
662
545
  supersededRequirementsClosed: lifecycle.closed,
663
546
  sourcePathsRewritten: lifecycle.rewritten,
664
547
  sourcePathsRemoved: lifecycle.removed,
665
- warning: migrationWarning,
548
+ preMigrationWarning: migrationWarning,
666
549
  steps: migrationSteps.map((step) => step.id),
667
- }));
550
+ });
551
+ writeJsonAtomically(auditPath, auditRecord);
668
552
  console.log(`Migrated the KB to schemaVersion ${LATEST_KB_SCHEMA_VERSION} on the canonical .kb/ layout (was ${fromVersionLabel}).`);
669
- if (symbolGranularityMigration.count > 0) {
670
- console.log(`Marked ${symbolGranularityMigration.count} existing coarse symbol link(s) as legacy-link.`);
671
- }
672
553
  if (semanticAdvisorBackfill === "pending") {
673
554
  console.log(`Marked semantic advisor backfill as pending in ${KB_MANIFEST_RELATIVE}.`);
674
555
  }
@@ -680,8 +561,25 @@ export async function migrateCommand(options = {}) {
680
561
  }
681
562
  console.log(`Wrote migration audit metadata to ${toRelativePath(cwd, auditPath)}.`);
682
563
  console.log("Migration complete. Future 'kibi migrate' runs will be a no-op.");
683
- updateGitIgnore(cwd);
684
- return { exitCode: 0 };
564
+ const gitignoreUpdated = updateGitIgnore(cwd);
565
+ return {
566
+ exitCode: 0,
567
+ summary: {
568
+ auditPath: toRelativePath(cwd, auditPath),
569
+ audit: auditRecord,
570
+ gitignoreUpdated,
571
+ },
572
+ };
573
+ }
574
+ /**
575
+ * One line naming what an applied migration run changed, read from the audit
576
+ * record it wrote: a count of zero shows a pass that had nothing left to do
577
+ * (for example legacy links an earlier plan action already marked).
578
+ */
579
+ // implements REQ-agent-guided-migration-orchestration, REQ-cli-schema-migration
580
+ export function describeMigrationRun(summary) {
581
+ const { audit } = summary;
582
+ return `Migrated schema ${audit.fromVersion ?? "none"} -> ${audit.toVersion} (audit ${summary.auditPath}): legacy-link marks ${audit.symbolGranularityLegacyLinks}, origin backfill ${audit.entityOriginBackfill}, superseded requirements closed ${audit.supersededRequirementsClosed}, source paths rewritten ${audit.sourcePathsRewritten}, source paths removed ${audit.sourcePathsRemoved}; .gitignore ${summary.gitignoreUpdated ? "updated" : "unchanged"}.`;
685
583
  }
686
584
  const KB_MANIFEST_RELATIVE = ".kb/manifest.json";
687
585
  // implements REQ-agent-guided-migration-orchestration, REQ-cli-schema-migration
@@ -750,9 +648,13 @@ async function buildWorkspaceMigrationPlan(workspaceRoot = process.cwd()) {
750
648
  if (checkable && storeSynced) {
751
649
  const checkResult = await executeOperation(runtime, checkSpec, {});
752
650
  if (checkResult.structuredContent?.migrationPlan !== undefined) {
753
- // Lifecycle repairs and their sync are planned above from authored
754
- // sources, which may be newer than the compiled store.
755
- plans.push(withoutActionCodes(checkResult.structuredContent.migrationPlan, SOURCE_PLANNED_LIFECYCLE_CODES));
651
+ // Lifecycle repairs, their sync and requirement status mappings are
652
+ // planned above from authored sources, which may be newer than the
653
+ // compiled store.
654
+ plans.push(withoutActionCodes(checkResult.structuredContent.migrationPlan, new Set([
655
+ ...SOURCE_PLANNED_LIFECYCLE_CODES,
656
+ "check_req-status-vocabulary",
657
+ ])));
756
658
  }
757
659
  const coverageInputs = [
758
660
  { by: "req", limit: 10_000, offset: 0 },
@@ -858,24 +760,6 @@ function approvedActionIdsOf(options) {
858
760
  .filter((id) => id.length > 0);
859
761
  return [...new Set(ids)];
860
762
  }
861
- /** How many of `files` Git does not track; 0 outside a repository. */
862
- // implements REQ-cli-schema-migration
863
- function untrackedFiles(cwd, files) {
864
- let tracked;
865
- try {
866
- tracked = new Set(execFileSync("git", ["-C", cwd, "ls-files", "-z", "--", ".kb"], {
867
- encoding: "utf8",
868
- stdio: ["ignore", "pipe", "ignore"],
869
- timeout: 10_000,
870
- })
871
- .split("\0")
872
- .filter((file) => file.length > 0));
873
- }
874
- catch {
875
- return 0;
876
- }
877
- return files.filter((file) => !tracked.has(file)).length;
878
- }
879
763
  /** The table rendering of an apply result; --format json prints it whole. */
880
764
  // implements REQ-cli-schema-migration
881
765
  function printApplySummary(content) {
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/manifest.ts"],"names":[],"mappings":"AAkBA,OAAO,EACL,UAAU,EACV,YAAY,EACZ,UAAU,EACV,UAAU,EACV,aAAa,EACd,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,SAAS,CAAC;AAE9D,OAAO,EAML,uBAAuB,EACxB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,KAAK,mBAAmB,EACxB,uBAAuB,EACxB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,0BAA0B,EAG3B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAG5E,UAAU,YAAY;IACpB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,2BAA2B,EAAE,OAAO,2BAA2B,CAAC;CACjE;AAkBD,eAAO,MAAM,8BAA8B,QAc1C,CAAC;AAaF;;;;;;;;;GASG;AACH,OAAO,EAAE,0BAA0B,EAAE,CAAC;AAEtC,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAG7E;AAoHD,wBAAsB,0BAA0B,CAE9C,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG;IAC7B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GACA,OAAO,CAAC,IAAI,CAAC,CA0Mf;AAED;;;;;;;;GAQG;AAEH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAC3B,MAAM,GAAG,IAAI,CAWf;AAED,wBAAgB,0BAA0B,CAExC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAOT;AAED,wBAAgB,8BAA8B,CAE5C,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAC3B,OAAO,CAUT"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/manifest.ts"],"names":[],"mappings":"AAkBA,OAAO,EACL,UAAU,EACV,YAAY,EACZ,UAAU,EACV,UAAU,EACV,aAAa,EACd,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,SAAS,CAAC;AAE9D,OAAO,EAML,uBAAuB,EACxB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,KAAK,mBAAmB,EACxB,uBAAuB,EACxB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,0BAA0B,EAG3B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAG5E,UAAU,YAAY;IACpB,QAAQ,EAAE,OAAO,QAAQ,CAAC;IAC1B,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,uBAAuB,EAAE,OAAO,uBAAuB,CAAC;IACxD,2BAA2B,EAAE,OAAO,2BAA2B,CAAC;CACjE;AAkBD,eAAO,MAAM,8BAA8B,QAc1C,CAAC;AAeF;;;;;;;;;GASG;AACH,OAAO,EAAE,0BAA0B,EAAE,CAAC;AAEtC,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAG7E;AA2HD,wBAAsB,0BAA0B,CAE9C,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG;IAC7B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GACA,OAAO,CAAC,IAAI,CAAC,CA0Mf;AAED;;;;;;;;GAQG;AAEH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAC3B,MAAM,GAAG,IAAI,CAWf;AAED,wBAAgB,0BAA0B,CAExC,KAAK,EAAE,mBAAmB,GACzB,OAAO,CAOT;AAED,wBAAgB,8BAA8B,CAE5C,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAC3B,OAAO,CAUT"}
@@ -63,6 +63,8 @@ const GENERATED_COORD_FIELDS = [
63
63
  const GENERATED_MANIFEST_FIELDS = new Set([
64
64
  ...GENERATED_COORD_FIELDS,
65
65
  "coordinatesGeneratedAt",
66
+ // Transient refresh outcome from the coordinate enricher; never authored.
67
+ "coordinateRefreshFailure",
66
68
  ]);
67
69
  /**
68
70
  * Coarse symbol anchors for which AST per-declaration coordinates are not
@@ -159,7 +161,14 @@ function manifestEntryIdentity(entry) {
159
161
  * granularity_reason (so the whole-file fallback is gated off) or the
160
162
  * fallback itself produced no span.
161
163
  */
164
+ // implements REQ-generated-coordinate-persistence
162
165
  function coarseAnchorFailureReason(entry) {
166
+ // The enricher names the cause when the title is a declaration the symbol
167
+ // extractor never produces (a private class member): no refresh can bind
168
+ // it, so the remedy is to re-point or remove the symbol.
169
+ if (typeof entry.coordinateRefreshFailure === "string") {
170
+ return entry.coordinateRefreshFailure;
171
+ }
163
172
  const reason = entry.granularity_reason;
164
173
  if (!isCoarseGranularityReason(reason)) {
165
174
  return `extractor produced no coordinates; add symbol_role and granularity_reason ${COARSE_GRANULARITY_REASONS_PARENTHESIZED} to enable the whole-file coarse fallback`;
@@ -191,6 +191,7 @@ function withoutGeneratedCoordinates(entry) {
191
191
  "sourceEndLine",
192
192
  "sourceEndColumn",
193
193
  "coordinatesGeneratedAt",
194
+ "coordinateRefreshFailure",
194
195
  ]);
195
196
  return Object.fromEntries(Object.entries(entry).filter(([field]) => !generatedFields.has(field)));
196
197
  }
@@ -1 +1 @@
1
- {"version":3,"file":"intent-search.d.ts","sourceRoot":"","sources":["../src/intent-search.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"intent-search.d.ts","sourceRoot":"","sources":["../src/intent-search.ts"],"names":[],"mappings":"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"}
@@ -153,6 +153,22 @@ function tokens(value) {
153
153
  .split(" ")
154
154
  .filter((token) => token.length > 0 && !STOP_WORDS.has(token))));
155
155
  }
156
+ // Clause boundaries an agent writes when it packs several questions into one
157
+ // query: "user roles: how many can a user have, support role".
158
+ const CLAUSE_SEPARATOR = /[;:,!?\n]+|\.(?=\s|$)|\s[-\u2013\u2014]\s/;
159
+ const MIN_CLAUSE_TOKENS = 2;
160
+ /**
161
+ * The token sets of a compound query's clauses, or none for a single clause.
162
+ * A clause needs two signal tokens: one word alone matches too broadly to
163
+ * stand in for the question.
164
+ */
165
+ function queryClauses(query) {
166
+ const clauses = query
167
+ .split(CLAUSE_SEPARATOR)
168
+ .map((clause) => tokens(clause))
169
+ .filter((clause) => clause.length >= MIN_CLAUSE_TOKENS);
170
+ return clauses.length > 1 ? clauses : [];
171
+ }
156
172
  function stringValues(value) {
157
173
  if (typeof value === "string")
158
174
  return value.trim() ? [value] : [];
@@ -392,10 +408,11 @@ async function readBodies(entities, workspaceRoot, cache) {
392
408
  export async function rankIntentEntities(entities, options, workspaceRoot, graphEdges = [], bodyCache = new Map()) {
393
409
  const queryTokens = tokens(options.query);
394
410
  const facets = facetValues(options.semanticFacets);
395
- const allTokens = Array.from(new Set([
396
- ...queryTokens,
397
- ...facets.flatMap((facet) => tokens(facet.value)),
398
- ]));
411
+ const facetTokens = facets.flatMap((facet) => tokens(facet.value));
412
+ const allTokens = Array.from(new Set([...queryTokens, ...facetTokens]));
413
+ // Each clause of a compound question is also scored on its own, so the
414
+ // words of one clause do not dilute a match on another.
415
+ const clauseTokenSets = queryClauses(options.query).map((clause) => Array.from(new Set([...clause, ...facetTokens])));
399
416
  const bodies = await readBodies(entities, workspaceRoot, bodyCache);
400
417
  const documentFrequency = buildDocumentFrequency(entities, bodies);
401
418
  const supersededIds = new Set(graphEdges
@@ -428,8 +445,13 @@ export async function rankIntentEntities(entities, options, workspaceRoot, graph
428
445
  // already capped; unbounded parallel paths only add noise to receipts.
429
446
  const graphEvidence = (graphByEntity.get(entityId) ?? []).slice(0, 8);
430
447
  const body = bodies.get(entity) ?? null;
431
- const scored = scoreEntity(entity, allTokens, facets, sourceEvidence, graphEvidence, documentFrequency, entities.length, body, supersededIds.has(entityId), isProvenanceStub(entity));
432
- if (scored.score < minScore)
448
+ let scored;
449
+ for (const signalTokens of [allTokens, ...clauseTokenSets]) {
450
+ const candidate = scoreEntity(entity, signalTokens, facets, sourceEvidence, graphEvidence, documentFrequency, entities.length, body, supersededIds.has(entityId), isProvenanceStub(entity));
451
+ if (scored === undefined || candidate.score > scored.score)
452
+ scored = candidate;
453
+ }
454
+ if (scored === undefined || scored.score < minScore)
433
455
  continue;
434
456
  const snippet = body === null
435
457
  ? undefined
@@ -51,6 +51,26 @@ export type InventoryRederivation = Readonly<{
51
51
  contract: InventoryContract;
52
52
  /** SHA-256 of the canonical re-derived contract; the apply step re-checks it. */
53
53
  contractHash: string;
54
+ /**
55
+ * Grounding links (requires_*) whose target no longer grounds a modeled
56
+ * claim of the re-derived inventory. Empty for a safe re-derivation.
57
+ */
58
+ orphanedGrounding: readonly OrphanedGroundingLink[];
59
+ /**
60
+ * True when an unsafe re-derivation passes ingestion once exactly the
61
+ * orphaned grounding links are removed from the requirement's front
62
+ * matter. A person approves that explicitly; it is never automatic.
63
+ */
64
+ rederivableByDroppingGrounding: boolean;
65
+ }>;
66
+ /** A grounding link the re-derived inventory no longer supports. */
67
+ export type OrphanedGroundingLink = Readonly<{
68
+ type: string;
69
+ target: string;
70
+ /** The target fact's claim_key; null when it declares none. */
71
+ claimKey: string | null;
72
+ /** Declared in the requirement's front matter `links` (not a shard). */
73
+ inFrontMatter: boolean;
54
74
  }>;
55
75
  /**
56
76
  * Every current requirement whose stored inventory contract no longer matches
@@ -58,7 +78,14 @@ export type InventoryRederivation = Readonly<{
58
78
  * reports all of them instead of stopping at the first. `onlyId` limits the
59
79
  * scan to one requirement.
60
80
  */
61
- export declare function planInventoryRederivation(workspaceRoot: string, onlyId?: string): InventoryRederivation[];
81
+ export declare function planInventoryRederivation(workspaceRoot: string, onlyId?: string, options?: Readonly<{
82
+ /**
83
+ * Plan as if the requirement had this status: a requirement whose status
84
+ * is outside the current vocabulary is not validated, so its drift only
85
+ * shows once the status is mapped.
86
+ */
87
+ status?: string;
88
+ }>): InventoryRederivation[];
62
89
  export type InventoryRederivationOutcome = Readonly<{
63
90
  requirementId: string;
64
91
  path: string;
@@ -72,6 +99,18 @@ export type InventoryRederivationOutcome = Readonly<{
72
99
  * left unchanged, so repeated runs are no-ops.
73
100
  */
74
101
  export declare function applyInventoryRederivation(workspaceRoot: string, requirementId: string, expectedContractHash?: string): InventoryRederivationOutcome;
102
+ /**
103
+ * Apply an unsafe re-derivation a person approved: write the re-derived
104
+ * contract and remove exactly `expectedDrops`, the orphaned grounding links
105
+ * the plan listed, from the requirement's front matter. The current plan must
106
+ * still produce the approved contract hash and the same orphaned links, and
107
+ * the rewritten requirement must pass ingestion before anything is written;
108
+ * the grounding facts themselves are left alone.
109
+ */
110
+ export declare function applyInventoryRederivationDroppingGrounding(workspaceRoot: string, requirementId: string, expectedContractHash: string, expectedDrops: readonly Readonly<{
111
+ type: string;
112
+ target: string;
113
+ }>[]): InventoryRederivationOutcome;
75
114
  /** Apply every safe re-derivation; unsafe ones are returned untouched. */
76
115
  export declare function applySafeInventoryRederivations(workspaceRoot: string): {
77
116
  rederived: InventoryRederivationOutcome[];
@@ -1 +1 @@
1
- {"version":3,"file":"inventory-rederive.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/inventory-rederive.ts"],"names":[],"mappings":"AA2EA,KAAK,cAAc,GAAG;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,gDAAgD;AAEhD,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EACF,MAAM,GACN,cAAc,GACd,cAAc,GACd,gBAAgB,GAChB,aAAa,GACb,gBAAgB,GAChB,aAAa,GACb,SAAS,CAAC;IACd,MAAM,CAAC,EAAE,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpD,KAAK,CAAC,EAAE,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD,CAAC,CAAC;AAGH,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC,CAAC;AAEH,oEAAoE;AAEpE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,0BAA0B,EAAE,MAAM,CAAC;IACnC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,SAAS,cAAc,EAAE,CAAC;IAC9C,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC,CAAC,CAAC;AAGH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,+DAA+D;IAC/D,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,4BAA4B,CAAC;IACtC,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACzC,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAAC;AA2UH;;;;;GAKG;AAEH,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,MAAM,EACrB,MAAM,CAAC,EAAE,MAAM,GACd,qBAAqB,EAAE,CA+BzB;AA0FD,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,GAAG,WAAW,CAAC;IACnC,OAAO,CAAC,EAAE,4BAA4B,CAAC;CACxC,CAAC,CAAC;AAEH;;;;;GAKG;AAEH,wBAAgB,0BAA0B,CACxC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,oBAAoB,CAAC,EAAE,MAAM,GAC5B,4BAA4B,CA0C9B;AAED,0EAA0E;AAE1E,wBAAgB,+BAA+B,CAAC,aAAa,EAAE,MAAM,GAAG;IACtE,SAAS,EAAE,4BAA4B,EAAE,CAAC;IAC1C,MAAM,EAAE,qBAAqB,EAAE,CAAC;CACjC,CAaA"}
1
+ {"version":3,"file":"inventory-rederive.d.ts","sourceRoot":"","sources":["../../../src/operations/migration/inventory-rederive.ts"],"names":[],"mappings":"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"}