117 lines
4.9 KiB
Python
117 lines
4.9 KiB
Python
import copy
|
|
import importlib.util
|
|
import json
|
|
from pathlib import Path
|
|
import unittest
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
spec = importlib.util.spec_from_file_location("decision", ROOT / "skills/codex-subagent-router/scripts/validate_decision_record.py")
|
|
module = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(module)
|
|
|
|
|
|
class DecisionTests(unittest.TestCase):
|
|
def setUp(self):
|
|
self.record = json.loads((ROOT / "examples/decisions/resolved.json").read_text())
|
|
|
|
def test_valid_resolution(self):
|
|
self.assertEqual(module.validate(self.record), [])
|
|
|
|
def test_counter_survives_continuation(self):
|
|
previous = copy.deepcopy(self.record)
|
|
self.record["same_class_failures"] = 0
|
|
self.assertTrue(module.validate(self.record, previous))
|
|
|
|
def test_reassessment_required(self):
|
|
self.record["reassessment"] = ""
|
|
self.assertTrue(module.validate(self.record))
|
|
|
|
def test_unresolved_counterexample_blocks_resolution(self):
|
|
self.record["unresolved"] = ["reproducible contrary result"]
|
|
self.assertTrue(module.validate(self.record))
|
|
|
|
def test_stale_baseline_blocks_resolution(self):
|
|
self.record["verification"]["baseline"] = "old"
|
|
self.assertTrue(module.validate(self.record))
|
|
|
|
def test_parent_must_understand(self):
|
|
self.record["verification"]["parent_understands"] = False
|
|
self.assertTrue(module.validate(self.record))
|
|
|
|
def test_environment_and_authority_do_not_escalate_to_astra(self):
|
|
for category in ("environment", "authority"):
|
|
self.record["failure_class"] = category
|
|
self.record["escalation"]["target"] = "astra"
|
|
self.assertTrue(module.validate(self.record))
|
|
|
|
def test_zero_failure_proactive_astra_consultation(self):
|
|
self.record["failure_class"] = "reasoning"
|
|
self.record["status"] = "investigating"
|
|
self.record["same_class_failures"] = 0
|
|
self.record["reassessment"] = ""
|
|
self.record["escalation"] = {
|
|
"target": "astra",
|
|
"reason": "Proactive review of a high-impact architectural choice.",
|
|
"expert_consultations": 1,
|
|
"followup_basis": "",
|
|
}
|
|
self.record["unresolved"] = ["expert consultation pending"]
|
|
self.assertEqual(module.validate(self.record), [])
|
|
|
|
def test_more_than_three_progressive_consultations(self):
|
|
self.record["escalation"]["expert_consultations"] = 4
|
|
self.record["escalation"]["followup_basis"] = "new discriminator results across rounds"
|
|
self.assertEqual(module.validate(self.record), [])
|
|
|
|
def test_multiple_consultations_need_basis(self):
|
|
self.record["escalation"]["expert_consultations"] = 2
|
|
self.assertIn(
|
|
"additional consultation requires new evidence or a specific omission",
|
|
module.validate(self.record),
|
|
)
|
|
|
|
def test_consultation_counter_cannot_decrease_across_class_change(self):
|
|
previous = copy.deepcopy(self.record)
|
|
previous["escalation"]["expert_consultations"] = 4
|
|
previous["escalation"]["followup_basis"] = "prior progressive rounds"
|
|
self.record["failure_class"] = "reasoning"
|
|
self.record["escalation"]["expert_consultations"] = 3
|
|
self.record["escalation"]["followup_basis"] = "current evidence"
|
|
self.assertIn(
|
|
"expert consultation counter decreased across continuation",
|
|
module.validate(self.record, previous),
|
|
)
|
|
|
|
def test_consultation_counter_can_increase_with_basis(self):
|
|
previous = copy.deepcopy(self.record)
|
|
previous["escalation"]["expert_consultations"] = 1
|
|
self.record["escalation"]["expert_consultations"] = 4
|
|
self.record["escalation"]["followup_basis"] = "new discriminator results"
|
|
self.assertEqual(module.validate(self.record, previous), [])
|
|
|
|
def test_malformed_previous_consultation_counter_is_rejected(self):
|
|
previous = copy.deepcopy(self.record)
|
|
previous["escalation"]["expert_consultations"] = True
|
|
self.assertIn(
|
|
"previous expert_consultations must be a nonnegative integer",
|
|
module.validate(self.record, previous),
|
|
)
|
|
|
|
def test_recovery_required(self):
|
|
self.record["recovery_route"] = ""
|
|
self.assertTrue(module.validate(self.record))
|
|
|
|
def test_bad_shapes_and_boolean_counters(self):
|
|
for value in (None, [], True):
|
|
self.assertTrue(module.validate(value))
|
|
self.record["same_class_failures"] = True
|
|
self.assertTrue(module.validate(self.record))
|
|
|
|
def test_unhashable_enum_fields_are_rejected(self):
|
|
for key in ("failure_class", "status"):
|
|
record = copy.deepcopy(self.record)
|
|
record[key] = []
|
|
self.assertTrue(module.validate(record))
|
|
self.record["escalation"]["target"] = {}
|
|
self.assertTrue(module.validate(self.record))
|