dos-kernel 0.22.0__py3-none-win_arm64.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.
Files changed (178) hide show
  1. dos/__init__.py +261 -0
  2. dos/_bin/dos-hook.exe +0 -0
  3. dos/_filelock.py +255 -0
  4. dos/_job_policy.py +97 -0
  5. dos/_tree.py +145 -0
  6. dos/admission.py +433 -0
  7. dos/answer_shape.py +299 -0
  8. dos/arbiter.py +859 -0
  9. dos/archive_lock.py +266 -0
  10. dos/arg_provenance.py +814 -0
  11. dos/attest.py +472 -0
  12. dos/breaker.py +311 -0
  13. dos/churn.py +226 -0
  14. dos/claim_extract.py +229 -0
  15. dos/claim_ttl.py +150 -0
  16. dos/cli.py +8721 -0
  17. dos/commit_audit.py +666 -0
  18. dos/completion.py +466 -0
  19. dos/concurrency_class.py +154 -0
  20. dos/config.py +1380 -0
  21. dos/config_lint.py +464 -0
  22. dos/cooldown.py +390 -0
  23. dos/coverage.py +387 -0
  24. dos/dangling_intent.py +287 -0
  25. dos/data_class.py +397 -0
  26. dos/decisions.py +1274 -0
  27. dos/decisions_tui.py +251 -0
  28. dos/dispatch_top.py +740 -0
  29. dos/dispatch_top_tui.py +116 -0
  30. dos/drivers/__init__.py +40 -0
  31. dos/drivers/ci_status.py +630 -0
  32. dos/drivers/citation_resolve.py +703 -0
  33. dos/drivers/decision_stop.py +98 -0
  34. dos/drivers/export_file.py +173 -0
  35. dos/drivers/export_otlp.py +275 -0
  36. dos/drivers/export_statsd.py +242 -0
  37. dos/drivers/hook_dialects.py +391 -0
  38. dos/drivers/job.py +47 -0
  39. dos/drivers/llm_judge.py +360 -0
  40. dos/drivers/memory_recall.py +1231 -0
  41. dos/drivers/notify_slack.py +373 -0
  42. dos/drivers/notify_webhook.py +251 -0
  43. dos/drivers/operator_judge.py +114 -0
  44. dos/drivers/os_acceptance.py +228 -0
  45. dos/drivers/paste_log.py +132 -0
  46. dos/drivers/plan_scope.py +133 -0
  47. dos/drivers/self_improve.py +375 -0
  48. dos/drivers/similarity_judge.py +249 -0
  49. dos/drivers/state_diff.py +274 -0
  50. dos/drivers/supervisor.py +347 -0
  51. dos/drivers/watchdog.py +363 -0
  52. dos/drivers/workshop.py +160 -0
  53. dos/durable_schema.py +344 -0
  54. dos/effect_witness.py +393 -0
  55. dos/efficiency.py +318 -0
  56. dos/enforce.py +414 -0
  57. dos/enumerate.py +776 -0
  58. dos/env_print.py +378 -0
  59. dos/event_severity.py +258 -0
  60. dos/evidence.py +692 -0
  61. dos/exec_capability.py +256 -0
  62. dos/export_cursor.py +143 -0
  63. dos/exporter.py +320 -0
  64. dos/firing_label.py +353 -0
  65. dos/fleet_roll.py +226 -0
  66. dos/gate_classify.py +827 -0
  67. dos/gh4_coverage.py +179 -0
  68. dos/git_delta.py +122 -0
  69. dos/guard.py +215 -0
  70. dos/health.py +552 -0
  71. dos/help_summary.py +519 -0
  72. dos/home.py +934 -0
  73. dos/hook_binary.py +194 -0
  74. dos/hook_dialect.py +271 -0
  75. dos/hook_exit.py +191 -0
  76. dos/hook_install.py +437 -0
  77. dos/id_alloc.py +304 -0
  78. dos/improve.py +499 -0
  79. dos/intent_ledger.py +635 -0
  80. dos/interpret.py +176 -0
  81. dos/intervention.py +769 -0
  82. dos/intervention_eval.py +371 -0
  83. dos/journal_delta.py +308 -0
  84. dos/judge_eval.py +328 -0
  85. dos/judges.py +366 -0
  86. dos/lane_infer.py +127 -0
  87. dos/lane_journal.py +1001 -0
  88. dos/lane_lease.py +952 -0
  89. dos/lane_overlap.py +228 -0
  90. dos/lease_health.py +282 -0
  91. dos/lifecycle.py +211 -0
  92. dos/liveness.py +352 -0
  93. dos/lock_modes.py +185 -0
  94. dos/log_source.py +395 -0
  95. dos/loop_decide.py +1746 -0
  96. dos/marker_gate.py +254 -0
  97. dos/marker_sensor.py +396 -0
  98. dos/noop_streak.py +280 -0
  99. dos/notify.py +479 -0
  100. dos/observe.py +175 -0
  101. dos/oracle.py +1661 -0
  102. dos/overlap_eval.py +214 -0
  103. dos/overlap_policy.py +342 -0
  104. dos/packet_sidecar.py +267 -0
  105. dos/phase_shipped.py +1985 -0
  106. dos/pick_priority.py +225 -0
  107. dos/pickable.py +369 -0
  108. dos/picker_oracle.py +1037 -0
  109. dos/plan_board.py +513 -0
  110. dos/plan_board_tui.py +113 -0
  111. dos/plan_source.py +455 -0
  112. dos/posttool_sensor.py +528 -0
  113. dos/precursor_gate.py +499 -0
  114. dos/precursor_gate_eval.py +239 -0
  115. dos/preflight.py +825 -0
  116. dos/pretool_sensor.py +490 -0
  117. dos/proc_delta.py +181 -0
  118. dos/productivity.py +296 -0
  119. dos/provider_limit.py +242 -0
  120. dos/py.typed +4 -0
  121. dos/reason_morphology.py +299 -0
  122. dos/reasons.py +449 -0
  123. dos/reconcile.py +173 -0
  124. dos/recurring_wedge.py +206 -0
  125. dos/render.py +393 -0
  126. dos/result_state.py +468 -0
  127. dos/resume.py +578 -0
  128. dos/resume_evidence.py +293 -0
  129. dos/retention.py +344 -0
  130. dos/reward.py +372 -0
  131. dos/rewind.py +587 -0
  132. dos/rewind_evidence.py +168 -0
  133. dos/rewind_tokens.py +252 -0
  134. dos/run_id.py +342 -0
  135. dos/scope.py +520 -0
  136. dos/scope_source.py +382 -0
  137. dos/scout.py +982 -0
  138. dos/self_modify.py +209 -0
  139. dos/sibling_scan.py +569 -0
  140. dos/skills/EXAMPLES.md +584 -0
  141. dos/skills/dos-class-cycle/SKILL.md +107 -0
  142. dos/skills/dos-dispatch/SKILL.md +177 -0
  143. dos/skills/dos-dispatch-loop/SKILL.md +254 -0
  144. dos/skills/dos-goal-gate/SKILL.md +269 -0
  145. dos/skills/dos-next-up/SKILL.md +231 -0
  146. dos/skills/dos-promote/SKILL.md +114 -0
  147. dos/skills/dos-replan/SKILL.md +159 -0
  148. dos/skills/dos-replan-loop/SKILL.md +114 -0
  149. dos/skills/dos-self-improve/SKILL.md +213 -0
  150. dos/skills/dos-supervise-loop/SKILL.md +180 -0
  151. dos/skills/dos-unstick/SKILL.md +108 -0
  152. dos/skills/dos-witness-claim/SKILL.md +251 -0
  153. dos/stamp.py +1002 -0
  154. dos/state_health.py +387 -0
  155. dos/status.py +114 -0
  156. dos/stop_policy.py +334 -0
  157. dos/supervise.py +1014 -0
  158. dos/testwitness.py +392 -0
  159. dos/timeline.py +1027 -0
  160. dos/tokens.py +485 -0
  161. dos/tool_stream.py +393 -0
  162. dos/tool_stream_eval.py +226 -0
  163. dos/trace.py +524 -0
  164. dos/verdict.py +140 -0
  165. dos/verdict_cli.py +189 -0
  166. dos/verdict_journal.py +497 -0
  167. dos/verdict_rollup.py +217 -0
  168. dos/verdicts.py +181 -0
  169. dos/wedge_reason.py +282 -0
  170. dos_kernel-0.22.0.dist-info/METADATA +859 -0
  171. dos_kernel-0.22.0.dist-info/RECORD +178 -0
  172. dos_kernel-0.22.0.dist-info/WHEEL +5 -0
  173. dos_kernel-0.22.0.dist-info/entry_points.txt +39 -0
  174. dos_kernel-0.22.0.dist-info/licenses/LICENSE +21 -0
  175. dos_kernel-0.22.0.dist-info/top_level.txt +2 -0
  176. dos_mcp/__init__.py +52 -0
  177. dos_mcp/py.typed +2 -0
  178. dos_mcp/server.py +779 -0
dos/evidence.py ADDED
@@ -0,0 +1,692 @@
1
+ """The evidence-source seam — Axis 8 of hackability: a pluggable witness population.
2
+
3
+ docs/121 §5 — the throughline slice. `verify()` answers "did this effect actually
4
+ happen?" and today it reads exactly one witness: **git** (existence + ancestry +
5
+ ship-stamp grammar, via `dos.oracle`/`dos.git_delta`). docs/121 §2.1 is blunt that
6
+ this is the kernel having shipped the witness for *one* class of effect — a commit —
7
+ and being blind to every other: an email sent, a webhook delivered, a payment made,
8
+ a migration run, a deploy shipped. For each of those the witness is not git; it is
9
+ **the counterparty that received the effect** — the recipient's record, the
10
+ provider's sent-log, the bank's ledger, the OS exit code of a kernel-launched
11
+ command. Git is the witness in exactly one row of that table.
12
+
13
+ This module is the **pure seam** a witness plugs into, so that population becomes
14
+ open: `verify` stops being git-only and starts being "ask whichever witness is
15
+ accountable for *this* effect." It is field-for-field the apparatus `judges` (the
16
+ JUDGE rung), `overlap_policy` (the disjointness scorer), and `log_source` (the
17
+ log-adapter spectrum) already proved — a Protocol, frozen value types, an
18
+ unshadowable built-in baseline, a by-name resolver over an entry-point group, and a
19
+ fail-safe runner — fused with the **floor discipline** `overlap_policy` made
20
+ structural. Every *witnessing* source with real I/O surface (run a command and read
21
+ the exit code, call a provider's API, read a TEE attestation) lives in a `drivers/*`
22
+ module — it imports the kernel; the kernel never imports it (the `drivers/__init__`
23
+ rule). The kernel ships only the abstraction + the honest floor.
24
+
25
+ The one idea that makes this *verification* and not a fact-aggregation library
26
+ ================================================================================
27
+
28
+ An `EvidenceSource` is **a witness whose byte-author is not the judged agent**
29
+ (docs/121 §2.1). `git` is the special case where the witness is a VCS and the effect
30
+ is a commit. So every source declares its **`accountability`** — who authored the
31
+ bytes — as DATA, reusing the docs/117 spectrum (`AGENT_AUTHORED` / `OS_RECORDED` /
32
+ `THIRD_PARTY`). That tag is the *ceiling* on how much a consumer may trust the
33
+ source, fixed by the source, never inferred from content.
34
+
35
+ The floor discipline — `believe ⟺ a non-forgeable source attests` (load-bearing)
36
+ ==============================================================================
37
+
38
+ This is the security-load-bearing core, the dual of `overlap_policy`'s
39
+ `admissible_under_floor`. An evidence verdict (`believe` / `abstain`) is *positive*
40
+ — it can upgrade `verify` toward SHIPPED — so, exactly as a policy that *includes
41
+ admit* needs a floor ANDed under it, a witness population that *includes belief*
42
+ needs a floor ORed-only-from-the-non-forgeable-side:
43
+
44
+ > A swapped evidence source may add *more* abstention or contribute a *stronger*
45
+ > attestation. It may never let `verify` BELIEVE an effect that no non-forgeable
46
+ > source attests.
47
+
48
+ `believe_under_floor` computes this structurally: belief is granted **only** when at
49
+ least one source whose `accountability` is non-forgeable (`OS_RECORDED` /
50
+ `THIRD_PARTY`) reached the effect and attested it. A source on the **forgeable
51
+ floor** (`AGENT_AUTHORED` — a pasted receipt, the agent's own stdout, an mtime) is
52
+ *structurally incapable* of being the attesting source: its attestation is recorded
53
+ and shown, but it can never, by itself, move the verdict from abstain to believe.
54
+ This is what makes an *open* evidence-source set safe — the judge seam's
55
+ fail-to-ABSTAIN and the overlap seam's conjunctive-floor, re-aimed at belief: the
56
+ worst a buggy/hostile/lying source can do is *withhold* an attestation it should
57
+ have given (a visible, safe-direction loss — `verify` falls back to a weaker
58
+ witness), never *manufacture* a belief the agent could forge.
59
+
60
+ Purity & layering
61
+ =================
62
+
63
+ Pure stdlib — an enum (re-exported from `log_source` so the spectrum has one home),
64
+ two frozen value types, a built-in source that always abstains, a fail-safe runner,
65
+ a resolver, and the floor helper. NO provider surface, no I/O inside a verdict, names
66
+ no host. It sits in the kernel layer beside `judges`/`overlap_policy`/`log_source`.
67
+ Entry-point discovery (the one bit of I/O) happens at the call boundary in
68
+ `active_evidence_sources`, exactly as `active_judges` / `active_log_sources` do.
69
+ """
70
+
71
+ from __future__ import annotations
72
+
73
+ import enum
74
+ import sys
75
+ from dataclasses import dataclass
76
+ from typing import Protocol, runtime_checkable
77
+
78
+ # The accountability spectrum has ONE home — docs/117's `log_source`. An evidence
79
+ # source sits on the same who-authored-the-byte axis as a log source (a log IS a
80
+ # kind of evidence), so we reuse the enum verbatim rather than fork a parallel one.
81
+ # Re-exported here so a consumer can `from dos.evidence import Accountability`
82
+ # without reaching across to the log seam.
83
+ from dos.log_source import Accountability
84
+
85
+ __all__ = [
86
+ "Accountability",
87
+ "EvidenceStance",
88
+ "EvidenceFacts",
89
+ "EvidenceSource",
90
+ "NullEvidenceSource",
91
+ "gather_evidence",
92
+ "believe_under_floor",
93
+ "derived_witness",
94
+ "EVIDENCE_SOURCE_ENTRY_POINT_GROUP",
95
+ "resolve_evidence_source",
96
+ "active_evidence_sources",
97
+ "active_evidence_source_names",
98
+ ]
99
+
100
+
101
+ class EvidenceStance(str, enum.Enum):
102
+ """What a gathered `EvidenceFacts` says about the effect it was asked to witness.
103
+
104
+ Three-valued on purpose — the same honest split the typed-verdict family makes
105
+ (a behavioral oracle's GREEN/RED/PENDING/NO_SIGNAL collapses to belief /
106
+ refutation / no-answer): a binary attest/silent would have to *lie* about the case
107
+ where the witness was reached and saw the effect did NOT happen (a refutation is
108
+ not the same as "no signal"). `str`-valued so it round-trips through a CLI token /
109
+ JSON without a lookup table (the `Liveness` / `Accountability` idiom).
110
+
111
+ ATTESTED — the source was reached and witnessed the effect (the recipient has
112
+ the email; the exit code was 0; the ledger shows the payment). A
113
+ push toward belief — but ONLY counts toward `verify`'s belief if the
114
+ source's `accountability` is non-forgeable (the floor discipline).
115
+ REFUTED — the source was reached and witnessed the effect did NOT happen (the
116
+ recipient never got it; the exit code was non-zero). The
117
+ load-bearing third value: a refutation by an accountable witness is
118
+ STRONGER than no signal — it should redden `verify`, never be
119
+ mistaken for "could not tell."
120
+ NO_SIGNAL — the source could not be reached/read, or has no record either way.
121
+ The honest floor; what every failure degrades to. A consumer reads
122
+ it as abstain (the `run_judge` / behavioral-oracle fail-safe).
123
+ """
124
+
125
+ ATTESTED = "ATTESTED"
126
+ REFUTED = "REFUTED"
127
+ NO_SIGNAL = "NO_SIGNAL"
128
+
129
+ def __str__(self) -> str: # pragma: no cover - trivial
130
+ return self.value
131
+
132
+
133
+ @dataclass(frozen=True)
134
+ class EvidenceFacts:
135
+ """Frozen, caller-gathered facts about one effect, from one witness.
136
+
137
+ The `CiEvidence` / `LogEvidence` / `ProgressEvidence` analogue: facts gathered at
138
+ the boundary (inside a source's `gather`) and handed to a consuming verdict, which
139
+ is pure. No verdict lives inside — the source reports what it *saw*, the floor
140
+ helper decides what `verify` may *believe*.
141
+
142
+ source_name — the backend that produced this (`"os_acceptance"`,
143
+ `"stripe_ledger"`), for the operator-facing reason + the JSON
144
+ consumer.
145
+ accountability — the source's spectrum rung (docs/117). The load-bearing field:
146
+ `believe_under_floor` grants belief only on a NON-FORGEABLE
147
+ rung, never off content. A class-level property of the source,
148
+ echoed onto the facts so a downstream consumer routes off the
149
+ evidence object alone.
150
+ stance — ATTESTED / REFUTED / NO_SIGNAL (above).
151
+ subject — the effect this witnesses (an opaque correlation handle: a
152
+ run-id, a message-id, a command, a SHA — the source decides),
153
+ echoed for the operator surface.
154
+ detail — a one-line human note (the exit code, the provider id, why
155
+ unreachable) — legible distrust, for the reason / `dos doctor`.
156
+ reachable — was the witness actually reached? **Defaults to False** — the
157
+ fail-safe zero: facts nobody successfully populated read as
158
+ "no signal," never an empty-but-trusted attestation. A
159
+ `NO_SIGNAL` stance with `reachable=False` is the honest floor.
160
+
161
+ Three constructors make the outcomes unmistakable and keep the fail-safe default
162
+ from being fat-fingered: `attest(...)` (reached, effect happened),
163
+ `refute(...)` (reached, effect did NOT happen), `no_signal(...)` (every degrade).
164
+ There is deliberately no other way to set `reachable=True`.
165
+ """
166
+
167
+ source_name: str
168
+ accountability: Accountability
169
+ stance: EvidenceStance = EvidenceStance.NO_SIGNAL
170
+ subject: str = ""
171
+ detail: str = ""
172
+ reachable: bool = False
173
+
174
+ @classmethod
175
+ def attest(
176
+ cls,
177
+ source_name: str,
178
+ accountability: Accountability,
179
+ subject: str,
180
+ *,
181
+ detail: str = "",
182
+ ) -> "EvidenceFacts":
183
+ """The witness was reached and the effect HAPPENED. One of only two
184
+ constructors that set `reachable=True` — so a reachable attestation is always
185
+ a deliberate, populated read, never an accident of the default."""
186
+ return cls(
187
+ source_name=source_name,
188
+ accountability=accountability,
189
+ stance=EvidenceStance.ATTESTED,
190
+ subject=subject,
191
+ detail=detail,
192
+ reachable=True,
193
+ )
194
+
195
+ @classmethod
196
+ def refute(
197
+ cls,
198
+ source_name: str,
199
+ accountability: Accountability,
200
+ subject: str,
201
+ *,
202
+ detail: str = "",
203
+ ) -> "EvidenceFacts":
204
+ """The witness was reached and the effect did NOT happen (the recipient has no
205
+ record; the exit code was non-zero). `reachable=True`, stance REFUTED — a
206
+ positive disconfirmation, distinct from "could not tell.\""""
207
+ return cls(
208
+ source_name=source_name,
209
+ accountability=accountability,
210
+ stance=EvidenceStance.REFUTED,
211
+ subject=subject,
212
+ detail=detail,
213
+ reachable=True,
214
+ )
215
+
216
+ @classmethod
217
+ def no_signal(
218
+ cls,
219
+ source_name: str,
220
+ accountability: Accountability,
221
+ subject: str = "",
222
+ *,
223
+ detail: str = "",
224
+ ) -> "EvidenceFacts":
225
+ """The witness could not be reached/read, or has no record either way — the
226
+ honest floor (no source wired, auth failed, timeout, no such record).
227
+ `reachable=False`, stance NO_SIGNAL. What every failure in `gather_evidence`
228
+ degrades to, and what a consuming verdict reads as abstain — never a
229
+ fabricated attestation (the `run_judge` fail-safe-never-fail-open discipline).
230
+ """
231
+ return cls(
232
+ source_name=source_name,
233
+ accountability=accountability,
234
+ stance=EvidenceStance.NO_SIGNAL,
235
+ subject=subject,
236
+ detail=detail,
237
+ reachable=False,
238
+ )
239
+
240
+ @property
241
+ def is_attesting(self) -> bool:
242
+ """True iff this is a reached ATTESTED read — the precondition (not the whole
243
+ condition) for contributing belief. `believe_under_floor` ANDs this with the
244
+ non-forgeable-accountability check; on its own it is necessary, not
245
+ sufficient."""
246
+ return self.reachable and self.stance is EvidenceStance.ATTESTED
247
+
248
+ def to_dict(self) -> dict:
249
+ return {
250
+ "source_name": self.source_name,
251
+ "accountability": self.accountability.value,
252
+ "stance": self.stance.value,
253
+ "subject": self.subject,
254
+ "detail": self.detail,
255
+ "reachable": self.reachable,
256
+ }
257
+
258
+
259
+ @runtime_checkable
260
+ class EvidenceSource(Protocol):
261
+ """The contract a backend implements to add a witness.
262
+
263
+ `name` is the token a resolver selects and `dos doctor` would list.
264
+ `accountability` is the source's declared spectrum rung — a CLASS-LEVEL property,
265
+ fixed by the backend, not chosen per call (an `os_acceptance` source is
266
+ `OS_RECORDED` always; it has no honest path to a higher rung; a `paste_receipt`
267
+ source is `AGENT_AUTHORED` always and can never attest belief). `gather` is handed
268
+ a `subject` (the opaque correlation handle — the source decides what it means) and
269
+ the active `config` (read-only), and returns `EvidenceFacts`.
270
+
271
+ A backend MAY do I/O *inside* `gather` (run a command, call a provider API, read a
272
+ TEE quote) — unlike a predicate or renderer, which are pure. That is exactly why a
273
+ real backend lives in a driver, outside the kernel boundary: this seam is where
274
+ I/O surface is allowed, the same latitude the `Judge` / `LogSource` protocols give.
275
+ The discipline that keeps it honest is not purity but **fail-safe** (enforced by
276
+ `gather_evidence`, below, not by trusting the backend) plus the **fixed
277
+ accountability tag** (a backend cannot lie its way up the spectrum at call time)
278
+ plus the **floor discipline** (`believe_under_floor` — a forgeable-floor source's
279
+ attestation can never, by itself, move `verify` to belief).
280
+ """
281
+
282
+ name: str
283
+ accountability: Accountability
284
+
285
+ def gather(self, subject: str, config: object) -> EvidenceFacts:
286
+ ...
287
+
288
+
289
+ class NullEvidenceSource:
290
+ """The built-in, always-available source: it witnesses nothing.
291
+
292
+ The evidence analogue of `NullLogSource` / `AbstainJudge` — a trusted,
293
+ unshadowable fallback (`resolve_evidence_source` resolves built-ins first) and the
294
+ honest zero of the seam: a deployment with NO witness wired still has a resolvable
295
+ source, and it returns `no_signal` for every subject. A device with no git and no
296
+ network resolves to {this} only, so `verify` honestly abstains (`via none`) rather
297
+ than inventing a witness.
298
+
299
+ Tagged `AGENT_AUTHORED` — the floor — so that even the *absence* of a real source
300
+ can never be mistaken for a trustworthy rung: the most a missing witness can claim
301
+ is the least-trusted tag, and it is unreachable on top of that. It is doubly
302
+ incapable of granting belief (forgeable rung AND never reachable).
303
+ """
304
+
305
+ name = "null"
306
+ accountability = Accountability.AGENT_AUTHORED
307
+
308
+ def gather(self, subject: str, config: object) -> EvidenceFacts:
309
+ return EvidenceFacts.no_signal(
310
+ self.name,
311
+ self.accountability,
312
+ subject,
313
+ detail=(
314
+ "no evidence source wired — the built-in null source witnesses "
315
+ "nothing, so this effect has no signal (configure a "
316
+ "dos.evidence_sources backend)."
317
+ ),
318
+ )
319
+
320
+
321
+ def gather_evidence(source: EvidenceSource, subject: str, config: object) -> EvidenceFacts:
322
+ """Run one source against one subject, enforcing **fail-safe, never fail-open**.
323
+
324
+ The wrapper EVERY consumer should call instead of `source.gather(...)` directly —
325
+ what makes "a backend can never manufacture an attestation by failing" structural
326
+ rather than hoped-for (the `run_judge` / `gather_log` discipline, restated for
327
+ witnesses):
328
+
329
+ * a source that **raises** (command missing, API timeout, a bug) → an
330
+ unreachable `no_signal` naming the failure. Never propagates; never a
331
+ reachable read; never an ATTESTED.
332
+ * a source that returns **anything that is not `EvidenceFacts`** (None, a dict,
333
+ a bare bool, a duck-typed look-alike) → `no_signal`. We never read a foreign
334
+ object's `.stance`/`.reachable`, so no fabricated attestation can sneak through
335
+ a wrong return type.
336
+
337
+ The degrade preserves the source's declared `accountability` (read defensively via
338
+ `getattr`, defaulting to the forgeable floor) so a consumer still routes correctly
339
+ on failure AND a malformed source object cannot escape to a higher rung via the
340
+ failure path. The safe failure is "no signal" (abstain), never "attest" and never
341
+ "refute" — an evidence gatherer that cannot read produces NO_SIGNAL, the same
342
+ direction `gather_log` takes (evidence-gathering, not a safety gate).
343
+ """
344
+ name = getattr(source, "name", type(source).__name__)
345
+ acct = getattr(source, "accountability", Accountability.AGENT_AUTHORED)
346
+ if not isinstance(acct, Accountability):
347
+ acct = Accountability.AGENT_AUTHORED
348
+ try:
349
+ facts = source.gather(subject, config)
350
+ except Exception as e: # fail-safe: a source that raises produces no signal
351
+ return EvidenceFacts.no_signal(
352
+ str(name),
353
+ acct,
354
+ subject,
355
+ detail=(
356
+ f"evidence source {name!r} raised ({e!r}) — no signal (a witness that "
357
+ f"cannot read produces NO_SIGNAL, never a fabricated attestation)."
358
+ ),
359
+ )
360
+ if not isinstance(facts, EvidenceFacts):
361
+ return EvidenceFacts.no_signal(
362
+ str(name),
363
+ acct,
364
+ subject,
365
+ detail=(
366
+ f"evidence source {name!r} returned a {type(facts).__name__}, not "
367
+ f"EvidenceFacts — no signal (a source that does not return the evidence "
368
+ f"type cannot be trusted to have witnessed anything)."
369
+ ),
370
+ )
371
+ return facts
372
+
373
+
374
+ # ---------------------------------------------------------------------------
375
+ # The floor discipline — `believe ⟺ a non-forgeable source attests`.
376
+ # The dual of `overlap_policy.admissible_under_floor`: a structural guarantee
377
+ # that no forgeable-floor source can manufacture belief.
378
+ # ---------------------------------------------------------------------------
379
+
380
+
381
+ @dataclass(frozen=True)
382
+ class BeliefVerdict:
383
+ """The folded answer over a set of gathered `EvidenceFacts` for one effect.
384
+
385
+ `believe` is the positive bit `verify` may consume — but it is True ONLY when at
386
+ least one NON-FORGEABLE source attested (the floor discipline). `refuted` is
387
+ surfaced separately because a refutation by an accountable witness is a distinct,
388
+ stronger signal than mere absence of belief — a consumer may redden on it.
389
+ `attesting` / `refuting` / `silent` name the sources behind the verdict (legible
390
+ distrust — not just "believed" but *which witness* attested, the RND renderer
391
+ seam). `to_dict()` is the JSON shape for `--json` / MCP / the decisions queue.
392
+ """
393
+
394
+ believe: bool
395
+ refuted: bool
396
+ reason: str
397
+ attesting: tuple[str, ...] = ()
398
+ refuting: tuple[str, ...] = ()
399
+ silent: tuple[str, ...] = ()
400
+
401
+ def to_dict(self) -> dict:
402
+ return {
403
+ "believe": self.believe,
404
+ "refuted": self.refuted,
405
+ "reason": self.reason,
406
+ "attesting": list(self.attesting),
407
+ "refuting": list(self.refuting),
408
+ "silent": list(self.silent),
409
+ }
410
+
411
+
412
+ def believe_under_floor(facts: "tuple[EvidenceFacts, ...] | list[EvidenceFacts]") -> BeliefVerdict:
413
+ """Fold gathered facts into a belief verdict, enforcing the floor discipline.
414
+
415
+ The security-load-bearing function — the dual of
416
+ `overlap_policy.admissible_under_floor`. It reads the gathered witnesses and
417
+ answers the only question `verify` cares about: *may we BELIEVE this effect
418
+ happened?* The rule is structural, not a threshold a host can loosen:
419
+
420
+ > believe ⟺ at least one source whose `accountability` is NON-FORGEABLE
421
+ > (`OS_RECORDED` / `THIRD_PARTY`) was reached and ATTESTED.
422
+
423
+ So a forgeable-floor source (`AGENT_AUTHORED` — a pasted receipt, the agent's own
424
+ stdout, an mtime) is *structurally incapable* of granting belief: its ATTESTED
425
+ facts are recorded in `attesting` and shown, but they are filtered out of the
426
+ belief decision by the accountability check. The worst a buggy/hostile/lying
427
+ AGENT_AUTHORED source can do is claim an attestation that is then **ignored for
428
+ belief** (a visible, safe-direction no-op), never manufacture a SHIPPED verdict.
429
+
430
+ A REFUTED by an accountable witness sets `refuted=True` (a consumer may redden);
431
+ a REFUTED by a forgeable source is recorded but, symmetrically, does not by itself
432
+ establish refutation (the floor cuts both ways — a forgeable source is too weak to
433
+ *redden* `verify` on its own, just as it is too weak to greenlight it). Belief and
434
+ refutation are independent: a population can attest (one accountable source) AND
435
+ refute (another) at once, which a consumer routes to a human as a conflict.
436
+
437
+ PURE — no I/O. The facts were gathered at the boundary; this only folds them.
438
+ """
439
+ attesting: list[str] = []
440
+ refuting: list[str] = []
441
+ silent: list[str] = []
442
+ believe = False
443
+ refuted = False
444
+
445
+ for f in facts:
446
+ non_forgeable = not f.accountability.is_agent_authored
447
+ if f.reachable and f.stance is EvidenceStance.ATTESTED:
448
+ attesting.append(f.source_name)
449
+ if non_forgeable:
450
+ believe = True
451
+ elif f.reachable and f.stance is EvidenceStance.REFUTED:
452
+ refuting.append(f.source_name)
453
+ if non_forgeable:
454
+ refuted = True
455
+ else:
456
+ silent.append(f.source_name)
457
+
458
+ if believe and refuted:
459
+ reason = (
460
+ f"CONFLICT — accountable witnesses disagree: {', '.join(attesting)} attest, "
461
+ f"{', '.join(refuting)} refute (route to a human)"
462
+ )
463
+ elif believe:
464
+ reason = f"believed — non-forgeable witness attested: {', '.join(attesting)}"
465
+ elif refuted:
466
+ reason = f"refuted — non-forgeable witness disconfirmed: {', '.join(refuting)}"
467
+ elif attesting:
468
+ # Something attested, but only on the forgeable floor — the floor discipline
469
+ # withholds belief. Name it so the operator sees WHY a present attestation did
470
+ # not count.
471
+ reason = (
472
+ f"abstain — only forgeable-floor (AGENT_AUTHORED) sources attested "
473
+ f"({', '.join(attesting)}); no accountable witness — verify cannot believe"
474
+ )
475
+ else:
476
+ reason = "abstain — no witness reached this effect (no signal)"
477
+
478
+ return BeliefVerdict(
479
+ believe=believe,
480
+ refuted=refuted,
481
+ reason=reason,
482
+ attesting=tuple(attesting),
483
+ refuting=tuple(refuting),
484
+ silent=tuple(silent),
485
+ )
486
+
487
+
488
+ # ---------------------------------------------------------------------------
489
+ # The derived-witness primitive — the floor discipline lifted to a DERIVATION.
490
+ # (docs/156 — the byte-inequality axiom, docs/141, moved up one level: a value
491
+ # COMPUTED from operands is only as non-forgeable as BOTH its operands AND its
492
+ # recorded operation. Closes the grounded-RAG adoption's one soundness hole — a
493
+ # host that brute-forced agent-SELECTED arithmetic onto the THIRD_PARTY rung.)
494
+ # ---------------------------------------------------------------------------
495
+
496
+ # The accountability spectrum ordered weakest→strongest, so a derivation can be
497
+ # capped at the MINIMUM rung among its operands (you cannot derive a stronger fact
498
+ # than your weakest input — the "ceiling fixed by the source" rule, made inductive).
499
+ _RUNG_ORDER: dict[Accountability, int] = {
500
+ Accountability.AGENT_AUTHORED: 0,
501
+ Accountability.OS_RECORDED: 1,
502
+ Accountability.THIRD_PARTY: 2,
503
+ }
504
+
505
+
506
+ def _operand_rung(operand: "EvidenceFacts | BeliefVerdict") -> "Accountability | None":
507
+ """The non-forgeable rung an operand was witnessed at, or None if it is not a
508
+ reached non-forgeable attestation. A `BeliefVerdict` operand counts iff it
509
+ `believe`s (which `believe_under_floor` only grants on a non-forgeable attest, so
510
+ a believed verdict is THIRD_PARTY-equivalent — the strongest the floor mints). An
511
+ `EvidenceFacts` operand counts iff it `is_attesting` on a non-forgeable rung."""
512
+ if isinstance(operand, BeliefVerdict):
513
+ # A believed verdict already passed the floor: a non-forgeable witness attested.
514
+ # It carries no single rung, so treat it as the floor's own guarantee (THIRD_PARTY).
515
+ return Accountability.THIRD_PARTY if (operand.believe and not operand.refuted) else None
516
+ if isinstance(operand, EvidenceFacts):
517
+ if operand.is_attesting and not operand.accountability.is_agent_authored:
518
+ return operand.accountability
519
+ return None
520
+ return None
521
+
522
+
523
+ def derived_witness(
524
+ source_name: str,
525
+ op: str,
526
+ operands: "tuple[EvidenceFacts | BeliefVerdict, ...] | list[EvidenceFacts | BeliefVerdict]",
527
+ *,
528
+ subject: str,
529
+ within_tol: bool,
530
+ detail: str = "",
531
+ ) -> EvidenceFacts:
532
+ """Mint an `EvidenceFacts` for a value the agent COMPUTED from operands, on a
533
+ non-forgeable rung ONLY when the derivation is honest by construction.
534
+
535
+ The dual of `believe_under_floor`, lifted from a witnessed effect to a *derivation*
536
+ (docs/156 §3). The security-load-bearing rule — structural, not a host knob:
537
+
538
+ > A derived value may be witnessed on a NON-FORGEABLE rung IFF
539
+ > (1) the operation `op` is a DECLARED token (passed in by the caller — never
540
+ > reverse-searched to fit the answer; a brute-force "does this equal SOME
541
+ > operand pairing?" search IS the agent-selection that forges the rung, and
542
+ > this helper refuses to express it — the caller must commit to one op), AND
543
+ > (2) EVERY operand was itself attested by a non-forgeable witness, AND
544
+ > (3) the recomputation of `op` over the operands matches the claim (`within_tol`).
545
+
546
+ Failure modes, in the safe direction:
547
+
548
+ - Any operand unwitnessed / forgeable → the derived fact degrades to
549
+ **AGENT_AUTHORED** (recorded, advisory, structurally incapable of granting belief
550
+ under `believe_under_floor`). You CANNOT reach a non-forgeable rung without
551
+ non-forgeable operands — the laundering the grounded-RAG host did (tagging
552
+ agent-selected arithmetic `THIRD_PARTY`) becomes impossible.
553
+ - `op` empty/missing → AGENT_AUTHORED (an undeclared op is a post-hoc fit).
554
+ - `within_tol=False` → **refute** (a positive disconfirmation, distinct from "could
555
+ not tell" — the recomputation was done and it disagreed).
556
+
557
+ The result's accountability is the **minimum rung** among the operands (the weakest
558
+ operand caps the derivation). PURE — no I/O; the operands were witnessed at the
559
+ boundary and the recomputation was done by the caller (it passes the verdict in via
560
+ `within_tol`); this only folds rung + op-declaration into the honest tag.
561
+ """
562
+ rungs = [_operand_rung(o) for o in operands]
563
+ op_declared = bool(op and op.strip())
564
+ all_non_forgeable = bool(operands) and all(r is not None for r in rungs)
565
+
566
+ if not within_tol:
567
+ # The recomputation disagreed — a refutation. Rung still capped honestly: a
568
+ # refutation from forgeable operands is weaker, but a disagreement is a
569
+ # disagreement; tag it at the min available rung (AGENT_AUTHORED if any operand
570
+ # is forgeable, so a forgeable refute cannot, by the floor, redden on its own).
571
+ rung = _min_rung(rungs)
572
+ return EvidenceFacts.refute(
573
+ source_name, rung, subject,
574
+ detail=detail or f"derived op={op or '(undeclared)'} recomputation disagrees",
575
+ )
576
+
577
+ if op_declared and all_non_forgeable:
578
+ rung = _min_rung(rungs)
579
+ return EvidenceFacts.attest(
580
+ source_name, rung, subject,
581
+ detail=detail or f"derived op={op} from {len(operands)} non-forgeable operand(s)",
582
+ )
583
+
584
+ # Honest degrade: the derivation is recorded but cannot reach a non-forgeable rung
585
+ # (undeclared op, or an operand the agent could have authored). AGENT_AUTHORED so
586
+ # the floor treats it as advisory — never a forged THIRD_PARTY.
587
+ why = (
588
+ "undeclared operation (post-hoc fit)" if not op_declared
589
+ else "an operand lacks a non-forgeable witness"
590
+ )
591
+ return EvidenceFacts.attest(
592
+ source_name, Accountability.AGENT_AUTHORED, subject,
593
+ detail=detail or f"derived op={op or '(undeclared)'} — advisory only: {why}",
594
+ )
595
+
596
+
597
+ def _min_rung(rungs: "list[Accountability | None]") -> Accountability:
598
+ """The weakest non-None rung among operands, or AGENT_AUTHORED if any is None/empty
599
+ (a missing operand witness caps the whole derivation at the forgeable floor)."""
600
+ present = [r for r in rungs if r is not None]
601
+ if not present or len(present) != len(rungs):
602
+ return Accountability.AGENT_AUTHORED
603
+ return min(present, key=lambda r: _RUNG_ORDER[r])
604
+
605
+
606
+ # ---------------------------------------------------------------------------
607
+ # Resolution — built-in first, then the `dos.evidence_sources` entry-point group.
608
+ # (The `resolve_judge` / `resolve_log_source` discipline, verbatim.)
609
+ # ---------------------------------------------------------------------------
610
+
611
+ # The entry-point group a workspace/researcher registers a witness backend under.
612
+ EVIDENCE_SOURCE_ENTRY_POINT_GROUP = "dos.evidence_sources"
613
+
614
+ # The built-in sources, resolvable by name and UNSHADOWABLE by a plugin (a plugin
615
+ # registering `null` cannot displace this one — built-ins resolve first). Only the
616
+ # conservative `null` baseline ships in the kernel; every witnessing backend lives in
617
+ # a driver/plugin (the kernel has no I/O/provider surface).
618
+ _BUILT_IN_SOURCES: dict[str, type] = {
619
+ NullEvidenceSource.name: NullEvidenceSource,
620
+ }
621
+
622
+
623
+ def _discover_entry_point_sources(*, _stderr=None) -> list[tuple[str, EvidenceSource]]:
624
+ """Find witness backends registered under the `dos.evidence_sources` group.
625
+
626
+ A backend plugin registers ``name = "pkg.module:SourceClass"`` in its
627
+ ``[project.entry-points."dos.evidence_sources"]``. We load each, instantiate it if
628
+ it is a class, and return ``(entry_point_name, source)`` pairs sorted by name
629
+ (stable, deterministic listing). A plugin that fails to load is skipped with a
630
+ one-line stderr note rather than crashing — the same posture judge / log-source /
631
+ predicate / renderer discovery take (a broken third-party plugin is the operator's
632
+ to fix, not a kernel fault).
633
+ """
634
+ stderr = _stderr if _stderr is not None else sys.stderr
635
+ out: list[tuple[str, EvidenceSource]] = []
636
+ try:
637
+ from importlib.metadata import entry_points
638
+ except Exception: # pragma: no cover - importlib.metadata always present py3.11+
639
+ return out
640
+ try:
641
+ eps = entry_points(group=EVIDENCE_SOURCE_ENTRY_POINT_GROUP)
642
+ except TypeError: # pragma: no cover - py<3.10 selectable-API fallback
643
+ eps = entry_points().get(EVIDENCE_SOURCE_ENTRY_POINT_GROUP, []) # type: ignore[attr-defined]
644
+ except Exception: # pragma: no cover - defensive: never let discovery crash a call
645
+ return out
646
+ for ep in sorted(eps, key=lambda e: e.name):
647
+ try:
648
+ obj = ep.load()
649
+ source = obj() if isinstance(obj, type) else obj
650
+ except Exception as e: # pragma: no cover - depends on third-party plugin
651
+ print(
652
+ f"warning: evidence source plugin {ep.name!r} failed to load ({e}); skipping",
653
+ file=stderr,
654
+ )
655
+ continue
656
+ out.append((ep.name, source))
657
+ return out
658
+
659
+
660
+ def resolve_evidence_source(name: str, *, _stderr=None) -> EvidenceSource:
661
+ """Resolve a witness by name: built-ins first, then `dos.evidence_sources` plugins.
662
+
663
+ Built-ins (`null`) resolve FIRST and cannot be shadowed by a plugin of the same
664
+ name — the trusted-fallback guarantee, identical to `resolve_judge` /
665
+ `resolve_log_source`. An unknown name fails LOUD with the known list (it never
666
+ silently degrades to `null`, which would hide a typo'd source name): the caller
667
+ asked for a specific witness and getting a different one silently is exactly the
668
+ unannounced substitution the kernel refuses.
669
+ """
670
+ if name in _BUILT_IN_SOURCES:
671
+ return _BUILT_IN_SOURCES[name]()
672
+ discovered = dict(_discover_entry_point_sources(_stderr=_stderr))
673
+ if name in discovered:
674
+ return discovered[name]
675
+ known = sorted(set(_BUILT_IN_SOURCES) | set(discovered))
676
+ raise ValueError(f"unknown evidence source {name!r}; known: {', '.join(known)}")
677
+
678
+
679
+ def active_evidence_sources(*, _stderr=None) -> list[tuple[str, EvidenceSource]]:
680
+ """Every resolvable source as ``(name, source)`` — built-ins THEN discovered
681
+ plugins. Does ENTRY-POINT DISCOVERY (I/O), so it is a call-boundary helper, never
682
+ called inside a verdict (the `active_judges` / `active_log_sources` discipline)."""
683
+ built = [(n, cls()) for n, cls in _BUILT_IN_SOURCES.items()]
684
+ discovered = _discover_entry_point_sources(_stderr=_stderr)
685
+ return built + discovered
686
+
687
+
688
+ def active_evidence_source_names(*, _stderr=None) -> list[str]:
689
+ """The names of every active source (built-in + discovered) — what `dos doctor`
690
+ would list so an operator can see which witnesses are wired (the evidence analogue
691
+ of "see the active judges / log sources / predicates")."""
692
+ return [name for name, _src in active_evidence_sources(_stderr=_stderr)]