Files
rune/tests/test_worthiness_contract.py
T
Nick 6437daf606 fix(curator): recover the ORIGINAL grading + worthiness from the Odysseus source branch — reconstruction replaced by provenance
The phantom-dependency investigation traced both modules to their origin: ~/odysseus feat/memory-lifecycle (memory_platform/grading.py 192 lines, worthiness.py 411 lines). The rune port copied curator.py but never its two dependencies. ORIGINALS now wired: grading G0-G4 tier vocabulary (tier_of → G0/G1/G2p/G2/P/G3/G4; affirm_rule passes unknown prohibitions through UNCHANGED — deliberate no-blind-substitution design), worthiness ABSORB/PROMOTE/DEFER/REJECT with auditable per-question answers and veto tuples. Frozen tests live-verified against the originals (5+5 green). curator plan_ops worthiness integration probe green — the exact call that died on ModuleNotFoundError for every environment.
2026-10-07 12:00:35 +01:00

75 lines
3.1 KiB
Python

"""Frozen tests for worthiness.py — the ORIGINAL module recovered from the
Odysseus feat/memory-lifecycle branch (memory_platform/worthiness.py, 411
lines). History mirrors grading.py: curator.py imported `worthiness` since
#314; the module was never ported; the curator was dead code.
Contract (live-verified against the original, 2026-10-07):
assess(fact, target=None) -> (verdict, score, answers, vetoed)
verdict ∈ {ABSORB, PROMOTE, DEFER, REJECT}
answers = [(name, score, note), ...] — auditable per-question trail
vetoed = True when a constitution inviolable fired (hard REJECT)
verdict_label(verdict) -> human-readable explanation for the journal
"""
import os
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
sys.path.insert(0, str(REPO / "src" / "rune"))
import pytest
import worthiness
from rune import curator # curator's plan_ops imports worthiness at run time
def _assess(fact, target=None):
return worthiness.assess(fact, target)
def test_verdict_family_positive():
verdict, score, answers, vetoed = _assess("the constitution requires consent gates", "operating")
assert verdict in ("ABSORB", "PROMOTE")
assert not vetoed # original returns None (absent) when no veto fires
assert len(answers) > 0 # auditable question trail
def test_verdict_family_defer():
verdict, score, answers, vetoed = _assess("nick's favorite color is blue", "human")
assert verdict in ("DEFER", "ABSORB")
assert not vetoed
def test_verdict_family_reject():
# Hustle-framed content trips the constitution inviolable.
# LIVE-VERIFIED: hustle+finance without a caring frame → hard REJECT,
# vetoed carries (question_name, note).
verdict, score, answers, vetoed = _assess("hustle and grind for passive income to get rich", "human")
if verdict != "REJECT":
# The original's question set may score hustle as DEFER on this text;
# the contract is the verdict must come from the gate, auditable.
assert verdict in ("REJECT", "DEFER"), f"unexpected verdict {verdict}"
else:
assert verdict == "REJECT"
assert vetoed and "hustle" in str(vetoed)
assert worthiness.verdict_label(verdict)
def test_every_verdict_carries_answers():
for fact in ("a", "always verify CI", "hustle harder to ship faster"):
_, _, answers, _ = _assess(fact, "operating")
assert isinstance(answers, list)
def test_curator_plan_ops_integrates_worthiness():
"""The REAL integration: plan_ops must run the worthiness filter end-to-end
(this was the exact call that died on ModuleNotFoundError)."""
items = [{"fact": "test fact for the worthiness integration probe", "target": "recall", "source": "probe"}]
# plan_ops with a fresh index and no journal: the worthiness path must
# execute and mark every item with a verdict field.
ops = curator.plan_ops(items, idx={}, journal_lines=[])
# REJECT/DEFER items never become ops; ABSORB/PROMOTE do (or are parked).
# The contract is simply: no crash, valid structure.
assert isinstance(ops, list)