kibi-cli 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/dist/cli-json-command.d.ts.map +1 -1
  2. package/dist/cli-json-command.js +2 -2
  3. package/dist/cli-operation-loader.d.ts.map +1 -1
  4. package/dist/cli-operation-loader.js +3 -0
  5. package/dist/cli-operation-metadata.d.ts +5 -1
  6. package/dist/cli-operation-metadata.d.ts.map +1 -1
  7. package/dist/cli-operation-metadata.js +6 -1
  8. package/dist/cli-register-maintenance.d.ts.map +1 -1
  9. package/dist/cli-register-maintenance.js +7 -0
  10. package/dist/cli-register-reporting.d.ts.map +1 -1
  11. package/dist/cli-register-reporting.js +4 -0
  12. package/dist/commands/check-diff.d.ts +5 -0
  13. package/dist/commands/check-diff.d.ts.map +1 -0
  14. package/dist/commands/check-diff.js +62 -0
  15. package/dist/commands/check-generated.d.ts.map +1 -1
  16. package/dist/commands/check-generated.js +41 -18
  17. package/dist/commands/check.d.ts.map +1 -1
  18. package/dist/commands/check.js +210 -73
  19. package/dist/commands/doctor.d.ts.map +1 -1
  20. package/dist/commands/doctor.js +63 -29
  21. package/dist/commands/github-init.d.ts.map +1 -1
  22. package/dist/commands/github-init.js +9 -2
  23. package/dist/commands/merge-driver.d.ts +31 -0
  24. package/dist/commands/merge-driver.d.ts.map +1 -0
  25. package/dist/commands/merge-driver.js +268 -0
  26. package/dist/commands/sync/manifest.d.ts.map +1 -1
  27. package/dist/commands/sync/manifest.js +3 -1
  28. package/dist/engine.d.ts +15 -1
  29. package/dist/engine.d.ts.map +1 -1
  30. package/dist/engine.js +252 -52
  31. package/dist/extractors/symbols-coordinator.d.ts +7 -0
  32. package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
  33. package/dist/extractors/symbols-coordinator.js +75 -39
  34. package/dist/operations/bootstrap/candidates.js +1 -1
  35. package/dist/operations/bootstrap/discovery.js +1 -1
  36. package/dist/operations/bootstrap/generate.d.ts.map +1 -1
  37. package/dist/operations/bootstrap/generate.js +21 -5
  38. package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
  39. package/dist/operations/bootstrap/guidance-actions.js +3 -0
  40. package/dist/operations/bootstrap/guidance.d.ts.map +1 -1
  41. package/dist/operations/bootstrap/guidance.js +7 -1
  42. package/dist/operations/bootstrap/intent-claims.d.ts +17 -0
  43. package/dist/operations/bootstrap/intent-claims.d.ts.map +1 -0
  44. package/dist/operations/bootstrap/intent-claims.js +95 -0
  45. package/dist/operations/bootstrap/presentation.d.ts +2 -0
  46. package/dist/operations/bootstrap/presentation.d.ts.map +1 -1
  47. package/dist/operations/bootstrap/presentation.js +60 -1
  48. package/dist/operations/bootstrap/types.d.ts +28 -0
  49. package/dist/operations/bootstrap/types.d.ts.map +1 -1
  50. package/dist/operations/bootstrap/types.js +16 -0
  51. package/dist/operations/modeling/predicate-inference-1.js +1 -1
  52. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  53. package/dist/operations/mutation/source-authoring.js +175 -53
  54. package/dist/operations/mutation/symbol-refresh.d.ts.map +1 -1
  55. package/dist/operations/mutation/symbol-refresh.js +4 -1
  56. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  57. package/dist/operations/mutation/upsert.js +5 -7
  58. package/dist/operations/planning/apply-plan.d.ts.map +1 -1
  59. package/dist/operations/planning/apply-plan.js +5 -9
  60. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  61. package/dist/operations/proof/ingest-proof.js +1 -0
  62. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  63. package/dist/operations/semantic-advisor/analysis-receipt.js +7 -1
  64. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  65. package/dist/operations/semantic-advisor/analyze-prose.js +26 -4
  66. package/dist/operations/semantic-advisor/clauses.d.ts +1 -0
  67. package/dist/operations/semantic-advisor/clauses.d.ts.map +1 -1
  68. package/dist/operations/semantic-advisor/clauses.js +7 -1
  69. package/dist/performance-trace.d.ts +17 -0
  70. package/dist/performance-trace.d.ts.map +1 -0
  71. package/dist/performance-trace.js +134 -0
  72. package/dist/plugins/approved-source-analyzers.d.ts +13 -0
  73. package/dist/plugins/approved-source-analyzers.d.ts.map +1 -0
  74. package/dist/plugins/approved-source-analyzers.generated.d.ts +71 -0
  75. package/dist/plugins/approved-source-analyzers.generated.d.ts.map +1 -0
  76. package/dist/plugins/approved-source-analyzers.generated.js +77 -0
  77. package/dist/plugins/approved-source-analyzers.js +3 -0
  78. package/dist/plugins/maintenance-source-analysis.d.ts +14 -0
  79. package/dist/plugins/maintenance-source-analysis.d.ts.map +1 -0
  80. package/dist/plugins/maintenance-source-analysis.js +191 -0
  81. package/dist/plugins/registry.d.ts +2 -1
  82. package/dist/plugins/registry.d.ts.map +1 -1
  83. package/dist/plugins/registry.js +6 -1
  84. package/dist/plugins/source-analysis-service.d.ts +36 -1
  85. package/dist/plugins/source-analysis-service.d.ts.map +1 -1
  86. package/dist/plugins/source-analysis-service.js +184 -27
  87. package/dist/plugins/source-change-analysis.d.ts +15 -0
  88. package/dist/plugins/source-change-analysis.d.ts.map +1 -0
  89. package/dist/plugins/source-change-analysis.js +54 -0
  90. package/dist/plugins/source-classification.d.ts +41 -0
  91. package/dist/plugins/source-classification.d.ts.map +1 -0
  92. package/dist/plugins/source-classification.js +490 -0
  93. package/dist/prolog/swipl-resolver.d.ts +88 -0
  94. package/dist/prolog/swipl-resolver.d.ts.map +1 -0
  95. package/dist/prolog/swipl-resolver.js +446 -0
  96. package/dist/prolog.d.ts +15 -1
  97. package/dist/prolog.d.ts.map +1 -1
  98. package/dist/prolog.js +67 -6
  99. package/dist/public/diagnostic-usage.d.ts +14 -0
  100. package/dist/public/diagnostic-usage.d.ts.map +1 -1
  101. package/dist/public/diagnostic-usage.js +55 -1
  102. package/dist/public/impact/analyzer.d.ts.map +1 -1
  103. package/dist/public/impact/analyzer.js +56 -5
  104. package/dist/public/impact/diagnostics.d.ts.map +1 -1
  105. package/dist/public/impact/diagnostics.js +3 -1
  106. package/dist/public/impact/manifest.d.ts.map +1 -1
  107. package/dist/public/impact/manifest.js +15 -1
  108. package/dist/public/impact/source-changes.d.ts.map +1 -1
  109. package/dist/public/impact/source-changes.js +35 -27
  110. package/dist/public/impact/types.d.ts +2 -0
  111. package/dist/public/impact/types.d.ts.map +1 -1
  112. package/dist/public/operations/catalog.d.ts +117 -1
  113. package/dist/public/operations/catalog.d.ts.map +1 -1
  114. package/dist/public/operations/catalog.js +2 -0
  115. package/dist/public/operations/contracts.d.ts.map +1 -1
  116. package/dist/public/operations/contracts.js +309 -8
  117. package/dist/public/operations/impact-review-preparation.d.ts +14 -0
  118. package/dist/public/operations/impact-review-preparation.d.ts.map +1 -0
  119. package/dist/public/operations/impact-review-preparation.js +379 -0
  120. package/dist/public/operations/index.d.ts +2 -0
  121. package/dist/public/operations/index.d.ts.map +1 -1
  122. package/dist/public/operations/index.js +2 -0
  123. package/dist/public/operations/node-ports.d.ts.map +1 -1
  124. package/dist/public/operations/node-ports.js +1 -35
  125. package/dist/public/operations/proof-receipt-projection.d.ts +5 -0
  126. package/dist/public/operations/proof-receipt-projection.d.ts.map +1 -0
  127. package/dist/public/operations/proof-receipt-projection.js +36 -0
  128. package/dist/public/operations/specs/bootstrap.d.ts +73 -1
  129. package/dist/public/operations/specs/bootstrap.d.ts.map +1 -1
  130. package/dist/public/operations/specs/bootstrap.js +66 -1
  131. package/dist/public/operations/specs/impact-review-preparation.d.ts +47 -0
  132. package/dist/public/operations/specs/impact-review-preparation.d.ts.map +1 -0
  133. package/dist/public/operations/specs/impact-review-preparation.js +43 -0
  134. package/dist/public/operations/symbol-repair-plan.d.ts.map +1 -1
  135. package/dist/public/operations/symbol-repair-plan.js +3 -1
  136. package/dist/public/operations/types.d.ts +1 -1
  137. package/dist/public/operations/types.d.ts.map +1 -1
  138. package/dist/public/skills/kibi-bootstrap/SKILL.md +47 -11
  139. package/dist/public/skills/kibi-bootstrap/resources/bootstrap.md +6 -1
  140. package/dist/public/skills/kibi-usage/SKILL.md +14 -0
  141. package/dist/public/skills/kibi-usage/resources/operation-access.md +5 -0
  142. package/dist/public/telemetry-acceptance.d.ts +8 -0
  143. package/dist/public/telemetry-acceptance.d.ts.map +1 -1
  144. package/dist/public/telemetry-acceptance.js +10 -0
  145. package/dist/traceability/analysis-gate.d.ts +39 -0
  146. package/dist/traceability/analysis-gate.d.ts.map +1 -0
  147. package/dist/traceability/analysis-gate.js +51 -0
  148. package/dist/traceability/git-change-snapshot.d.ts +27 -0
  149. package/dist/traceability/git-change-snapshot.d.ts.map +1 -0
  150. package/dist/traceability/git-change-snapshot.js +411 -0
  151. package/dist/traceability/git-staged.d.ts +5 -1
  152. package/dist/traceability/git-staged.d.ts.map +1 -1
  153. package/dist/traceability/git-staged.js +16 -11
  154. package/dist/traceability/impact-evaluator.d.ts +54 -0
  155. package/dist/traceability/impact-evaluator.d.ts.map +1 -0
  156. package/dist/traceability/impact-evaluator.js +270 -0
  157. package/dist/traceability/impact-git-tree.d.ts +12 -0
  158. package/dist/traceability/impact-git-tree.d.ts.map +1 -0
  159. package/dist/traceability/impact-git-tree.js +46 -0
  160. package/dist/traceability/impact-knowledge.d.ts +16 -0
  161. package/dist/traceability/impact-knowledge.d.ts.map +1 -0
  162. package/dist/traceability/impact-knowledge.js +165 -0
  163. package/dist/traceability/impact-policy.d.ts +15 -0
  164. package/dist/traceability/impact-policy.d.ts.map +1 -0
  165. package/dist/traceability/impact-policy.js +48 -0
  166. package/dist/traceability/impact-policy.v1.schema.json +48 -0
  167. package/dist/traceability/impact-pr-diff.d.ts +5 -0
  168. package/dist/traceability/impact-pr-diff.d.ts.map +1 -0
  169. package/dist/traceability/impact-pr-diff.js +83 -0
  170. package/dist/traceability/impact-record-validation.d.ts +9 -0
  171. package/dist/traceability/impact-record-validation.d.ts.map +1 -0
  172. package/dist/traceability/impact-record-validation.js +113 -0
  173. package/dist/traceability/impact-review.d.ts +148 -0
  174. package/dist/traceability/impact-review.d.ts.map +1 -0
  175. package/dist/traceability/impact-review.js +494 -0
  176. package/dist/traceability/impact-review.schema.json +365 -0
  177. package/dist/traceability/impact-side-evidence.d.ts +13 -0
  178. package/dist/traceability/impact-side-evidence.d.ts.map +1 -0
  179. package/dist/traceability/impact-side-evidence.js +240 -0
  180. package/dist/traceability/reviewed-coordinate-refresh.d.ts +10 -0
  181. package/dist/traceability/reviewed-coordinate-refresh.d.ts.map +1 -0
  182. package/dist/traceability/reviewed-coordinate-refresh.js +49 -0
  183. package/dist/traceability/snapshot-knowledge.d.ts +4 -0
  184. package/dist/traceability/snapshot-knowledge.d.ts.map +1 -0
  185. package/dist/traceability/snapshot-knowledge.js +98 -0
  186. package/dist/traceability/staged-file-coverage.d.ts +23 -0
  187. package/dist/traceability/staged-file-coverage.d.ts.map +1 -1
  188. package/dist/traceability/staged-impact-contract.d.ts.map +1 -1
  189. package/dist/traceability/staged-impact-contract.js +2 -16
  190. package/dist/traceability/staged-symbols-manifest.d.ts +4 -0
  191. package/dist/traceability/staged-symbols-manifest.d.ts.map +1 -1
  192. package/dist/traceability/staged-symbols-manifest.js +17 -6
  193. package/dist/traceability/symbol-extract.d.ts +3 -5
  194. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  195. package/dist/traceability/symbol-extract.js +49 -34
  196. package/dist/traceability/temp-kb.d.ts +1 -1
  197. package/dist/traceability/temp-kb.d.ts.map +1 -1
  198. package/dist/traceability/temp-kb.js +49 -13
  199. package/dist/traceability/trusted-pr-event.d.ts +13 -0
  200. package/dist/traceability/trusted-pr-event.d.ts.map +1 -0
  201. package/dist/traceability/trusted-pr-event.js +105 -0
  202. package/dist/utils/canonical-path.d.ts +3 -0
  203. package/dist/utils/canonical-path.d.ts.map +1 -0
  204. package/dist/utils/canonical-path.js +33 -0
  205. package/package.json +14 -5
  206. package/src/public/diagnostic-usage.ts +59 -1
  207. package/src/public/impact/analyzer.ts +88 -5
  208. package/src/public/impact/diagnostics.ts +7 -5
  209. package/src/public/impact/manifest.ts +14 -1
  210. package/src/public/impact/source-changes.ts +39 -34
  211. package/src/public/impact/types.ts +5 -0
  212. package/src/public/operations/catalog.ts +2 -0
  213. package/src/public/operations/contracts.ts +385 -9
  214. package/src/public/operations/impact-review-preparation.ts +548 -0
  215. package/src/public/operations/index.ts +2 -0
  216. package/src/public/operations/node-ports.ts +1 -39
  217. package/src/public/operations/proof-receipt-projection.ts +39 -0
  218. package/src/public/operations/specs/bootstrap.ts +78 -4
  219. package/src/public/operations/specs/impact-review-preparation.ts +46 -0
  220. package/src/public/operations/symbol-repair-plan.ts +3 -1
  221. package/src/public/operations/types.ts +1 -0
  222. package/src/public/skills/kibi-bootstrap/SKILL.md +47 -11
  223. package/src/public/skills/kibi-bootstrap/resources/bootstrap.md +6 -1
  224. package/src/public/skills/kibi-usage/SKILL.md +14 -0
  225. package/src/public/skills/kibi-usage/resources/operation-access.md +5 -0
  226. package/src/public/telemetry-acceptance.ts +9 -0
  227. package/src/traceability/impact-policy.v1.schema.json +48 -0
  228. package/src/traceability/impact-review.schema.json +365 -0
  229. package/templates/github/kibi-badge.yml +0 -4
  230. package/templates/github/kibi-report.yml +0 -4
@@ -15,19 +15,23 @@
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 { existsSync } from "node:fs";
19
18
  import * as path from "node:path";
20
19
  import { EngineClient } from "../engine.js";
21
- import { isCliTraceOrDebugEnabled } from "../env.js";
22
- import { extractFromManifest, extractFromManifestString, } from "../extractors/manifest.js";
20
+ import { extractFromManifestString } from "../extractors/manifest.js";
23
21
  import { extractFromMarkdownString, } from "../extractors/markdown.js";
22
+ import { createMaintenanceSourceAnalysisService, fingerprintMaintenanceSourceSet, readSnapshotSourceConfig, } from "../plugins/maintenance-source-analysis.js";
23
+ import { analyzeSourceChanges, assertSourceAnalysisGate, } from "../plugins/source-change-analysis.js";
24
24
  import { PrologProcess } from "../prolog.js";
25
25
  import { escapeAtom, normalizeEntityId, parseTriples, parseViolationRows, } from "../prolog/codec.js";
26
26
  import { createSemanticReviewDiagnostics, createSymbolGranularityDiagnostics, createSymbolQualityDiagnostics, hasBlockingImpactDiagnostics, } from "../public/impact-diagnostics.js";
27
27
  import { executeCheck } from "../public/operations/check-executor.js";
28
28
  import { KIBI_NO_IMPACT_DECLARATION, KIBI_SYMBOLS_MANIFEST_PATH, KIBI_SYMBOL_COORDINATES_PATH, } from "../traceability/evidence-model.js";
29
- import { getStagedInventory, supportedStagedFiles, } from "../traceability/git-staged.js";
29
+ import { captureStagedSnapshot } from "../traceability/git-change-snapshot.js";
30
+ import { supportedStagedFiles, } from "../traceability/git-staged.js";
31
+ import { evaluateImpactReview, fingerprintImpactEvaluator, hasValidBaseImpactPolicy, } from "../traceability/impact-evaluator.js";
32
+ import { IMPACT_REVIEW_PATH } from "../traceability/impact-review.js";
30
33
  import { validateStagedMarkdown } from "../traceability/markdown-validate.js";
34
+ import { readSnapshotKnowledge } from "../traceability/snapshot-knowledge.js";
31
35
  import { collectStagedKibiDiagnostics, } from "../traceability/staged-diagnostics.js";
32
36
  import { createStagedEntityIdStyleDiagnostics } from "../traceability/staged-entity-id-style.js";
33
37
  import { analyzeStagedFileCoverage, } from "../traceability/staged-file-coverage.js";
@@ -43,7 +47,7 @@ function getMatchGroup(match, index = 1) {
43
47
  const value = match?.[index];
44
48
  return typeof value === "string" ? value : null;
45
49
  }
46
- function buildManifestLookup(stagedFiles) {
50
+ function buildManifestLookup(stagedFiles, snapshotEntities) {
47
51
  const manifestLookup = new Map();
48
52
  const manifestResults = [];
49
53
  const authoredSymbolResults = [];
@@ -69,40 +73,29 @@ function buildManifestLookup(stagedFiles) {
69
73
  results[existingIndex] = result;
70
74
  }
71
75
  };
72
- // Pre-populate lookup from working-tree manifests so that code-only changes
73
- // (where symbols.yaml is not staged) still resolve to the correct symbol IDs
74
- // and relationships already defined on disk.
75
- const symbolsRelPath = CANONICAL_ENTITY_PATHS.symbols;
76
- {
77
- const absSymbolsPath = path.resolve(process.cwd(), symbolsRelPath);
78
- if (existsSync(absSymbolsPath)) {
79
- try {
80
- const entries = extractFromManifest(absSymbolsPath);
81
- for (const entry of entries) {
82
- upsertResult(authoredSymbolResults, authoredSymbolIndexByKey, entry);
83
- const sourceFile = entry.sourceFile || entry.entity.source || absSymbolsPath;
84
- const key = `${sourceFile}:${entry.entity.title}`;
85
- manifestLookup.set(key, {
86
- id: entry.entity.id,
87
- relationships: entry.relationships
88
- .filter((relationship) => relationship.type === "implements" ||
89
- relationship.type === "covered_by" ||
90
- relationship.type === "executable_for")
91
- .map((relationship) => ({
92
- type: relationship.type,
93
- to: relationship.to,
94
- })),
95
- });
96
- }
97
- }
98
- catch (e) {
99
- // Ignore working-tree manifest parsing errors; staged-only fallback still applies
100
- if (isCliTraceOrDebugEnabled()) {
101
- const msg = e instanceof Error ? e.message : String(e);
102
- console.debug(`[kibi] skipping working-tree manifest ${absSymbolsPath}: ${msg}`);
103
- }
104
- }
76
+ // Authored ownership comes exclusively from the captured index tree.
77
+ // A sentinel prevents symbol extraction from consulting working-tree manifests.
78
+ manifestLookup.set(createManifestLookupSentinelKey(CANONICAL_ENTITY_PATHS.symbols), { id: CANONICAL_ENTITY_PATHS.symbols });
79
+ const ambiguousLocators = new Set();
80
+ for (const entry of snapshotEntities.filter((entry) => entry.entity.type === "symbol")) {
81
+ upsertResult(authoredSymbolResults, authoredSymbolIndexByKey, entry);
82
+ const sourceFile = entry.sourceFile || entry.entity.source;
83
+ if (!sourceFile)
84
+ continue;
85
+ const key = `${sourceFile}:${entry.entity.title}`;
86
+ if (ambiguousLocators.has(key))
87
+ continue;
88
+ if (manifestLookup.has(key)) {
89
+ manifestLookup.delete(key);
90
+ ambiguousLocators.add(key);
91
+ continue;
105
92
  }
93
+ manifestLookup.set(key, {
94
+ id: entry.entity.id,
95
+ relationships: entry.relationships
96
+ .filter((r) => ["implements", "covered_by", "executable_for"].includes(r.type))
97
+ .map((r) => ({ type: r.type, to: r.to })),
98
+ });
106
99
  }
107
100
  const stagedManifestFiles = stagedFiles.filter((file) => file.content !== undefined &&
108
101
  (file.path === CANONICAL_ENTITY_PATHS.symbols ||
@@ -132,19 +125,6 @@ function buildManifestLookup(stagedFiles) {
132
125
  upsertResult(manifestResults, manifestResultIndexByKey, manifestResult, true);
133
126
  upsertResult(authoredSymbolResults, authoredSymbolIndexByKey, authoredSymbolResult, true);
134
127
  upsertResult(stagedAuthoredSymbolResults, stagedAuthoredSymbolIndexByKey, authoredSymbolResult);
135
- const sourceFile = entry.sourceFile || entry.entity.source || manifestFile.path;
136
- const key = `${sourceFile}:${entry.entity.title}`;
137
- manifestLookup.set(key, {
138
- id: entry.entity.id,
139
- relationships: entry.relationships
140
- .filter((relationship) => relationship.type === "implements" ||
141
- relationship.type === "covered_by" ||
142
- relationship.type === "executable_for")
143
- .map((relationship) => ({
144
- type: relationship.type,
145
- to: relationship.to,
146
- })),
147
- });
148
128
  }
149
129
  }
150
130
  catch {
@@ -304,6 +284,39 @@ function printStagedResult(input) {
304
284
  if (input.operationalError)
305
285
  console.error(input.operationalError);
306
286
  }
287
+ function clearResolvedImpactReviewAdvisories(coverage) {
288
+ const transport = coverage.files.find((file) => file.path === IMPACT_REVIEW_PATH);
289
+ const plainTransportChange = transport !== undefined &&
290
+ (transport.status === "A" || transport.status === "M") &&
291
+ transport.oldPath === undefined;
292
+ const reviewedPaths = new Set(coverage.files
293
+ .filter((file) => file.path !== IMPACT_REVIEW_PATH)
294
+ .map((file) => file.path));
295
+ coverage.diagnostics = coverage.diagnostics.filter((diagnostic) => {
296
+ if (diagnostic.id === "staged_file_impact_review_needed" &&
297
+ reviewedPaths.has(diagnostic.path)) {
298
+ return false;
299
+ }
300
+ return !(diagnostic.id === "staged_file_ownership_missing" &&
301
+ diagnostic.path === IMPACT_REVIEW_PATH &&
302
+ plainTransportChange);
303
+ });
304
+ }
305
+ function noValidatedSymbolsMessage(sourceAnalysis) {
306
+ const partialFiles = [...sourceAnalysis.values()].flatMap((analysis) => {
307
+ const partialSide = [analysis.before, analysis.after].find((side) => side?.status === "partial");
308
+ if (!partialSide)
309
+ return [];
310
+ const provider = partialSide.providerId
311
+ ? ` via ${partialSide.providerId}`
312
+ : "";
313
+ return [`${analysis.path}${provider}`];
314
+ });
315
+ if (partialFiles.length > 0) {
316
+ return `Partial source analysis was reviewed for ${partialFiles.join(", ")}; no fully analyzed exported symbols or staged entities were available for symbol validation.`;
317
+ }
318
+ return "No exported symbols or staged entities found in staged files.";
319
+ }
307
320
  function uniqueSorted(values) {
308
321
  return Array.from(new Set(values)).sort();
309
322
  }
@@ -335,11 +348,14 @@ function buildStagedKibiImpactEvidence(options) {
335
348
  const allSourcePaths = sourceChanges.map((change) => change.path);
336
349
  const behaviorSourceFiles = sourceFiles.filter((file) => behaviorSourcePaths.includes(file.path));
337
350
  const stagedSymbolsManifest = assessStagedSymbolsManifest({
351
+ ...(options.analyzeSource ? { analyzeSource: options.analyzeSource } : {}),
352
+ ...(options.readBaseFile ? { readBaseFile: options.readBaseFile } : {}),
338
353
  symbolsManifestPath,
339
354
  stagedFiles,
340
355
  sourceFiles: behaviorSourceFiles,
341
356
  });
342
357
  const stagedAuthoredSymbolsEvidence = collectStagedAuthoredSymbolsManifestEvidence({
358
+ ...(options.readBaseFile ? { readBaseFile: options.readBaseFile } : {}),
343
359
  stagedFiles,
344
360
  sourceFiles: behaviorSourceFiles,
345
361
  });
@@ -436,19 +452,77 @@ export async function checkCommand(options) {
436
452
  let stagedCoverage = null;
437
453
  let tempCtx = null;
438
454
  try {
439
- const stagedInventory = getStagedInventory();
440
- stagedCoverage = analyzeStagedFileCoverage(stagedInventory);
455
+ const snapshot = captureStagedSnapshot(process.cwd());
456
+ const stagedInventory = snapshot.inventory;
457
+ const trustedSourceConfig = readSnapshotSourceConfig(snapshot, snapshot.baseTree);
458
+ const sourceService = createMaintenanceSourceAnalysisService(process.cwd(), trustedSourceConfig);
459
+ const sourceAnalysis = await analyzeSourceChanges(stagedInventory, sourceService);
460
+ for (const file of stagedInventory) {
461
+ const analysis = sourceAnalysis.get(file.path);
462
+ if (analysis?.after?.status === "ok") {
463
+ file.analysisDepth = "symbol";
464
+ file.disposition = "checked";
465
+ }
466
+ }
467
+ const printSnapshotResult = (input) => {
468
+ snapshot.assertUnchanged();
469
+ printStagedResult(input);
470
+ };
471
+ stagedCoverage = analyzeStagedFileCoverage(stagedInventory, snapshot.readGit);
472
+ stagedCoverage.snapshot = {
473
+ baseTree: snapshot.baseTree,
474
+ headTree: snapshot.headTree,
475
+ headCommit: snapshot.headCommit,
476
+ };
477
+ for (const record of stagedCoverage.files) {
478
+ const analysis = sourceAnalysis.get(record.path);
479
+ if (!analysis)
480
+ continue;
481
+ const describe = (side) => side
482
+ ? {
483
+ status: side.status,
484
+ language: side.language,
485
+ symbolCount: side.symbols.length,
486
+ providerId: side.providerId,
487
+ inputFingerprint: side.inputFingerprint,
488
+ providerFingerprint: side.providerFingerprint,
489
+ }
490
+ : null;
491
+ record.sourceAnalysis = {
492
+ before: describe(analysis.before),
493
+ after: describe(analysis.after),
494
+ };
495
+ record.providerId =
496
+ analysis.after?.providerId ?? analysis.before?.providerId ?? null;
497
+ }
498
+ const impactPolicyEnabled = stagedInventory.length > 0 && hasValidBaseImpactPolicy(snapshot);
499
+ // One rule decides which analysis gaps block (see analysis-gate): the
500
+ // committed side never blocks, and an after-side local gap blocks only
501
+ // where it overlaps the staged lines. With a policy, the impact review
502
+ // evaluates the same obligations and accepts reviewed partial gaps.
503
+ if (!impactPolicyEnabled)
504
+ assertSourceAnalysisGate(stagedInventory, sourceAnalysis);
505
+ if (impactPolicyEnabled) {
506
+ const impactEvaluation = evaluateImpactReview(snapshot, {
507
+ providerSetFingerprint: fingerprintMaintenanceSourceSet(process.cwd(), trustedSourceConfig),
508
+ evaluatorFingerprint: fingerprintImpactEvaluator(),
509
+ analyses: sourceAnalysis,
510
+ });
511
+ if (!impactEvaluation.passed)
512
+ throw new Error(`Staged impact review failed:\n${impactEvaluation.diagnostics.map((item) => `${item.code}: ${item.message}`).join("\n")}`);
513
+ if (stagedCoverage) {
514
+ clearResolvedImpactReviewAdvisories(stagedCoverage);
515
+ }
516
+ }
441
517
  const stagedFiles = supportedStagedFiles(stagedInventory);
442
518
  if (stagedInventory.length === 0) {
443
- printStagedResult({
519
+ printSnapshotResult({
444
520
  format: options.format,
445
521
  coverage: stagedCoverage,
446
522
  messages: ["No staged files found."],
447
523
  });
448
524
  return { exitCode: 0 };
449
525
  }
450
- const { manifestLookup, manifestResults, authoredSymbolResults, stagedAuthoredSymbolResults, } = buildManifestLookup(stagedFiles);
451
- const symbolsManifestPath = KIBI_SYMBOLS_MANIFEST_PATH;
452
526
  const symbolPaths = new Set(stagedInventory
453
527
  .filter((file) => file.analysisDepth === "symbol")
454
528
  .map((file) => file.path));
@@ -462,7 +536,7 @@ export async function checkCommand(options) {
462
536
  }
463
537
  }
464
538
  if (markdownErrors.length > 0) {
465
- printStagedResult({
539
+ printSnapshotResult({
466
540
  format: options.format,
467
541
  coverage: stagedCoverage,
468
542
  violations: markdownErrors.map((message) => ({
@@ -479,6 +553,12 @@ export async function checkCommand(options) {
479
553
  }
480
554
  return { exitCode: 1 };
481
555
  }
556
+ const snapshotEntities = readSnapshotKnowledge(snapshot.readGit, snapshot.headTree, snapshot.readBlobs);
557
+ const snapshotRequirementIds = new Set(snapshotEntities
558
+ .filter((row) => row.entity.type === "req")
559
+ .map((row) => row.entity.id));
560
+ const { manifestLookup, manifestResults, authoredSymbolResults, stagedAuthoredSymbolResults, } = buildManifestLookup(stagedFiles, snapshotEntities);
561
+ const symbolsManifestPath = KIBI_SYMBOLS_MANIFEST_PATH;
482
562
  const allSymbols = [];
483
563
  const symbolsByFile = new Map();
484
564
  const sourceContentByFile = new Map();
@@ -487,8 +567,16 @@ export async function checkCommand(options) {
487
567
  if (f.content !== undefined) {
488
568
  sourceContentByFile.set(f.path, f.content);
489
569
  }
490
- // Maintenance path: builtin-only (no CapabilityRegistry / workspaceRoot).
491
- const symbols = await extractSymbolsFromStagedFileAsync(f, manifestLookup, {});
570
+ // Maintenance uses only host-approved source analyzers over captured bytes.
571
+ const symbols = await extractSymbolsFromStagedFileAsync(f, manifestLookup, {
572
+ analyzeText: async () => sourceAnalysis.get(f.path)?.after ?? null,
573
+ });
574
+ for (const symbol of symbols) {
575
+ for (const requirement of symbol.reqLinks) {
576
+ if (!snapshotRequirementIds.has(requirement))
577
+ throw new Error(`Symbol ${symbol.name} references a requirement absent from the captured knowledge snapshot: ${requirement}`);
578
+ }
579
+ }
492
580
  symbolsByFile.set(f.path, symbols);
493
581
  if (symbols?.length) {
494
582
  allSymbols.push(...symbols);
@@ -496,8 +584,7 @@ export async function checkCommand(options) {
496
584
  }
497
585
  catch (e) {
498
586
  const message = `Error extracting symbols from staged file ${f.path}: ${e instanceof Error ? e.message : String(e)}`;
499
- if (options.format !== "json")
500
- console.error(message);
587
+ throw new Error(message);
501
588
  }
502
589
  }
503
590
  const markdownResultsByPath = new Map();
@@ -515,6 +602,22 @@ export async function checkCommand(options) {
515
602
  ...markdownResultsByPath.values(),
516
603
  ];
517
604
  const stagedKibiEvidence = buildStagedKibiImpactEvidence({
605
+ analyzeSource: (filePath) => {
606
+ const result = sourceAnalysis.get(filePath)?.after;
607
+ if (!result)
608
+ throw new Error(`Missing captured source analysis: ${filePath}`);
609
+ return result;
610
+ },
611
+ readBaseFile: (filePath) => {
612
+ try {
613
+ return snapshot
614
+ .readGit(["show", `${snapshot.baseTree}:${filePath}`])
615
+ .toString("utf8");
616
+ }
617
+ catch {
618
+ return null;
619
+ }
620
+ },
518
621
  stagedFiles,
519
622
  sourceFiles,
520
623
  markdownFiles,
@@ -532,7 +635,45 @@ export async function checkCommand(options) {
532
635
  const activeGranularityResults = authoredSymbolResults.filter((result) => activeStagedSymbolEntityIds.has(result.entity.id) ||
533
636
  (result.sourceFile !== undefined &&
534
637
  stagedSourcePaths.has(result.sourceFile)));
638
+ const snapshotSymbolsByFile = new Map();
639
+ for (const result of activeGranularityResults) {
640
+ const file = result.sourceFile;
641
+ if (!file || snapshotSymbolsByFile.has(file))
642
+ continue;
643
+ const existing = sourceAnalysis.get(file)?.after;
644
+ if (existing) {
645
+ snapshotSymbolsByFile.set(file, await extractSymbolsFromStagedFileAsync({
646
+ path: file,
647
+ status: "M",
648
+ content: "",
649
+ hunkRanges: [{ start: 1, end: Number.MAX_SAFE_INTEGER }],
650
+ }, manifestLookup, { analyzeText: async () => existing }));
651
+ continue;
652
+ }
653
+ const entry = snapshot
654
+ .readGit(["ls-tree", snapshot.headTree, "--", `:(literal)${file}`])
655
+ .toString("utf8");
656
+ if (!entry) {
657
+ snapshotSymbolsByFile.set(file, []);
658
+ continue;
659
+ }
660
+ if (!/^100(?:644|755) blob /.test(entry))
661
+ throw new Error(`Snapshot symbol source is not a regular file: ${file}`);
662
+ const content = snapshot
663
+ .readGit(["show", `${snapshot.headTree}:${file}`])
664
+ .toString("utf8");
665
+ sourceContentByFile.set(file, content);
666
+ snapshotSymbolsByFile.set(file, await extractSymbolsFromStagedFileAsync({
667
+ path: file,
668
+ status: "M",
669
+ content,
670
+ hunkRanges: [{ start: 1, end: Number.MAX_SAFE_INTEGER }],
671
+ }, manifestLookup, {
672
+ analyzeText: (name, text) => sourceService.analyzeTextV2(name, text),
673
+ }));
674
+ }
535
675
  stagedKibiDiagnostics.push(...createSymbolGranularityDiagnostics({
676
+ sourceSymbolsByFile: snapshotSymbolsByFile,
536
677
  manifestResults: activeGranularityResults,
537
678
  ...(activeStagedSymbolEntityIds.size > 0
538
679
  ? { activeEntityIds: activeStagedSymbolEntityIds }
@@ -566,12 +707,10 @@ export async function checkCommand(options) {
566
707
  }
567
708
  return { exitCode: blocking ? 1 : 0 };
568
709
  }
569
- printStagedResult({
710
+ printSnapshotResult({
570
711
  format: options.format,
571
712
  coverage: stagedCoverage,
572
- messages: [
573
- "No exported symbols or staged entities found in staged files.",
574
- ],
713
+ messages: [noValidatedSymbolsMessage(sourceAnalysis)],
575
714
  });
576
715
  return { exitCode: 0 };
577
716
  }
@@ -595,7 +734,7 @@ export async function checkCommand(options) {
595
734
  }
596
735
  return { exitCode: blocking ? 1 : 0 };
597
736
  }
598
- printStagedResult({
737
+ printSnapshotResult({
599
738
  format: options.format,
600
739
  coverage: stagedCoverage,
601
740
  messages: ["✓ No violations found in staged files."],
@@ -603,10 +742,8 @@ export async function checkCommand(options) {
603
742
  return { exitCode: 0 };
604
743
  }
605
744
  // Create temp KB
606
- tempCtx = await createTempKb(resolvedKbPath);
607
- if (stagedEntityResults.length > 0) {
608
- await projectStagedEntities(tempCtx.prolog, stagedEntityResults);
609
- }
745
+ tempCtx = await createTempKb();
746
+ await projectStagedEntities(tempCtx.prolog, snapshotEntities);
610
747
  const overlayFacts = createOverlayFacts(allSymbols);
611
748
  const fs = await import("node:fs/promises");
612
749
  await fs.writeFile(tempCtx.overlayPath, overlayFacts, "utf8");
@@ -618,7 +755,7 @@ export async function checkCommand(options) {
618
755
  });
619
756
  const violationsFormatted = formatStagedViolations(violationsRaw);
620
757
  if (violationsRaw && violationsRaw.length > 0) {
621
- printStagedResult({
758
+ printSnapshotResult({
622
759
  format: options.format,
623
760
  coverage: stagedCoverage,
624
761
  violations: violationsRaw,
@@ -639,7 +776,7 @@ export async function checkCommand(options) {
639
776
  if (stagedKibiDiagnostics.length > 0) {
640
777
  await cleanupTempKb(tempCtx.tempDir);
641
778
  const blocking = hasBlockingImpactDiagnostics(stagedKibiDiagnostics);
642
- printStagedResult({
779
+ printSnapshotResult({
643
780
  format: options.format,
644
781
  coverage: stagedCoverage,
645
782
  qualityDiagnostics: stagedKibiDiagnostics,
@@ -660,7 +797,7 @@ export async function checkCommand(options) {
660
797
  exitCode: 1,
661
798
  };
662
799
  }
663
- printStagedResult({
800
+ printSnapshotResult({
664
801
  format: options.format,
665
802
  coverage: stagedCoverage,
666
803
  messages: ["✓ No violations found in staged symbols."],
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAkEA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAGD,wBAAsB,aAAa,CACjC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgG/B;AAED,wBAAsB,4BAA4B,CAChD,IAAI,GAAE,MAAM,OAAO,CAAC;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,CACT,GACxC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;MAkE3C;AAkGD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGzE;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAepB"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AA+EA,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAGD,wBAAsB,aAAa,CACjC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgG/B;AAED,wBAAsB,4BAA4B,CAChD,IAAI,GAAE,MAAM,OAAO,CAAC;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,CACT,GACxC,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;MAkE3C;AAkGD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGzE;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAepB"}
@@ -22,6 +22,7 @@ import * as path from "node:path";
22
22
  import { fileURLToPath } from "node:url";
23
23
  import { bootstrapKibiEnvironment, secretSourceFromBootstrap, } from "../env/bootstrap.js";
24
24
  import { describeConfiguredCapabilityPlugins, readProjectKibiConfig, } from "../plugins/project-config.js";
25
+ import { SwiplResolutionError, inspectSwiplBundle, probeRequiredLibraries, resolveSwipl, } from "../prolog/swipl-resolver.js";
25
26
  import { buildMigrationPlan, migrationAction, } from "../public/operations/migration-plan.js";
26
27
  import { resolveGitRepository, } from "../utils/git-repository-context.js";
27
28
  import { readKbManifestStatus } from "../utils/kb-manifest.js";
@@ -319,45 +320,78 @@ function resolveInstalledPackageInfo(name) {
319
320
  dependencies: undefined,
320
321
  };
321
322
  }
323
+ const SWIPL_SOURCE_LABELS = {
324
+ env: "KIBI_SWIPL",
325
+ bundled: "the bundled build",
326
+ path: "PATH",
327
+ };
328
+ // implements REQ-prolog-doctor-runtime-report
322
329
  function checkSWIProlog() {
330
+ let resolved;
323
331
  try {
324
- const output = execSync("swipl --version", { encoding: "utf-8" });
325
- const versionMatch = output.match(/version\s+(\d+)\.(\d+)/i);
326
- if (!versionMatch) {
327
- return {
328
- passed: false,
329
- message: "Unable to parse version",
330
- remediation: "Reinstall SWI-Prolog from https://www.swi-prolog.org/",
331
- };
332
- }
333
- const majorText = versionMatch[1];
334
- if (!majorText) {
335
- return {
336
- passed: false,
337
- message: "Unable to parse major version",
338
- remediation: "Reinstall SWI-Prolog from https://www.swi-prolog.org/",
339
- };
340
- }
341
- const major = Number.parseInt(majorText, 10);
342
- if (major < 9) {
332
+ resolved = resolveSwipl();
333
+ }
334
+ catch (error) {
335
+ if (!(error instanceof SwiplResolutionError))
336
+ throw error;
337
+ const [headline = error.message, ...guidance] = error.message.split("\n");
338
+ return {
339
+ passed: false,
340
+ message: headline,
341
+ ...(guidance.length === 0 ? {} : { remediation: guidance.join("\n ") }),
342
+ details: {
343
+ code: error.code,
344
+ platform: error.platform,
345
+ ...(error.packageName === undefined
346
+ ? {}
347
+ : { bundledPackage: error.packageName }),
348
+ },
349
+ };
350
+ }
351
+ const details = {
352
+ source: resolved.source,
353
+ path: resolved.bin,
354
+ version: resolved.version,
355
+ ...(resolved.home === undefined ? {} : { home: resolved.home }),
356
+ };
357
+ const summary = `Version ${resolved.version} from ${SWIPL_SOURCE_LABELS[resolved.source]} at ${resolved.bin}`;
358
+ const probe = probeRequiredLibraries(resolved);
359
+ if (probe.kind !== "ok") {
360
+ const remediation = resolved.source === "bundled"
361
+ ? "Reinstall the bundled SWI-Prolog package, or set KIBI_SWIPL=system to use swipl from PATH."
362
+ : "Install a full SWI-Prolog 9.0+ distribution that provides these libraries (for example swi-prolog rather than swi-prolog-nox or a minimal build), or point KIBI_SWIPL at one.";
363
+ if (probe.kind === "missing") {
343
364
  return {
344
365
  passed: false,
345
- message: `Version ${major}.x found (requires ≥9.0)`,
346
- remediation: "Upgrade SWI-Prolog to version 9.0 or higher from https://www.swi-prolog.org/",
366
+ message: `${summary}; cannot load required libraries: ${probe.libraries.join(", ")}`,
367
+ remediation,
368
+ details: { ...details, missingLibraries: probe.libraries },
347
369
  };
348
370
  }
349
- return {
350
- passed: true,
351
- message: `Version ${versionMatch[0]} installed`,
352
- };
353
- }
354
- catch (error) {
355
371
  return {
356
372
  passed: false,
357
- message: "Not installed or not in PATH",
358
- remediation: "Install SWI-Prolog from https://www.swi-prolog.org/ and add to PATH",
373
+ message: `${summary}; the required-library load check could not run (${probe.detail})`,
374
+ remediation,
375
+ details,
359
376
  };
360
377
  }
378
+ let bundleNote = "";
379
+ if (resolved.source === "path") {
380
+ try {
381
+ const bundle = inspectSwiplBundle();
382
+ if (bundle.state === "missing") {
383
+ bundleNote = `; bundled ${bundle.packageName} is not installed (npm install --save-dev ${bundle.packageName})`;
384
+ }
385
+ }
386
+ catch {
387
+ // The bundle note is advisory; never let it fail the check.
388
+ }
389
+ }
390
+ return {
391
+ passed: true,
392
+ message: `${summary}; required libraries load${bundleNote}`,
393
+ details,
394
+ };
361
395
  }
362
396
  /**
363
397
  * Read-only view of package.json plugin activation.
@@ -1 +1 @@
1
- {"version":3,"file":"github-init.d.ts","sourceRoot":"","sources":["../../src/commands/github-init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"github-init.d.ts","sourceRoot":"","sources":["../../src/commands/github-init.ts"],"names":[],"mappings":"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"}
@@ -16,7 +16,7 @@
16
16
  along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
  */
18
18
  import { execFileSync } from "node:child_process";
19
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
19
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync, } from "node:fs";
20
20
  import * as path from "node:path";
21
21
  import { fileURLToPath } from "node:url";
22
22
  const __filename = fileURLToPath(import.meta.url);
@@ -101,9 +101,16 @@ export function hasKibiBadge(content) {
101
101
  return /\[!\[Kibi requirement health\]/i.test(content);
102
102
  }
103
103
  export function detectReadmePath(cwd) {
104
+ let entries;
105
+ try {
106
+ entries = new Set(readdirSync(cwd));
107
+ }
108
+ catch {
109
+ return undefined;
110
+ }
104
111
  for (const name of README_CANDIDATES) {
105
112
  const candidate = path.join(cwd, name);
106
- if (existsSync(candidate)) {
113
+ if (entries.has(name) && existsSync(candidate)) {
107
114
  return candidate;
108
115
  }
109
116
  }
@@ -0,0 +1,31 @@
1
+ import type { CommandResult } from "../cli-command.js";
2
+ export type KbManifestMergeResult = {
3
+ readonly status: "merged";
4
+ readonly content: string;
5
+ } | {
6
+ readonly status: "conflict";
7
+ readonly conflicts: readonly string[];
8
+ };
9
+ /**
10
+ * Three-way merge of an id-keyed Kibi manifest (`.kb/symbols.yaml` or a
11
+ * `.kb/relationships/*.yaml` shard).
12
+ *
13
+ * Both sides usually append new records at the end of the list, which Git
14
+ * reports as a conflict although the additions are independent. This merge
15
+ * keeps every record either side added, applies edits made on only one
16
+ * side, honors a deletion made on one side when the other left the record
17
+ * unchanged, and unions concurrent relationship and link additions on one
18
+ * symbol. Anything else both sides changed differently is a real conflict
19
+ * and is reported rather than guessed.
20
+ */
21
+ export declare function mergeKbManifests(baseContent: string, oursContent: string, theirsContent: string): KbManifestMergeResult;
22
+ /**
23
+ * Git merge driver entry point: `kibi merge-driver %O %A %B`.
24
+ *
25
+ * Writes the merged manifest to the current (`%A`) file and exits 0. On a
26
+ * real conflict it prints each one and falls back to Git's textual merge so
27
+ * the file carries ordinary conflict markers, then exits 1 so Git keeps the
28
+ * path unmerged.
29
+ */
30
+ export declare function mergeDriverCommand(basePath: string, currentPath: string, otherPath: string): Promise<CommandResult>;
31
+ //# sourceMappingURL=merge-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-driver.d.ts","sourceRoot":"","sources":["../../src/commands/merge-driver.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAiBvD,MAAM,MAAM,qBAAqB,GAC7B;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAoI3E;;;;;;;;;;;GAWG;AAEH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,GACpB,qBAAqB,CAyFvB;AAWD;;;;;;;GAOG;AAEH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,CAAC,CA8BxB"}