feat(p17b): ONE commission, SEVERAL bases -- reachable from the command line

``run_mandate_across_bundles`` has existed since session 58, reachable from FIVE
test files and from NO command line (measured: ``grep -n across-bundle run.py``
= 0 hits). ``--across-bundle <dir>``, repeated once per base, is that door.

The engine takes a CALLBACK rather than an outbox directory. Its own docstring
has always said N runs need N ``run_id``s and that minting them there would
default a key this repo requires a caller to supply -- so ``outbox_for`` is that
contract KEPT, not relaxed, and the operator-chosen ``<run-id>-<bundle_id>``
rule lives in ``main()`` where the decision was made. The order's alternative (a
caller running ``run_project`` itself over ``route_by_bundle``'s sub-mandates)
would be a second copy of the loop's id reconciliation, shared store, per-base
project resolution, collision accounting and both budget teeth.

``resolve_bundle_routing`` is ONE resolution shared by the engine and the
dry-run arm: a free trip answering with a different project id, or tolerating a
duplicate id the paid dispatch refuses, would rehearse a different run.

``{run-id}-multibase.json`` is written from a ``finally`` and every row is built
from the resolution plus disk, so the pass a cap cut short still leaves the
record. ``completed`` is a required field for ``ExplorationTrace.completed``'s
reason. ``stop_reason`` is read BACK from each base's own coverage artefact.

Load-bearing MEASURED (17 arms), four mutations all red against the WHOLE suite,
green control 1761/5 (from 1744/5, superset, 0 removed), golden byte-unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-15 04:24:48 +02:00
commit 5e4c497a84
5 changed files with 994 additions and 37 deletions

View file

@ -230,6 +230,55 @@ def write_debate_tools(
return path
def write_multibase(
outbox_dir: str,
run_id: str,
*,
runs: Sequence[Mapping[str, Any]],
completed: bool,
unreached: Sequence[Mapping[str, Any]],
collisions: Sequence[Mapping[str, Any]],
stopped_early: bool,
budget_stop: Mapping[str, Any] | None,
) -> Path:
"""Write ``{run_id}-multibase.json`` — what ONE commission did across SEVERAL bases (P17b).
The question no per-base artefact can answer. Each base writes its own full set under its own
minted ``run_id``, but nothing in that set says in which ORDER the bases were spent, which id
each one was given, which approaches were never reached, or which candidates two bases both
described and a reader who has to reconstruct the ``<run-id>-<bundle_id>`` convention to
pair the files back to the pass has been handed a naming rule instead of a record.
Written IFF the pass was given an outbox, exactly like its neighbours, and the per-base
``stop_reason`` rows are READ BACK from each base's own ``{run_id}-coverage.json`` by the
caller rather than recomputed here: P19 D2 put that fact in that file, and a second derivation
of it would be free to disagree with the one the judge reads.
Plain data only, so the RAW output layer stays MAF-free (``write_debate_tools``' own rule)."""
directory = Path(outbox_dir)
directory.mkdir(parents=True, exist_ok=True)
path = directory / f"{run_id}-multibase.json"
path.write_text(
_dump(
{
"run_id": run_id,
# REQUIRED, never inferred from an empty ``unreached``: a pass a cap or a provider
# cut short never got to say what it did not reach, and "nothing was left
# unreached" must not be the value that means "we never found out"
# (``ExplorationTrace.completed``'s own reason).
"completed": completed,
"runs": [dict(row) for row in runs],
"unreached": [dict(row) for row in unreached],
"collisions": [dict(row) for row in collisions],
"stopped_early": stopped_early,
"budget_stop": dict(budget_stop) if budget_stop is not None else None,
}
),
encoding="utf-8",
)
return path
def write_prepass(
outbox_dir: str,
run_id: str,

View file

@ -29,7 +29,7 @@ import asyncio
import json
from collections.abc import Awaitable, Callable, Iterable, Sequence
from contextlib import AsyncExitStack
from dataclasses import dataclass, replace
from dataclasses import asdict, dataclass, replace
from pathlib import Path
from typing import Any, Literal, cast
@ -2181,6 +2181,12 @@ class BundleRun:
bundle_dir: str
project_id: str
result: RunResult
#: The ``run_id`` this base's artefacts were written under, or ``""`` when the pass wrote no
#: outbox at all. Carried here rather than re-derived by the caller for the reason the two
#: fields above are: the CALLER minted it (P17b — N runs need N ids, and this engine refuses
#: to default a key the repo requires a caller to supply), so a reader pairing an artefact
#: back to a base must not have to reconstruct the naming convention to do it.
run_id: str = ""
@dataclass(frozen=True)
@ -2213,6 +2219,116 @@ class MultiBaseResult:
collisions: tuple[VerdictCollision, ...] = ()
def _coverage_stop_reason(outbox_dir: str, run_id: str) -> str:
"""``BudgetExceeded.kind`` this base recorded, read back off its OWN coverage artefact.
Never recomputed from the ``RunResult``: P19 D2 put "why did this run stop" in
``{run_id}-coverage.json`` precisely because ``_evaluate_mandate`` swallows the exception once
something has been produced, so the dispatcher never sees it. A second derivation here would
be free to disagree with the file the judge reads.
``"absent"`` is a THIRD value, and not the same as ``""``: a base that wrote no coverage file
at all is a different finding from one that finished with nothing stopping it the
``stress`` judge's own vocabulary, reused rather than re-invented."""
path = Path(outbox_dir) / f"{run_id}-coverage.json"
if not path.is_file():
return "absent"
try:
return str(json.loads(path.read_text(encoding="utf-8")).get("stop_reason", ""))
except (OSError, json.JSONDecodeError):
return "absent"
def _write_multibase_summary(
outbox_dir: str,
run_id: str,
*,
resolved: Sequence[tuple[str, str, str]],
mint: Callable[[str], tuple[str, str]],
multi: MultiBaseResult | None,
) -> None:
"""Write ``{run_id}-multibase.json`` for a multi-base pass, COMPLETED or not (P17b).
Called from a ``finally``, which is ``write_parse_failures``' rule applied one layer up: the
pass that most needs a record of what it spent is the one a cap or a provider cut short, and
the engine's documented limit is that a base which RAISES propagates. Every per-base row is
therefore built from the RESOLUTION and from DISK the configured bases, the caller's own
minting rule, and each base's own ``{run_id}-coverage.json`` — none of which needs the
dispatch to have returned.
``completed`` is a REQUIRED field of the artefact and not an inference from an empty
``unreached``: ``ExplorationTrace.completed``'s reason verbatim, because "nothing was left
unreached" and "we never found out" must not be the same value. When the pass did not
complete, ``unreached``/``collisions``/``budget_stop`` are what the dispatch never got to say,
and they are written as empty/``None`` UNDER that flag rather than as findings.
"""
rows = []
for bundle_id, bundle_dir, project_id in resolved:
_, base_run_id = mint(bundle_id)
rows.append(
{
"bundle_id": bundle_id,
"bundle_dir": bundle_dir,
"project_id": project_id,
"run_id": base_run_id,
"stop_reason": _coverage_stop_reason(outbox_dir, base_run_id),
}
)
outbox.write_multibase(
outbox_dir,
run_id,
runs=rows,
completed=multi is not None,
unreached=[asdict(row) for row in multi.unreached] if multi is not None else [],
collisions=[asdict(row) for row in multi.collisions] if multi is not None else [],
stopped_early=multi.stopped_early if multi is not None else False,
budget_stop=(
asdict(multi.budget_stop)
if multi is not None and multi.budget_stop is not None
else None
),
)
def resolve_bundle_routing(
bundle_dirs: Sequence[str],
) -> tuple[tuple[str, str, str], ...]:
"""``(bundle_id, bundle_dir, project_id)`` per configured base, in CONFIGURED order.
The ONE resolution shared by ``run_mandate_across_bundles`` and the CLI's multi-base dry run
(P17b). Extracted rather than copied for the reason the id derivation itself was unified in
Step 10: a drill that answered with a different project id, or tolerated a duplicate id the
paid dispatch refuses, would be a free trip that fails to measure the very run it precedes.
``bundle_id`` is ``okf.reconcile_bundle_id``'s — the declared id wins over the mount (S7a-3).
Two bases answering to ONE id refuse here, the same refusal ``explore._bundle_index`` makes
and for the same reason: the id is how the mandate NAMES a base, so a collision would let an
approach be evaluated against A while the report says B (the S3.2 key-collision class).
``project_id`` is S7b søm 1's precedence, and it is load-bearing in BOTH directions: the
hand-written IR projection FIRST (that file is what every existing base has always been routed
by), the base's own DECLARED id as the fallback (an ingested corpus carries no projection, so
file-only could not route it at all). No caller-supplied constant is admitted: it could only
ever be right for one base out of N.
:raises MandateRoutingError: two configured bases share one id.
"""
out: list[tuple[str, str, str]] = []
seen: dict[str, str] = {}
for raw in bundle_dirs:
bundle_id = okf.reconcile_bundle_id(raw).id
if bundle_id in seen:
raise MandateRoutingError(
f"two knowledge bases share the id {bundle_id!r} ({seen[bundle_id]!r} and "
f"{raw!r}); an approach names a base by that id, so it must be unique"
)
seen[bundle_id] = raw
declared_ir = okf.load_optional_ir_projection(raw)
project_id = str(declared_ir["project_id"]) if declared_ir is not None else bundle_id
out.append((bundle_id, raw, project_id))
return tuple(out)
async def run_mandate_across_bundles(
mandate: Mandate,
bundle_dirs: Sequence[str],
@ -2233,6 +2349,17 @@ async def run_mandate_across_bundles(
#: AND ``project_id`` — each base's own, read by ``_project_from_bundle`` — so bases can be
#: told apart even when a multi-base commission reuses approach ids.
proposal_reviewer: ProposalReviewer | None = None,
#: P17b. Where THIS base's artefacts go, and under which ``run_id`` — supplied by the caller
#: per base, never minted here. That is the engine's own long-standing contract kept rather
#: than relaxed: N runs need N ``run_id``s, and minting one here would default a key this repo
#: requires a caller to supply, for byte-determinism. A CALLBACK rather than an
#: ``outbox_dir``/``run_id`` pair because the naming rule is an OPERATOR decision
#: (``<run-id>-<bundle_id>``, chosen 14.09) and belongs at the call site that made it; the
#: alternative the order offered — a caller running ``run_project`` itself over
#: ``route_by_bundle``'s sub-mandates — would be a SECOND copy of this loop's id
#: reconciliation, shared store, per-base project resolution, collision accounting and both
#: budget teeth (kø-(p), over five rules that each have exactly one home).
outbox_for: Callable[[str], tuple[str, str]] | None = None,
) -> MultiBaseResult:
"""Evaluate ONE commission across SEVERAL knowledge bases — the multi-base dispatch (§ C.7).
@ -2267,30 +2394,18 @@ async def run_mandate_across_bundles(
independent projects, whereas here the caller asked for ONE commission to be evaluated.
(2) Without a ``portfolio_meter`` the pass's ceiling is the number of routed bases times
``max_tokens``, each run bounded on its own the global ledger is opt-in, and this does not
re-implement it (``_run_meter`` is the one copy of the binding rule). (3) The outbox is NOT
wired: N runs need N ``run_id``s, and minting them here would default a key this repo requires
a caller to supply, for byte-determinism. A caller who needs artefacts per base calls
``run_project`` itself with the sub-mandates ``route_by_bundle`` hands back.
re-implement it (``_run_meter`` is the one copy of the binding rule). (3) The outbox is
CALLER-KEYED: N runs need N ``run_id``s, and minting them here would default a key this repo
requires a caller to supply, for byte-determinism so ``outbox_for`` hands each base its
directory and its id, and a caller that offers no callback still writes nothing (every
pre-P17b call site, unchanged).
:raises MandateRoutingError: the commission cannot be routed against ``bundle_dirs``.
:raises BudgetRefused: a global remainder that cannot fund a single run.
"""
by_id: dict[str, str] = {}
for raw in bundle_dirs:
# The ONE derivation rule (Step 10) — this used to be a second private copy of
# ``Path(raw).name``, free to drift from ``explore``'s. The REFUSAL below stays local:
# ``MandateRoutingError`` is this door's class, ``ExplorationError`` is explore's, and
# unifying the derivation is not the same as unifying the two doors' error vocabularies.
bundle_id = okf.reconcile_bundle_id(raw).id
if bundle_id in by_id:
# The same refusal ``explore._bundle_index`` makes, for the same reason: the id is how
# the mandate names a base, so two bases answering to one name would let an approach be
# evaluated against A while the report says B (the S3.2 key-collision class).
raise MandateRoutingError(
f"two knowledge bases share the id {bundle_id!r} ({by_id[bundle_id]!r} and "
f"{raw!r}); an approach names a base by that id, so it must be unique"
)
by_id[bundle_id] = raw
resolved = resolve_bundle_routing(bundle_dirs)
by_id = {bundle_id: bundle_dir for bundle_id, bundle_dir, _ in resolved}
project_by_id = {bundle_id: project_id for bundle_id, _, project_id in resolved}
routed = route_by_bundle(mandate, tuple(by_id))
@ -2327,19 +2442,7 @@ async def run_mandate_across_bundles(
break
bundle_dir = by_id[bundle_id]
# ONE reading of the base's own project id, used both to ADDRESS the run and to LABEL it.
# A second lookup for the label would be the kø-(p) duplicate free to drift from the value
# the run was actually dispatched with.
#
# S7b søm 1: the hand-written projection FIRST, the base's DECLARED id as the fallback. The
# precedence is load-bearing in both directions. Declaration-first would re-address every
# existing base whose ``project_id`` differs from its ``bundle_id`` — the file is what those
# bases have always been routed by. File-only was the refusal this seam removes: an ingested
# corpus carries no projection, so it could not be routed at all. ``bundle_id`` is the
# identity every other door already resolves through (S7a-3), so the fallback introduces no
# third notion of what a base is called; ``by_id`` above is that same resolution, reused.
declared_ir = okf.load_optional_ir_projection(bundle_dir)
project_id = str(declared_ir["project_id"]) if declared_ir is not None else bundle_id
project_id = project_by_id[bundle_id]
# D2: the id of the verdict THIS base minted, taken from ``run_project``'s existing
# ``notify`` seam rather than off the returned ``RunResult``. ``notify`` fires inside the
# capture block, so it is called exactly when a verdict exists (F2: never when nobody
@ -2347,6 +2450,7 @@ async def run_mandate_across_bundles(
# each iteration — a shared accumulator would let a later base read the previous base's
# verdict and manufacture a collision that never happened.
minted_here: list[str] = []
base_outbox, base_run_id = outbox_for(bundle_id) if outbox_for is not None else (None, "")
result = cast(
RunResult,
await run_project(
@ -2354,6 +2458,8 @@ async def run_mandate_across_bundles(
profile,
docs_dir=bundle_dir,
bundle_dir=bundle_dir,
outbox_dir=base_outbox,
run_id=base_run_id or None,
notify=lambda verdict: minted_here.append(verdict.id),
verdict_input=verdict_input,
verdict_dir=verdict_dir,
@ -2397,6 +2503,7 @@ async def run_mandate_across_bundles(
bundle_dir=bundle_dir,
project_id=project_id,
result=result,
run_id=base_run_id,
)
)
@ -2535,6 +2642,18 @@ def main(argv: list[str] | None = None) -> int:
parser.add_argument(
"--bundle-dir", default=None, help="OKF bundle dir (enables the Step-1 fold)"
)
parser.add_argument(
"--across-bundle",
action="append",
default=None,
metavar="DIR",
help="P17b: run ONE commission across SEVERAL knowledge bases — repeat the flag once per "
"base. The mandate is partitioned by each approach's bundle_id and the existing pipeline "
"runs once per base, sequentially, threading ONE verdict store so a verdict minted against "
"base k reaches base k+1. Each base writes its own artefact set under <run-id>-<bundle_id>, "
"plus one <run-id>-multibase.json summary. Requires --mandate, --run-id and --outbox-dir; "
"--bundle-dir stays ONE directory and is refused here",
)
parser.add_argument(
"--verdict-dir",
default=None,
@ -2888,6 +3007,10 @@ def main(argv: list[str] | None = None) -> int:
"--goals": args.goals is not None,
"--docs-dir": args.docs_dir is not None,
"--bundle-dir": args.bundle_dir is not None,
# P17b, and for its neighbours' reason: report mode returns ABOVE every dispatch,
# including the multi-base one, so an omission here is a SILENT DROP of a whole pass
# rather than a refusal (the F4 class).
"--across-bundle": bool(args.across_bundle),
"--verdict-dir": args.verdict_dir is not None,
"--outbox-dir": args.outbox_dir is not None,
"--run-id": args.run_id is not None,
@ -2969,6 +3092,13 @@ def main(argv: list[str] | None = None) -> int:
single_only = {
"--docs-dir": args.docs_dir,
"--bundle-dir": args.bundle_dir,
# P17b. A portfolio pass keys on PROJECTS and reads each project's base off its own
# row, so a run-level list of bases has nowhere to go; the two are different axes
# (``MultiBaseResult`` is a distinct type from ``PortfolioResult`` for exactly that
# reason). BY NAME, like its neighbours: falling through to "--across-bundle requires
# --mandate" would tell an operator who wrote --portfolio --across-bundle to add a
# flag that is legal in both modes, which answers the wrong question.
"--across-bundle": bool(args.across_bundle),
"--verdict-dir": args.verdict_dir,
"--outbox-dir": args.outbox_dir,
"--run-id": args.run_id,
@ -3037,13 +3167,63 @@ def main(argv: list[str] | None = None) -> int:
)
return 1
# P17b — the multi-base door's own refusals, at FUNCTION level and never nested under another
# flag's branch, for the F4 reason its neighbours are: under one, a bare combination falls
# straight through to a dispatch that drops the flag in silence. Placed ABOVE the required-args
# guard because this mode takes NO ``PROJECT_ID`` at all — each base's project is read from
# THAT base's own IR projection, which is the whole reason the dispatch has no such parameter.
if args.across_bundle:
# The three things a multi-base pass cannot invent. ``--mandate`` because the commission IS
# the partition key (without ``Approach.bundle_id`` there is nothing to route on), and the
# outbox pair because N runs need N ``run_id``s: the engine refuses to default that key,
# so the caller must supply the stem it mints them from.
required = {
"--mandate": args.mandate,
"--run-id": args.run_id,
"--outbox-dir": args.outbox_dir,
}
missing = [name for name, value in required.items() if not value]
if missing:
print(
f"run refused: --across-bundle requires {', '.join(missing)} (the commission is "
"what partitions the pass by base, and each base writes its own artefact set "
"under <run-id>-<bundle_id> — a key this repo requires a caller to supply)",
file=sys.stderr,
)
return 1
# Four single-base modes, each refused BY NAME rather than by falling through. Every one
# of them resolves something from THE base — one directory, one cut, one exploration, one
# derived schedule — and silently picking which of N that means is the guessed-shape class
# this repo refuses outright.
conflicting = {
"--bundle-dir": args.bundle_dir,
"--explore": args.explore,
"--prepass-payload": args.prepass_payload,
"--proposals-from-mandate": args.proposals_from_mandate,
}
clash = [name for name, value in conflicting.items() if value]
if clash:
print(
f"run refused: --across-bundle cannot be combined with {', '.join(clash)} (each "
"of those resolves ONE knowledge base — a directory, a declared cut, an "
"exploration or a derived schedule — and this mode configures several; which one "
"was meant is not something this layer may decide)",
file=sys.stderr,
)
return 1
# Single-project mode requires PROJECT_ID + --docs-dir (compensating for the relaxed argparse
# required/positional so the legacy contract keeps failing loudly via the refusal surface).
# HOISTED above the scripted door (below) so an incomplete argv is refused BEFORE the honesty
# banner could claim a scripted run happened; the refusal ORDER within single-project mode
# (required args -> semantic-retrieval -> scripted) is unchanged.
if not args.portfolio and (
args.project_id is None or (args.docs_dir is None and args.bundle_dir is None)
#
# ``not args.across_bundle`` is a MODE test, not a relaxation: the multi-base pass takes no
# PROJECT_ID and no single ``--bundle-dir``, and both of those are refused above by name.
if (
not args.portfolio
and not args.across_bundle
and (args.project_id is None or (args.docs_dir is None and args.bundle_dir is None))
):
print(
"run refused: single-project mode requires PROJECT_ID and either --docs-dir or "
@ -3892,6 +4072,158 @@ def main(argv: list[str] | None = None) -> int:
print(settle(coverage))
return 0
# P17b — the multi-base dispatch. Placed BELOW the announcement (the commission is declared
# before the work it commissions) and ABOVE the portfolio dispatch, because it is a MODE
# rather than a modifier: it runs the pass and returns. The dry-run arm lives INSIDE this
# block rather than in the generic ``--live-dry-run`` branch further down, which addresses
# ``args.project_id``/``args.bundle_dir`` — neither of which this argv has — and would
# therefore drop the whole pass in silence (the F4 class).
if args.across_bundle:
assert mandate is not None # narrowed by the required-flags refusal above
assert args.run_id is not None and args.outbox_dir is not None # same refusal
bases = list(args.across_bundle)
try:
# Resolved and ROUTED on the free trip too: a commission that cannot be executed as
# written must be refused while it is still free (the økt-57 hoist), and a drill that
# tolerated a routing error the paid pass refuses would be a rehearsal of a different
# run.
resolved = resolve_bundle_routing(bases)
route_by_bundle(mandate, tuple(bundle_id for bundle_id, _, _ in resolved))
except (MandateRoutingError, okf.BundleIdMismatch, FileNotFoundError, ValueError) as exc:
print(f"run refused: {exc}", file=sys.stderr)
return 1
if args.live_dry_run:
for bundle_id, bundle_dir, project_id in resolved:
try:
report = asyncio.run(
run_project(
project_id,
args.profile,
docs_dir=bundle_dir,
bundle_dir=bundle_dir,
verdict_dir=args.verdict_dir,
dimension=(
load_dimension(args.dimension_config)
if args.dimension_config
else None
),
max_rounds=args.max_rounds,
max_tokens=args.max_tokens,
require_cost_baseline=args.require_cost_baseline,
mcp_servers=mcp_servers,
live_dry_run=True,
)
)
except (ValueError, FileNotFoundError, ValidationError) as exc:
print(f"live-dry-run refused: {bundle_id}: {exc}", file=sys.stderr)
return 1
assert isinstance(report, DryRunReport)
print(
f"{bundle_id} ({project_id}): LIVE-DRY-RUN OK (profile={report.profile}, "
f"models={report.resolved_models}, max_rounds={report.max_rounds}, "
f"max_tokens={report.max_tokens}, top_k={report.top_k}) — "
"ingen modellkall gjort (stoppet før første debate.run)"
)
# Every notice the single-base drill prints, per base: a pass whose SECOND base
# cannot be anchored is exactly as unanchored as one whose first cannot, and a
# drill that said it once would leave the operator guessing which base it meant.
for notice in (
cost_baseline_notice(report.cost_baseline_anchored),
grounding_offer_notice(report.grounding_offer),
skipped_links_notice(report.skipped_links),
bundle_id_notice(report.bundle_id_source),
):
if notice is not None:
print(notice)
return 0
outbox_dir = args.outbox_dir
stem = args.run_id
def outbox_for(bundle_id: str) -> tuple[str, str]:
"""The OPERATOR-CHOSEN minting rule (14.09): ``<run-id>-<bundle_id>``, one stem per
base. Written here, at the call site that made the decision, rather than inside the
dispatch which is precisely why the engine takes a callback and not a directory."""
return outbox_dir, f"{stem}-{bundle_id}"
#: Bound by the dispatch when it RETURNS; still ``None`` when a base raised. The summary
#: is written from a ``finally`` either way (``write_parse_failures``' precedent), because
#: the pass that most needs a record of what it spent is the one a cap or a provider cut
#: short — and the engine's documented limit is that a base which RAISES propagates.
multi: MultiBaseResult | None = None
try:
multi = asyncio.run(
run_mandate_across_bundles(
mandate,
tuple(bases),
args.profile,
verdict_dir=args.verdict_dir,
dimension=(
load_dimension(args.dimension_config) if args.dimension_config else None
),
client_factory=scripted_client_factory,
max_rounds=args.max_rounds,
max_tokens=args.max_tokens,
verdict_input=_verdict_input_from_args(args),
proposal_reviewer=(
terminal_proposal_reviewer() if args.proposal_review else None
),
outbox_for=outbox_for,
)
)
except ChatClientException as exc:
print(f"run stopped: {exc}", file=sys.stderr)
return 1
except ProposalReviewInputError as exc:
print(f"run stopped: {exc}", file=sys.stderr)
return 1
except (
MandateRoutingError,
okf.BundleIdMismatch,
FileNotFoundError,
ValidationError,
ValueError,
BudgetExceeded,
) as exc:
# ``BudgetExceeded`` is in the tuple for the single-project path's measured reason: it
# is a ``RuntimeError``, and the FIRST approach to hit the cap re-raises by design
# (``_evaluate_mandate`` only swallows it mid-list). Over several bases that is not an
# edge case — round 3 measured ``stop_reason: rounds`` in 5 of 5 runs — so without this
# arm the ordinary outcome of a multi-base pass is a traceback.
print(f"run refused: {exc}", file=sys.stderr)
return 1
finally:
_write_multibase_summary(
outbox_dir,
args.run_id,
resolved=resolved,
mint=outbox_for,
multi=multi,
)
for bundle_run in multi.runs:
print(f"--- {bundle_run.bundle_id} ({bundle_run.project_id}) ---")
print(
f"{bundle_run.project_id}: {type(bundle_run.result.outcome).__name__} "
f"({verdict_notice(bundle_run.result)})"
)
# Every per-run notice the single-base path prints, read off THIS base's own stamp —
# a pass that said them once could only be talking about one of N bases, and the
# reader could not tell which.
for notice in (
cost_baseline_notice(bundle_run.result.provenance.cost_baseline_anchored),
bundle_id_notice(bundle_run.result.provenance.bundle_id_source),
skipped_links_notice(bundle_run.result.skipped_links),
unkeyed_verdicts_notice(bundle_run.result.unkeyed_verdicts),
):
if notice is not None:
print(notice)
notice = collision_notice(multi.collisions)
if notice is not None:
print(notice)
return 0
if args.portfolio:
# Portfolio mode (Step 3): dispatch to the EXISTING run_portfolio via the fail-fast loaders
# (run_portfolio itself is unchanged). Loader/ValueError failures surface through the same