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.
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/interpret.py ADDED
@@ -0,0 +1,176 @@
1
+ """Agent-facing interpretation — one line of "what this verdict means for your
2
+ NEXT action," shared by every surface that speaks to an agent.
3
+
4
+ Why this module exists (the de-duplication that makes parity structural)
5
+ ========================================================================
6
+
7
+ A kernel verdict is deliberately terse: `{"shipped": false, "source": "none"}`,
8
+ `{"outcome": "refuse", ...}`. That is the right *machine* contract — a closed,
9
+ byte-faithful shape a pipe consumer can parse. But an LLM agent acts measurably
10
+ better on the *gloss* than on the bare dict: it does the right thing far more
11
+ often when told "treat this as NOT done; do NOT accept a worker's claim it
12
+ shipped without evidence" than when handed `{"shipped": false}` and left to
13
+ infer the discipline. The MCP server learned this first and grew an
14
+ `interpretation` field on every tool return. The `dos` CLI is the *more*-used
15
+ agent surface, though, and an agent shelling `dos verify --json` got only the
16
+ bare dict — the better intelligence lived behind the `[mcp]` extra, which is
17
+ backwards.
18
+
19
+ This module is that intelligence, lifted to ONE place both surfaces import:
20
+ the MCP tools (`dos_mcp.server`) and the CLI's opt-in `--explain` flag
21
+ (`dos verify --explain`, `dos arbitrate --explain`) both call the SAME function,
22
+ so they can never drift — the parity is structural, not a copy kept in sync by
23
+ hand. A `tests/test_interpret_parity.py` pins that the two surfaces emit
24
+ byte-identical interpretation strings for the same verdict.
25
+
26
+ Not every gloss has BOTH surfaces yet: `verify`/`arbitrate`/`check_reason` are
27
+ emitted by both the MCP tools and the CLI, and the parity is cross-tested.
28
+ `gate` is so far CLI-only (`dos gate --explain`) — there is no `dos_gate` MCP
29
+ tool — but it lives here, beside the others, so the gloss style stays consistent
30
+ and it is parity-ready the day a gate tool is added. (Same one-invariant either
31
+ way: pure presentation, downstream of an already-decided verdict.)
32
+
33
+ The one invariant (the renderer/Axis-4 rule, applied here)
34
+ ==========================================================
35
+
36
+ **An interpretation is PURE PRESENTATION, strictly downstream of an
37
+ already-decided verdict.** Each function takes the verdict's own `to_dict()`
38
+ (a plain dict) and returns a string. It receives no config, no leases, nothing
39
+ it could decide *with* — exactly the constraint `dos.render` puts on a renderer.
40
+ So the hint can never leak policy back into the adjudication: the worst a wrong
41
+ gloss can do is read awkwardly; it cannot mis-verify a ship or mis-admit a lease.
42
+ That is why this lives beside `render.py` (presentation seam, layer 3), not
43
+ inside a verdict module like `oracle.py` — the adjudication core stays
44
+ prose-free, and an agent-facing English sentence is held at the boundary.
45
+
46
+ These functions are byte-faithful lifts of the `_*_interpretation` helpers that
47
+ used to live in `dos_mcp.server`; the strings are unchanged so existing MCP
48
+ behavior is identical, only their home moved.
49
+ """
50
+
51
+ from __future__ import annotations
52
+
53
+
54
+ def verify(verdict: dict) -> str:
55
+ """One line on what a `verify` (ShipVerdict) result means for the next action.
56
+
57
+ Reads the verdict's `to_dict()` fields (`shipped`, `source`, `sha`). The
58
+ three branches mirror the three things a truth-syscall answer can be: a real
59
+ artefact-backed ship (rely on it), an honest no-evidence-either-way (treat as
60
+ not done, distrust the claim), and a checked-but-unshipped (not done yet).
61
+ """
62
+ shipped = verdict.get("shipped")
63
+ source = verdict.get("source", "")
64
+ if shipped:
65
+ where = {"registry": "a run-registry row", "grep": "a git commit"}.get(
66
+ source, "evidence")
67
+ sha = verdict.get("sha")
68
+ return (f"SHIPPED — confirmed by {where}"
69
+ + (f" ({sha})" if sha else "")
70
+ + ". You can rely on this; the evidence is real, not self-reported.")
71
+ if source == "none":
72
+ return ("NOT shipped — and there is NO positive evidence either way "
73
+ "(no registry row, no matching commit). Treat it as not done. "
74
+ "Do NOT accept a worker's claim that it shipped without evidence.")
75
+ return ("NOT shipped on the evidence checked. Treat it as not done until a "
76
+ "real commit or registry row appears.")
77
+
78
+
79
+ def arbitrate(decision: dict) -> str:
80
+ """One line on what an `arbitrate` (LaneDecision) result means for the next action.
81
+
82
+ Reads the decision's `to_dict()` fields (`outcome`, `lane`, `auto_picked`,
83
+ `free_clusters`). A GO names the (possibly auto-picked) lane and why
84
+ concurrency is safe; a STOP says don't start and lists any free lane to take
85
+ instead.
86
+ """
87
+ if decision.get("outcome") == "acquire":
88
+ lane = decision.get("lane", "")
89
+ picked = " (auto-picked for you)" if decision.get("auto_picked") else ""
90
+ return (f"GO — you may take lane {lane!r}{picked}. Its file tree is "
91
+ f"disjoint from every live lease, so concurrent work is safe.")
92
+ free = decision.get("free_clusters") or []
93
+ tail = (f" Free lanes you could take instead: {', '.join(free)}."
94
+ if free else " No free lane is available right now — wait or retry.")
95
+ return ("STOP — do not start this work. Taking this lane would collide with a "
96
+ "live lease (or it is exclusive/held)." + tail)
97
+
98
+
99
+ def gate(result: dict) -> str:
100
+ """One line on what a `gate` (empty-packet) verdict means for the loop's next step.
101
+
102
+ Reads the `dos gate` result fields (`verdict`, `reason`). The five verdicts
103
+ map to the five things a /next-up packet can be — and, crucially, to whether
104
+ the dispatch loop should CONTINUE, REPLAN/STOP, SELF-HEAL, or RETRY. This
105
+ mirrors `gate_classify.gate_policy` (the pure policy matrix) in prose, so an
106
+ agent gating its empty case reads the same routing the loop would take.
107
+ """
108
+ verdict = str(result.get("verdict", "")).upper()
109
+ if verdict == "LIVE":
110
+ return ("LIVE — the packet has dispatchable work; CONTINUE dispatch. This "
111
+ "is the success case, not a stop.")
112
+ if verdict == "DRAIN":
113
+ return ("DRAIN — the backlog is genuinely empty. STOP (or /replan to "
114
+ "refill); a second consecutive DRAIN is the real drained-twice "
115
+ "stop. This is the only verdict that counts toward an early stop.")
116
+ if verdict == "STALE-STAMP":
117
+ return ("STALE-STAMP — work shipped in git but the plan rows weren't "
118
+ "stamped, so it only LOOKS drained. Do NOT treat as done-and-empty: "
119
+ "reconcile the stamps and re-dispatch. Never counts toward "
120
+ "drained-twice.")
121
+ if verdict == "BLOCKED":
122
+ return ("BLOCKED — picks exist but a sibling claim / quota blocks them. Do "
123
+ "NOT loop unattended; surface it for the operator (or /replan). "
124
+ "Never counts toward drained-twice.")
125
+ if verdict == "RACE":
126
+ return ("RACE — you lost a candidates-cache lock; the on-disk packet is "
127
+ "wrong-scope. Do NOT read it as a real DRAIN/BLOCKED — sleep "
128
+ "briefly and retry once; the foreign holder will emit the intended "
129
+ "packet. Never counts toward drained-twice.")
130
+ return ("Unrecognised gate verdict — treat conservatively as NOT a clean LIVE; "
131
+ "do not continue dispatch on it without checking the reason.")
132
+
133
+
134
+ def check_reason(out: dict) -> str:
135
+ """One line on whether a reason token is safe to emit.
136
+
137
+ Reads the `dos_check_reason` / `dos check-reason` result fields (`known`,
138
+ `refusal`). A known reason is safe to emit (the oracle can verify the
139
+ condition it names); an unknown one is `UNCLASSIFIED` prose-drift the kernel
140
+ exists to kill, so it must not be emitted.
141
+ """
142
+ if out.get("known"):
143
+ kind = "a refusal (route to replan)" if out.get("refusal") else "advisory-only"
144
+ return (f"VALID reason — {kind}. Safe to emit; the oracle can verify the "
145
+ f"condition it names.")
146
+ return ("UNKNOWN reason — this token is NOT in the closed vocabulary, so it is "
147
+ "UNCLASSIFIED drift. Do NOT emit it. Pick a real reason from "
148
+ "`dos_refuse_reasons`, or have the workspace declare this one in "
149
+ "dos.toml [reasons] first.")
150
+
151
+
152
+ def commit_audit(verdict: dict) -> str:
153
+ """One line on what a `commit-audit` (ClaimVerdict) result means for the next action.
154
+
155
+ Reads the verdict's `to_dict()` fields (`verdict`, `witness`, `reason`). The
156
+ three branches mirror the three things a claim-vs-diff grade can be: a claim
157
+ its own diff contradicts (fix it before reporting done), a claim the diff
158
+ witnesses (rely on the rung, but note presence ≠ correctness), and no
159
+ checkable claim (nothing to act on). Author-neutral — the same gloss whether a
160
+ human or an agent wrote the commit.
161
+ """
162
+ v = str(verdict.get("verdict", "")).upper()
163
+ if v == "CLAIM_UNWITNESSED":
164
+ why = verdict.get("reason", "")
165
+ return ("CLAIM UNWITNESSED — this commit's message claims something its own "
166
+ "diff does not show" + (f" ({why})" if why else "") + ". Before you "
167
+ "report this as done, either make the change the message claims or "
168
+ "rewrite the message to match what the diff actually did. (This grades "
169
+ "did-it-do-the-kind-of-thing-claimed, not whether the code is correct.)")
170
+ if v == "OK":
171
+ return ("WITNESSED — the diff does the KIND of thing the message claims "
172
+ f"(rung: {verdict.get('witness', '')}). This is NOT a correctness "
173
+ "check (a wrong-but-real change still passes); it only confirms the "
174
+ "claim isn't empty. Run the tests for correctness.")
175
+ return ("NO CHECKABLE CLAIM — the subject makes no concrete code/test claim to "
176
+ "verify against the diff (e.g. wip/merge/chore). Nothing to act on here.")