feat(okf): den erklaerte bundle_id-en er identiteten - mountet er en filsystem-tilfeldighet

S7a-3 pkt. 1. Til i dag NEKTET reconcile_bundle_id en base som erklaerte en id
katalogen ikke bar. Maalt mot K2 - den foerste leverte basen som erklaerer sin
egen id (618 av 630 konseptfiler + rot-index, alle "k2-trinn1-20260903", levert
som "K2-bundle-20260903") - betydde det at basen ikke kunne aapnes slik den var
levert, og at eneste botemiddel var aa montere den paa nytt for haand, en gang
per leveranse. PM-beslutning: konsumenten slakker.

- Erklaert vinner (B1s rekkefoelge uroert), avviket REGISTRERES:
  ResolvedBundleId.mount + ProvenanceStamp.bundle_id_source +
  DryRunReport.bundle_id_source + run.bundle_id_notice (None ved enighet).
  Stempel-feltet er PAAKREVD uten default: None er en VERDI (veg-stien).
- Det som fortsatt nekter er den EKTE kollisjonen: to KONSEPTER i en base som
  erklaerer ULIKE id-er (okf.assert_declared_ids_agree, kalt ved hver doer som
  aapner en base). Rot-index er IKKE med i enighets-settet - konsept-slaar-index
  er en presedens-regel, saa en index i utakt er fallbacken som taper.
- KONSEKVENS, ikke scope-krype: explore._bundle_index loeser naa den erklaerte
  id-en. Den brukte Path(raw).name mens dispatcheren brukte reconcile...id; med
  erklaert-vinner ville explore() myntet approaches som navngir MOUNTET mens
  dispatcheren ruter paa ERKLAERINGEN - en utforskning med uruterbart mandat.

Load-bearing MAALT: 10 mutasjoner alle roede mot HELE suiten, groenn kontroll
1243 passed / 5 skipped og golden demo-transcript.stdout byte-uendret
(shasum -a 1 = ea8c534773acdbe41ae68f2c55724d69aaf8be4f).
M1 1 / M2 1 / M3 1 / M4 9 / M5 2 / M6 1 / M7 1 / M8 2 / M9 2 / M11 1.

Tre armer i test_bundle_id_reconciliation_loadbearing er SKREVET OM (ikke
slettet) - de pinnet nekten beslutningen fjernet. (j) ble skarpere enn den den
erstattet: erklaert id ruter, mountet nektes.

Kontrakt: docs/okf-konsum-kontrakter.md § 3.1. Invariantrad i CLAUDE.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-03 06:47:58 +02:00
commit baae7507a9
14 changed files with 708 additions and 73 deletions

View file

@ -18,6 +18,7 @@ from typing import Literal
from agent_framework import Annotation, TextSpanRegion
from pydantic import BaseModel, Field
from portfolio_optimiser.okf import ResolvedBundleId
from portfolio_optimiser.retrieval import TextSpan
@ -71,6 +72,20 @@ class ProvenanceStamp(BaseModel):
#: forgot claim an anchoring that never happened, and ``False`` would under-claim a real one.
#: A binary fact about a falsifier has no honest default.
cost_baseline_anchored: bool
#: WHICH knowledge base this proposal was reasoned from, and how its identity was established —
#: ``okf.ResolvedBundleId`` (declared id / origin / the mount it was read from), or ``None`` on
#: the road path, where no knowledge base was involved at all.
#:
#: REQUIRED WITHOUT DEFAULT, for ``cost_baseline_anchored``'s reason: ``None`` is a VALUE here
#: (a run with no base), so letting an omitted field mean it would make "no base" and "nobody
#: filled this in" the same answer. A stamp that cannot say which corpus it judged cannot be
#: joined back to one, and the artefact leaves the process.
#:
#: Not on ``RunResult`` beside ``skipped_links``, and the distinction is deliberate:
#: ``skipped_links`` is diagnostic about the NAVIGATION, while this is the identity of the
#: artefact that was judged — the same class as ``cost_baseline_anchored``, which also resolves
#: once per run and is stamped per proposal.
bundle_id_source: ResolvedBundleId | None
#: External service calls the run made (B4). EMPTY is a positive statement — "nothing outside
#: this process was contacted" — not an absent field, which is why it is always serialized.
external_calls: list[ExternalCall] = Field(default_factory=list)