feat(explore): U4+U13 del 3 - multi-base er en PARTISJON, ikke en videre signatur (ORDRE 20260825T080753Z) [skip-docs]
Ordrens premiss («endrer run_project sin signatur») er FALSIFISERT foer bygging, og ordren ba selv om nettopp den sjekken. run_project kan ikke ta mer enn en bundle_dir: paa bundle-stien avleder den FIRE enkeltverdier fra DEN basen - prosjektet (_project_from_bundle fail-faster naar basens egen project_id ikke er den forespurte), validatorens stage-0-baseline, agentenes lesekontekst og ExpeL-noekkelen - og returnerer ETT stemplet RunResult. En andre katalog paa den signaturen ville tvunget et stille velg-en for alle fire. Planens egen setning sier det samme lest naert: «pipelinen kjoeres per bundle som i dag (run_portfolio-formen)» = N kall, ikke ett kall med N. Levert form, tre soemmer: - mandate.Approach.bundle_id (default "" - hvert mandat skrevet foer i dag er fortsatt gyldig og dispatchbart uendret) - mandate.route_by_bundle - ren partisjon, fail-fast paa et mandat som ikke kan utfoeres som skrevet (load_mandate-regelen). En base som ingen approach navngir kjoeres ikke; med NOEYAKTIG en base absorberer den alt uten navn, som ikke er en gjetning men det eneste mulige svaret. - run.run_mandate_across_bundles - dispatchen. INGEN project_id-parameter: hver base sitt prosjekt leses fra DEN basens egen IR-projeksjon, altsaa den verdien _project_from_bundle allerede fail-faster mot. En delt VerdictStore traades paa tvers (kryss-base-laering, run_portfolio-formen), og med portfolio_meter gjelder de to S3.4-tennene som HAR mening her: oppstartsnekt (BudgetRefused) og aldri-startet + budget_stop + not_evaluated-rader. INGEN eksisterende kaller endrer signatur - CLI, hosting og simulation sender fortsatt en base hver, og kan fortsatt gjoere det. explore(): hver myntet approach baerer bundle_id; markoeren kan navngi basen; en umerket markoer med flere baser NEKTES (HypothesisParseError), med en base resolveres den. Froe-approaches VALIDERES men skrives ALDRI om (§ C.6 doer 1 er en bevaringsregel) - og valideringen skjer FOER foerste modellkall, samme oekt-57-hoist-grunn: ved unntaket alene ser en nekt etter forbruket identisk ut. explore()-docstringens gamle aerlighets-grense («venter paa at run_project tar mer enn en bundle_dir») er RETTET - den ville vaert usann fra i dag. Load-bearing MAALT, 12 mutasjoner alle roede mot HELE suiten, groenn kontroll 1020/5 (fra 999/5 + 21 nye tester); golden demo-transcript.stdout BYTE-UENDRET (ea8c534773acdbe41ae68f2c55724d69aaf8be4f): detach myntet bundle_id (2) · stille gjennomfall ved >1 base (1) · ukjent id resolvert etter rekkefoelge (1) · froe-sjekk etter forbruket (2) · ruteren gjetter foerste base (1) · uroutbar approach droppet (1) · dispatchen kollapser til en base (5) · project_id fra foerste base (2) · detach aldri-startet-tannen (1) · unreached urapportert (1) · fersk store per base (1) · detach oppstartsnekten (2). EN MUTASJON FALSIFISERTE TESTEN FOERST (repoets vakuoes-gate-klasse, aattende gang): store-testen sammenlignet med ==, og VerdictStore er en pydantic-modell med VERDI-likhet - tre ulike tomme stores er alle like, saa «fersk store per base» lot hele suiten staa groenn. Delt INSTANS er paastanden, saa testen asserterer naa paa `is`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L3YHobQC3WzYVoxSgZus4d
This commit is contained in:
parent
3cbea91a72
commit
18af86e422
6 changed files with 1051 additions and 17 deletions
|
|
@ -29,6 +29,7 @@ Two refusals are load-bearing, both at construction time:
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Sequence
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import Literal
|
||||
|
|
@ -50,6 +51,14 @@ class Approach(BaseModel):
|
|||
id: str = Field(min_length=1)
|
||||
label: str = Field(min_length=1)
|
||||
description: str = ""
|
||||
#: Which knowledge base this approach belongs to (§ C.7), by the base's id — the directory's
|
||||
#: BASENAME, exactly as ``explore._bundle_index`` names it. DEFAULTS to empty, meaning "no base
|
||||
#: named": a legitimate statement when the run has only one base to name, and what keeps every
|
||||
#: mandate written before multi-base existed valid and dispatchable unchanged.
|
||||
#:
|
||||
#: The field is a ROUTING key, never a claim about content. It says which pipeline the approach
|
||||
#: must be evaluated in, and ``route_by_bundle`` is the one place that reads it.
|
||||
bundle_id: str = ""
|
||||
|
||||
|
||||
class Mandate(BaseModel):
|
||||
|
|
@ -88,6 +97,85 @@ class Mandate(BaseModel):
|
|||
return self
|
||||
|
||||
|
||||
class MandateRoutingError(ValueError):
|
||||
"""A commission that cannot be executed against the bases it was given (§ C.7).
|
||||
|
||||
**A ``ValueError`` by construction, and that is a measurement rather than a taxonomy note.**
|
||||
økt 57 paid for the opposite: ``ExplorationError`` is a ``RuntimeError`` and therefore fell
|
||||
outside ``run.main``'s ``(ValueError, FileNotFoundError, ValidationError)`` refusal tuple and
|
||||
outside ``hosting``'s 400 arm, so a caller's configuration mistake would have left as a
|
||||
traceback on one surface and a 500 — the crash channel — on the other. A routing refusal is
|
||||
exactly that class of caller mistake, so it is born inside both nets instead of being
|
||||
retrofitted into them later.
|
||||
"""
|
||||
|
||||
|
||||
def route_by_bundle(mandate: Mandate, bundle_ids: Sequence[str]) -> tuple[tuple[str, Mandate], ...]:
|
||||
"""Partition one commission into one sub-mandate PER knowledge base (§ C.7).
|
||||
|
||||
This is the whole of "multi-base", and it is deliberately a partition rather than a widening.
|
||||
``run_project`` derives four single-valued things from THE bundle it is given — the project
|
||||
(``_project_from_bundle`` fail-fasts when the bundle's own ``project_id`` is not the requested
|
||||
one), the validator's stage-0 cost baseline, the agents' read context and the ExpeL query key —
|
||||
and returns ONE ``RunResult`` with ONE ``ProvenanceStamp``. A second ``bundle_dir`` on that
|
||||
signature would force a silent pick-one for all four. § C.7 says the same thing in its own
|
||||
words: *pipelinen kjøres per bundle som i dag* — N calls, not one call taking N.
|
||||
|
||||
Order is taken from ``bundle_ids``, never from first appearance among the approaches, so the
|
||||
dispatch's spend order is a property of how the run was configured rather than of how a model
|
||||
happened to sequence its hypotheses.
|
||||
|
||||
**Fail-fast on a commission that cannot be executed as written**, mirroring ``load_mandate``'s
|
||||
contract for exactly its reason: a run must never proceed on a *silently degraded* commission,
|
||||
because the coverage report would then describe work nobody ordered. Two ways that happens, and
|
||||
both refuse by name rather than resolving by position (the S3.2 key-collision class):
|
||||
|
||||
* an approach naming a base that was not configured;
|
||||
* an approach naming NO base while more than one is configured — with a single base there is no
|
||||
other value the field could take, so resolving it there is the only answer rather than a
|
||||
guess, and it is what keeps every pre-multi-base mandate dispatchable unchanged.
|
||||
|
||||
A base that no approach names is NOT run: a run costs money and the commission ordered nothing
|
||||
for it. The single-base case keeps its own rule above, so an own-proposals-only mandate still
|
||||
reaches the one base it could possibly mean.
|
||||
|
||||
:raises MandateRoutingError: no bases configured, or an approach that cannot be routed.
|
||||
"""
|
||||
if not bundle_ids:
|
||||
raise MandateRoutingError(
|
||||
"a mandate cannot be routed against zero knowledge bases: an empty plan reads as "
|
||||
"'there was nothing to do', which is indistinguishable from a commission that was "
|
||||
"fully evaluated against nothing"
|
||||
)
|
||||
|
||||
known = tuple(bundle_ids)
|
||||
sole = known[0] if len(known) == 1 else None
|
||||
grouped: dict[str, list[Approach]] = {bundle_id: [] for bundle_id in known}
|
||||
for approach in mandate.approaches:
|
||||
target = approach.bundle_id or sole
|
||||
if target is None:
|
||||
raise MandateRoutingError(
|
||||
f"approach {approach.id!r} names no knowledge base and {len(known)} are "
|
||||
f"configured ({', '.join(known)}); which one it belongs to is not something this "
|
||||
"layer may decide on the expert's behalf"
|
||||
)
|
||||
if target not in grouped:
|
||||
raise MandateRoutingError(
|
||||
f"approach {approach.id!r} names knowledge base {target!r}, which is not "
|
||||
f"configured for this run; configured: {', '.join(known)}"
|
||||
)
|
||||
grouped[target].append(approach)
|
||||
|
||||
return tuple(
|
||||
(
|
||||
bundle_id,
|
||||
mandate.model_copy(update={"approaches": tuple(grouped[bundle_id])}),
|
||||
)
|
||||
for bundle_id in known
|
||||
if grouped[bundle_id] or sole is not None
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ApproachOutcome:
|
||||
"""What became of ONE commissioned approach — one row of the run's coverage report.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue