feat(skill): one generic skill by default, carrying a working method and an answer form

The operator built a 2313-concept bundle from one project's own documentation,
asked it a question in his own words, and judged the result unusable. The
generated skill was an audit contract: all its discipline sat on the accounting
-- markings, denominators, budget lines, source pointers -- and none of it on
understanding the question, searching again, or writing one coherent answer.
Two sentences actively forbade the second of those.

**The two forbidding sentences are gone and their replacements are tested from
both sides.** "Do not go looking for context the pre-pass deliberately
withheld" read as "one run per question", and no wording of the operator's
question put the right document inside a single run's cut -- so a rule against
a second run was a rule against finding it at all. "Not something to retry with
a narrower question" generalised a budget-refusal case into the same ban.
SS 2.2 of the contract said the first of them, so the contract moved with the
skill rather than being left to disagree with it: a second pre-pass run with
other terms, and a fetch of a concept the payload NAMED, are reachable; SS 9's
two real boundaries -- directory enumeration, the verdict layer -- are not.

**Two new sections, and the checker requires them.** `## Working method`: read
the bundle's map, put the question into the bundle's own words, split a broad
question into 2-4 sub-questions, search per sub-question, read what lay just
outside the cut and search again with its words, same method across several
bundles, then assemble ONE answer ordered by sub-question, saying which source
holds and what is not covered. `## Answer form`: the questioner's language,
plain prose, no `below_k`, no digests, no budget lines, no denominators; short
textbook-style references (document + section, plus bundle where several were
read); and the audit trail written only when the questioner asks for it or
into a document that travels without the skill. `REQUIRED_SECTIONS` follows the
template and the contract's new SS 2.5 and SS 2.6 -- never the other way round.

**The generic skill becomes what `okf skill` and `okf project` write.** A
per-bundle skill's numbers go stale the moment its bundle is rebuilt, one copy
per consuming project, and a project with two bundles installs two
near-identical skills; the generic form carries no bundle's numbers and names
`okf card` for them. `--for-bundle` is the opt-in for the instantiated copy,
which still refuses out loud on a stale pairing -- safe to keep, not enough to
keep default. `rule_bundle_identity` learned to tell a generic skill from an
unfilled template by the frontmatter name the generator writes, so the template
still fails for the opposite reason: it declares no identity because it is
unfinished.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-20 23:53:34 +02:00
commit 30edd3f5d8
12 changed files with 564 additions and 92 deletions

View file

@ -1223,9 +1223,9 @@ lines — so it could not be moved, shared, or run by anyone else.
```sh
okf build ./documents --bundle ./bundle --bundle-id my-bundle --okf-version 0.2
okf skill ./bundle --out ./project/.claude/skills/my-bundle-consume
okf skill --out ./project/.claude/skills/okf-consume-any
okf consume ./bundle --question "your question" --out /tmp/payload.json
okf check --skill ./project/.claude/skills/my-bundle-consume/SKILL.md --payload /tmp/payload.json
okf check --skill ./project/.claude/skills/okf-consume-any/SKILL.md --payload /tmp/payload.json
```
A bundle you only have read access to is fine — the generator only reads it.
@ -1311,27 +1311,32 @@ server existed, and it is red today on row 2. The measurements, the update
drill and the limits are in
[`docs/2026-09-20-mcp-to-varianter.md`](docs/2026-09-20-mcp-to-varianter.md).
### One skill for every bundle: `okf card` and `okf skill --generic`
### One skill for every bundle: `okf skill` and `okf card`
`okf skill <bundle>` writes a consumption skill for **that** bundle, with its
identity and its numbers measured into the text — which is what makes the file
stale the moment the bundle is rebuilt. `okf skill --generic` writes one
installable skill for **any** bundle instead:
**`okf skill --out <dir>` writes one installable skill for ANY bundle. That is
the default since 2026-09-20**, and `okf project` installs the same one:
```sh
okf skill --generic --out ~/.claude/skills/okf-consume-any
okf skill --out ~/.claude/skills/okf-consume-any
okf card .okf/my-bundle # the per-bundle numbers, as JSON, on demand
```
The generic skill carries no bundle's id, no ref and no count; it tells its
reader to run `okf card <bundle>` first. The card is **derived on every run and
never written into the bundle**, so there is no second artefact that can
disagree with the bytes beside it.
disagree with the bytes beside it. It is therefore never stale, and one skill
serves every bundle a project holds.
`okf skill <bundle> --for-bundle` still writes the per-bundle form, with the
identity and the numbers measured into the text — which is exactly what makes
that file stale the moment the bundle is rebuilt. It refuses out loud when it
was not regenerated (`bundle_mismatch`), so its cost is a stopped session
rather than a wrong answer; that is why it is no longer the default.
Measured on two unrelated bundles: two per-bundle skills are identical on 281
of 313 and 311 lines. The 62 lines that differ are exactly identity, concept
count, the conditional-field table, the whole-bundle cost and the breaking
point — the five things a rebuild invalidates.
count, the conditional-field table, the whole-bundle cost and the payload-cost
section — the five things a rebuild invalidates.
## Implemented scope (v1)