dsh-openwrite 0.2.8

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 (275) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +107 -0
  3. package/THIRD_PARTY_NOTICES.md +33 -0
  4. package/assets/logo-dark.svg +31 -0
  5. package/assets/logo-light.svg +31 -0
  6. package/cordis.patch.yml +11 -0
  7. package/docs/BENCHMARK_TASKS.md +54 -0
  8. package/docs/COST_MEASUREMENT.md +39 -0
  9. package/docs/DEVELOPMENT.md +65 -0
  10. package/docs/DSH_STORE.md +58 -0
  11. package/docs/FRAMEWORK_ADVANTAGES.md +288 -0
  12. package/docs/IMPROVEMENT_PLAN.md +252 -0
  13. package/docs/INSTALL.md +99 -0
  14. package/docs/LEARNING.md +68 -0
  15. package/docs/OPEN_SOURCE_NOVEL_AUDIT.md +191 -0
  16. package/docs/PLUGIN_MAINTENANCE.md +54 -0
  17. package/docs/PLUGIN_MAINTENANCE_RC7.md +157 -0
  18. package/docs/QA_20260908.md +103 -0
  19. package/docs/QA_20260909_BENCHMARK.md +24 -0
  20. package/docs/RELEASE_ACCEPTANCE.md +116 -0
  21. package/docs/REVIEW_DAG_FRAMEWORK.md +82 -0
  22. package/docs/TARGETED_NOVEL_PROJECT_REVIEW.md +167 -0
  23. package/docs/WORKFLOWS.md +74 -0
  24. package/docs/WORKSPACE_CONTEXT_CONTRACT.md +125 -0
  25. package/docs/WORKSPACE_INTEGRATION_GOAL.md +278 -0
  26. package/docs/research/autosave-race-repro.mjs +133 -0
  27. package/docs/research/framework-stats-2026-09-05.json +116 -0
  28. package/dog-tools.mjs +11 -0
  29. package/package.json +132 -0
  30. package/packages/openwrite-bridge/LICENSE +201 -0
  31. package/packages/openwrite-bridge/cordis.patch.yml +10 -0
  32. package/packages/openwrite-bridge/lib/client.d.ts +95 -0
  33. package/packages/openwrite-bridge/lib/client.js +193 -0
  34. package/packages/openwrite-bridge/lib/contracts-generated.d.ts +367 -0
  35. package/packages/openwrite-bridge/lib/contracts-generated.js +1764 -0
  36. package/packages/openwrite-bridge/lib/dog-delivery.d.ts +12 -0
  37. package/packages/openwrite-bridge/lib/dog-delivery.js +362 -0
  38. package/packages/openwrite-bridge/lib/dog-review.d.ts +50 -0
  39. package/packages/openwrite-bridge/lib/dog-review.js +470 -0
  40. package/packages/openwrite-bridge/lib/domain.d.ts +70 -0
  41. package/packages/openwrite-bridge/lib/domain.js +496 -0
  42. package/packages/openwrite-bridge/lib/index.d.ts +17 -0
  43. package/packages/openwrite-bridge/lib/index.js +89 -0
  44. package/packages/openwrite-bridge/lib/managed-runtime.d.ts +95 -0
  45. package/packages/openwrite-bridge/lib/managed-runtime.js +510 -0
  46. package/packages/openwrite-bridge/lib/preset-tools.d.ts +13 -0
  47. package/packages/openwrite-bridge/lib/preset-tools.js +18 -0
  48. package/packages/openwrite-bridge/lib/tool-policy.d.ts +6 -0
  49. package/packages/openwrite-bridge/lib/tool-policy.js +56 -0
  50. package/packages/openwrite-bridge/lib/tools.d.ts +24 -0
  51. package/packages/openwrite-bridge/lib/tools.js +2404 -0
  52. package/packages/openwrite-bridge/package.json +67 -0
  53. package/packages/studio-panel/LICENSE +21 -0
  54. package/packages/studio-panel/README.md +51 -0
  55. package/packages/studio-panel/cordis.patch.yml +5 -0
  56. package/packages/studio-panel/lib/client.js +158087 -0
  57. package/packages/studio-panel/lib/client.js.map +1 -0
  58. package/packages/studio-panel/lib/index.js +50 -0
  59. package/packages/studio-panel/lib/types/client/AssetEditor.d.ts +122 -0
  60. package/packages/studio-panel/lib/types/client/AssetsView.d.ts +43 -0
  61. package/packages/studio-panel/lib/types/client/BenchmarkView.d.ts +9 -0
  62. package/packages/studio-panel/lib/types/client/ContinuousReader.d.ts +13 -0
  63. package/packages/studio-panel/lib/types/client/CreationView.d.ts +6 -0
  64. package/packages/studio-panel/lib/types/client/DagCanvas.d.ts +11 -0
  65. package/packages/studio-panel/lib/types/client/DiscardDraftDialog.d.ts +8 -0
  66. package/packages/studio-panel/lib/types/client/DomainToolCard.d.ts +9 -0
  67. package/packages/studio-panel/lib/types/client/GraphView.d.ts +46 -0
  68. package/packages/studio-panel/lib/types/client/HeaderChrome.d.ts +18 -0
  69. package/packages/studio-panel/lib/types/client/LaunchOpenWrite.d.ts +13 -0
  70. package/packages/studio-panel/lib/types/client/LibraryView.d.ts +6 -0
  71. package/packages/studio-panel/lib/types/client/MarkdownText.d.ts +3 -0
  72. package/packages/studio-panel/lib/types/client/ModelView.d.ts +9 -0
  73. package/packages/studio-panel/lib/types/client/OperationsView.d.ts +6 -0
  74. package/packages/studio-panel/lib/types/client/OutlinePlans.d.ts +37 -0
  75. package/packages/studio-panel/lib/types/client/OutlineView.d.ts +29 -0
  76. package/packages/studio-panel/lib/types/client/ResearchView.d.ts +7 -0
  77. package/packages/studio-panel/lib/types/client/ReviewCard.d.ts +28 -0
  78. package/packages/studio-panel/lib/types/client/SceneWorkbench.d.ts +55 -0
  79. package/packages/studio-panel/lib/types/client/SearchView.d.ts +33 -0
  80. package/packages/studio-panel/lib/types/client/TasksView.d.ts +11 -0
  81. package/packages/studio-panel/lib/types/client/TransferWorkspaces.d.ts +19 -0
  82. package/packages/studio-panel/lib/types/client/TurnMutationSummary.d.ts +62 -0
  83. package/packages/studio-panel/lib/types/client/VditorBody.d.ts +55 -0
  84. package/packages/studio-panel/lib/types/client/WorkbenchStore.d.ts +121 -0
  85. package/packages/studio-panel/lib/types/client/api.d.ts +72 -0
  86. package/packages/studio-panel/lib/types/client/asset-drafts.d.ts +20 -0
  87. package/packages/studio-panel/lib/types/client/benchmark-options.d.ts +43 -0
  88. package/packages/studio-panel/lib/types/client/draft-store.d.ts +26 -0
  89. package/packages/studio-panel/lib/types/client/dto.d.ts +517 -0
  90. package/packages/studio-panel/lib/types/client/index.d.ts +4 -0
  91. package/packages/studio-panel/lib/types/client/locales.d.ts +15 -0
  92. package/packages/studio-panel/lib/types/client/manuscript-annotations.d.ts +59 -0
  93. package/packages/studio-panel/lib/types/client/manuscript-markers.d.ts +61 -0
  94. package/packages/studio-panel/lib/types/client/manuscript-mentions.d.ts +30 -0
  95. package/packages/studio-panel/lib/types/client/manuscript-overlay-dom.d.ts +7 -0
  96. package/packages/studio-panel/lib/types/client/manuscript-overlay.d.ts +42 -0
  97. package/packages/studio-panel/lib/types/client/manuscript-selection.d.ts +59 -0
  98. package/packages/studio-panel/lib/types/client/model-view-memory.d.ts +17 -0
  99. package/packages/studio-panel/lib/types/client/storage.d.ts +8 -0
  100. package/packages/studio-panel/lib/types/client/workbench-epochs.d.ts +16 -0
  101. package/packages/studio-panel/lib/types/client/workspace-context.d.ts +52 -0
  102. package/packages/studio-panel/lib/types/client/writing-scope.d.ts +7 -0
  103. package/packages/studio-panel/lib/types/index.d.ts +5 -0
  104. package/packages/studio-panel/package.json +105 -0
  105. package/packages/studio-panel/vendor/vditor/LICENSE +21 -0
  106. package/packages/studio-panel/vendor/vditor/dist/css/content-theme/dark.css +123 -0
  107. package/packages/studio-panel/vendor/vditor/dist/css/content-theme/light.css +101 -0
  108. package/packages/studio-panel/vendor/vditor/dist/index.css +1823 -0
  109. package/packages/studio-panel/vendor/vditor/dist/index.min.js +1 -0
  110. package/packages/studio-panel/vendor/vditor/dist/js/i18n/zh_CN.js +86 -0
  111. package/packages/studio-panel/vendor/vditor/dist/js/icons/ant.js +174 -0
  112. package/packages/studio-panel/vendor/vditor/dist/js/lute/lute.min.js +72 -0
  113. package/plugin.d.ts +3 -0
  114. package/plugin.mjs +80 -0
  115. package/presets/README.md +32 -0
  116. package/presets/openwrite/agent.cordis.yml +317 -0
  117. package/presets/openwrite/preset.yml +3 -0
  118. package/presets/openwrite/skills/canon/SKILL.md +15 -0
  119. package/presets/openwrite/skills/dialoguequality/SKILL.md +166 -0
  120. package/presets/openwrite/skills/dog-delivery-query/SKILL.md +40 -0
  121. package/presets/openwrite/skills/dog-import-query/SKILL.md +27 -0
  122. package/presets/openwrite/skills/dog-review-query/SKILL.md +40 -0
  123. package/presets/openwrite/skills/export-book/SKILL.md +14 -0
  124. package/presets/openwrite/skills/foreshadow/SKILL.md +14 -0
  125. package/presets/openwrite/skills/foreshadowing-system/SKILL.md +125 -0
  126. package/presets/openwrite/skills/learn/SKILL.md +24 -0
  127. package/presets/openwrite/skills/novel-creator/SKILL.md +88 -0
  128. package/presets/openwrite/skills/novel-creator/templates/beat_templates.yaml +179 -0
  129. package/presets/openwrite/skills/novel-creator/templates/example_usage.yaml +74 -0
  130. package/presets/openwrite/skills/novel-reviewer/SKILL.md +85 -0
  131. package/presets/openwrite/skills/oh-story-deslop/LICENSE +21 -0
  132. package/presets/openwrite/skills/oh-story-deslop/SKILL.md +36 -0
  133. package/presets/openwrite/skills/oh-story-deslop/agents/openai.yaml +4 -0
  134. package/presets/openwrite/skills/oh-story-deslop/references/method.md +22 -0
  135. package/presets/openwrite/skills/oh-story-long-analyze/LICENSE +21 -0
  136. package/presets/openwrite/skills/oh-story-long-analyze/SKILL.md +37 -0
  137. package/presets/openwrite/skills/oh-story-long-analyze/agents/openai.yaml +4 -0
  138. package/presets/openwrite/skills/oh-story-long-analyze/references/method.md +22 -0
  139. package/presets/openwrite/skills/oh-story-long-scan/LICENSE +21 -0
  140. package/presets/openwrite/skills/oh-story-long-scan/SKILL.md +36 -0
  141. package/presets/openwrite/skills/oh-story-long-scan/agents/openai.yaml +4 -0
  142. package/presets/openwrite/skills/oh-story-long-scan/references/method.md +21 -0
  143. package/presets/openwrite/skills/oh-story-long-write/LICENSE +21 -0
  144. package/presets/openwrite/skills/oh-story-long-write/SKILL.md +37 -0
  145. package/presets/openwrite/skills/oh-story-long-write/agents/openai.yaml +4 -0
  146. package/presets/openwrite/skills/oh-story-long-write/references/method.md +33 -0
  147. package/presets/openwrite/skills/oh-story-review/LICENSE +21 -0
  148. package/presets/openwrite/skills/oh-story-review/SKILL.md +36 -0
  149. package/presets/openwrite/skills/oh-story-review/agents/openai.yaml +4 -0
  150. package/presets/openwrite/skills/oh-story-review/references/method.md +25 -0
  151. package/presets/openwrite/skills/progress/SKILL.md +16 -0
  152. package/presets/openwrite/skills/review-chapter/SKILL.md +17 -0
  153. package/presets/openwrite/skills/revise-span/SKILL.md +16 -0
  154. package/presets/openwrite/skills/style-system/SKILL.md +135 -0
  155. package/presets/openwrite/skills/style-system/prompts/analyze_style.md +214 -0
  156. package/presets/openwrite/skills/style-system/prompts/batch_extract_style.md +66 -0
  157. package/presets/openwrite/skills/style-system/prompts/compose_style.md +83 -0
  158. package/presets/openwrite/skills/style-system/prompts/extract_style.md +84 -0
  159. package/presets/openwrite/skills/style-system/prompts/initialize_style.md +52 -0
  160. package/presets/openwrite/skills/style-system/templates/analysis_report.yaml +78 -0
  161. package/presets/openwrite/skills/style-system/templates/composed_style.md +96 -0
  162. package/presets/openwrite/skills/style-system/templates/extraction_report.yaml +80 -0
  163. package/presets/openwrite/skills/style-system/templates/fingerprint.yaml +61 -0
  164. package/presets/openwrite/skills/style-system/tools/README.md +33 -0
  165. package/presets/openwrite/skills/truth-validation/SKILL.md +119 -0
  166. package/presets/openwrite/skills/workflow-manager/SKILL.md +81 -0
  167. package/presets/openwrite/skills/world-query/SKILL.md +45 -0
  168. package/presets/openwrite/skills/write-next/SKILL.md +17 -0
  169. package/release/core-requirements.in +12 -0
  170. package/release/licenses/@deepseek-ai__cosmokit@1.8.3/LICENSE +21 -0
  171. package/release/licenses/@deepseek-ai__schemastery@3.18.2/LICENSE +21 -0
  172. package/release/licenses/@isaacs__fs-minipass@4.0.1/LICENSE +15 -0
  173. package/release/licenses/@standard-schema__spec@1.1.0/LICENSE +21 -0
  174. package/release/licenses/@types__d3-color@3.1.3/LICENSE +21 -0
  175. package/release/licenses/@types__d3-drag@3.0.7/LICENSE +21 -0
  176. package/release/licenses/@types__d3-interpolate@3.0.4/LICENSE +21 -0
  177. package/release/licenses/@types__d3-selection@3.0.11/LICENSE +21 -0
  178. package/release/licenses/@types__d3-transition@3.0.9/LICENSE +21 -0
  179. package/release/licenses/@types__d3-zoom@3.0.8/LICENSE +21 -0
  180. package/release/licenses/@xyflow__react@12.11.6/LICENSE +21 -0
  181. package/release/licenses/@xyflow__system@0.0.82/LICENSE +21 -0
  182. package/release/licenses/ajv-formats@3.0.1/LICENSE +21 -0
  183. package/release/licenses/ajv@8.20.0/LICENSE +22 -0
  184. package/release/licenses/chownr@3.0.0/LICENSE.md +63 -0
  185. package/release/licenses/classcat@5.0.5/LICENSE.md +7 -0
  186. package/release/licenses/commander@7.2.0/LICENSE +22 -0
  187. package/release/licenses/d3-array@3.2.4/LICENSE +13 -0
  188. package/release/licenses/d3-axis@3.0.0/LICENSE +13 -0
  189. package/release/licenses/d3-brush@3.0.0/LICENSE +13 -0
  190. package/release/licenses/d3-chord@3.0.1/LICENSE +13 -0
  191. package/release/licenses/d3-color@3.1.0/LICENSE +13 -0
  192. package/release/licenses/d3-contour@4.0.2/LICENSE +13 -0
  193. package/release/licenses/d3-delaunay@6.0.4/LICENSE +14 -0
  194. package/release/licenses/d3-dispatch@3.0.1/LICENSE +13 -0
  195. package/release/licenses/d3-drag@3.0.0/LICENSE +13 -0
  196. package/release/licenses/d3-dsv@3.0.1/LICENSE +13 -0
  197. package/release/licenses/d3-ease@3.0.1/LICENSE +28 -0
  198. package/release/licenses/d3-fetch@3.0.1/LICENSE +13 -0
  199. package/release/licenses/d3-force@3.0.0/LICENSE +13 -0
  200. package/release/licenses/d3-format@3.1.2/LICENSE +13 -0
  201. package/release/licenses/d3-geo@3.1.1/LICENSE +34 -0
  202. package/release/licenses/d3-hierarchy@3.1.2/LICENSE +13 -0
  203. package/release/licenses/d3-interpolate@3.0.1/LICENSE +13 -0
  204. package/release/licenses/d3-path@3.1.0/LICENSE +13 -0
  205. package/release/licenses/d3-polygon@3.0.1/LICENSE +13 -0
  206. package/release/licenses/d3-quadtree@3.0.1/LICENSE +13 -0
  207. package/release/licenses/d3-random@3.0.1/LICENSE +13 -0
  208. package/release/licenses/d3-scale-chromatic@3.1.0/LICENSE +28 -0
  209. package/release/licenses/d3-scale@4.0.2/LICENSE +13 -0
  210. package/release/licenses/d3-selection@3.0.0/LICENSE +13 -0
  211. package/release/licenses/d3-shape@3.2.0/LICENSE +13 -0
  212. package/release/licenses/d3-time-format@4.1.0/LICENSE +13 -0
  213. package/release/licenses/d3-time@3.1.0/LICENSE +13 -0
  214. package/release/licenses/d3-timer@3.0.1/LICENSE +13 -0
  215. package/release/licenses/d3-transition@3.0.1/LICENSE +13 -0
  216. package/release/licenses/d3-zoom@3.0.0/LICENSE +13 -0
  217. package/release/licenses/d3@7.9.0/LICENSE +13 -0
  218. package/release/licenses/delaunator@5.1.0/LICENSE +15 -0
  219. package/release/licenses/elkjs@0.12.0/LICENSE.md +263 -0
  220. package/release/licenses/fast-deep-equal@3.1.3/LICENSE +21 -0
  221. package/release/licenses/fast-uri@3.1.7/LICENSE +30 -0
  222. package/release/licenses/fflate@0.8.2/LICENSE +21 -0
  223. package/release/licenses/graceful-fs@4.2.11/LICENSE +15 -0
  224. package/release/licenses/iconv-lite@0.6.3/LICENSE +21 -0
  225. package/release/licenses/internmap@2.0.3/LICENSE +13 -0
  226. package/release/licenses/json-schema-traverse@1.0.0/LICENSE +21 -0
  227. package/release/licenses/lucide-react@0.468.0/LICENSE +15 -0
  228. package/release/licenses/minipass@7.1.3/LICENSE.md +55 -0
  229. package/release/licenses/minizlib@3.1.0/LICENSE +26 -0
  230. package/release/licenses/proper-lockfile@4.1.2/LICENSE +21 -0
  231. package/release/licenses/require-from-string@2.0.2/license +21 -0
  232. package/release/licenses/retry@0.12.0/License +21 -0
  233. package/release/licenses/robust-predicates@3.0.3/LICENSE +24 -0
  234. package/release/licenses/rw@1.3.3/LICENSE +26 -0
  235. package/release/licenses/safer-buffer@2.1.2/LICENSE +21 -0
  236. package/release/licenses/signal-exit@3.0.7/LICENSE.txt +16 -0
  237. package/release/licenses/tar@7.5.7/LICENSE.md +55 -0
  238. package/release/licenses/use-sync-external-store@1.6.0/LICENSE +21 -0
  239. package/release/licenses/yallist@5.0.0/LICENSE.md +63 -0
  240. package/release/licenses/zustand@4.5.7/LICENSE +21 -0
  241. package/release/openwrite-5.8.1-py3-none-any.whl +0 -0
  242. package/release/platform-overrides.in +5 -0
  243. package/release/python-constraints.in +96 -0
  244. package/release/requirements.lock +2927 -0
  245. package/release/runtime-manifest.json +98 -0
  246. package/release/sdk-compatibility.json +240 -0
  247. package/release/source.json +859 -0
  248. package/release/wheels/cryptography-50.0.1-cp312-abi3-macosx_13_0_x86_64.whl +0 -0
  249. package/release/wheels/licenses/LICENSE.txt +177 -0
  250. package/release/wheels/provenance.json +15 -0
  251. package/scripts/dog/delivery-stage.js +32 -0
  252. package/scripts/dog/import-chapter.js +20 -0
  253. package/scripts/dog/import-record.js +35 -0
  254. package/scripts/dog/review-dimension.js +41 -0
  255. package/scripts/dog/review-record.js +42 -0
  256. package/scripts/maintenance.mjs +179 -0
  257. package/scripts/prepare.mjs +21 -0
  258. package/vendor/dsh-dog/LICENSE +29 -0
  259. package/vendor/dsh-dog/README.md +114 -0
  260. package/vendor/dsh-dog/UPSTREAM.md +22 -0
  261. package/vendor/dsh-dog/cordis.patch.yml +14 -0
  262. package/vendor/dsh-dog/lib/client.js +2898 -0
  263. package/vendor/dsh-dog/lib/client.js.map +1 -0
  264. package/vendor/dsh-dog/lib/core-BiEBMLz3.d.ts +495 -0
  265. package/vendor/dsh-dog/lib/core-DdfMcrB4.js +2074 -0
  266. package/vendor/dsh-dog/lib/core.d.ts +2 -0
  267. package/vendor/dsh-dog/lib/core.js +2 -0
  268. package/vendor/dsh-dog/lib/index.d.ts +133 -0
  269. package/vendor/dsh-dog/lib/index.js +967 -0
  270. package/vendor/dsh-dog/package.json +97 -0
  271. package/vendor/dsh-dog/schemas/schema-0.2/graph.schema.json +139 -0
  272. package/vendor/dsh-dog/schemas/schema-0.2/report.schema.json +87 -0
  273. package/vendor/dsh-dog/schemas/schema-0.2/run.schema.json +259 -0
  274. package/vendor/dsh-dog/schemas/schema-0.2/runtime-event.schema.json +105 -0
  275. package/vendor/dsh-dog/schemas/schema-0.2/verification.schema.json +40 -0
@@ -0,0 +1,967 @@
1
+ import { a as DogRepository, c as parseGraph, d as parseBoolExpr, i as runPlan, l as isJsonValue, n as resolveScriptPath, o as loadSchemaSet, r as WorkspaceManager, s as DogValidationError, t as DogEngine, u as evaluateBoolExpr } from "./core-DdfMcrB4.js";
2
+ import { spawn } from "node:child_process";
3
+ import { fileURLToPath } from "node:url";
4
+ import { dshHomePath } from "@deepseek-ai/dsh-home-paths";
5
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
6
+ import { isAbsolute, join } from "node:path";
7
+ import z from "@deepseek-ai/schemastery";
8
+ import { defineTool } from "@deepseek-ai/dsh-tools";
9
+ //#region src/owned-script.ts
10
+ /** Execute without blocking the host event loop; cancellation owns only this process tree. */
11
+ async function runOwnedScript(script, input, signal) {
12
+ signal?.throwIfAborted();
13
+ const js = /\.(?:c|m)?js$/.test(script);
14
+ const child = spawn(js ? process.execPath : script, js ? [script, input] : [input], {
15
+ detached: process.platform !== "win32",
16
+ windowsHide: true,
17
+ stdio: [
18
+ "ignore",
19
+ "pipe",
20
+ "pipe"
21
+ ]
22
+ });
23
+ let output = "";
24
+ let failure;
25
+ let escalation;
26
+ const stop = () => {
27
+ if (!child.pid || child.exitCode !== null || child.signalCode !== null) return;
28
+ if (process.platform === "win32") spawn("taskkill", [
29
+ "/pid",
30
+ String(child.pid),
31
+ "/T",
32
+ "/F"
33
+ ], {
34
+ windowsHide: true,
35
+ stdio: "ignore"
36
+ }).once("error", () => child.kill());
37
+ else {
38
+ try {
39
+ process.kill(-child.pid, "SIGTERM");
40
+ } catch {
41
+ child.kill();
42
+ }
43
+ escalation ??= setTimeout(() => {
44
+ if (child.exitCode !== null || child.signalCode !== null) return;
45
+ try {
46
+ process.kill(-child.pid, "SIGKILL");
47
+ } catch {
48
+ child.kill("SIGKILL");
49
+ }
50
+ }, 3e3);
51
+ }
52
+ };
53
+ child.stdout.on("data", (chunk) => {
54
+ output += String(chunk);
55
+ if (Buffer.byteLength(output) > 32 * 1024 ** 2) {
56
+ failure = /* @__PURE__ */ new Error("verifier output exceeds limit");
57
+ stop();
58
+ }
59
+ });
60
+ child.stderr.resume();
61
+ signal?.addEventListener("abort", stop, { once: true });
62
+ const timer = setTimeout(() => {
63
+ failure = /* @__PURE__ */ new Error("verifier timeout");
64
+ stop();
65
+ }, 9e5);
66
+ try {
67
+ if (signal?.aborted) stop();
68
+ await new Promise((done, reject) => {
69
+ child.once("error", reject);
70
+ child.once("close", (code) => code === 0 ? done() : reject(failure ?? /* @__PURE__ */ new Error(`verifier exited (${code})`)));
71
+ });
72
+ signal?.throwIfAborted();
73
+ if (failure) throw failure;
74
+ return output;
75
+ } finally {
76
+ clearTimeout(timer);
77
+ if (escalation) clearTimeout(escalation);
78
+ signal?.removeEventListener("abort", stop);
79
+ }
80
+ }
81
+ //#endregion
82
+ //#region src/debug-contract.ts
83
+ const DOG_DEBUG_RPC_CHANNEL = "/dog-rpc";
84
+ const DOG_DEBUG_SNAPSHOT_ENDPOINT = "snapshot";
85
+ const DOG_RUNTIME_TRACE_ENDPOINT = "goal-runtime";
86
+ //#endregion
87
+ //#region src/debug.ts
88
+ const MAX_RUNTIME_EVENTS_PER_GOAL = 64;
89
+ /** Build a digest-safe view: an old run is never shown against a newer graph revision. */
90
+ async function buildDogDebugSnapshot(repository, now = () => /* @__PURE__ */ new Date()) {
91
+ const [allGraphs, runs] = await Promise.all([repository.listGraphs(), repository.listRuns()]);
92
+ const graphs = allGraphs.filter((graph) => graph.input.schemaVersion === "0.9");
93
+ const graphIds = [...new Set(graphs.map((graph) => graph.input.id))];
94
+ const settled = await Promise.allSettled(graphIds.map((id) => repository.loadGraph(id)));
95
+ const currentDigests = new Set(settled.filter((result) => result.status === "fulfilled").map((result) => result.value.graphDigest));
96
+ const revisions = graphs.map((graph) => ({
97
+ graph,
98
+ current: currentDigests.has(graph.graphDigest),
99
+ runs: runs.filter((run) => run.graphDigest === graph.graphDigest)
100
+ })).sort(compareRevisions);
101
+ return {
102
+ schemaVersion: "0.1",
103
+ generatedAt: now().toISOString(),
104
+ graphs: revisions
105
+ };
106
+ }
107
+ /** Build one bounded node trace without loading any DSH transcript or artifact bytes. */
108
+ async function buildGoalRuntimeTrace(repository, runId, goalId) {
109
+ const run = await repository.loadRun(runId);
110
+ const result = run.goals[goalId];
111
+ if (result === void 0) throw new Error(`run ${runId} has no goal ${goalId}`);
112
+ const matching = [...await repository.loadGoalRuntimeEvents(runId, goalId)];
113
+ const truncated = matching.length > MAX_RUNTIME_EVENTS_PER_GOAL;
114
+ return {
115
+ schemaVersion: "0.1",
116
+ runId: run.runId,
117
+ graphId: run.graphId,
118
+ graphDigest: run.graphDigest,
119
+ runState: run.state,
120
+ ...run.rootState === void 0 ? {} : { rootState: run.rootState },
121
+ goalId,
122
+ result,
123
+ ...run.invocation === void 0 ? {} : { invocation: run.invocation },
124
+ ...run.runtimeWarning === void 0 ? {} : { runtimeWarning: boundedMessage(run.runtimeWarning) },
125
+ events: truncated ? matching.slice(-64) : matching,
126
+ truncated
127
+ };
128
+ }
129
+ /** Register this handler on the trusted-host Connection channel, never as an unauthenticated raw HTTP route. */
130
+ function createDogDebugRpcHandler(repository) {
131
+ return async (endpoint, payload, signal) => {
132
+ try {
133
+ signal.throwIfAborted();
134
+ if (endpoint === "snapshot") {
135
+ requireEmptyPayload(payload);
136
+ return {
137
+ ok: true,
138
+ value: await buildDogDebugSnapshot(repository)
139
+ };
140
+ }
141
+ if (endpoint === "goal-runtime") {
142
+ const request = parseGoalRuntimeRequest(payload);
143
+ return {
144
+ ok: true,
145
+ value: await buildGoalRuntimeTrace(repository, request.runId, request.goalId)
146
+ };
147
+ }
148
+ return internalError(`unknown DoG debugger endpoint ${endpoint}`);
149
+ } catch (error) {
150
+ if (signal.aborted) return {
151
+ ok: false,
152
+ error: {
153
+ code: "cancelled",
154
+ message: "DoG debugger request cancelled",
155
+ details: {}
156
+ }
157
+ };
158
+ return internalError(messageOf(error));
159
+ }
160
+ };
161
+ }
162
+ function compareRevisions(left, right) {
163
+ if (left.current !== right.current) return left.current ? -1 : 1;
164
+ const leftUpdated = left.runs[0]?.updatedAt ?? "";
165
+ const byActivity = (right.runs[0]?.updatedAt ?? "").localeCompare(leftUpdated);
166
+ if (byActivity !== 0) return byActivity;
167
+ const byId = left.graph.input.id.localeCompare(right.graph.input.id);
168
+ return byId === 0 ? left.graph.graphDigest.localeCompare(right.graph.graphDigest) : byId;
169
+ }
170
+ function requireEmptyPayload(value) {
171
+ if (value === null || typeof value !== "object" || Array.isArray(value) || Object.keys(value).length !== 0) throw new Error("DoG snapshot request payload must be an empty object");
172
+ }
173
+ function parseGoalRuntimeRequest(value) {
174
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("DoG runtime request payload must be an object");
175
+ const record = Object.fromEntries(Object.entries(value));
176
+ if (Object.keys(record).length !== 2) throw new Error("DoG runtime request requires exactly runId and goalId");
177
+ return {
178
+ runId: requireBoundedId(record.runId, "runId"),
179
+ goalId: requireBoundedId(record.goalId, "goalId")
180
+ };
181
+ }
182
+ function requireBoundedId(value, label) {
183
+ if (typeof value !== "string" || value.length === 0 || value.length > 512) throw new Error(`${label} must contain 1-512 characters`);
184
+ return value;
185
+ }
186
+ function internalError(message) {
187
+ return {
188
+ ok: false,
189
+ error: {
190
+ code: "internal",
191
+ message: boundedMessage(message),
192
+ details: {}
193
+ }
194
+ };
195
+ }
196
+ function boundedMessage(value) {
197
+ const normalized = value.length === 0 ? "DoG debugger request failed" : value;
198
+ return normalized.length <= 512 ? normalized : `${normalized.slice(0, 509)}...`;
199
+ }
200
+ function messageOf(error) {
201
+ return error instanceof Error ? error.message : String(error);
202
+ }
203
+ //#endregion
204
+ //#region src/tools.ts
205
+ /** Model-facing DoG tools over the verification-first engine. */
206
+ const DOG_VALIDATE_TOOL = "dog_validate";
207
+ const DOG_CREATE_TOOL = "dog_create";
208
+ const DOG_RUN_TOOL = "dog_run";
209
+ const DOG_BIND_AGENT_TOOL = "dog_bind_agent";
210
+ const DOG_DELEGATE_AGENT_TOOL = "dog_delegate_agent";
211
+ const DOG_STATUS_TOOL = "dog_status";
212
+ const DOG_CANCEL_TOOL = "dog_cancel";
213
+ const DOG_WAIT_TOOL = "dog_wait";
214
+ const JSON_OUTPUT = {
215
+ schema: { type: "json" },
216
+ render: (_args, value) => [{
217
+ type: "text",
218
+ text: JSON.stringify(value, null, 2)
219
+ }]
220
+ };
221
+ /** Build the complete DoG v0.1 tool surface around one engine instance. */
222
+ function createDogTools(engine, hostJobs = () => void 0) {
223
+ return [
224
+ defineTool({
225
+ name: DOG_VALIDATE_TOOL,
226
+ description: "Statically validate a DoG v0.2 graph. This does not write files, capture sandbox files, or run goals.",
227
+ parameters: { graph: {
228
+ type: "json",
229
+ required: true,
230
+ description: "Complete JSON DoG graph using schemaVersion 0.2."
231
+ } },
232
+ output: JSON_OUTPUT,
233
+ isConcurrencySafe: () => true,
234
+ execute: async (args, exec) => {
235
+ exec.signal.throwIfAborted();
236
+ return jsonResult(engine().validate(args.graph));
237
+ }
238
+ }),
239
+ defineTool({
240
+ name: DOG_CREATE_TOOL,
241
+ description: "Compile and persist a valid DoG v0.2 graph, capturing verifier input files from the configured sandbox as immutable bytes.",
242
+ parameters: { graph: {
243
+ type: "json",
244
+ required: true,
245
+ description: "Complete JSON DoG graph using schemaVersion 0.2."
246
+ } },
247
+ output: JSON_OUTPUT,
248
+ async execute(args, exec) {
249
+ exec.signal.throwIfAborted();
250
+ const cwd = exec.agent?.session.header.cwd;
251
+ const compiled = await engine().create(args.graph, typeof cwd === "string" && cwd.length > 0 ? { captureBaseDir: cwd } : {});
252
+ exec.signal.throwIfAborted();
253
+ return jsonResult(compiledGraphSummary(compiled));
254
+ }
255
+ }),
256
+ defineTool({
257
+ name: DOG_RUN_TOOL,
258
+ description: "Run trusted atomic verification for the latest persisted revision of a graph and recompute its root result.",
259
+ parameters: { graphId: {
260
+ type: "string",
261
+ required: true,
262
+ description: "Graph ID previously persisted by dog_create."
263
+ } },
264
+ output: JSON_OUTPUT,
265
+ async execute(args, exec) {
266
+ exec.signal.throwIfAborted();
267
+ const run = await engine().startRun(args.graphId, {
268
+ invocation: {
269
+ callId: String(exec.callId),
270
+ ...exec.agent === void 0 ? {} : { agentSessionId: String(exec.agent.id) },
271
+ ...exec.agent?.session.header.parentSession === void 0 ? {} : { parentSessionId: String(exec.agent.session.header.parentSession) }
272
+ },
273
+ ...exec.agent === void 0 ? {} : { agent: exec.agent }
274
+ });
275
+ exec.signal.throwIfAborted();
276
+ return jsonResult(Object.assign({}, runSummary(run), { note: "verification runs in the background; agentic leaves spawn verifier Agents that live in THIS process. If this is a one-shot launch (e.g. dsh --profile headless), the process exits after answering and verifier workers are interrupted: background agentic verification requires a resident host process. Poll with dog_status." }));
277
+ }
278
+ }),
279
+ defineTool({
280
+ name: DOG_BIND_AGENT_TOOL,
281
+ description: "Bind the current trusted DSH Agent session to one goal in an existing DoG run. Use dog_delegate_agent instead when creating a new worker that must remain directly interactive after its first turn. Session identity is captured from the tool execution context and cannot be supplied by the model.",
282
+ parameters: {
283
+ runId: {
284
+ type: "string",
285
+ required: true,
286
+ description: "Run ID returned by dog_run."
287
+ },
288
+ goalId: {
289
+ type: "string",
290
+ required: true,
291
+ description: "Goal ID this Agent is working on or verifying."
292
+ },
293
+ role: {
294
+ type: "string",
295
+ required: true,
296
+ enum: [
297
+ "orchestrator",
298
+ "verifier",
299
+ "reviewer"
300
+ ],
301
+ description: "The Agent role for this goal."
302
+ }
303
+ },
304
+ output: JSON_OUTPUT,
305
+ isConcurrencySafe: () => true,
306
+ async execute(args, exec) {
307
+ exec.signal.throwIfAborted();
308
+ if (exec.agent === void 0) throw new Error("dog_bind_agent requires a trusted DSH Agent execution context");
309
+ const binding = await engine().bindAgent({
310
+ runId: args.runId,
311
+ goalId: args.goalId,
312
+ role: args.role,
313
+ sessionId: String(exec.agent.id),
314
+ ...exec.agent.session.header.parentSession === void 0 ? {} : { parentSessionId: String(exec.agent.session.header.parentSession) }
315
+ });
316
+ exec.signal.throwIfAborted();
317
+ return jsonResult({
318
+ runId: binding.run.runId,
319
+ goalId: args.goalId,
320
+ agent: binding.agent
321
+ });
322
+ }
323
+ }),
324
+ defineTool({
325
+ name: DOG_STATUS_TOOL,
326
+ description: "Read the bounded persisted status and verifier evidence for one DoG run.",
327
+ parameters: { runId: {
328
+ type: "string",
329
+ required: true,
330
+ description: "Run ID returned by dog_run."
331
+ } },
332
+ output: JSON_OUTPUT,
333
+ isConcurrencySafe: () => true,
334
+ async execute(args, exec) {
335
+ exec.signal.throwIfAborted();
336
+ const run = await engine().status(args.runId);
337
+ exec.signal.throwIfAborted();
338
+ return jsonResult(runSummary(run));
339
+ }
340
+ }),
341
+ defineTool({
342
+ name: DOG_WAIT_TOOL,
343
+ description: "Wait for one DoG run to settle. Preferred path: when the host job service is available this registers a background \"dog\" job (returns instantly with jobId) and the harness notifies you automatically when the run completes — inspect with job_output, cancel with job_kill. Fallback (no job service, e.g. a bare one-shot process): returns the current state instantly and you must call dog_wait repeatedly until the state is terminal; each poll keeps the calling session and process alive, which protects the verifier workers the run spawned. Always wait until the returned state is terminal before summarizing — finishing early releases the workers. Same report shape as dog_status.",
344
+ parameters: {
345
+ runId: {
346
+ type: "string",
347
+ required: true,
348
+ description: "Run ID returned by dog_run."
349
+ },
350
+ timeout: {
351
+ type: "number",
352
+ description: "Advisory total wait budget in seconds; not enforced (each call returns instantly)."
353
+ }
354
+ },
355
+ output: JSON_OUTPUT,
356
+ isConcurrencySafe: () => true,
357
+ async execute(args, exec) {
358
+ exec.signal.throwIfAborted();
359
+ const run = await engine().status(args.runId);
360
+ exec.signal.throwIfAborted();
361
+ const jobs = hostJobs();
362
+ if (jobs !== void 0 && run.state === "running") {
363
+ const controller = new AbortController();
364
+ const done = engine().waitRun(args.runId, {
365
+ signal: controller.signal,
366
+ timeoutMs: 72e5
367
+ }).then((settled) => ({
368
+ status: "completed",
369
+ output: JSON.stringify(runSummary(settled))
370
+ })).catch((error) => ({
371
+ status: controller.signal.aborted ? "killed" : "failed",
372
+ detail: String(error instanceof Error ? error.message : error).slice(0, 200)
373
+ }));
374
+ const jobId = jobs.start({
375
+ kind: "dog",
376
+ label: `DoG wait ${String(args.runId).slice(0, 8)}`,
377
+ ...exec.agent === void 0 ? {} : { owner: exec.agent },
378
+ run: () => ({
379
+ cancel: (reason) => {
380
+ controller.abort(new Error(reason ?? "cancelled"));
381
+ },
382
+ done
383
+ })
384
+ });
385
+ return jsonResult({
386
+ runId: run.runId,
387
+ graphId: run.graphId,
388
+ state: run.state,
389
+ jobId,
390
+ note: "background wait job registered; the harness will notify you when the run completes (that is the wait). NEVER call job_output with wait:true — a long wait gets interrupted by background notices and that interruption is expected; if an unofficial job_output result comes back interrupted, just keep your current turn alive or reply with another dog_wait."
391
+ });
392
+ }
393
+ return jsonResult(Object.assign({}, runSummary(run), { ...run.state === "running" ? { note: "instant poll: the run is still running (this call returned immediately and cannot be interrupted). Call dog_wait again, repeatedly, until the state is terminal." } : {} }));
394
+ }
395
+ }),
396
+ defineTool({
397
+ name: DOG_CANCEL_TOOL,
398
+ description: "Cancel one running DoG run and its verifier workers; partial records remain inspectable.",
399
+ parameters: {
400
+ runId: {
401
+ type: "string",
402
+ required: true,
403
+ description: "Run ID returned by dog_run."
404
+ },
405
+ reason: {
406
+ type: "string",
407
+ description: "Bounded human-readable cancellation reason."
408
+ }
409
+ },
410
+ output: JSON_OUTPUT,
411
+ isConcurrencySafe: () => true,
412
+ async execute(args, exec) {
413
+ exec.signal.throwIfAborted();
414
+ const runId = args.runId;
415
+ const reason = typeof args.reason === "string" && args.reason.length > 0 ? args.reason : "cancelled by operator";
416
+ const cancelled = await engine().cancelRun(runId, reason);
417
+ exec.signal.throwIfAborted();
418
+ return jsonResult(runSummary(cancelled));
419
+ }
420
+ })
421
+ ];
422
+ }
423
+ /** Build the DoG-aware continuable Agent launcher once the host subagent service is available. */
424
+ function createDogDelegateAgentTool(engine, launcher) {
425
+ return defineTool({
426
+ name: DOG_DELEGATE_AGENT_TOOL,
427
+ description: "Start a durable continuable DSH Agent for one DoG goal and bind its host-issued session identity to the run. The child remains directly interactive in the session UI after its first turn. Use this instead of a foreground or one-shot subagent for user-addressable DoG workers.",
428
+ parameters: {
429
+ runId: {
430
+ type: "string",
431
+ required: true,
432
+ description: "Run ID returned by dog_run."
433
+ },
434
+ goalId: {
435
+ type: "string",
436
+ required: true,
437
+ description: "Goal ID assigned to the new Agent."
438
+ },
439
+ role: {
440
+ type: "string",
441
+ required: true,
442
+ enum: [
443
+ "orchestrator",
444
+ "verifier",
445
+ "reviewer"
446
+ ],
447
+ description: "The Agent role for this goal."
448
+ },
449
+ label: {
450
+ type: "string",
451
+ required: true,
452
+ description: "Short human-readable Agent label shown in the session tree."
453
+ },
454
+ prompt: {
455
+ type: "string",
456
+ required: true,
457
+ description: "Complete first-turn assignment for the Agent."
458
+ }
459
+ },
460
+ output: JSON_OUTPUT,
461
+ async execute(args, exec) {
462
+ exec.signal.throwIfAborted();
463
+ if (exec.agent === void 0) throw new Error("dog_delegate_agent requires a trusted DSH Agent execution context");
464
+ const parentSessionId = String(exec.agent.id);
465
+ await engine().assertAgentCanDelegate({
466
+ runId: args.runId,
467
+ goalId: args.goalId,
468
+ parentSessionId
469
+ });
470
+ exec.signal.throwIfAborted();
471
+ const child = await launcher.launch({
472
+ label: args.label,
473
+ prompt: args.prompt,
474
+ parent: exec.agent,
475
+ signal: exec.signal
476
+ });
477
+ if (child.sessionId.length === 0) throw new Error("DoG Agent launcher returned an empty child session ID");
478
+ try {
479
+ const binding = await engine().bindAgent({
480
+ runId: args.runId,
481
+ goalId: args.goalId,
482
+ role: args.role,
483
+ sessionId: child.sessionId,
484
+ parentSessionId
485
+ });
486
+ return jsonResult({
487
+ runId: binding.run.runId,
488
+ goalId: args.goalId,
489
+ lifecycle: "continuable",
490
+ agent: binding.agent
491
+ });
492
+ } catch (error) {
493
+ try {
494
+ await launcher.interrupt?.(child.sessionId, exec.agent);
495
+ } catch {}
496
+ throw error;
497
+ }
498
+ }
499
+ });
500
+ }
501
+ function compiledGraphSummary(compiled) {
502
+ return {
503
+ graphId: compiled.input.id,
504
+ graphDigest: compiled.graphDigest,
505
+ acceptancePlans: Object.values(compiled.acceptancePlans).map((plan) => ({
506
+ goalId: plan.goalId,
507
+ mode: plan.verifier.mode,
508
+ ...plan.verifier.mode === "programmatic" ? { script: plan.verifier.script } : { instruction: plan.verifier.instruction },
509
+ target: plan.target,
510
+ ...plan.input === void 0 ? {} : {
511
+ inputPath: plan.input.path,
512
+ digest: plan.input.digest,
513
+ exists: plan.input.exists,
514
+ byteLength: plan.input.byteLength
515
+ }
516
+ }))
517
+ };
518
+ }
519
+ function ciReport(run) {
520
+ const goals = Object.entries(run.goals).map(([goalId, result]) => goalReport(goalId, result));
521
+ const revalidated = Object.entries(run.gmDigests).filter(([goalId]) => run.goals[goalId]?.state !== "inherited").map(([goalId]) => goalId);
522
+ const inherited = Object.entries(run.goals).filter(([, result]) => result.state === "inherited").map(([goalId, result]) => ({
523
+ goalId,
524
+ fromRunId: result.inheritedFrom ?? run.runId,
525
+ state: "inherited"
526
+ }));
527
+ const warning = revalidateWarning(run, revalidated);
528
+ return {
529
+ runId: run.runId,
530
+ graphId: run.graphId,
531
+ ...run.graphDigest === void 0 ? {} : { graphDigest: run.graphDigest },
532
+ rootState: run.rootState ?? (run.state === "running" ? "running" : "cancelled"),
533
+ goals: goals.sort((left, right) => left.goalId.localeCompare(right.goalId)),
534
+ revalidated,
535
+ inherited,
536
+ ...warning === void 0 ? {} : { warning },
537
+ generatedAt: run.updatedAt
538
+ };
539
+ }
540
+ function goalReport(goalId, result) {
541
+ const verification = result.verification;
542
+ return {
543
+ goalId,
544
+ state: result.state,
545
+ ...verification === void 0 ? {} : { verifier: { mode: verification.judgment.mode } },
546
+ ...verification === void 0 || verification.evidence === void 0 ? {} : { evidence: [verification.evidence] },
547
+ ...result.reason === void 0 ? {} : { defect: result.reason }
548
+ };
549
+ }
550
+ function revalidateWarning(run, revalidated) {
551
+ const warning = run.runtimeWarning;
552
+ return warning === void 0 ? void 0 : warning;
553
+ }
554
+ function runSummary(run) {
555
+ return ciReport(run);
556
+ }
557
+ function jsonResult(value) {
558
+ if (!isJsonValue(value)) throw new Error("DoG produced a non-JSON tool result");
559
+ return value;
560
+ }
561
+ //#endregion
562
+ //#region src/verifier-file.ts
563
+ /** File-backed settlement channel for continuable verifier subagents. */
564
+ /**
565
+ * Same as {@link waitForSettlement}, but short-circuits once the verifier child
566
+ * has finished its turn: if the settlement file is still absent shortly after
567
+ * the child's turn ended, the child is not coming back — settle inconclusive
568
+ * immediately instead of blocking the run for the full timeout.
569
+ */
570
+ async function waitForSettlementFlexible(resultPath, signal, timeoutMs, childSettled) {
571
+ const startAt = Date.now();
572
+ while (Date.now() - startAt < timeoutMs) {
573
+ if (signal.aborted) return {
574
+ state: "inconclusive",
575
+ observation: { outcome: "aborted" },
576
+ waitedMs: Date.now() - startAt
577
+ };
578
+ try {
579
+ const source = await readFile(resultPath, "utf8");
580
+ return {
581
+ ...parseSettlementFile(source),
582
+ source,
583
+ waitedMs: Date.now() - startAt
584
+ };
585
+ } catch (error) {
586
+ if (!isMissing(error)) return {
587
+ state: "inconclusive",
588
+ observation: { outcome: "unreadable settlement file" },
589
+ waitedMs: Date.now() - startAt
590
+ };
591
+ if (await childSettled()) {
592
+ await sleep(15e3);
593
+ try {
594
+ const source = await readFile(resultPath, "utf8");
595
+ return {
596
+ ...parseSettlementFile(source),
597
+ source,
598
+ waitedMs: Date.now() - startAt
599
+ };
600
+ } catch {
601
+ return {
602
+ state: "inconclusive",
603
+ observation: { outcome: "verifier child finished without writing the settlement file" },
604
+ waitedMs: Date.now() - startAt
605
+ };
606
+ }
607
+ }
608
+ await sleep(500);
609
+ }
610
+ }
611
+ return {
612
+ state: "inconclusive",
613
+ observation: { outcome: "timed out waiting for verifier result" },
614
+ waitedMs: Date.now() - startAt
615
+ };
616
+ }
617
+ function parseSettlementFile(source) {
618
+ const value = parseLooseJson(source);
619
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return {
620
+ state: "inconclusive",
621
+ observation: { outcome: "settlement file is not a JSON object" }
622
+ };
623
+ const raw = value;
624
+ const state = raw.verdict ?? raw.settlement;
625
+ if (state !== "pass" && state !== "fail" && state !== "inconclusive") return {
626
+ state: "inconclusive",
627
+ observation: { outcome: "settlement file has an invalid settlement value" }
628
+ };
629
+ const observation = raw.evidence ?? raw.observation;
630
+ if (observation === void 0) return {
631
+ state: "inconclusive",
632
+ observation: { outcome: "settlement file has no observation evidence" }
633
+ };
634
+ if (observation === null || typeof observation !== "object" || Array.isArray(observation)) return {
635
+ state: "inconclusive",
636
+ observation: { outcome: "settlement observation is not an object" }
637
+ };
638
+ const record = {};
639
+ for (const [key, item] of Object.entries(observation)) if (typeof item === "string" || typeof item === "number" || typeof item === "boolean" || item === null) record[key] = item;
640
+ else if (Array.isArray(item) || typeof item === "object") {
641
+ if (isJsonValueLike(item)) record[key] = item;
642
+ }
643
+ if (Object.keys(record).length === 0) record.settled = state;
644
+ return {
645
+ state,
646
+ observation: record
647
+ };
648
+ }
649
+ /** Parse a settlement payload leniently: strip markdown fences, then try to extract the outermost JSON object. */
650
+ function parseLooseJson(source) {
651
+ let text = source.trim();
652
+ if (text.startsWith("```")) {
653
+ text = text.replace(/^```[A-Za-z]*\s*/u, "").replace(/\s*```\s*$/u, "");
654
+ text = text.trim();
655
+ }
656
+ try {
657
+ return JSON.parse(text);
658
+ } catch {
659
+ const start = text.indexOf("{");
660
+ if (start < 0) throw new Error("no JSON object found");
661
+ let depth = 0;
662
+ for (let index = start; index < text.length; index++) {
663
+ const ch = text[index];
664
+ if (ch === "{") depth++;
665
+ else if (ch === "}") {
666
+ depth--;
667
+ if (depth === 0) return JSON.parse(text.slice(start, index + 1));
668
+ }
669
+ }
670
+ }
671
+ throw new Error("no complete JSON object found");
672
+ }
673
+ function isJsonValueLike(value) {
674
+ if (value === null || typeof value === "string" || typeof value === "boolean") return true;
675
+ if (typeof value === "number") return Number.isFinite(value);
676
+ if (Array.isArray(value)) return value.every(isJsonValueLike);
677
+ if (typeof value !== "object") return false;
678
+ return Object.values(value).every(isJsonValueLike);
679
+ }
680
+ function isMissing(error) {
681
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
682
+ }
683
+ function sleep(ms) {
684
+ return new Promise((resolve) => setTimeout(resolve, ms));
685
+ }
686
+ //#endregion
687
+ //#region src/index.ts
688
+ /** Cordis plugin name. */
689
+ const name = "dsh-dog";
690
+ /** Required Harness services. */
691
+ const inject = ["tools", "subagents"];
692
+ /** Loader-validated DoG deployment configuration. */
693
+ const Config = z.object({
694
+ storageDirectory: z.string().default("dog"),
695
+ workspaceRoot: z.string().default("dog/workspace"),
696
+ scriptsDirectory: z.string().default(fileURLToPath(new URL("../../../scripts/dog/", import.meta.url))),
697
+ maxGraphNodes: z.natural().min(1).default(256),
698
+ maxExpressionNodes: z.natural().min(1).default(512),
699
+ maxExpressionDepth: z.natural().min(1).default(64),
700
+ maxSandboxBytes: z.natural().min(1).default(67108864),
701
+ allowPartialRoot: z.boolean().default(false),
702
+ maxConcurrentVerifications: z.natural().min(1).default(1),
703
+ revalidateThreshold: z.number().default(.3),
704
+ gmDigestAlgo: z.string().default("sha256"),
705
+ subagentProvider: z.string().default("spawn"),
706
+ subagentMaxDepth: z.natural().default(3)
707
+ });
708
+ /** Register all DoG tools as Cordis-owned effects so fiber disposal removes them. */
709
+ async function apply(ctx, config) {
710
+ const schema = await loadSchemaSet();
711
+ let resolved = config;
712
+ let settingsCurrent;
713
+ ctx.inject(["settings"], (settingsCtx) => settingsCtx.settings.installSection(ctx, "dog", z.object({
714
+ storageDirectory: z.string().default("dog"),
715
+ workspaceRoot: z.string().default("dog/workspace"),
716
+ scriptsDirectory: z.string().default(fileURLToPath(new URL("../../../scripts/dog/", import.meta.url))),
717
+ maxGraphNodes: z.natural().min(1).default(256),
718
+ maxExpressionNodes: z.natural().min(1).default(512),
719
+ maxExpressionDepth: z.natural().min(1).default(64),
720
+ maxSandboxBytes: z.natural().min(1).default(67108864),
721
+ allowPartialRoot: z.boolean().default(false),
722
+ maxConcurrentVerifications: z.natural().min(1).default(1),
723
+ revalidateThreshold: z.number().default(.3),
724
+ gmDigestAlgo: z.string().default("sha256"),
725
+ subagentProvider: z.string().default("spawn"),
726
+ subagentMaxDepth: z.natural().default(3)
727
+ }), config, {
728
+ setSource: (current) => {
729
+ settingsCurrent = current;
730
+ resolved = {
731
+ ...config,
732
+ ...current()
733
+ };
734
+ },
735
+ onChange: () => void 0
736
+ }));
737
+ const repository = new DogRepository(dshHomePath(config.storageDirectory), schema);
738
+ repository.markOrphanedRunningRuns((/* @__PURE__ */ new Date()).toISOString()).catch(() => void 0);
739
+ const scriptsDir = isAbsolute(config.scriptsDirectory) ? config.scriptsDirectory : dshHomePath(config.scriptsDirectory);
740
+ const programmatic = async (script, inputPath, env) => {
741
+ let out;
742
+ try {
743
+ out = await runOwnedScript(resolveScriptPath(scriptsDir, script), inputPath, env.signal);
744
+ } catch (error) {
745
+ return {
746
+ state: "inconclusive",
747
+ evidence: { error: String(error instanceof Error ? error.message : error) },
748
+ reason: "script execution failed"
749
+ };
750
+ }
751
+ return parseVerdict(out);
752
+ };
753
+ let dogEngine;
754
+ ctx.effect(() => async () => {
755
+ await dogEngine?.dispose();
756
+ });
757
+ let agenticRunnerRef;
758
+ let subagentRuntimeRef;
759
+ const activeVerifiers = /* @__PURE__ */ new Map();
760
+ const getEngine = () => {
761
+ if (dogEngine === void 0) {
762
+ const effective = settingsCurrent === void 0 ? resolved : {
763
+ ...config,
764
+ ...settingsCurrent()
765
+ };
766
+ dogEngine = new DogEngine({
767
+ config: {
768
+ ...effective,
769
+ workspaceRoot: isAbsolute(effective.workspaceRoot) ? effective.workspaceRoot : dshHomePath(effective.workspaceRoot),
770
+ scriptsDirectory: isAbsolute(effective.scriptsDirectory) ? effective.scriptsDirectory : dshHomePath(effective.scriptsDirectory)
771
+ },
772
+ programmatic,
773
+ ...agenticRunnerRef === void 0 ? {} : { agentic: agenticRunnerRef },
774
+ repository,
775
+ workspaces: new WorkspaceManager({ baseDir: effective.workspaceRoot }),
776
+ onRunCancelled: (runId) => {
777
+ for (const [sessionId, record] of activeVerifiers) {
778
+ if (record.runId !== runId) continue;
779
+ try {
780
+ subagentRuntimeRef?.interrupt(sessionId, {
781
+ kind: "ancestor",
782
+ agent: record.parent
783
+ });
784
+ } catch {}
785
+ }
786
+ },
787
+ liveConfig: () => {
788
+ const live = settingsCurrent?.();
789
+ return live === void 0 ? {} : { maxConcurrentVerifications: live.maxConcurrentVerifications };
790
+ },
791
+ resolveLivingAgent: (sessionId) => {
792
+ return ctx.get("agents")?.get(sessionId);
793
+ }
794
+ });
795
+ }
796
+ return dogEngine;
797
+ };
798
+ const scopedTools = [...createDogTools(getEngine, () => ctx.get("jobs"))];
799
+ ctx.provide("openwriteDog", { tools: scopedTools });
800
+ ctx.inject(["subagents"], (subagentCtx) => {
801
+ const subagents = subagentCtx.subagents;
802
+ subagentRuntimeRef = subagents;
803
+ const agenticRunner = async (instruction, workspace, inputPath, env) => {
804
+ const { parent, runId } = env;
805
+ const signal = env.signal ?? new AbortController().signal;
806
+ const goalId = env.goalId ?? "verification";
807
+ const resultPath = join(workspace.path, "settlement.json");
808
+ const parentSessionId = readSessionId(parent);
809
+ if (parent === void 0) throw new Error("verifier delegation requires a live parent Agent (recovered runs without a live parent cannot spawn verification workers)");
810
+ const sessionId = (await subagents.startContinuable({
811
+ provider: config.subagentProvider,
812
+ label: `verifier ${goalId} · ${runId === void 0 ? "run" : runId.slice(0, 6)}`,
813
+ request: {
814
+ prompt: [{
815
+ type: "text",
816
+ text: buildVerifierPrompt(instruction, inputPath, resultPath)
817
+ }],
818
+ parent,
819
+ maxDepth: config.subagentMaxDepth
820
+ },
821
+ signal
822
+ })).childId;
823
+ activeVerifiers.set(sessionId, {
824
+ parent,
825
+ runId: runId ?? ""
826
+ });
827
+ if (runId !== void 0) try {
828
+ await getEngine().annotateRun(runId, `bind-branch entered for ${goalId}: session ${sessionId.slice(0, 8)}`);
829
+ const binding = await getEngine().bindAgent({
830
+ runId,
831
+ goalId,
832
+ role: "verifier",
833
+ sessionId,
834
+ ...parentSessionId.length > 0 ? { parentSessionId } : {}
835
+ }, { allowUnrooted: parentSessionId.length === 0 });
836
+ await getEngine().annotateRun(runId, `verifier bound for ${goalId}: ${sessionId.slice(0, 8)} (${binding.run.goals[goalId]?.agentSessions?.length ?? 0} bound)`);
837
+ } catch (bindingError) {
838
+ await getEngine().annotateRun(runId, `verifier binding failed for ${goalId}: ${String(bindingError).slice(0, 300)}`);
839
+ await getEngine().recordVerifierLifecycle(runId, goalId, "verifier_bind_failed", sessionId, String(bindingError));
840
+ }
841
+ const settlement = await waitForSettlementFlexible(resultPath, signal, 9e5, async () => verifierChildTurnEnded(ctx, sessionId));
842
+ if (settlement.source !== void 0 && runId !== void 0) repository.saveSettlement(runId, goalId, settlement.source).catch(() => void 0);
843
+ if (runId !== void 0 && parent !== void 0 && parentSessionId.length > 0) try {
844
+ await subagents.drainContinuableChildren(parent, [sessionId]);
845
+ activeVerifiers.delete(sessionId);
846
+ await getEngine().recordVerifierLifecycle(runId, goalId, "verifier_released", sessionId);
847
+ } catch (releaseError) {
848
+ await getEngine().annotateRun(runId, `verifier release failed for ${goalId}: ${String(releaseError).slice(0, 300)}`);
849
+ }
850
+ return {
851
+ state: settlement.state,
852
+ evidence: settlement.observation
853
+ };
854
+ };
855
+ agenticRunnerRef = agenticRunner;
856
+ const delegateTool = createDogDelegateAgentTool(getEngine, {
857
+ async launch(input) {
858
+ return { sessionId: (await subagents.startContinuable({
859
+ provider: config.subagentProvider,
860
+ label: input.label,
861
+ request: {
862
+ prompt: [{
863
+ type: "text",
864
+ text: input.prompt
865
+ }],
866
+ parent: input.parent,
867
+ maxDepth: config.subagentMaxDepth
868
+ },
869
+ signal: input.signal
870
+ })).childId };
871
+ },
872
+ interrupt(sessionId, parent) {
873
+ subagents.interrupt(sessionId, {
874
+ kind: "ancestor",
875
+ agent: parent
876
+ });
877
+ }
878
+ });
879
+ scopedTools.push(delegateTool);
880
+ });
881
+ const debugHandler = createDogDebugRpcHandler(repository);
882
+ ctx.on("session/event", (session, event) => {
883
+ if (event.type !== "turn/end") return;
884
+ if (event.data.reason?.kind !== "interrupted") return;
885
+ captureInterruptedTurn(repository, session, event).catch(() => void 0);
886
+ });
887
+ ctx.inject(["connection"], (connectionCtx) => {
888
+ connectionCtx.effect(() => connectionCtx.connection.rpc.handle(DOG_DEBUG_RPC_CHANNEL, debugHandler), "dog: trusted debugger RPC");
889
+ });
890
+ }
891
+ async function captureInterruptedTurn(repository, session, event) {
892
+ const diagnosticsDir = join(repository.rootPath, "diagnostics");
893
+ await mkdir(diagnosticsDir, { recursive: true });
894
+ const recentEvents = session.snapshotEvents().slice(-12).map((candidate) => ({
895
+ seq: candidate.seq,
896
+ type: candidate.type,
897
+ time: candidate.time
898
+ }));
899
+ const payload = {
900
+ capturedAt: (/* @__PURE__ */ new Date()).toISOString(),
901
+ process: {
902
+ pid: process.pid,
903
+ startedAt: (/* @__PURE__ */ new Date(Date.now() - process.uptime() * 1e3)).toISOString()
904
+ },
905
+ sessionId: session.id,
906
+ interruptSeq: event.seq,
907
+ interruptEventTime: new Date(event.time).toISOString(),
908
+ recentEvents
909
+ };
910
+ await writeFile(join(diagnosticsDir, `interrupt-${session.id.replaceAll(/[^a-zA-Z0-9-]/gu, "_")}-${event.seq}.json`), JSON.stringify(payload, null, 2));
911
+ }
912
+ function buildVerifierPrompt(instruction, inputPath, resultPath) {
913
+ return [
914
+ "You are a DoG verifier. Judge only the object handed to you.",
915
+ "",
916
+ `Object (read from here; only this tree is yours): ${inputPath}`,
917
+ "",
918
+ "Instruction:",
919
+ instruction,
920
+ "",
921
+ "Decide on your own terms; gather the strongest evidence you can with your own judgment. No fixed evidence format.",
922
+ `Write your verdict to this exact absolute path: ${resultPath}. The file must contain exactly:`,
923
+ "{\"verdict\": \"pass\" | \"fail\" | \"inconclusive\", \"evidence\": <any JSON>}",
924
+ "Create it (it does not exist yet); never write it as a relative path or to another location. After writing, stop."
925
+ ].join("\n");
926
+ }
927
+ function parseVerdict(out) {
928
+ let value;
929
+ try {
930
+ value = JSON.parse(out);
931
+ } catch {
932
+ return {
933
+ state: "inconclusive",
934
+ evidence: { parseError: "script output was not JSON" },
935
+ reason: "script output was not JSON"
936
+ };
937
+ }
938
+ const record = value;
939
+ if (record === null || typeof record !== "object" || Array.isArray(record)) return {
940
+ state: "inconclusive",
941
+ evidence: { parseError: "script output was not an object" },
942
+ reason: "script output was not an object"
943
+ };
944
+ const verdict = record.verdict;
945
+ if (verdict !== "pass" && verdict !== "fail" && verdict !== "inconclusive") return {
946
+ state: "inconclusive",
947
+ evidence: { parseError: "invalid verdict" },
948
+ reason: "script returned an invalid verdict"
949
+ };
950
+ return {
951
+ state: verdict,
952
+ evidence: isJsonValue(record.evidence) ? record.evidence : { outcome: "no evidence supplied by script" }
953
+ };
954
+ }
955
+ /** Read the durable session id from a live Agent, or '' outside an agent boundary. */
956
+ function readSessionId(parent) {
957
+ if (parent === void 0) return "";
958
+ return String(parent.id);
959
+ }
960
+ /** True once the verifier child's turn has ended (or the child is gone entirely). */
961
+ function verifierChildTurnEnded(ctx, sessionId) {
962
+ const agent = ctx.get("agents")?.get(sessionId);
963
+ if (agent === void 0) return true;
964
+ return agent.session.snapshotEvents().at(-1)?.type === "turn/end";
965
+ }
966
+ //#endregion
967
+ export { Config, DOG_BIND_AGENT_TOOL, DOG_CREATE_TOOL, DOG_DEBUG_RPC_CHANNEL, DOG_DEBUG_SNAPSHOT_ENDPOINT, DOG_DELEGATE_AGENT_TOOL, DOG_RUNTIME_TRACE_ENDPOINT, DOG_RUN_TOOL, DOG_STATUS_TOOL, DOG_VALIDATE_TOOL, DOG_WAIT_TOOL, DogEngine, DogValidationError, WorkspaceManager, apply, buildDogDebugSnapshot, buildGoalRuntimeTrace, createDogDebugRpcHandler, createDogDelegateAgentTool, createDogTools, evaluateBoolExpr, inject, loadSchemaSet, name, parseBoolExpr, parseGraph, runPlan };