kibi-cursor 2.9.3 → 2.9.6
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.
- package/.cursor-plugin/plugin.json +1 -1
- package/CHANGELOG.md +96 -0
- package/agent-plugin/plugin.json +1 -1
- package/agent-plugin/skills/kibi-commit-review/SKILL.md +8 -8
- package/agent-plugin/skills/kibi-commit-review/resources/staged-gate.md +6 -6
- package/agent-plugin/skills/kibi-decisions/SKILL.md +5 -2
- package/agent-plugin/skills/kibi-decisions/resources/decision-records.md +4 -1
- package/agent-plugin/skills/kibi-freshness/SKILL.md +2 -2
- package/agent-plugin/skills/kibi-traceability/SKILL.md +3 -2
- package/agent-plugin/skills/kibi-usage/SKILL.md +5 -3
- package/agent-plugin/skills/kibi-usage/resources/proof.md +105 -9
- package/dist/.cursor-plugin/plugin.json +1 -1
- package/dist/skills/.canon-hash.json +8 -8
- package/dist/skills/kibi-commit-review/SKILL.md +8 -8
- package/dist/skills/kibi-commit-review/resources/staged-gate.md +6 -6
- package/dist/skills/kibi-decisions/SKILL.md +5 -2
- package/dist/skills/kibi-decisions/resources/decision-records.md +4 -1
- package/dist/skills/kibi-freshness/SKILL.md +2 -2
- package/dist/skills/kibi-traceability/SKILL.md +3 -2
- package/dist/skills/kibi-usage/SKILL.md +5 -3
- package/dist/skills/kibi-usage/resources/proof.md +105 -9
- package/package.json +1 -1
- package/skills/.canon-hash.json +8 -8
- package/skills/kibi-commit-review/SKILL.md +8 -8
- package/skills/kibi-commit-review/resources/staged-gate.md +6 -6
- package/skills/kibi-decisions/SKILL.md +5 -2
- package/skills/kibi-decisions/resources/decision-records.md +4 -1
- package/skills/kibi-freshness/SKILL.md +2 -2
- package/skills/kibi-traceability/SKILL.md +3 -2
- package/skills/kibi-usage/SKILL.md +5 -3
- package/skills/kibi-usage/resources/proof.md +105 -9
|
@@ -178,8 +178,14 @@ left:
|
|
|
178
178
|
goes unhandled (a switch ending in a `never` assignment, or a
|
|
179
179
|
`satisfies Record<Domain, ...>` map). Set `witness.path` and
|
|
180
180
|
`domain_source`; the witness must import the domain. Kibi compiles the
|
|
181
|
-
witness itself (strict, with the workspace's TypeScript
|
|
182
|
-
|
|
181
|
+
witness itself (strict, with the workspace's TypeScript and the import
|
|
182
|
+
resolution and declaration files of the nearest `tsconfig.json`), so
|
|
183
|
+
`typescript` must be
|
|
184
|
+
installed in the workspace (TypeScript 7 has no compiler API: add
|
|
185
|
+
`typescript@6` as a dev dependency). With `proves`, Kibi decides each
|
|
186
|
+
claim with its own witness and reports the fields or members that break
|
|
187
|
+
it. When the test's compile failed, the rejection adds the first error
|
|
188
|
+
Kibi's own compile of the witness reports.
|
|
183
189
|
- `arithmetic`: a claim on one `int` or `real` variable decided exactly from
|
|
184
190
|
typed facts. Set `constraint_source: { fact_ids: [FACT-...] }` to the
|
|
185
191
|
numeric `property_value` facts (one subject and property); the
|
|
@@ -187,10 +193,93 @@ left:
|
|
|
187
193
|
exactly their constraints. To read the value from the code instead, set
|
|
188
194
|
`value_source: [{ symbol_id: SYM-<constant>, export: <name> }]`; Kibi
|
|
189
195
|
evaluates the number export itself and adds `variable eq value` as an
|
|
190
|
-
assumption.
|
|
196
|
+
assumption. For a count claim over a collection ("exactly 32 tools") add
|
|
197
|
+
`measure: count` and name the list, set, map or object export; Kibi uses
|
|
198
|
+
its size, so do not add a number export just for the proof. A count
|
|
199
|
+
claim needs only `value_source`. Naming the claim's own fact in
|
|
200
|
+
`constraint_source` assumes the claim: without `value_source` Kibi counts
|
|
201
|
+
that derivation as intent only (tested), and with it a code value that
|
|
202
|
+
breaks the claim shows up as contradictory assumptions, which the
|
|
203
|
+
rejection names.
|
|
204
|
+
A claim that every member of a closed set has a property ("Every currency
|
|
205
|
+
in GBP, ILS and ZAR must fail closed") is a set fact whose `property_key`
|
|
206
|
+
names the property, whose `value_set` is the members and whose operator
|
|
207
|
+
is `includes` (other members may have the property too, so two such
|
|
208
|
+
claims over different sets do not contradict). Prove it with `rule`: Kibi
|
|
209
|
+
checks the property on each listed member. The kinds that compare the
|
|
210
|
+
whole set (`exhaustive`, `state_machine`) reject an `includes` fact.
|
|
191
211
|
- `smt`: an SMT-LIB query that declares the facts' property as a constant,
|
|
192
212
|
asserts each `constraint_source` fact constraint and then the claim's
|
|
193
213
|
negation. Kibi re-runs z3 or cvc5 on it and accepts only `unsat`.
|
|
214
|
+
- `rule`: decisions over finite domains. Set `predicate_source: {<predicate>:
|
|
215
|
+
{ symbol_id }}` to the function behind each predicate the claim uses (it
|
|
216
|
+
takes the arguments in order and returns a boolean) and `domains: {<type>:
|
|
217
|
+
{ symbol_id }}` to the export listing each argument type's values. Kibi
|
|
218
|
+
calls every function on every combination and model checks the claim's
|
|
219
|
+
fact: a `kibi.logic.v1` rule fact (from `kb_model_requirement` with
|
|
220
|
+
`logic`) must hold for every assignment, a predicate fact must be decided
|
|
221
|
+
as it says, and a set fact whose `property_key` names a predicate needs it
|
|
222
|
+
true for every member. A type name is also a one-argument predicate
|
|
223
|
+
(`role(R)`) to range a variable. A failure names the assignment. A domain
|
|
224
|
+
can come from the project instead of an export (`domains: {<type>:
|
|
225
|
+
{source: {...}}}`, see `source` below). When the predicate is a test
|
|
226
|
+
harness that drives real code (it calls the handler with each role), add
|
|
227
|
+
`harness_for: [SYM-...]` naming that code; the claim binds with scope
|
|
228
|
+
`harness`, which proves, and those symbols must be `covered_by` the test.
|
|
229
|
+
Add `export: <name>` to a `predicate_source` entry when the function's
|
|
230
|
+
export is not the symbol's title.
|
|
231
|
+
- `state_machine`: set `domain_source` to the transition table (object or
|
|
232
|
+
Map from state to next states, or `[from, to]` pairs) or to a
|
|
233
|
+
`next(state, event)` function with `domains: {state, event}`;
|
|
234
|
+
`initial_source` names the initial state. Model "transitions must be one of
|
|
235
|
+
a -> b, ..." as a `transitions` set fact (members `a->b`), and terminal,
|
|
236
|
+
initial or reachable states as `terminal_states`, `initial_states` or
|
|
237
|
+
`reachable_states` set facts; Kibi checks that projection exactly.
|
|
238
|
+
Temporal claims use two more projections: "a cancelled invoice can never
|
|
239
|
+
become paid" is a `reachable_pairs` fact with `operator: excludes` and
|
|
240
|
+
member `cancelled->paid`, and "every path from draft to paid must pass
|
|
241
|
+
through approved" is a `required_waypoints` fact with member
|
|
242
|
+
`draft->paid via approved` (paid must be reachable from draft, and not
|
|
243
|
+
once approved is removed). Any projection also takes `includes`,
|
|
244
|
+
`subset_of` and `excludes`. Rules over a machine use `transition`,
|
|
245
|
+
`reachable`, `initial`, `terminal`, `state`.
|
|
246
|
+
- `regex`: set `pattern_source` to a `RegExp`, a Python `re.compile(...)` or
|
|
247
|
+
a string constant. Model "X must match `re`" as a string fact with
|
|
248
|
+
`operator: matches` (a JavaScript pattern with the `u` flag, matched
|
|
249
|
+
whole); Kibi decides exact language equality and reports the shortest
|
|
250
|
+
string only one side accepts. Backreferences, lookaround, `\b`, the `g`,
|
|
251
|
+
`y`, `m` and `v` flags, Python `\d`/`\w` without `re.ASCII` and
|
|
252
|
+
non-ASCII letters under `i` are refused with the reason. An exact string
|
|
253
|
+
fact (`eq`/`neq`) checks a constant.
|
|
254
|
+
- `source`: Kibi reads a project source itself and checks a set fact
|
|
255
|
+
against what it read, so the test only runs the proof (it may write
|
|
256
|
+
nothing, or `sourceCertificate({ testId })`). Set `source: {reader, ...}`:
|
|
257
|
+
`json`/`yaml` (`file`, `path`, `select`), `glob` (`pattern`, `capture`),
|
|
258
|
+
`openapi` (`file`, `select: operations|unsecured_operations|...`),
|
|
259
|
+
`references` (`files`, `extract: env|imports|calls|string_args|thrown|
|
|
260
|
+
property`), `schema` (`format: drizzle|prisma|sql`, `select:
|
|
261
|
+
tables|columns|required_columns|nullable_columns|foreign_keys`), `routes`
|
|
262
|
+
(Hono or Express app export, `path_prefix`, `names_from`, `select:
|
|
263
|
+
routes|middleware`) or `validator` (zod, valibot or pydantic, `select:
|
|
264
|
+
fields|required_fields|optional_fields`). A member Kibi cannot read
|
|
265
|
+
statically (a computed env name, a dynamic import, an env object handed
|
|
266
|
+
to a variable) fails the read with its location, and so does an empty
|
|
267
|
+
read (a glob matching no file, migrations with no `CREATE TABLE`), so a
|
|
268
|
+
read is never silently partial. Model the claim as a set fact: `eq`
|
|
269
|
+
(exactly), `includes` (at least), `subset_of` ("must be one of"),
|
|
270
|
+
`excludes` ("must never use"); `property_key: required_fields` or
|
|
271
|
+
`nullable_fields` (only `eq`/`includes`) with bare members `name` for
|
|
272
|
+
"every table" (it also covers tables added later) or `table.name` for
|
|
273
|
+
one; `middleware` with `includes` for "every route under /p must use M"
|
|
274
|
+
(Kibi checks each route). Name middleware with `names_from`: a
|
|
275
|
+
zero-argument factory export such as `requireAuth()` names the
|
|
276
|
+
middleware it returns `requireAuth`. Write the fact with `kb_model`
|
|
277
|
+
(requirement mode, `operator` plus a list `value`) or `kb_upsert`. The
|
|
278
|
+
receipt stales when a file the read touched changes, and the claim binds
|
|
279
|
+
with scope `source`. `value_source` accepts `{source, measure: count}`.
|
|
280
|
+
The builders need kibi-cli 2.33.0 or newer in the project. The env
|
|
281
|
+
extractor reads `process.env`, `import.meta.env`, `Bun.env`,
|
|
282
|
+
`Deno.env.get`, `os.environ` and `os.getenv`, through casts.
|
|
194
283
|
|
|
195
284
|
`arithmetic` and `smt` from `constraint_source` alone prove that the
|
|
196
285
|
knowledge base's facts entail the claim, not that code follows the facts:
|
|
@@ -202,8 +291,11 @@ Every certificate contract names the claims it proves in `proves:
|
|
|
202
291
|
[CLAIM-...]` (blocking `proof-contract-claims` from schema 12). Kibi derives
|
|
203
292
|
each claim's obligation from its grounding fact: a set fact (`value_type:
|
|
204
293
|
set`, `value_set: [...]`) needs the `exhaustive` domain or the `typecheck`
|
|
205
|
-
domain type to be exactly the set
|
|
206
|
-
|
|
294
|
+
domain type to be exactly the set (with `property_key: required_fields`,
|
|
295
|
+
`typecheck` instead needs every member to be a required, non-nullable field
|
|
296
|
+
of the domain type); a numeric fact needs the `arithmetic` claim or the
|
|
297
|
+
negated `smt` assertion to be its constraint; rule, predicate, machine and
|
|
298
|
+
string facts need the `rule`, `state_machine` or `regex` checks above. The receipt
|
|
207
299
|
records one binding per claim: `derived` (checked, the only kind that
|
|
208
300
|
proves), `attested` (the fact has no derivation; counts as tested) or
|
|
209
301
|
`rejected` with the reason. Model an enumerated claim as a set fact and a
|
|
@@ -212,13 +304,16 @@ REQ-...` shows each claim with its bindings.
|
|
|
212
304
|
|
|
213
305
|
Build the certificate with `kibi-cli/proof-certificates`
|
|
214
306
|
(`exhaustiveCertificate`, `typecheckCertificate`, `arithmeticCertificate`,
|
|
215
|
-
`smtCertificate`
|
|
216
|
-
|
|
307
|
+
`smtCertificate`, `ruleCertificate`, `stateMachineCertificate`,
|
|
308
|
+
`regexCertificate`, `sourceCertificate`; `readProjectSource` returns Kibi's
|
|
309
|
+
read for a test that wants to assert on it), fail the test when it records a failure
|
|
310
|
+
(`failedMembers`, `failedCalls`), and call `writeCodeCertificate`; it writes to the
|
|
217
311
|
directory `kibi prove` sets in `KIBI_PROOF_CERTIFICATES` and does nothing
|
|
218
312
|
elsewhere. A Python test writes the same `kibi.code-certificate.v1` JSON
|
|
219
313
|
to that directory itself. Wire the KB: the proof file symbol is
|
|
220
314
|
`executable_for` the test and named in `required_proofs`; the domain symbol
|
|
221
|
-
|
|
315
|
+
(and every symbol a rule, machine or pattern contract names) `implements`
|
|
316
|
+
the requirement and is `covered_by` the test; the test
|
|
222
317
|
`validates` one of the requirement's scenarios. `proved` is per claim: a
|
|
223
318
|
multi-claim requirement is proved only when certificates derive every
|
|
224
319
|
applicable claim, and reads `tested` with `n/m claims proved` otherwise. A
|
|
@@ -296,7 +391,8 @@ re-run `kibi prove --stale` (or the affected selection), then confirm
|
|
|
296
391
|
unit test count only while that unit test has a current passing receipt, so
|
|
297
392
|
prove unit tests that cover type-shape symbols too.
|
|
298
393
|
|
|
299
|
-
Full reference:
|
|
394
|
+
Full reference: [Proving requirements](https://looted.github.io/kibi/reference/proving.html)
|
|
395
|
+
(`docs/proving-requirements.md` in the Kibi repository).
|
|
300
396
|
|
|
301
397
|
## Debugging proof regressions
|
|
302
398
|
|