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:
parent
5adb1cca62
commit
baae7507a9
14 changed files with 708 additions and 73 deletions
|
|
@ -749,15 +749,32 @@ def load_parked(payload: Mapping[str, Any]) -> ParkedExploration:
|
|||
|
||||
|
||||
def _bundle_index(bundle_dirs: Sequence[str]) -> dict[str, str]:
|
||||
"""Map each knowledge base's id to its directory. The id is the directory's BASENAME.
|
||||
"""Map each knowledge base's id to its directory — the DECLARED id where the base declares one,
|
||||
the directory's basename otherwise (``okf.reconcile_bundle_id``'s rule, S7a-3 pkt. 1).
|
||||
|
||||
A duplicate basename is REFUSED rather than resolved by order: the id is what the manager
|
||||
**Why this door resolves the declaration at all — a CONSEQUENCE of the slacken, not scope
|
||||
creep.** This used to be ``Path(raw).name`` while ``run_mandate_across_bundles`` used
|
||||
``reconcile_bundle_id(raw).id``. While a declared id that disagreed with its mount was refused
|
||||
outright the two could not differ. With declared-wins they can, and then ``explore()`` mints
|
||||
approaches naming the MOUNT while the dispatcher routes by the DECLARATION — an exploration
|
||||
whose own mandate is unroutable.
|
||||
|
||||
**Unreadable falls back to the basename rather than raising, and that is measured.**
|
||||
``test_explore_loadbearing.py`` configures ``/tmp/base-a`` and ``/tmp/one/shared-name`` —
|
||||
directories that do not exist — and expects an ExplorationError about IDs, not an I/O error.
|
||||
Nothing is widened by the fallback: this index answers "which ids may be NAMED", and a base
|
||||
nobody can read is refused a moment later by whichever door actually opens it.
|
||||
|
||||
A duplicate id is REFUSED rather than resolved by order: the id is what the manager
|
||||
names a base by, and two bases answering to one name would let it read A while believing it
|
||||
read B — the S3.2 key-collision class, one layer up.
|
||||
"""
|
||||
index: dict[str, str] = {}
|
||||
for raw in bundle_dirs:
|
||||
bundle_id = Path(raw).name
|
||||
try:
|
||||
bundle_id = okf.reconcile_bundle_id(raw).id
|
||||
except ValueError:
|
||||
bundle_id = Path(raw).name
|
||||
if bundle_id in index:
|
||||
raise ExplorationError(
|
||||
f"two knowledge bases share the id {bundle_id!r} ({index[bundle_id]!r} and "
|
||||
|
|
@ -883,11 +900,12 @@ def navigator_tools(bundle_dirs: Sequence[str]) -> list[FunctionTool]:
|
|||
)
|
||||
def read_bundle(bundle_id: str) -> list[dict[str, Any]]:
|
||||
bundle_dir = _resolve_bundle(index, bundle_id)
|
||||
# The base is OPENED here, so this is where it is reconciled against its mount (Step 10).
|
||||
# ``_bundle_index`` above stays PURE — it does no file I/O, and must not: two of its own
|
||||
# arms configure directories that do not exist and expect an id error, not an I/O one.
|
||||
okf.reconcile_bundle_id(bundle_dir)
|
||||
bundle = okf.navigate_bundle(bundle_dir)
|
||||
# The base is OPENED here, so this is where it must be able to say what it IS (S7a-3
|
||||
# pkt. 1). A declared id that disagrees with the MOUNT is no longer refused — that is a
|
||||
# filesystem accident, recorded by the run rather than blocked here — but two concepts
|
||||
# declaring two different corpora is a base no fallback can settle.
|
||||
okf.assert_declared_ids_agree(bundle)
|
||||
# ``context_files``, NEVER ``files``: it is the property that drops the ``type: verdict``
|
||||
# layer AND nested ``index.md`` at every level. Building from ``files`` would put prior
|
||||
# verdicts in front of the navigator around the gated ExpeL fold (målbilde §4), and the
|
||||
|
|
|
|||
|
|
@ -866,7 +866,20 @@ def navigate_bundle(bundle_dir: str) -> Bundle:
|
|||
|
||||
|
||||
class BundleIdMismatch(ValueError):
|
||||
"""A base declares a ``bundle_id`` its mount does not carry.
|
||||
"""A base cannot say what it is: two of its CONCEPTS declare different ``bundle_id`` values.
|
||||
|
||||
**This used to mean something else, and the change is an operator decision (S7a-3 pkt. 1).**
|
||||
Until 2026-09-03 it also covered a declared id that disagreed with the directory the base was
|
||||
mounted under. That refusal was measured against the first delivered corpus that declares its
|
||||
own id (K2: 618 of 630 concept files, mounted under a different name) and it made the base
|
||||
unopenable at every door, with re-mounting by hand as the only remedy. The mount is a filesystem
|
||||
accident; the declaration is the artefact speaking. A disagreement between them is now RECORDED
|
||||
(``ResolvedBundleId.mount`` + ``ProvenanceStamp.bundle_id_source`` + one warning line), never
|
||||
refused.
|
||||
|
||||
What is left is the disagreement no mount name could ever settle: within ONE base, two concepts
|
||||
naming two different corpora. There is no fallback that makes that base coherent, and an
|
||||
artefact stamped from it would name one of the two at random.
|
||||
|
||||
A ``ValueError`` DELIBERATELY: it must land on ``run.main``'s refusal tuple and on hosting's
|
||||
400 arm rather than on the crash channel. ``ExplorationError`` is a ``RuntimeError`` and would
|
||||
|
|
@ -884,16 +897,22 @@ _BUNDLE_ID_KEY = "bundle_id"
|
|||
|
||||
@dataclass(frozen=True)
|
||||
class ResolvedBundleId:
|
||||
"""A base's id together with WHERE it came from.
|
||||
"""A base's id, WHERE it came from, and the mount it was read from.
|
||||
|
||||
``origin`` is REQUIRED WITHOUT DEFAULT, for the reason ``ProvenanceStamp.cost_baseline_anchored``
|
||||
is: both defaults would lie about an event. Defaulting to ``"mount-derived"`` would let a
|
||||
resolver that never read the base claim it had; defaulting to a declared value would claim a
|
||||
declaration that never happened.
|
||||
|
||||
``mount`` is CARRIED rather than discarded once the declaration wins (S7a-3 pkt. 1): the
|
||||
warning a run prints names both, and a caller reading an artefact months later needs to know
|
||||
which directory the corpus was read from. A resolver that kept only the winner could report
|
||||
that something was overridden without being able to say what.
|
||||
"""
|
||||
|
||||
id: str
|
||||
origin: BundleIdOrigin
|
||||
mount: str
|
||||
|
||||
|
||||
def _declared_bundle_id(frontmatter: dict[str, str]) -> str:
|
||||
|
|
@ -901,18 +920,6 @@ def _declared_bundle_id(frontmatter: dict[str, str]) -> str:
|
|||
return unquote_scalar(frontmatter.get(_BUNDLE_ID_KEY, "")).strip()
|
||||
|
||||
|
||||
def _reconciled(
|
||||
declared: str, mount: str, origin: BundleIdOrigin, bundle_dir: str
|
||||
) -> ResolvedBundleId:
|
||||
if declared != mount:
|
||||
raise BundleIdMismatch(
|
||||
f"knowledge base {bundle_dir!r} declares bundle_id {declared!r} but is mounted as "
|
||||
f"{mount!r}; an approach names a base by that id, so a run would evaluate against one "
|
||||
f"and report the other (source: {origin})"
|
||||
)
|
||||
return ResolvedBundleId(id=declared, origin=origin)
|
||||
|
||||
|
||||
def reconcile_bundle_id(
|
||||
bundle_dir: str | Path, *, concept_name: str | None = None
|
||||
) -> ResolvedBundleId:
|
||||
|
|
@ -930,16 +937,26 @@ def reconcile_bundle_id(
|
|||
2. the root ``index.md``'s frontmatter → ``"declared-index"``;
|
||||
3. the mount's basename → ``"mount-derived"``.
|
||||
|
||||
A declared id that DISAGREES with the mount raises ``BundleIdMismatch`` at whichever source
|
||||
declared it. A base whose root ``index.md`` cannot be read is **unknown, not undeclared**:
|
||||
A declared id that DISAGREES with the mount is NOT an error (operator decision, S7a-3 pkt. 1):
|
||||
the declaration wins, the mount is carried alongside on ``ResolvedBundleId.mount``, and the
|
||||
caller that opened the base is the one that reports it. What still refuses is a base whose
|
||||
CONCEPTS disagree with each other — see ``assert_declared_ids_agree``, which is a separate,
|
||||
unconditionally called check rather than a branch here, so a door that forgot it fails a test
|
||||
of its own instead of quietly skipping a refusal.
|
||||
|
||||
A base whose root ``index.md`` cannot be read is **unknown, not undeclared**:
|
||||
``navigate_bundle``'s fail-fast propagates unchanged, because reading an unreadable base as
|
||||
"it declares nothing" would widen the answer on missing evidence.
|
||||
|
||||
MEASURED 2026-09-02: no file under ``shared/`` declares the key (zero ``^bundle_id`` hits
|
||||
against a known-positive control of 31 files carrying ``^type:``), so every base in this repo
|
||||
resolves ``mount-derived`` today and both declared branches are DEFENSIVE.
|
||||
resolves ``mount-derived`` today and both declared branches are DEFENSIVE — the first corpus in
|
||||
the wild to take a declared branch was K2 (measured 2026-09-03, 619 declaring files).
|
||||
|
||||
**Honesty limit, stated:** without ``concept_name`` the root ``index.md`` answers, so a base
|
||||
whose index declares X while its concepts declare Y resolves to X. That is B1's resolution
|
||||
ORDER, unchanged here; the agreement check below is about concepts colliding with each other.
|
||||
|
||||
:raises BundleIdMismatch: a declared id the mount does not carry.
|
||||
:raises ValueError: the root ``index.md`` is missing or unreadable.
|
||||
"""
|
||||
root = str(bundle_dir)
|
||||
|
|
@ -950,14 +967,52 @@ def reconcile_bundle_id(
|
|||
raise ValueError(f"OKF bundle has no readable concept {concept_name!r}: {root!r}")
|
||||
declared = _declared_bundle_id(concept.frontmatter)
|
||||
if declared:
|
||||
return _reconciled(declared, mount, "declared-concept", root)
|
||||
return ResolvedBundleId(id=declared, origin="declared-concept", mount=mount)
|
||||
index = _load_file(root, _INDEX_NAME)
|
||||
if index is None:
|
||||
raise ValueError(f"OKF bundle has no readable {_INDEX_NAME}: {root!r}")
|
||||
declared = _declared_bundle_id(index.frontmatter)
|
||||
if declared:
|
||||
return _reconciled(declared, mount, "declared-index", root)
|
||||
return ResolvedBundleId(id=mount, origin="mount-derived")
|
||||
return ResolvedBundleId(id=declared, origin="declared-index", mount=mount)
|
||||
return ResolvedBundleId(id=mount, origin="mount-derived", mount=mount)
|
||||
|
||||
|
||||
def assert_declared_ids_agree(bundle: Bundle) -> None:
|
||||
"""Refuse a navigated base whose CONCEPTS declare two different ``bundle_id`` values.
|
||||
|
||||
This is the collision the slacken (S7a-3 pkt. 1) deliberately keeps: a declared id that
|
||||
disagrees with the MOUNT is a filesystem accident and is now recorded rather than refused, but
|
||||
two concepts inside one base naming two different corpora is a base that cannot say what it is.
|
||||
No fallback settles it, and every artefact stamped from it would name one of the two at random.
|
||||
|
||||
**Concepts only — the root ``index.md`` is NOT in the set, and that is decision B1 applied a
|
||||
second time.** Concept-beats-index is a PRECEDENCE rule, so an index out of step with its
|
||||
concepts is the fallback losing, not a collision. Folding the index in would newly refuse
|
||||
exactly the K2-shaped bases the slacken exists to admit.
|
||||
|
||||
Reads ``context_files``, which is also what drops the ``type: verdict`` layer and nested
|
||||
``index.md`` at every level — the same property ``read_bundle`` is built from, so the two
|
||||
cannot disagree about which files count as concepts.
|
||||
|
||||
A SEPARATE function rather than a branch inside ``reconcile_bundle_id``: it needs a navigated
|
||||
bundle, and ``reconcile_bundle_id`` must stay pure (``explore._bundle_index`` resolves ids for
|
||||
directories that may not exist). Being separate also gives it its own mutation — detach the call
|
||||
at a door and that door's own arm goes red, instead of a refusal quietly not happening.
|
||||
|
||||
:raises BundleIdMismatch: two concepts declare different ids.
|
||||
"""
|
||||
declared: dict[str, str] = {}
|
||||
for f in bundle.context_files:
|
||||
value = _declared_bundle_id(f.frontmatter)
|
||||
if value:
|
||||
declared.setdefault(value, f.name)
|
||||
if len(declared) > 1:
|
||||
named = ", ".join(f"{value!r} (in {name!r})" for value, name in sorted(declared.items()))
|
||||
raise BundleIdMismatch(
|
||||
f"knowledge base {bundle.dir!r} cannot say what it is: its concepts declare "
|
||||
f"{len(declared)} different bundle_id values — {named}; an approach names a base by "
|
||||
"that id, so a run would evaluate against one corpus and report the other"
|
||||
)
|
||||
|
||||
|
||||
def bundle_context(bundle: Bundle, *, dimension: str | None = None) -> str:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -224,6 +224,12 @@ class DryRunReport:
|
|||
#: because a dry run stops before any proposal exists, so there is no stamp to read it off —
|
||||
#: and this surface is precisely where the un-anchored case was measured to be silent.
|
||||
cost_baseline_anchored: bool
|
||||
#: Which knowledge base a real run would judge, and how its identity was established
|
||||
#: (``ProvenanceStamp.bundle_id_source``). Carried here for the same reason
|
||||
#: ``cost_baseline_anchored`` is: a dry run stops before any stamp exists, and this surface is
|
||||
#: precisely where a mount that disagrees with the declaration would otherwise be silent.
|
||||
#: ``None`` on the road path.
|
||||
bundle_id_source: okf.ResolvedBundleId | None
|
||||
#: Every cross-link the bundle navigation could not follow (``okf.Bundle.skipped``). EMPTY is a
|
||||
#: positive statement — "every cross-link was followed" — which is why it DEFAULTS, unlike
|
||||
#: ``cost_baseline_anchored`` above: a missing bool would have to claim something about an event
|
||||
|
|
@ -535,6 +541,34 @@ def cost_baseline_notice(anchored: bool) -> str | None:
|
|||
return None if anchored else _UNANCHORED_NOTICE
|
||||
|
||||
|
||||
def bundle_id_notice(resolved: okf.ResolvedBundleId | None) -> str | None:
|
||||
"""Render the one line that says a base was mounted under a name it does not answer to, or
|
||||
``None`` when there is nothing to say.
|
||||
|
||||
The warning half of the S7a-3 slacken. A declared id that disagrees with its directory is no
|
||||
longer refused — it is a filesystem accident, and refusing it made the first delivered corpus
|
||||
that declares its own id unopenable — but it must not become SILENT either: every artefact the
|
||||
run stamps names the declared id, while the operator typed the mount.
|
||||
|
||||
ONE renderer with N callsites, never N copies of the wording (kø-(p)), and it takes the
|
||||
ALREADY-RESOLVED value rather than a bundle path: a renderer that re-read the base would be a
|
||||
second resolution of the same rule, free to drift from the run it describes
|
||||
(``cost_baseline_notice``'s rule, and the reason ``ResolvedBundleId`` carries the mount).
|
||||
|
||||
``None`` on agreement AND on ``None`` — omission, never an empty row (``mandate.announce``'s
|
||||
rule). A run with no knowledge base has no identity to disagree about.
|
||||
|
||||
Both names are printed. A warning that says only "mismatch" leaves the operator to go and look
|
||||
for the two values it is warning about."""
|
||||
if resolved is None or resolved.id == resolved.mount:
|
||||
return None
|
||||
return (
|
||||
f" Knowledge base: declares bundle_id {resolved.id!r} (source: {resolved.origin}) but is "
|
||||
f"mounted as {resolved.mount!r} — the DECLARED id is the identity, so every artefact this "
|
||||
f"run stamps names {resolved.id!r}"
|
||||
)
|
||||
|
||||
|
||||
def collision_notice(collisions: tuple[VerdictCollision, ...]) -> str | None:
|
||||
"""Render which candidates two bases both described, or ``None`` when none did.
|
||||
|
||||
|
|
@ -690,11 +724,13 @@ async def run_project(
|
|||
# before the amendment (every commons-owned golden) is legitimately un-anchored -> None =
|
||||
# pre-S4.0 behaviour. A baseline that exists but is malformed still raises (fail-closed).
|
||||
if bundle_dir is not None:
|
||||
# ONE bundle-id rule (Step 10): the base is reconciled against the mount it was opened
|
||||
# from, HERE rather than in ``explore._bundle_index``, which stays pure and does no I/O.
|
||||
# A base that declares an id its mount does not carry is refused before anything is spent.
|
||||
okf.reconcile_bundle_id(bundle_dir)
|
||||
bundle = okf.navigate_bundle(bundle_dir)
|
||||
# ONE bundle-id rule (Step 10, slackened S7a-3 pkt. 1): the DECLARED id is the identity and
|
||||
# the mount is carried alongside, so a base delivered under a directory name of its own is
|
||||
# opened rather than refused. What is still refused, before a single model call: a base
|
||||
# whose concepts declare two different corpora.
|
||||
resolved_bundle_id: okf.ResolvedBundleId | None = okf.reconcile_bundle_id(bundle_dir)
|
||||
okf.assert_declared_ids_agree(bundle)
|
||||
project = _project_from_bundle(bundle_dir, project_id, bundle=bundle)
|
||||
# The THIRD projection into ``CostBaseline`` (MAJOR-4), behind an EXPLICIT commission and
|
||||
# never silent. The refusal PROPAGATES rather than degrading to the file loader: a caller
|
||||
|
|
@ -722,6 +758,8 @@ async def run_project(
|
|||
citations = [chunk_dict_to_citation(c) for c in chunks]
|
||||
context = "\n".join(c["snippet"] for c in chunks)
|
||||
skipped_links = ()
|
||||
# No knowledge base, so no bundle identity — said by ABSENCE rather than by minting one.
|
||||
resolved_bundle_id = None
|
||||
debate_tools = [make_retrieval_tool(docs_dir, top_k=top_k)]
|
||||
|
||||
# Trekk B2 (krav 3): configured MCP servers become tools the AGENTS can call during the debate.
|
||||
|
|
@ -783,6 +821,7 @@ async def run_project(
|
|||
max_tokens=max_tokens,
|
||||
top_k=top_k,
|
||||
cost_baseline_anchored=baseline is not None,
|
||||
bundle_id_source=resolved_bundle_id,
|
||||
skipped_links=skipped_links,
|
||||
)
|
||||
# The MCP lifecycle (Trekk B2): entered HERE, after the dry-run cut above, so a dry run never
|
||||
|
|
@ -914,6 +953,10 @@ async def run_project(
|
|||
# anchoring than the one that ran. The road path is anchored by construction (the reference
|
||||
# project's own cost_items ARE the baseline); a bundle is anchored iff it ships the file.
|
||||
cost_baseline_anchored=baseline is not None,
|
||||
# WHICH corpus was judged, and whether the base named itself or the mount named it for it.
|
||||
# Read off the SAME resolution the run opened the base with (kø-(p)); ``None`` on the road
|
||||
# path, where no knowledge base exists to name.
|
||||
bundle_id_source=resolved_bundle_id,
|
||||
# B4: which external service the debate actually called. Read AFTER the debate, so it is a
|
||||
# record rather than an intention. The honesty limit lives on ``ExternalCall`` itself: this
|
||||
# is the call and its source, not a verified rendering of the service's answer.
|
||||
|
|
@ -2842,6 +2885,12 @@ def main(argv: list[str] | None = None) -> int:
|
|||
nav_notice = skipped_links_notice(report.skipped_links)
|
||||
if nav_notice is not None:
|
||||
print(nav_notice)
|
||||
# The third silence on this surface (S7a-3 pkt. 1): a base delivered under a directory name
|
||||
# of its own now OPENS, so the disagreement has to be said out loud or nothing ever reports
|
||||
# that the run's artefacts name something other than the path the operator typed.
|
||||
id_notice = bundle_id_notice(report.bundle_id_source)
|
||||
if id_notice is not None:
|
||||
print(id_notice)
|
||||
return 0
|
||||
|
||||
try:
|
||||
|
|
@ -2890,6 +2939,11 @@ def main(argv: list[str] | None = None) -> int:
|
|||
nav_notice = skipped_links_notice(result.skipped_links)
|
||||
if nav_notice is not None:
|
||||
print(nav_notice)
|
||||
# Same renderer on the full run, read off the run's OWN stamp — so stdout and the outbox
|
||||
# artefact cannot disagree about which corpus was judged.
|
||||
id_notice = bundle_id_notice(result.provenance.bundle_id_source)
|
||||
if id_notice is not None:
|
||||
print(id_notice)
|
||||
# The settlement against the commission (Trekk A4). Empty without a mandate, so an
|
||||
# un-commissioned run prints exactly what it printed before.
|
||||
settlement = settle(result.coverage)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue