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/effect_witness.py
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
"""effect_witness — did the world actually CHANGE the way the agent CLAIMED? (docs/181)
|
|
2
|
+
|
|
3
|
+
The result-state witness DOS named (docs/176/177) as its most valuable member: the
|
|
4
|
+
one tool-verification check whose value *grows* with model strength, because it does
|
|
5
|
+
not read the trajectory at all. Every in-trajectory detector (`tool_stream`,
|
|
6
|
+
`terminal_error`, `dangling_intent`) reads a distress *shape* the agent's own bytes
|
|
7
|
+
co-author, so a competent model fails them silently (docs/177: 83.3% of frontier
|
|
8
|
+
fails leave no in-trace signal). This module reads a different thing: an
|
|
9
|
+
**out-of-trajectory read-back of world state**, authored by a witness the agent did
|
|
10
|
+
not control, and asks whether the claimed effect is actually *present* in it.
|
|
11
|
+
|
|
12
|
+
The field shipped this in three shapes in early 2026 (docs/180) — Agent-Diff
|
|
13
|
+
(state-diff against a golden delta), VAGEN (a verifier agent that takes its OWN read
|
|
14
|
+
actions), Tool Receipts (an HMAC receipt the LLM cannot forge). This is DOS's
|
|
15
|
+
domain-free, deterministic, floor-disciplined version of the same idea, fused with
|
|
16
|
+
the apparatus the kernel already proved in `evidence.py`.
|
|
17
|
+
|
|
18
|
+
The one idea: a verdict is a JOIN of two independently-authored facts
|
|
19
|
+
=====================================================================
|
|
20
|
+
|
|
21
|
+
`effect_witness` does NOT verify by re-reading the agent's claim against itself — that
|
|
22
|
+
is the mirror-verifier trap (`[[consistency-is-not-grounding]]`): re-deriving an
|
|
23
|
+
author's own bytes is consistency, never grounding. It mints a verdict ONLY by
|
|
24
|
+
joining two facts with *different* byte-authors (the `derived_witness` /
|
|
25
|
+
`journal_delta`-vs-`git_delta` law, docs/179):
|
|
26
|
+
|
|
27
|
+
1. the **claim** — what the agent ASSERTED it did to the world (an `EffectClaim`:
|
|
28
|
+
an opaque effect key the agent narrated, e.g. "quiz:Classic-Art-History created"
|
|
29
|
+
or "row id=42 inserted in table orders"). The agent authored this. It is the
|
|
30
|
+
forgeable floor — on its own it can never grant belief.
|
|
31
|
+
2. the **read-back** — an `evidence.EvidenceFacts` from a witness that RE-READ the
|
|
32
|
+
world from a surface the agent did not author (a fresh GET against the live API,
|
|
33
|
+
a state-snapshot diff, an OS-recorded query result). The witness authored this.
|
|
34
|
+
|
|
35
|
+
The verdict is the JOIN: *is the claimed effect PRESENT in the witnessed state?* —
|
|
36
|
+
and crucially the join's TRUST is capped by the read-back's `accountability`, exactly
|
|
37
|
+
as `believe_under_floor` requires. A claim "confirmed" only by re-reading the agent's
|
|
38
|
+
own narration is structurally incapable of CONFIRMED here; the read-back must come
|
|
39
|
+
from a non-forgeable rung. This is the §5a satisfaction-predicate line held: we never
|
|
40
|
+
ask the agent's own bytes "is the answer right?" — we ask an independent witness "is
|
|
41
|
+
the claimed change THERE?", which is a presence question over non-forgeable bytes.
|
|
42
|
+
|
|
43
|
+
Why "presence" and not "correctness"
|
|
44
|
+
====================================
|
|
45
|
+
|
|
46
|
+
We deliberately verify **claim ⊆ witnessed-delta** (was the change the agent claimed
|
|
47
|
+
actually made?), not "is the end-state globally correct?". Global correctness needs a
|
|
48
|
+
gold state (a benchmark oracle has one; a live deployment does not). Presence needs
|
|
49
|
+
only the agent's claim + a read-back, both of which a live runtime HAS. This is the
|
|
50
|
+
honest, domain-free slice: DOS confirms the *specific effect the agent took credit
|
|
51
|
+
for*, refutes it when the witness shows it absent, and abstains when no accountable
|
|
52
|
+
witness could be reached — never inventing a gold state it cannot have.
|
|
53
|
+
|
|
54
|
+
The four-valued verdict (the typed-verdict family)
|
|
55
|
+
==================================================
|
|
56
|
+
|
|
57
|
+
CONFIRMED — an accountable (non-forgeable) witness re-read the world and the
|
|
58
|
+
claimed effect is PRESENT. The only value that grants belief; gated by
|
|
59
|
+
the floor (a forgeable read-back can never reach it).
|
|
60
|
+
REFUTED — an accountable witness re-read the world and the claimed effect is
|
|
61
|
+
ABSENT (the agent said it created the quiz; the fresh GET shows no such
|
|
62
|
+
quiz). The load-bearing value: this is the silent frontier-fail
|
|
63
|
+
(docs/177) made VISIBLE — a confidently-narrated success the world
|
|
64
|
+
does not corroborate. Stronger than "no signal".
|
|
65
|
+
UNWITNESSED — no accountable witness could be reached, OR the only read-back was on
|
|
66
|
+
the forgeable floor (the agent re-read its own surface). The honest
|
|
67
|
+
abstain — what every degrade lands on. Distinct from REFUTED: we could
|
|
68
|
+
not tell, not "we checked and it's absent".
|
|
69
|
+
NO_CLAIM — the agent asserted no checkable effect (free prose, "I'm done"). There
|
|
70
|
+
is nothing to witness; the `claim_extract` abstain-never-invent law,
|
|
71
|
+
restated for effects. (A consumer reads this as "nothing to do here",
|
|
72
|
+
NOT as a pass.)
|
|
73
|
+
|
|
74
|
+
PURE — no I/O. The claim was extracted at the boundary (`claim_extract` or a host
|
|
75
|
+
adapter) and the read-back was gathered at the boundary (`evidence.gather_evidence`
|
|
76
|
+
over a `drivers/*` witness). This module only JOINS them. Sits in the kernel layer
|
|
77
|
+
beside `evidence`/`liveness`/`completion`. A real read-back witness (a state-diff
|
|
78
|
+
prober, an HTTP re-GET, an HMAC-receipt checker) lives in a driver — it imports the
|
|
79
|
+
kernel; the kernel never imports it.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
from __future__ import annotations
|
|
83
|
+
|
|
84
|
+
import enum
|
|
85
|
+
from dataclasses import dataclass, field
|
|
86
|
+
|
|
87
|
+
from dos.evidence import (
|
|
88
|
+
Accountability,
|
|
89
|
+
BeliefVerdict,
|
|
90
|
+
EvidenceFacts,
|
|
91
|
+
EvidenceStance,
|
|
92
|
+
believe_under_floor,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
__all__ = [
|
|
96
|
+
"EffectClaim",
|
|
97
|
+
"EffectStance",
|
|
98
|
+
"EffectWitnessVerdict",
|
|
99
|
+
"witness_effect",
|
|
100
|
+
"PRESENT",
|
|
101
|
+
"ABSENT",
|
|
102
|
+
"INDETERMINATE",
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
# ---------------------------------------------------------------------------
|
|
107
|
+
# The claim side — what the agent asserted it did to the world.
|
|
108
|
+
# ---------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@dataclass(frozen=True)
|
|
112
|
+
class EffectClaim:
|
|
113
|
+
"""One checkable effect the agent ASSERTED it produced.
|
|
114
|
+
|
|
115
|
+
`key` is the OPAQUE effect identity the join is over — the host/extractor decides
|
|
116
|
+
its grammar (`"quiz:Classic-Art-History"`, `"orders:row:42"`, an idempotency key).
|
|
117
|
+
It is the bridge between "what the agent said" and "what to look for in the
|
|
118
|
+
read-back": a witness re-reads the world and reports whether an effect with THIS
|
|
119
|
+
key is present. `subject` is the witness's correlation handle (often == key, but a
|
|
120
|
+
host may map a claim key to a different probe subject — e.g. the command/URL that
|
|
121
|
+
re-reads it). `narrated` is the agent's original phrasing, carried for the
|
|
122
|
+
operator surface (legible distrust — show WHAT was claimed), never parsed for
|
|
123
|
+
truth. The claim is, by construction, `AGENT_AUTHORED` — the forgeable floor; it
|
|
124
|
+
is the thing to be checked, never itself evidence.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
key: str
|
|
128
|
+
subject: str = ""
|
|
129
|
+
narrated: str = ""
|
|
130
|
+
|
|
131
|
+
def probe_subject(self) -> str:
|
|
132
|
+
"""The handle to hand a read-back witness — `subject` if set, else `key`."""
|
|
133
|
+
return self.subject or self.key
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# ---------------------------------------------------------------------------
|
|
137
|
+
# The read-back side reports one of three *presence* answers about the effect.
|
|
138
|
+
# These are NOT the witness's reachability (that is EvidenceFacts.reachable/stance);
|
|
139
|
+
# they are what an accountable, reached witness SAW about the claimed effect's
|
|
140
|
+
# presence in world state. A host's read-back witness encodes its answer in the
|
|
141
|
+
# EvidenceFacts stance it returns (see witness_effect's mapping), but we also accept
|
|
142
|
+
# an explicit presence tag for a witness that distinguishes "reached, effect absent"
|
|
143
|
+
# from "reached, a DIFFERENT effect present".
|
|
144
|
+
# ---------------------------------------------------------------------------
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class EffectStance(str, enum.Enum):
|
|
148
|
+
"""What an accountable read-back saw about the CLAIMED effect's presence."""
|
|
149
|
+
|
|
150
|
+
PRESENT = "PRESENT" # the claimed effect IS in the witnessed state
|
|
151
|
+
ABSENT = "ABSENT" # the witness re-read and the effect is NOT there
|
|
152
|
+
INDETERMINATE = "INDETERMINATE" # reached, but cannot tell about THIS effect
|
|
153
|
+
|
|
154
|
+
def __str__(self) -> str: # pragma: no cover - trivial
|
|
155
|
+
return self.value
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
PRESENT = EffectStance.PRESENT
|
|
159
|
+
ABSENT = EffectStance.ABSENT
|
|
160
|
+
INDETERMINATE = EffectStance.INDETERMINATE
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# ---------------------------------------------------------------------------
|
|
164
|
+
# The verdict.
|
|
165
|
+
# ---------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class _Verdict(str, enum.Enum):
|
|
169
|
+
CONFIRMED = "CONFIRMED"
|
|
170
|
+
REFUTED = "REFUTED"
|
|
171
|
+
UNWITNESSED = "UNWITNESSED"
|
|
172
|
+
NO_CLAIM = "NO_CLAIM"
|
|
173
|
+
|
|
174
|
+
def __str__(self) -> str: # pragma: no cover - trivial
|
|
175
|
+
return self.value
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
@dataclass(frozen=True)
|
|
179
|
+
class EffectWitnessVerdict:
|
|
180
|
+
"""The folded answer: did an accountable witness corroborate the claimed effect?
|
|
181
|
+
|
|
182
|
+
`verdict` is the four-valued result token (CONFIRMED / REFUTED / UNWITNESSED /
|
|
183
|
+
NO_CLAIM). `believe` is the positive bit a consumer may consume — True ONLY on
|
|
184
|
+
CONFIRMED (a non-forgeable witness saw the effect present). `refuted` is surfaced
|
|
185
|
+
separately because a refutation by an accountable witness is the silent-fail
|
|
186
|
+
detector — a consumer may RED-flag on it even though `believe` is also False.
|
|
187
|
+
`claim_key`/`narrated` echo what was checked; `witness`/`accountability` name the
|
|
188
|
+
read-back behind the verdict; `reason` is the one-line legible-distrust string for
|
|
189
|
+
`dos doctor` / the decisions queue / `--json`.
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
verdict: _Verdict
|
|
193
|
+
believe: bool
|
|
194
|
+
refuted: bool
|
|
195
|
+
reason: str
|
|
196
|
+
claim_key: str = ""
|
|
197
|
+
narrated: str = ""
|
|
198
|
+
witness: str = ""
|
|
199
|
+
accountability: Accountability | None = None
|
|
200
|
+
silent_witnesses: tuple[str, ...] = field(default_factory=tuple)
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def is_confirmed(self) -> bool:
|
|
204
|
+
return self.verdict is _Verdict.CONFIRMED
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def is_refuted(self) -> bool:
|
|
208
|
+
return self.verdict is _Verdict.REFUTED
|
|
209
|
+
|
|
210
|
+
def to_dict(self) -> dict:
|
|
211
|
+
return {
|
|
212
|
+
"verdict": self.verdict.value,
|
|
213
|
+
"believe": self.believe,
|
|
214
|
+
"refuted": self.refuted,
|
|
215
|
+
"reason": self.reason,
|
|
216
|
+
"claim_key": self.claim_key,
|
|
217
|
+
"narrated": self.narrated,
|
|
218
|
+
"witness": self.witness,
|
|
219
|
+
"accountability": self.accountability.value if self.accountability else None,
|
|
220
|
+
"silent_witnesses": list(self.silent_witnesses),
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def _effect_stance_of(facts: EvidenceFacts) -> EffectStance:
|
|
225
|
+
"""Map a read-back `EvidenceFacts` onto a presence answer about the claimed effect.
|
|
226
|
+
|
|
227
|
+
The default, conservative mapping for a witness that does NOT carry an explicit
|
|
228
|
+
presence tag (most do not — they answer "did the acceptance check pass?"):
|
|
229
|
+
|
|
230
|
+
* a reached ATTESTED read → PRESENT (the witness confirmed the effect)
|
|
231
|
+
* a reached REFUTED read → ABSENT (the witness disconfirmed the effect)
|
|
232
|
+
* NO_SIGNAL / unreachable → INDETERMINATE (could not tell)
|
|
233
|
+
|
|
234
|
+
A richer witness that distinguishes "effect absent" from "reached but can't tell
|
|
235
|
+
about this specific effect" encodes that by returning REFUTED vs a reached
|
|
236
|
+
NO_SIGNAL; we honor the stance it chose. We never UPGRADE a stance — a witness's
|
|
237
|
+
own conservatism is preserved.
|
|
238
|
+
"""
|
|
239
|
+
if facts.reachable and facts.stance is EvidenceStance.ATTESTED:
|
|
240
|
+
return EffectStance.PRESENT
|
|
241
|
+
if facts.reachable and facts.stance is EvidenceStance.REFUTED:
|
|
242
|
+
return EffectStance.ABSENT
|
|
243
|
+
return EffectStance.INDETERMINATE
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def witness_effect(
|
|
247
|
+
claim: EffectClaim | None,
|
|
248
|
+
readbacks: "tuple[EvidenceFacts, ...] | list[EvidenceFacts]",
|
|
249
|
+
) -> EffectWitnessVerdict:
|
|
250
|
+
"""Join a claimed effect to its read-back witnesses under the floor discipline.
|
|
251
|
+
|
|
252
|
+
The pure keystone. The rule, structural and not a host-tunable threshold:
|
|
253
|
+
|
|
254
|
+
> CONFIRMED ⟺ at least one read-back on a NON-FORGEABLE rung
|
|
255
|
+
> (`OS_RECORDED`/`THIRD_PARTY`) was reached and saw the effect PRESENT.
|
|
256
|
+
> REFUTED ⟺ (no non-forgeable witness confirmed it) AND at least one
|
|
257
|
+
> non-forgeable read-back was reached and saw the effect ABSENT.
|
|
258
|
+
> NO_CLAIM ⟺ there is no claim to check.
|
|
259
|
+
> UNWITNESSED otherwise — no accountable witness reached a presence answer
|
|
260
|
+
> (only forgeable-floor reads, or only NO_SIGNAL).
|
|
261
|
+
|
|
262
|
+
The floor is enforced by delegating the belief decision to
|
|
263
|
+
`evidence.believe_under_floor` — a forgeable-floor read-back (the agent re-read its
|
|
264
|
+
OWN surface, `AGENT_AUTHORED`) is recorded but structurally cannot CONFIRM or, by
|
|
265
|
+
the symmetric rule, REFUTE on its own. So the worst a lying same-surface witness can
|
|
266
|
+
do is be IGNORED (a safe-direction no-op), never manufacture a CONFIRMED for an
|
|
267
|
+
effect that did not happen, nor a REFUTED for one that did.
|
|
268
|
+
|
|
269
|
+
PURE — no I/O. Claim extracted at the boundary, read-backs gathered at the boundary
|
|
270
|
+
(`evidence.gather_evidence`); this only folds.
|
|
271
|
+
"""
|
|
272
|
+
if claim is None or not (claim.key or "").strip():
|
|
273
|
+
return EffectWitnessVerdict(
|
|
274
|
+
verdict=_Verdict.NO_CLAIM,
|
|
275
|
+
believe=False,
|
|
276
|
+
refuted=False,
|
|
277
|
+
reason="no checkable effect claimed — nothing to witness (abstain, never invent)",
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
facts = tuple(readbacks)
|
|
281
|
+
|
|
282
|
+
# Reuse the floor's belief fold for the PRESENT side: an ATTESTED read-back means
|
|
283
|
+
# "effect present", so a believed BeliefVerdict over the read-backs == an
|
|
284
|
+
# accountable witness saw the effect present. This keeps the floor discipline in
|
|
285
|
+
# ONE place (the dual-of-overlap_policy guarantee) rather than re-implementing it.
|
|
286
|
+
belief: BeliefVerdict = believe_under_floor(facts)
|
|
287
|
+
|
|
288
|
+
# Identify, per the same accountability rule, whether any non-forgeable witness saw
|
|
289
|
+
# the effect ABSENT (a REFUTED read-back on a non-forgeable rung). believe_under_floor
|
|
290
|
+
# already computes `refuted` exactly this way, so we read it off the fold.
|
|
291
|
+
confirmed = belief.believe
|
|
292
|
+
refuted_by_accountable = belief.refuted
|
|
293
|
+
|
|
294
|
+
# Name the witness behind the headline answer, for the operator surface.
|
|
295
|
+
def _first_nonforgeable(stance: EvidenceStance) -> EvidenceFacts | None:
|
|
296
|
+
for f in facts:
|
|
297
|
+
if (
|
|
298
|
+
f.reachable
|
|
299
|
+
and f.stance is stance
|
|
300
|
+
and not f.accountability.is_agent_authored
|
|
301
|
+
):
|
|
302
|
+
return f
|
|
303
|
+
return None
|
|
304
|
+
|
|
305
|
+
silent = tuple(
|
|
306
|
+
f.source_name
|
|
307
|
+
for f in facts
|
|
308
|
+
if not (f.reachable and f.stance in (EvidenceStance.ATTESTED, EvidenceStance.REFUTED))
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
if confirmed and refuted_by_accountable:
|
|
312
|
+
# Accountable witnesses disagree — the CONFLICT case. Surface both; a consumer
|
|
313
|
+
# routes to a human (the believe_under_floor CONFLICT posture). We do NOT
|
|
314
|
+
# collapse to CONFIRMED: a disagreement among accountable witnesses is not a
|
|
315
|
+
# clean confirmation.
|
|
316
|
+
w = _first_nonforgeable(EvidenceStance.ATTESTED)
|
|
317
|
+
return EffectWitnessVerdict(
|
|
318
|
+
verdict=_Verdict.REFUTED, # conservative: a contested effect is not believed
|
|
319
|
+
believe=False,
|
|
320
|
+
refuted=True,
|
|
321
|
+
reason=(
|
|
322
|
+
f"CONFLICT — accountable witnesses disagree on effect {claim.key!r}: "
|
|
323
|
+
f"{', '.join(belief.attesting)} present, {', '.join(belief.refuting)} absent "
|
|
324
|
+
f"(route to a human)"
|
|
325
|
+
),
|
|
326
|
+
claim_key=claim.key,
|
|
327
|
+
narrated=claim.narrated,
|
|
328
|
+
witness=(w.source_name if w else ""),
|
|
329
|
+
accountability=(w.accountability if w else None),
|
|
330
|
+
silent_witnesses=silent,
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
if confirmed:
|
|
334
|
+
w = _first_nonforgeable(EvidenceStance.ATTESTED)
|
|
335
|
+
return EffectWitnessVerdict(
|
|
336
|
+
verdict=_Verdict.CONFIRMED,
|
|
337
|
+
believe=True,
|
|
338
|
+
refuted=False,
|
|
339
|
+
reason=(
|
|
340
|
+
f"CONFIRMED — non-forgeable witness re-read the world and effect "
|
|
341
|
+
f"{claim.key!r} is PRESENT: {', '.join(belief.attesting)}"
|
|
342
|
+
),
|
|
343
|
+
claim_key=claim.key,
|
|
344
|
+
narrated=claim.narrated,
|
|
345
|
+
witness=(w.source_name if w else ""),
|
|
346
|
+
accountability=(w.accountability if w else None),
|
|
347
|
+
silent_witnesses=silent,
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
if refuted_by_accountable:
|
|
351
|
+
w = _first_nonforgeable(EvidenceStance.REFUTED)
|
|
352
|
+
return EffectWitnessVerdict(
|
|
353
|
+
verdict=_Verdict.REFUTED,
|
|
354
|
+
believe=False,
|
|
355
|
+
refuted=True,
|
|
356
|
+
reason=(
|
|
357
|
+
f"REFUTED — non-forgeable witness re-read the world and effect "
|
|
358
|
+
f"{claim.key!r} is ABSENT: {', '.join(belief.refuting)} "
|
|
359
|
+
f"(a narrated success the world does not corroborate)"
|
|
360
|
+
),
|
|
361
|
+
claim_key=claim.key,
|
|
362
|
+
narrated=claim.narrated,
|
|
363
|
+
witness=(w.source_name if w else ""),
|
|
364
|
+
accountability=(w.accountability if w else None),
|
|
365
|
+
silent_witnesses=silent,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
# Nothing accountable reached a presence answer — abstain. If something attested on
|
|
369
|
+
# the forgeable floor only, say WHY it didn't count (the believe_under_floor
|
|
370
|
+
# forgeable-floor reason), so an operator sees the same-surface read-back was
|
|
371
|
+
# ignored on purpose.
|
|
372
|
+
if belief.attesting:
|
|
373
|
+
reason = (
|
|
374
|
+
f"UNWITNESSED — effect {claim.key!r} was only re-read on the forgeable floor "
|
|
375
|
+
f"(AGENT_AUTHORED: {', '.join(belief.attesting)}); no accountable witness — "
|
|
376
|
+
f"cannot confirm (the agent re-reading its own surface is not corroboration)"
|
|
377
|
+
)
|
|
378
|
+
else:
|
|
379
|
+
reason = (
|
|
380
|
+
f"UNWITNESSED — no accountable witness reached effect {claim.key!r} "
|
|
381
|
+
f"(no signal); cannot tell whether it happened"
|
|
382
|
+
)
|
|
383
|
+
return EffectWitnessVerdict(
|
|
384
|
+
verdict=_Verdict.UNWITNESSED,
|
|
385
|
+
believe=False,
|
|
386
|
+
refuted=False,
|
|
387
|
+
reason=reason,
|
|
388
|
+
claim_key=claim.key,
|
|
389
|
+
narrated=claim.narrated,
|
|
390
|
+
witness="",
|
|
391
|
+
accountability=None,
|
|
392
|
+
silent_witnesses=silent,
|
|
393
|
+
)
|