kibi-cli 2.38.0 → 2.40.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 (222) hide show
  1. package/dist/cli-json-command.d.ts.map +1 -1
  2. package/dist/cli-json-command.js +4 -0
  3. package/dist/cli-register-foundation.js +2 -2
  4. package/dist/cli-register-reporting.d.ts.map +1 -1
  5. package/dist/cli-register-reporting.js +1 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +3 -0
  8. package/dist/commands/check.d.ts.map +1 -1
  9. package/dist/commands/check.js +33 -9
  10. package/dist/commands/coverage.d.ts +1 -0
  11. package/dist/commands/coverage.d.ts.map +1 -1
  12. package/dist/commands/coverage.js +40 -0
  13. package/dist/commands/doctor.d.ts +5 -0
  14. package/dist/commands/doctor.d.ts.map +1 -1
  15. package/dist/commands/doctor.js +29 -0
  16. package/dist/commands/init.d.ts.map +1 -1
  17. package/dist/commands/init.js +4 -0
  18. package/dist/commands/migrate-plan-record.d.ts +18 -0
  19. package/dist/commands/migrate-plan-record.d.ts.map +1 -0
  20. package/dist/commands/migrate-plan-record.js +112 -0
  21. package/dist/commands/migrate.d.ts +11 -2
  22. package/dist/commands/migrate.d.ts.map +1 -1
  23. package/dist/commands/migrate.js +60 -8
  24. package/dist/commands/prove.d.ts.map +1 -1
  25. package/dist/commands/prove.js +18 -3
  26. package/dist/commands/sync/manifest.d.ts.map +1 -1
  27. package/dist/commands/sync/manifest.js +17 -4
  28. package/dist/commands/sync/persistence.d.ts.map +1 -1
  29. package/dist/commands/sync/persistence.js +6 -0
  30. package/dist/commands/sync.d.ts.map +1 -1
  31. package/dist/commands/sync.js +8 -0
  32. package/dist/commands/telemetry.d.ts.map +1 -1
  33. package/dist/commands/telemetry.js +12 -2
  34. package/dist/extractors/markdown.d.ts +6 -0
  35. package/dist/extractors/markdown.d.ts.map +1 -1
  36. package/dist/extractors/markdown.js +21 -0
  37. package/dist/extractors/symbol-title-match.d.ts +31 -0
  38. package/dist/extractors/symbol-title-match.d.ts.map +1 -0
  39. package/dist/extractors/symbol-title-match.js +133 -0
  40. package/dist/extractors/symbols-coordinator.d.ts.map +1 -1
  41. package/dist/extractors/symbols-coordinator.js +81 -12
  42. package/dist/operations/bootstrap/discovery-evidence.d.ts.map +1 -1
  43. package/dist/operations/bootstrap/discovery-evidence.js +44 -2
  44. package/dist/operations/bootstrap/discovery.d.ts.map +1 -1
  45. package/dist/operations/bootstrap/discovery.js +1 -0
  46. package/dist/operations/bootstrap/guidance-actions.d.ts.map +1 -1
  47. package/dist/operations/bootstrap/guidance-actions.js +12 -1
  48. package/dist/operations/bootstrap/plugin-offers.d.ts +7 -1
  49. package/dist/operations/bootstrap/plugin-offers.d.ts.map +1 -1
  50. package/dist/operations/bootstrap/plugin-offers.js +73 -3
  51. package/dist/operations/modeling/logic-modeling.d.ts.map +1 -1
  52. package/dist/operations/modeling/logic-modeling.js +2 -1
  53. package/dist/operations/modeling/model-requirement.d.ts.map +1 -1
  54. package/dist/operations/modeling/model-requirement.js +2 -1
  55. package/dist/operations/mutation/symbol-refresh.d.ts +2 -0
  56. package/dist/operations/mutation/symbol-refresh.d.ts.map +1 -1
  57. package/dist/operations/mutation/symbol-refresh.js +6 -1
  58. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  59. package/dist/operations/mutation/upsert.js +7 -0
  60. package/dist/operations/planning/compile-intent.d.ts.map +1 -1
  61. package/dist/operations/planning/compile-intent.js +2 -1
  62. package/dist/operations/proof/claim-bindings.d.ts +11 -0
  63. package/dist/operations/proof/claim-bindings.d.ts.map +1 -1
  64. package/dist/operations/proof/claim-bindings.js +144 -1
  65. package/dist/operations/proof/code-certificates.d.ts +10 -3
  66. package/dist/operations/proof/code-certificates.d.ts.map +1 -1
  67. package/dist/operations/proof/code-certificates.js +65 -13
  68. package/dist/operations/proof/code-languages.d.ts +104 -0
  69. package/dist/operations/proof/code-languages.d.ts.map +1 -0
  70. package/dist/operations/proof/code-languages.js +119 -0
  71. package/dist/operations/proof/code-models.d.ts +2 -0
  72. package/dist/operations/proof/code-models.d.ts.map +1 -1
  73. package/dist/operations/proof/code-models.js +11 -5
  74. package/dist/operations/proof/code-runner.d.ts +12 -9
  75. package/dist/operations/proof/code-runner.d.ts.map +1 -1
  76. package/dist/operations/proof/code-runner.js +81 -38
  77. package/dist/operations/proof/code-scope.d.ts +8 -0
  78. package/dist/operations/proof/code-scope.d.ts.map +1 -1
  79. package/dist/operations/proof/code-scope.js +30 -1
  80. package/dist/operations/proof/explain.d.ts +76 -0
  81. package/dist/operations/proof/explain.d.ts.map +1 -1
  82. package/dist/operations/proof/explain.js +228 -0
  83. package/dist/operations/proof/ingest-proof.d.ts +2 -0
  84. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  85. package/dist/operations/proof/ingest-proof.js +1 -0
  86. package/dist/operations/proof/java-package-shadow.d.ts +14 -0
  87. package/dist/operations/proof/java-package-shadow.d.ts.map +1 -0
  88. package/dist/operations/proof/java-package-shadow.js +389 -0
  89. package/dist/operations/proof/prolog-evaluator.d.ts +14 -0
  90. package/dist/operations/proof/prolog-evaluator.d.ts.map +1 -0
  91. package/dist/operations/proof/prolog-evaluator.js +247 -0
  92. package/dist/operations/proof/prolog-source-reader.d.ts +20 -0
  93. package/dist/operations/proof/prolog-source-reader.d.ts.map +1 -0
  94. package/dist/operations/proof/prolog-source-reader.js +1123 -0
  95. package/dist/operations/proof/source-code-readers.d.ts +6 -0
  96. package/dist/operations/proof/source-code-readers.d.ts.map +1 -1
  97. package/dist/operations/proof/source-code-readers.js +879 -75
  98. package/dist/operations/semantic-advisor/analyze-prose.d.ts +9 -1
  99. package/dist/operations/semantic-advisor/analyze-prose.d.ts.map +1 -1
  100. package/dist/operations/semantic-advisor/analyze-prose.js +21 -0
  101. package/dist/operations/semantic-advisor/case-preview.d.ts +24 -0
  102. package/dist/operations/semantic-advisor/case-preview.d.ts.map +1 -0
  103. package/dist/operations/semantic-advisor/case-preview.js +216 -0
  104. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  105. package/dist/operations/semantic-advisor/shared.js +3 -0
  106. package/dist/operations/semantic-advisor/types.d.ts +23 -0
  107. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  108. package/dist/plugins/approved-source-analyzers.generated.d.ts +15 -34
  109. package/dist/plugins/approved-source-analyzers.generated.d.ts.map +1 -1
  110. package/dist/plugins/approved-source-analyzers.generated.js +15 -34
  111. package/dist/plugins/plugin-install-check.d.ts +21 -0
  112. package/dist/plugins/plugin-install-check.d.ts.map +1 -0
  113. package/dist/plugins/plugin-install-check.js +62 -0
  114. package/dist/plugins/proof-reference-extractors.d.ts +20 -0
  115. package/dist/plugins/proof-reference-extractors.d.ts.map +1 -0
  116. package/dist/plugins/proof-reference-extractors.js +104 -0
  117. package/dist/plugins/reference-language-suggestion.d.ts +51 -0
  118. package/dist/plugins/reference-language-suggestion.d.ts.map +1 -0
  119. package/dist/plugins/reference-language-suggestion.js +277 -0
  120. package/dist/plugins/registry.d.ts.map +1 -1
  121. package/dist/plugins/registry.js +3 -1
  122. package/dist/plugins/source-analysis-service.d.ts.map +1 -1
  123. package/dist/plugins/source-analysis-service.js +4 -0
  124. package/dist/plugins/source-change-analysis.d.ts +26 -1
  125. package/dist/plugins/source-change-analysis.d.ts.map +1 -1
  126. package/dist/plugins/source-change-analysis.js +77 -5
  127. package/dist/plugins/source-classification.d.ts +2 -2
  128. package/dist/plugins/source-classification.d.ts.map +1 -1
  129. package/dist/plugins/source-classification.js +45 -1
  130. package/dist/public/operations/catalog.d.ts +62 -7
  131. package/dist/public/operations/catalog.d.ts.map +1 -1
  132. package/dist/public/operations/check-executor.d.ts.map +1 -1
  133. package/dist/public/operations/check-executor.js +3 -0
  134. package/dist/public/operations/evidence-floor.d.ts +8 -0
  135. package/dist/public/operations/evidence-floor.d.ts.map +1 -1
  136. package/dist/public/operations/evidence-floor.js +19 -1
  137. package/dist/public/operations/repair-plan.d.ts +46 -0
  138. package/dist/public/operations/repair-plan.d.ts.map +1 -1
  139. package/dist/public/operations/repair-plan.js +110 -1
  140. package/dist/public/operations/schema6-check-actions.js +1 -1
  141. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  142. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  143. package/dist/public/operations/specs/check-rules.generated.js +3 -1
  144. package/dist/public/operations/specs/check.d.ts +1 -1
  145. package/dist/public/operations/specs/mutation-schemas.d.ts +61 -6
  146. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  147. package/dist/public/operations/specs/mutation-schemas.js +30 -0
  148. package/dist/public/operations/specs/reporting.d.ts +8 -0
  149. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  150. package/dist/public/operations/specs/reporting.js +26 -3
  151. package/dist/public/operations/specs/semantic.d.ts.map +1 -1
  152. package/dist/public/operations/specs/semantic.js +2 -1
  153. package/dist/public/operations/specs/upsert.d.ts +61 -6
  154. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  155. package/dist/public/operations/symbol-coordinates-check.d.ts +11 -0
  156. package/dist/public/operations/symbol-coordinates-check.d.ts.map +1 -0
  157. package/dist/public/operations/symbol-coordinates-check.js +66 -0
  158. package/dist/public/proof-protocol.d.ts +31 -6
  159. package/dist/public/proof-protocol.d.ts.map +1 -1
  160. package/dist/public/proof-protocol.js +45 -15
  161. package/dist/public/proof-sources.d.ts +4 -2
  162. package/dist/public/proof-sources.d.ts.map +1 -1
  163. package/dist/public/proof-sources.js +43 -4
  164. package/dist/public/schemas/entity.d.ts.map +1 -1
  165. package/dist/public/schemas/entity.js +59 -0
  166. package/dist/public/skills/kibi-commit-review/SKILL.md +6 -2
  167. package/dist/public/skills/kibi-decisions/SKILL.md +7 -2
  168. package/dist/public/skills/kibi-decisions/resources/signoff-views.md +3 -1
  169. package/dist/public/skills/kibi-usage/SKILL.md +14 -3
  170. package/dist/public/skills/kibi-usage/resources/prolog-proofs.md +207 -0
  171. package/dist/public/skills/kibi-usage/resources/proof.md +44 -3
  172. package/dist/schemas/entity.schema.json +126 -6
  173. package/dist/search-answer.d.ts +3 -2
  174. package/dist/search-answer.d.ts.map +1 -1
  175. package/dist/search-answer.js +56 -3
  176. package/dist/traceability/analysis-gate.d.ts +3 -1
  177. package/dist/traceability/analysis-gate.d.ts.map +1 -1
  178. package/dist/traceability/analysis-gate.js +9 -1
  179. package/dist/traceability/impact-knowledge.d.ts.map +1 -1
  180. package/dist/traceability/impact-knowledge.js +2 -0
  181. package/dist/traceability/staged-file-coverage.d.ts.map +1 -1
  182. package/dist/traceability/staged-file-coverage.js +7 -2
  183. package/dist/traceability/symbol-extract.d.ts +17 -0
  184. package/dist/traceability/symbol-extract.d.ts.map +1 -1
  185. package/dist/traceability/symbol-extract.js +69 -15
  186. package/dist/traceability/temp-kb.d.ts.map +1 -1
  187. package/dist/traceability/temp-kb.js +11 -1
  188. package/dist/traceability/validate.d.ts.map +1 -1
  189. package/dist/traceability/validate.js +5 -7
  190. package/dist/types/entities.d.ts +12 -0
  191. package/dist/types/entities.d.ts.map +1 -1
  192. package/dist/usage-telemetry.d.ts +9 -0
  193. package/dist/usage-telemetry.d.ts.map +1 -1
  194. package/dist/usage-telemetry.js +50 -4
  195. package/dist/utils/first-sentence.d.ts +9 -0
  196. package/dist/utils/first-sentence.d.ts.map +1 -0
  197. package/dist/utils/first-sentence.js +52 -0
  198. package/dist/utils/rule-registry.generated.d.ts +11 -0
  199. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  200. package/dist/utils/rule-registry.generated.js +13 -0
  201. package/package.json +5 -5
  202. package/schema/entities.pl +12 -0
  203. package/src/public/operations/check-executor.ts +8 -0
  204. package/src/public/operations/evidence-floor.ts +29 -1
  205. package/src/public/operations/repair-plan.ts +152 -1
  206. package/src/public/operations/schema6-check-actions.ts +1 -1
  207. package/src/public/operations/specs/check-rules.generated.ts +3 -1
  208. package/src/public/operations/specs/mutation-schemas.ts +34 -0
  209. package/src/public/operations/specs/reporting.ts +38 -3
  210. package/src/public/operations/specs/semantic.ts +2 -1
  211. package/src/public/operations/symbol-coordinates-check.ts +79 -0
  212. package/src/public/proof-protocol-types.d.ts +22 -5
  213. package/src/public/proof-protocol.ts +78 -19
  214. package/src/public/proof-sources.ts +51 -3
  215. package/src/public/schemas/entity.ts +65 -0
  216. package/src/public/skills/kibi-commit-review/SKILL.md +6 -2
  217. package/src/public/skills/kibi-decisions/SKILL.md +7 -2
  218. package/src/public/skills/kibi-decisions/resources/signoff-views.md +3 -1
  219. package/src/public/skills/kibi-usage/SKILL.md +14 -3
  220. package/src/public/skills/kibi-usage/resources/prolog-proofs.md +207 -0
  221. package/src/public/skills/kibi-usage/resources/proof.md +44 -3
  222. package/src/schemas/entity.schema.json +126 -6
@@ -1,7 +1,9 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { readManifestWithCoordinateOverlay } from "../extractors/manifest.js";
3
+ import { declarationTitleAliases, matchDeclarationTitle, } from "../extractors/symbol-title-match.js";
3
4
  import { createTsMorphSourceAnalysisProvider, isPrivateClassMember, } from "../extractors/symbols-ts.js";
4
5
  import { inferSymbolRole, } from "../public/symbol-granularity.js";
6
+ import { analysisObligation } from "./analysis-gate.js";
5
7
  const TRACEABILITY_RELATIONSHIP_TYPES = new Set([
6
8
  "implements",
7
9
  "covered_by",
@@ -103,7 +105,7 @@ function extractRelationshipsFromManifestRecord(record) {
103
105
  }
104
106
  return relationships;
105
107
  }
106
- function buildSymbolResult(stagedFile, name, kind, span, inlineReqLinks, manifestLookup) {
108
+ function buildSymbolResult(stagedFile, name, kind, span, inlineReqLinks, manifestLookup, nestedSpans = []) {
107
109
  const { id, relationships } = resolveSymbolTraceability(stagedFile.path, name, manifestLookup);
108
110
  const manifestReqLinks = getRequirementLinks(relationships);
109
111
  const mergedReqLinks = inlineReqLinks.length > 0 ? inlineReqLinks : manifestReqLinks;
@@ -117,7 +119,7 @@ function buildSymbolResult(stagedFile, name, kind, span, inlineReqLinks, manifes
117
119
  startLine: span.startLine,
118
120
  endLine: span.endLine,
119
121
  },
120
- hunkRanges: intersectingHunks(span.startLine, span.endLine, stagedFile.hunkRanges),
122
+ hunkRanges: ownedHunks(span, nestedSpans, stagedFile.hunkRanges),
121
123
  reqLinks: mergedReqLinks,
122
124
  ...(relationships !== undefined ? { relationships } : {}),
123
125
  };
@@ -215,11 +217,33 @@ export async function extractSymbolsFromStagedFileAsync(stagedFile, manifestLook
215
217
  else {
216
218
  analysis = analyzeWithBuiltinFallback(stagedFile.path, content);
217
219
  }
220
+ // A local gap (a macro, an include, a dynamic definition) does not hide the
221
+ // declarations the parser placed, so those are validated; a changed line
222
+ // that no placed declaration contains is reviewed at file level instead.
223
+ if (analysis && partialAnalysisSymbolsUsable(analysis))
224
+ return symbolsFromAnalysis(stagedFile, analysis, manifestLookup);
218
225
  if (analysis?.status === "failed" || analysis?.status === "partial") {
219
226
  throw new Error(`Source analysis ${analysis.status} for ${stagedFile.path}; complete symbol validation is unavailable`);
220
227
  }
221
228
  return symbolsFromAnalysis(stagedFile, analysis, manifestLookup);
222
229
  }
230
+ /**
231
+ * Whether a partial result still places its declarations: every gap is local
232
+ * (no parser, timeout or integrity finding) and no output cap hid symbols.
233
+ */
234
+ // implements REQ-cli-staged-impact-enforcement
235
+ export function partialAnalysisSymbolsUsable(analysis) {
236
+ if (analysis.status !== "partial")
237
+ return false;
238
+ const codes = (analysis.diagnostics ?? []).map((item) => item.code);
239
+ if (codes.some((code) => /LIMIT/i.test(code)))
240
+ return false;
241
+ return (analysisObligation("after", {
242
+ status: "partial",
243
+ diagnosticCodes: codes,
244
+ uncoveredRanges: analysis.uncoveredRanges ?? [],
245
+ }, []).kind !== "blocked");
246
+ }
223
247
  function symbolsFromAnalysis(stagedFile, analysis, manifestLookup) {
224
248
  if (!analysis)
225
249
  return [];
@@ -234,8 +258,9 @@ function symbolsFromAnalysis(stagedFile, analysis, manifestLookup) {
234
258
  }
235
259
  const results = [];
236
260
  for (const symbol of analysis.symbols) {
261
+ const nested = nestedSpans(symbol, analysis.symbols);
237
262
  try {
238
- results.push(buildSymbolResult(stagedFile, sourceSymbolLocator(symbol, analysis.symbols, stagedFile.path, manifestLookup), symbol.kind, { startLine: symbol.startLine, endLine: symbol.endLine }, parseReqDirectives(symbol.directiveText ?? ""), manifestLookup));
263
+ results.push(buildSymbolResult(stagedFile, sourceSymbolLocator(symbol, analysis.symbols, stagedFile.path, manifestLookup), symbol.kind, { startLine: symbol.startLine, endLine: symbol.endLine }, parseReqDirectives(symbol.directiveText ?? ""), manifestLookup, nested));
239
264
  }
240
265
  catch (error) {
241
266
  if (analysis.status !== undefined)
@@ -252,13 +277,37 @@ function symbolsFromAnalysis(stagedFile, analysis, manifestLookup) {
252
277
  return results;
253
278
  }
254
279
  export { isPrivateClassMember };
255
- function intersectingHunks(startLine, endLine, hunks) {
256
- const out = [];
257
- for (const h of hunks) {
258
- if (rangesIntersect(startLine, endLine, h.start, h.end))
259
- out.push(h);
260
- }
261
- return out;
280
+ /** Spans of the other declarations strictly inside a declaration's span. */
281
+ function nestedSpans(symbol, symbols) {
282
+ return symbols
283
+ .filter((other) => other !== symbol &&
284
+ symbol.startLine <= other.startLine &&
285
+ other.endLine <= symbol.endLine &&
286
+ (other.startLine !== symbol.startLine ||
287
+ other.endLine !== symbol.endLine))
288
+ .sort((left, right) => left.startLine - right.startLine);
289
+ }
290
+ /**
291
+ * Hunks with a changed line inside the span that no nested declaration
292
+ * contains: a line inside a member changes the member, not its class.
293
+ */
294
+ function ownedHunks(span, nested, hunks) {
295
+ return hunks.filter((hunk) => {
296
+ if (!rangesIntersect(span.startLine, span.endLine, hunk.start, hunk.end))
297
+ return false;
298
+ const end = Math.min(span.endLine, hunk.end);
299
+ let line = Math.max(span.startLine, hunk.start);
300
+ for (const child of nested) {
301
+ if (child.endLine < line)
302
+ continue;
303
+ if (child.startLine > line)
304
+ return true;
305
+ line = child.endLine + 1;
306
+ if (line > end)
307
+ return false;
308
+ }
309
+ return line <= end;
310
+ });
262
311
  }
263
312
  // implements REQ-cli-staged-impact-enforcement
264
313
  function sourceSymbolLocator(symbol, symbols, filePath, lookup) {
@@ -267,10 +316,15 @@ function sourceSymbolLocator(symbol, symbols, filePath, lookup) {
267
316
  return symbol.name;
268
317
  if (lookup?.has(`${filePath}:${qualified}`))
269
318
  return qualified;
270
- // Preserve an authored legacy unqualified locator only when unambiguous.
271
- if (symbols.filter((candidate) => candidate.name === symbol.name).length ===
272
- 1 &&
273
- lookup?.has(`${filePath}:${symbol.name}`))
274
- return symbol.name;
319
+ // Another title sync places on this declaration alone: a Terraform
320
+ // address, a bare name no other declaration shares, a class named like
321
+ // its constructors.
322
+ for (const title of [...declarationTitleAliases(symbol), symbol.name]) {
323
+ if (!lookup?.has(`${filePath}:${title}`))
324
+ continue;
325
+ const match = matchDeclarationTitle(title, symbols, filePath);
326
+ if ("symbol" in match && match.symbol === symbol)
327
+ return title;
328
+ }
275
329
  return qualified;
276
330
  }
@@ -1 +1 @@
1
- {"version":3,"file":"temp-kb.d.ts","sourceRoot":"","sources":["../../src/traceability/temp-kb.ts"],"names":[],"mappings":"AAMA,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAET;AACD,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CASvC;AAQD;;;GAGG;AACH,wBAAgB,iBAAiB,CAE/B,OAAO,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,KAAK,aAAa,GACpE,IAAI,CAEN;AA+RD,iBAAe,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB/D;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAe1B,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CA4Df;AAED,wBAAsB,YAAY,CAChC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CA+CxB;AAGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAkBrE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE"}
1
+ {"version":3,"file":"temp-kb.d.ts","sourceRoot":"","sources":["../../src/traceability/temp-kb.ts"],"names":[],"mappings":"AAMA,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAET;AACD,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;CACvB;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CASvC;AAQD;;;GAGG;AACH,wBAAgB,iBAAiB,CAE/B,OAAO,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,KAAK,aAAa,GACpE,IAAI,CAEN;AAySD,iBAAe,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB/D;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAe1B,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,gBAAgB,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CA4Df;AAED,wBAAsB,YAAY,CAChC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,aAAa,CAAC,CA+CxB;AAGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAkBrE;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BlE"}
@@ -55,6 +55,10 @@ const FACT_STRING_FIELDS = new Set([
55
55
  "canonical_key",
56
56
  "claim_key",
57
57
  "claim_text",
58
+ "dimension_waiver",
59
+ "dimension_waiver_approved_by",
60
+ "case_waiver",
61
+ "case_waiver_approved_by",
58
62
  "predicate_name",
59
63
  "predicate_namespace",
60
64
  "rule_hash",
@@ -187,7 +191,13 @@ function buildEntityAssertionGoal(entity, sourceFile) {
187
191
  if (entity.type === "req" && entity.semantic_inventory) {
188
192
  props.push(`semantic_inventory=${toPrologString(JSON.stringify(entity.semantic_inventory))}`);
189
193
  }
190
- for (const field of ["approved_by", "approval_ref", "rationale"]) {
194
+ for (const field of [
195
+ "approved_by",
196
+ "approval_ref",
197
+ "failure_side_waiver",
198
+ "failure_side_waiver_approved_by",
199
+ "rationale",
200
+ ]) {
191
201
  const value = entity.type === "req" ? entity[field] : undefined;
192
202
  if (value !== undefined)
193
203
  props.push(`${field}=${toPrologString(value)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/traceability/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,cAAc,CAAC;AACnE,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO1C;AAED,iBAAS,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B/C;AAED,iBAAS,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA8CnD;AAED,iBAAS,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAuBzD;AAGD,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,SAAS,EAAE,CAAC,CAgDtB;AAED;;;;;GAKG;AAEH,wBAAsB,4BAA4B,CAAC,OAAO,EAAE;IAC1D,MAAM,EAAE,aAAa,CAAC;IACtB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAgB7B;AAED,8EAA8E;AAE9E,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,SAAS,eAAe,EAAE,GACrC,MAAM,CAaR;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CAkBhE;AAGD,eAAO,MAAM,QAAQ;;;;;CAKpB,CAAC"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/traceability/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,cAAc,CAAC;AACnE,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO1C;AAED,iBAAS,kBAAkB,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B/C;AAED,iBAAS,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA8CnD;AAED,iBAAS,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAuBzD;AAGD,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,SAAS,EAAE,CAAC,CAgDtB;AAED;;;;;GAKG;AAEH,wBAAsB,4BAA4B,CAAC,OAAO,EAAE;IAC1D,MAAM,EAAE,aAAa,CAAC;IACtB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAgB7B;AAED,8EAA8E;AAE9E,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,SAAS,eAAe,EAAE,GACrC,MAAM,CAaR;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,SAAS,EAAE,GAAG,MAAM,CAoBhE;AAGD,eAAO,MAAM,QAAQ;;;;;CAKpB,CAAC"}
@@ -188,15 +188,13 @@ export function formatViolations(violations) {
188
188
  return "";
189
189
  const total = violations.length;
190
190
  const minLinks = violations[0]?.requiredLinks ?? 0;
191
- const lines = [];
192
- lines.push(`Traceability failed: ${total}/${total} staged symbols unlinked (minLinks=${minLinks})`);
191
+ const lines = [
192
+ `Traceability failed: ${total} changed symbol(s) have fewer than ${minLinks} requirement link(s) (minLinks=${minLinks}):`,
193
+ ];
193
194
  for (const v of violations) {
194
- const loc = `${v.file}:${v.line}`;
195
- const name = `${v.name}()`;
196
- // Suggest adding requirement links with role-specific guidance
197
- const suggestion = "Add ownership: implements: REQ-<area>-<behavior> (production code), use covered_by for production coverage, or executable_for for executable test code";
198
- lines.push(`${loc} ${name} -> ${suggestion}`);
195
+ lines.push(` ${v.file}:${v.line} ${v.name} (${v.currentLinks} of ${v.requiredLinks} link(s))`);
199
196
  }
197
+ lines.push("To link a symbol, give it an owning requirement, stage the change and re-run kibi check --staged:", ` - Add a .kb/symbols.yaml entry with kb_upsert (CLI: kibi upsert --input -): title as listed above (e.g. ${JSON.stringify(violations[0]?.name ?? "")}), sourceFile, and the relationship implements -> REQ-<area>-<behavior> for production code or executable_for -> TEST-<area>-<behavior> for executable test code. Stage .kb/symbols.yaml with the code.`, " - Or write a comment `implements REQ-<area>-<behavior>` directly above the declaration.", " If no requirement fits, find one with kb_search or create it with kb_upsert (type req) first; production symbols also need covered_by -> TEST-<area>-<behavior>.");
200
198
  return lines.join("\n");
201
199
  }
202
200
  // Test helpers for edge-case coverage
@@ -37,6 +37,14 @@ export interface FactFields {
37
37
  canonical_key?: string;
38
38
  claim_key?: string;
39
39
  claim_text?: string;
40
+ /** Why a quantifier word in claim_text ranges over nothing. */
41
+ dimension_waiver?: string;
42
+ /** The person who accepted the dimension waiver. */
43
+ dimension_waiver_approved_by?: string;
44
+ /** Why the fact's derived edge cases are covered some other way. */
45
+ case_waiver?: string;
46
+ /** The person who accepted the case waiver. */
47
+ case_waiver_approved_by?: string;
40
48
  predicate_name?: string;
41
49
  predicate_namespace?: string;
42
50
  predicate_arity?: number;
@@ -66,6 +74,10 @@ export type Requirement = BaseEntity & {
66
74
  approved_by?: string;
67
75
  /** Optional reference to the approval decision record. */
68
76
  approval_ref?: string;
77
+ /** Why the requirement has no failure side to test. */
78
+ failure_side_waiver?: string;
79
+ /** The person who accepted the failure-side waiver. */
80
+ failure_side_waiver_approved_by?: string;
69
81
  /** Why the requirement exists; explanation, not checked meaning. */
70
82
  rationale?: string;
71
83
  /** How firmly it was decided; absent reads as `default` when an agent wrote it, else `firm`. */
@@ -1 +1 @@
1
- {"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/types/entities.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../../src/types/entities.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,11 @@
1
1
  import type { Command } from "commander";
2
+ /**
3
+ * Name why this command failed with a fixed identifier (an error code, a
4
+ * failing doctor check), for the event recorded at exit. The first note wins.
5
+ */
6
+ export declare function noteCliErrorCategory(category: string | undefined): void;
7
+ /** The error code of a failed JSON result printed by a command, if any. */
8
+ export declare function noteCliResultError(stdout: string | undefined): void;
2
9
  /** Remember which registered command ran, for the event recorded at exit. */
3
10
  export declare function trackCommandPath(program: Command): () => string | undefined;
4
11
  export declare function finishCliTelemetry(input: {
@@ -6,6 +13,8 @@ export declare function finishCliTelemetry(input: {
6
13
  readonly packageVersion: string;
7
14
  readonly startedAt: Date;
8
15
  readonly exitCode: number;
16
+ /** The error the command threw, when it failed by throwing. */
17
+ readonly error?: unknown;
9
18
  readonly env?: NodeJS.ProcessEnv;
10
19
  }): Promise<void>;
11
20
  //# sourceMappingURL=usage-telemetry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"usage-telemetry.d.ts","sourceRoot":"","sources":["../src/usage-telemetry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBzC,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,MAAM,GAAG,SAAS,CAc3E;AAGD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BhB"}
1
+ {"version":3,"file":"usage-telemetry.d.ts","sourceRoot":"","sources":["../src/usage-telemetry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBzC;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAIvE;AAGD,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAanE;AAgBD,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,MAAM,GAAG,SAAS,CAc3E;AAGD,wBAAsB,kBAAkB,CAAC,KAAK,EAAE;IAC9C,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC,GAAG,OAAO,CAAC,IAAI,CAAC,CAkChB"}
@@ -1,4 +1,4 @@
1
- import { flushTelemetry, recordOperationTelemetry, takeTelemetryNotice, } from "kibi-agent-core/usage-telemetry";
1
+ import { detectTelemetryHost, flushTelemetry, recordOperationTelemetry, takeTelemetryNotice, } from "kibi-agent-core/usage-telemetry";
2
2
  /**
3
3
  * Anonymous usage telemetry for the CLI: one summary event per command,
4
4
  * named by its registered command path (`sync`, `storage compact`, `search`)
@@ -7,6 +7,45 @@ import { flushTelemetry, recordOperationTelemetry, takeTelemetryNotice, } from "
7
7
  */
8
8
  /** Commands that manage telemetry itself are not recorded. */
9
9
  const UNRECORDED_COMMANDS = new Set(["telemetry"]);
10
+ let notedErrorCategory;
11
+ // implements REQ-kibi-anonymous-usage-telemetry
12
+ /**
13
+ * Name why this command failed with a fixed identifier (an error code, a
14
+ * failing doctor check), for the event recorded at exit. The first note wins.
15
+ */
16
+ export function noteCliErrorCategory(category) {
17
+ if (category && notedErrorCategory === undefined) {
18
+ notedErrorCategory = category;
19
+ }
20
+ }
21
+ // implements REQ-kibi-anonymous-usage-telemetry
22
+ /** The error code of a failed JSON result printed by a command, if any. */
23
+ export function noteCliResultError(stdout) {
24
+ if (!stdout)
25
+ return;
26
+ try {
27
+ const parsed = JSON.parse(stdout);
28
+ if (parsed.status === "error" && typeof parsed.error?.code === "string") {
29
+ noteCliErrorCategory(parsed.error.code);
30
+ }
31
+ }
32
+ catch {
33
+ // Not a JSON result.
34
+ }
35
+ }
36
+ /** A thrown error's code or class name; never its message. */
37
+ function thrownErrorCategory(error) {
38
+ if (error !== null && typeof error === "object") {
39
+ const code = error.code;
40
+ if (typeof code === "string" && code !== "")
41
+ return code;
42
+ const name = error.name;
43
+ if (typeof name === "string" && name !== "" && name !== "Error") {
44
+ return name;
45
+ }
46
+ }
47
+ return "uncaught_error";
48
+ }
10
49
  // implements REQ-kibi-anonymous-usage-telemetry
11
50
  /** Remember which registered command ran, for the event recorded at exit. */
12
51
  export function trackCommandPath(program) {
@@ -24,6 +63,8 @@ export function trackCommandPath(program) {
24
63
  export async function finishCliTelemetry(input) {
25
64
  const env = input.env ?? process.env;
26
65
  const command = input.commandPath;
66
+ const noted = notedErrorCategory;
67
+ notedErrorCategory = undefined;
27
68
  if (!command || UNRECORDED_COMMANDS.has(command.split(" ")[0] ?? "")) {
28
69
  return;
29
70
  }
@@ -33,15 +74,20 @@ export async function finishCliTelemetry(input) {
33
74
  recordOperationTelemetry({
34
75
  packageName: "kibi-cli",
35
76
  packageVersion: input.packageVersion,
36
- host: env.KIBI_HOST?.trim() ||
37
- env.KIBI_MCP_HOST?.trim() ||
38
- (env.CLAUDECODE === "1" ? "claude-code" : undefined),
77
+ host: detectTelemetryHost(env),
78
+ workspaceRoot: process.cwd(),
39
79
  }, {
40
80
  interface: "cli",
41
81
  operation: command,
42
82
  status: input.exitCode === 0 ? "success" : "error",
43
83
  durationMs: Date.now() - input.startedAt.getTime(),
44
84
  exitCode: input.exitCode,
85
+ errorCategory: input.exitCode === 0
86
+ ? undefined
87
+ : (noted ??
88
+ (input.error === undefined
89
+ ? undefined
90
+ : thrownErrorCategory(input.error))),
45
91
  }, env);
46
92
  await flushTelemetry({}, env);
47
93
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The first sentence of prose, used to title a requirement. A sentence ends
3
+ * at `.`, `!` or `?` followed by whitespace and an uppercase letter, or at
4
+ * the end of the text, so the dot in a path (`src/match.c`), a dotted name
5
+ * (`console.log`, `exec.Command`), a version (`v1.2`), an abbreviation or
6
+ * backticks never cuts it. A closing dot is dropped.
7
+ */
8
+ export declare function firstSentence(text: string): string;
9
+ //# sourceMappingURL=first-sentence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first-sentence.d.ts","sourceRoot":"","sources":["../../src/utils/first-sentence.ts"],"names":[],"mappings":"AAyBA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAmBlD"}
@@ -0,0 +1,52 @@
1
+ /*
2
+ Kibi — repo-local, per-branch, queryable long-term memory for software projects
3
+ Copyright (C) 2026 Piotr Franczyk
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Affero General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Affero General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Affero General Public License
16
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ */
18
+ /** Abbreviations whose dot does not end a sentence. */
19
+ const ABBREVIATION = /(?:^|[\s(])(?:e\.g|i\.e|etc|vs|cf|approx)\.$/i;
20
+ /** After a sentence end: whitespace, then an uppercase letter (maybe quoted). */
21
+ const NEXT_SENTENCE = /^\s+["'(“]?\p{Lu}/u;
22
+ // implements REQ-mcp-semantic-advisor-preflight
23
+ /**
24
+ * The first sentence of prose, used to title a requirement. A sentence ends
25
+ * at `.`, `!` or `?` followed by whitespace and an uppercase letter, or at
26
+ * the end of the text, so the dot in a path (`src/match.c`), a dotted name
27
+ * (`console.log`, `exec.Command`), a version (`v1.2`), an abbreviation or
28
+ * backticks never cuts it. A closing dot is dropped.
29
+ */
30
+ export function firstSentence(text) {
31
+ const value = text.trim();
32
+ let quoted = false;
33
+ for (let index = 0; index < value.length; index += 1) {
34
+ const char = value[index] ?? "";
35
+ if (char === "`") {
36
+ quoted = !quoted;
37
+ continue;
38
+ }
39
+ if (quoted || (char !== "." && char !== "!" && char !== "?"))
40
+ continue;
41
+ const rest = value.slice(index + 1);
42
+ const atEnd = rest.trim() === "";
43
+ if (!atEnd && !NEXT_SENTENCE.test(rest))
44
+ continue;
45
+ if (char === "." && ABBREVIATION.test(value.slice(0, index + 1)))
46
+ continue;
47
+ return (char === "." ? value.slice(0, index) : value.slice(0, index + 1))
48
+ .replace(/\.+$/, "")
49
+ .trim();
50
+ }
51
+ return value;
52
+ }
@@ -18,6 +18,12 @@ export declare const GENERATED_RULES: readonly [{
18
18
  readonly description: "A symbol with traceability relationships must not link its source file coarsely while narrower behavioral symbols are available, unless it carries an allowed granularity_reason; the staged gate's symbol_granularity_violation evaluated KB-wide";
19
19
  readonly enforcementClass: "canonical";
20
20
  readonly category: "traceability";
21
+ }, {
22
+ readonly name: "symbol-coordinates-missing";
23
+ readonly description: "Advisory: an active symbol names a source file that exists, but Kibi could not place it there (the declaration was not found, the file is unreadable to the analyzer, or a declared plugin or grammar pack is missing), so its link is checked against no code";
24
+ readonly enforcementClass: "advisory";
25
+ readonly category: "traceability";
26
+ readonly diagnosticSeverity: "warning";
21
27
  }, {
22
28
  readonly name: "no-dangling-refs";
23
29
  readonly description: "All relationship targets must exist in the KB";
@@ -68,6 +74,11 @@ export declare const GENERATED_RULES: readonly [{
68
74
  readonly description: "Advisory: a scenario that expects success assumes nothing, assumes values that contradict each other, assumes a property value no governing requirement constrains comparably (type, unit or operator mismatch, or conflicting requirements), leaves a governing rule's conditions undecided, or conflicts only with constraints whose validity window may not cover it, so its feasibility cannot be decided";
69
75
  readonly enforcementClass: "advisory";
70
76
  readonly category: "integrity";
77
+ }, {
78
+ readonly name: "scenario-outcome-mismatch";
79
+ readonly description: "A scenario that expects rejection or error must assume a value or situation a current requirement forbids: when every assumption is governed by current requirements and they permit all of them together, the knowledge base predicts success and the scenario exercises no failure side";
80
+ readonly enforcementClass: "canonical";
81
+ readonly category: "integrity";
71
82
  }, {
72
83
  readonly name: "exception-claim-keys";
73
84
  readonly description: "An exception requirement's exempts_claims must name claim keys of a requirement it exempts, and requires an exempts link";
@@ -1 +1 @@
1
- {"version":3,"file":"rule-registry.generated.d.ts","sourceRoot":"","sources":["../../src/utils/rule-registry.generated.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmZlB,CAAC"}
1
+ {"version":3,"file":"rule-registry.generated.d.ts","sourceRoot":"","sources":["../../src/utils/rule-registry.generated.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkalB,CAAC"}
@@ -32,6 +32,13 @@ export const GENERATED_RULES = [
32
32
  enforcementClass: "canonical",
33
33
  category: "traceability",
34
34
  },
35
+ {
36
+ name: "symbol-coordinates-missing",
37
+ description: "Advisory: an active symbol names a source file that exists, but Kibi could not place it there (the declaration was not found, the file is unreadable to the analyzer, or a declared plugin or grammar pack is missing), so its link is checked against no code",
38
+ enforcementClass: "advisory",
39
+ category: "traceability",
40
+ diagnosticSeverity: "warning",
41
+ },
35
42
  {
36
43
  name: "no-dangling-refs",
37
44
  description: "All relationship targets must exist in the KB",
@@ -92,6 +99,12 @@ export const GENERATED_RULES = [
92
99
  enforcementClass: "advisory",
93
100
  category: "integrity",
94
101
  },
102
+ {
103
+ name: "scenario-outcome-mismatch",
104
+ description: "A scenario that expects rejection or error must assume a value or situation a current requirement forbids: when every assumption is governed by current requirements and they permit all of them together, the knowledge base predicts success and the scenario exercises no failure side",
105
+ enforcementClass: "canonical",
106
+ category: "integrity",
107
+ },
95
108
  {
96
109
  name: "exception-claim-keys",
97
110
  description: "An exception requirement's exempts_claims must name claim keys of a requirement it exempts, and requires an exempts link",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-cli",
3
- "version": "2.38.0",
3
+ "version": "2.40.0",
4
4
  "type": "module",
5
5
  "description": "Kibi CLI for knowledge base management",
6
6
  "engines": {
@@ -239,14 +239,14 @@
239
239
  "fast-glob": "^3.2.12",
240
240
  "gray-matter": "^4.0.3",
241
241
  "js-yaml": "^4.1.0",
242
- "kibi-core": "^0.27.0",
243
- "kibi-plugin-builtin": "^0.5.3",
244
- "kibi-plugin-sdk": "^0.5.1",
242
+ "kibi-core": "^0.29.0",
243
+ "kibi-plugin-builtin": "^0.5.4",
244
+ "kibi-plugin-sdk": "^0.6.0",
245
245
  "kibi-swipl": "^1.0.1",
246
246
  "saxes": "^6.0.0",
247
247
  "ignore": "^5.3.0",
248
248
  "yaml": "^2.9.1",
249
- "kibi-agent-core": "^0.10.0"
249
+ "kibi-agent-core": "^0.11.1"
250
250
  },
251
251
  "devDependencies": {
252
252
  "@types/node": "latest",
@@ -47,6 +47,10 @@ entity_property(req, proof_exempt_reason, string).
47
47
  % Only an approved exception makes a success scenario feasible.
48
48
  entity_property(req, approved_by, string).
49
49
  entity_property(req, approval_ref, string).
50
+ % Why a requirement has no failure side to test (its claims state a
51
+ % capability or output shape), and the human who accepted that.
52
+ entity_property(req, failure_side_waiver, string).
53
+ entity_property(req, failure_side_waiver_approved_by, string).
50
54
  % Why the requirement exists, in the words of whoever stated the intent.
51
55
  % Explanation only: it is never part of the checked meaning.
52
56
  entity_property(req, rationale, string).
@@ -83,6 +87,12 @@ entity_property(fact, valid_to, datetime).
83
87
  entity_property(fact, canonical_key, string).
84
88
  entity_property(fact, claim_key, string).
85
89
  entity_property(fact, claim_text, string).
90
+ % Why a quantifier word in claim_text ranges over nothing, so the claim
91
+ % needs no dimension, and the human who accepted that.
92
+ entity_property(fact, dimension_waiver, string).
93
+ entity_property(fact, dimension_waiver_approved_by, string).
94
+ entity_property(fact, case_waiver, string).
95
+ entity_property(fact, case_waiver_approved_by, string).
86
96
  entity_property(fact, predicate_name, string).
87
97
  entity_property(fact, predicate_namespace, string).
88
98
  entity_property(fact, predicate_arity, integer).
@@ -149,6 +159,8 @@ optional_property(req, semantic_source_hash).
149
159
  optional_property(req, semantic_inventory).
150
160
  optional_property(req, proof_exempt).
151
161
  optional_property(req, proof_exempt_reason).
162
+ optional_property(req, failure_side_waiver).
163
+ optional_property(req, failure_side_waiver_approved_by).
152
164
  optional_property(req, approved_by).
153
165
  optional_property(req, approval_ref).
154
166
  optional_property(req, rationale).
@@ -61,6 +61,7 @@ import {
61
61
  collectSourcePathDanglingViolations,
62
62
  } from "./source-path-dangling.js";
63
63
  import { collectSourceRelationshipParityViolations } from "./source-relationship-parity.js";
64
+ import { collectSymbolCoordinatesMissingViolations } from "./symbol-coordinates-check.js";
64
65
  import { collectSymbolGranularityViolations } from "./symbol-granularity-check.js";
65
66
  import type { OperationResult } from "./types.js";
66
67
  import { readWorkspaceSnapshot } from "./workspace-snapshot.js";
@@ -414,6 +415,12 @@ export async function executeCheck(
414
415
  rulesAllowlist,
415
416
  analysisCacheDir(context, workspaceRoot, options),
416
417
  );
418
+ const symbolCoordinateFindings =
419
+ await collectSymbolCoordinatesMissingViolations(
420
+ prolog,
421
+ workspaceRoot,
422
+ rulesAllowlist,
423
+ );
417
424
  const originReviewFindings = await collectOriginReviewViolations(
418
425
  prolog,
419
426
  rulesAllowlist,
@@ -449,6 +456,7 @@ export async function executeCheck(
449
456
  ...sourceRelationshipParityViolations,
450
457
  ...sourcePathFindings,
451
458
  ...symbolGranularityFindings,
459
+ ...symbolCoordinateFindings,
452
460
  ...predicateConformanceFindings,
453
461
  ...originReviewFindings,
454
462
  ...entityContextFindings,
@@ -46,6 +46,12 @@ export type EvidenceFloorRow = Readonly<{
46
46
  proofGaps: readonly string[];
47
47
  /** The tests and symbols behind the gaps; empty lists are left out. */
48
48
  gapDetails?: Readonly<Record<string, readonly string[]>>;
49
+ /** Claims a proof refuted: the test, the claim and what the test read. */
50
+ refutations?: readonly Readonly<{
51
+ test: string;
52
+ claimKey: string;
53
+ reason: string;
54
+ }>[];
49
55
  }>;
50
56
 
51
57
  type EvidenceFloorPayload = {
@@ -100,7 +106,28 @@ export function gapDetailLines(row: EvidenceFloorRow): string[] {
100
106
  );
101
107
  }
102
108
 
109
+ /** Gaps a refuted claim leaves that a derived proof would have covered. */
110
+ const REFUTATION_GAPS = new Set(["happy_path_only", "uncovered_case"]);
111
+
112
+ /** Each refuted claim in plain words: which test refutes it and why. */
113
+ // implements REQ-kibi-claim-bound-proofs
114
+ export function refutationText(row: EvidenceFloorRow): string | undefined {
115
+ const refutations = row.refutations ?? [];
116
+ if (refutations.length === 0) return undefined;
117
+ return refutations
118
+ .map(
119
+ (refutation) =>
120
+ `${refutation.test} refutes ${refutation.claimKey}: ${refutation.reason}`,
121
+ )
122
+ .join("; ");
123
+ }
124
+
103
125
  function suggestionFor(row: EvidenceFloorRow): string {
126
+ const refuted = refutationText(row);
127
+ if (refuted !== undefined) {
128
+ const following = row.proofGaps.filter((gap) => REFUTATION_GAPS.has(gap));
129
+ return `The code breaks a claim of ${row.id} (${refuted}). Fix the code so it keeps the claim, or, with the person who owns the rule, change the requirement, then run kibi prove${following.length > 0 ? `; ${following.join(" and ")} ${following.length > 1 ? "clear" : "clears"} once the proof derives the claim` : ""}. kibi proof explain ${row.id} shows each claim's bindings.`;
130
+ }
104
131
  if (row.status === "pending_reproof")
105
132
  return `Run kibi prove for the tests behind ${row.id} so its receipts match the current code, then rerun kibi check --fresh-evidence.`;
106
133
  switch (row.requiredEvidence) {
@@ -127,7 +154,7 @@ export function evidenceFloorViolations(
127
154
  description:
128
155
  row.status === "pending_reproof"
129
156
  ? `${row.id} is ${row.evidenceLevel} but needs ${row.requiredEvidence} (${floorSource(row)}); its receipts are older than the code`
130
- : `${row.id} is ${row.evidenceLevel} but needs ${row.requiredEvidence} (${floorSource(row)})`,
157
+ : `${row.id} is ${row.evidenceLevel} but needs ${row.requiredEvidence} (${floorSource(row)})${refutationText(row) === undefined ? "" : `; its proof refutes a claim: ${refutationText(row)}`}`,
131
158
  suggestion: suggestionFor(row),
132
159
  evidence: {
133
160
  evidenceLevel: row.evidenceLevel,
@@ -137,6 +164,7 @@ export function evidenceFloorViolations(
137
164
  proofStatus: row.proofStatus,
138
165
  proofGaps: row.proofGaps,
139
166
  ...(row.gapDetails === undefined ? {} : { gapDetails: row.gapDetails }),
167
+ ...(row.refutations?.length ? { refutations: row.refutations } : {}),
140
168
  },
141
169
  }));
142
170
  }