kibi-cursor 2.11.0 → 2.12.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.
- package/.cursor-plugin/plugin.json +1 -1
- package/CHANGELOG.md +47 -0
- package/README.md +1 -1
- package/agent-plugin/plugin.json +1 -1
- package/agent-plugin/skills/kibi-bootstrap/SKILL.md +2 -2
- package/agent-plugin/skills/kibi-provable-code/SKILL.md +203 -0
- package/agent-plugin/skills/kibi-provable-code/resources/provable-patterns.md +172 -0
- package/agent-plugin/skills/kibi-usage/SKILL.md +4 -1
- package/agent-plugin/skills/kibi-usage/resources/proof.md +31 -10
- package/bin/hook-runner.mjs +5 -2
- package/dist/.cursor-plugin/plugin.json +1 -1
- package/dist/bin/hook-runner.mjs +5 -2
- package/dist/skills/.canon-hash.json +5 -3
- package/dist/skills/kibi-bootstrap/SKILL.md +2 -2
- package/dist/skills/kibi-provable-code/SKILL.md +203 -0
- package/dist/skills/kibi-provable-code/resources/provable-patterns.md +172 -0
- package/dist/skills/kibi-usage/SKILL.md +4 -1
- package/dist/skills/kibi-usage/resources/proof.md +31 -10
- package/package.json +2 -2
- package/skills/.canon-hash.json +5 -3
- package/skills/kibi-bootstrap/SKILL.md +2 -2
- package/skills/kibi-provable-code/SKILL.md +203 -0
- package/skills/kibi-provable-code/resources/provable-patterns.md +172 -0
- package/skills/kibi-usage/SKILL.md +4 -1
- package/skills/kibi-usage/resources/proof.md +31 -10
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: kibi-provable-code
|
|
3
|
+
name: kibi-provable-code
|
|
4
|
+
description: "Use when writing, designing or refactoring code that implements a Kibi requirement (policies, limits, allow-lists, roles, state machines, routes, env and config reads, validators, error types), when a source proof or a value/domain read is refused because Kibi cannot read a name statically (a computed key, a dynamic import or require, eval, reflection, globals()[name], getattr with a computed name, $$var, a macro), or when deciding how to treat generated or vendored code. Covers design practices that make code easier to review, test and replace and that also let Kibi prove claims exactly, the line between a good refactor and a contortion for the tool, the accepted dynamic exceptions (plugins, serialization, registries), and generated code as a boundary."
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
kibiCompatibility: ">=1.0.0"
|
|
7
|
+
tags:
|
|
8
|
+
- kibi
|
|
9
|
+
- proof
|
|
10
|
+
- code-quality
|
|
11
|
+
- design
|
|
12
|
+
- agent-guidance
|
|
13
|
+
resources:
|
|
14
|
+
- resources/provable-patterns.md
|
|
15
|
+
---
|
|
16
|
+
## Goal
|
|
17
|
+
|
|
18
|
+
Write code a reviewer can check by reading it. Code that states its decisions
|
|
19
|
+
once, names what it depends on, and keeps decisions apart from effects is
|
|
20
|
+
easier to review, test, change and replace. The same properties let Kibi read
|
|
21
|
+
the code exactly and prove claims about it. Provability is a side effect of
|
|
22
|
+
good design here, never a reason to make the design worse.
|
|
23
|
+
|
|
24
|
+
This skill is about the code. How to write the proof itself (proof kinds,
|
|
25
|
+
`value_source`, `domains`, the `source` readers) is in
|
|
26
|
+
`kibi-usage/resources/proof.md`; links between requirements, symbols and tests
|
|
27
|
+
are in `kibi-traceability`.
|
|
28
|
+
|
|
29
|
+
## Interface Selection
|
|
30
|
+
|
|
31
|
+
Use the visible approved MCP tools or the trusted project-local CLI as equal
|
|
32
|
+
peer interfaces (CLI JSON: `printf '%s\n' '{"query":"..."}' | npx --no-install
|
|
33
|
+
kibi search --input -`). Exact routes are in
|
|
34
|
+
`kibi-usage/resources/operation-access.md`. If neither is available, write the
|
|
35
|
+
code by the practices below and say that Kibi could not be consulted. Never
|
|
36
|
+
read or edit `.kb/` files directly.
|
|
37
|
+
|
|
38
|
+
## Before you design
|
|
39
|
+
|
|
40
|
+
1. `kb_search` the area (or its `sourceLocations`) and `kb_query({id})` the
|
|
41
|
+
requirements the code implements, with `includeBody: true` when you need
|
|
42
|
+
their prose. A claim names the decision the code has to state: a limit, a
|
|
43
|
+
set of allowed values, a transition, a forbidden dependency.
|
|
44
|
+
2. Shape the code so that decision sits in one readable place (see
|
|
45
|
+
Practices). The requirement tells you what to make explicit; it never
|
|
46
|
+
tells you to bend the design.
|
|
47
|
+
3. After the change, `kb_check` and `kb_status` show whether links and
|
|
48
|
+
proof receipts went stale. Re-prove what the change touched.
|
|
49
|
+
|
|
50
|
+
## The test for every change
|
|
51
|
+
|
|
52
|
+
Before changing code so that Kibi can read it, ask: would a reviewer who has
|
|
53
|
+
never heard of Kibi accept this change on its own merits? Keep the change
|
|
54
|
+
only if the answer is yes, because it removes duplication, names a hidden
|
|
55
|
+
dependency, narrows a module, or makes a decision testable.
|
|
56
|
+
|
|
57
|
+
Never do any of these to satisfy Kibi:
|
|
58
|
+
|
|
59
|
+
- Duplicate a value into a second constant, or add an export that only the
|
|
60
|
+
proof reads, when the code already has one source of truth. A count claim
|
|
61
|
+
reads the size of the list; a dotted export (`POLICY.limit`) reads a field.
|
|
62
|
+
- Unroll a loop, inline a lookup table, or replace a clear generic mechanism
|
|
63
|
+
with copy-pasted branches so that a reader sees literal names.
|
|
64
|
+
- Split a cohesive function or module only to shrink a proof's file list.
|
|
65
|
+
- Drop a file from a proof's `files`, rename it, or mark hand-written code as
|
|
66
|
+
generated, so that a refused read goes away.
|
|
67
|
+
- Weaken types, add casts or silence a linter so that a construct parses as
|
|
68
|
+
a literal.
|
|
69
|
+
|
|
70
|
+
When good design and a readable proof disagree, keep the good design and
|
|
71
|
+
change the evidence instead: model a claim the code can show, or keep the
|
|
72
|
+
requirement at `tested` with ordinary tests. `tested` is a sound evidence
|
|
73
|
+
level. `proved` is worth reaching only where the code is already shaped well.
|
|
74
|
+
|
|
75
|
+
## Practices
|
|
76
|
+
|
|
77
|
+
Each practice below is a general one. Kibi's benefit is listed second.
|
|
78
|
+
|
|
79
|
+
1. **State each decision once, as data.** Limits, allow-lists, role-to-
|
|
80
|
+
permission tables, supported formats, transition tables and feature lists
|
|
81
|
+
belong in one named constant that the behaviour reads, not in conditions
|
|
82
|
+
repeated across files. One place to change, one place to review.
|
|
83
|
+
Kibi reads the constant directly (`value_source`, `exhaustive`,
|
|
84
|
+
`state_machine`, `regex`, a `domains` export).
|
|
85
|
+
2. **Name dependencies where they are used.** Import modules by literal
|
|
86
|
+
specifiers, read environment variables and configuration keys by literal
|
|
87
|
+
names, and call functions by name. A reader, an IDE and a bundler can then
|
|
88
|
+
find every use. Kibi's `references` reader lists them exactly
|
|
89
|
+
(`imports`, `env`, `calls`, `string_args`, `property`).
|
|
90
|
+
3. **Read configuration at one boundary.** Read the environment and config
|
|
91
|
+
files in one module that turns them into a typed object, and pass that
|
|
92
|
+
object on. The rest of the code is then testable without a real
|
|
93
|
+
environment, and the full list of settings sits in one file. Kibi proves
|
|
94
|
+
"the service reads only these variables" over that one file.
|
|
95
|
+
4. **Keep decisions pure and effects at the edge.** A function that decides
|
|
96
|
+
(`canInvite(role, target)`, `nextState(state, event)`, `priceFor(plan)`)
|
|
97
|
+
takes its inputs as arguments and returns a value; the code around it does
|
|
98
|
+
the I/O. Pure deciders are unit-testable over every input. Kibi's `rule`
|
|
99
|
+
and `state_machine` kinds call them on every combination of a finite
|
|
100
|
+
domain and prove the claim for all of them.
|
|
101
|
+
5. **Make states and their transitions explicit.** Prefer one status field
|
|
102
|
+
with a transition table (or a `next(state, event)` function) over several
|
|
103
|
+
booleans that together imply a state. Impossible combinations disappear,
|
|
104
|
+
and Kibi can prove reachability and "can never become" claims.
|
|
105
|
+
6. **Name failures.** Throw or return named error types (`ForbiddenError`,
|
|
106
|
+
`ErrQuotaExceeded`) instead of bare strings or a generic error with a
|
|
107
|
+
computed message. Callers can handle them precisely, and Kibi's `thrown`
|
|
108
|
+
read lists them.
|
|
109
|
+
7. **Declare routes, middleware and schemas in one place.** Register routes in
|
|
110
|
+
a router module, declare middleware on the route or the mount, and derive
|
|
111
|
+
types from one schema or validator instead of keeping parallel
|
|
112
|
+
definitions. Kibi's `routes`, `schema` and `validator` readers read them.
|
|
113
|
+
8. **Keep modules small and single-purpose.** A module with one reason to
|
|
114
|
+
change is easier to replace. A proof over it covers fewer files, so its
|
|
115
|
+
receipt stales only when that concern changes.
|
|
116
|
+
|
|
117
|
+
`resources/provable-patterns.md` has before-and-after examples per language.
|
|
118
|
+
|
|
119
|
+
## Dynamic code
|
|
120
|
+
|
|
121
|
+
Runtime lookups and code built from text hide what a program does from
|
|
122
|
+
every static reader, people included: `eval`, `new Function`, `exec`,
|
|
123
|
+
`globals()[name]`, `getattr(obj, name)` with a computed name, PHP `$$var` and
|
|
124
|
+
`$obj->$method()`, a dynamic `import()` or `require(path)` with a computed
|
|
125
|
+
path, reflection (`Class.forName`, `Method.invoke`, `reflect.Value.Call`,
|
|
126
|
+
`Type.GetMethod`), C# `dynamic`, `process.env[key]` with a computed key, and
|
|
127
|
+
C# `#if` around the code a claim is about. Kibi refuses a read that meets
|
|
128
|
+
one of these and names the line. Rust `#[cfg]` items are read as if every
|
|
129
|
+
build compiled them, so a "never" claim holds in each build; a `cfg_attr`
|
|
130
|
+
Kibi cannot split is still refused.
|
|
131
|
+
|
|
132
|
+
Replace a dynamic lookup when an explicit form is clearer, which is the usual
|
|
133
|
+
case: a computed `getattr` dispatch becomes a dict from name to function, a
|
|
134
|
+
computed env key becomes a named setting in the config module, `$$var`
|
|
135
|
+
becomes an array, a computed `require` becomes a static map of loaders.
|
|
136
|
+
|
|
137
|
+
Keep the dynamic form where it is the design:
|
|
138
|
+
|
|
139
|
+
- **Plugins and extension points**, where the set of implementations is open
|
|
140
|
+
by design.
|
|
141
|
+
- **Serialization and ORMs**, which map names to fields by reflection.
|
|
142
|
+
- **Registries and dependency injection**, which wire implementations by key.
|
|
143
|
+
- **Generated code** (next section).
|
|
144
|
+
|
|
145
|
+
For these, keep the dynamic part small and in one place: one loader or
|
|
146
|
+
registry module, with the code around it written statically. List the known
|
|
147
|
+
entries in a literal table where one exists (a registry of built-in handlers),
|
|
148
|
+
so the rest stays readable. Then model claims that do not depend on the open
|
|
149
|
+
part, or keep them at `tested`. Never write a proof that pretends an open set
|
|
150
|
+
is closed.
|
|
151
|
+
|
|
152
|
+
## Generated code
|
|
153
|
+
|
|
154
|
+
Treat generated code as a boundary: it is the generator's output, not code the
|
|
155
|
+
project writes, so it does not have to follow these practices and is not
|
|
156
|
+
refactored to make Kibi read it.
|
|
157
|
+
|
|
158
|
+
1. **Do not hand-edit it.** Change the input (schema, grammar, OpenAPI or
|
|
159
|
+
protobuf spec, template) and regenerate. A hand edit is lost on the next
|
|
160
|
+
run and hides the real source of the behaviour.
|
|
161
|
+
2. **Mark it.** Keep the generator's header (`// Code generated ... DO NOT
|
|
162
|
+
EDIT.`, `@generated`, `auto-generated`) and list generated paths as
|
|
163
|
+
`linguist-generated` (vendored code as `linguist-vendored`) in
|
|
164
|
+
`.gitattributes`. `kibi doctor` and `kibi init` then leave those files out
|
|
165
|
+
of language pack suggestions unless the KB names them.
|
|
166
|
+
3. **Put requirements on the input.** A claim about what the generated code
|
|
167
|
+
exposes is a claim about the generator input: prove it over the schema,
|
|
168
|
+
spec or grammar with the `json`/`yaml`/`openapi`/`schema`/`validator`
|
|
169
|
+
readers, or over the generator's configuration.
|
|
170
|
+
4. **Keep the hand-written wrapper thin and readable.** The adapter that
|
|
171
|
+
calls generated code is ordinary code and follows the practices above;
|
|
172
|
+
link it with `implements` and prove claims over it.
|
|
173
|
+
5. **Use tests where the output itself matters.** When a requirement depends
|
|
174
|
+
on what the generator produced (a parser accepts this input, a client
|
|
175
|
+
sends this header), cover it with a test or a snapshot, and check in CI
|
|
176
|
+
that regenerating gives the committed files. That evidence is `tested`.
|
|
177
|
+
Prefer the input over the generated files for a source proof: generated
|
|
178
|
+
code often uses constructs the readers refuse, and a proof over generated
|
|
179
|
+
text stales on every regeneration and follows the generator's version
|
|
180
|
+
rather than the requirement.
|
|
181
|
+
6. **Do not link generated symbols as the implementation** of a requirement
|
|
182
|
+
when a hand-written wrapper or the generator input says the same thing.
|
|
183
|
+
|
|
184
|
+
## When a read is refused
|
|
185
|
+
|
|
186
|
+
1. Read the refusal: it names the file, the line and the construct.
|
|
187
|
+
2. If the construct is incidental (a computed key that is really one of three
|
|
188
|
+
literal names), rewrite it the explicit way, run the tests, and retry.
|
|
189
|
+
3. If it is one of the accepted exceptions, leave it. Narrow the claim to the
|
|
190
|
+
files that are static, or model a claim the code can show, and keep the
|
|
191
|
+
rest at `tested`. Keep every file the claim is about in `files`.
|
|
192
|
+
4. If the file is generated, move the claim to the generator input.
|
|
193
|
+
5. Report what you changed and why it improves the code, and which claims
|
|
194
|
+
stayed `tested` and why.
|
|
195
|
+
|
|
196
|
+
## Typed results
|
|
197
|
+
|
|
198
|
+
Parse `kibiProtocol`, `status`, diagnostics and typed `nextActions` on every
|
|
199
|
+
Kibi result. A refused proof read names the file, line and construct; it is
|
|
200
|
+
never an empty member list, so never read it as "nothing found". On
|
|
201
|
+
`committed_with_repairs` a write stands: run the repair actions and never
|
|
202
|
+
resend the original. Kibi authors tracked files but never Git-stages or
|
|
203
|
+
commits them.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Provable Patterns
|
|
2
|
+
|
|
3
|
+
Before-and-after examples for the practices in `kibi-provable-code`. Each
|
|
4
|
+
"after" is a change worth making without Kibi; the note says what Kibi can
|
|
5
|
+
then read. Keep the "before" when the dynamic form is the design (plugins,
|
|
6
|
+
serialization, registries, generated code).
|
|
7
|
+
|
|
8
|
+
## One source of truth for a decision
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
// Before: the limit lives in two conditions.
|
|
12
|
+
if (files.length > 20) throw new Error("too many files");
|
|
13
|
+
// ...elsewhere
|
|
14
|
+
const remaining = 20 - files.length;
|
|
15
|
+
|
|
16
|
+
// After: one named constant that both read.
|
|
17
|
+
export const UPLOAD_POLICY = { maxFiles: 20 } as const;
|
|
18
|
+
if (files.length > UPLOAD_POLICY.maxFiles) throw new TooManyFilesError();
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Kibi reads `UPLOAD_POLICY.maxFiles` as a `value_source` with a dotted export.
|
|
22
|
+
Do not add a second `MAX_FILES` export just for the proof.
|
|
23
|
+
|
|
24
|
+
```py
|
|
25
|
+
# Before: allowed roles spread over checks.
|
|
26
|
+
if role == "owner" or role == "admin": ...
|
|
27
|
+
|
|
28
|
+
# After: one set, read by the check.
|
|
29
|
+
INVITER_ROLES = frozenset({"owner", "admin"})
|
|
30
|
+
if role in INVITER_ROLES: ...
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Dispatch through a table, not a computed name
|
|
34
|
+
|
|
35
|
+
```py
|
|
36
|
+
# Before: any attribute name can be called.
|
|
37
|
+
handler = getattr(self, f"handle_{event.kind}")
|
|
38
|
+
# or: globals()[f"handle_{event.kind}"]
|
|
39
|
+
|
|
40
|
+
# After: the handled kinds are listed.
|
|
41
|
+
HANDLERS = {"created": handle_created, "deleted": handle_deleted}
|
|
42
|
+
handler = HANDLERS[event.kind]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```php
|
|
46
|
+
// Before
|
|
47
|
+
$$name = $value; // variable variables
|
|
48
|
+
$this->$method($arg); // computed method name
|
|
49
|
+
|
|
50
|
+
// After
|
|
51
|
+
$settings[$name] = $value;
|
|
52
|
+
match ($method) { 'archive' => $this->archive($arg), 'restore' => $this->restore($arg) };
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
// Before: the loaded module depends on run-time text.
|
|
57
|
+
const exporter = await import(`./exporters/${format}.js`);
|
|
58
|
+
|
|
59
|
+
// After: the supported formats are a literal map.
|
|
60
|
+
const EXPORTERS = {
|
|
61
|
+
csv: () => import("./exporters/csv.js"),
|
|
62
|
+
pdf: () => import("./exporters/pdf.js"),
|
|
63
|
+
} as const;
|
|
64
|
+
const exporter = await EXPORTERS[format]();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The table is also the list of supported values: Kibi's `exhaustive` kind or
|
|
68
|
+
an `Object.keys(EXPORTERS)` domain proves "only CSV and PDF are supported".
|
|
69
|
+
|
|
70
|
+
## Configuration at one boundary
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
// Before: environment reads spread through the code, some computed.
|
|
74
|
+
const url = process.env[`${service.toUpperCase()}_URL`];
|
|
75
|
+
|
|
76
|
+
// After: config.ts reads every variable by name and exports a typed object.
|
|
77
|
+
export const config = {
|
|
78
|
+
billingUrl: process.env.BILLING_URL,
|
|
79
|
+
searchUrl: process.env.SEARCH_URL,
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```go
|
|
84
|
+
// After: one function reads the environment; the rest receives Config.
|
|
85
|
+
func LoadConfig() Config {
|
|
86
|
+
return Config{Port: os.Getenv("PORT"), DatabaseURL: os.Getenv("DATABASE_URL")}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`extract: env` over `config.ts` (or the Go file) proves "the service reads
|
|
91
|
+
only these variables". Code elsewhere that reads the environment directly is
|
|
92
|
+
then a review finding in its own right.
|
|
93
|
+
|
|
94
|
+
## Pure deciders, effects at the edge
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
// Before: the decision reads the database and the session itself.
|
|
98
|
+
async function invite(req) {
|
|
99
|
+
const me = await db.members.find(req.user);
|
|
100
|
+
if (me.role !== "owner" && !(me.role === "admin" && req.body.role !== "owner")) throw ...
|
|
101
|
+
await db.invites.insert(...);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// After: the decision is a pure function over finite inputs.
|
|
105
|
+
export function canInvite(inviter: Role, invitee: Role): boolean {
|
|
106
|
+
return inviter === "owner" || (inviter === "admin" && invitee !== "owner");
|
|
107
|
+
}
|
|
108
|
+
async function invite(req) {
|
|
109
|
+
const me = await db.members.find(req.user);
|
|
110
|
+
if (!canInvite(me.role, req.body.role)) throw new ForbiddenError();
|
|
111
|
+
await db.invites.insert(...);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Kibi's `rule` kind calls `canInvite` on every pair of roles.
|
|
116
|
+
|
|
117
|
+
## Explicit state
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
// Before: several flags imply a state, and impossible pairs are possible.
|
|
121
|
+
{ sent: true, paid: false, cancelled: true }
|
|
122
|
+
|
|
123
|
+
// After: one status and its transitions.
|
|
124
|
+
export const INVOICE_TRANSITIONS = {
|
|
125
|
+
draft: ["sent", "cancelled"],
|
|
126
|
+
sent: ["paid", "cancelled"],
|
|
127
|
+
paid: [],
|
|
128
|
+
cancelled: [],
|
|
129
|
+
} as const;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`state_machine` proves "a cancelled invoice can never become paid".
|
|
133
|
+
|
|
134
|
+
## Named failures
|
|
135
|
+
|
|
136
|
+
```java
|
|
137
|
+
// Before
|
|
138
|
+
throw new RuntimeException("quota " + kind + " exceeded");
|
|
139
|
+
// After
|
|
140
|
+
throw new QuotaExceededException(kind);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The `thrown` read lists `QuotaExceededException`; callers catch it by type.
|
|
144
|
+
|
|
145
|
+
## Accepted dynamic code
|
|
146
|
+
|
|
147
|
+
Keep reflection, open registries and dynamic loading where they are the
|
|
148
|
+
design, and fence them:
|
|
149
|
+
|
|
150
|
+
- One loader module discovers plugins; the rest of the code calls the
|
|
151
|
+
plugin interface statically.
|
|
152
|
+
- An ORM or serializer maps fields by reflection; claims about the fields
|
|
153
|
+
are proved over the schema or validator, not over the mapper.
|
|
154
|
+
- A dependency-injection container wires by key; the bindings sit in one
|
|
155
|
+
module with literal keys where the container allows it.
|
|
156
|
+
- Built-in entries of an open registry live in a literal table, so a claim
|
|
157
|
+
about the built-ins is provable while the open part stays `tested`.
|
|
158
|
+
|
|
159
|
+
## Generated and vendored code
|
|
160
|
+
|
|
161
|
+
- Keep the generator header and list the paths in `.gitattributes`:
|
|
162
|
+
|
|
163
|
+
```gitattributes
|
|
164
|
+
src/gen/** linguist-generated
|
|
165
|
+
third_party/** linguist-vendored
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
- Change the generator input and regenerate; never hand-edit the output.
|
|
169
|
+
- Prove claims over the input (`openapi`, `schema`, `json`/`yaml`,
|
|
170
|
+
`validator` readers) and over the thin hand-written wrapper.
|
|
171
|
+
- Cover behaviour of the output with tests or snapshots, plus a CI step
|
|
172
|
+
that regenerates and fails on a diff.
|
|
@@ -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.
|
|
5
|
+
version: 2.42.0
|
|
6
6
|
kibiCompatibility: ">=1.0.0"
|
|
7
7
|
tags:
|
|
8
8
|
- kibi
|
|
@@ -456,6 +456,9 @@ arithmetic, smt, rule, state_machine, regex, source) reach `proved` for the clai
|
|
|
456
456
|
predicate bound with `harness_for` (scope `harness`) also counts toward
|
|
457
457
|
`proved`; an intent-scope binding stays `tested`. When the `evidence-floor` rule fails, follow Debugging
|
|
458
458
|
proof regressions in `resources/proof.md` and use `kibi proof explain`.
|
|
459
|
+
Load `kibi-provable-code` before writing or refactoring code that implements
|
|
460
|
+
a requirement, when a source read is refused for a computed name, dynamic
|
|
461
|
+
import, reflection or eval, or when deciding how to treat generated code.
|
|
459
462
|
|
|
460
463
|
## Quantified claims: model the dimension
|
|
461
464
|
|
|
@@ -263,7 +263,8 @@ left:
|
|
|
263
263
|
`openapi` (`file`, `select: operations|unsecured_operations|...`),
|
|
264
264
|
`references` (`files`, `extract: env|imports|calls|string_args|thrown|
|
|
265
265
|
property`; TypeScript, JavaScript, Python and SWI-Prolog files, and Go,
|
|
266
|
-
Java, C
|
|
266
|
+
Java, C#, Rust, PHP, C, Bash and Terraform/HCL files through
|
|
267
|
+
`kibi-plugin-treesitter`), `schema` (`format: drizzle|prisma|sql`, `select:
|
|
267
268
|
tables|columns|required_columns|nullable_columns|foreign_keys`), `routes`
|
|
268
269
|
(Hono or Express app export, `path_prefix`, `names_from`, `select:
|
|
269
270
|
routes|middleware`) or `validator` (zod, valibot or pydantic, `select:
|
|
@@ -292,9 +293,11 @@ left:
|
|
|
292
293
|
The builders need kibi-cli 2.33.0 or newer in the project. The env
|
|
293
294
|
extractor reads `process.env`, `import.meta.env`, `Bun.env`,
|
|
294
295
|
`Deno.env.get`, `os.environ` and `os.getenv`, through casts.
|
|
295
|
-
- `references` over Go, Java, C
|
|
296
|
-
the language's grammar pack
|
|
297
|
-
`kibi-lang-
|
|
296
|
+
- `references` over Go, Java, C#, Rust, PHP, C, Bash or Terraform/HCL
|
|
297
|
+
needs `kibi-plugin-treesitter` and the language's grammar pack
|
|
298
|
+
(`kibi-lang-go`, `kibi-lang-java`, `kibi-lang-csharp`, `kibi-lang-rust`,
|
|
299
|
+
`kibi-lang-php`, `kibi-lang-c`, `kibi-lang-bash`, `kibi-lang-hcl`) in
|
|
300
|
+
`devDependencies`, with the
|
|
298
301
|
plugin activated for proofs:
|
|
299
302
|
`"kibi.reference-extractor.v1": { "mode": "augment" }` in its
|
|
300
303
|
`kibi.plugins` entry (next to `"kibi.symbol-extractor.v2"`). A project
|
|
@@ -304,12 +307,30 @@ left:
|
|
|
304
307
|
written as the code names them (`os.Getenv`, `System.out.println`,
|
|
305
308
|
`Console.WriteLine`, `std::env::var`, Go import paths, `java.util.*`,
|
|
306
309
|
`std::io::Write`); a method on an expression Kibi cannot name is
|
|
307
|
-
`*.name`.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
310
|
+
`*.name`. Rust `#[cfg(...)]` items are read as if every build compiled
|
|
311
|
+
them (`#[cfg(test)]` items are skipped): a name two gated `use` items
|
|
312
|
+
bind is listed under both, and a `cfg_attr` counts as the attributes it
|
|
313
|
+
applies, so `excludes` holds in every build while `includes` and `eq`
|
|
314
|
+
may count a member only some builds compile. Reflection, a name
|
|
315
|
+
computed at run time, the whole environment, C# `dynamic` and `#if`, a
|
|
316
|
+
`cfg_attr` Kibi cannot split, and any macro for Rust `calls` and
|
|
317
|
+
`thrown` fail the read with their place: the claim cannot be decided
|
|
318
|
+
for that file, so model a claim the code can show (Rust `calls` over a file with
|
|
319
|
+
`println!` is always refused). PHP class names are written in full with
|
|
320
|
+
backslashes (`App\Mail\Mailer::send`) and functions in lower case;
|
|
321
|
+
PHP names ignore letter case, so a PHP `excludes` refuses a member that
|
|
322
|
+
differs from an item only in case (`Exec` for `exec`);
|
|
323
|
+
Terraform/HCL reads only `property`; C and Bash have no `thrown`, and
|
|
324
|
+
Bash no `property`. A Bash variable the script expands but never sets is
|
|
325
|
+
an environment read, and one it sets only on some paths is refused. A
|
|
326
|
+
Terraform `override.tf`, `*_override.tf` or `.tofu` file in the folder
|
|
327
|
+
refuses an HCL read, so a value claim there cannot be proved. C
|
|
328
|
+
`property` reads only initializers (a later `cfg.field = v` is not
|
|
329
|
+
seen), Bash does not read code handed to another interpreter
|
|
330
|
+
(`python -c`, `awk`), and the commands a sourced Bash file or an
|
|
331
|
+
included C file runs are that file's: model such claims over the code
|
|
332
|
+
that holds them, listing every file it runs.
|
|
333
|
+
Never drop a file the claim is about
|
|
313
334
|
from `files`: the read decides a claim only for the files it covers,
|
|
314
335
|
and a proof is rejected when a symbol the test covers or that
|
|
315
336
|
implements the claim's requirement lies outside them.
|