dos-kernel 0.22.0__py3-none-win_amd64.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.
- dos/__init__.py +261 -0
- dos/_bin/dos-hook.exe +0 -0
- dos/_filelock.py +255 -0
- dos/_job_policy.py +97 -0
- dos/_tree.py +145 -0
- dos/admission.py +433 -0
- dos/answer_shape.py +299 -0
- dos/arbiter.py +859 -0
- dos/archive_lock.py +266 -0
- dos/arg_provenance.py +814 -0
- dos/attest.py +472 -0
- dos/breaker.py +311 -0
- dos/churn.py +226 -0
- dos/claim_extract.py +229 -0
- dos/claim_ttl.py +150 -0
- dos/cli.py +8721 -0
- dos/commit_audit.py +666 -0
- dos/completion.py +466 -0
- dos/concurrency_class.py +154 -0
- dos/config.py +1380 -0
- dos/config_lint.py +464 -0
- dos/cooldown.py +390 -0
- dos/coverage.py +387 -0
- dos/dangling_intent.py +287 -0
- dos/data_class.py +397 -0
- dos/decisions.py +1274 -0
- dos/decisions_tui.py +251 -0
- dos/dispatch_top.py +740 -0
- dos/dispatch_top_tui.py +116 -0
- dos/drivers/__init__.py +40 -0
- dos/drivers/ci_status.py +630 -0
- dos/drivers/citation_resolve.py +703 -0
- dos/drivers/decision_stop.py +98 -0
- dos/drivers/export_file.py +173 -0
- dos/drivers/export_otlp.py +275 -0
- dos/drivers/export_statsd.py +242 -0
- dos/drivers/hook_dialects.py +391 -0
- dos/drivers/job.py +47 -0
- dos/drivers/llm_judge.py +360 -0
- dos/drivers/memory_recall.py +1231 -0
- dos/drivers/notify_slack.py +373 -0
- dos/drivers/notify_webhook.py +251 -0
- dos/drivers/operator_judge.py +114 -0
- dos/drivers/os_acceptance.py +228 -0
- dos/drivers/paste_log.py +132 -0
- dos/drivers/plan_scope.py +133 -0
- dos/drivers/self_improve.py +375 -0
- dos/drivers/similarity_judge.py +249 -0
- dos/drivers/state_diff.py +274 -0
- dos/drivers/supervisor.py +347 -0
- dos/drivers/watchdog.py +363 -0
- dos/drivers/workshop.py +160 -0
- dos/durable_schema.py +344 -0
- dos/effect_witness.py +393 -0
- dos/efficiency.py +318 -0
- dos/enforce.py +414 -0
- dos/enumerate.py +776 -0
- dos/env_print.py +378 -0
- dos/event_severity.py +258 -0
- dos/evidence.py +692 -0
- dos/exec_capability.py +256 -0
- dos/export_cursor.py +143 -0
- dos/exporter.py +320 -0
- dos/firing_label.py +353 -0
- dos/fleet_roll.py +226 -0
- dos/gate_classify.py +827 -0
- dos/gh4_coverage.py +179 -0
- dos/git_delta.py +122 -0
- dos/guard.py +215 -0
- dos/health.py +552 -0
- dos/help_summary.py +519 -0
- dos/home.py +934 -0
- dos/hook_binary.py +194 -0
- dos/hook_dialect.py +271 -0
- dos/hook_exit.py +191 -0
- dos/hook_install.py +437 -0
- dos/id_alloc.py +304 -0
- dos/improve.py +499 -0
- dos/intent_ledger.py +635 -0
- dos/interpret.py +176 -0
- dos/intervention.py +769 -0
- dos/intervention_eval.py +371 -0
- dos/journal_delta.py +308 -0
- dos/judge_eval.py +328 -0
- dos/judges.py +366 -0
- dos/lane_infer.py +127 -0
- dos/lane_journal.py +1001 -0
- dos/lane_lease.py +952 -0
- dos/lane_overlap.py +228 -0
- dos/lease_health.py +282 -0
- dos/lifecycle.py +211 -0
- dos/liveness.py +352 -0
- dos/lock_modes.py +185 -0
- dos/log_source.py +395 -0
- dos/loop_decide.py +1746 -0
- dos/marker_gate.py +254 -0
- dos/marker_sensor.py +396 -0
- dos/noop_streak.py +280 -0
- dos/notify.py +479 -0
- dos/observe.py +175 -0
- dos/oracle.py +1661 -0
- dos/overlap_eval.py +214 -0
- dos/overlap_policy.py +342 -0
- dos/packet_sidecar.py +267 -0
- dos/phase_shipped.py +1985 -0
- dos/pick_priority.py +225 -0
- dos/pickable.py +369 -0
- dos/picker_oracle.py +1037 -0
- dos/plan_board.py +513 -0
- dos/plan_board_tui.py +113 -0
- dos/plan_source.py +455 -0
- dos/posttool_sensor.py +528 -0
- dos/precursor_gate.py +499 -0
- dos/precursor_gate_eval.py +239 -0
- dos/preflight.py +825 -0
- dos/pretool_sensor.py +490 -0
- dos/proc_delta.py +181 -0
- dos/productivity.py +296 -0
- dos/provider_limit.py +242 -0
- dos/py.typed +4 -0
- dos/reason_morphology.py +299 -0
- dos/reasons.py +449 -0
- dos/reconcile.py +173 -0
- dos/recurring_wedge.py +206 -0
- dos/render.py +393 -0
- dos/result_state.py +468 -0
- dos/resume.py +578 -0
- dos/resume_evidence.py +293 -0
- dos/retention.py +344 -0
- dos/reward.py +372 -0
- dos/rewind.py +587 -0
- dos/rewind_evidence.py +168 -0
- dos/rewind_tokens.py +252 -0
- dos/run_id.py +342 -0
- dos/scope.py +520 -0
- dos/scope_source.py +382 -0
- dos/scout.py +982 -0
- dos/self_modify.py +209 -0
- dos/sibling_scan.py +569 -0
- dos/skills/EXAMPLES.md +584 -0
- dos/skills/dos-class-cycle/SKILL.md +107 -0
- dos/skills/dos-dispatch/SKILL.md +177 -0
- dos/skills/dos-dispatch-loop/SKILL.md +254 -0
- dos/skills/dos-goal-gate/SKILL.md +269 -0
- dos/skills/dos-next-up/SKILL.md +231 -0
- dos/skills/dos-promote/SKILL.md +114 -0
- dos/skills/dos-replan/SKILL.md +159 -0
- dos/skills/dos-replan-loop/SKILL.md +114 -0
- dos/skills/dos-self-improve/SKILL.md +213 -0
- dos/skills/dos-supervise-loop/SKILL.md +180 -0
- dos/skills/dos-unstick/SKILL.md +108 -0
- dos/skills/dos-witness-claim/SKILL.md +251 -0
- dos/stamp.py +1002 -0
- dos/state_health.py +387 -0
- dos/status.py +114 -0
- dos/stop_policy.py +334 -0
- dos/supervise.py +1014 -0
- dos/testwitness.py +392 -0
- dos/timeline.py +1027 -0
- dos/tokens.py +485 -0
- dos/tool_stream.py +393 -0
- dos/tool_stream_eval.py +226 -0
- dos/trace.py +524 -0
- dos/verdict.py +140 -0
- dos/verdict_cli.py +189 -0
- dos/verdict_journal.py +497 -0
- dos/verdict_rollup.py +217 -0
- dos/verdicts.py +181 -0
- dos/wedge_reason.py +282 -0
- dos_kernel-0.22.0.dist-info/METADATA +859 -0
- dos_kernel-0.22.0.dist-info/RECORD +178 -0
- dos_kernel-0.22.0.dist-info/WHEEL +5 -0
- dos_kernel-0.22.0.dist-info/entry_points.txt +39 -0
- dos_kernel-0.22.0.dist-info/licenses/LICENSE +21 -0
- dos_kernel-0.22.0.dist-info/top_level.txt +2 -0
- dos_mcp/__init__.py +52 -0
- dos_mcp/py.typed +2 -0
- dos_mcp/server.py +779 -0
dos/testwitness.py
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
"""TWV — the test-witness verdict: does this new test actually WITNESS this change? (docs/288)
|
|
2
|
+
|
|
3
|
+
"I added a test for this" is one of the highest-frequency work claims an agent
|
|
4
|
+
makes, and today every kernel consumer takes it at face value the moment the
|
|
5
|
+
suite is green: `verify()` witnesses that a *phase shipped* (it never looks
|
|
6
|
+
inside a test), `improve()` requires *suite green on the candidate tree* (a new
|
|
7
|
+
test that passes on BOTH trees keeps the suite green by construction), and the
|
|
8
|
+
diff-presence rung ("the commit contains a test file") is W2 presence, never W3
|
|
9
|
+
goal (docs/204). So the canonical inflation goes uncaught: an agent fixes (or
|
|
10
|
+
half-fixes, or doesn't fix) a bug, writes a test that asserts something *already
|
|
11
|
+
true on the baseline*, and every downstream consumer — the keep-gate, the reward
|
|
12
|
+
set, the reviewer reading "tests added ✓" — banks a unit of assurance that does
|
|
13
|
+
not exist.
|
|
14
|
+
|
|
15
|
+
The deterministic kill for exactly this is Cognition's FrontierCode
|
|
16
|
+
**reverse-classical testing** rule: run the new test against the tree WITHOUT
|
|
17
|
+
the change; it must fail. A test that passes on both trees witnesses nothing.
|
|
18
|
+
That check is two env-authored bits joined — which is to say, it is a DOS
|
|
19
|
+
verdict, and this module is it:
|
|
20
|
+
|
|
21
|
+
testwitness.classify(TestRunEvidence) -> TestWitnessVerdict
|
|
22
|
+
DISCRIMINATES / VACUOUS / UNSATISFIED / REGRESSIVE / ABSTAIN
|
|
23
|
+
|
|
24
|
+
**Byte-clean by construction (the docs/138 invariant).** The test's *content* is
|
|
25
|
+
agent-authored — maximally forgeable; the kernel never reads it. What the
|
|
26
|
+
verdict joins is two bits the agent authors zero bytes of: the runner's outcome
|
|
27
|
+
on the baseline tree and the runner's outcome on the candidate tree. Two
|
|
28
|
+
independently-authored facts (two different trees, one env-controlled runner),
|
|
29
|
+
joined into a label neither fact carries alone — the docs/179 fold-mints-data
|
|
30
|
+
rule, satisfied the same way `liveness` joins git-delta to journal-delta. An
|
|
31
|
+
agent cannot write its way from VACUOUS to DISCRIMINATES: the only path is a
|
|
32
|
+
test that actually fails on the tree it didn't get to touch. And the `rung`
|
|
33
|
+
field makes the floor structural rather than procedural: outcomes that exist
|
|
34
|
+
only as the agent's own narration arrive on `AGENT_AUTHORED` and the verdict
|
|
35
|
+
ABSTAINS — `--baseline fail --candidate pass --forgeable` cannot DISCRIMINATE,
|
|
36
|
+
exactly as `--witness confirm --forgeable` cannot ACCEPT in `reward`. Same
|
|
37
|
+
floor, same shape, same $0 demo.
|
|
38
|
+
|
|
39
|
+
THE HONEST RESIDUE — what DISCRIMINATES does NOT prove (docs/288 §6)
|
|
40
|
+
====================================================================
|
|
41
|
+
|
|
42
|
+
* **Tree-discrimination ≠ behavior-assertion.** An adversarial test can
|
|
43
|
+
discriminate trivially (`assert os.path.exists("the_new_file.py")` is
|
|
44
|
+
red→green across any change that adds a file). DISCRIMINATES is sound
|
|
45
|
+
against the *lazy* inflation (the vacuous test — the overwhelmingly common
|
|
46
|
+
case) and against pass/pass forgery; it is not sound against an adversarial
|
|
47
|
+
test author. "Does this test assert the intended *behavior*?" is semantic —
|
|
48
|
+
that residue goes UP the ladder to the JUDGE rung (`dos.judges`, advisory,
|
|
49
|
+
fail-to-abstain), exactly where FrontierCode puts its own LLM rubric. The
|
|
50
|
+
`assert_level` bit narrows the residue (a structural discrimination is
|
|
51
|
+
flagged typed, not buried in prose) but does not close it.
|
|
52
|
+
* **One test, one change — not a suite verdict.** TWV adjudicates a (test,
|
|
53
|
+
change) pair. "The suite is green" stays `improve()`'s floor; TWV is the
|
|
54
|
+
*per-new-test* rung a keep-gate may additionally AND in.
|
|
55
|
+
* **The gather is the caller's.** Running the same test on two trees (a
|
|
56
|
+
worktree checkout without the candidate diff, then with it) is I/O — it
|
|
57
|
+
lives at the boundary (a CI step, the `dos-self-improve` engine's worktree
|
|
58
|
+
flow, a host driver), never inside `classify`. The kernel adjudicates
|
|
59
|
+
outcomes; it does not run pytest.
|
|
60
|
+
|
|
61
|
+
PURE — no I/O, no clock, and deliberately **no policy object**: the rule is
|
|
62
|
+
structural (there is no threshold a host could legitimately tune). It sits in
|
|
63
|
+
the kernel layer beside `reward` / `efficiency` / `liveness` and names no host,
|
|
64
|
+
no runner, no test framework. ADVISORY (docs/99): it reports; a consumer
|
|
65
|
+
(`improve()`'s host engine, a reward-set builder, a CI gate) decides.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
from __future__ import annotations
|
|
69
|
+
|
|
70
|
+
import enum
|
|
71
|
+
from dataclasses import dataclass
|
|
72
|
+
|
|
73
|
+
# The accountability spectrum (docs/117) — who authored the two outcome bits.
|
|
74
|
+
# A kernel sibling import (the CLAUDE.md layer-1 rule): the spectrum has one
|
|
75
|
+
# home and the floor must be the SAME floor `reward`/`evidence` enforce.
|
|
76
|
+
from dos.evidence import Accountability
|
|
77
|
+
|
|
78
|
+
__all__ = [
|
|
79
|
+
"RunOutcome",
|
|
80
|
+
"TestWitness",
|
|
81
|
+
"TestRunEvidence",
|
|
82
|
+
"TestWitnessVerdict",
|
|
83
|
+
"classify",
|
|
84
|
+
"DISCRIMINATES",
|
|
85
|
+
"VACUOUS",
|
|
86
|
+
"UNSATISFIED",
|
|
87
|
+
"REGRESSIVE",
|
|
88
|
+
"ABSTAIN",
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class RunOutcome(str, enum.Enum):
|
|
93
|
+
"""One runner outcome for one test on one tree — a closed, four-valued enum.
|
|
94
|
+
|
|
95
|
+
`str`-valued so it round-trips through a CLI flag / JSON without a lookup
|
|
96
|
+
table (the `Liveness` / `Efficiency` idiom). The FAILED/ERRORED split is
|
|
97
|
+
load-bearing (it feeds the verdict's `assert_level` bit):
|
|
98
|
+
|
|
99
|
+
PASSED — the test ran and its assertions held.
|
|
100
|
+
FAILED — the test RAN and an assertion was false (assert-level red): the
|
|
101
|
+
test executed against the tree's behavior and rejected it.
|
|
102
|
+
ERRORED — the test could not run at all (a collection/import error —
|
|
103
|
+
e.g. it imports a module only the candidate tree has):
|
|
104
|
+
structural red, weaker than assert-level.
|
|
105
|
+
NOT_RUN — no outcome exists for this tree. Half a join is not a join;
|
|
106
|
+
`classify` ABSTAINS rather than guess the missing half.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
PASSED = "PASSED"
|
|
110
|
+
FAILED = "FAILED"
|
|
111
|
+
ERRORED = "ERRORED"
|
|
112
|
+
NOT_RUN = "NOT_RUN"
|
|
113
|
+
|
|
114
|
+
def __str__(self) -> str: # pragma: no cover - trivial
|
|
115
|
+
return self.value
|
|
116
|
+
|
|
117
|
+
@classmethod
|
|
118
|
+
def parse(cls, token: str) -> "RunOutcome":
|
|
119
|
+
"""Parse a CLI-friendly token (`pass`/`fail`/`error`/`not-run`, or the
|
|
120
|
+
enum value itself, any case) into an outcome. Raises ValueError on
|
|
121
|
+
anything else — an outcome the runner never emitted must not be
|
|
122
|
+
invented at the parse boundary."""
|
|
123
|
+
t = (token or "").strip().lower().replace("_", "-")
|
|
124
|
+
aliases = {
|
|
125
|
+
"pass": cls.PASSED, "passed": cls.PASSED,
|
|
126
|
+
"fail": cls.FAILED, "failed": cls.FAILED,
|
|
127
|
+
"error": cls.ERRORED, "errored": cls.ERRORED,
|
|
128
|
+
"not-run": cls.NOT_RUN, "notrun": cls.NOT_RUN,
|
|
129
|
+
}
|
|
130
|
+
if t in aliases:
|
|
131
|
+
return aliases[t]
|
|
132
|
+
raise ValueError(
|
|
133
|
+
f"unknown run outcome {token!r}; expected one of "
|
|
134
|
+
f"pass/fail/error/not-run"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class TestWitness(str, enum.Enum):
|
|
139
|
+
"""The typed test-witness verdict — five states, mutually exclusive.
|
|
140
|
+
|
|
141
|
+
The ladder is documented on `classify`; the one-line meanings:
|
|
142
|
+
|
|
143
|
+
DISCRIMINATES — red→green across the change: the ONLY verdict that
|
|
144
|
+
licenses "this test witnesses this change."
|
|
145
|
+
VACUOUS — passed on BOTH trees: the test would have passed without
|
|
146
|
+
the change; it witnesses nothing. The FrontierCode
|
|
147
|
+
false-positive shape — the load-bearing verdict.
|
|
148
|
+
UNSATISFIED — the change does not satisfy its own test (candidate not
|
|
149
|
+
green): the red half of red→green without the green.
|
|
150
|
+
REGRESSIVE — the change BREAKS a baseline-green test.
|
|
151
|
+
ABSTAIN — forgeable rung or a missing run: never mint a witness
|
|
152
|
+
off a narration or half a join.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
# Not a pytest class, despite the Test* name (dunders are not enum members).
|
|
156
|
+
__test__ = False
|
|
157
|
+
|
|
158
|
+
DISCRIMINATES = "DISCRIMINATES"
|
|
159
|
+
VACUOUS = "VACUOUS"
|
|
160
|
+
UNSATISFIED = "UNSATISFIED"
|
|
161
|
+
REGRESSIVE = "REGRESSIVE"
|
|
162
|
+
ABSTAIN = "ABSTAIN"
|
|
163
|
+
|
|
164
|
+
def __str__(self) -> str: # pragma: no cover - trivial
|
|
165
|
+
return self.value
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# Module-level aliases so a consumer writes `verdict is testwitness.VACUOUS`
|
|
169
|
+
# (the `reward.ACCEPT` idiom).
|
|
170
|
+
DISCRIMINATES = TestWitness.DISCRIMINATES
|
|
171
|
+
VACUOUS = TestWitness.VACUOUS
|
|
172
|
+
UNSATISFIED = TestWitness.UNSATISFIED
|
|
173
|
+
REGRESSIVE = TestWitness.REGRESSIVE
|
|
174
|
+
ABSTAIN = TestWitness.ABSTAIN
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@dataclass(frozen=True)
|
|
178
|
+
class TestRunEvidence:
|
|
179
|
+
"""The facts `classify()` reads — gathered by the CALLER at its boundary.
|
|
180
|
+
|
|
181
|
+
No I/O inside the verdict (the arbiter rule): the caller's boundary (a CI
|
|
182
|
+
step, the self-improve engine's worktree flow, the `dos test-witness`
|
|
183
|
+
flags) ran ONE test on TWO trees and froze the outcomes here.
|
|
184
|
+
|
|
185
|
+
baseline — the runner's outcome for THE TEST on the tree WITHOUT the
|
|
186
|
+
change (the merge-base / HEAD-before checkout).
|
|
187
|
+
candidate — the runner's outcome for THE TEST on the tree WITH the change.
|
|
188
|
+
rung — who authored those two outcome bits (docs/117 spectrum).
|
|
189
|
+
`OS_RECORDED` by default: a runner exit the environment
|
|
190
|
+
recorded. `AGENT_AUTHORED` = the agent *narrated* "it failed
|
|
191
|
+
before and passes now" — forgeable, and the verdict ABSTAINS
|
|
192
|
+
on it (the structural floor, not a procedural convention).
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
__test__ = False # not a pytest class, despite the Test* name
|
|
196
|
+
|
|
197
|
+
baseline: RunOutcome
|
|
198
|
+
candidate: RunOutcome
|
|
199
|
+
rung: Accountability = Accountability.OS_RECORDED
|
|
200
|
+
|
|
201
|
+
def __post_init__(self) -> None:
|
|
202
|
+
if not isinstance(self.baseline, RunOutcome):
|
|
203
|
+
raise ValueError("baseline must be a RunOutcome (use RunOutcome.parse)")
|
|
204
|
+
if not isinstance(self.candidate, RunOutcome):
|
|
205
|
+
raise ValueError("candidate must be a RunOutcome (use RunOutcome.parse)")
|
|
206
|
+
if not isinstance(self.rung, Accountability):
|
|
207
|
+
raise ValueError("rung must be an Accountability")
|
|
208
|
+
|
|
209
|
+
@classmethod
|
|
210
|
+
def of(
|
|
211
|
+
cls,
|
|
212
|
+
baseline: "RunOutcome | str",
|
|
213
|
+
candidate: "RunOutcome | str",
|
|
214
|
+
*,
|
|
215
|
+
forgeable: bool = False,
|
|
216
|
+
) -> "TestRunEvidence":
|
|
217
|
+
"""Build evidence from two outcomes (enum members or CLI tokens).
|
|
218
|
+
`forgeable=True` puts the outcomes on the `AGENT_AUTHORED` rung — the
|
|
219
|
+
floor demo: the same two bits, narrated instead of recorded, ABSTAIN."""
|
|
220
|
+
b = baseline if isinstance(baseline, RunOutcome) else RunOutcome.parse(baseline)
|
|
221
|
+
c = candidate if isinstance(candidate, RunOutcome) else RunOutcome.parse(candidate)
|
|
222
|
+
rung = Accountability.AGENT_AUTHORED if forgeable else Accountability.OS_RECORDED
|
|
223
|
+
return cls(baseline=b, candidate=c, rung=rung)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@dataclass(frozen=True)
|
|
227
|
+
class TestWitnessVerdict:
|
|
228
|
+
"""The single verdict `classify()` returns, with the facts echoed back.
|
|
229
|
+
|
|
230
|
+
`verdict` is the typed `TestWitness`. `witnesses` is the one projection bit
|
|
231
|
+
a consumer ANDs in (True iff DISCRIMINATES) — a keep-gate / reward-set
|
|
232
|
+
builder branches on the bit, never re-parses the prose. `assert_level` is
|
|
233
|
+
True only for an assert-level discrimination (baseline FAILED, not ERRORED):
|
|
234
|
+
both forms honestly discriminate — the test provably cannot pass without the
|
|
235
|
+
change — but the assert-level form is the stronger witness (the test *ran*
|
|
236
|
+
against the old behavior and rejected it), and a consumer that wants only
|
|
237
|
+
the strong form filters on the bit. `reason` is the one-line operator-facing
|
|
238
|
+
summary; `evidence` is carried so `--json` emits the verdict *and the facts
|
|
239
|
+
behind it* in one object (the legible-distrust renderer seam).
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
__test__ = False # not a pytest class, despite the Test* name
|
|
243
|
+
|
|
244
|
+
verdict: TestWitness
|
|
245
|
+
reason: str
|
|
246
|
+
witnesses: bool
|
|
247
|
+
assert_level: bool
|
|
248
|
+
evidence: TestRunEvidence
|
|
249
|
+
|
|
250
|
+
def to_dict(self) -> dict:
|
|
251
|
+
e = self.evidence
|
|
252
|
+
return {
|
|
253
|
+
"verdict": self.verdict.value,
|
|
254
|
+
"reason": self.reason,
|
|
255
|
+
"witnesses": self.witnesses,
|
|
256
|
+
"assert_level": self.assert_level,
|
|
257
|
+
"evidence": {
|
|
258
|
+
"baseline": e.baseline.value,
|
|
259
|
+
"candidate": e.candidate.value,
|
|
260
|
+
"rung": e.rung.value,
|
|
261
|
+
},
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def classify(evidence: TestRunEvidence) -> TestWitnessVerdict:
|
|
266
|
+
"""Classify whether a (test, change) pair's two-tree outcomes witness the change.
|
|
267
|
+
|
|
268
|
+
PURE — no I/O, no clock, no policy (the rule is structural; there is no
|
|
269
|
+
threshold a host could legitimately tune). The ladder, top to bottom
|
|
270
|
+
(docs/288 §4):
|
|
271
|
+
|
|
272
|
+
1. ABSTAIN — the rung is forgeable (`AGENT_AUTHORED`: the agent narrated
|
|
273
|
+
the red→green), or either run is `NOT_RUN`. Half a join is not a join;
|
|
274
|
+
a narration is not a run. Never mint a witness off either — the
|
|
275
|
+
`believe_under_floor` direction, applied to discrimination.
|
|
276
|
+
2. REGRESSIVE — baseline PASSED, candidate not: the change *breaks* the
|
|
277
|
+
test. For a pre-existing test, a regression; for a test the change
|
|
278
|
+
itself ships, an incoherent claim. (FrontierCode's "regression safety"
|
|
279
|
+
dimension, reduced to its deterministic core.)
|
|
280
|
+
3. UNSATISFIED — candidate not PASSED (and the baseline didn't pass
|
|
281
|
+
either): the change does not satisfy its own test. Nothing is
|
|
282
|
+
witnessed, and the fix claim itself is now in doubt — the red half of
|
|
283
|
+
red→green without the green.
|
|
284
|
+
4. VACUOUS — PASSED on both trees. The test would have passed without the
|
|
285
|
+
change; it witnesses nothing. The FrontierCode false-positive shape,
|
|
286
|
+
and the load-bearing verdict of this module — the one a naive
|
|
287
|
+
"tests added ✓" reviewer banks as assurance.
|
|
288
|
+
5. DISCRIMINATES — baseline FAILED/ERRORED, candidate PASSED: red→green
|
|
289
|
+
across the change. The only verdict whose `witnesses` bit is True.
|
|
290
|
+
`assert_level` distinguishes the strong form (baseline FAILED — the
|
|
291
|
+
test ran and rejected the old behavior) from the structural form
|
|
292
|
+
(baseline ERRORED — e.g. the test imports a module only the candidate
|
|
293
|
+
tree has; it provably cannot pass without the change, but it never
|
|
294
|
+
executed against the old behavior).
|
|
295
|
+
"""
|
|
296
|
+
b, c = evidence.baseline, evidence.candidate
|
|
297
|
+
|
|
298
|
+
# 1. ABSTAIN — forgeable rung: the outcomes are the agent's own narration.
|
|
299
|
+
# The structural floor: an agent cannot narrate its way to DISCRIMINATES,
|
|
300
|
+
# exactly as a forgeable read-back cannot ACCEPT in `reward`.
|
|
301
|
+
if evidence.rung.is_agent_authored:
|
|
302
|
+
return TestWitnessVerdict(
|
|
303
|
+
verdict=TestWitness.ABSTAIN,
|
|
304
|
+
reason=(
|
|
305
|
+
f"outcomes are AGENT_AUTHORED (narrated '{b} -> {c}') — a "
|
|
306
|
+
f"narration is not a run; no witness minted (gather both "
|
|
307
|
+
f"outcomes from an env-recorded runner)"
|
|
308
|
+
),
|
|
309
|
+
witnesses=False,
|
|
310
|
+
assert_level=False,
|
|
311
|
+
evidence=evidence,
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
# 1b. ABSTAIN — half a join is not a join: one (or both) trees has no
|
|
315
|
+
# runner outcome. Never guess the missing half.
|
|
316
|
+
if b is RunOutcome.NOT_RUN or c is RunOutcome.NOT_RUN:
|
|
317
|
+
missing = "baseline" if b is RunOutcome.NOT_RUN else "candidate"
|
|
318
|
+
if b is RunOutcome.NOT_RUN and c is RunOutcome.NOT_RUN:
|
|
319
|
+
missing = "baseline and candidate"
|
|
320
|
+
return TestWitnessVerdict(
|
|
321
|
+
verdict=TestWitness.ABSTAIN,
|
|
322
|
+
reason=(
|
|
323
|
+
f"the {missing} run is missing (NOT_RUN) — half a join is not "
|
|
324
|
+
f"a join; run the test on both trees"
|
|
325
|
+
),
|
|
326
|
+
witnesses=False,
|
|
327
|
+
assert_level=False,
|
|
328
|
+
evidence=evidence,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
# 2. REGRESSIVE — the change breaks a baseline-green test.
|
|
332
|
+
if b is RunOutcome.PASSED and c is not RunOutcome.PASSED:
|
|
333
|
+
return TestWitnessVerdict(
|
|
334
|
+
verdict=TestWitness.REGRESSIVE,
|
|
335
|
+
reason=(
|
|
336
|
+
f"baseline PASSED, candidate {c} — the change BREAKS this test "
|
|
337
|
+
f"(a regression for a pre-existing test; an incoherent claim "
|
|
338
|
+
f"for a test the change itself ships)"
|
|
339
|
+
),
|
|
340
|
+
witnesses=False,
|
|
341
|
+
assert_level=False,
|
|
342
|
+
evidence=evidence,
|
|
343
|
+
)
|
|
344
|
+
|
|
345
|
+
# 3. UNSATISFIED — the change does not satisfy its own test (no green half).
|
|
346
|
+
if c is not RunOutcome.PASSED:
|
|
347
|
+
return TestWitnessVerdict(
|
|
348
|
+
verdict=TestWitness.UNSATISFIED,
|
|
349
|
+
reason=(
|
|
350
|
+
f"candidate {c} (baseline {b}) — the change does not satisfy "
|
|
351
|
+
f"its own test: the red half of red->green without the green; "
|
|
352
|
+
f"the fix claim itself is in doubt"
|
|
353
|
+
),
|
|
354
|
+
witnesses=False,
|
|
355
|
+
assert_level=False,
|
|
356
|
+
evidence=evidence,
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
# 4. VACUOUS — green on both trees: the test witnesses nothing. The
|
|
360
|
+
# FrontierCode false-positive shape; the verdict this module exists for.
|
|
361
|
+
if b is RunOutcome.PASSED:
|
|
362
|
+
return TestWitnessVerdict(
|
|
363
|
+
verdict=TestWitness.VACUOUS,
|
|
364
|
+
reason=(
|
|
365
|
+
"PASSED on both trees — the test would have passed WITHOUT the "
|
|
366
|
+
"change; it witnesses nothing (the vacuous-test inflation a "
|
|
367
|
+
"'tests added' reviewer banks as assurance)"
|
|
368
|
+
),
|
|
369
|
+
witnesses=False,
|
|
370
|
+
assert_level=False,
|
|
371
|
+
evidence=evidence,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
# 5. DISCRIMINATES — red→green across the change. The only witness-minting
|
|
375
|
+
# verdict; `assert_level` flags the strong (ran-and-rejected) form.
|
|
376
|
+
assert_level = b is RunOutcome.FAILED
|
|
377
|
+
strength = (
|
|
378
|
+
"assert-level (the test RAN against the old behavior and rejected it)"
|
|
379
|
+
if assert_level
|
|
380
|
+
else "structural (baseline ERRORED — it provably cannot pass without "
|
|
381
|
+
"the change, but it never executed against the old behavior)"
|
|
382
|
+
)
|
|
383
|
+
return TestWitnessVerdict(
|
|
384
|
+
verdict=TestWitness.DISCRIMINATES,
|
|
385
|
+
reason=(
|
|
386
|
+
f"baseline {b}, candidate PASSED — red->green across the change: "
|
|
387
|
+
f"this test witnesses it; {strength}"
|
|
388
|
+
),
|
|
389
|
+
witnesses=True,
|
|
390
|
+
assert_level=assert_level,
|
|
391
|
+
evidence=evidence,
|
|
392
|
+
)
|