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:
parent
9847e014e7
commit
938a1ca30e
23 changed files with 718 additions and 115 deletions
|
|
@ -328,13 +328,47 @@ def test_row6_green_needs_both_the_probes_and_zero_undeclared() -> None:
|
|||
assert gate.score_undeclared(_PROBES, failing, _CLEAN, "s").status == gate.RED
|
||||
|
||||
|
||||
def test_row6_missing_artefacts_are_never_zero() -> None:
|
||||
def test_row6_missing_artefacts_are_never_zero_and_never_green() -> None:
|
||||
"""Probes passing and artefacts absent (clean clone, CI, a base mid-rebuild) is NOT a pass:
|
||||
the row says IKKE MÅLT and fails the exit code."""
|
||||
row = gate.score_undeclared(
|
||||
_PROBES, _all_pass(_PROBES), gate.StressMeasure(missing="ut finnes ikke"), "s"
|
||||
)
|
||||
assert row.k is None
|
||||
assert "ikke målt, artefakter mangler" in row.reason
|
||||
assert "ikke målt" in row.reason
|
||||
assert "– av –" in row.line()
|
||||
assert (row.status, row.failing) == (gate.NOT_MEASURED, True)
|
||||
assert gate.exit_code([row]) == 1
|
||||
|
||||
|
||||
def test_row6_artefacts_older_than_the_rule_are_not_measured() -> None:
|
||||
old = gate.StressMeasure(validated=10, undeclared=10, unaddressed=12, where="x")
|
||||
row = gate.score_undeclared(_PROBES, _all_pass(_PROBES), old, "s")
|
||||
assert (row.k, row.status) == (None, gate.NOT_MEASURED)
|
||||
assert "eldre enn regelen" in row.reason and "approach_id mangler" in row.reason
|
||||
|
||||
|
||||
def test_row7_not_measured_is_not_green_either() -> None:
|
||||
row = gate.score_named(gate.StressMeasure(missing="borte"), "s")
|
||||
assert (row.k, row.status, row.failing) == (None, gate.NOT_MEASURED, False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("missing", ["all", "outcome0", "kept"])
|
||||
def test_rows_1_2_4_with_missing_files_are_red(tmp_path: Path, missing: str) -> None:
|
||||
root = _green_rounds(tmp_path / "r")
|
||||
if missing == "all":
|
||||
root = tmp_path / "absent"
|
||||
elif missing == "outcome0":
|
||||
(root / "0" / "outcome.json").unlink()
|
||||
else:
|
||||
(root / "3" / "report.kept.md").unlink()
|
||||
rows = [
|
||||
gate.score_rounds(root, 3, _AI),
|
||||
gate.score_changes(root, 3, _AI),
|
||||
gate.score_kept(root, 0.8),
|
||||
]
|
||||
assert gate.exit_code(rows) == 1
|
||||
assert gate.GREEN not in {r.status for r in rows} or missing != "all"
|
||||
|
||||
|
||||
def test_row6_measures_the_stress_outboxes_when_they_exist(tmp_path: Path) -> None:
|
||||
|
|
@ -353,6 +387,9 @@ def test_row6_measures_the_stress_outboxes_when_they_exist(tmp_path: Path) -> No
|
|||
assert m.validated == 0
|
||||
pytest.skip(f"stress artefacts not judgeable right now: {m.missing}")
|
||||
assert (m.validated, m.undeclared, m.named, m.commissioned) == (10, 10, 1, 20)
|
||||
assert m.unaddressed > 0 # stress round 6 predates approach-addressed declarations
|
||||
row = gate.score_undeclared(_PROBES, _all_pass(_PROBES), m, "s")
|
||||
assert (row.k, row.status) == (None, gate.NOT_MEASURED)
|
||||
|
||||
|
||||
def test_row7_is_a_diagnosis_and_never_moves_the_exit_code() -> None:
|
||||
|
|
@ -427,5 +464,7 @@ def test_the_command_is_red_today_with_every_row_in_its_output(tmp_path: Path) -
|
|||
assert (rows["types"]["k"], rows["types"]["n"]) == (3, 8)
|
||||
assert rows["kept"]["status"] == gate.RED
|
||||
assert (rows["maf"]["k"], rows["maf"]["n"], rows["maf"]["status"]) == (3, 8, gate.RED)
|
||||
assert rows["undeclared"]["status"] == gate.RED
|
||||
# Probes green since row 6; stress round 6 predates the rule (or is absent) -> never green.
|
||||
assert rows["undeclared"]["status"] == gate.NOT_MEASURED
|
||||
assert rows["undeclared"]["k"] is None
|
||||
assert rows["named"]["failing"] is False
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue