145 lines
5.1 KiB
Python
145 lines
5.1 KiB
Python
|
|
"""
|
||
|
|
Tests for `NominationIntakeFilter` in scripts/calibrate_helpers.py.
|
||
|
|
|
||
|
|
Covers tasks 2.1/2.2 of the calibrate-assessment-inventory change: the
|
||
|
|
deterministic, no-model filter that runs between haiku nomination and the
|
||
|
|
strong-model judge (lifecycle-spec.md §8 step 3, calibrate spec's
|
||
|
|
"Deterministic Nomination Intake Filter" requirement).
|
||
|
|
|
||
|
|
sys.path is patched here (no shared conftest), matching the existing
|
||
|
|
tests/test_calibrate_helpers.py pattern.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
_SCRIPTS_DIR = Path(__file__).parent.parent / "scripts"
|
||
|
|
if str(_SCRIPTS_DIR) not in sys.path:
|
||
|
|
sys.path.insert(0, str(_SCRIPTS_DIR))
|
||
|
|
|
||
|
|
from calibrate_helpers import NominationIntakeFilter # noqa: E402
|
||
|
|
|
||
|
|
|
||
|
|
def _rejected(glob, lifetime, why="why", consider_instead=None):
|
||
|
|
d = {
|
||
|
|
"glob": glob,
|
||
|
|
"lifetime": lifetime,
|
||
|
|
"why": why,
|
||
|
|
"rejected_by": "judge",
|
||
|
|
"judged_on": "2026-07-15",
|
||
|
|
}
|
||
|
|
if consider_instead is not None:
|
||
|
|
d["consider_instead"] = consider_instead
|
||
|
|
return d
|
||
|
|
|
||
|
|
|
||
|
|
def _consult(glob, question="q?"):
|
||
|
|
return {
|
||
|
|
"glob": glob,
|
||
|
|
"question": question,
|
||
|
|
"evidence": "e",
|
||
|
|
"cluster_key": "k",
|
||
|
|
"asked_on": "2026-07-15",
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
class TestExactRepeatDrop:
|
||
|
|
def test_exact_glob_and_lifetime_match_is_dropped_and_logged(self):
|
||
|
|
rejected = [_rejected("docs/research/**", "temporary")]
|
||
|
|
filt = NominationIntakeFilter(rejected=rejected, consults=[])
|
||
|
|
|
||
|
|
nominations = [{"glob": "docs/research/**", "lifetime": "temporary"}]
|
||
|
|
shortlist = ["docs/research/notes.md"]
|
||
|
|
|
||
|
|
result = filt.filter(nominations, shortlist)
|
||
|
|
|
||
|
|
assert result["survivors"] == []
|
||
|
|
assert len(result["dropped"]) == 1
|
||
|
|
assert result["dropped"][0]["glob"] == "docs/research/**"
|
||
|
|
assert result["dropped"][0]["lifetime"] == "temporary"
|
||
|
|
|
||
|
|
def test_same_glob_different_lifetime_is_not_dropped(self):
|
||
|
|
rejected = [_rejected("docs/research/**", "temporary")]
|
||
|
|
filt = NominationIntakeFilter(rejected=rejected, consults=[])
|
||
|
|
|
||
|
|
nominations = [{"glob": "docs/research/**", "lifetime": "keep"}]
|
||
|
|
shortlist = ["docs/research/notes.md"]
|
||
|
|
|
||
|
|
result = filt.filter(nominations, shortlist)
|
||
|
|
|
||
|
|
assert len(result["survivors"]) == 1
|
||
|
|
assert result["dropped"] == []
|
||
|
|
|
||
|
|
|
||
|
|
class TestVariantAnnotation:
|
||
|
|
def test_variant_survives_annotated_with_related_rejection(self):
|
||
|
|
# #52 worked example: docs/research/** -> temporary was rejected;
|
||
|
|
# docs/research/drafts/** -> temporary is a narrower variant whose
|
||
|
|
# match set intersects the rejected glob's match set on the
|
||
|
|
# shortlist -- it survives, annotated with the rejection.
|
||
|
|
rejected = [
|
||
|
|
_rejected(
|
||
|
|
"docs/research/**",
|
||
|
|
"temporary",
|
||
|
|
why="findings docs other artifacts link to",
|
||
|
|
consider_instead="an extract-to-vault rule",
|
||
|
|
)
|
||
|
|
]
|
||
|
|
filt = NominationIntakeFilter(rejected=rejected, consults=[])
|
||
|
|
|
||
|
|
nominations = [{"glob": "docs/research/drafts/**", "lifetime": "temporary"}]
|
||
|
|
shortlist = [
|
||
|
|
"docs/research/drafts/outline.md",
|
||
|
|
"docs/research/other-notes.md",
|
||
|
|
]
|
||
|
|
|
||
|
|
result = filt.filter(nominations, shortlist)
|
||
|
|
|
||
|
|
assert len(result["survivors"]) == 1
|
||
|
|
survivor = result["survivors"][0]
|
||
|
|
assert survivor["glob"] == "docs/research/drafts/**"
|
||
|
|
assert len(survivor["related_rejections"]) == 1
|
||
|
|
related = survivor["related_rejections"][0]
|
||
|
|
assert related["glob"] == "docs/research/**"
|
||
|
|
assert related["why"] == "findings docs other artifacts link to"
|
||
|
|
assert related["consider_instead"] == "an extract-to-vault rule"
|
||
|
|
assert result["dropped"] == []
|
||
|
|
|
||
|
|
def test_no_annotation_when_match_sets_do_not_intersect(self):
|
||
|
|
rejected = [_rejected("docs/research/**", "temporary")]
|
||
|
|
filt = NominationIntakeFilter(rejected=rejected, consults=[])
|
||
|
|
|
||
|
|
nominations = [{"glob": "docs/other-area/**", "lifetime": "temporary"}]
|
||
|
|
# shortlist has no path that both globs could match in common
|
||
|
|
shortlist = ["docs/research/notes.md", "docs/other-area/thing.md"]
|
||
|
|
|
||
|
|
result = filt.filter(nominations, shortlist)
|
||
|
|
|
||
|
|
assert len(result["survivors"]) == 1
|
||
|
|
survivor = result["survivors"][0]
|
||
|
|
assert survivor["related_rejections"] == []
|
||
|
|
|
||
|
|
|
||
|
|
class TestOpenConsultsPassThrough:
|
||
|
|
def test_open_consults_pass_through_even_with_no_nominations(self):
|
||
|
|
consults = [_consult("docs/orchestration-audit/*.md")]
|
||
|
|
filt = NominationIntakeFilter(rejected=[], consults=consults)
|
||
|
|
|
||
|
|
result = filt.filter([], [])
|
||
|
|
|
||
|
|
assert result["consults"] == consults
|
||
|
|
assert result["survivors"] == []
|
||
|
|
assert result["dropped"] == []
|
||
|
|
|
||
|
|
def test_open_consults_pass_through_alongside_survivors(self):
|
||
|
|
consults = [_consult("docs/orchestration-audit/*.md")]
|
||
|
|
filt = NominationIntakeFilter(rejected=[], consults=consults)
|
||
|
|
|
||
|
|
nominations = [{"glob": "a/*.md", "lifetime": "keep"}]
|
||
|
|
result = filt.filter(nominations, ["a/x.md"])
|
||
|
|
|
||
|
|
assert result["consults"] == consults
|
||
|
|
assert len(result["survivors"]) == 1
|