kibi-cli 2.29.0 → 2.31.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 (116) hide show
  1. package/dist/cli-operation-metadata.d.ts +8 -8
  2. package/dist/cli-operation-metadata.js +8 -8
  3. package/dist/cli-register-reporting.d.ts.map +1 -1
  4. package/dist/cli-register-reporting.js +35 -2
  5. package/dist/commands/check-certificates.d.ts +52 -0
  6. package/dist/commands/check-certificates.d.ts.map +1 -0
  7. package/dist/commands/check-certificates.js +163 -0
  8. package/dist/commands/check.d.ts.map +1 -1
  9. package/dist/commands/check.js +4 -0
  10. package/dist/commands/discovery-table.d.ts.map +1 -1
  11. package/dist/commands/discovery-table.js +14 -2
  12. package/dist/commands/report.js +3 -3
  13. package/dist/commands/signoff.d.ts +37 -0
  14. package/dist/commands/signoff.d.ts.map +1 -0
  15. package/dist/commands/signoff.js +155 -0
  16. package/dist/operations/modeling/predicate-applicability.d.ts +5 -1
  17. package/dist/operations/modeling/predicate-applicability.d.ts.map +1 -1
  18. package/dist/operations/modeling/predicate-applicability.js +35 -2
  19. package/dist/operations/modeling/suggest-predicates.d.ts.map +1 -1
  20. package/dist/operations/modeling/suggest-predicates.js +3 -1
  21. package/dist/operations/mutation/contradictions.d.ts +7 -5
  22. package/dist/operations/mutation/contradictions.d.ts.map +1 -1
  23. package/dist/operations/mutation/contradictions.js +8 -6
  24. package/dist/operations/mutation/source-authoring.d.ts +15 -0
  25. package/dist/operations/mutation/source-authoring.d.ts.map +1 -1
  26. package/dist/operations/mutation/source-authoring.js +19 -7
  27. package/dist/operations/mutation/types.d.ts +5 -0
  28. package/dist/operations/mutation/types.d.ts.map +1 -1
  29. package/dist/operations/mutation/upsert.d.ts +14 -0
  30. package/dist/operations/mutation/upsert.d.ts.map +1 -1
  31. package/dist/operations/mutation/upsert.js +42 -36
  32. package/dist/operations/mutation/validate-upsert.d.ts.map +1 -1
  33. package/dist/operations/mutation/validate-upsert.js +61 -37
  34. package/dist/operations/planning/apply-plan.js +5 -5
  35. package/dist/operations/proof/baseline-diff.d.ts +1 -1
  36. package/dist/operations/proof/baseline-diff.js +1 -1
  37. package/dist/operations/proof/impact.d.ts +10 -4
  38. package/dist/operations/proof/impact.d.ts.map +1 -1
  39. package/dist/operations/proof/impact.js +27 -7
  40. package/dist/public/diagnostic-usage.js +2 -2
  41. package/dist/public/operations/catalog.d.ts +31 -10
  42. package/dist/public/operations/catalog.d.ts.map +1 -1
  43. package/dist/public/operations/contracts.d.ts.map +1 -1
  44. package/dist/public/operations/contracts.js +2 -0
  45. package/dist/public/operations/specs/bootstrap.d.ts +1 -1
  46. package/dist/public/operations/specs/bootstrap.js +1 -1
  47. package/dist/public/operations/specs/check-rules.generated.d.ts +1 -1
  48. package/dist/public/operations/specs/check-rules.generated.d.ts.map +1 -1
  49. package/dist/public/operations/specs/check-rules.generated.js +3 -1
  50. package/dist/public/operations/specs/check.d.ts +1 -1
  51. package/dist/public/operations/specs/composite.d.ts +1 -1
  52. package/dist/public/operations/specs/composite.js +1 -1
  53. package/dist/public/operations/specs/discovery.d.ts +1 -1
  54. package/dist/public/operations/specs/discovery.js +1 -1
  55. package/dist/public/operations/specs/impact-review-preparation.d.ts +2 -1
  56. package/dist/public/operations/specs/impact-review-preparation.d.ts.map +1 -1
  57. package/dist/public/operations/specs/impact-review-preparation.js +2 -1
  58. package/dist/public/operations/specs/planning.d.ts +1 -1
  59. package/dist/public/operations/specs/planning.js +1 -1
  60. package/dist/public/operations/specs/reporting.d.ts +25 -5
  61. package/dist/public/operations/specs/reporting.d.ts.map +1 -1
  62. package/dist/public/operations/specs/reporting.js +102 -26
  63. package/dist/public/skills/kibi-commit-review/SKILL.md +125 -0
  64. package/dist/public/skills/kibi-commit-review/resources/staged-gate.md +98 -0
  65. package/dist/public/skills/kibi-decisions/SKILL.md +130 -0
  66. package/dist/public/skills/kibi-decisions/resources/decision-records.md +142 -0
  67. package/dist/public/skills/kibi-decisions/resources/signoff-views.md +66 -0
  68. package/dist/public/skills/kibi-freshness/SKILL.md +3 -1
  69. package/dist/public/skills/kibi-traceability/SKILL.md +4 -0
  70. package/dist/public/skills/kibi-usage/SKILL.md +21 -16
  71. package/dist/public/skills/kibi-usage/resources/proof.md +36 -4
  72. package/dist/public/skills/kibi-usage/resources/workflows.md +1 -1
  73. package/dist/report/html-report.css +11 -4
  74. package/dist/report/html-report.d.ts +2 -2
  75. package/dist/report/html-report.d.ts.map +1 -1
  76. package/dist/report/html-report.js +27 -21
  77. package/dist/report/report-view.d.ts +2 -2
  78. package/dist/report/report-view.js +2 -2
  79. package/dist/signoff/collect.d.ts +39 -0
  80. package/dist/signoff/collect.d.ts.map +1 -0
  81. package/dist/signoff/collect.js +402 -0
  82. package/dist/signoff/html.d.ts +4 -0
  83. package/dist/signoff/html.d.ts.map +1 -0
  84. package/dist/signoff/html.js +210 -0
  85. package/dist/signoff/markdown.d.ts +20 -0
  86. package/dist/signoff/markdown.d.ts.map +1 -0
  87. package/dist/signoff/markdown.js +203 -0
  88. package/dist/signoff/model.d.ts +139 -0
  89. package/dist/signoff/model.d.ts.map +1 -0
  90. package/dist/signoff/model.js +142 -0
  91. package/dist/traceability/staged-consistency.d.ts.map +1 -1
  92. package/dist/traceability/staged-consistency.js +3 -1
  93. package/dist/utils/rule-registry.generated.d.ts +10 -0
  94. package/dist/utils/rule-registry.generated.d.ts.map +1 -1
  95. package/dist/utils/rule-registry.generated.js +12 -0
  96. package/package.json +2 -2
  97. package/src/public/diagnostic-usage.ts +3 -3
  98. package/src/public/operations/contracts.ts +2 -0
  99. package/src/public/operations/specs/bootstrap.ts +1 -1
  100. package/src/public/operations/specs/check-rules.generated.ts +3 -1
  101. package/src/public/operations/specs/composite.ts +1 -1
  102. package/src/public/operations/specs/discovery.ts +1 -1
  103. package/src/public/operations/specs/impact-review-preparation.ts +3 -1
  104. package/src/public/operations/specs/planning.ts +1 -1
  105. package/src/public/operations/specs/reporting.ts +114 -26
  106. package/src/public/skills/kibi-commit-review/SKILL.md +125 -0
  107. package/src/public/skills/kibi-commit-review/resources/staged-gate.md +98 -0
  108. package/src/public/skills/kibi-decisions/SKILL.md +130 -0
  109. package/src/public/skills/kibi-decisions/resources/decision-records.md +142 -0
  110. package/src/public/skills/kibi-decisions/resources/signoff-views.md +66 -0
  111. package/src/public/skills/kibi-freshness/SKILL.md +3 -1
  112. package/src/public/skills/kibi-traceability/SKILL.md +4 -0
  113. package/src/public/skills/kibi-usage/SKILL.md +21 -16
  114. package/src/public/skills/kibi-usage/resources/proof.md +36 -4
  115. package/src/public/skills/kibi-usage/resources/workflows.md +1 -1
  116. package/templates/github/kibi-badge.yml +1 -1
@@ -2,7 +2,7 @@
2
2
  id: kibi-usage
3
3
  name: Kibi Usage
4
4
  description: Use Kibi's source-first, exact-Git, migration-aware, proof-aware operations safely across MCP or the trusted local CLI, including partial completion repair.
5
- version: 2.20.0
5
+ version: 2.24.0
6
6
  kibiCompatibility: ">=1.0.0"
7
7
  tags:
8
8
  - kibi
@@ -121,6 +121,10 @@ component that renders it) with `implements` through `kb_upsert`. Without a read
121
121
  still answers and `kibi sync` regenerates the manifest. The search tip and the
122
122
  `.kb/` note appear once per session and need no action.
123
123
 
124
+ Before you edit a source file that Kibi tracks, run `kb_search` with that file in `sourceLocations`, and treat both its ranked results and its `data.answer` layer as discovery only, not as the governing text. Then call `kb_query` by `id` on each current governing requirement that the search names, read what each one requires, and make the edit only after those exact reads. A `kb_check`, `kb_status` or `kb_coverage` result does not replace that `kb_query` read. This rule only adds an exact read before the edit and does not change the order of any other step in this workflow. It adds nothing to a modeling or write task: that task still ends with the real `kb_upsert` of every planned fact and requirement and the closing `kb_check`.
125
+
126
+ For an edit that keeps the governing rule, limit the consultation before the edit to exactly two Kibi calls: `kb_search` with the file in `sourceLocations`, then one `kb_query` (by the governing requirement's `id`, or by `sourceFile` when several requirements govern the file). Do not start with `kb_status`, and do not repeat the search or the query before editing; run `kb_status`, `kb_check` and `kb_coverage` after the edit. This limit applies only to source edits. A task that models a claim keeps its full order, one step after the other: `kb_search`, then the exact `kb_query` of the supplied target, then `kb_model` with `mode: "analyze"` on the complete claim, then `mode: "predicates"` for each relational clause, then `kb_model` with `mode: "requirement"` for a strict or typed-rule clause, and only then the real `kb_upsert` of every planned fact and requirement and the closing `kb_check`. Never call `kb_model` before that exact `kb_query`, and never stop at a dry run.
127
+
124
128
  ## Safe workflow
125
129
 
126
130
  1. Always discover before you mutate: start with `kb_search`, then exact-filter with `kb_query`. Use
@@ -164,7 +168,7 @@ End every task with these five independent fields:
164
168
  taskOutcome: complete | interim | blocked
165
169
  kbState: clean_fresh | stale | dirty | legacy_compat | not_evaluated
166
170
  verificationState: fresh | dirty | unavailable | not_evaluated
167
- proofState: proven | mixed | unresolved | not_evaluated
171
+ proofState: tested | mixed | unresolved | not_evaluated
168
172
  limitationDisposition: none | accepted | unaccepted | not_applicable
169
173
  ```
170
174
 
@@ -356,7 +360,9 @@ authored. Each one is the order the write path accepts.
356
360
 
357
361
  Entities record `origin` (`kind`: `human`, `agent`, `migration`, or `import`,
358
362
  plus optional `ref` and `approved_by`). `kb_upsert` records `kind: agent` on
359
- entities you create; leave `origin.approved_by` to the person who reviews them.
363
+ entities you create; leave `origin.approved_by` to the person who reviews them,
364
+ and ask for that review with `kibi signoff` (see `kibi-decisions`), never with
365
+ a summary in your own words.
360
366
  An exception (a requirement that `exempts` another) exempts nothing until a
361
367
  human sets `approved_by`; `kb_check` flags approvals an agent recorded without
362
368
  corroboration. Never fill in an approval yourself. Record why a requirement
@@ -365,6 +371,8 @@ exists in `rationale`, or link the ADR that explains it.
365
371
  ## Decision firmness
366
372
 
367
373
  Requirements and ADRs carry `firmness`, which says what you may do with them.
374
+ Load `kibi-decisions` when a person states a rule, a hook asks before an edit
375
+ of firm code, or a request conflicts with a recorded rule.
368
376
  Search answers, `kb_query` rows and hook snippets show it (snippets label only
369
377
  `[firm: ask before changing]` and `[exploratory]`; an unlabeled decision is
370
378
  `default`).
@@ -394,17 +402,12 @@ task or in reply: then supersede it with `firmness: firm` and `origin.ref` to
394
402
  their words (or, for a correction they asked for in place, update it with
395
403
  `origin.ref` to those words), and say in the final answer which rule changed.
396
404
 
397
- Set `firmness` from what a human actually said: only their stated rule is
398
- `firm` (with `origin.ref`); "do whatever" or your own pick is `default`; a
399
- guess is `exploratory`. Write it explicitly whenever you record a decision,
400
- including when importing rules from documents, tests or tickets (a rule a
401
- person wrote there is `firm`, with `origin.ref` to that document). A
402
- supersede needs `## Why this changed` in the new entity's body (at least 12
403
- words): name the evidence (a failing test, a measured cost, a constraint the
404
- old decision missed, a new requirement, the person's instruction) and answer
405
- the old decision's reasoning; `kb_check` blocks it otherwise. A preference is
406
- not evidence: propose it instead of superseding. Kibi checks only that a firm
407
- decision has a reference; never cite words nobody said.
405
+ Set `firmness` explicitly from what a human actually said: only their stated
406
+ rule is `firm` (with `origin.ref` to their words); your own pick is `default`;
407
+ a guess is `exploratory`. A supersede needs a `## Why this changed` section of
408
+ at least 12 words naming the evidence; a preference is not evidence. Never
409
+ cite words nobody said. `kibi-decisions` has the recording and supersede
410
+ payloads.
408
411
 
409
412
  Conditional clauses ("only when", "only if", "must not ... unless") compile
410
413
  into typed `forbid` rules linked by `requires_rule`, not property facts; one
@@ -418,7 +421,8 @@ read `unresolved` as consistent. Compare the intent with each candidate's
418
421
  `statement`, then compile again with `conflictReviews`
419
422
  (`{requirementId, verdict: "conflict" | "no_conflict", note}`). On a conflict
420
423
  the plan is `blocked`: ask the human which rule holds (a firm requirement is
421
- theirs), then supersede or change it, or change the intent.
424
+ theirs), then supersede or change it, or change the intent (see
425
+ `kibi-decisions`).
422
426
 
423
427
  ## Semantic and proof guardrails
424
428
 
@@ -558,4 +562,5 @@ retrying the same payload; inspect the typed error and `nextActions`.
558
562
  Kibi may now author tracked Markdown/YAML evidence transactionally. The former
559
563
  statement “Kibi operation writes do not automatically stage markdown evidence”
560
564
  means Kibi writes do not Git-stage it: review and commit remain ordinary Git
561
- workflows.
565
+ workflows. When `kibi check --staged` or the pre-commit hook blocks a commit,
566
+ load `kibi-commit-review`.
@@ -1,6 +1,6 @@
1
1
  # Proof and Verification Workflow
2
2
 
3
- Use this resource when a requirement must be proven before handoff, when
3
+ Use this resource when a requirement must be tested end to end before handoff, when
4
4
  wiring a proof-bearing test, or when `kb_ingest_proof` or `kibi prove`
5
5
  rejected evidence.
6
6
 
@@ -97,9 +97,9 @@ Cosmetic edits (descriptions, labels) never stale proof. Execution-relevant
97
97
  edits (command, artifact, targets, options, bindings, contract) change the
98
98
  effective fingerprint and do.
99
99
 
100
- ## What counts toward proofProven
100
+ ## What counts toward proofTested
101
101
 
102
- A requirement is proven only by its scenarios' tests, and a scenario test
102
+ A requirement reaches `proofStatus: tested` only through its scenarios' tests, and a scenario test
103
103
  counts only when it is an **end-to-end** test with a valid, fresh, passing
104
104
  receipt for the current snapshot.
105
105
 
@@ -109,7 +109,7 @@ receipt for the current snapshot.
109
109
  `source` path contains `e2e`) counts as end-to-end; anything else is
110
110
  `unknown` scope.
111
111
  - A `unit` or `integration` receipt is still recorded on the test entity, but
112
- it does not move `proofProven` for a behavioural requirement: the
112
+ it does not move `proofTested` for a behavioural requirement: the
113
113
  requirement keeps the `missing_passing_e2e` gap in `proofGaps`. The one
114
114
  exception is a scenario whose specifying requirements are all grounded only
115
115
  in component-scope UI predicates (`ui_pattern`, `same_pattern`,
@@ -120,6 +120,38 @@ receipt for the current snapshot.
120
120
  receipt does not change it, and a `passing` status without a fresh receipt
121
121
  proves nothing.
122
122
 
123
+ ## Evidence levels
124
+
125
+ Every requirement row also carries `evidenceLevel`, the strength of what backs
126
+ it, and `evidence`, the entries that earned it (each with `kind`, `scope` and
127
+ `level`):
128
+
129
+ - `proved`: a re-checkable certificate covers every case. No proof kind issues
130
+ certificates yet, so nothing reaches it today.
131
+ - `tested`: `proofStatus` is `tested`; fresh E2E receipts cover every linked
132
+ scenario.
133
+ - `asserted`: a person stands behind the statement (approved, or firm by
134
+ `firmness` or a non-agent origin) but nothing current checks it.
135
+ - `unverified`: an agent wrote it, no person approved it, nothing checks it.
136
+
137
+ Report the level as it is. Never call an `asserted` or `unverified`
138
+ requirement proven or tested, and never call `tested` proved. Firmness is a
139
+ separate axis: it says how sure the person is, not how strong the evidence is.
140
+
141
+ ## Knowledge-base certificates
142
+
143
+ `kb_check` (`kibi check`) proves facts about the KB itself in its
144
+ `kb-consistency` rule and re-checks each answer with an independent checker:
145
+ property facts are consistent (a model per subject, property and scope, or an
146
+ irreducible contradiction core), predicate facts and allow/deny decisions are
147
+ consistent, and stored rules are stratified. It catches facts that contradict
148
+ only together, which the pairwise `domain-contradictions` rule misses. A
149
+ `kb-consistency` violation names the core facts and the requirements behind
150
+ them: supersede or change one of those requirements; never edit the facts so
151
+ the check passes. Quote a `kb-consistency-unresolved` diagnostic as
152
+ unresolved, never as consistent. Opposing rule pairs and scenario
153
+ feasibility are not certified yet; their own rules still decide them.
154
+
123
155
  ## Attempt semantics (factual, never optimistic)
124
156
 
125
157
  - `attempts: {status: "complete", entries: [...]}` — known history; the
@@ -9,7 +9,7 @@ success flag):
9
9
  taskOutcome: complete | interim | blocked
10
10
  kbState: clean_fresh | stale | dirty | legacy_compat | not_evaluated
11
11
  verificationState: fresh | dirty | unavailable | not_evaluated
12
- proofState: proven | mixed | unresolved | not_evaluated
12
+ proofState: tested | mixed | unresolved | not_evaluated
13
13
  limitationDisposition: none | accepted | unaccepted | not_applicable
14
14
  ```
15
15
 
@@ -341,7 +341,7 @@ h1 span {
341
341
  content: "";
342
342
  background: var(--amber);
343
343
  }
344
- .requirement--proven::before {
344
+ .requirement--tested::before {
345
345
  background: var(--green);
346
346
  }
347
347
  .requirement--unresolved::before {
@@ -356,6 +356,13 @@ h1 span {
356
356
  align-items: start;
357
357
  justify-content: space-between;
358
358
  }
359
+ .evidence-level {
360
+ margin-left: 6px;
361
+ opacity: 0.75;
362
+ font-weight: 700;
363
+ text-transform: uppercase;
364
+ letter-spacing: .06em;
365
+ }
359
366
  .requirement__id {
360
367
  margin-bottom: 7px;
361
368
  color: var(--muted);
@@ -380,7 +387,7 @@ h1 span {
380
387
  letter-spacing: .07em;
381
388
  text-transform: uppercase;
382
389
  }
383
- .proof-badge--proven {
390
+ .proof-badge--tested {
384
391
  border-color: rgba(98, 230, 167, 0.25);
385
392
  color: var(--green);
386
393
  background: rgba(98, 230, 167, 0.08);
@@ -1001,7 +1008,7 @@ h1 {
1001
1008
  .requirement::before {
1002
1009
  background: var(--warning);
1003
1010
  }
1004
- .requirement--proven::before {
1011
+ .requirement--tested::before {
1005
1012
  background: var(--success);
1006
1013
  }
1007
1014
  .requirement--unresolved::before {
@@ -1024,7 +1031,7 @@ h1 {
1024
1031
  background: rgba(242, 184, 75, 0.07);
1025
1032
  font: 800 9px / 1.2 var(--mono);
1026
1033
  }
1027
- .proof-badge--proven {
1034
+ .proof-badge--tested {
1028
1035
  border-color: rgba(99, 201, 154, 0.3);
1029
1036
  color: var(--success);
1030
1037
  background: rgba(99, 201, 154, 0.07);
@@ -15,7 +15,7 @@ export type HtmlReportInput = Readonly<{
15
15
  generatedAt: Date;
16
16
  repository?: ReportRepository;
17
17
  }>;
18
- export declare function firstFailingProofGate(gates: readonly ProofGateKey[], passes: (gate: ProofGateKey) => boolean): ProofGateKey | "proven";
19
- export declare function earliestUnmetGate(row: UnknownRecord): ProofGateKey | "proven";
18
+ export declare function firstFailingProofGate(gates: readonly ProofGateKey[], passes: (gate: ProofGateKey) => boolean): ProofGateKey | "tested";
19
+ export declare function earliestUnmetGate(row: UnknownRecord): ProofGateKey | "tested";
20
20
  export declare function renderHtmlReport(input: HtmlReportInput): string;
21
21
  //# 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;AA8YD,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,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"}
@@ -143,7 +143,7 @@ function implementationOwned(stages) {
143
143
  return productionSymbols.every((symbol) => !missingCoordinates.has(symbol));
144
144
  }
145
145
  function passesProofGate(row, gate) {
146
- if (row.proofStatus === "proven")
146
+ if (row.proofStatus === "tested")
147
147
  return true;
148
148
  const stages = record(row.proofStages);
149
149
  if (gate === "semantic") {
@@ -158,7 +158,7 @@ function passesProofGate(row, gate) {
158
158
  if (gate === "e2e") {
159
159
  return stagePassed(stages, "scenarioTests") && hasEndToEndTest(stages);
160
160
  }
161
- return row.proofStatus === "proven";
161
+ return row.proofStatus === "tested";
162
162
  }
163
163
  function proofGates(rows) {
164
164
  const definitions = [
@@ -197,13 +197,13 @@ export function firstFailingProofGate(gates, passes) {
197
197
  if (!passes(gate))
198
198
  return gate;
199
199
  }
200
- return "proven";
200
+ return "tested";
201
201
  }
202
202
  // implements REQ-kibi-html-health-report
203
203
  // covered_by TEST-kibi-html-health-report
204
204
  export function earliestUnmetGate(row) {
205
- if (row.proofStatus === "proven")
206
- return "proven";
205
+ if (row.proofStatus === "tested")
206
+ return "tested";
207
207
  return firstFailingProofGate(["semantic", "scenario", "implementation", "e2e", "evidence"], (gate) => passesProofGate(row, gate));
208
208
  }
209
209
  function evidenceStage(passingE2e, testSources, repository) {
@@ -401,15 +401,15 @@ function rowSeverity(row) {
401
401
  return 0;
402
402
  if (gaps.includes("stale_proof_receipt"))
403
403
  return 1;
404
- if (row.proofStatus !== "proven")
404
+ if (row.proofStatus !== "tested")
405
405
  return 2;
406
406
  return 3;
407
407
  }
408
408
  function rowStates(row) {
409
409
  const states = new Set();
410
410
  const gaps = strings(row.proofGaps);
411
- if (row.proofStatus === "proven")
412
- states.add("proven");
411
+ if (row.proofStatus === "tested")
412
+ states.add("tested");
413
413
  else
414
414
  states.add("attention");
415
415
  if (gaps.includes("stale_proof_receipt"))
@@ -430,8 +430,8 @@ function renderRequirement(row, repository) {
430
430
  const proofStatus = text(row.proofStatus, "missing");
431
431
  const proofGaps = strings(row.proofGaps);
432
432
  const proofAdvisories = strings(row.proofAdvisories);
433
- const blockingGaps = proofStatus === "proven" ? [] : proofGaps;
434
- const advisories = proofStatus === "proven"
433
+ const blockingGaps = proofStatus === "tested" ? [] : proofGaps;
434
+ const advisories = proofStatus === "tested"
435
435
  ? [
436
436
  ...proofAdvisories,
437
437
  ...proofGaps.filter((gap) => !proofAdvisories.includes(gap)),
@@ -439,7 +439,8 @@ function renderRequirement(row, repository) {
439
439
  : proofAdvisories;
440
440
  const conflicts = records(record(record(row.proofStages).contradictions).conflicts).filter((conflict) => text(conflict.status) === "contradiction");
441
441
  const stages = requirementStages(row, repository);
442
- const badgeLabel = proofStatus === "proven" ? "Proven" : "Needs attention";
442
+ const badgeLabel = proofStatus === "tested" ? "Tested" : "Needs attention";
443
+ const evidenceLevel = text(row.evidenceLevel, "unverified");
443
444
  const requirementSource = sourceCoordinate({
444
445
  path: text(record(record(row.proofStages).sourceCoordinates).requirementPath, text(row.source)),
445
446
  }) ?? sourceCoordinate({ path: text(row.source) });
@@ -447,7 +448,7 @@ function renderRequirement(row, repository) {
447
448
  return `<article class="requirement requirement--${escapeHtml(proofStatus)}" data-state="${rowStates(row)}" data-gate="${escapeHtml(gate)}">
448
449
  <header class="requirement__header">
449
450
  <div>
450
- <div class="requirement__id">${linkedLabel(id, sourceWebUrl(repository, requirementSource))}</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>
451
452
  <h3>${linkedLabel(title, sourceWebUrl(repository, requirementSource))}</h3>
452
453
  </div>
453
454
  <span class="proof-badge proof-badge--${escapeHtml(proofStatus)}">${escapeHtml(badgeLabel)}</span>
@@ -458,6 +459,11 @@ function renderRequirement(row, repository) {
458
459
  ${renderIssueList(advisories, "proof-advisories", "advisory", "advisories")}
459
460
  </article>`;
460
461
  }
462
+ // implements REQ-kibi-evidence-levels
463
+ function evidenceCount(rows, level) {
464
+ return rows.filter((row) => text(row.evidenceLevel, "unverified") === level)
465
+ .length;
466
+ }
461
467
  function metric(label, value, tone = "") {
462
468
  return `<div class="metric${tone ? ` metric--${tone}` : ""}"><span>${escapeHtml(label)}</span><strong>${value.toLocaleString("en-US")}</strong></div>`;
463
469
  }
@@ -513,7 +519,7 @@ function reportIdentity(input) {
513
519
  function renderFilters(counts) {
514
520
  const labels = {
515
521
  all: "All",
516
- proven: "Proven",
522
+ tested: "Tested",
517
523
  attention: "Needs attention",
518
524
  stale: "Stale evidence",
519
525
  contradiction: "Contradictions",
@@ -537,10 +543,10 @@ export function renderHtmlReport(input) {
537
543
  const total = count(summary.total);
538
544
  const notApplicable = count(summary.proofNotApplicable);
539
545
  const currentRequirements = Math.max(0, total - notApplicable);
540
- const proven = count(summary.proofProven);
546
+ const tested = count(summary.proofTested);
541
547
  const proofPercent = currentRequirements === 0
542
548
  ? 0
543
- : Math.round((proven / currentRequirements) * 100);
549
+ : Math.round((tested / currentRequirements) * 100);
544
550
  const missingScenarios = currentRows.filter((row) => strings(row.proofGaps).includes("missing_scenario")).length;
545
551
  const staleEvidence = currentRows.filter((row) => strings(row.proofGaps).includes("stale_proof_receipt")).length;
546
552
  const withoutImplementation = currentRows.filter((row) => strings(row.proofGaps).includes("missing_production_symbol")).length;
@@ -561,12 +567,10 @@ export function renderHtmlReport(input) {
561
567
  })));
562
568
  const identity = reportIdentity({ ...input, repository });
563
569
  const faviconHref = renderKibiFaviconDataUri();
564
- const scoreLabel = currentRequirements === 0
565
- ? "No current requirements"
566
- : "Strict proof coverage";
570
+ const scoreLabel = currentRequirements === 0 ? "No current requirements" : "Tested end to end";
567
571
  const scoreRatio = currentRequirements === 0
568
572
  ? "No current requirements to prove"
569
- : `${proven.toLocaleString("en-US")} of ${currentRequirements.toLocaleString("en-US")} current requirements fully proven end-to-end`;
573
+ : `${tested.toLocaleString("en-US")} of ${currentRequirements.toLocaleString("en-US")} current requirements fully tested end-to-end`;
570
574
  return `<!doctype html>
571
575
  <html lang="en">
572
576
  <head>
@@ -596,7 +600,7 @@ export function renderHtmlReport(input) {
596
600
  <h1>Intent to proof,<br>without the gaps.</h1>
597
601
  <p>Kibi compiles product intent into an inspectable chain of semantics, scenarios, implementation ownership, end-to-end tests, and fresh evidence.</p>
598
602
  </div>
599
- <div class="score" aria-label="${proofPercent}% strict proof coverage, ${proven} of ${currentRequirements} current requirements fully proven end-to-end">
603
+ <div class="score" aria-label="${proofPercent}% tested end to end, ${tested} of ${currentRequirements} current requirements fully tested end-to-end">
600
604
  <div class="score__value">${proofPercent}<span>%</span></div>
601
605
  <div class="score__label">${escapeHtml(scoreLabel)}</div>
602
606
  <div class="score__ratio">${escapeHtml(scoreRatio)}</div>
@@ -613,7 +617,9 @@ export function renderHtmlReport(input) {
613
617
  </section>
614
618
  <section class="metrics" aria-label="Requirement health summary">
615
619
  ${metric("Requirements", currentRequirements)}
616
- ${metric("Strict proof coverage", proven, "good")}
620
+ ${metric("Tested end to end", tested, "good")}
621
+ ${metric("Asserted, no current test", evidenceCount(currentRows, "asserted"), evidenceCount(currentRows, "asserted") ? "warn" : "")}
622
+ ${metric("Unverified", evidenceCount(currentRows, "unverified"), evidenceCount(currentRows, "unverified") ? "warn" : "")}
617
623
  ${metric("Missing scenarios", missingScenarios, missingScenarios ? "warn" : "")}
618
624
  ${metric("Stale E2E evidence", staleEvidence, staleEvidence ? "warn" : "")}
619
625
  ${metric("Contradictions", contradictions.length, contradictions.length ? "bad" : "")}
@@ -1,11 +1,11 @@
1
- export declare const REPORT_FILTERS: readonly ["all", "proven", "attention", "stale", "contradiction"];
1
+ export declare const REPORT_FILTERS: readonly ["all", "tested", "attention", "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];
5
5
  export type RequirementView = Readonly<{
6
6
  text: string;
7
7
  states: readonly string[];
8
- earliestGate: ProofGateKey | "proven";
8
+ earliestGate: ProofGateKey | "tested";
9
9
  }>;
10
10
  export type ReportViewQuery = Readonly<{
11
11
  query: string;
@@ -1,6 +1,6 @@
1
1
  export const REPORT_FILTERS = [
2
2
  "all",
3
- "proven",
3
+ "tested",
4
4
  "attention",
5
5
  "stale",
6
6
  "contradiction",
@@ -24,7 +24,7 @@ export function matchesReportView(row, view) {
24
24
  export function reportFilterCounts(rows) {
25
25
  return {
26
26
  all: rows.length,
27
- proven: rows.filter((row) => row.states.includes("proven")).length,
27
+ tested: rows.filter((row) => row.states.includes("tested")).length,
28
28
  attention: rows.filter((row) => row.states.includes("attention")).length,
29
29
  stale: rows.filter((row) => row.states.includes("stale")).length,
30
30
  contradiction: rows.filter((row) => row.states.includes("contradiction"))
@@ -0,0 +1,39 @@
1
+ import { type ExtractedEntity } from "../extractors/markdown.js";
2
+ import { type SignoffProof, type SignoffQuestionInput, type SignoffQuestions, type SignoffSummary } from "./model.js";
3
+ export type SignoffScope = "staged" | "working";
4
+ /** Changed code symbols per requirement they implement. */
5
+ export type AffectedRequirements = ReadonlyMap<string, readonly string[]>;
6
+ export type SignoffCollectDeps = Readonly<{
7
+ /** Run git in the workspace and return stdout; throws on failure. */
8
+ git?: (args: readonly string[]) => string;
9
+ /** Requirements the changed code implements, from the impact analysis. */
10
+ loadAffected?: (scope: SignoffScope) => Promise<AffectedRequirements>;
11
+ /** Proof rows by requirement id, from coverage. */
12
+ loadProof?: () => Promise<ReadonlyMap<string, SignoffProof>>;
13
+ now?: () => Date;
14
+ }>;
15
+ /** The requirement's statement: its semantic text, else its title. */
16
+ export declare function requirementStatement(entity: ExtractedEntity): string;
17
+ /**
18
+ * The end-of-work signoff summary: the requirements the change adds, rewrites,
19
+ * retires, or leaves unchanged while changing code that implements them, each
20
+ * with its statement, firmness, origin, scenarios and proof state.
21
+ */
22
+ export declare function collectSignoffSummary(workspaceRoot: string, scope: SignoffScope, deps?: SignoffCollectDeps): Promise<SignoffSummary>;
23
+ /**
24
+ * Requirements whose implementing code the change edits, read from the
25
+ * `requirement_statement_unverified` impact diagnostics of `kibi check`.
26
+ */
27
+ export declare function loadAffectedForScope(workspaceRoot: string, scope: SignoffScope): Promise<AffectedRequirements>;
28
+ /**
29
+ * The mid-work decision questions, numbered, with the recorded requirement a
30
+ * question would change and the recorded rules it conflicts with quoted from
31
+ * the knowledge base rather than from the agent's memory.
32
+ */
33
+ export declare function collectSignoffQuestions(workspaceRoot: string, inputs: readonly SignoffQuestionInput[], now?: () => Date): SignoffQuestions;
34
+ /**
35
+ * Parse the questions input: `{"questions":[{statement, id?, title?, quote?,
36
+ * firmness?, governs?, conflictsWith?, question?, answer?}]}` or a bare array.
37
+ */
38
+ export declare function parseSignoffQuestionsInput(raw: string): SignoffQuestionInput[];
39
+ //# sourceMappingURL=collect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/signoff/collect.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,eAAe,EAErB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAIL,KAAK,YAAY,EAEjB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EAGrB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AASpB,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhD,2DAA2D;AAC3D,MAAM,MAAM,oBAAoB,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;AAE1E,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,qEAAqE;IACrE,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC;IAC1C,0EAA0E;IAC1E,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACtE,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC;IAC7D,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC,CAAC;AAuCH,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAEpE;AAyGD;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,YAAY,EACnB,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,cAAc,CAAC,CAiKzB;AAGD;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,oBAAoB,CAAC,CA8B/B;AAGD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,SAAS,oBAAoB,EAAE,EACvC,GAAG,GAAE,MAAM,IAAuB,GACjC,gBAAgB,CA4BlB;AA+BD;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,MAAM,GACV,oBAAoB,EAAE,CAkDxB"}