docs(okf-v0.2): ship to a pilot set before general availability

Operator directive 2026-07-26: consumers are better served by getting the
latest version early and reporting back than by us holding it until we judge
it finished.

This closes a real gap. Every test in the plan -- including V-A8 against
upstream's reference implementation -- asks whether output is conformant.
None asks whether it is usable: whether a bundle is awkward to construct,
whether a rejection message is actionable, whether the profile can express
what a consumer's actual data needs. Only real data surfaces that.

Pilot set is three repos, one axis each, chosen for signal:
portfolio-optimiser-claude for the producer path (one real manifest run),
catalog for gate acceptance (their gate on our fixture, measured rather than
inferred from the regex), and claude-code-llm-wiki for expressiveness across
522 real documents.

The load-bearing design detail is that most of the pilot is read-only on our
side: we run the v0.2 reader over real consumer bundles and send the report.
That needs no adoption, no writes into their trees (O2 holds), and no change
to a contract their operator ratified. Only the producer axis asks a
consumer to do anything, and it asks for one run.

Excluded with reasons rather than silently: okr (Node side not yet lifted),
linkedin-studio (v0.2's provenance families would put implicit pressure on
the ingest/published carve-out we agreed not to normalize), commons (they
are deciding V1 -- a participant, not a test site).

Shipping a provisional surface without owing stability rests on three rules,
not on saying "provisional": OKF_LATEST does not point at v0.2 until GA, so
flipping it is the GA event rather than a merge side effect; the docstring
and CHANGELOG name the pilot repos; and breaking changes during the pilot
get no deprecation cycle. Stating that last one up front is what buys the
freedom to act on feedback -- discovering it later is what turns a pilot
into a de-facto release.

Feedback is requested in five named parts, because unstructured reports are
not comparable across three repos. The one that matters most is "what was
awkward but worked": workarounds are the highest-value signal and never
appear as a failure.

GA exit criteria are testable, and carry one honest limit: a three-repo
pilot exercises only what those three use, so `sources` with usage_window,
multi-verifier `verified`, and Attested Computation will likely go
unexercised. Those stay marked provisional at GA instead of being silently
promoted -- claiming otherwise would be the same unearned-claim pattern that
"conform first, claim after" exists to prevent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2aKJxLejT9S8jYwoZ9fut
This commit is contained in:
Kjell Tore Guttormsen 2026-07-26 13:50:28 +02:00
commit a27017e635
2 changed files with 115 additions and 2 deletions

View file

@ -80,6 +80,12 @@ crisis, and it is bounded by three facts that do not yield to it:
repo's contract from here violates O2.
- `okf_version`'s *value* belongs to catalog (decision E1).
**Rollout is pilot-first.** A new upstream version reaches a small pilot set on a
pre-release tag and is revised on their feedback before general availability —
consumers testing real data find what fixtures cannot. `OKF_LATEST` means the
latest version supported as *stable*, so flipping that alias is the GA event, not
a merge side effect.
Two invariants fall out: no profile hard-codes an upstream version, and no bundle
declares a version its shape has not earned. Where upstream itself defers a
contract — v0.2's attestation receipt and verdict wire formats — the format is

View file

@ -148,6 +148,12 @@ library upgrade. The versioned constants are the stable binding and are what
consumers should pin; `OKF_LATEST` is for callers who have explicitly opted into
tracking.
`OKF_LATEST` means *the latest version supported as stable*, not the latest
version present in the tree. During the pilot it therefore keeps pointing at the
v0.1 semantics, and **flipping it to v0.2 is the GA event** — a single, auditable
action rather than a side effect of a merge. This is what keeps the alias from
becoming the footgun that drags tracking consumers into a provisional surface.
`at` binds to the already-validated required `ingested_at` argument, so no
wall-clock default is introduced and determinism holds.
@ -175,6 +181,101 @@ recorded in this doc (V-A1), and the release checklist gains one item — re-che
upstream for a newer OKF version and record the result, even when unchanged. A
standing policy with no detection mechanism is an intention, not a policy.
## Rollout — pilot before general availability
Operator directive 2026-07-26: consumers are better served by getting the latest
version early, testing it, and reporting back than by us holding it until we
judge it finished. So v0.2 ships to a small pilot set first, and general
availability is what happens *after* the findings are addressed.
This closes a gap the plan otherwise had. Every test in the suite — including
V-A8 against upstream's reference implementation — asks whether the output is
*conformant*. None asks whether it is *usable*: whether a real bundle is awkward
to construct, whether a rejection message tells the consumer anything actionable,
whether the profile can express what their actual data needs. Only a consumer
running real data surfaces that.
### The pilot set, chosen for signal rather than convenience
Three repos, each exercising a different axis, and deliberately cheap for them:
| Repo | Axis under test | What we ask of them | Their cost |
|---|---|---|---|
| `portfolio-optimiser-claude` | **Producer path.** Real Door A ingestion emitting v0.2 from a real manifest | Pin the pre-release tag, run one real manifest, report | one run |
| `catalog` | **Gate acceptance.** Does a bundle *declaring* `okf_version: "0.2"` actually pass their gate — measured against their gate, not our reading of its regex | Run their existing gate on our fixture. No code change | one gate run |
| `claude-code-llm-wiki` | **Expressiveness.** Can the profile object express a strict consumer at v0.2, over 522 real documents | Nothing. We read their bundle and send them the report | zero |
The wiki entry is the important design detail: **most of the pilot is read-only
on our side.** We run the v0.2 reader over real consumer bundles and report what
we find. That needs no adoption, no writes into their tree (O2 holds), and no
change to a contract their operator ratified. Only the *producer* axis requires a
consumer to do anything.
Deliberately excluded, with reasons: `okr` (Node side, not yet lifted — wrong
time); `linkedin-studio` (their `ingest/published/` provenance grammar is
deliberately not normalized, and v0.2's provenance families would put implicit
pressure on exactly that carve-out); `portfolio-optimiser-commons` (they are
deciding V1 — a participant, not a test site); `llm-ingestion-pipeline-security`
(not an OKF consumer in this sense).
### Stages
- **P1 — read-only sweep (us).** Run the v0.2 reader over real bundles from the
pilot set. Finds parser gaps, tolerance-rule violations, and expressiveness
gaps at zero risk to anyone. Runs as soon as D1D3 are green.
- **P2 — one producer, opt-in.** `portfolio-optimiser-claude` emits a v0.2 bundle
against the pre-release tag.
- **P3 — gate check.** `catalog` runs their real gate on P2's output.
- **P4 — fix, then GA.** Address findings, then flip `OKF_LATEST` as its own
release.
### Shipping a provisional surface without owing stability
The install channel is a direct git reference, so consumers pin a tag explicitly
and nothing reaches anyone implicitly. The pilot therefore ships as a
**pre-release tag** (`v0.5.0a1`), and the marker lives in the tag name so a pin
is self-documenting. Three rules make the provisional status real rather than
stated:
1. `OKF_LATEST` does not point at v0.2 until GA (above).
2. The v0.2 profile's docstring and the CHANGELOG entry both say the surface may
change on pilot feedback, and name the pilot repos.
3. Breaking changes during the pilot are expected and do **not** get a
deprecation cycle. Saying this up front is what buys the freedom to act on
feedback; discovering it later is what makes a pilot a de-facto release.
### Feedback shape
Unstructured feedback is not comparable across three repos, so ask for five
things by name:
1. What was run, against which tag.
2. What failed — with the bytes or the actual error, not a summary.
3. **What was awkward but worked.** The workarounds are the highest-value signal
and the one that never shows up as a failure.
4. What was needed that the profile could not express.
5. Whether they would adopt it as-is.
### GA exit criteria
1. Every P1P3 finding is either fixed or explicitly accepted with the reason
recorded in this doc.
2. Golden fixtures byte-exact; V-A8 green.
3. The two existing profiles unchanged byte-for-byte, existing tests unmodified
(V-A6).
4. `mypy --strict src/`, ruff, and the boundary grep-gate clean.
5. At least one consumer has *emitted* and one has *consumed* a v0.2 bundle
end-to-end.
6. `OKF_LATEST` flips to v0.2 in its own release, with a CHANGELOG entry stating
what changed for anyone bound to the alias.
**One honest limit on what GA can mean.** A three-repo pilot exercises only what
those three repos use. `sources` with `usage_window`, multi-verifier `verified`,
and `Attested Computation` will very likely go unexercised. Those stay marked
provisional at GA rather than being silently promoted: "stable" applies to the
surface the pilot actually covered, and claiming more would be the same
unearned-claim pattern that "conform first, claim after" exists to prevent.
## Open questions
**V1 — `generated`'s shape in `DEFAULT` (commons').** *No longer blocks our v0.2
@ -219,8 +320,14 @@ everything after.
5. **D2** — the `OKF_V0_2` profile and `OKF_LATEST` alias.
6. **D5** — v0.2 golden fixtures; `okf_version: "0.2"` is declared only here,
once 15 are green (conform first, claim after).
7. **D4**`Attested Computation` as a type with round-trip fidelity.
8. **V1 to commons** in parallel throughout; **D6** lands with the release.
7. **P1** — read-only sweep over real pilot bundles. Cheap, zero-risk, and the
first point where a finding can come from outside our own assumptions.
8. **Pre-release tag `v0.5.0a1`**, then **P2** (producer) and **P3** (gate).
9. **D4**`Attested Computation` round-trip. Placed after the pilot on purpose:
nothing in the pilot set uses it, so building it earlier would add surface the
feedback cannot reach.
10. **P4** — address findings, then GA: flip `OKF_LATEST`, its own release.
11. **V1 to commons** in parallel throughout; **D6** lands with the GA release.
## Key assumptions, each with its test