kibi-cli 2.24.0 → 2.26.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 (107) hide show
  1. package/dist/cli-errors.d.ts +14 -0
  2. package/dist/cli-errors.d.ts.map +1 -1
  3. package/dist/cli-errors.js +31 -0
  4. package/dist/commands/check.d.ts.map +1 -1
  5. package/dist/commands/check.js +28 -0
  6. package/dist/commands/migrate.d.ts +2 -0
  7. package/dist/commands/migrate.d.ts.map +1 -1
  8. package/dist/commands/migrate.js +115 -4
  9. package/dist/commands/sync/cache.d.ts +30 -0
  10. package/dist/commands/sync/cache.d.ts.map +1 -1
  11. package/dist/commands/sync/cache.js +61 -0
  12. package/dist/commands/sync/extraction.d.ts +6 -0
  13. package/dist/commands/sync/extraction.d.ts.map +1 -1
  14. package/dist/commands/sync/extraction.js +4 -1
  15. package/dist/commands/sync.d.ts.map +1 -1
  16. package/dist/commands/sync.js +27 -1
  17. package/dist/firm-decision-edit.d.ts +30 -0
  18. package/dist/firm-decision-edit.d.ts.map +1 -0
  19. package/dist/firm-decision-edit.js +90 -0
  20. package/dist/operations/bootstrap/claim-restatement.d.ts +37 -0
  21. package/dist/operations/bootstrap/claim-restatement.d.ts.map +1 -0
  22. package/dist/operations/bootstrap/claim-restatement.js +83 -0
  23. package/dist/operations/bootstrap/generate.d.ts.map +1 -1
  24. package/dist/operations/bootstrap/generate.js +23 -12
  25. package/dist/operations/bootstrap/intent-claims.d.ts +5 -2
  26. package/dist/operations/bootstrap/intent-claims.d.ts.map +1 -1
  27. package/dist/operations/bootstrap/intent-claims.js +44 -4
  28. package/dist/operations/migration/requirement-status.d.ts +41 -2
  29. package/dist/operations/migration/requirement-status.d.ts.map +1 -1
  30. package/dist/operations/migration/requirement-status.js +75 -7
  31. package/dist/operations/migration/schema6.d.ts +9 -5
  32. package/dist/operations/migration/schema6.d.ts.map +1 -1
  33. package/dist/operations/migration/schema6.js +82 -13
  34. package/dist/operations/migration/symbol-coordinates-refresh.d.ts +36 -0
  35. package/dist/operations/migration/symbol-coordinates-refresh.d.ts.map +1 -0
  36. package/dist/operations/migration/symbol-coordinates-refresh.js +99 -0
  37. package/dist/operations/mutation/firm-decision-guard.d.ts +10 -0
  38. package/dist/operations/mutation/firm-decision-guard.d.ts.map +1 -0
  39. package/dist/operations/mutation/firm-decision-guard.js +71 -0
  40. package/dist/operations/mutation/source-authoring.d.ts +9 -0
  41. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  42. package/dist/operations/mutation/source-authoring.js +20 -0
  43. package/dist/operations/mutation/stored-entity.d.ts +5 -0
  44. package/dist/operations/mutation/stored-entity.d.ts.map +1 -1
  45. package/dist/operations/mutation/uncompiled-source.d.ts +43 -0
  46. package/dist/operations/mutation/uncompiled-source.d.ts.map +1 -0
  47. package/dist/operations/mutation/uncompiled-source.js +115 -0
  48. package/dist/operations/mutation/upsert.d.ts +6 -0
  49. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  50. package/dist/operations/mutation/upsert.js +34 -5
  51. package/dist/public/impact/analyzer.d.ts.map +1 -1
  52. package/dist/public/impact/analyzer.js +13 -3
  53. package/dist/public/impact/diagnostics.js +1 -1
  54. package/dist/public/impact/unowned-files.d.ts +31 -0
  55. package/dist/public/impact/unowned-files.d.ts.map +1 -0
  56. package/dist/public/impact/unowned-files.js +171 -0
  57. package/dist/public/operations/catalog.d.ts +3 -3
  58. package/dist/public/operations/decision-firmness.d.ts +11 -1
  59. package/dist/public/operations/decision-firmness.d.ts.map +1 -1
  60. package/dist/public/operations/decision-firmness.js +78 -5
  61. package/dist/public/operations/discovery-entities.d.ts +11 -0
  62. package/dist/public/operations/discovery-entities.d.ts.map +1 -1
  63. package/dist/public/operations/discovery-entities.js +28 -0
  64. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  65. package/dist/public/operations/discovery-executors.js +13 -1
  66. package/dist/public/operations/result-envelope.d.ts +2 -0
  67. package/dist/public/operations/result-envelope.d.ts.map +1 -1
  68. package/dist/public/operations/result-envelope.js +1 -0
  69. package/dist/public/operations/source-relationship-parity.d.ts.map +1 -1
  70. package/dist/public/operations/source-relationship-parity.js +22 -7
  71. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  72. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  73. package/dist/public/operations/specs/check-rules.generated.js +2 -1
  74. package/dist/public/operations/specs/check.d.ts +2 -2
  75. package/dist/public/operations/specs/check.js +1 -1
  76. package/dist/public/operations/specs/mutation-schemas.d.ts +1 -1
  77. package/dist/public/operations/specs/mutation-schemas.js +1 -1
  78. package/dist/public/operations/specs/upsert.d.ts +1 -1
  79. package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
  80. package/dist/public/skills/kibi-usage/SKILL.md +18 -7
  81. package/dist/traceability/git-change-snapshot.d.ts.map +1 -1
  82. package/dist/traceability/git-change-snapshot.js +44 -3
  83. package/dist/traceability/staged-diagnostics.d.ts +1 -1
  84. package/dist/traceability/staged-diagnostics.d.ts.map +1 -1
  85. package/dist/traceability/staged-migration.d.ts +13 -0
  86. package/dist/traceability/staged-migration.d.ts.map +1 -0
  87. package/dist/traceability/staged-migration.js +59 -0
  88. package/dist/traceability/staged-symbols-manifest.d.ts +11 -0
  89. package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
  90. package/dist/traceability/staged-symbols-manifest.js +50 -16
  91. package/dist/utils/rule-registry.generated.d.ts +5 -0
  92. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  93. package/dist/utils/rule-registry.generated.js +6 -0
  94. package/package.json +2 -2
  95. package/src/public/impact/analyzer.ts +21 -7
  96. package/src/public/impact/diagnostics.ts +1 -1
  97. package/src/public/impact/unowned-files.ts +229 -0
  98. package/src/public/operations/decision-firmness.ts +110 -13
  99. package/src/public/operations/discovery-entities.ts +36 -0
  100. package/src/public/operations/discovery-executors.ts +17 -1
  101. package/src/public/operations/result-envelope.ts +3 -0
  102. package/src/public/operations/source-relationship-parity.ts +22 -7
  103. package/src/public/operations/specs/check-rules.generated.ts +2 -1
  104. package/src/public/operations/specs/check.ts +1 -1
  105. package/src/public/operations/specs/mutation-schemas.ts +1 -1
  106. package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
  107. package/src/public/skills/kibi-usage/SKILL.md +18 -7
@@ -12,4 +12,18 @@ export declare class OperationError extends Error {
12
12
  readonly exitCode = 1;
13
13
  constructor(code: string, detail: string, retryable?: boolean);
14
14
  }
15
+ /** The error envelope fields a thrown Kibi error carries. */
16
+ export type CodedErrorFields = {
17
+ readonly code: string;
18
+ readonly message: string;
19
+ readonly retryable: boolean;
20
+ };
21
+ /**
22
+ * The code, message and retryability of a thrown InputError or
23
+ * OperationError, so the CLI JSON route and the MCP server answer it with the
24
+ * same error envelope. A copy of these classes bundled into another package
25
+ * fails `instanceof`, so an error with the same name and a code-shaped `code`
26
+ * counts too. Any other error carries no Kibi code and returns null.
27
+ */
28
+ export declare function codedErrorOf(error: unknown): CodedErrorFields | null;
15
29
  //# sourceMappingURL=cli-errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli-errors.d.ts","sourceRoot":"","sources":["../src/cli-errors.ts"],"names":[],"mappings":"AACA,qBAAa,UAAW,SAAQ,KAAK;IAMjC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IALzB,QAAQ,CAAC,QAAQ,KAAK;IACtB,QAAQ,CAAC,SAAS,SAAS;gBAGhB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM;CAK1B;AAGD,qBAAa,cAAe,SAAQ,KAAK;IAKrC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,SAAS;IALpB,QAAQ,CAAC,QAAQ,KAAK;gBAGX,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,UAAO;CAK5B"}
1
+ {"version":3,"file":"cli-errors.d.ts","sourceRoot":"","sources":["../src/cli-errors.ts"],"names":[],"mappings":"AACA,qBAAa,UAAW,SAAQ,KAAK;IAMjC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IALzB,QAAQ,CAAC,QAAQ,KAAK;IACtB,QAAQ,CAAC,SAAS,SAAS;gBAGhB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM;CAK1B;AAGD,qBAAa,cAAe,SAAQ,KAAK;IAKrC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,SAAS;IALpB,QAAQ,CAAC,QAAQ,KAAK;gBAGX,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,UAAO;CAK5B;AAED,6DAA6D;AAE7D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B,CAAC;AAIF;;;;;;GAMG;AAEH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CA4BpE"}
@@ -27,3 +27,34 @@ export class OperationError extends Error {
27
27
  this.name = "OperationError";
28
28
  }
29
29
  }
30
+ const ERROR_CODE = /^[A-Z][A-Z0-9_]*$/;
31
+ /**
32
+ * The code, message and retryability of a thrown InputError or
33
+ * OperationError, so the CLI JSON route and the MCP server answer it with the
34
+ * same error envelope. A copy of these classes bundled into another package
35
+ * fails `instanceof`, so an error with the same name and a code-shaped `code`
36
+ * counts too. Any other error carries no Kibi code and returns null.
37
+ */
38
+ // implements REQ-mcp-coded-error-envelope
39
+ export function codedErrorOf(error) {
40
+ if (error instanceof InputError || error instanceof OperationError)
41
+ return {
42
+ code: error.code,
43
+ message: error.detail,
44
+ retryable: error.retryable,
45
+ };
46
+ if (!(error instanceof Error))
47
+ return null;
48
+ const candidate = error;
49
+ if ((candidate.name !== "InputError" && candidate.name !== "OperationError") ||
50
+ typeof candidate.code !== "string" ||
51
+ !ERROR_CODE.test(candidate.code))
52
+ return null;
53
+ return {
54
+ code: candidate.code,
55
+ message: typeof candidate.detail === "string" ? candidate.detail : error.message,
56
+ retryable: typeof candidate.retryable === "boolean"
57
+ ? candidate.retryable
58
+ : candidate.name === "OperationError",
59
+ };
60
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAqCA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAiF7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAE3D,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AA8gBD,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,CAAC,EACtC,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,EAC5B,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GAC3B,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAMpB;AAGD,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA2oB/B;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAoDtB;AAID,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBnB;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,aAAa,EACrB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBnB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAkEtB;AAID,wBAAsB,aAAa,CACjC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAmGtB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,SAAS,EAAE,CAAC,CAyCtB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAgDtB;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CA0BtB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAqBtB;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAqBtB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAqBtB"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAqCA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAkF7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAE3D,YAAY,EAAE,SAAS,EAAE,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AA6hBD,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,CAAC,EACtC,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,EAC5B,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,SAAS,GAC3B,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAMpB;AAGD,wBAAsB,YAAY,CAChC,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgqB/B;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAoDtB;AAID,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBnB;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,aAAa,EACrB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBnB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAkEtB;AAID,wBAAsB,aAAa,CACjC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAmGtB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,EACrB,YAAY,EAAE,MAAM,EAAE,GACrB,OAAO,CAAC,SAAS,EAAE,CAAC,CAyCtB;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAgDtB;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CA0BtB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAqBtB;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAqBtB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,EAAE,CAAC,CAqBtB"}
@@ -39,6 +39,7 @@ import { createStagedEntityIdStyleDiagnostics } from "../traceability/staged-ent
39
39
  import { analyzeStagedFileCoverage, } from "../traceability/staged-file-coverage.js";
40
40
  import { classifyKibiImpactEvidence, isBehaviorSourceEdit, parseKibiImpactOverride, } from "../traceability/staged-impact-contract.js";
41
41
  import { stagedInventoryDriftViolations } from "../traceability/staged-inventory-drift.js";
42
+ import { stagedCommitCarriesMigration } from "../traceability/staged-migration.js";
42
43
  import { assessStagedSymbolsManifest, collectStagedAuthoredSymbolsManifestEvidence, } from "../traceability/staged-symbols-manifest.js";
43
44
  import { createManifestLookupSentinelKey, extractSymbolsFromStagedFileAsync, } from "../traceability/symbol-extract.js";
44
45
  import { cleanupTempKb, consultOverlay, createOverlayFacts, createTempKb, projectStagedEntities, } from "../traceability/temp-kb.js";
@@ -323,6 +324,13 @@ function noValidatedSymbolsMessage(sourceAnalysis) {
323
324
  function uniqueSorted(values) {
324
325
  return Array.from(new Set(values)).sort();
325
326
  }
327
+ /** The Baseline-style line naming records changed only by a migration. */
328
+ // implements REQ-cli-migration-first-commit
329
+ function migrationOnlyNote(entityIds) {
330
+ const shown = entityIds.slice(0, 5).join(", ");
331
+ const more = entityIds.length > 5 ? ` and ${entityIds.length - 5} more` : "";
332
+ return `Migration commit: ${entityIds.length} symbol record(s) changed only by kibi migrate (legacy-link marks, review:context-missing tags) are not judged as changed by this commit: ${shown}${more}. Run kibi check for the full report.`;
333
+ }
326
334
  function hasYamlFrontmatter(content) {
327
335
  const trimmed = content.trimStart();
328
336
  return trimmed.startsWith("---") && trimmed.slice(3).includes("\n---");
@@ -361,7 +369,10 @@ function buildStagedKibiImpactEvidence(options) {
361
369
  ...(options.readBaseFile ? { readBaseFile: options.readBaseFile } : {}),
362
370
  stagedFiles,
363
371
  sourceFiles: behaviorSourceFiles,
372
+ ignoreMigrationOwnedEdits: options.ignoreMigrationOwnedEdits === true,
364
373
  });
374
+ if (stagedAuthoredSymbolsEvidence.migrationOnlyEntityIds !== undefined)
375
+ options.onMigrationOnlySymbols?.(stagedAuthoredSymbolsEvidence.migrationOnlyEntityIds);
365
376
  const resolvedKbArtifacts = [];
366
377
  let override = null;
367
378
  for (const file of markdownFiles) {
@@ -670,7 +681,24 @@ export async function checkCommand(options) {
670
681
  ...scopedManifestResults,
671
682
  ...markdownResultsByPath.values(),
672
683
  ];
684
+ const readTreeFile = (tree) => (filePath) => {
685
+ try {
686
+ return snapshot
687
+ .readGit(["show", `${tree}:${filePath}`])
688
+ .toString("utf8");
689
+ }
690
+ catch {
691
+ return null;
692
+ }
693
+ };
694
+ // A commit that carries a kibi migrate run is not charged with the
695
+ // fields the migration rewrote mechanically in existing records.
696
+ const carriesMigration = stagedCommitCarriesMigration(readTreeFile(snapshot.baseTree), readTreeFile(snapshot.headTree));
673
697
  const stagedKibiEvidence = buildStagedKibiImpactEvidence({
698
+ ignoreMigrationOwnedEdits: carriesMigration,
699
+ onMigrationOnlySymbols: (entityIds) => {
700
+ baselineNotes.push(migrationOnlyNote(entityIds));
701
+ },
674
702
  analyzeSource: (filePath) => {
675
703
  const result = sourceAnalysis.get(filePath)?.after;
676
704
  if (!result)
@@ -31,6 +31,8 @@ export interface MigrationAuditRecord {
31
31
  sourcePathsRewritten: number;
32
32
  /** Authored source values this run removed: they named the entity's own file or nothing. */
33
33
  sourcePathsRemoved: number;
34
+ /** Requirements whose delivery status (implemented, done, completed) this run mapped to closed plus tag implemented. */
35
+ legacyStatusesMapped: number;
34
36
  toVersion: number;
35
37
  /** The schema warning the KB showed before this run migrated it. */
36
38
  preMigrationWarning: string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AA+CA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,wCAAwC,CAAC;AAwBhD,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB,EAAE,SAAS,GAAG,WAAW,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC3E,MAAM,EAAE,SAAS,CAAC;IAClB,4BAA4B,EAAE,MAAM,CAAC;IACrC,8EAA8E;IAC9E,oBAAoB,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,4BAA4B,EAAE,MAAM,CAAC;IACrC,sEAAsE;IACtE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,4FAA4F;IAC5F,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,iFAAiF;AACjF,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,oBAAoB,CAAC;IAC5B,0EAA0E;IAC1E,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAgJD,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,OAAO,EACzB,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,MAAM,CAUR;AAsOD,wBAAgB,+BAA+B,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKtE;AAGD,wBAAsB,cAAc,CAClC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAmb9D;AAED;;;;GAIG;AAEH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAGzE;AA+WD;;;;;GAKG;AAEH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,GACpC,OAAO,CAOT"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"AA0DA,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,wCAAwC,CAAC;AAwBhD,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB,EAAE,SAAS,GAAG,WAAW,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC3E,MAAM,EAAE,SAAS,CAAC;IAClB,4BAA4B,EAAE,MAAM,CAAC;IACrC,8EAA8E;IAC9E,oBAAoB,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,4BAA4B,EAAE,MAAM,CAAC;IACrC,sEAAsE;IACtE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,4FAA4F;IAC5F,kBAAkB,EAAE,MAAM,CAAC;IAC3B,wHAAwH;IACxH,oBAAoB,EAAE,MAAM,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,iFAAiF;AACjF,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,oBAAoB,CAAC;IAC5B,0EAA0E;IAC1E,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAgJD,wBAAgB,mBAAmB,CACjC,gBAAgB,EAAE,OAAO,EACzB,UAAU,EAAE,MAAM,GAAG,IAAI,GACxB,MAAM,CAUR;AAiWD,wBAAgB,+BAA+B,IAAI;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAKtE;AAGD,wBAAsB,cAAc,CAClC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAkd9D;AAED;;;;GAIG;AAEH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAGzE;AA+WD;;;;;GAKG;AAEH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,GACpC,OAAO,CAOT"}
@@ -19,8 +19,10 @@ import { existsSync, mkdirSync, renameSync, writeFileSync, } from "node:fs";
19
19
  import * as path from "node:path";
20
20
  import { applySafeInventoryRederivations, planInventoryRederivation, } from "../operations/migration/inventory-rederive.js";
21
21
  import { applyOriginBackfill, planOriginBackfill, } from "../operations/migration/origin-backfill.js";
22
+ import { applyDeliveredStatusMappings, planRequirementStatusMappings, } from "../operations/migration/requirement-status.js";
22
23
  import { applySourcePathRepairs, findSourceRepairs, } from "../operations/migration/source-paths.js";
23
24
  import { applySupersededClosures, planSupersededClosures, } from "../operations/migration/superseded-closure.js";
25
+ import { coordinateRefreshFailureMessage, readGeneratedManifestBytes, refreshCoordinatesAfterMigration, } from "../operations/migration/symbol-coordinates-refresh.js";
24
26
  import { applySymbolLegacyLinks, planSymbolLegacyLinks, } from "../operations/migration/symbol-legacy-links.js";
25
27
  import { resolveBranchAttachment } from "../utils/branch-resolver.js";
26
28
  import { defaultKbManifest, readKbManifest, readKbManifestStatus, writeKbManifest, } from "../utils/kb-manifest.js";
@@ -155,6 +157,7 @@ function buildMigrationAuditRecord(args) {
155
157
  supersededRequirementsClosed: args.supersededRequirementsClosed,
156
158
  sourcePathsRewritten: args.sourcePathsRewritten,
157
159
  sourcePathsRemoved: args.sourcePathsRemoved,
160
+ legacyStatusesMapped: args.legacyStatusesMapped,
158
161
  toVersion: LATEST_KB_SCHEMA_VERSION,
159
162
  preMigrationWarning: args.preMigrationWarning,
160
163
  steps: args.steps,
@@ -187,6 +190,19 @@ function markLegacySymbolLinks(cwd, dryRun, manifestPath) {
187
190
  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.`);
188
191
  return marked.length;
189
192
  }
193
+ /**
194
+ * Refresh generated symbol coordinates after the migration rewrote or moved
195
+ * .kb/symbols.yaml, so the first commit does not hit the generated-manifest
196
+ * gate. A failure leaves the migration applied and names the manual step.
197
+ */
198
+ // implements REQ-cli-migration-first-commit
199
+ async function refreshMigratedSymbolCoordinates(cwd, before) {
200
+ const refresh = await refreshCoordinatesAfterMigration(cwd, before);
201
+ if (refresh.outcome === "refreshed")
202
+ console.log("Refreshed generated symbol coordinates for the migrated .kb/symbols.yaml; stage .kb/symbols.yaml and .kb/symbol-coordinates.yaml with the migration.");
203
+ else if (refresh.outcome === "failed")
204
+ printWarning(coordinateRefreshFailureMessage(refresh.reason));
205
+ }
190
206
  function describeRederivation(plan) {
191
207
  const { keptModeled, roleChanges, newlyUnresolved, downgradedModeled } = plan.summary;
192
208
  return `${plan.requirementId}: ${keptModeled} modeled claim(s) kept, ${roleChanges} role change(s), ${newlyUnresolved} claim(s) now unresolved, ${downgradedModeled} modeled claim(s) downgraded`;
@@ -300,6 +316,74 @@ function repairLifecycleFindings(cwd, dryRun) {
300
316
  manual: supersession.cycles.length + unrepaired.length,
301
317
  };
302
318
  }
319
+ function describeDeliveredMappings(findings) {
320
+ const byStatus = new Map();
321
+ for (const finding of findings) {
322
+ byStatus.set(finding.status, [
323
+ ...(byStatus.get(finding.status) ?? []),
324
+ finding,
325
+ ]);
326
+ }
327
+ return [...byStatus]
328
+ .map(([status, group]) => `legacy status ${status} -> ${group[0]?.automatic?.status ?? "closed"} (tag ${group[0]?.automatic?.tag ?? "implemented"}) on ${group.length} requirement(s): ${group.map((finding) => finding.requirementId).join(", ")}`)
329
+ .join("; ");
330
+ }
331
+ /**
332
+ * Map delivery statuses (implemented, done, completed) to closed plus the tag
333
+ * implemented: kibi sync cannot compile them, and that is their one lossless
334
+ * reading. Returns the requirement statuses a person still has to decide.
335
+ */
336
+ // implements REQ-cli-schema-migration
337
+ function mapLegacyRequirementStatuses(cwd, dryRun) {
338
+ const findings = planRequirementStatusMappings(cwd);
339
+ const delivered = findings.filter((finding) => finding.automatic !== null);
340
+ if (dryRun) {
341
+ const review = findings.filter((finding) => finding.automatic === null);
342
+ if (delivered.length > 0)
343
+ console.log(`dry run: would map ${describeDeliveredMappings(delivered)}.`);
344
+ if (review.length > 0)
345
+ console.log(`dry run: ${review.length} requirement status(es) need a person to choose the current status: ${review.map((finding) => `${finding.requirementId} (${finding.status})`).join(", ")}; kibi migrate --format json lists them as req_status_vocabulary_map.`);
346
+ return { mapped: delivered.length, review };
347
+ }
348
+ if (delivered.length === 0)
349
+ return { mapped: 0, review: findings };
350
+ const result = applyDeliveredStatusMappings(cwd);
351
+ if (result.mapped.length > 0)
352
+ console.log(`Mapped ${describeDeliveredMappings(result.mapped)}.`);
353
+ for (const skip of result.skipped)
354
+ printWarning(`Status not mapped for ${skip.path}: ${skip.reason}.`);
355
+ return {
356
+ mapped: result.mapped.length,
357
+ review: planRequirementStatusMappings(cwd),
358
+ };
359
+ }
360
+ /**
361
+ * Print what a `kibi migrate --yes` run left for a person, naming the
362
+ * requirements kibi sync cannot compile first. Returns false when nothing
363
+ * remains, so the caller may call the migration complete.
364
+ */
365
+ // implements REQ-cli-schema-migration
366
+ function printRemainingMigrationWork(remaining) {
367
+ const { statuses, manualInventories, manualLifecycle } = remaining;
368
+ if (statuses.length === 0 && manualInventories === 0 && manualLifecycle === 0)
369
+ return false;
370
+ const uncompiled = statuses.filter((finding) => finding.extractionError !== null);
371
+ const skipped = statuses.filter((finding) => finding.extractionError === null);
372
+ const notCompiled = uncompiled.length + manualInventories;
373
+ console.log(`Migration incomplete: ${notCompiled} requirement(s) are not compiled, so kb_query, kb_coverage and kb_upsert do not see them, and ${skipped.length + manualLifecycle} other item(s) need a decision.`);
374
+ for (const finding of uncompiled) {
375
+ console.log(` ${finding.requirementId} (${finding.path}): status ${finding.status} is not a status Kibi knows, so kibi sync cannot compile it (${finding.extractionError}). Set status to open, in_progress or closed in the file (closed with the tag implemented for delivered work), then run kibi sync.`);
376
+ }
377
+ if (manualInventories > 0)
378
+ console.log(` ${manualInventories} requirement inventory(ies) need the manual fix in the warnings above; kibi sync rejects them until then.`);
379
+ for (const finding of skipped) {
380
+ console.log(` ${finding.requirementId} (${finding.path}): status ${finding.status} is not a requirement status, so the proof ladder skips it. ${finding.suggestedStatus === null ? "Set status to open, in_progress or closed in the file" : `Approve req-status-vocabulary-map-${finding.requirementId} (${finding.status} -> ${finding.suggestedStatus}) with kibi migrate --apply-safe, or set the status in the file`}.`);
381
+ }
382
+ if (manualLifecycle > 0)
383
+ console.log(` ${manualLifecycle} lifecycle item(s) need a person; see the warnings above.`);
384
+ console.log("Run 'kibi migrate' for the remaining actions; rerun 'kibi migrate --yes' after fixing them.");
385
+ return true;
386
+ }
303
387
  export function warnMigrationRequiredWithoutYes() {
304
388
  printWarning("Migration required for this repository.");
305
389
  console.log("No changes applied.");
@@ -375,26 +459,43 @@ export async function migrateCommand(options = {}) {
375
459
  console.error(`Unsupported schemaVersion ${configStatus.currentVersion}. Upgrade kibi-cli before migrating this KB.`);
376
460
  return { exitCode: 1 };
377
461
  }
462
+ // What the generated manifests held before this run, so the run refreshes
463
+ // coordinates only when it rewrote or moved the symbols manifest.
464
+ const generatedManifestsBefore = readGeneratedManifestBytes(cwd);
378
465
  if (!needsStorageMigration && !needsSchemaUpgrade) {
379
466
  const { planPolarityValueBackfill, applyPolarityValueBackfill } = await import("../operations/migration/polarity-values.js");
380
467
  const polarityCount = options.dryRun
381
468
  ? planPolarityValueBackfill(cwd).length
382
469
  : applyPolarityValueBackfill(cwd);
470
+ // Delivery statuses keep requirements out of the store at any version;
471
+ // map them before the drift check, which only sees compiled requirements.
472
+ const statuses = mapLegacyRequirementStatuses(cwd, options.dryRun === true);
383
473
  // An advisor change can make stored inventories drift at any version,
384
474
  // and lifecycle findings block kibi check at any version.
385
475
  const drift = rederiveDriftedInventories(cwd, options.dryRun === true);
386
476
  const lifecycle = repairLifecycleFindings(cwd, options.dryRun === true);
387
477
  const legacyLinks = markLegacySymbolLinks(cwd, options.dryRun === true);
388
478
  const rewroteSources = polarityCount > 0 ||
479
+ statuses.mapped > 0 ||
389
480
  legacyLinks > 0 ||
390
481
  drift.rederived.length > 0 ||
391
482
  lifecycle.closed > 0 ||
392
483
  lifecycle.rewritten > 0 ||
393
484
  lifecycle.removed > 0;
394
- if (rewroteSources || drift.manual > 0 || lifecycle.manual > 0) {
485
+ if (rewroteSources ||
486
+ statuses.review.length > 0 ||
487
+ drift.manual > 0 ||
488
+ lifecycle.manual > 0) {
395
489
  if (options.dryRun !== true && rewroteSources) {
490
+ await refreshMigratedSymbolCoordinates(cwd, generatedManifestsBefore);
396
491
  console.log("Run 'kibi sync' to recompile the rewritten sources.");
397
492
  }
493
+ if (options.dryRun !== true)
494
+ printRemainingMigrationWork({
495
+ statuses: statuses.review,
496
+ manualInventories: drift.manual,
497
+ manualLifecycle: lifecycle.manual,
498
+ });
398
499
  if (options.yes === true)
399
500
  updateGitIgnore(cwd);
400
501
  return { exitCode: 0 };
@@ -468,6 +569,7 @@ export async function migrateCommand(options = {}) {
468
569
  console.log(`dry run: would record origin {kind: migration} on ${backfill.targets.length} authored entit(ies) without one.`);
469
570
  }
470
571
  }
572
+ mapLegacyRequirementStatuses(cwd, true);
471
573
  rederiveDriftedInventories(cwd, true);
472
574
  repairLifecycleFindings(cwd, true);
473
575
  console.log(`dry run: would write migration audit metadata to ${toRelativePath(cwd, auditPath)}.`);
@@ -520,7 +622,8 @@ export async function migrateCommand(options = {}) {
520
622
  const originBackfill = originBackfillStep
521
623
  ? applyOriginBackfill(cwd, migratedAt)
522
624
  : { written: [], skipped: [], previouslyStamped: 0 };
523
- rederiveDriftedInventories(cwd, false);
625
+ const statuses = mapLegacyRequirementStatuses(cwd, false);
626
+ const drift = rederiveDriftedInventories(cwd, false);
524
627
  const lifecycle = repairLifecycleFindings(cwd, false);
525
628
  const supersedesUnexplained = decisionFirmnessStep
526
629
  ? planSupersedesReasonAcknowledgement(cwd)
@@ -558,6 +661,7 @@ export async function migrateCommand(options = {}) {
558
661
  console.log(`Acknowledged ${supersedesUnexplained.length} supersede(s) recorded without a 'Why this changed' section; new supersedes must explain themselves.`);
559
662
  if (firmSupersedes.length > 0)
560
663
  console.log(`Acknowledged ${firmSupersedes.length} supersede(s) of decisions without firmness that read as firm from schema 10; a new replacement of such a decision must be firm.`);
664
+ await refreshMigratedSymbolCoordinates(cwd, generatedManifestsBefore);
561
665
  const auditRecord = buildMigrationAuditRecord({
562
666
  branch,
563
667
  manifestPath: KB_MANIFEST_RELATIVE,
@@ -569,6 +673,7 @@ export async function migrateCommand(options = {}) {
569
673
  supersededRequirementsClosed: lifecycle.closed,
570
674
  sourcePathsRewritten: lifecycle.rewritten,
571
675
  sourcePathsRemoved: lifecycle.removed,
676
+ legacyStatusesMapped: statuses.mapped,
572
677
  preMigrationWarning: migrationWarning,
573
678
  steps: migrationSteps.map((step) => step.id),
574
679
  });
@@ -584,7 +689,13 @@ export async function migrateCommand(options = {}) {
584
689
  printWarning(`Origin not recorded for ${skip.path}: ${skip.reason}.`);
585
690
  }
586
691
  console.log(`Wrote migration audit metadata to ${toRelativePath(cwd, auditPath)}.`);
587
- console.log("Migration complete. Future 'kibi migrate' runs will be a no-op.");
692
+ const incomplete = printRemainingMigrationWork({
693
+ statuses: statuses.review,
694
+ manualInventories: drift.manual,
695
+ manualLifecycle: lifecycle.manual,
696
+ });
697
+ if (!incomplete)
698
+ console.log("Migration complete. Future 'kibi migrate' runs will be a no-op.");
588
699
  const mergeDriverGaps = manifestMergeDriverGaps(cwd);
589
700
  if (mergeDriverGaps !== null && mergeDriverGaps.length > 0) {
590
701
  console.log(`Tip: kibi merge-driver resolves .kb/symbols.yaml merges by record id, but it is not wired up (${mergeDriverGaps.join("; ")}). ${MERGE_DRIVER_SETUP}`);
@@ -607,7 +718,7 @@ export async function migrateCommand(options = {}) {
607
718
  // implements REQ-agent-guided-migration-orchestration, REQ-cli-schema-migration
608
719
  export function describeMigrationRun(summary) {
609
720
  const { audit } = summary;
610
- 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"}.`;
721
+ 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}, legacy statuses mapped ${audit.legacyStatusesMapped}; .gitignore ${summary.gitignoreUpdated ? "updated" : "unchanged"}.`;
611
722
  }
612
723
  const KB_MANIFEST_RELATIVE = ".kb/manifest.json";
613
724
  // implements REQ-agent-guided-migration-orchestration, REQ-cli-schema-migration
@@ -23,6 +23,24 @@ export type SyncCache = {
23
23
  semanticContracts: Record<string, boolean>;
24
24
  /** Compiler contract that produced the cached compilation; see below. */
25
25
  compilerFingerprint?: string;
26
+ /**
27
+ * Authored sources the last sync could not extract, keyed like `hashes`:
28
+ * their entities are missing from the store, so kb_status reports them.
29
+ */
30
+ extractionFailures?: Record<string, SourceExtractionFailure>;
31
+ };
32
+ /** One authored source the last sync could not extract. */
33
+ export type SourceExtractionFailure = {
34
+ /** SHA-256 of the bytes that failed. */
35
+ hash: string;
36
+ /** The extraction error sync reported. */
37
+ message: string;
38
+ /**
39
+ * The source failed in the store's first compilation (or in every sync
40
+ * since), so it is legacy content that missed the semantic baseline, not
41
+ * new authoring.
42
+ */
43
+ baseline?: boolean;
26
44
  };
27
45
  /**
28
46
  * v2: cache identities are workspace-root relative instead of process-cwd
@@ -46,6 +64,18 @@ export declare const SYNC_COMPILER_FINGERPRINT: string;
46
64
  * visible before the next sync repairs it.
47
65
  */
48
66
  export declare function compilerFingerprintReason(storePath: string, deps?: Partial<SyncCacheDeps>): Record<string, unknown> | null;
67
+ /** Stale-reason code for an authored source the last sync could not extract. */
68
+ export declare const SOURCE_EXTRACTION_FAILED = "source_extraction_failed";
69
+ /**
70
+ * One blocking reason per authored source the last sync could not extract
71
+ * and that still has the bytes that failed: its entities are missing from the
72
+ * store, so the KB is not current even when every compiled file is. A file
73
+ * edited since then is reported by the changed-source reasons instead, and a
74
+ * deleted one by nothing.
75
+ */
76
+ export declare function sourceExtractionFailureReasons(workspaceRoot: string, storePath: string, deps?: Partial<SyncCacheDeps>): Record<string, unknown>[];
77
+ /** How to make an authored source that sync cannot extract compile. */
78
+ export declare function sourceExtractionRemediation(file: string, message: string): string;
49
79
  export declare function toCacheKey(workspaceRoot: string, filePath: string): string;
50
80
  export declare function hashFile(workspaceRoot: string, filePath: string, deps?: Partial<SyncCacheDeps>): string;
51
81
  /** Deterministically hash a JSON-compatible compiler payload. */
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/cache.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAO7E,UAAU,aAAa;IACrB,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,YAAY,EAAE,OAAO,YAAY,CAAC;IAClC,aAAa,EAAE,OAAO,aAAa,CAAC;CACrC;AAaD,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,iEAAiE;IACjE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3C,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,iBAAiB,QAA2B,CAAC;AAE1D;;;;;;GAMG;AAEH,eAAO,MAAM,yBAAyB,QAEtB,CAAC;AAEjB;;;;GAIG;AAEH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAyBhC;AAED,wBAAgB,UAAU,CAAC,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAM1E;AAED,wBAAgB,QAAQ,CAEtB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,MAAM,CAIR;AAED,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAerD;AAED;;;;;GAKG;AAEH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,MAAM,CA4FR;AAED,wBAAgB,aAAa,CAE3B,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,EAC7B,OAAO,GAAE;IACP,oEAAoE;IACpE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAClC,GACL,SAAS,CA8DX;AAED,wBAAgB,cAAc,CAE5B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,SAAS,EAChB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,IAAI,CAaN;AAED,wBAAgB,aAAa,CAE3B,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,GAC5B,IAAI,CASN"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/cache.ts"],"names":[],"mappings":"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"}
@@ -81,6 +81,64 @@ export function compilerFingerprintReason(storePath, deps) {
81
81
  remediation: { command_argv: ["kibi", "sync"], applyRequired: false },
82
82
  };
83
83
  }
84
+ /** Stale-reason code for an authored source the last sync could not extract. */
85
+ // implements REQ-kibi-uncompiled-source-visibility
86
+ export const SOURCE_EXTRACTION_FAILED = "source_extraction_failed";
87
+ /**
88
+ * One blocking reason per authored source the last sync could not extract
89
+ * and that still has the bytes that failed: its entities are missing from the
90
+ * store, so the KB is not current even when every compiled file is. A file
91
+ * edited since then is reported by the changed-source reasons instead, and a
92
+ * deleted one by nothing.
93
+ */
94
+ // implements REQ-kibi-uncompiled-source-visibility
95
+ export function sourceExtractionFailureReasons(workspaceRoot, storePath, deps) {
96
+ const resolved = resolveDeps(deps);
97
+ const cachePath = path.join(storePath, "sync-cache.json");
98
+ if (!resolved.existsSync(cachePath))
99
+ return [];
100
+ let failures;
101
+ try {
102
+ const parsed = JSON.parse(resolved.readFileSync(cachePath, "utf8"));
103
+ if (parsed.extractionFailures === null ||
104
+ typeof parsed.extractionFailures !== "object")
105
+ return [];
106
+ failures = parsed.extractionFailures;
107
+ }
108
+ catch {
109
+ return [];
110
+ }
111
+ const reasons = [];
112
+ for (const [key, failure] of Object.entries(failures).sort(([a], [b]) => a.localeCompare(b))) {
113
+ const absolute = path.resolve(workspaceRoot, key);
114
+ let current;
115
+ try {
116
+ current = hashFile(workspaceRoot, absolute, deps);
117
+ }
118
+ catch {
119
+ continue;
120
+ }
121
+ if (current !== failure?.hash)
122
+ continue;
123
+ const message = String(failure.message);
124
+ reasons.push({
125
+ code: SOURCE_EXTRACTION_FAILED,
126
+ path: key,
127
+ entityIds: [],
128
+ detail: `${key} cannot be compiled, so the entities it declares are missing from the KB: ${message}`,
129
+ remediation: sourceExtractionRemediation(key, message),
130
+ blocking: true,
131
+ });
132
+ }
133
+ return reasons;
134
+ }
135
+ /** How to make an authored source that sync cannot extract compile. */
136
+ // implements REQ-kibi-uncompiled-source-visibility
137
+ export function sourceExtractionRemediation(file, message) {
138
+ if (/\/status\b/.test(message))
139
+ return `Run 'kibi migrate --yes' to map a legacy requirement status (implemented, done and completed become closed with the tag implemented), or set status in ${file} to a status Kibi knows (open, in_progress or closed for a requirement); then run kibi sync.`;
140
+ return `Fix the front matter of ${file} named in the error (edit the file, or rewrite the entity with kb_upsert so the write replaces the failing field), then run kibi sync.`;
141
+ }
84
142
  export function toCacheKey(workspaceRoot, filePath) {
85
143
  const root = path.resolve(workspaceRoot);
86
144
  const target = path.isAbsolute(filePath)
@@ -255,6 +313,9 @@ cachePath, deps, options = {}) {
255
313
  if (parsed.compilerFingerprint !== undefined) {
256
314
  cache.compilerFingerprint = parsed.compilerFingerprint;
257
315
  }
316
+ if (parsed.extractionFailures !== undefined) {
317
+ cache.extractionFailures = parsed.extractionFailures;
318
+ }
258
319
  return cache;
259
320
  }
260
321
  catch {
@@ -2,10 +2,16 @@ import { type ExtractionResult } from "../../extractors/markdown.js";
2
2
  export interface ExtractionOutput {
3
3
  results: ExtractionResult[];
4
4
  failedCacheKeys: Set<string>;
5
+ /** Extraction failures, collected only in validate-only mode. */
5
6
  errors: {
6
7
  file: string;
7
8
  message: string;
8
9
  }[];
10
+ /** Every source that could not be extracted, in any mode. */
11
+ failures: {
12
+ file: string;
13
+ message: string;
14
+ }[];
9
15
  }
10
16
  /**
11
17
  * Authored source identities are workspace-relative POSIX paths. Code symbol
@@ -1 +1 @@
1
- {"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/extraction.ts"],"names":[],"mappings":"AAuBA,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC7C;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,aAAa,EAAE,MAAM,GACpB,gBAAgB,EAAE,CAoBpB;AAED,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,CAAC;IACxD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;CAC3D;AAOD,wBAAsB,kBAAkB,CAEtC,oBAAoB,EAAE,MAAM,EAAE,EAC9B,oBAAoB,EAAE,MAAM,EAAE,EAC9B,YAAY,EAAE,OAAO,EACrB,aAAa,SAAgB,EAC7B,YAAY,GAAE,sBAAwD,GACrE,OAAO,CAAC,gBAAgB,CAAC,CAmD3B"}
1
+ {"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../../../src/commands/sync/extraction.ts"],"names":[],"mappings":"AAuBA,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,iEAAiE;IACjE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,6DAA6D;IAC7D,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,aAAa,EAAE,MAAM,GACpB,gBAAgB,EAAE,CAoBpB;AAED,UAAU,sBAAsB;IAC9B,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,CAAC;IACxD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,EAAE,CAAC;CAC3D;AAOD,wBAAsB,kBAAkB,CAEtC,oBAAoB,EAAE,MAAM,EAAE,EAC9B,oBAAoB,EAAE,MAAM,EAAE,EAC9B,YAAY,EAAE,OAAO,EACrB,aAAa,SAAgB,EAC7B,YAAY,GAAE,sBAAwD,GACrE,OAAO,CAAC,gBAAgB,CAAC,CAsD3B"}
@@ -57,6 +57,7 @@ changedMarkdownFiles, changedManifestFiles, validateOnly, workspaceRoot = proces
57
57
  const results = [];
58
58
  const failedCacheKeys = new Set();
59
59
  const errors = [];
60
+ const failures = [];
60
61
  for (const file of changedMarkdownFiles) {
61
62
  try {
62
63
  results.push(dependencies.extractFromMarkdown(file));
@@ -74,6 +75,7 @@ changedMarkdownFiles, changedManifestFiles, validateOnly, workspaceRoot = proces
74
75
  else {
75
76
  console.warn(`Warning: Failed to extract from ${file}: ${message}`);
76
77
  }
78
+ failures.push({ file, message });
77
79
  failedCacheKeys.add(toCacheKey(workspaceRoot, file));
78
80
  }
79
81
  }
@@ -95,8 +97,9 @@ changedMarkdownFiles, changedManifestFiles, validateOnly, workspaceRoot = proces
95
97
  else {
96
98
  console.warn(`Warning: Failed to extract from ${file}: ${message}`);
97
99
  }
100
+ failures.push({ file, message });
98
101
  failedCacheKeys.add(toCacheKey(workspaceRoot, file));
99
102
  }
100
103
  }
101
- return { results, failedCacheKeys, errors };
104
+ return { results, failedCacheKeys, errors, failures };
102
105
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA6BjE,OAAO,EAEL,yBAAyB,EAE1B,MAAM,gDAAgD,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,6BAA6B,CAAC;AAyBrC,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAkCxE,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAmCD,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,EACxB,4BAA4B,UAAQ,EACpC,4BAA4B,GAAE,4BAA4B,EAAO,GAChE,MAAM,EAAE,CAuGV;AAiFD,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,yBAAyB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3E,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,yBAAyB,GAAG;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,KACzD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,aAAa,CAAC;IAC/D,yBAAyB,CAAC,EAAE,OAAO,yBAAyB,CAAC;CAC9D;AA+FD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGvE;AAGD,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,IAAI,GAChB,IAAI,CAMN;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,IAAI,CAIN;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAMP;AAED,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,UAAU,EAAE,EACzB,oBAAoB,EAAE,OAAO,EAC7B,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,IAAI,CAUN;AAGD,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;CACZ,EACN,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CA4rCrB;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/commands/sync.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AA6BjE,OAAO,EAEL,yBAAyB,EAE1B,MAAM,gDAAgD,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,6BAA6B,CAAC;AAyBrC,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAkCxE,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAmCD,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,MAAM,EACrB,gBAAgB,EAAE,MAAM,EACxB,4BAA4B,UAAQ,EACpC,4BAA4B,GAAE,4BAA4B,EAAO,GAChE,MAAM,EAAE,CAuGV;AAiFD,MAAM,WAAW,UAAW,SAAQ,WAAW;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,yBAAyB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,kBAAkB;IAC1B,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC3E,UAAU,CAAC,EAAE,CACX,OAAO,EAAE,yBAAyB,GAAG;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,KACzD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KAAK,aAAa,CAAC;IAC/D,yBAAyB,CAAC,EAAE,OAAO,yBAAyB,CAAC;CAC9D;AA+FD,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAGvE;AAGD,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,IAAI,GAChB,IAAI,CAMN;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,UAAU,EAAE,EACzB,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,IAAI,CAIN;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAMP;AAED,wBAAgB,iCAAiC,CAC/C,WAAW,EAAE,UAAU,EAAE,EACzB,oBAAoB,EAAE,OAAO,EAC7B,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,IAAI,CAUN;AAGD,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IACP,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;CACZ,EACN,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CAstCrB;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -644,6 +644,27 @@ export async function syncCommand(options = {}, runtime = {}) {
644
644
  changedManifestFiles.length === manifestFiles.length;
645
645
  const extraction = await processExtractions(changedMarkdownFiles, changedManifestFiles, validateOnly, workspaceRoot);
646
646
  const { failedCacheKeys, errors } = extraction;
647
+ // implements REQ-kibi-uncompiled-source-visibility
648
+ // Sources sync could not extract stay out of the store; record them so
649
+ // kb_status can say so. A source that failed in the store's first
650
+ // compilation (and in every sync since) is legacy content that missed the
651
+ // semantic baseline, so it keeps the baseline treatment once it compiles.
652
+ const previousExtractionFailures = syncCache.extractionFailures ?? {};
653
+ const nextExtractionFailures = {};
654
+ for (const failure of extraction.failures) {
655
+ const key = toCacheKey(workspaceRoot, failure.file);
656
+ const hash = nextHashes[key];
657
+ if (hash === undefined)
658
+ continue;
659
+ nextExtractionFailures[key] = {
660
+ hash,
661
+ message: failure.message,
662
+ ...(initialSemanticBaseline ||
663
+ previousExtractionFailures[key]?.baseline === true
664
+ ? { baseline: true }
665
+ : {}),
666
+ };
667
+ }
647
668
  const extractedResults = normalizeExtractionSources(extraction.results, workspaceRoot);
648
669
  const nextEntityHashes = {
649
670
  ...(syncCache.entityHashes ?? {}),
@@ -739,7 +760,9 @@ export async function syncCommand(options = {}, runtime = {}) {
739
760
  const advertisedContract = result.entity.semantic_inventory_version !== undefined ||
740
761
  result.entity.semantic_source_hash !== undefined ||
741
762
  result.entity.semantic_inventory !== undefined;
742
- const enforceBoundary = (!initialSemanticBaseline && syncCache.hashes[key] === undefined) ||
763
+ const enforceBoundary = (!initialSemanticBaseline &&
764
+ syncCache.hashes[key] === undefined &&
765
+ previousExtractionFailures[key]?.baseline !== true) ||
743
766
  syncCache.semanticContracts[key] === true ||
744
767
  (previousSemanticHash !== undefined &&
745
768
  previousSemanticHash !== boundary.sourceHash) ||
@@ -841,6 +864,7 @@ export async function syncCommand(options = {}, runtime = {}) {
841
864
  semanticHashes: evictedSemanticHashes,
842
865
  semanticContracts: evictedSemanticContracts,
843
866
  compilerFingerprint: SYNC_COMPILER_FINGERPRINT,
867
+ extractionFailures: nextExtractionFailures,
844
868
  });
845
869
  info("✓ Imported 0 entities, 0 relationships (no changes)");
846
870
  return withOptionalCommit({
@@ -990,6 +1014,7 @@ export async function syncCommand(options = {}, runtime = {}) {
990
1014
  semanticHashes: evictedSemanticHashes,
991
1015
  semanticContracts: evictedSemanticContracts,
992
1016
  compilerFingerprint: SYNC_COMPILER_FINGERPRINT,
1017
+ extractionFailures: nextExtractionFailures,
993
1018
  });
994
1019
  published = true;
995
1020
  if (performedFullReindex &&
@@ -1180,6 +1205,7 @@ export async function syncCommand(options = {}, runtime = {}) {
1180
1205
  semanticHashes: evictedSemanticHashes,
1181
1206
  semanticContracts: evictedSemanticContracts,
1182
1207
  compilerFingerprint: SYNC_COMPILER_FINGERPRINT,
1208
+ extractionFailures: nextExtractionFailures,
1183
1209
  });
1184
1210
  published = true;
1185
1211
  maybePushDocsNotIndexedDiagnostic(diagnostics, performedFullReindex, markdownFiles.length, entityCount);