kibi-cli 2.31.0 → 2.32.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 (226) hide show
  1. package/dist/cli-register-proof.d.ts.map +1 -1
  2. package/dist/cli-register-proof.js +19 -7
  3. package/dist/cli-register-reporting.d.ts.map +1 -1
  4. package/dist/cli-register-reporting.js +2 -0
  5. package/dist/commands/check.d.ts +1 -0
  6. package/dist/commands/check.d.ts.map +1 -1
  7. package/dist/commands/check.js +14 -5
  8. package/dist/commands/discovery-table.d.ts.map +1 -1
  9. package/dist/commands/discovery-table.js +51 -4
  10. package/dist/commands/doctor.js +19 -4
  11. package/dist/commands/migrate.d.ts.map +1 -1
  12. package/dist/commands/migrate.js +89 -3
  13. package/dist/commands/prove.d.ts +48 -1
  14. package/dist/commands/prove.d.ts.map +1 -1
  15. package/dist/commands/prove.js +293 -8
  16. package/dist/commands/report.d.ts +1 -0
  17. package/dist/commands/report.d.ts.map +1 -1
  18. package/dist/commands/report.js +70 -5
  19. package/dist/commands/signoff.d.ts.map +1 -1
  20. package/dist/commands/signoff.js +21 -2
  21. package/dist/commands/sync/manifest.d.ts.map +1 -1
  22. package/dist/commands/sync/manifest.js +20 -4
  23. package/dist/commands/sync/persistence.d.ts.map +1 -1
  24. package/dist/commands/sync/persistence.js +16 -5
  25. package/dist/diagnostics.js +1 -1
  26. package/dist/engine.js +1 -1
  27. package/dist/extractors/markdown.d.ts +3 -1
  28. package/dist/extractors/markdown.d.ts.map +1 -1
  29. package/dist/extractors/markdown.js +17 -0
  30. package/dist/operations/bootstrap/candidate-helpers.d.ts +3 -0
  31. package/dist/operations/bootstrap/candidate-helpers.d.ts.map +1 -1
  32. package/dist/operations/bootstrap/candidate-helpers.js +4 -0
  33. package/dist/operations/migration/evidence-floor.d.ts +41 -0
  34. package/dist/operations/migration/evidence-floor.d.ts.map +1 -0
  35. package/dist/operations/migration/evidence-floor.js +230 -0
  36. package/dist/operations/migration/proof-contract-claims.d.ts +59 -0
  37. package/dist/operations/migration/proof-contract-claims.d.ts.map +1 -0
  38. package/dist/operations/migration/proof-contract-claims.js +182 -0
  39. package/dist/operations/migration/schema6.d.ts +6 -0
  40. package/dist/operations/migration/schema6.d.ts.map +1 -1
  41. package/dist/operations/migration/schema6.js +94 -0
  42. package/dist/operations/mutation/omitted-properties.d.ts +11 -0
  43. package/dist/operations/mutation/omitted-properties.d.ts.map +1 -0
  44. package/dist/operations/mutation/omitted-properties.js +76 -0
  45. package/dist/operations/mutation/serialization.d.ts.map +1 -1
  46. package/dist/operations/mutation/serialization.js +1 -0
  47. package/dist/operations/mutation/strict-fact.d.ts.map +1 -1
  48. package/dist/operations/mutation/strict-fact.js +6 -2
  49. package/dist/operations/mutation/symbol-granularity.d.ts.map +1 -1
  50. package/dist/operations/mutation/symbol-granularity.js +5 -3
  51. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  52. package/dist/operations/mutation/upsert.js +7 -1
  53. package/dist/operations/mutation/validation.d.ts +2 -0
  54. package/dist/operations/mutation/validation.d.ts.map +1 -1
  55. package/dist/operations/mutation/validation.js +4 -0
  56. package/dist/operations/proof/claim-bindings.d.ts +23 -0
  57. package/dist/operations/proof/claim-bindings.d.ts.map +1 -0
  58. package/dist/operations/proof/claim-bindings.js +211 -0
  59. package/dist/operations/proof/code-certificates.d.ts +135 -0
  60. package/dist/operations/proof/code-certificates.d.ts.map +1 -0
  61. package/dist/operations/proof/code-certificates.js +785 -0
  62. package/dist/operations/proof/code-scope.d.ts +11 -1
  63. package/dist/operations/proof/code-scope.d.ts.map +1 -1
  64. package/dist/operations/proof/code-scope.js +20 -2
  65. package/dist/operations/proof/compact-receipts.d.ts.map +1 -1
  66. package/dist/operations/proof/compact-receipts.js +4 -3
  67. package/dist/operations/proof/explain.d.ts +32 -0
  68. package/dist/operations/proof/explain.d.ts.map +1 -1
  69. package/dist/operations/proof/explain.js +91 -0
  70. package/dist/operations/proof/ingest-proof.d.ts +9 -1
  71. package/dist/operations/proof/ingest-proof.d.ts.map +1 -1
  72. package/dist/operations/proof/ingest-proof.js +41 -2
  73. package/dist/operations/proof/receipt-compaction.d.ts +2 -0
  74. package/dist/operations/proof/receipt-compaction.d.ts.map +1 -1
  75. package/dist/operations/proof/receipt-compaction.js +6 -2
  76. package/dist/operations/semantic-advisor/shared.d.ts.map +1 -1
  77. package/dist/operations/semantic-advisor/shared.js +4 -0
  78. package/dist/operations/semantic-advisor/strict-rules.js +3 -3
  79. package/dist/operations/semantic-advisor/types.d.ts +2 -1
  80. package/dist/operations/semantic-advisor/types.d.ts.map +1 -1
  81. package/dist/plugins/approved-source-analyzers.generated.d.ts +6 -6
  82. package/dist/plugins/approved-source-analyzers.generated.js +6 -6
  83. package/dist/proof/command-test-report.d.ts +4 -3
  84. package/dist/proof/command-test-report.d.ts.map +1 -1
  85. package/dist/proof/command-test-report.js +4 -10
  86. package/dist/proof/evaluate.d.ts.map +1 -1
  87. package/dist/proof/evaluate.js +18 -2
  88. package/dist/proof/inspect.d.ts.map +1 -1
  89. package/dist/proof/inspect.js +58 -0
  90. package/dist/proof/producers/playwright-reporter.d.ts +3 -0
  91. package/dist/proof/producers/playwright-reporter.d.ts.map +1 -1
  92. package/dist/proof/producers/playwright-reporter.js +25 -2
  93. package/dist/proof/step-runner.d.ts +36 -0
  94. package/dist/proof/step-runner.d.ts.map +1 -0
  95. package/dist/proof/step-runner.js +234 -0
  96. package/dist/public/evidence-levels.d.ts +12 -0
  97. package/dist/public/evidence-levels.d.ts.map +1 -0
  98. package/dist/public/evidence-levels.js +19 -0
  99. package/dist/public/impact/coverage-depth-quality.d.ts +7 -0
  100. package/dist/public/impact/coverage-depth-quality.d.ts.map +1 -1
  101. package/dist/public/impact/coverage-depth-quality.js +59 -0
  102. package/dist/public/impact/full-kb-quality.d.ts.map +1 -1
  103. package/dist/public/impact/full-kb-quality.js +3 -1
  104. package/dist/public/operations/catalog.d.ts +167 -6
  105. package/dist/public/operations/catalog.d.ts.map +1 -1
  106. package/dist/public/operations/check-executor.d.ts +2 -0
  107. package/dist/public/operations/check-executor.d.ts.map +1 -1
  108. package/dist/public/operations/check-executor.js +6 -0
  109. package/dist/public/operations/evidence-floor.d.ts +48 -0
  110. package/dist/public/operations/evidence-floor.d.ts.map +1 -0
  111. package/dist/public/operations/evidence-floor.js +143 -0
  112. package/dist/public/operations/migration-plan.d.ts +19 -5
  113. package/dist/public/operations/migration-plan.d.ts.map +1 -1
  114. package/dist/public/operations/migration-plan.js +22 -5
  115. package/dist/public/operations/node-ports.d.ts.map +1 -1
  116. package/dist/public/operations/node-ports.js +4 -1
  117. package/dist/public/operations/proof-contract-claims.d.ts +26 -0
  118. package/dist/public/operations/proof-contract-claims.d.ts.map +1 -0
  119. package/dist/public/operations/proof-contract-claims.js +71 -0
  120. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  121. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  122. package/dist/public/operations/specs/check-rules.generated.js +3 -1
  123. package/dist/public/operations/specs/check.d.ts +1 -1
  124. package/dist/public/operations/specs/mutation-schemas.d.ts +157 -5
  125. package/dist/public/operations/specs/mutation-schemas.d.ts.map +1 -1
  126. package/dist/public/operations/specs/mutation-schemas.js +15 -2
  127. package/dist/public/operations/specs/proof.d.ts +9 -0
  128. package/dist/public/operations/specs/proof.d.ts.map +1 -1
  129. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  130. package/dist/public/operations/specs/reporting.js +19 -10
  131. package/dist/public/operations/specs/upsert.d.ts +157 -5
  132. package/dist/public/operations/specs/upsert.d.ts.map +1 -1
  133. package/dist/public/proof-certificates.d.ts +89 -0
  134. package/dist/public/proof-certificates.d.ts.map +1 -0
  135. package/dist/public/proof-certificates.js +207 -0
  136. package/dist/public/proof-protocol.d.ts +126 -3
  137. package/dist/public/proof-protocol.d.ts.map +1 -1
  138. package/dist/public/proof-protocol.js +239 -3
  139. package/dist/public/proof-receipt.d.ts +89 -6
  140. package/dist/public/proof-receipt.d.ts.map +1 -1
  141. package/dist/public/proof-receipt.js +83 -7
  142. package/dist/public/schemas/entity.d.ts.map +1 -1
  143. package/dist/public/schemas/entity.js +18 -1
  144. package/dist/public/skills/kibi-bootstrap/SKILL.md +2 -2
  145. package/dist/public/skills/kibi-commit-review/SKILL.md +4 -3
  146. package/dist/public/skills/kibi-commit-review/resources/staged-gate.md +6 -1
  147. package/dist/public/skills/kibi-decisions/SKILL.md +10 -2
  148. package/dist/public/skills/kibi-decisions/resources/decision-records.md +6 -1
  149. package/dist/public/skills/kibi-decisions/resources/signoff-views.md +3 -2
  150. package/dist/public/skills/kibi-freshness/SKILL.md +5 -1
  151. package/dist/public/skills/kibi-traceability/SKILL.md +11 -1
  152. package/dist/public/skills/kibi-usage/SKILL.md +6 -4
  153. package/dist/public/skills/kibi-usage/resources/proof.md +124 -19
  154. package/dist/public/skills/kibi-usage/resources/workflows.md +4 -4
  155. package/dist/report/html-report.css +38 -1
  156. package/dist/report/html-report.d.ts +8 -0
  157. package/dist/report/html-report.d.ts.map +1 -1
  158. package/dist/report/html-report.js +141 -6
  159. package/dist/report/report-view.d.ts +1 -1
  160. package/dist/report/report-view.d.ts.map +1 -1
  161. package/dist/report/report-view.js +7 -0
  162. package/dist/schemas/entity.schema.json +212 -4
  163. package/dist/search-answer.d.ts.map +1 -1
  164. package/dist/search-answer.js +1 -0
  165. package/dist/signoff/html.d.ts.map +1 -1
  166. package/dist/signoff/html.js +3 -0
  167. package/dist/signoff/markdown.d.ts.map +1 -1
  168. package/dist/signoff/markdown.js +3 -0
  169. package/dist/signoff/model.d.ts +20 -0
  170. package/dist/signoff/model.d.ts.map +1 -1
  171. package/dist/signoff/model.js +20 -1
  172. package/dist/traceability/impact-knowledge.d.ts.map +1 -1
  173. package/dist/traceability/impact-knowledge.js +1 -0
  174. package/dist/traceability/temp-kb.d.ts.map +1 -1
  175. package/dist/traceability/temp-kb.js +1 -0
  176. package/dist/types/entities.d.ts +4 -1
  177. package/dist/types/entities.d.ts.map +1 -1
  178. package/dist/utils/merge-driver-setup.d.ts +8 -1
  179. package/dist/utils/merge-driver-setup.d.ts.map +1 -1
  180. package/dist/utils/merge-driver-setup.js +23 -2
  181. package/dist/utils/rule-registry.generated.d.ts +10 -0
  182. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  183. package/dist/utils/rule-registry.generated.js +12 -0
  184. package/dist/utils/schema-version.d.ts +1 -1
  185. package/dist/utils/schema-version.d.ts.map +1 -1
  186. package/dist/utils/schema-version.js +5 -1
  187. package/package.json +6 -2
  188. package/schema/entities.pl +6 -0
  189. package/schema/validation.pl +4 -1
  190. package/src/public/evidence-levels.ts +23 -0
  191. package/src/public/impact/coverage-depth-quality.ts +73 -0
  192. package/src/public/impact/full-kb-quality.ts +6 -1
  193. package/src/public/operations/check-executor.ts +13 -0
  194. package/src/public/operations/evidence-floor.ts +203 -0
  195. package/src/public/operations/migration-plan.ts +39 -6
  196. package/src/public/operations/node-ports.ts +3 -1
  197. package/src/public/operations/proof-contract-claims.ts +103 -0
  198. package/src/public/operations/specs/check-rules.generated.ts +3 -1
  199. package/src/public/operations/specs/mutation-schemas.ts +17 -2
  200. package/src/public/operations/specs/reporting.ts +20 -10
  201. package/src/public/proof-certificates.ts +271 -0
  202. package/src/public/proof-protocol-types.d.ts +17 -1
  203. package/src/public/proof-protocol.ts +318 -3
  204. package/src/public/proof-receipt.ts +127 -7
  205. package/src/public/schemas/entity.ts +19 -1
  206. package/src/public/skills/kibi-bootstrap/SKILL.md +2 -2
  207. package/src/public/skills/kibi-commit-review/SKILL.md +4 -3
  208. package/src/public/skills/kibi-commit-review/resources/staged-gate.md +6 -1
  209. package/src/public/skills/kibi-decisions/SKILL.md +10 -2
  210. package/src/public/skills/kibi-decisions/resources/decision-records.md +6 -1
  211. package/src/public/skills/kibi-decisions/resources/signoff-views.md +3 -2
  212. package/src/public/skills/kibi-freshness/SKILL.md +5 -1
  213. package/src/public/skills/kibi-traceability/SKILL.md +11 -1
  214. package/src/public/skills/kibi-usage/SKILL.md +6 -4
  215. package/src/public/skills/kibi-usage/resources/proof.md +124 -19
  216. package/src/public/skills/kibi-usage/resources/workflows.md +4 -4
  217. package/src/schemas/entity.schema.json +212 -4
  218. package/dist/commands/proof-impact.d.ts +0 -7
  219. package/dist/commands/proof-impact.d.ts.map +0 -1
  220. package/dist/commands/proof-impact.js +0 -39
  221. package/dist/operations/proof/baseline-diff.d.ts +0 -41
  222. package/dist/operations/proof/baseline-diff.d.ts.map +0 -1
  223. package/dist/operations/proof/baseline-diff.js +0 -153
  224. package/dist/operations/proof/impact.d.ts +0 -51
  225. package/dist/operations/proof/impact.d.ts.map +0 -1
  226. package/dist/operations/proof/impact.js +0 -138
@@ -116,7 +116,7 @@ The canonical workflow for any KB operation follows this pattern:
116
116
  7. **Create endpoints**: validated `kb_upsert` for new entities, sequentially
117
117
  8. **Link**: validated `kb_upsert` with `requires_rule`, `requires_predicate`, `constrains`, or `requires_property`, sequentially
118
118
  9. **Validate coverage and consistency**: targeted `rule-safety`, `rule-verifiability`, `semantic-completeness`, `logic-coverage`, `predicate-verifiability`, and `domain-contradictions`, then final full `kb_check`
119
- 10. **Prove execution**: read `kb_status.proofSnapshot`, run `kibi prove` so each configured integration executes once and its `kibi.proof-run.v1` artifact is evaluated against every selected test's `kibi.proof-contract.v1` obligations, appending idempotent `kibi.proof-receipt.v1` receipts; then re-run `kb_coverage`. Never promote durable test status into fresh evidence.
119
+ 10. **Prove execution**: read `kb_status.proofSnapshot`, run `kibi prove` so each configured integration executes once and its `kibi.proof-run.v1` artifact is evaluated against every selected test's `kibi.proof-contract.v1` obligations, appending idempotent `kibi.proof-receipt.v2` receipts; then re-run `kb_coverage` and read each requirement's `evidenceLevel` and `evidenceFloor`. Never promote durable test status into fresh evidence.
120
120
  11. **Repair incrementally**: require `kb_coverage.repairPlan.scope.complete`, apply only one `ready` dependency batch per requirement, validate before every sequential write, and rerun coverage before selecting the next batch
121
121
  12. **Gate workflow evidence**: when `.kb/usage.log` exists, run `kibi usage-metrics --format json --require-acceptance`; repair ranked telemetry diagnostics and never treat stale or insufficient evidence as a pass
122
122
 
@@ -144,7 +144,7 @@ choose package managers, ground semantic claims, resolve contradictions, rerun
144
144
  E2E tests, rewrite receipt history, remap authored symbols, or accept
145
145
  limitations. Those actions remain explicit review/operator/execution steps.
146
146
 
147
- For `e2e_receipt_freshness_low`, query each listed requirement/test gap and run `kibi prove --requirement <id>` (or the covering integration); this appends proof receipts idempotently and preserves history. If `coverage_depth_review` conflicts with a coverage row whose `proofStages.passingE2e.status` is `passed`, report the diagnostic as a stale heuristic and keep any independent proof gaps unresolved.
147
+ For `e2e_receipt_freshness_low`, query each listed requirement/test gap and run `kibi prove --requirement <id>` (or the covering integration); this appends proof receipts idempotently and preserves history. If `coverage_depth_review` conflicts with a coverage row whose `proofStages.passingE2e.status` is `passed`, report the diagnostic as a stale heuristic and keep any independent proof gaps unresolved. For `coarse_anchor_only_review`, the requirement is implemented only by whole-file anchors: link the functions, methods or types that implement it (with `covered_by` to their tests) so its `tested` evidence is tied to that code.
148
148
 
149
149
  ## Creating a New Feature
150
150
  ```
@@ -172,8 +172,8 @@ Do not create a test-fact pair. Facts describe invariants; requirements or scena
172
172
 
173
173
  1. Confirm the exact `REQ -> SCEN -> TEST` path and require typed `verification_scope: end_to_end`; direct requirement-to-test links do not satisfy the conservative scenario stage.
174
174
  2. Read `kb_status` and retain its available `proofSnapshot`. Stop if the runtime reports `unknown`; proof must fail closed when the code identity cannot be computed.
175
- 3. Run the exact E2E command against that snapshot. Record runner, command, start/finish timestamps, outcome, an environment SHA-256, and an artifact/output SHA-256. Do not mint a passed receipt from an authored test status or from an unexecuted assertion.
176
- 4. Preserve every existing receipt byte-for-byte and append the derived `kibi.proof-receipt.v1` object with strictly later `finished_at`. Earlier receipts may bind older contracts or fingerprints; they remain audit history but cannot prove the current contract. Mutation and incremental sync reject history removal, rewriting, and reordering.
175
+ 3. Run `kibi prove --test TEST-<id>` (or `--requirement`, `--integration`, `--all`). It runs the configured producer once against that snapshot and appends a `kibi.proof-receipt.v2` receipt per evaluated contract. Never hand-write a receipt, and never mint a passed receipt from an authored test status or from an unexecuted assertion.
176
+ 4. Receipts are append-only. Earlier receipts, including `kibi.proof-receipt.v1` ones, may bind older contracts or fingerprints; they remain audit history but cannot prove the current contract. Mutation and incremental sync reject history removal, rewriting, and reordering.
177
177
  5. Re-read `kb_status`; if the snapshot changed during the run, discard the candidate as proof and rerun against the new snapshot. Then run `kb_coverage` and inspect `proofStages.passingE2e.receiptEvidence` plus gap codes.
178
178
 
179
179
  Only the newest receipt matching the live snapshot, current contract hash, and current execution fingerprint qualifies, and it must be passed, no more than seven days old, and no more than five minutes in the future. Wrong-snapshot and older-contract history is retained but cannot prove the current test. `missing_proof_receipt`, `stale_proof_receipt`, `failed_proof_receipt`, `invalid_proof_receipt`, `proof_contract_mismatch`, and `proof_snapshot_unavailable` are repair states, not warnings to waive.
@@ -363,6 +363,24 @@ h1 span {
363
363
  text-transform: uppercase;
364
364
  letter-spacing: .06em;
365
365
  }
366
+ .claims-proved {
367
+ margin-left: 6px;
368
+ opacity: 0.75;
369
+ font-weight: 400;
370
+ }
371
+ .evidence-floor {
372
+ margin-left: 6px;
373
+ font-weight: 400;
374
+ opacity: 0.75;
375
+ }
376
+ .evidence-floor--below {
377
+ color: var(--red);
378
+ opacity: 1;
379
+ }
380
+ .evidence-floor--pending_reproof {
381
+ color: var(--amber);
382
+ opacity: 1;
383
+ }
366
384
  .requirement__id {
367
385
  margin-bottom: 7px;
368
386
  color: var(--muted);
@@ -392,6 +410,11 @@ h1 span {
392
410
  color: var(--green);
393
411
  background: rgba(98, 230, 167, 0.08);
394
412
  }
413
+ .proof-badge--proved {
414
+ border-color: rgba(98, 230, 167, 0.45);
415
+ color: var(--green);
416
+ background: rgba(98, 230, 167, 0.16);
417
+ }
395
418
  .proof-badge--unresolved {
396
419
  border-color: rgba(255, 125, 144, 0.25);
397
420
  color: var(--red);
@@ -1036,6 +1059,11 @@ h1 {
1036
1059
  color: var(--success);
1037
1060
  background: rgba(99, 201, 154, 0.07);
1038
1061
  }
1062
+ .proof-badge--proved {
1063
+ border-color: rgba(99, 201, 154, 0.55);
1064
+ color: var(--success);
1065
+ background: rgba(99, 201, 154, 0.16);
1066
+ }
1039
1067
  .proof-badge--unresolved {
1040
1068
  border-color: rgba(240, 113, 120, 0.3);
1041
1069
  color: var(--danger);
@@ -1043,6 +1071,9 @@ h1 {
1043
1071
  }
1044
1072
  .stages {
1045
1073
  grid-template-columns: repeat(5, minmax(0, 1fr));
1074
+ }
1075
+ .stages:has(> :nth-child(6)) {
1076
+ grid-template-columns: repeat(6, minmax(0, 1fr));
1046
1077
  gap: 0;
1047
1078
  }
1048
1079
  .stage {
@@ -1178,7 +1209,8 @@ footer {
1178
1209
  .proof-path__header p {
1179
1210
  text-align: left;
1180
1211
  }
1181
- .stages {
1212
+ .stages,
1213
+ .stages:has(> :nth-child(6)) {
1182
1214
  grid-template-columns: 1fr;
1183
1215
  }
1184
1216
  .stage {
@@ -1245,3 +1277,8 @@ footer {
1245
1277
  color: inherit;
1246
1278
  }
1247
1279
  }
1280
+ .kb-certificates {
1281
+ margin: 14px 0 28px;
1282
+ color: var(--muted);
1283
+ font-size: 13px;
1284
+ }
@@ -8,14 +8,22 @@ export type HtmlReportCoverage = Readonly<{
8
8
  rows: readonly UnknownRecord[];
9
9
  meta?: UnknownRecord;
10
10
  }>;
11
+ /** A kibi.certificates.v1 bundle published next to the report. */
12
+ export type HtmlReportKbCertificates = Readonly<{
13
+ count: number;
14
+ kinds: Readonly<Record<string, number>>;
15
+ href: string;
16
+ }>;
11
17
  export type HtmlReportInput = Readonly<{
12
18
  requirements: HtmlReportCoverage;
13
19
  symbols: HtmlReportCoverage;
14
20
  branch: string;
15
21
  generatedAt: Date;
16
22
  repository?: ReportRepository;
23
+ kbCertificates?: HtmlReportKbCertificates;
17
24
  }>;
18
25
  export declare function firstFailingProofGate(gates: readonly ProofGateKey[], passes: (gate: ProofGateKey) => boolean): ProofGateKey | "tested";
19
26
  export declare function earliestUnmetGate(row: UnknownRecord): ProofGateKey | "tested";
27
+ export declare function certificateRejectionLines(row: UnknownRecord): readonly string[];
20
28
  export declare function renderHtmlReport(input: HtmlReportInput): string;
21
29
  //# sourceMappingURL=html-report.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-report.d.ts","sourceRoot":"","sources":["../../src/report/html-report.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,KAAK,gBAAgB,EAMtB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAuB9D,eAAO,MAAM,UAAU,6FACqE,CAAC;AAG7F,eAAO,MAAM,wBAAwB,gEAC0B,CAAC;AAEhE,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,OAAO,EAAE,aAAa,CAAC;IACvB,IAAI,EAAE,SAAS,aAAa,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB,CAAC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,YAAY,EAAE,kBAAkB,CAAC;IACjC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,IAAI,CAAC;IAClB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B,CAAC,CAAC;AAkNH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,MAAM,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,GACtC,YAAY,GAAG,QAAQ,CAKzB;AAID,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,GAAG,QAAQ,CAM7E;AAqZD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAuM/D"}
1
+ {"version":3,"file":"html-report.d.ts","sourceRoot":"","sources":["../../src/report/html-report.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,YAAY,EAGlB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,KAAK,gBAAgB,EAMtB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAuB9D,eAAO,MAAM,UAAU,6FACqE,CAAC;AAG7F,eAAO,MAAM,wBAAwB,gEAC0B,CAAC;AAEhE,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,OAAO,EAAE,aAAa,CAAC;IACvB,IAAI,EAAE,SAAS,aAAa,EAAE,CAAC;IAC/B,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB,CAAC,CAAC;AAEH,kEAAkE;AAClE,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,YAAY,EAAE,kBAAkB,CAAC;IACjC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,IAAI,CAAC;IAClB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,wBAAwB,CAAC;CAC3C,CAAC,CAAC;AAkNH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,MAAM,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,GACtC,YAAY,GAAG,QAAQ,CAKzB;AAID,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,GAAG,QAAQ,CAM7E;AAyWD,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,aAAa,GACjB,SAAS,MAAM,EAAE,CAWnB;AA2LD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAiN/D"}
@@ -285,6 +285,7 @@ function requirementStages(row, repository) {
285
285
  const testSources = sourceCoordinates(record(stages.scenarioTests).sources);
286
286
  const productionSources = sourceCoordinates(productionSymbols.coordinates);
287
287
  const executableSources = sourceCoordinates(executableSymbols.coordinates);
288
+ const certificate = certificateStage(row);
288
289
  let implementationState = "failed";
289
290
  let implementationDetail = "No production symbol ownership";
290
291
  if (stageStatus(productionSymbols) === "passed" &&
@@ -342,6 +343,7 @@ function requirementStages(row, repository) {
342
343
  state: e2eState,
343
344
  },
344
345
  evidenceStage(passingE2e, testSources, repository),
346
+ ...(certificate === undefined ? [] : [certificate]),
345
347
  ];
346
348
  }
347
349
  function renderStage(stage) {
@@ -395,16 +397,36 @@ function renderContradiction(conflict) {
395
397
  <p>${escapeHtml(text(conflict.reason, "Two current requirements encode incompatible claims."))}</p>
396
398
  </div>`;
397
399
  }
400
+ /**
401
+ * The requirement's evidence floor, when it has one: required_evidence, or
402
+ * tested for a firm requirement. A floor of unverified accepts anything and
403
+ * reads as no floor.
404
+ */
405
+ // implements REQ-kibi-evidence-floors
406
+ function evidenceFloor(row) {
407
+ const floor = record(row.evidenceFloor);
408
+ const required = text(floor.required);
409
+ if (!required || required === "unverified")
410
+ return undefined;
411
+ return {
412
+ required,
413
+ source: text(floor.source, "explicit"),
414
+ status: text(floor.status, "below"),
415
+ };
416
+ }
398
417
  function rowSeverity(row) {
399
418
  const gaps = strings(row.proofGaps);
400
419
  if (gaps.includes("blocking_contradiction"))
401
420
  return 0;
402
- if (gaps.includes("stale_proof_receipt"))
421
+ if (evidenceFloor(row)?.status === "below")
403
422
  return 1;
404
- if (row.proofStatus !== "tested")
423
+ if (gaps.includes("stale_proof_receipt"))
405
424
  return 2;
406
- return 3;
425
+ if (row.proofStatus !== "tested")
426
+ return 3;
427
+ return 4;
407
428
  }
429
+ // implements REQ-kibi-html-health-report, REQ-kibi-evidence-floors
408
430
  function rowStates(row) {
409
431
  const states = new Set();
410
432
  const gaps = strings(row.proofGaps);
@@ -412,18 +434,95 @@ function rowStates(row) {
412
434
  states.add("tested");
413
435
  else
414
436
  states.add("attention");
437
+ if (row.evidenceLevel === "proved")
438
+ states.add("proved");
439
+ const floorStatus = evidenceFloor(row)?.status;
440
+ if (floorStatus === "below")
441
+ states.add("below_floor");
442
+ if (floorStatus === "pending_reproof")
443
+ states.add("pending_reproof");
415
444
  if (gaps.includes("stale_proof_receipt"))
416
445
  states.add("stale");
417
446
  if (gaps.includes("blocking_contradiction"))
418
447
  states.add("contradiction");
419
448
  return [...states].join(" ");
420
449
  }
450
+ const FLOOR_STATUS_LABELS = {
451
+ met: "met",
452
+ below: "below",
453
+ pending_reproof: "pending re-proof",
454
+ };
455
+ // implements REQ-kibi-evidence-floors
456
+ function renderFloorChip(floor) {
457
+ if (floor === undefined)
458
+ return "";
459
+ const origin = floor.source === "firmness"
460
+ ? "the default floor for a firm requirement"
461
+ : "set by required_evidence";
462
+ const status = FLOOR_STATUS_LABELS[floor.status] ?? humanize(floor.status);
463
+ return ` <span class="evidence-floor evidence-floor--${escapeHtml(floor.status)}" title="Evidence floor: ${escapeHtml(floor.required)}, ${escapeHtml(origin)}">floor ${escapeHtml(floor.required)}${floor.source === "explicit" ? "*" : ""} · ${escapeHtml(status)}</span>`;
464
+ }
465
+ /**
466
+ * Certificates a requirement's tests carry: the proof kinds that earned
467
+ * proved, and certificates or claim bindings that no longer re-check.
468
+ */
469
+ // implements REQ-kibi-code-proof-kinds
470
+ function certificateStage(row) {
471
+ const certificate = records(row.evidence).find((entry) => text(entry.kind) === "certificate");
472
+ const rejections = certificateRejectionLines(row);
473
+ const claims = record(row.claimSummary);
474
+ const applicable = count(claims.applicable);
475
+ const proved = count(claims.proved);
476
+ const claimText = applicable > 0 ? `${proved}/${applicable} claims proved` : "";
477
+ if (certificate !== undefined) {
478
+ const kinds = strings(certificate.kinds).join(", ");
479
+ const tests = strings(certificate.tests);
480
+ return {
481
+ label: "Certificate",
482
+ detail: escapeHtml([
483
+ `${kinds || "certificate"} · ${tests.length} ${tests.length === 1 ? "test" : "tests"}`,
484
+ claimText,
485
+ ]
486
+ .filter(Boolean)
487
+ .join(" · ")),
488
+ state: rejections.length > 0 ? "warning" : "passed",
489
+ };
490
+ }
491
+ if (rejections.length > 0) {
492
+ return {
493
+ label: "Certificate",
494
+ detail: escapeHtml(`${rejections.length} ${rejections.length === 1 ? "certificate does" : "certificates do"} not re-check`),
495
+ state: "failed",
496
+ };
497
+ }
498
+ if (proved > 0 || count(claims.attested) > 0) {
499
+ return {
500
+ label: "Certificate",
501
+ detail: escapeHtml(claimText),
502
+ state: "warning",
503
+ };
504
+ }
505
+ return undefined;
506
+ }
507
+ // implements REQ-kibi-code-proof-kinds
508
+ export function certificateRejectionLines(row) {
509
+ return [
510
+ ...records(row.certificateRejections).map((item) => `${text(item.test, "test")}: certificate rejected, ${text(item.reason, "no reason given")}`),
511
+ ...records(row.claimBindingRejections).map((item) => `${text(item.test, "test")}: binding for ${text(item.claimKey, "claim")} rejected, ${text(item.reason, "no reason given")}`),
512
+ ];
513
+ }
421
514
  function renderIssueList(codes, className, singular, plural) {
422
515
  if (codes.length === 0)
423
516
  return "";
424
517
  const label = `${codes.length} ${codes.length === 1 ? singular : plural}`;
425
518
  return `<details class="${className}"><summary>${escapeHtml(label)}</summary><ul>${codes.map((code) => `<li>${escapeHtml(humanize(code))}</li>`).join("")}</ul></details>`;
426
519
  }
520
+ function renderRejectionList(lines) {
521
+ if (lines.length === 0)
522
+ return "";
523
+ const label = `${lines.length} ${lines.length === 1 ? "certificate rejection" : "certificate rejections"}`;
524
+ return `<details class="proof-gaps certificate-rejections"><summary>${escapeHtml(label)}</summary><ul>${lines.map((line) => `<li>${escapeHtml(line)}</li>`).join("")}</ul></details>`;
525
+ }
427
526
  function renderRequirement(row, repository) {
428
527
  const id = text(row.id, "REQ-UNKNOWN");
429
528
  const title = text(row.title, "Untitled requirement");
@@ -439,8 +538,15 @@ function renderRequirement(row, repository) {
439
538
  : proofAdvisories;
440
539
  const conflicts = records(record(record(row.proofStages).contradictions).conflicts).filter((conflict) => text(conflict.status) === "contradiction");
441
540
  const stages = requirementStages(row, repository);
442
- const badgeLabel = proofStatus === "tested" ? "Tested" : "Needs attention";
443
541
  const evidenceLevel = text(row.evidenceLevel, "unverified");
542
+ const badgeLabel = proofStatus !== "tested"
543
+ ? "Needs attention"
544
+ : evidenceLevel === "proved"
545
+ ? "Proved"
546
+ : "Tested";
547
+ const floor = evidenceFloor(row);
548
+ const rejections = certificateRejectionLines(row);
549
+ const claims = claimsProvedLabel(row);
444
550
  const requirementSource = sourceCoordinate({
445
551
  path: text(record(record(row.proofStages).sourceCoordinates).requirementPath, text(row.source)),
446
552
  }) ?? sourceCoordinate({ path: text(row.source) });
@@ -448,22 +554,42 @@ function renderRequirement(row, repository) {
448
554
  return `<article class="requirement requirement--${escapeHtml(proofStatus)}" data-state="${rowStates(row)}" data-gate="${escapeHtml(gate)}">
449
555
  <header class="requirement__header">
450
556
  <div>
451
- <div class="requirement__id">${linkedLabel(id, sourceWebUrl(repository, requirementSource))} <span class="evidence-level evidence-level--${escapeHtml(evidenceLevel)}" title="Evidence level">${escapeHtml(evidenceLevel)}</span></div>
557
+ <div class="requirement__id">${linkedLabel(id, sourceWebUrl(repository, requirementSource))} <span class="evidence-level evidence-level--${escapeHtml(evidenceLevel)}" title="Evidence level">${escapeHtml(evidenceLevel)}</span>${renderFloorChip(floor)}${claims === null ? "" : ` <span class="claims-proved" title="Requirement claims a re-checked certificate derives">${escapeHtml(claims)}</span>`}</div>
452
558
  <h3>${linkedLabel(title, sourceWebUrl(repository, requirementSource))}</h3>
453
559
  </div>
454
- <span class="proof-badge proof-badge--${escapeHtml(proofStatus)}">${escapeHtml(badgeLabel)}</span>
560
+ <span class="proof-badge proof-badge--${escapeHtml(badgeLabel === "Proved" ? "proved" : proofStatus)}">${escapeHtml(badgeLabel)}</span>
455
561
  </header>
456
562
  <ul class="stages">${stages.map(renderStage).join("")}</ul>
457
563
  ${conflicts.map(renderContradiction).join("")}
458
564
  ${renderIssueList(blockingGaps, "proof-gaps", "proof gap", "proof gaps")}
459
565
  ${renderIssueList(advisories, "proof-advisories", "advisory", "advisories")}
566
+ ${renderRejectionList(rejections)}
460
567
  </article>`;
461
568
  }
569
+ // implements REQ-kibi-claim-bound-proofs
570
+ function claimsProvedLabel(row) {
571
+ const summary = record(row.claimSummary);
572
+ const applicable = summary.applicable;
573
+ if (typeof applicable !== "number" || applicable === 0)
574
+ return null;
575
+ const proved = typeof summary.proved === "number" ? summary.proved : 0;
576
+ return `${proved}/${applicable} claims proved`;
577
+ }
462
578
  // implements REQ-kibi-evidence-levels
463
579
  function evidenceCount(rows, level) {
464
580
  return rows.filter((row) => text(row.evidenceLevel, "unverified") === level)
465
581
  .length;
466
582
  }
583
+ // implements REQ-kibi-kb-certificates
584
+ function renderKbCertificates(bundle) {
585
+ if (bundle === undefined)
586
+ return "";
587
+ const kinds = Object.entries(bundle.kinds)
588
+ .sort(([left], [right]) => left.localeCompare(right))
589
+ .map(([kind, total]) => `${total.toLocaleString("en-US")} ${humanize(kind).toLowerCase()}`)
590
+ .join(", ");
591
+ return `<p class="kb-certificates">KB consistency: ${bundle.count.toLocaleString("en-US")} ${bundle.count === 1 ? "certificate" : "certificates"}${kinds ? ` (${escapeHtml(kinds)})` : ""} · <a href="${escapeHtml(bundle.href)}">${escapeHtml(bundle.href)}</a> · re-check with <code>kibi check --certificates ${escapeHtml(bundle.href)}</code></p>`;
592
+ }
467
593
  function metric(label, value, tone = "") {
468
594
  return `<div class="metric${tone ? ` metric--${tone}` : ""}"><span>${escapeHtml(label)}</span><strong>${value.toLocaleString("en-US")}</strong></div>`;
469
595
  }
@@ -519,8 +645,11 @@ function reportIdentity(input) {
519
645
  function renderFilters(counts) {
520
646
  const labels = {
521
647
  all: "All",
648
+ proved: "Proved",
522
649
  tested: "Tested",
523
650
  attention: "Needs attention",
651
+ below_floor: "Below floor",
652
+ pending_reproof: "Pending re-proof",
524
653
  stale: "Stale evidence",
525
654
  contradiction: "Contradictions",
526
655
  };
@@ -551,6 +680,8 @@ export function renderHtmlReport(input) {
551
680
  const staleEvidence = currentRows.filter((row) => strings(row.proofGaps).includes("stale_proof_receipt")).length;
552
681
  const withoutImplementation = currentRows.filter((row) => strings(row.proofGaps).includes("missing_production_symbol")).length;
553
682
  const contradictions = contradictionRows(currentRows);
683
+ const belowFloor = currentRows.filter((row) => evidenceFloor(row)?.status === "below").length;
684
+ const pendingReproof = currentRows.filter((row) => evidenceFloor(row)?.status === "pending_reproof").length;
554
685
  const unmappedProductionSymbols = Math.max(0, count(symbolSummary.uncovered) - count(symbolSummary.mixedRole));
555
686
  const generatedAt = input.generatedAt.toISOString();
556
687
  const snapshot = text(input.requirements.meta?.proofSnapshot);
@@ -618,14 +749,18 @@ export function renderHtmlReport(input) {
618
749
  <section class="metrics" aria-label="Requirement health summary">
619
750
  ${metric("Requirements", currentRequirements)}
620
751
  ${metric("Tested end to end", tested, "good")}
752
+ ${metric("Proved by certificate", evidenceCount(currentRows, "proved"), evidenceCount(currentRows, "proved") ? "good" : "")}
621
753
  ${metric("Asserted, no current test", evidenceCount(currentRows, "asserted"), evidenceCount(currentRows, "asserted") ? "warn" : "")}
622
754
  ${metric("Unverified", evidenceCount(currentRows, "unverified"), evidenceCount(currentRows, "unverified") ? "warn" : "")}
755
+ ${metric("Below evidence floor", belowFloor, belowFloor ? "bad" : "good")}
756
+ ${metric("Pending re-proof", pendingReproof, pendingReproof ? "warn" : "")}
623
757
  ${metric("Missing scenarios", missingScenarios, missingScenarios ? "warn" : "")}
624
758
  ${metric("Stale E2E evidence", staleEvidence, staleEvidence ? "warn" : "")}
625
759
  ${metric("Contradictions", contradictions.length, contradictions.length ? "bad" : "")}
626
760
  ${metric("Unmapped production symbols", unmappedProductionSymbols, unmappedProductionSymbols ? "bad" : "")}
627
761
  ${metric("Requirements without implementation", withoutImplementation, withoutImplementation ? "warn" : "")}
628
762
  </section>
763
+ ${renderKbCertificates(input.kbCertificates)}
629
764
  <section>
630
765
  <div class="section-header">
631
766
  <div><p class="eyebrow">Proof ledger</p><h2>Requirements</h2></div>
@@ -1,4 +1,4 @@
1
- export declare const REPORT_FILTERS: readonly ["all", "tested", "attention", "stale", "contradiction"];
1
+ export declare const REPORT_FILTERS: readonly ["all", "proved", "tested", "attention", "below_floor", "pending_reproof", "stale", "contradiction"];
2
2
  export type ReportFilter = (typeof REPORT_FILTERS)[number];
3
3
  export declare const PROOF_GATE_KEYS: readonly ["semantic", "scenario", "implementation", "e2e", "evidence"];
4
4
  export type ProofGateKey = (typeof PROOF_GATE_KEYS)[number];
@@ -1 +1 @@
1
- {"version":3,"file":"report-view.d.ts","sourceRoot":"","sources":["../../src/report/report-view.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,mEAMjB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,eAAO,MAAM,eAAe,wEAMlB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,YAAY,EAAE,YAAY,GAAG,QAAQ,CAAC;CACvC,CAAC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,YAAY,GAAG,KAAK,CAAC;CAC5B,CAAC,CAAC;AAGH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,eAAe,GACpB,OAAO,CAQT;AAGD,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,eAAe,EAAE,GAC/B,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CASxC"}
1
+ {"version":3,"file":"report-view.d.ts","sourceRoot":"","sources":["../../src/report/report-view.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,+GASjB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,eAAO,MAAM,eAAe,wEAMlB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,YAAY,EAAE,YAAY,GAAG,QAAQ,CAAC;CACvC,CAAC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,YAAY,GAAG,KAAK,CAAC;CAC5B,CAAC,CAAC;AAGH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,eAAe,GACpB,OAAO,CAQT;AAGD,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,SAAS,eAAe,EAAE,GAC/B,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAexC"}
@@ -1,7 +1,10 @@
1
1
  export const REPORT_FILTERS = [
2
2
  "all",
3
+ "proved",
3
4
  "tested",
4
5
  "attention",
6
+ "below_floor",
7
+ "pending_reproof",
5
8
  "stale",
6
9
  "contradiction",
7
10
  ];
@@ -24,8 +27,12 @@ export function matchesReportView(row, view) {
24
27
  export function reportFilterCounts(rows) {
25
28
  return {
26
29
  all: rows.length,
30
+ proved: rows.filter((row) => row.states.includes("proved")).length,
27
31
  tested: rows.filter((row) => row.states.includes("tested")).length,
28
32
  attention: rows.filter((row) => row.states.includes("attention")).length,
33
+ below_floor: rows.filter((row) => row.states.includes("below_floor"))
34
+ .length,
35
+ pending_reproof: rows.filter((row) => row.states.includes("pending_reproof")).length,
29
36
  stale: rows.filter((row) => row.states.includes("stale")).length,
30
37
  contradiction: rows.filter((row) => row.states.includes("contradiction"))
31
38
  .length,