This commit is contained in:
Kjell Tore Guttormsen 2026-09-02 21:16:39 +02:00
commit 21c476bbe7
13 changed files with 693 additions and 9 deletions

View file

@ -58,6 +58,19 @@ checker (reasoning) — they judge the same candidate and are never conflated (
Eight steps. Steps 16 happen within one run; steps 78 close the learning loop across runs
separated in time.
**Informative note — exploration before the loop (deliberately unnumbered).** The loop is entered
with a **mandate**: one project, plus the objective its candidates are generated against. This
specification does not say where that mandate comes from — a consumer can be handed one, or can
*derive* one first, by asking clarifying questions, testing framings against the bundles that are
available, and settling the objective before Step 1 begins. Consumers have called that preparatory
activity *step 0 — explore*. It is not numbered here, and this specification defines no step zero:
the loop's steps are 18, a number in the same row would inherit that row's authority, and this
activity carries no conformance requirement — it adds no contract field, and no seam in §11 covers
it. It relaxes nothing downstream either: however the mandate was arrived at, Step 1's navigation
rules, Step 4's deterministic validator gate and the verdict-layer exclusion apply unchanged. The
note exists so that two implementations building the same preparatory stage recognise it as the
same stage — not so that either is required to build it.
### Step 1 — Understand the context (navigate, never stuff)
The agent read-context for a project MUST be built by **navigating** its OKF bundle with
@ -89,6 +102,45 @@ it) into the prompt:
in-/out-of-bundle test.
- Frontmatter is the leading `---`-delimited block, parsed line-oriented as `key: value`
strings; the single required field is `type`; unknown fields MUST be preserved.
**Line-oriented parsing is normative and is not relaxed by the amendment below:** a value is
what follows the first `: ` on its own line, and a value continued onto a following line is
not read.
- **Amendment A1 (2026-09-02) — multi-source provenance.** A concept MAY derive from more than
one source, and `sources` is the field that records it. Its normative written form is a
**single-line flow sequence of one or more flow mappings**`sources: [{ k: v, … }]` or
`sources: [{ k: v, … }, { k: v, … }]` — read as an **ordered tuple of entries**, one entry
per mapping, in written order. Entry keys are read **as written**, never against a closed
set, so a profile that adds entry keys stays readable. A **block list** (`sources:` followed
by indented `- ` items) MUST NOT be emitted; a consumer that encounters one MUST report it as
**unreadable, naming the shape and the number of entries seen**, and MUST NOT silently keep
one entry. A single-mapping flow value normalises to a one-element tuple, so *one source* and
*several sources* are the same shape read the same way, and last-write-wins never arises.
*(Amendments carry the date they were decided; the version record is in
[CHANGELOG.md](CHANGELOG.md).)*
**Informative note — what A1 fixes, and the axis it does not speak on.** The form was pinned
because line-oriented `key: value` has exactly one value per key, so a multi-source concept
written as a block list loses every entry but one, silently — the failure mode a consumer
cannot detect after the fact. The amendment also carries a figure this repository did not
measure and reports as its author's: the order that commissioned A1 states, of the reference
corpus on 2026-09-01, *"K5-taket målt 01.09: 2 av 5 nøkler på ÉN kilde"* — a ceiling on how far
a claim can be corroborated rather than a property of the material. The mechanism above carries
A1 on its own; the figure is support, not the ground. A1 binds **emission** — what a producer MUST write. It does not
say a block list is malformed as such: a consumer's own decoder is entitled to accept a
narrower subset than it is handed, and the reference consumer records exactly that of its
accepted subset — *"A block sequence and a block mapping are both **conformant** OKF; they
are simply outside the accepted subset, and the decoder is not entitled to an opinion about
whether the author erred."* The two statements sit on different axes and neither overrides
the other: A1 forbids **writing** the block form here; it does not reclassify text already
written elsewhere.
**Open finding, measured 2026-09-02, not resolved by A1.** The `llm-ingestion-guard` gate at
version 1.2.0 rejects **both** forms — `sources: [{ … }]` with `OKFFrontmatterError: value
begins with a disallowed YAML indicator '['`, and the block list with `a mapping is not
expressible in OKF frontmatter`. Known-positive control: a single-line `title` passes, and
`verified: { by: …, at: … }` passes as a flow mapping. So A1 pins a form no shipped version
of that gate reads today. This is recorded here rather than worked around, because the
alternative form fails for a worse reason: it loses data instead of raising.
- The rendered read-context is the index body (the summary) followed by each non-index
concept file as a `## {type}: {title}` section; empty sections are dropped. Rendering is
**flat regardless of nesting depth** — directory structure is navigation, not presentation,
@ -461,4 +513,5 @@ is enforced by the spec-integrity test):
| `approved`, `rejected` | decision vocabulary (run path, binary) | §4, §4.1 |
| `approved_with_adjustment` | decision vocabulary (seed frontmatter + gate only) | §4, §6 |
| `type` | OKF frontmatter (required field) | §2, §3 Step 1 |
| `sources` | OKF frontmatter (multi-source provenance, Amendment A1) | §3 Step 1 |
| `realization_rate` (frontmatter) | bundle seed (structured learning fields) | §3 Step 1, §6 |