kibi-cli 2.0.0 → 2.1.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 (217) hide show
  1. package/dist/cli-register-proof.d.ts.map +1 -1
  2. package/dist/cli-register-proof.js +25 -1
  3. package/dist/cli-register-reporting.d.ts.map +1 -1
  4. package/dist/cli-register-reporting.js +6 -0
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +2 -0
  7. package/dist/commands/check-generated.d.ts +7 -0
  8. package/dist/commands/check-generated.d.ts.map +1 -0
  9. package/dist/commands/check-generated.js +192 -0
  10. package/dist/commands/check.d.ts.map +1 -1
  11. package/dist/commands/check.js +3 -2
  12. package/dist/commands/doctor.d.ts.map +1 -1
  13. package/dist/commands/doctor.js +122 -1
  14. package/dist/commands/engine.d.ts.map +1 -1
  15. package/dist/commands/engine.js +3 -1
  16. package/dist/commands/init-helpers.d.ts.map +1 -1
  17. package/dist/commands/init-helpers.js +13 -7
  18. package/dist/commands/proof-explain.d.ts +10 -0
  19. package/dist/commands/proof-explain.d.ts.map +1 -0
  20. package/dist/commands/proof-explain.js +45 -0
  21. package/dist/commands/proof-impact.d.ts +7 -0
  22. package/dist/commands/proof-impact.d.ts.map +1 -0
  23. package/dist/commands/proof-impact.js +39 -0
  24. package/dist/commands/proof-migrate-legacy.js +1 -1
  25. package/dist/commands/proof-prune.js +1 -1
  26. package/dist/commands/prove.js +4 -4
  27. package/dist/commands/report.d.ts.map +1 -1
  28. package/dist/commands/report.js +17 -2
  29. package/dist/commands/sync/manifest.d.ts +1 -0
  30. package/dist/commands/sync/manifest.d.ts.map +1 -1
  31. package/dist/commands/sync/manifest.js +18 -16
  32. package/dist/commands/sync/persistence.d.ts.map +1 -1
  33. package/dist/commands/sync/persistence.js +6 -0
  34. package/dist/engine.d.ts +3 -1
  35. package/dist/engine.d.ts.map +1 -1
  36. package/dist/engine.js +134 -61
  37. package/dist/env/bootstrap.d.ts +84 -0
  38. package/dist/env/bootstrap.d.ts.map +1 -0
  39. package/dist/env/bootstrap.js +310 -0
  40. package/dist/extractors/manifest.d.ts.map +1 -1
  41. package/dist/extractors/manifest.js +1 -1
  42. package/dist/extractors/markdown.d.ts +2 -0
  43. package/dist/extractors/markdown.d.ts.map +1 -1
  44. package/dist/extractors/markdown.js +19 -0
  45. package/dist/extractors/symbols-coordinator.d.ts +8 -0
  46. package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
  47. package/dist/extractors/symbols-coordinator.js +40 -0
  48. package/dist/extractors/symbols-ts.d.ts +8 -19
  49. package/dist/extractors/symbols-ts.d.ts.map +1 -1
  50. package/dist/extractors/symbols-ts.js +33 -503
  51. package/dist/intent-search.d.ts.map +1 -1
  52. package/dist/intent-search.js +4 -5
  53. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  54. package/dist/operations/modeling/model-requirement.js +4 -0
  55. package/dist/operations/modeling/suggest-predicates.d.ts +1 -1
  56. package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
  57. package/dist/operations/modeling/suggest-predicates.js +30 -3
  58. package/dist/operations/mutation/symbol-granularity.d.ts.map +1 -1
  59. package/dist/operations/mutation/symbol-granularity.js +9 -87
  60. package/dist/operations/planning/compile-intent.d.ts +49 -0
  61. package/dist/operations/planning/compile-intent.d.ts.map +1 -1
  62. package/dist/operations/planning/compile-intent.js +63 -3
  63. package/dist/operations/proof/baseline-diff.d.ts +41 -0
  64. package/dist/operations/proof/baseline-diff.d.ts.map +1 -0
  65. package/dist/operations/proof/baseline-diff.js +153 -0
  66. package/dist/operations/proof/explain.d.ts +75 -0
  67. package/dist/operations/proof/explain.d.ts.map +1 -0
  68. package/dist/operations/proof/explain.js +294 -0
  69. package/dist/operations/proof/impact.d.ts +45 -0
  70. package/dist/operations/proof/impact.d.ts.map +1 -0
  71. package/dist/operations/proof/impact.js +118 -0
  72. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  73. package/dist/operations/proof/ingest-proof.js +44 -3
  74. package/dist/operations/proof/migrate-legacy-receipts.d.ts.map +1 -1
  75. package/dist/operations/proof/migrate-legacy-receipts.js +21 -17
  76. package/dist/operations/proof/prune-receipts.js +1 -1
  77. package/dist/operations/proof/receipt-document.js +2 -2
  78. package/dist/operations/semantic-advisor/analysis-receipt.d.ts.map +1 -1
  79. package/dist/operations/semantic-advisor/analysis-receipt.js +3 -9
  80. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  81. package/dist/operations/semantic-advisor/analyze-prose.js +18 -67
  82. package/dist/operations/semantic-advisor/plugin-orchestration.d.ts +63 -0
  83. package/dist/operations/semantic-advisor/plugin-orchestration.d.ts.map +1 -0
  84. package/dist/operations/semantic-advisor/plugin-orchestration.js +489 -0
  85. package/dist/operations/semantic-advisor/predicate-rules-core.d.ts +15 -2
  86. package/dist/operations/semantic-advisor/predicate-rules-core.d.ts.map +1 -1
  87. package/dist/operations/semantic-advisor/predicate-rules-core.js +7 -140
  88. package/dist/operations/semantic-advisor/predicate-rules-launcher.d.ts +11 -12
  89. package/dist/operations/semantic-advisor/predicate-rules-launcher.d.ts.map +1 -1
  90. package/dist/operations/semantic-advisor/predicate-rules-launcher.js +6 -94
  91. package/dist/operations/semantic-advisor/predicate-rules-policy.d.ts +16 -0
  92. package/dist/operations/semantic-advisor/predicate-rules-policy.d.ts.map +1 -1
  93. package/dist/operations/semantic-advisor/predicate-rules-policy.js +7 -150
  94. package/dist/operations/semantic-advisor/predicate-rules-product-tail.d.ts +9 -0
  95. package/dist/operations/semantic-advisor/predicate-rules-product-tail.d.ts.map +1 -1
  96. package/dist/operations/semantic-advisor/predicate-rules-product-tail.js +7 -102
  97. package/dist/operations/semantic-advisor/predicate-rules-product.d.ts +13 -0
  98. package/dist/operations/semantic-advisor/predicate-rules-product.d.ts.map +1 -1
  99. package/dist/operations/semantic-advisor/predicate-rules-product.js +7 -133
  100. package/dist/operations/semantic-advisor/types.d.ts +1 -0
  101. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  102. package/dist/plugins/compose-ontology-packs.d.ts +51 -0
  103. package/dist/plugins/compose-ontology-packs.d.ts.map +1 -0
  104. package/dist/plugins/compose-ontology-packs.js +257 -0
  105. package/dist/plugins/compose-semantic-classifier.d.ts +42 -0
  106. package/dist/plugins/compose-semantic-classifier.d.ts.map +1 -0
  107. package/dist/plugins/compose-semantic-classifier.js +211 -0
  108. package/dist/plugins/external-allowlist.d.ts +10 -0
  109. package/dist/plugins/external-allowlist.d.ts.map +1 -0
  110. package/dist/plugins/external-allowlist.js +16 -0
  111. package/dist/plugins/index.d.ts +9 -0
  112. package/dist/plugins/index.d.ts.map +1 -0
  113. package/dist/plugins/index.js +33 -0
  114. package/dist/plugins/load-plugin.d.ts +19 -0
  115. package/dist/plugins/load-plugin.d.ts.map +1 -0
  116. package/dist/plugins/load-plugin.js +59 -0
  117. package/dist/plugins/project-config.d.ts +28 -0
  118. package/dist/plugins/project-config.d.ts.map +1 -0
  119. package/dist/plugins/project-config.js +90 -0
  120. package/dist/plugins/registry.d.ts +93 -0
  121. package/dist/plugins/registry.d.ts.map +1 -0
  122. package/dist/plugins/registry.js +338 -0
  123. package/dist/plugins/resolve-package.d.ts +47 -0
  124. package/dist/plugins/resolve-package.d.ts.map +1 -0
  125. package/dist/plugins/resolve-package.js +262 -0
  126. package/dist/plugins/source-analysis-service.d.ts +44 -0
  127. package/dist/plugins/source-analysis-service.d.ts.map +1 -0
  128. package/dist/plugins/source-analysis-service.js +232 -0
  129. package/dist/prolog/janitor.d.ts.map +1 -1
  130. package/dist/prolog/janitor.js +1 -1
  131. package/dist/prolog/store-lock.d.ts +1 -1
  132. package/dist/prolog/store-lock.d.ts.map +1 -1
  133. package/dist/proof/inspect.js +1 -1
  134. package/dist/proof/producers/playwright-case-id.js +2 -2
  135. package/dist/proof/producers/playwright-reporter.js +4 -4
  136. package/dist/public/extractors/symbols-coordinator.d.ts +1 -1
  137. package/dist/public/extractors/symbols-coordinator.d.ts.map +1 -1
  138. package/dist/public/extractors/symbols-coordinator.js +1 -1
  139. package/dist/public/impact/analyzer.d.ts +1 -1
  140. package/dist/public/impact/analyzer.d.ts.map +1 -1
  141. package/dist/public/impact/analyzer.js +6 -4
  142. package/dist/public/operations/catalog.d.ts +4 -1
  143. package/dist/public/operations/catalog.d.ts.map +1 -1
  144. package/dist/public/operations/check-executor.js +1 -1
  145. package/dist/public/operations/check-helpers.d.ts +1 -1
  146. package/dist/public/operations/check-helpers.d.ts.map +1 -1
  147. package/dist/public/operations/check-helpers.js +1 -1
  148. package/dist/public/operations/contracts.d.ts.map +1 -1
  149. package/dist/public/operations/contracts.js +35 -12
  150. package/dist/public/operations/discovery-entities.d.ts +12 -0
  151. package/dist/public/operations/discovery-entities.d.ts.map +1 -1
  152. package/dist/public/operations/discovery-entities.js +34 -0
  153. package/dist/public/operations/discovery-executors.d.ts.map +1 -1
  154. package/dist/public/operations/discovery-executors.js +23 -18
  155. package/dist/public/operations/prolog-json.d.ts +1 -1
  156. package/dist/public/operations/prolog-json.d.ts.map +1 -1
  157. package/dist/public/operations/prolog-json.js +7 -7
  158. package/dist/public/operations/runtime-types.d.ts +16 -1
  159. package/dist/public/operations/runtime-types.d.ts.map +1 -1
  160. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  161. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  162. package/dist/public/operations/specs/check-rules.generated.js +2 -1
  163. package/dist/public/operations/specs/check.d.ts +1 -1
  164. package/dist/public/operations/specs/discovery.d.ts +3 -0
  165. package/dist/public/operations/specs/discovery.d.ts.map +1 -1
  166. package/dist/public/operations/specs/discovery.js +3 -0
  167. package/dist/public/operations/specs/proof.js +1 -1
  168. package/dist/public/operations/specs/reporting.d.ts +1 -0
  169. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  170. package/dist/public/operations/specs/reporting.js +2 -2
  171. package/dist/public/operations/specs/semantic.d.ts +1 -1
  172. package/dist/public/operations/specs/semantic.d.ts.map +1 -1
  173. package/dist/public/operations/specs/semantic.js +54 -4
  174. package/dist/public/operations/symbol-repair-plan.d.ts.map +1 -1
  175. package/dist/public/operations/symbol-repair-plan.js +3 -1
  176. package/dist/public/operations/types.d.ts +5 -0
  177. package/dist/public/operations/types.d.ts.map +1 -1
  178. package/dist/public/proof-protocol.js +4 -4
  179. package/dist/public/skills/kibi-usage/SKILL.md +4 -1
  180. package/dist/public/skills/kibi-usage/resources/proof.md +45 -0
  181. package/dist/public/symbol-granularity.d.ts +1 -1
  182. package/dist/public/symbol-granularity.d.ts.map +1 -1
  183. package/dist/public/symbol-granularity.generated.d.ts.map +1 -1
  184. package/dist/public/symbol-granularity.generated.js +38 -5
  185. package/dist/report/html-report.css +1239 -281
  186. package/dist/runtime/cli-runtime.d.ts.map +1 -1
  187. package/dist/runtime/cli-runtime.js +18 -0
  188. package/dist/traceability/symbol-extract.d.ts +24 -7
  189. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  190. package/dist/traceability/symbol-extract.js +64 -208
  191. package/dist/utils/rule-registry.generated.d.ts +5 -0
  192. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  193. package/dist/utils/rule-registry.generated.js +6 -0
  194. package/package.json +14 -11
  195. package/src/public/extractors/symbols-coordinator.ts +1 -0
  196. package/src/public/impact/analyzer.ts +15 -12
  197. package/src/public/operations/check-executor.ts +1 -1
  198. package/src/public/operations/check-helpers.ts +2 -2
  199. package/src/public/operations/contracts.ts +40 -12
  200. package/src/public/operations/discovery-entities.ts +46 -0
  201. package/src/public/operations/discovery-executors.ts +39 -26
  202. package/src/public/operations/prolog-json.ts +13 -5
  203. package/src/public/operations/runtime-types.ts +21 -2
  204. package/src/public/operations/specs/check-rules.generated.ts +2 -1
  205. package/src/public/operations/specs/discovery.ts +3 -0
  206. package/src/public/operations/specs/proof.ts +1 -1
  207. package/src/public/operations/specs/reporting.ts +2 -2
  208. package/src/public/operations/specs/semantic.ts +79 -17
  209. package/src/public/operations/symbol-repair-plan.ts +3 -4
  210. package/src/public/operations/types.ts +5 -0
  211. package/src/public/proof-fingerprint.ts +1 -1
  212. package/src/public/proof-protocol-types.d.ts +1 -1
  213. package/src/public/proof-protocol.ts +4 -4
  214. package/src/public/skills/kibi-usage/SKILL.md +4 -1
  215. package/src/public/skills/kibi-usage/resources/proof.md +45 -0
  216. package/src/public/symbol-granularity.generated.ts +45 -12
  217. package/src/public/symbol-granularity.ts +3 -3
@@ -33,6 +33,25 @@ function objectData(
33
33
  };
34
34
  }
35
35
 
36
+ /**
37
+ * kibi.job.v1 receipt returned by async-mode operations (kb_check with
38
+ * `async: true`) instead of the synchronous payload. Agents poll
39
+ * kb_job_status with the jobId. Declared as a union member of the operation
40
+ * data contract so hosts validating tool output against the declared schema
41
+ * accept the receipt without weakening the synchronous payload contract.
42
+ */
43
+ const jobReceiptData: OperationJsonSchema = objectData(
44
+ {
45
+ kibiProtocol: { const: 1 },
46
+ jobVersion: { const: "kibi.job.v1" },
47
+ jobId: { type: "string" },
48
+ tool: { type: "string" },
49
+ status: { type: "string" },
50
+ pollWith: { const: "kb_job_status" },
51
+ },
52
+ ["kibiProtocol", "jobVersion", "jobId", "tool", "status", "pollWith"],
53
+ );
54
+
36
55
  const stringValue: OperationJsonSchema = { type: "string" };
37
56
  const integerValue: OperationJsonSchema = { type: "integer" };
38
57
  const numberValue: OperationJsonSchema = { type: "number" };
@@ -135,6 +154,7 @@ export const OPERATION_DATA_SCHEMAS: Readonly<
135
154
  kb_semantic_advisor: objectData({
136
155
  receipt: recordValue,
137
156
  warnings: stringArray,
157
+ capabilityPlugins: recordValue,
138
158
  }),
139
159
  kb_model_requirement: objectData({
140
160
  statement: stringValue,
@@ -240,18 +260,25 @@ export const OPERATION_DATA_SCHEMAS: Readonly<
240
260
  effectFailures: recordArray,
241
261
  nextActions: recordArray,
242
262
  }),
243
- kb_check: objectData({
244
- violations: valueArray,
245
- count: integerValue,
246
- diagnostics: recordArray,
247
- qualityDiagnostics: recordArray,
248
- impactDiagnostics: recordArray,
249
- sourceFiles: stringArray,
250
- extractedSymbols: recordArray,
251
- linkedEntities: recordArray,
252
- nextActions: valueArray,
253
- migrationPlan: recordValue,
254
- }),
263
+ kb_check: {
264
+ description:
265
+ "Synchronous check payload, or a kibi.job.v1 receipt when async:true detached the check into a background job (poll kb_job_status with the jobId).",
266
+ anyOf: [
267
+ objectData({
268
+ violations: valueArray,
269
+ count: integerValue,
270
+ diagnostics: recordArray,
271
+ qualityDiagnostics: recordArray,
272
+ impactDiagnostics: recordArray,
273
+ sourceFiles: stringArray,
274
+ extractedSymbols: recordArray,
275
+ linkedEntities: recordArray,
276
+ nextActions: valueArray,
277
+ migrationPlan: recordValue,
278
+ }),
279
+ jobReceiptData,
280
+ ],
281
+ },
255
282
  kb_compile_intent: objectData({
256
283
  version: stringValue,
257
284
  planHash: stringValue,
@@ -265,6 +292,7 @@ export const OPERATION_DATA_SCHEMAS: Readonly<
265
292
  steps: valueArray,
266
293
  sourceWrites: recordArray,
267
294
  diagnostics: stringArray,
295
+ capabilityPlugins: recordValue,
268
296
  }),
269
297
  kb_apply_plan: objectData({
270
298
  version: stringValue,
@@ -116,6 +116,52 @@ export function paginateResults<T>(
116
116
  return results.slice(offset, offset + limit);
117
117
  }
118
118
 
119
+ /**
120
+ * Page size for index-backed search candidate fetches. Each page is one
121
+ * Prolog query, so a fixed page size substantially bounds each response and
122
+ * fixes the observed large-KB output overflow; it is a practical bound, not
123
+ * a byte-size guarantee for arbitrarily large individual entity payloads.
124
+ */
125
+ // implements REQ-kibi-operation-interface-parity, REQ-mcp-search-discovery
126
+ export const SEARCH_CANDIDATE_PAGE_SIZE = 500;
127
+
128
+ // implements REQ-kibi-operation-interface-parity, REQ-mcp-search-discovery
129
+ export async function loadSearchCandidates(
130
+ prolog: Pick<PrologPort, "searchEntities">,
131
+ input: {
132
+ readonly query: string;
133
+ readonly type?: string;
134
+ readonly maxCandidates?: number;
135
+ },
136
+ signal?: AbortSignal,
137
+ ): Promise<Record<string, unknown>[]> {
138
+ const maxCandidates = input.maxCandidates ?? Number.POSITIVE_INFINITY;
139
+ const candidates: Record<string, unknown>[] = [];
140
+ let offset = 0;
141
+ let total = Number.POSITIVE_INFINITY;
142
+ while (offset < total && candidates.length < maxCandidates) {
143
+ // Call through the port property, never via a detached local: EngineClient
144
+ // searchEntities depends on `this` (this.command), and the PrologPort
145
+ // contract does not promise a pre-bound method.
146
+ const page = await prolog.searchEntities?.(
147
+ {
148
+ query: input.query,
149
+ ...(input.type !== undefined ? { type: input.type } : {}),
150
+ limit: SEARCH_CANDIDATE_PAGE_SIZE,
151
+ offset,
152
+ },
153
+ signal,
154
+ );
155
+ if (!page || page.entities.length === 0) break;
156
+ candidates.push(...page.entities);
157
+ total = page.count;
158
+ offset += page.entities.length;
159
+ }
160
+ return Number.isFinite(maxCandidates)
161
+ ? candidates.slice(0, maxCandidates)
162
+ : candidates;
163
+ }
164
+
119
165
  // implements REQ-002
120
166
  export function dedupeEntities(
121
167
  entities: readonly Record<string, unknown>[],
@@ -14,11 +14,12 @@ import { resolveBranchAttachment } from "../../utils/branch-resolver.js";
14
14
  import {
15
15
  type BranchStoreInspection,
16
16
  branchStoreReason,
17
- storeLockJournalReason,
18
17
  inspectBranchStore,
18
+ storeLockJournalReason,
19
19
  } from "../../utils/branch-store.js";
20
20
  import {
21
21
  loadEntities,
22
+ loadSearchCandidates,
22
23
  paginateResults,
23
24
  validateEntityType,
24
25
  } from "./discovery-entities.js";
@@ -140,15 +141,19 @@ export async function executeQuery(
140
141
  const { type, id, tags, sourceFile, limit = 100, offset = 0 } = input;
141
142
  try {
142
143
  const prolog = requireProlog(context);
144
+ const signal = context.signal;
143
145
  const indexedPage = prolog.queryEntities
144
- ? await prolog.queryEntities({
145
- ...(type !== undefined ? { type } : {}),
146
- ...(id !== undefined ? { id } : {}),
147
- ...(tags !== undefined ? { tags } : {}),
148
- ...(sourceFile !== undefined ? { sourceFile } : {}),
149
- limit,
150
- offset,
151
- })
146
+ ? await prolog.queryEntities(
147
+ {
148
+ ...(type !== undefined ? { type } : {}),
149
+ ...(id !== undefined ? { id } : {}),
150
+ ...(tags !== undefined ? { tags } : {}),
151
+ ...(sourceFile !== undefined ? { sourceFile } : {}),
152
+ limit,
153
+ offset,
154
+ },
155
+ signal,
156
+ )
152
157
  : null;
153
158
  if (indexedPage !== null) {
154
159
  const paginated = indexedPage.entities;
@@ -260,15 +265,17 @@ export async function executeSearch(
260
265
  };
261
266
  }
262
267
  const indexedCandidates = prolog.searchEntities
263
- ? await prolog.searchEntities({
264
- query: trimmedQuery,
265
- ...(type !== undefined ? { type } : {}),
266
- limit: 100_000,
267
- offset: 0,
268
- })
268
+ ? await loadSearchCandidates(
269
+ prolog,
270
+ {
271
+ query: trimmedQuery,
272
+ ...(type !== undefined ? { type } : {}),
273
+ },
274
+ context.signal,
275
+ )
269
276
  : null;
270
277
  const entities = indexedCandidates
271
- ? [...indexedCandidates.entities]
278
+ ? [...indexedCandidates]
272
279
  : await loadEntities(prolog, {
273
280
  ...(type !== undefined ? { type } : {}),
274
281
  });
@@ -335,21 +342,27 @@ export async function executeStatus(
335
342
  };
336
343
  } else
337
344
  try {
338
- const prolog =
339
- context.prolog ??
340
- (() => {
341
- ownedEngine = new EngineClient({
342
- workspaceRoot: context.workspaceRoot,
343
- branch: attachment.kbBranch,
344
- timeout: 15_000,
345
- });
346
- return ownedEngine;
347
- })();
345
+ // Prefer an injected or session-backed engine so MCP status shares the
346
+ // same client as discovery tools. Only spawn an owned fallback when no
347
+ // host session is available (CLI status without a live runtime port).
348
+ let prolog = context.prolog;
349
+ if (!prolog && context.ensureProlog) {
350
+ prolog = await context.ensureProlog();
351
+ }
352
+ if (!prolog) {
353
+ ownedEngine = new EngineClient({
354
+ workspaceRoot: context.workspaceRoot,
355
+ branch: attachment.kbBranch,
356
+ timeout: 15_000,
357
+ });
358
+ prolog = ownedEngine;
359
+ }
348
360
  payload = await runOperationJsonQuery<StatusPayload>(
349
361
  prolog,
350
362
  "status.pl",
351
363
  "status:kb_status_json(JsonString)",
352
364
  "Status execution",
365
+ context.signal,
353
366
  );
354
367
  if (!isStatusPayload(payload)) {
355
368
  throw new Error("Status execution query returned an invalid payload");
@@ -55,6 +55,7 @@ export async function runOperationJsonQuery<T>(
55
55
  fileName: string,
56
56
  goal: string,
57
57
  errorLabel: string,
58
+ signal?: AbortSignal,
58
59
  ): Promise<T> {
59
60
  const modulePath = escapeAtom(
60
61
  resolveCoreModulePath(fileName).replaceAll("\\", "/"),
@@ -73,10 +74,16 @@ export async function runOperationJsonQuery<T>(
73
74
  const typedStatusQuery = prolog.queryStatusJson;
74
75
  const result =
75
76
  fileName === "status.pl" && typeof typedStatusQuery === "function"
76
- ? await typedStatusQuery.call(prolog)
77
+ ? await typedStatusQuery.call(prolog, signal)
77
78
  : oneShotMode
78
- ? await prolog.query(`(use_module('${modulePath}'), ${goal})`)
79
- : await runInteractiveModuleQuery(prolog, modulePath, goal, errorLabel);
79
+ ? await prolog.query(`(use_module('${modulePath}'), ${goal})`, signal)
80
+ : await runInteractiveModuleQuery(
81
+ prolog,
82
+ modulePath,
83
+ goal,
84
+ errorLabel,
85
+ signal,
86
+ );
80
87
  if (!result.success) {
81
88
  throw new Error(
82
89
  `${errorLabel} query failed: ${result.error ?? "Unknown error"}`,
@@ -115,14 +122,15 @@ async function runInteractiveModuleQuery(
115
122
  modulePath: string,
116
123
  goal: string,
117
124
  errorLabel: string,
125
+ signal?: AbortSignal,
118
126
  ) {
119
- const loadResult = await prolog.query(`use_module('${modulePath}')`);
127
+ const loadResult = await prolog.query(`use_module('${modulePath}')`, signal);
120
128
  if (!loadResult.success) {
121
129
  throw new Error(
122
130
  `${errorLabel} module load failed: ${loadResult.error ?? "Unknown error"}`,
123
131
  );
124
132
  }
125
- return prolog.query(goal);
133
+ return prolog.query(goal, signal);
126
134
  }
127
135
 
128
136
  export function toPrologAtom(value?: string): string {
@@ -1,8 +1,17 @@
1
+ import type { CapabilityRegistry } from "../../plugins/registry.js";
1
2
  import type { PrologErrorRecord } from "../../prolog/error-terms.js";
2
3
  import type { BranchAttachment } from "../../utils/branch-resolver.js";
3
4
  import type { OperationEffect } from "./types.js";
4
5
 
5
6
  export type { OperationEffect } from "./types.js";
7
+ // implements REQ-capability-plugin-activation-disclosure-v1
8
+ export type { CapabilityRegistry } from "../../plugins/registry.js";
9
+
10
+ /** Lazy or pre-materialized capability-plugin registry for an operation. */
11
+ // implements REQ-capability-plugin-activation-disclosure-v1
12
+ export type OperationPlugins =
13
+ | CapabilityRegistry
14
+ | (() => Promise<CapabilityRegistry>);
6
15
 
7
16
  export type PrologQueryResult = {
8
17
  readonly success: boolean;
@@ -115,7 +124,7 @@ export interface PrologPort {
115
124
  /** Present on the journaled engine; used to distinguish a persistent port from one-shot SWI. */
116
125
  storageStatus?(): Promise<PrologQueryResult>;
117
126
  /** Typed public freshness query; avoids exposing module loading over RPC. */
118
- queryStatusJson?(): Promise<PrologQueryResult>;
127
+ queryStatusJson?(signal?: AbortSignal): Promise<PrologQueryResult>;
119
128
  }
120
129
 
121
130
  export type FilesystemStat = {
@@ -175,6 +184,8 @@ export type RuntimeOptions = {
175
184
  readonly fs?: FilesystemPort;
176
185
  readonly git?: GitPort;
177
186
  readonly net?: NetworkPort;
187
+ /** Optional injectable capability registry (or lazy factory). */
188
+ readonly plugins?: OperationPlugins;
178
189
  };
179
190
 
180
191
  export type OperationContext = {
@@ -195,12 +206,20 @@ export type OperationContext = {
195
206
  readonly git?: GitPort;
196
207
  readonly net?: NetworkPort;
197
208
  readonly branchAttachment?: BranchAttachment;
209
+ /** Pre-materialized or lazy capability registry supplied by the host runtime. */
210
+ readonly plugins?: OperationPlugins;
211
+ /** Lazily materialize the workspace capability registry. */
212
+ readonly ensurePlugins?: () => Promise<CapabilityRegistry>;
198
213
  };
199
-
200
214
  export interface RuntimeOperationSpec<TInput = unknown, TResult = unknown> {
201
215
  readonly name: string;
202
216
  readonly effects: readonly OperationEffect[];
203
217
  readonly requiresProlog: boolean;
218
+ /**
219
+ * When true, MCP embeds envelope `data` JSON in tool `content` for hosts that
220
+ * hide `structuredContent` (discovery/proof lookup). Default false.
221
+ */
222
+ readonly agentVisibleStructuredData?: boolean;
204
223
  execute(input: TInput, context: OperationContext): Promise<TResult>;
205
224
  }
206
225
 
@@ -29,9 +29,10 @@ export const SELECTABLE_RULE_NAMES: readonly string[] = [
29
29
  "predicate-verifiability",
30
30
  "strict-readiness",
31
31
  "semantic-completeness",
32
+ "proof-contract-symbols",
32
33
  ];
33
34
 
34
35
  // implements REQ-006
35
36
  /** Comma-separated "Allowed:" fragment for the kb_check rules description. */
36
37
  export const SELECTABLE_RULES_ALLOWED =
37
- "must-priority-coverage, symbol-coverage, symbol-traceability, no-dangling-refs, source-relationship-parity, no-cycles, required-fields, deprecated-adr-no-successor, domain-contradictions, logic-coverage, rule-safety, rule-verifiability, query-plan-safety, req-status-vocabulary, strict-fact-shape, strict-req-fact-pairing, predicate-verifiability, strict-readiness, semantic-completeness";
38
+ "must-priority-coverage, symbol-coverage, symbol-traceability, no-dangling-refs, source-relationship-parity, no-cycles, required-fields, deprecated-adr-no-successor, domain-contradictions, logic-coverage, rule-safety, rule-verifiability, query-plan-safety, req-status-vocabulary, strict-fact-shape, strict-req-fact-pairing, predicate-verifiability, strict-readiness, semantic-completeness, proof-contract-symbols";
@@ -70,6 +70,7 @@ export const querySpec = {
70
70
  },
71
71
  requiresProlog: true,
72
72
  effects: ["kb-read"],
73
+ agentVisibleStructuredData: true,
73
74
  execute: executeQuery,
74
75
  } as const satisfies OperationSpec<QueryInput, QueryPayload>;
75
76
 
@@ -164,6 +165,7 @@ export const searchSpec = {
164
165
  },
165
166
  requiresProlog: true,
166
167
  effects: ["kb-read"],
168
+ agentVisibleStructuredData: true,
167
169
  execute: executeSearch,
168
170
  } as const satisfies OperationSpec<SearchInput, SearchPayload>;
169
171
 
@@ -176,5 +178,6 @@ export const statusSpec = {
176
178
  // Status must remain available when the branch store cannot be attached.
177
179
  requiresProlog: false,
178
180
  effects: ["kb-read", "workspace-read"],
181
+ agentVisibleStructuredData: true,
179
182
  execute: executeStatus,
180
183
  } as const satisfies OperationSpec<StatusInput, StatusPayload>;
@@ -12,7 +12,7 @@ export type {
12
12
  } from "../../../operations/proof/ingest-proof.js";
13
13
  export { executeIngestProof } from "../../../operations/proof/ingest-proof.js";
14
14
 
15
- // implements REQ-kibi-proof-evidence-protocol
15
+ // implements REQ-kibi-verification-evidence-contract
16
16
  export const ingestProofSpec = {
17
17
  name: "kb_ingest_proof",
18
18
  cliName: "ingest-proof",
@@ -193,14 +193,14 @@ export const findGapsSpec = {
193
193
  * KIBI_PROOF_BINDING_MODE=strict-snapshot opts out (receipts then match only
194
194
  * against the whole-workspace snapshot they were proven on).
195
195
  */
196
- // implements REQ-kibi-proof-evidence-protocol
196
+ // implements REQ-kibi-verification-evidence-contract
197
197
  export function currentProofBindingMode(): "per_contract" | "strict_snapshot" {
198
198
  return process.env.KIBI_PROOF_BINDING_MODE?.trim() === "strict-snapshot"
199
199
  ? "strict_snapshot"
200
200
  : "per_contract";
201
201
  }
202
202
 
203
- async function perContractTestBindings(
203
+ export async function perContractTestBindings(
204
204
  context: OperationContext,
205
205
  ): Promise<string | null> {
206
206
  if (currentProofBindingMode() !== "per_contract") return null;
@@ -1,9 +1,10 @@
1
1
  import { InputError } from "../../../cli-errors.js";
2
- import { analyzeSemanticAdvisorInput } from "../../../operations/semantic-advisor/analyze-prose.js";
2
+ import { analyzeSemanticAdvisorInputWithPlugins } from "../../../operations/semantic-advisor/plugin-orchestration.js";
3
3
  import type {
4
4
  SemanticAdvisorArgs,
5
5
  SemanticAdvisorOperationResult,
6
6
  } from "../../../operations/semantic-advisor/types.js";
7
+ import { publicCapabilityStamp } from "../../../plugins/compose-semantic-classifier.js";
7
8
  import type { OperationContext } from "../runtime-types.js";
8
9
  import type { OperationSpec } from "../types.js";
9
10
 
@@ -25,28 +26,85 @@ function optionalString(value: unknown): string | undefined {
25
26
 
26
27
  export async function executeSemanticAdvisor(
27
28
  args: SemanticAdvisorArgs,
28
- _context?: OperationContext,
29
+ context?: OperationContext,
29
30
  ): Promise<SemanticAdvisorOperationResult> {
30
31
  const text = requiredText(args.text);
31
32
  const id = optionalString(args.id) ?? "REQ-SEMANTIC-ADVISOR-PREVIEW";
32
33
  const title = optionalString(args.title) ?? text.split(/[.!?]/, 1)[0] ?? text;
33
34
  const source = optionalString(args.source) ?? "mcp://kibi/semantic-advisor";
34
- const result = analyzeSemanticAdvisorInput({
35
- payload: {
36
- type: optionalString(args.type) ?? "req",
37
- id,
38
- properties: {
39
- title,
40
- status: optionalString(args.status) ?? "open",
41
- source,
42
- semantic_text: text,
35
+ const orchestrated = await analyzeSemanticAdvisorInputWithPlugins(
36
+ {
37
+ payload: {
38
+ type: optionalString(args.type) ?? "req",
39
+ id,
40
+ properties: {
41
+ title,
42
+ status: optionalString(args.status) ?? "open",
43
+ source,
44
+ semantic_text: text,
45
+ },
43
46
  },
47
+ ...(args.clauses !== undefined ? { clauses: args.clauses } : {}),
48
+ ...(args.interpretations !== undefined
49
+ ? { interpretations: args.interpretations }
50
+ : {}),
51
+ },
52
+ {
53
+ operationName: "kb_semantic_advisor",
54
+ ...(context?.ensurePlugins
55
+ ? { ensurePlugins: context.ensurePlugins }
56
+ : {}),
44
57
  },
45
- ...(args.clauses !== undefined ? { clauses: args.clauses } : {}),
46
- ...(args.interpretations !== undefined
47
- ? { interpretations: args.interpretations }
48
- : {}),
49
- });
58
+ );
59
+ const result = orchestrated.analysis;
60
+ const pluginWarnings =
61
+ orchestrated.stamps.length > 0
62
+ ? [
63
+ `Capability plugins consulted: ${orchestrated.stamps
64
+ .map((stamp) => `${stamp.pluginId}/${stamp.capability}`)
65
+ .join(", ")}.`,
66
+ ]
67
+ : [];
68
+ const capabilityPlugins =
69
+ orchestrated.stamps.length > 0 ||
70
+ (orchestrated.classification?.shadowComparisons.length ?? 0) > 0 ||
71
+ orchestrated.ontologyShadowMatches.length > 0
72
+ ? {
73
+ stamps: orchestrated.stamps.map((stamp) =>
74
+ publicCapabilityStamp(stamp),
75
+ ),
76
+ classification: orchestrated.classification
77
+ ? {
78
+ fallbackUsed: orchestrated.classification.fallbackUsed,
79
+ decisions: orchestrated.classification.decisions,
80
+ shadowComparisons:
81
+ orchestrated.classification.shadowComparisons.map(
82
+ (comparison) => ({
83
+ ...publicCapabilityStamp(comparison.stamp),
84
+ decisions: comparison.decisions.map((decision) => ({
85
+ claimKey: decision.claimKey,
86
+ lane: decision.lane,
87
+ confidence: decision.confidence,
88
+ })),
89
+ }),
90
+ ),
91
+ }
92
+ : null,
93
+ ontology: {
94
+ replaced: orchestrated.ontologyCatalog?.replaced ?? false,
95
+ matchCount: orchestrated.ontologyMatches.length,
96
+ shadowMatchCount: orchestrated.ontologyShadowMatches.length,
97
+ shadowMatches: orchestrated.ontologyShadowMatches.map(
98
+ (candidate) => ({
99
+ packId: candidate.packId,
100
+ schemaId: candidate.schemaId,
101
+ predicateName: candidate.predicateName,
102
+ confidence: candidate.confidence,
103
+ }),
104
+ ),
105
+ },
106
+ }
107
+ : undefined;
50
108
  return {
51
109
  content: [
52
110
  {
@@ -54,7 +112,11 @@ export async function executeSemanticAdvisor(
54
112
  text: `kb_semantic_advisor: ${result.receipt.summary} Suggestions: ${result.receipt.suggestions.map(({ kind }) => kind).join(", ") || "none"}.`,
55
113
  },
56
114
  ],
57
- structuredContent: { receipt: result.receipt, warnings: result.warnings },
115
+ structuredContent: {
116
+ receipt: result.receipt,
117
+ warnings: [...result.warnings, ...pluginWarnings],
118
+ ...(capabilityPlugins ? { capabilityPlugins } : {}),
119
+ },
58
120
  };
59
121
  }
60
122
 
@@ -240,10 +240,9 @@ export async function buildSymbolRepairPlan(
240
240
  : path.resolve(context.workspaceRoot, source);
241
241
  if (!existsSync(absolute)) continue;
242
242
  try {
243
- const analysis = analyzeSourceText(
244
- absolute,
245
- readFileSync(absolute, "utf8"),
246
- );
243
+ const content = readFileSync(absolute, "utf8");
244
+ // Coverage/impact is a maintenance path: never import project plugins.
245
+ const analysis = analyzeSourceText(absolute, content);
247
246
  if (analysis.providerId === null) continue;
248
247
  extractedByPath.set(
249
248
  source,
@@ -93,6 +93,11 @@ export interface OperationSpec<
93
93
  readonly businessInputSchema: Readonly<Record<string, unknown>>;
94
94
  readonly requiresProlog: boolean;
95
95
  readonly effects: readonly OperationEffect[];
96
+ /**
97
+ * When true, MCP duplicates envelope `data` into tool `content` text so hosts
98
+ * that hide `structuredContent` still expose discovery/proof payloads.
99
+ */
100
+ readonly agentVisibleStructuredData?: boolean;
96
101
  /** Generated effect metadata used by MCP annotations and telemetry. */
97
102
  readonly declaredEffects?: readonly OperationEffectDeclaration[];
98
103
  /** Version of the machine-readable result data for this operation. */
@@ -71,7 +71,7 @@ export function proofContractHash(contract: ProofContract): string {
71
71
  * workspace state changes, and goes stale the moment the test's own contract
72
72
  * or document does. Callers pass the receipt-stripped document content.
73
73
  */
74
- // implements REQ-kibi-proof-evidence-protocol
74
+ // implements REQ-kibi-verification-evidence-contract
75
75
  export interface ReceiptCodeScopeEntry {
76
76
  readonly symbolId: string;
77
77
  readonly sourceHash: string;
@@ -1,4 +1,4 @@
1
- // implements REQ-kibi-proof-evidence-protocol
1
+ // implements REQ-kibi-verification-evidence-contract
2
2
  export type ProofRunOutcome =
3
3
  | "passed"
4
4
  | "failed"
@@ -1,10 +1,10 @@
1
- // implements REQ-kibi-proof-evidence-protocol
1
+ // implements REQ-kibi-verification-evidence-contract
2
2
  export const PROOF_RUN_VERSION = "kibi.proof-run.v1" as const;
3
- // implements REQ-kibi-proof-evidence-protocol
3
+ // implements REQ-kibi-verification-evidence-contract
4
4
  export const PROOF_CONTRACT_VERSION = "kibi.proof-contract.v1" as const;
5
- // implements REQ-kibi-proof-evidence-protocol
5
+ // implements REQ-kibi-verification-evidence-contract
6
6
  export const PROOF_RECEIPT_VERSION = "kibi.proof-receipt.v1" as const;
7
- // implements REQ-kibi-proof-evidence-protocol
7
+ // implements REQ-kibi-verification-evidence-contract
8
8
  export const PROOF_INTEGRATION_VERSION = "kibi.proof-integration.v1" as const;
9
9
 
10
10
  export const PROOF_RUN_OUTCOMES = [
@@ -2,7 +2,7 @@
2
2
  id: kibi-usage
3
3
  name: Kibi Usage
4
4
  description: Use Kibi's source-first, exact-Git, migration-aware, proof-aware operations safely across MCP or the trusted local CLI, including partial completion repair.
5
- version: 2.1.2
5
+ version: 2.1.3
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -133,6 +133,9 @@ safe normative claims; use `observation` or `meta` for bug/workaround notes and
133
133
  tests, symbol ownership, and fresh proof-bearing receipts before claiming proof.
134
134
  For an existing product KB that needs semantic backfill, read
135
135
  `resources/kb-improvement.md`, and `resources/proof.md` for the proof workflow.
136
+ When a proof ratchet fails, follow Debugging proof regressions in
137
+ `resources/proof.md`: use `kibi proof explain` and compare current proof state
138
+ to committed `proof/baseline.json` with `kibi proof impact`.
136
139
 
137
140
  ## Predicate Ontology Decision Tree
138
141
 
@@ -103,3 +103,48 @@ re-run `kibi prove` for the affected selection, then confirm `kb_status` and
103
103
  `kb_coverage` before handoff.
104
104
 
105
105
  Full reference: `docs/proving-requirements.md`.
106
+
107
+ ## Debugging proof regressions
108
+
109
+ When a proof ratchet fails, diagnose first. Do not treat
110
+ `proof/baseline.json` as the thing to edit.
111
+
112
+ 1. Do not refresh `proof/baseline.json` as the first fix.
113
+ 2. Identify the exact requirement and symbol responsible for the regression.
114
+ 3. Use Kibi proof diagnostics rather than reverse-engineering
115
+ `requirement_proof.pl`:
116
+
117
+ ```bash
118
+ kibi proof explain REQ-<id>
119
+ kibi proof explain SYM-<id>
120
+ kibi proof impact
121
+ ```
122
+
123
+ `kibi proof impact` compares the current Proof projection to
124
+ `HEAD:proof/baseline.json` (the committed ratchet snapshot, not the
125
+ working-tree file). It is diagnostic: fingerprint differences are reported
126
+ and the command exits 0 on successful evaluation. The strict ratchet remains
127
+ `scripts/check-proof-baseline.mjs`.
128
+ 4. For `missing_production_symbol_coverage`, inspect symbol role, owning
129
+ requirement, `covered_by`, candidate test scope, the requirement scenario
130
+ chain, and the current proof receipt. `kibi proof explain` prints those as
131
+ three labeled blocks so they cannot be confused:
132
+ `required_proofs` (TEST contract obligations), `executable_for` (test-code
133
+ identity), and `covered_by` (production coverage candidates with primary
134
+ plus optional secondary reasons).
135
+ 5. A behavioral production symbol requires qualifying behavioral/E2E evidence
136
+ under the current proof model.
137
+ 6. Unit coverage can satisfy structural/type-shape requirements only when the
138
+ symbol genuinely represents structural shape and the proof model allows it.
139
+ 7. `executable_for` identifies executable test code. Never use it on
140
+ production helpers merely to remove production coverage obligations.
141
+ 8. Do not trust TEST names. Resolve
142
+ `TEST -> proof_contract.required_proofs -> SYM -> source` and inspect what
143
+ the executable test actually exercises. Kibi does not infer “this TEST name
144
+ does not match that source file.”
145
+ 9. A passing proof producer does not automatically make every authored
146
+ `covered_by` relationship semantically correct.
147
+ 10. Prefer one meaningful E2E scenario covering multiple internal functions
148
+ plus focused unit tests for edge cases, rather than an E2E test per helper.
149
+ 11. Refresh the baseline only after a genuine intentional proof-state
150
+ improvement requires the ratchet snapshot to be updated.