fix(okf-v0.2): generated.by is process:okf-ingest — the id commons decided

v0.5.0a1 shipped the one actor value the spec owner had already excluded.
Caught before any pilot was notified, so it costs a tag, not a migration.

Commons decided <fast id> = process:okf-ingest on 2026-07-31, on this repo's
own proposal, superseding option (d) (process:llm-ingestion-okf) chosen here on
07-27. The exclusion is ingest-spec.md:7-8, frozen on the spec being
framework-neutral: normalising OUR repo name into the normative id would force
every other conformant implementation to write it into its own output. Verified
against three independent sources before touching anything — commons' coord
message 20260731T154140Z, their plan :215-216/:244, and their STATE :37.

Why this had to land before the pilot notifications rather than after:

  actor is both the stamp written and the value owned back (OwnershipPolicy),
  and recognition is one-way. A pilot that had run Test A against the excluded
  id would hold bundles this library stops recognising the moment the id is
  corrected — collision_unstamped on their OWN files. That is the A-E5 failure
  mode, and we would have inflicted it.

Worse, it would not have shown up as a failure: the plan's A-E3 expectation
(:854) named the same excluded value as the code, so Test A would have PASSED
and confirmed the error. Expectation and implementation agreeing is not
evidence when both predate the decision.

Nothing in the wild carried the old value: OKF_V0_2 did not exist at v0.4.0, so
the profile has never been released. v0.5.0a1 is abandoned, not moved — a tag
already on a public remote does not get force-pushed, and the history should
say plainly that a1 was wrong.

A-E3 now records both corrections with dates. The V1 paragraph at :1169 is
superseded in place rather than rewritten: its reasoning still holds, only its
outcome moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVTup4v7tW9QiVyBENk2LV
This commit is contained in:
Kjell Tore Guttormsen 2026-07-31 20:50:21 +02:00
commit 805a2d50d9
8 changed files with 74 additions and 22 deletions

View file

@ -5,7 +5,30 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.5.0a1] — 2026-07-31
## [0.5.0a2] — 2026-07-31
**This is the pre-release the pilots pin. `v0.5.0a1` was tagged and abandoned
unused — do not pin it.** It carried a `generated.by` actor that the spec owner
had already excluded, and it was caught before any pilot was notified.
### Fixed
- **`OKF_V0_2`'s `generated.by` actor is `process:okf-ingest`**, not
`process:llm-ingestion-okf`. Commons decided the fixed id on this repo's own
proposal 2026-07-31, superseding option (d) chosen here 2026-07-27. The
exclusion is `ingest-spec.md:7-8`, frozen on the spec being framework-neutral:
normalising *our* repo name into the id would force every other conformant
implementation to write it into its own output.
Nothing in the wild carried the excluded value — `OKF_V0_2` did not exist at
`v0.4.0`, and no pilot had been notified — so this costs a tag rather than a
migration. It is recorded rather than quietly folded in because the failure it
avoids is specific: `actor` is both the stamp written and the value owned back
(`OwnershipPolicy`), and recognition is one-way, so a pilot holding bundles
stamped with the excluded id would have hit `collision_unstamped` on its own
files the moment the id was corrected.
## [0.5.0a1] — 2026-07-31 — ABANDONED, do not pin
**Pre-release. PROVISIONAL surface.** Shipped to a named pilot set —
`portfolio-optimiser-claude`, the plugin marketplace catalog, and
@ -244,6 +267,7 @@ Phase 1 (Door A) implemented against the normative `ingest-spec.md` owned by
- The Door A public surface: `materialize_bundle` plus the typed error hierarchy
rooted in `IngestError`.
[0.5.0a2]: https://git.fromaitochitta.com/open/llm-ingestion-okf/compare/v0.5.0a1...v0.5.0a2
[0.5.0a1]: https://git.fromaitochitta.com/open/llm-ingestion-okf/compare/v0.4.0...v0.5.0a1
[0.4.0]: https://git.fromaitochitta.com/open/llm-ingestion-okf/compare/v0.3.2...v0.4.0
[0.3.2]: https://git.fromaitochitta.com/open/llm-ingestion-okf/compare/v0.3.1...v0.3.2

View file

@ -851,16 +851,34 @@ output is the baseline. Materialize it twice with the *same* explicit
frontmatter block where the profile requires one satisfies A-E2; a diff in
body bytes does not.
- **A-E3** `generated` is an inline flow mapping
`{ by: process:llm-ingestion-okf, at: <ingested_at> }` — not the string
`{ by: process:okf-ingest, at: <ingested_at> }` — not the string
`true` — and `at` equals the `ingested_at` argument **exactly**.
**Corrected 2026-07-27**, before the pilot receives the tag. The original read
`{ by: llm-ingestion-okf/<version>, ... }`, written before V1 resolved. The
actor now carries **no version**, which is the whole point of the change: a
producer version inside a byte-compared golden fires regression on every
release with no contract having changed. A pilot expectation that outlives its
own decision is the A-E6 defect class, so this is sent to po-claude rather than
left to surface during their run.
**Corrected twice, both times before the pilot receives the tag.** First
2026-07-27: the original read `{ by: llm-ingestion-okf/<version>, ... }`,
written before V1 resolved, and the actor lost its version — a producer
version inside a byte-compared golden fires regression on every release with
no contract having changed.
Then **2026-07-31, and this one changed the actor itself.** Commons decided
`<fast id>` = `process:okf-ingest` on our own proposal, explicitly excluding
option (d) (`process:llm-ingestion-okf`) that we had shipped in D2. The
exclusion is `ingest-spec.md:7-8`, frozen on the spec being framework-neutral:
normalising *our* repo name would force every other conformant implementation
to write it into its own output. This landed in code, in the byte-compared
fixture, and here **before any pilot was notified**`v0.5.0a1` carried the
excluded id and was abandoned unused for `v0.5.0a2`.
Catching it late would have been expensive in a specific way worth recording:
`actor` is both the stamp written and the value owned back
(`OwnershipPolicy`), and recognition is one-way. A pilot that had run Test A
against the excluded id would hold bundles this library stops recognising the
moment the id is corrected — `collision_unstamped` on their *own* files, which
is exactly the A-E5 failure mode, inflicted by us.
A pilot expectation that outlives its own decision is the A-E6 defect class,
so both corrections are sent to po-claude rather than left to surface during
their run.
- **A-E4** `sources` is present as an inline flow sequence of one flow mapping —
`[{ id: <source id>, resource: <source reference> }]` — carrying at least a
`resource` derived from the manifest's source. **Corrected 2026-07-26** from
@ -1164,8 +1182,16 @@ Either way the decision is the operator's via commons' queue, not ours. Our only
ask: if (d) is ratified, we want it before freezing a v0.2 fixture carrying
`generated`, so the regeneration happens once.
**Settled for OUR profile 2026-07-27 — and only for ours.** The operator chose
(d) for `OKF_V0_2`, which shipped in D2 as
**Settled for OUR profile 2026-07-27 — and only for ours. SUPERSEDED 2026-07-31:
the actor is `process:okf-ingest`, and option (d) is excluded.** Commons decided
the fixed id on our own proposal, and `ingest-spec.md:7-8` — frozen on the spec
being framework-neutral — is what excludes (d): our repo name in the normative
id would force every other conformant implementation to write it into its own
output. The paragraph below is kept as written because its *reasoning* still
holds and only its outcome moved; the ask it describes was discharged in the
direction we control, just not at the value we first chose.
The operator chose (d) for `OKF_V0_2`, which shipped in D2 as
`OwnershipPolicy(actor="process:llm-ingestion-okf")`. Keep the two apart: V1 as
raised is about `DEFAULT`'s `generated`, and `DEFAULT` states **commons'** §5
layer, so that half stays in their ratification queue as item 8 and is not

View file

@ -5,7 +5,7 @@ source_system: golden-v0-2-sales
source_query: sales.csv
ingested_at: 2026-07-16T12:00:00Z
ingest_manifest: manifest@a83c86e8f847eca2
generated: { by: process:llm-ingestion-okf, at: 2026-07-16T12:00:00Z }
generated: { by: process:okf-ingest, at: 2026-07-16T12:00:00Z }
sources: [{ id: golden-v0-2-sales, resource: fixture }]
---

View file

@ -4,7 +4,7 @@ build-backend = "hatchling.build"
[project]
name = "llm-ingestion-okf"
version = "0.5.0a1"
version = "0.5.0a2"
description = "Shared OKF (Open Knowledge Format) ingestion library: spec-based connectors, bundle inbox, and external-bundle import, with security delegated to llm-ingestion-guard."
readme = "README.md"
license = "MIT"

View file

@ -73,7 +73,7 @@ from .manifest import (
)
from .materialize import IngestResult, materialize_bundle
__version__ = "0.5.0a1"
__version__ = "0.5.0a2"
__all__ = [
"BlockedFile",

View file

@ -748,7 +748,7 @@ OKF_V0_2 = BundleProfile(
# (§8, §12). Built with `replace` rather than restated so a later change to
# the shared shape cannot drift between the two.
index=replace(DEFAULT.index, root_frontmatter=("okf_version",)),
ownership=OwnershipPolicy(actor="process:llm-ingestion-okf"),
ownership=OwnershipPolicy(actor="process:okf-ingest"),
)

View file

@ -18,11 +18,13 @@ Three things, in the order the risk runs:
type: `root`, `connection_ref`, `base_url`. `credential_ref` is never a
locator and never reaches frontmatter.
`generated.by` is `process:llm-ingestion-okf` option (d) from the plan's V1,
chosen by the operator 2026-07-27 over the `<producer>/<version>` form A-E3 was
written against. The value carries no version, which is what keeps a byte-
compared fixture stable across releases. **A-E3 is now stale in the pilot
specification and owes po-claude a correction.**
`generated.by` is `process:okf-ingest` decided by commons 2026-07-31 on this
repo's own proposal, superseding option (d) (`process:llm-ingestion-okf`), which
was chosen here 2026-07-27 and is now explicitly excluded. The exclusion is
`ingest-spec.md:7-8`, frozen on the spec being framework-neutral: normalising
*our* repo name would force every other conformant implementation to write it
into its own output. The value carries no version either way, which is what
keeps a byte-compared fixture stable across releases.
"""
from __future__ import annotations
@ -46,7 +48,7 @@ from llm_ingestion_okf.profiles import DEFAULT, OKF_LATEST, OKF_V0_2, STRICT_V1,
INGESTED_AT = "2026-07-25T12:00:00Z"
STAMP = "manifest@0123456789abcdef"
V0_2_STAMP = f"{{ by: process:llm-ingestion-okf, at: {INGESTED_AT} }}"
V0_2_STAMP = f"{{ by: process:okf-ingest, at: {INGESTED_AT} }}"
def _manifest(source: Source) -> Manifest:

View file

@ -88,7 +88,7 @@ def test_v0_2_profile_reaches_the_emitted_frontmatter(file_setup: tuple[Path, Pa
manifest_path, bundle = file_setup
materialize_bundle(manifest_path, bundle, INGESTED_AT, profile=OKF_V0_2)
text = (bundle / "ingest-orders.md").read_text(encoding="utf-8")
assert f"generated: {{ by: process:llm-ingestion-okf, at: {INGESTED_AT} }}" in text
assert f"generated: {{ by: process:okf-ingest, at: {INGESTED_AT} }}" in text
assert "sources: [{ id: catalogue-1, resource: data }]" in text
assert "generated: true" not in text