verdict4 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- quaternary/__init__.py +68 -0
- quaternary/core.py +109 -0
- quaternary/qict.py +766 -0
- quaternary/runner.py +250 -0
- verdict4-0.2.0.dist-info/METADATA +207 -0
- verdict4-0.2.0.dist-info/RECORD +8 -0
- verdict4-0.2.0.dist-info/WHEEL +4 -0
- verdict4-0.2.0.dist-info/licenses/LICENSE +21 -0
quaternary/__init__.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Quaternary Verdict — four-value evaluation for agentic loops."""
|
|
2
|
+
|
|
3
|
+
from .core import (
|
|
4
|
+
CheckResult,
|
|
5
|
+
ComputeNeed,
|
|
6
|
+
EvidenceNeed,
|
|
7
|
+
Needed,
|
|
8
|
+
Verdict,
|
|
9
|
+
iff,
|
|
10
|
+
maybe,
|
|
11
|
+
no,
|
|
12
|
+
yes,
|
|
13
|
+
)
|
|
14
|
+
from .qict import (
|
|
15
|
+
AuditResult,
|
|
16
|
+
CandidateDisposition,
|
|
17
|
+
ControllerAction,
|
|
18
|
+
ControllerEvent,
|
|
19
|
+
ControllerEventKind,
|
|
20
|
+
ControllerState,
|
|
21
|
+
ControllerStatus,
|
|
22
|
+
DependencyRecord,
|
|
23
|
+
EvaluationReceipt,
|
|
24
|
+
EventReceipt,
|
|
25
|
+
Lease,
|
|
26
|
+
LeaseKind,
|
|
27
|
+
QICTConfig,
|
|
28
|
+
QICTController,
|
|
29
|
+
ResolutionOutcome,
|
|
30
|
+
TransitionReceipt,
|
|
31
|
+
audit_trace,
|
|
32
|
+
rank,
|
|
33
|
+
)
|
|
34
|
+
from .runner import LoopOutcome, run
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"AuditResult",
|
|
38
|
+
"CandidateDisposition",
|
|
39
|
+
"CheckResult",
|
|
40
|
+
"ComputeNeed",
|
|
41
|
+
"ControllerAction",
|
|
42
|
+
"ControllerEvent",
|
|
43
|
+
"ControllerEventKind",
|
|
44
|
+
"ControllerState",
|
|
45
|
+
"ControllerStatus",
|
|
46
|
+
"DependencyRecord",
|
|
47
|
+
"EvaluationReceipt",
|
|
48
|
+
"EventReceipt",
|
|
49
|
+
"EvidenceNeed",
|
|
50
|
+
"Lease",
|
|
51
|
+
"LeaseKind",
|
|
52
|
+
"LoopOutcome",
|
|
53
|
+
"Needed",
|
|
54
|
+
"QICTConfig",
|
|
55
|
+
"QICTController",
|
|
56
|
+
"ResolutionOutcome",
|
|
57
|
+
"TransitionReceipt",
|
|
58
|
+
"Verdict",
|
|
59
|
+
"audit_trace",
|
|
60
|
+
"iff",
|
|
61
|
+
"maybe",
|
|
62
|
+
"no",
|
|
63
|
+
"rank",
|
|
64
|
+
"run",
|
|
65
|
+
"yes",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
__version__ = "0.2.0"
|
quaternary/core.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Quaternary Verdict — four-value evaluation for agentic loops.
|
|
3
|
+
|
|
4
|
+
Replace boolean pass/fail with four states:
|
|
5
|
+
NO — fails a named condition
|
|
6
|
+
YES — satisfies conditions
|
|
7
|
+
MAYBE — cannot be evaluated with available evidence
|
|
8
|
+
IFF — correct if and only if a dependency holds
|
|
9
|
+
|
|
10
|
+
https://metacortexdynamics.substack.com/p/your-loop-has-two-states-it-needs
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
from enum import IntEnum
|
|
17
|
+
from typing import Any, TypeAlias
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Verdict(IntEnum):
|
|
21
|
+
"""Four-value evaluation result.
|
|
22
|
+
|
|
23
|
+
Binary loops compress MAYBE and IFF into failure.
|
|
24
|
+
That compression destroys correct work.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
NO = 0
|
|
28
|
+
YES = 1
|
|
29
|
+
MAYBE = 2
|
|
30
|
+
IFF = 3
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True, slots=True)
|
|
34
|
+
class EvidenceNeed:
|
|
35
|
+
"""A canonical request for one finite piece of absent evidence."""
|
|
36
|
+
|
|
37
|
+
evidence: str
|
|
38
|
+
|
|
39
|
+
def __post_init__(self) -> None:
|
|
40
|
+
if not self.evidence:
|
|
41
|
+
raise ValueError("EvidenceNeed requires a non-empty canonical identifier.")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True, slots=True)
|
|
45
|
+
class ComputeNeed:
|
|
46
|
+
"""A canonical request for one further application of the loop body."""
|
|
47
|
+
|
|
48
|
+
step: str
|
|
49
|
+
|
|
50
|
+
def __post_init__(self) -> None:
|
|
51
|
+
if not self.step:
|
|
52
|
+
raise ValueError("ComputeNeed requires a non-empty canonical identifier.")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
Needed: TypeAlias = EvidenceNeed | ComputeNeed
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True, slots=True)
|
|
59
|
+
class CheckResult:
|
|
60
|
+
"""Structured evaluation carrying its own operational consequence.
|
|
61
|
+
|
|
62
|
+
NO → reason: why the output failed (named, not anonymous)
|
|
63
|
+
YES → accepted (reason/needed/dependency unused)
|
|
64
|
+
MAYBE → needed: what evidence is missing
|
|
65
|
+
IFF → dependency: what must hold for the output to hold
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
verdict: Verdict
|
|
69
|
+
reason: str | None = None
|
|
70
|
+
needed: str | Needed | None = None
|
|
71
|
+
dependency: str | None = None
|
|
72
|
+
meta: dict[str, Any] = field(default_factory=dict)
|
|
73
|
+
|
|
74
|
+
def __post_init__(self) -> None:
|
|
75
|
+
if self.verdict == Verdict.NO and self.reason is None:
|
|
76
|
+
raise ValueError(
|
|
77
|
+
"NO verdict requires a reason. Failure must not be anonymous."
|
|
78
|
+
)
|
|
79
|
+
if self.verdict == Verdict.MAYBE and self.needed is None:
|
|
80
|
+
raise ValueError("MAYBE verdict requires needed evidence.")
|
|
81
|
+
if self.verdict == Verdict.IFF and self.dependency is None:
|
|
82
|
+
raise ValueError("IFF verdict requires a named dependency.")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# --- Constructors (convenience) ---
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def no(reason: str, **meta: Any) -> CheckResult:
|
|
89
|
+
"""Reject with named reason."""
|
|
90
|
+
return CheckResult(verdict=Verdict.NO, reason=reason, meta=meta)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def yes(**meta: Any) -> CheckResult:
|
|
94
|
+
"""Accept."""
|
|
95
|
+
return CheckResult(verdict=Verdict.YES, meta=meta)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def maybe(needed: str | Needed, **meta: Any) -> CheckResult:
|
|
99
|
+
"""Hold because typed evidence or computation is needed.
|
|
100
|
+
|
|
101
|
+
Strings remain accepted for compatibility with the v0.1.0 runner. The
|
|
102
|
+
finite-rank controller requires EvidenceNeed or ComputeNeed.
|
|
103
|
+
"""
|
|
104
|
+
return CheckResult(verdict=Verdict.MAYBE, needed=needed, meta=meta)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def iff(dependency: str, **meta: Any) -> CheckResult:
|
|
108
|
+
"""Conditional — correct if dependency holds."""
|
|
109
|
+
return CheckResult(verdict=Verdict.IFF, dependency=dependency, meta=meta)
|