feat(prepass): --prepass-seed makes the cut a starting point, and K2 says it costs

Q5 = B, bygget som MAALT OPSJON. --prepass-payload gir DEBATTEN et deklarert
kutt og trekker de fire navigatoerverktoeyene; --prepass-seed gir UTFORSKNINGEN
det samme kuttet som utgangspunkt og BEHOLDER verktoeyene.

Nekten M32/F4 staar ORDRETT. B er et nytt flagg, aldri en loesning av den, og
hjemmelen er konsumkontraktens SS 2.2: en skill maa ikke lese «outside what the
payload delivers or explicitly names as reachable». Andre ledd er hele arm B, og
PrepassDeclaration.rest_reachable er det som gjoer de to lesningene skillbare i
ettertid -- paakrevd uten default av cost_baseline_anchoreds grunn, fordi begge
defaults ville loeyet om hvilken arm som leste kuttet.

Soemmene:
  admit_payload er EN opptaks-gate (form -> montert base -> tom-leveranse-nekt)
    delt av begge doerer; to kopier ville latt en doer slippe inn det den andre
    nekter.
  render_seed deler header, regel->ANTALL-foldingen og DATA-blokkene med
    render_context. Det eneste som skiller dem er avsnittet som sier hva
    leseren kan gjoere videre.
  explore(seed_context=...) legger kuttet i TASK-MELDINGEN, aldri i prompt:
    _finish bygger Mandate.objective av prompt, og en kommisjon med 22 335
    tokens utdrag i objektivet er uleselig for den som skrev den. Tom streng gir
    en byte-identisk task-melding.
  trace_payload(prepass=...) skriver deklarasjonen fra en finally. MAALT baerende
    -- den seedede kjoeringen som doede paa en Azure-400 etterlot likevel kuttet
    deklarert.
  Fem nekter ved navn. --checkpoint-dir baerer en beslutning: en gjenopptatt
    etappe kjoerer i en prosess som aldri saa payloaden og ville overskrevet den
    parkerte etappens deklarasjon med prepass: null.
  --dimension-config er BEVISST ikke nektet (arm A nekter den): maalt bygger
    utforskningen navigator_tools(bundle_dirs) UTEN dimensjon, saa aa skope
    seedet ville nektet tekst den samme loekka kan aapne et oeyeblikk senere.

MAALT PAA K2 MED LEVENDE MODELL, og maalingen taler MOT aa gjoere B til default:
like-for-like gratis 4 317 -> 227 675 o200k (x 52,7), og betalt er manageren
x 21 paa samme antall prompter. Viktigere enn prisen: den USEEDETE kontrollen
hentet prisskjemaet i fire steg (del-ii-bilag-7-prisskjema/prissammenstilling-
sheet-1.md), mens BEGGE seedede armer lot vaere -- den ene med null verktoeykall
fordi manageren rutet til hypotesisereren i alle tre runder, den andre ved aa
gjette stier ut av kuttets egne konsept-navn og mynte en base-id som ikke finnes.
Erkjennelsen kom (manageren skrev i hver runde at utdragene ikke rakk),
handlingen ikke. Ingen av de 40 svarene brukte ett eneste av kontraktens fem
literaler. NOK 2,78 av taket 5, 0 x 429. Anbefaling skrevet, beslutning ikke
tatt -- den er operatoerens.

Load-bearing maalt: 26 armer, 16 mutasjoner alle roede mot HELE suiten, groenn
kontroll 1493 passed / 5 skipped (fra 1467/5; +26 node-ider, 0 fjernet), golden
demo-transcript.stdout byte-uendret (shasum -a 1 av innholdet =
ea8c534773acdbe41ae68f2c55724d69aaf8be4f).

To armer var GROENNE AV FEIL GRUNN og ble rettet, ikke droppet: tool_calls alene
kan ikke skille «et verktoey ble kalt» fra «basen var aapen», fordi recorderen
appender FOER call_next; og id-enighets-armen maalte den stale digesten i stedet
for id-gaten. Sonden var dessuten feil foer koden var det -- foerste
diskriminator var norsk, og verktoeysvar serialiseres med \uXXXX-escapes.

Avvik, uttalt: implementasjonen ble skrevet FOER testfila. Roedmaalingen er gjort
etterpaa ved aa reversere src/ til HEAD (16 av 24 armer roede), deretter
restaurert med shasum-verifikasjon. Beviset er ekte, rekkefoelgen var ikke.

Rapportert, ikke fikset: ChatClientException (Azure 400, «No tool call found for
function call output») etter tre quick_validate-nekter paa rad -- den ligger
utenfor main()s nekt-tuppel og forlater CLI-en som traceback.

Azure-konfigurasjonen er uendret; endepunktet utledes inline fra az og er aldri
lagret i fil. Ruff + mypy rene.

Maaling: docs/2026-09-07-prepass-mater-q5b-k2.md
Ordre: 20260907T234344Z-9062321009-from-.claude

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-08 04:02:09 +02:00
commit 76b939b3b8
9 changed files with 1474 additions and 42 deletions

View file

@ -347,6 +347,52 @@ def _in_dimension(path: Path, dimension: str) -> bool:
)
# --- The one admission gate, shared by every door that consumes a payload --------------------
def admit_payload(
payload: PrepassPayload,
*,
bundle_dir: str,
resolved_id: okf.ResolvedBundleId,
dimension: str | None = None,
) -> None:
"""Everything that must hold before a payload may shape a run. Raises, or returns nothing.
ONE copy, because there are now TWO doors onto this file the debate's ``--prepass-payload``
(the cut REPLACES the pointer and the tools are withdrawn) and the exploration's
``--prepass-seed`` (the cut is the STARTING POINT and the tools stay). The two arms differ in
what they do with an admitted payload and in nothing at all about what makes one admissible,
and two copies of an admission rule is the ko-(p) drift that would let one door accept what
the other refuses.
The three steps, in this order and for this reason: the shape gate reads no disk and so is
free, the bundle check is the expensive one, and the empty-delivery refusal comes last because
a payload that does not hold has not earned an interpretation of its own emptiness.
**``delivered == 0`` is refused on BOTH arms**, and on the seeding arm that is a decision
rather than an inheritance. Measured, it is reachable only when every concept failed to match
lexically (the producer REFUSES the other empty case, where concepts matched and the budget
admitted none), so it is evidence of ABSENCE for this question at this ref. On the seeding arm
a caller might argue the tools are still there and the run could proceed but it would then
proceed as a PLAIN exploration while the operator had asked for a seeded one, which is the
silently downgraded order ``load_mandate`` fail-fasts against.
"""
check_payload_shape(payload)
verify_against_bundle(
payload, bundle_dir=bundle_dir, resolved_id=resolved_id, dimension=dimension
)
if not payload.excerpts:
# Saying it beats two silent alternatives: an empty prompt, or falling through to
# ``run_project``'s citation guard, whose message names ``docs_dir`` — ``None`` on this
# path. SS 7.3's own posture: the skill stops and says so.
raise PrepassRefused(
f"the pre-pass delivered 0 of {payload.denominators.considered} concepts for the "
f"question {payload.question!r} at ref {payload.bundle.ref}; an empty cut is evidence "
"that this knowledge base does not answer that question, not something to run over"
)
# --- Rendering the cut for the prompt --------------------------------------------------------
@ -382,24 +428,86 @@ def render_context(payload: PrepassPayload) -> str:
GATE is ``verify_against_bundle``, which makes the text re-derivable from the mounted base, so
a payload cannot deliver bytes the base does not hold.
"""
return "\n".join(
_declaration_lines(payload)
+ [
"",
"Each excerpt below matched the question LEXICALLY. That is not the same as answering "
"it: a base that holds no answer still returns its closest matches. If the delivered "
"text does not support a claim, say so with [sourced-not-sufficient] rather than "
"filling the gap. adjudication and trust_tier are the producer's declarations about "
"each document, carried here unchanged.",
]
+ _data_blocks(payload)
)
def render_seed(payload: PrepassPayload) -> str:
"""What the EXPLORATION is handed IN ADDITION to its prompt, keeping its navigation tools.
The other arm of one decision, and the difference is a single fact stated in both directions:
:func:`render_context` says "you have no tools to read further, what is below is all of it",
which is true there and would be a LIE here. Contract SS 2.2 forbids reading "outside what the
payload delivers **or explicitly names as reachable**" — the second clause is what makes this
arm conformant, and a rendering that did not say the rest was reachable would leave a model
obeying the first clause while holding the tools for the second.
**Not a second copy of the rendering rule.** The declaration header, the rule -> COUNT folding
and the delimited DATA blocks are the SAME functions the other arm uses; what differs is the
one paragraph that tells the reader what it may do next. Two full copies would drift, and a
drifted pair would state two different cuts for one run (ko-(p)).
``[unread]`` is used deliberately, and it is one of contract SS 4.1's five required literals:
a withheld concept in this arm is not absent and not unavailable, it is simply not yet read
and saying so is what turns the withheld list from a boundary into a next step.
"""
return "\n".join(
_declaration_lines(payload, rest_reachable=True)
+ [
"",
"Each excerpt below matched the question LEXICALLY. That is not the same as answering "
"it: a base that holds no answer still returns its closest matches. The withheld "
"concepts are [unread], not absent — if the delivered text does not support a claim, "
"OPEN THE BASE with your navigation tools rather than filling the gap, and reserve "
"[sourced-not-sufficient] for a claim the base itself could not support. Report what "
"you actually read. adjudication and trust_tier are the producer's declarations about "
"each document, carried here unchanged.",
]
+ _data_blocks(payload)
)
def _declaration_lines(payload: PrepassPayload, *, rest_reachable: bool = False) -> list[str]:
"""The header both renderings open with: the base, what the cut may be used for, the counts.
ONE copy, because these lines ARE the declaration (SS 2.3) and two of them would be two
answers to "what was this run's cut". Only the second line differs between the arms, and it
differs on exactly the fact ``PrepassDeclaration.rest_reachable`` carries.
"""
counts = payload.denominators
rules = ", ".join(f"{rule} ({count})" for rule, count in declaration_of(payload).withheld_rules)
lines = [
rules = ", ".join(f"{rule} ({count})" for rule, count in withheld_rule_counts(payload))
stance = (
"You are reading a DECLARED CUT of that base as your STARTING POINT, not as a replacement "
"for it. The rest of the base stays reachable with your navigation tools, and you are "
"expected to use them when the cut does not carry what you need."
if rest_reachable
else "You are reading a DECLARED CUT of that base, not the base itself, and you have no "
"tools to read further. What is below is all of it."
)
return [
f"Knowledge base: {payload.bundle.bundle_id} (ref {payload.bundle.ref}).",
"",
"You are reading a DECLARED CUT of that base, not the base itself, and you have no tools "
"to read further. What is below is all of it.",
stance,
f"The cut was computed for this question: {payload.question}",
f"Concepts considered: {counts.considered}. Withheld: {counts.withheld}. "
f"Delivered below: {counts.delivered}.",
f"Withheld by rule: {rules}." if rules else "Withheld by rule: none.",
"",
"Each excerpt below matched the question LEXICALLY. That is not the same as answering it: "
"a base that holds no answer still returns its closest matches. If the delivered text "
"does not support a claim, say so with [sourced-not-sufficient] rather than filling the "
"gap. adjudication and trust_tier are the producer's declarations about each document, "
"carried here unchanged.",
]
def _data_blocks(payload: PrepassPayload) -> list[str]:
"""The delimited DATA blocks, one per delivered excerpt (SS 9.3), shared by both arms."""
lines: list[str] = []
for excerpt in payload.excerpts:
lines += [
"",
@ -408,7 +516,7 @@ def render_context(payload: PrepassPayload) -> str:
excerpt.text,
f"--- END DATA {excerpt.concept_id} ---",
]
return "\n".join(lines)
return lines
# --- The declaration -------------------------------------------------------------------------
@ -421,6 +529,15 @@ class PrepassDeclaration:
It reports the payload's OWN denominators verbatim, never a recount off the navigated bundle:
the pre-pass may legitimately have considered a different set (it counts the verdict layer,
``Bundle.context_files`` does not), and two numbers for one fact is ko-(p).
``rest_reachable`` says which of the two arms consumed the cut, and it is REQUIRED WITHOUT A
DEFAULT for ``ProvenanceStamp.cost_baseline_anchored``'s reason: **both defaults would lie.**
``False`` would let a run that kept its navigation tools publish a declaration claiming the cut
was all it could read; ``True`` would let the arm that WITHDREW them claim the base stayed
open. It is the contract's own distinction -- SS 2.2 forbids reading "outside what the payload
delivers **or explicitly names as reachable**", so a conformant consumer may keep the base
reachable, and the difference between the two readings is exactly what a reader of this
declaration needs to know.
"""
bundle_id: str
@ -430,19 +547,34 @@ class PrepassDeclaration:
withheld: int
delivered: int
withheld_rules: tuple[tuple[str, int], ...]
rest_reachable: bool
def declaration_of(payload: PrepassPayload) -> PrepassDeclaration:
"""The declaration a verified payload supports.
def withheld_rule_counts(payload: PrepassPayload) -> tuple[tuple[str, int], ...]:
"""rule -> COUNT, sorted. The ONE folding of the withheld list in this repository.
``withheld_rules`` is rule -> COUNT, sorted. The concept ids are deliberately NOT carried:
measured on a 629-concept corpus the withheld list alone is 34 451 o200k tokens, and a rule
name is the fact a reader can act on while a list of ids they cannot open is cost without
information. The full list stays in the payload, one artefact away.
The concept ids are deliberately NOT carried: measured on a 629-concept corpus the withheld
list alone is 34 451 o200k tokens, and a rule name is the fact a reader can act on while a
list of ids they cannot open is cost without information. The full list stays in the payload,
one artefact away.
It is a function of its own rather than a step inside ``declaration_of`` because THREE
surfaces need it -- the declaration and both renderings -- and a second copy of "how the
withheld list folds" would be free to disagree about the run it describes (ko-(p)).
"""
counts: dict[str, int] = {}
for entry in payload.withheld:
counts[entry.rule] = counts.get(entry.rule, 0) + 1
return tuple(sorted(counts.items()))
def declaration_of(payload: PrepassPayload, *, rest_reachable: bool) -> PrepassDeclaration:
"""The declaration a verified payload supports, for the arm that consumed it.
``rest_reachable`` is a REQUIRED keyword: see :class:`PrepassDeclaration`. The payload cannot
supply it -- a cut does not know what its consumer did with the navigation tools -- so it is
the caller's to state, and every caller states it.
"""
return PrepassDeclaration(
bundle_id=payload.bundle.bundle_id,
ref=payload.bundle.ref,
@ -450,7 +582,8 @@ def declaration_of(payload: PrepassPayload) -> PrepassDeclaration:
considered=payload.denominators.considered,
withheld=payload.denominators.withheld,
delivered=payload.denominators.delivered,
withheld_rules=tuple(sorted(counts.items())),
withheld_rules=withheld_rule_counts(payload),
rest_reachable=rest_reachable,
)
@ -466,4 +599,8 @@ def declaration_payload(declaration: PrepassDeclaration) -> Mapping[str, object]
"withheld_rules": [
{"rule": rule, "count": count} for rule, count in declaration.withheld_rules
],
# Which arm read the cut. An artefact that reported the denominators without saying
# whether the consumer could still open the base would leave a reader unable to tell a
# bounded run from a seeded one -- the same undeclared claim, one level up.
"rest_reachable": declaration.rest_reachable,
}