feat(okf-v0.2): D5 — the v0.2 golden fixture, with okf_version in root frontmatter
Placement settled by catalog's own reading of upstream at the pinned commit
3fcbb9f: SS8:509-510 and SS12:773-775 both put `okf_version` in a bundle-root
`index.md` frontmatter block, and SS12 calls it the only place frontmatter is
permitted in an index. Catalog's spec says the opposite about the same file;
that divergence is theirs against upstream, and we conform to upstream.
The value never touches a profile. `OKF_V0_2.index.root_frontmatter` names the
key; the caller supplies the value through a new keyword-only
`root_frontmatter_values` mapping. That keeps V4/V-A5 intact - `okf_version`'s
value tracks the upstream Google version and belongs to catalog (E1), so a
constant here would claim a decision we do not own and would have to be chased
on every upstream release. In the fixture the value is fixture DATA
(`okf-version.txt`), not a literal in our source.
Ordering comes from the policy, not the caller's mapping: a dict preserves
insertion order, so two callers passing the same keys would otherwise emit
different bytes. A key the policy does not name is refused fail-fast, before
any disk mutation. Omitting the argument emits no block at all - SS12 is a MAY
and none of upstream's four reference bundles declares the key.
The block is written only when the index is CREATED, so a re-run into an
existing bundle stays byte-identical (A-E5).
Raw-byte assertions rather than parsed ones, on the committed fixture as well
as on fresh runs: catalog measured that a quoted value fails their shape regex
with exit 1 and that a BOM hides the marker while still exiting 0.
`yaml.safe_load` returns "0.2" either way and strips a BOM first, so a parsed
assertion masks exactly those two defects. Asserting the frozen fixture catches
what a self-comparison cannot - regenerating from a broken emitter moves both
sides together.
A-E6 is now placement-explicit (promised catalog in 99cf987), and separates the
two byte properties: BOM-free is a property of the file, unquoted is a property
of CATALOG'S GATE and not of OKF v0.2 - upstream's own SS12 example is quoted,
so their gate rejects the spec's canonical form.
README gains the upstream-version section it was missing; CLAUDE.md gains the
mechanism behind "no profile hard-codes an upstream version": a profile names a
key, a caller owns its value.
550 -> 559 tests. test_profile_threading's `OKF_V0_2.index is DEFAULT.index`
assertion is replaced rather than deleted: object identity was a proxy for "the
shipped profiles differ in no NAME-bearing field", which is what makes the
synthetic test profile necessary, so the guard now asserts that directly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013dgkSPjkLpACjMayd9R5jx
This commit is contained in:
parent
ed08ac15e9
commit
2504011010
14 changed files with 470 additions and 34 deletions
42
README.md
42
README.md
|
|
@ -104,6 +104,48 @@ verification criteria:
|
|||
contract and fixture suite, not code —
|
||||
[plan](docs/plan/phase-4-node-half.md).
|
||||
|
||||
## Upstream OKF versions
|
||||
|
||||
The library targets the current latest version of Google's OKF. Support is
|
||||
**additive** — a new upstream version arrives as a new profile, never as a
|
||||
migration of an existing one — so upgrading the library does not change the
|
||||
bytes an existing profile emits.
|
||||
|
||||
| Profile | Contract | Status |
|
||||
|---|---|---|
|
||||
| `DEFAULT` | commons' ingest-spec §5 layer (OKF v0.1 semantics) | stable |
|
||||
| `STRICT_V1` | a consumer's ratified v0.1 contract | stable |
|
||||
| `OKF_V0_2` | OKF v0.2 | **provisional**, pre-release only |
|
||||
| `OKF_LATEST` | alias for the latest version supported as *stable* | currently `DEFAULT` |
|
||||
|
||||
`OKF_V0_2` ships first as a pre-release to a named pilot set and may change on
|
||||
their feedback without a deprecation cycle. Pin the versioned constant rather
|
||||
than `OKF_LATEST` unless you have explicitly opted into tracking; `OKF_LATEST`
|
||||
moves at general availability, which is a deliberate release event rather than
|
||||
a side effect of an upgrade.
|
||||
|
||||
Selecting a profile is keyword-only, so existing call sites are unaffected:
|
||||
|
||||
```python
|
||||
materialize_bundle(manifest, bundle_dir, ingested_at, profile=OKF_V0_2)
|
||||
```
|
||||
|
||||
A bundle may declare the version it targets. OKF v0.2 §12 makes this a MAY, and
|
||||
puts the declaration in the bundle-root `index.md`'s frontmatter block. The
|
||||
profile names the key; the **caller supplies the value**, because that value
|
||||
tracks the upstream version and is not this library's to decide:
|
||||
|
||||
```python
|
||||
materialize_bundle(
|
||||
manifest, bundle_dir, ingested_at,
|
||||
profile=OKF_V0_2,
|
||||
root_frontmatter_values={"okf_version": "0.2"},
|
||||
)
|
||||
```
|
||||
|
||||
Omit the argument and no frontmatter block is written. Offering a key the
|
||||
profile does not name is refused before anything is written to disk.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Verdict/feedback machinery from the method specification (stays in the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue