portfolio-optimiser/docs/okf-konsum-kontrakter.md
Kjell Tore Guttormsen 9e35cfefbf docs(okf): grep-bart anker inn i SPEC-en, ikke et linjenummer
Et linjenummer inn i et ANNET repos fil raatner paa deres neste redigering, og
denne fila skal kunne leses utenfra. Samme regel som STATE-pekere: paragraf-
anker, verifisert med en grep som faktisk treffer.

Co-Authored-By: Claude <claude-opus-5>
2026-09-02 20:23:43 +02:00

124 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# OKF consumption contracts
> **This file is the source.** Three facts below span a producer
> ([`llm-ingestion-okf`](https://git.fromaitochitta.com/open/llm-ingestion-okf)) and this consumer,
> so neither side can hold the other to them from inside its own plan file. Docstrings, tests and
> the invariant ledger in `CLAUDE.md` point *here*; they do not restate the rule. A second copy of a
> contract is the drift this repository has a rule against.
>
> The producer's half is recorded in that repository's `docs/plan/office-intake.md` §§ 45 and
> `docs/consumption-contract.md`. Ratified at programme level 2026-09-02. Written in English because
> the counterparty half is, and a contract split across two languages is a contract nobody reads
> whole.
>
> Every number below comes from a command, and each command is written next to its number.
## § 1. The falsification threshold — `present` and not `unverified`
A falsification verdict may rest on a concept **only when both hold**:
```
evidence_for(path).state == "present" AND tier != "unverified"
```
Everything else is **reported and explicitly discounted**, never silently excluded. The report
carries the triple `(state, reason, items_seen)`: a concept that was dropped and a concept that was
read-and-discounted are different facts, and only the second is honest about what was actually read.
The threshold is expressed in **exactly one place**`okf.admits_falsification(evidence) -> bool`.
A threshold spelled inline at each caller is a threshold nobody can find, and a second copy is free
to drift from the first.
**`author`, `usage_count` and `last_modified` are deliberately NOT required, and the denominator is
written down rather than implied.** SPEC § 5.1 names **six** keys on a `sources` entry — `resource`,
`id`, `title`, `author`, `usage_count`, `last_modified` — and the producer writes **two of them**:
```sh
# Grep-able anchor, never a line number — a line anchor into another repository's file rots
# on that repository's next edit, and this one has to survive being read from outside.
grep -A11 'Each `sources` entry:' ~/repos/_okf-canonical/SPEC.md # the six entry keys
grep -rh '^sources:' ~/repos/llm-ingestion-okf/examples/
# -> sources: [{ id: golden-v0-2-sales, resource: fixture }]
# (1 of the 26 markdown files under examples/ carries the key at all)
```
Measured 2026-09-02 against producer `62b6192`. **2 of 6, not 2 of 5** — an earlier draft of this
contract carried the smaller denominator, which would have understated how much of § 5.1 the
producer leaves unwritten. Requiring the three credibility signals would make the threshold
unreachable in practice while looking strict on paper: the worst of both. **The threshold names only
what is actually written.**
`usage_window` is a sibling of `sources`, not an entry key, and is outside the six.
## § 2. The adjudication state — absence is `unknown`, never `absent`
A concept carries its adjudication state in the frontmatter key **`adjudication`**, whose value set
is **closed**: `proposed` or `adjudicated`.
| Observation | State |
|---|---|
| `adjudication: proposed` | `proposed` |
| `adjudication: adjudicated` | `adjudicated` |
| the key is not present | **`unknown`** |
| any other value | **refused by name** — never mapped into the vocabulary |
**The third row is the whole contract.** A concept that does not carry the key means *we did not
learn whether this was adjudicated* (an older bundle), and collapsing that into `absent` — *it was
not adjudicated* — is a verdict on missing evidence presented as evidence of absence. It is the same
defect as collapsing `unreadable` into `absent` one layer up, and the same defect the ungiven-verdict
work removed from `RunResult.verdict`.
The fourth row is **validation, never repair**: an out-of-vocabulary value is an error, not an
extension point, and mapping it to `unknown` would silently invent the very state this contract
exists to keep honest.
**Honesty limit, stated:** this consumer's fixtures are **hand-written to the contract above**, not
produced by `llm-ingestion-okf`. Integration against the producer's own golden is later work and is
not claimed here.
## § 3. Identity across bundles — the pair `(bundle_id, concept_id)`
A concept ID is **bundle-local and stable**. Identity **across** bundles is the pair
**`(bundle_id, concept_id)`** — never the concept ID alone.
`bundle_id` resolves in a **fixed order**, and the resolved value carries **which source answered**:
| Order | Source | `origin` |
|---|---|---|
| 1 | the concept's own frontmatter | `declared-concept` |
| 2 | the bundle root's `index.md` | `declared-index` |
| 3 | neither declared it — the mount basename is used | `mount-derived` |
**Three origins, not a boolean.** A caller that cannot tell *"the concept said so"* from *"we fell
back twice"* has been handed a stamp it cannot audit.
**A base with no readable `index.md` is not "undeclared".** The existing navigation fail-fast
propagates unchanged; reading an unreadable base as *"no declaration"* is the tolerant-read defect
that widens an answer instead of refusing it. Only a base whose index *is* readable and declares
nothing falls through to the next row.
**Measured today: every base resolves `mount-derived`.** No shipped `index.md` declares the key:
```sh
find shared -name index.md | wc -l # -> 7
grep -l 'bundle_id' $(find shared -name index.md) | wc -l # -> 0
```
So this contract changes which sources are **consulted**, not what happens when none of them
declares anything — which is why adopting it moves no existing call site.
**There is no cross-bundle link form.** A consumer holding several bundles partitions per bundle;
the producer emits no syntax for pointing from inside one bundle into another, and adding one is out
of scope until a consumer states the need.
## § 4. What these three do not settle
- **The wire form of `sources` is the producer's to fix.** Flow-sequence-of-mappings is the normative
emission form; block form remains conformant OKF but outside the accepted subset. A known defect
stands on the producer side: `llm-ingestion-guard` 1.2.0 rejects a flow sequence of mappings for
`sources`. That is a **known producer-side gate defect, not a consumer error**, and this consumer
does not wait on it.
- **The trust tiers themselves** (§ 5.3 of the SPEC) are inferred, never stored — no credibility
score is written by either side.
- **Nothing here wires a library primitive into a run's stdout.** The reader reads; the caller
decides. Both halves of that split predate these contracts and are unchanged by them.