fix(rectification): wire unique-minute confirmation to VedAstro and sealed holdout
Keep confirmation fail-closed until the public AA set is ready, and rewrite Technique Audit from the attached VedAstro status instead of a hardcoded blocked row. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from scripts.rectification.decision_policy import (
|
||||
apply_vedastro_minute_sensitive_to_receipt,
|
||||
build_candidate_decisions,
|
||||
build_decision_receipt,
|
||||
indistinguishable_width_minutes,
|
||||
)
|
||||
from scripts.rectification.sealed_holdout import (
|
||||
PILOT_REPORT_PATH,
|
||||
holdout_passed,
|
||||
load_sealed_minute_holdout,
|
||||
)
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def _request(*, extra_events=()):
|
||||
events = [
|
||||
{
|
||||
"id": "00000000-0000-4000-8000-000000000001",
|
||||
"domain": "career",
|
||||
"summary": "入职",
|
||||
"event_kind": "career_entry",
|
||||
"precision": "day",
|
||||
"date_start": "2016-09-15",
|
||||
"date_end": "2016-09-15",
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-4000-8000-000000000002",
|
||||
"domain": "relationship",
|
||||
"summary": "开始一段关系",
|
||||
"event_kind": "relationship_start",
|
||||
"precision": "day",
|
||||
"date_start": "2018-03-01",
|
||||
"date_end": "2018-03-01",
|
||||
},
|
||||
{
|
||||
"id": "00000000-0000-4000-8000-000000000003",
|
||||
"domain": "education",
|
||||
"summary": "毕业",
|
||||
"event_kind": "education_completion",
|
||||
"precision": "day",
|
||||
"date_start": "2015-06-01",
|
||||
"date_end": "2015-06-01",
|
||||
},
|
||||
*extra_events,
|
||||
]
|
||||
return {"events": events}
|
||||
|
||||
|
||||
def _diagnostics():
|
||||
return {
|
||||
"leave_one_event_out_retention_rate": 1,
|
||||
"leave_one_domain_out_retention_rate": 1,
|
||||
"date_sensitivity_retention_rate": 1,
|
||||
"primary_secondary_margin_percent": 50,
|
||||
}
|
||||
|
||||
|
||||
def _rows():
|
||||
return [
|
||||
{"time": "05:13", "score": 20, "evidence": [], "missing_layers": []},
|
||||
{"time": "05:14", "score": 8, "evidence": [], "missing_layers": []},
|
||||
]
|
||||
|
||||
|
||||
def test_sealed_holdout_contract_matches_v2_pilot_and_stays_closed() -> None:
|
||||
holdout = load_sealed_minute_holdout()
|
||||
report = json.loads(PILOT_REPORT_PATH.read_text(encoding="utf-8"))
|
||||
product = json.loads((ROOT / "references" / "rectification_sealed_holdout.v1.json").read_text(encoding="utf-8"))
|
||||
assert holdout["sealed_benchmark_id"] == report["benchmark_id"] == product["sealed_benchmark_id"]
|
||||
assert holdout["valid_public_aa_cases"] == report["case_gate"]["valid_public_aa_cases"]
|
||||
assert holdout["required_cases"] == report["case_gate"]["minimum_public_aa_cases"]
|
||||
assert holdout["top_1_rate"] == report["metrics"]["top_1_rate"]
|
||||
assert holdout["confirmation_coverage_rate"] == report["metrics"]["confirmation_coverage_rate"]
|
||||
assert holdout["status"] == "not_ready"
|
||||
assert holdout_passed(holdout) is False
|
||||
|
||||
|
||||
def test_vedastro_pass_rewrites_audit_but_holdout_still_blocks(monkeypatch) -> None:
|
||||
extra = [{
|
||||
"id": "00000000-0000-4000-8000-000000000004",
|
||||
"domain": "family",
|
||||
"summary": "家人变化",
|
||||
"event_kind": "family_event",
|
||||
"precision": "day",
|
||||
"date_start": "2020-01-01",
|
||||
"date_end": "2020-01-01",
|
||||
}]
|
||||
decisions = build_candidate_decisions(_rows(), result_id="00000000-0000-4000-8000-000000000099")
|
||||
receipt = build_decision_receipt(_request(extra_events=extra), decisions, {"missing_layers": [], "matrix": {}}, _diagnostics())
|
||||
assert receipt["gates"]["exact_confirmation"]["engine_granted"] is True
|
||||
apply_vedastro_minute_sensitive_to_receipt(receipt, "passed", summary={"discriminated": True})
|
||||
audit = {row["technique"]: row for row in receipt["technique_audit_table"]}
|
||||
assert audit["VedAstro 分钟级校验"]["status"] == "executed"
|
||||
assert "未调用不等于失败" not in audit["VedAstro 分钟级校验"]["note"]
|
||||
assert audit["唯一分钟确认"]["status"] == "blocked"
|
||||
assert receipt["confirmation_allowed"] is False
|
||||
assert receipt["gates"]["exact_confirmation"]["holdout"]["status"] == "not_ready"
|
||||
|
||||
|
||||
def test_confirmation_allowed_only_when_holdout_ready(monkeypatch) -> None:
|
||||
extra = [{
|
||||
"id": "00000000-0000-4000-8000-000000000004",
|
||||
"domain": "family",
|
||||
"summary": "家人变化",
|
||||
"event_kind": "family_event",
|
||||
"precision": "day",
|
||||
"date_start": "2020-01-01",
|
||||
"date_end": "2020-01-01",
|
||||
}]
|
||||
monkeypatch.setattr(
|
||||
"scripts.rectification.decision_policy.load_sealed_minute_holdout",
|
||||
lambda: {
|
||||
"sealed_benchmark_id": "minute_rectification_holdout_v2",
|
||||
"status": "ready",
|
||||
"valid_public_aa_cases": 20,
|
||||
"required_cases": 20,
|
||||
"top_1_rate": 0.7,
|
||||
"confirmation_coverage_rate": 0.2,
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr("scripts.rectification.decision_policy.holdout_passed", lambda holdout=None: True)
|
||||
decisions = build_candidate_decisions(_rows(), result_id="00000000-0000-4000-8000-000000000099")
|
||||
receipt = build_decision_receipt(_request(extra_events=extra), decisions, {"missing_layers": [], "matrix": {}}, _diagnostics())
|
||||
apply_vedastro_minute_sensitive_to_receipt(receipt, "passed", summary={"discriminated": True})
|
||||
assert receipt["confirmation_allowed"] is True
|
||||
assert receipt["confirm_allowed"] is True
|
||||
audit = {row["technique"]: row for row in receipt["technique_audit_table"]}
|
||||
assert audit["唯一分钟确认"]["status"] == "executed"
|
||||
|
||||
|
||||
def test_timeout_status_stays_not_evaluated_not_fail() -> None:
|
||||
decisions = build_candidate_decisions(_rows(), result_id="00000000-0000-4000-8000-000000000099")
|
||||
receipt = build_decision_receipt(_request(), decisions, {"missing_layers": [], "matrix": {}}, _diagnostics())
|
||||
apply_vedastro_minute_sensitive_to_receipt(
|
||||
receipt,
|
||||
"not_evaluated",
|
||||
summary={"reason": "vedastro_minute_snapshot_timeout"},
|
||||
)
|
||||
exact = receipt["gates"]["exact_confirmation"]
|
||||
assert exact["external_validation_status"] == "not_evaluated"
|
||||
assert exact["external_validation_status"] != "failed"
|
||||
assert receipt["confirmation_allowed"] is False
|
||||
note = next(row["note"] for row in receipt["technique_audit_table"] if row["technique"] == "VedAstro 分钟级校验")
|
||||
assert "不等于失败" in note
|
||||
|
||||
|
||||
def test_indistinguishable_width_matches_public_span() -> None:
|
||||
width = indistinguishable_width_minutes([
|
||||
{"time": "04:45", "rank": 1, "tied_minute_count": 25},
|
||||
{"time": "04:46", "rank": 2, "tied_minute_count": 25},
|
||||
{"time": "04:47", "rank": 3, "tied_minute_count": 25},
|
||||
])
|
||||
assert width >= 25
|
||||
@@ -278,6 +278,10 @@ def _scored_result(*, acceptance=True):
|
||||
"acceptance_allowed": acceptance,
|
||||
"confirmation_allowed": False,
|
||||
"gates": {"exact_confirmation": {"external_validation_status": "not_evaluated"}},
|
||||
"technique_audit_table": [
|
||||
{"technique": "VedAstro 分钟级校验", "status": "blocked", "note": "官方分钟级校验尚未评估。"},
|
||||
{"technique": "唯一分钟确认", "status": "blocked", "note": "采用不等于确认唯一分钟。"},
|
||||
],
|
||||
}
|
||||
return {
|
||||
"candidate_decisions": [
|
||||
@@ -309,6 +313,10 @@ def test_v5_score_attaches_minute_sensitive_pass_without_search_events(monkeypat
|
||||
assert exact["external_validation_status"] == "passed"
|
||||
assert exact["vedastro_minute_sensitive"]["discriminated"] is True
|
||||
assert result["confirmation_allowed"] is False
|
||||
audit = {row["technique"]: row for row in result["decision_receipt"]["technique_audit_table"]}
|
||||
assert audit["VedAstro 分钟级校验"]["status"] == "executed"
|
||||
assert "已通过" in audit["VedAstro 分钟级校验"]["note"]
|
||||
assert audit["唯一分钟确认"]["status"] == "blocked"
|
||||
assert range_calls == []
|
||||
serialized = str(result)
|
||||
assert "36.419" not in serialized
|
||||
|
||||
Reference in New Issue
Block a user