feat(row6): a proposal whose approach declared no requirement is unsupported

Stress round 6 validated three falsification arms, and every validated
approach rested only on run-level declarations nobody can attribute to one
approach. declare_requirement now takes a required approach_id (a mandate
id or own-proposal; an unknown id is refused naming the valid ones), and a
ValidatedProposal whose approach has neither a mandate requirement nor a
declaration under its own id becomes validator.Unsupported - a Rejection
subclass carrying the validator's own ruling, reported as `unsupported` in
coverage, the outcome artefact, the settlement and the judge, and never
counted or summed. The rule is active whenever the debate held the
declaration tool, the micro base included; the road and pre-pass paths are
untouched. Declaration quality is not judged, so the rule can be satisfied
by declaring any document the run read.

The v1 gate's row 6 probes pass; its artefact half reads IKKE MÅLT because
stress round 6 predates approach-addressed declarations, and IKKE MÅLT is
never green - it fails the exit code.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-17 16:40:54 +02:00
commit 938a1ca30e
23 changed files with 718 additions and 115 deletions

View file

@ -42,6 +42,8 @@ _AI_LINE_MIN = 30
GREEN = "GRØNN"
RED = "RØD"
DIAGNOSIS = "DIAGNOSE"
#: A row whose evidence could not be read. Never green: on a failing row it fails the exit code.
NOT_MEASURED = "IKKE MÅLT"
ROUNDS_CONTRACT = """\
Rundekatalogen (--rounds-dir) har fast form:
@ -498,6 +500,8 @@ class StressMeasure:
commissioned: int = 0
where: str = ""
missing: str = ""
#: Declarations with no ``approach_id`` — written before the rule; the row cannot be measured.
unaddressed: int = 0
undeclared_ids: tuple[str, ...] = field(default=())
@ -538,6 +542,7 @@ def measure_stress(
approaches = [a for v in verdicts for a in v.approaches]
validated = [a for a in approaches if a.status == "validated"]
undeclared = [a for a in validated if a.requirement_source != "approach"]
unaddressed = sum(v.unaddressed_declarations for v in verdicts)
commissioned = sum(
len(load_mandate(repo_root / c / "mandate.json").approaches) for c in contexts
)
@ -549,6 +554,7 @@ def measure_stress(
rows=len(approaches),
commissioned=commissioned,
where=str(stress_root),
unaddressed=unaddressed,
undeclared_ids=tuple(a.approach_id for a in undeclared),
)
@ -556,29 +562,54 @@ def measure_stress(
def score_undeclared(
probes: Sequence[str], outcomes: Mapping[str, str], m: StressMeasure, label: str
) -> Row:
"""GREEN only when every probe passes AND the artefacts were measured with k = 0. Evidence that
could not be read is IKKE MÅLT never green, and it fails the exit code like red does."""
failing = [
f"{n.split('::')[-1]}={outcomes.get(n, 'missing')}"
for n in probes
if outcomes.get(n) != "passed"
]
if not probes:
failing.append("ingen probe registrert")
title = "6 validert UTEN erklært krav (tilnærmingens egen)"
exceptions = [f"probe {x}" for x in failing]
probe_state = "prober røde" if failing else "prober grønne"
k: int | None = None
n: int | None = None
diagnostics: tuple[str, ...] = ()
if m.missing:
reason = f"{label}: ikke målt, artefakter mangler ({m.missing})"
k: int | None = None
n: int | None = None
reason = f"{probe_state}; {label}: ikke målt, artefakter mangler ({m.missing})"
elif m.unaddressed:
reason = (
f"{probe_state}; {label}: ikke målt: artefaktene er eldre enn regelen "
f"(approach_id mangler på {m.unaddressed} erklæring(er))"
)
diagnostics = (
f"før regelen: {m.undeclared} av {m.validated} validerte uten tilnærmingens egen "
"erklæring — regelen ville gjort dem unsupported, men modellen fikk aldri spørsmålet",
)
else:
k, n = m.undeclared, m.validated
reason = (
f"{label} ({m.where}): {k} av {n} validerte uten erklæring fra tilnærmingen; "
f"{m.undeclared_anywhere} uten noen erklæring i kjøringen"
f"{probe_state}; {label} ({m.where}): {k} av {n} validerte uten erklæring fra "
f"tilnærmingen; {m.undeclared_anywhere} uten noen erklæring i kjøringen"
)
exceptions += [f"validert uten erklæring: {a}" for a in m.undeclared_ids]
red = bool(failing) or bool(k)
if not probes:
red, exceptions = True, [*exceptions, "ingen probe registrert"]
if failing or k:
status = RED
elif k is None:
status = NOT_MEASURED
else:
status = GREEN
return Row(
"undeclared", title, k, n, RED if red else GREEN, reason, exceptions=tuple(exceptions)
"undeclared",
title,
k,
n,
status,
reason,
exceptions=tuple(exceptions),
diagnostics=diagnostics,
)
@ -596,7 +627,7 @@ def score_named(m: StressMeasure, label: str) -> Row:
title,
None,
None,
DIAGNOSIS,
NOT_MEASURED,
f"{label}: ikke målt, artefakter mangler ({m.missing})",
failing=False,
diagnostics=(NAMED_WARNING,),