@arnilo/prism-tools 0.0.0-stage → 0.13.1

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 (331) hide show
  1. package/CHANGELOG.md +418 -0
  2. package/LICENSE +21 -0
  3. package/README.md +44 -2
  4. package/browser/README.md +98 -0
  5. package/browser/skills/browser-automation/SKILL.md +14 -0
  6. package/browser/src/actions/cdp.ts +131 -0
  7. package/browser/src/actions/dialog.ts +25 -0
  8. package/browser/src/actions/download_release.ts +22 -0
  9. package/browser/src/actions/index.ts +37 -0
  10. package/browser/src/actions/locator.ts +70 -0
  11. package/browser/src/actions/navigate.ts +23 -0
  12. package/browser/src/actions/screenshot.ts +27 -0
  13. package/browser/src/actions/scroll.ts +24 -0
  14. package/browser/src/actions/select_page.ts +21 -0
  15. package/browser/src/actions/types.ts +114 -0
  16. package/browser/src/actions/upload.ts +44 -0
  17. package/browser/src/actions/wait.ts +45 -0
  18. package/browser/src/browser.ts +197 -0
  19. package/browser/src/cdp.ts +178 -0
  20. package/browser/src/checkpoint.ts +189 -0
  21. package/browser/src/config.ts +72 -0
  22. package/browser/src/downloads.ts +253 -0
  23. package/browser/src/errors.ts +31 -0
  24. package/browser/src/evaluate.ts +101 -0
  25. package/browser/src/index.ts +129 -0
  26. package/browser/src/limits.ts +271 -0
  27. package/browser/src/manager.ts +730 -0
  28. package/browser/src/network.ts +263 -0
  29. package/browser/src/observe.ts +178 -0
  30. package/browser/src/policy.ts +133 -0
  31. package/browser/src/screenshot.ts +107 -0
  32. package/browser/src/shared-sandbox.ts +53 -0
  33. package/browser/src/snapshot.ts +99 -0
  34. package/browser/src/targets.ts +165 -0
  35. package/browser/src/tools.ts +480 -0
  36. package/browser/src/types.ts +316 -0
  37. package/browser/src/uploads.ts +174 -0
  38. package/coding/README.md +337 -0
  39. package/coding/src/agent/acp-operations.ts +146 -0
  40. package/coding/src/agent/artifacts.ts +38 -0
  41. package/coding/src/agent/ask-user-decision.ts +623 -0
  42. package/coding/src/agent/atomic-write.ts +23 -0
  43. package/coding/src/agent/bounded-file.ts +21 -0
  44. package/coding/src/agent/checks.ts +301 -0
  45. package/coding/src/agent/coding-checkpoint.ts +828 -0
  46. package/coding/src/agent/delete.ts +237 -0
  47. package/coding/src/agent/diagnostics-tool.ts +163 -0
  48. package/coding/src/agent/diagnostics.ts +262 -0
  49. package/coding/src/agent/edit-diff.ts +382 -0
  50. package/coding/src/agent/edit.ts +322 -0
  51. package/coding/src/agent/effects.ts +102 -0
  52. package/coding/src/agent/env.ts +28 -0
  53. package/coding/src/agent/execution-policy.ts +89 -0
  54. package/coding/src/agent/file-mutation-queue.ts +72 -0
  55. package/coding/src/agent/forge/github.ts +603 -0
  56. package/coding/src/agent/forge/index.ts +16 -0
  57. package/coding/src/agent/forge/types.ts +185 -0
  58. package/coding/src/agent/git-aware-repository.ts +305 -0
  59. package/coding/src/agent/git-exec.ts +326 -0
  60. package/coding/src/agent/git-status.ts +177 -0
  61. package/coding/src/agent/git-tools.ts +360 -0
  62. package/coding/src/agent/git.ts +1074 -0
  63. package/coding/src/agent/glob-match.ts +146 -0
  64. package/coding/src/agent/glob.ts +182 -0
  65. package/coding/src/agent/goal-verify.ts +385 -0
  66. package/coding/src/agent/grep-worker.ts +74 -0
  67. package/coding/src/agent/grep.ts +459 -0
  68. package/coding/src/agent/identity.ts +48 -0
  69. package/coding/src/agent/index.ts +676 -0
  70. package/coding/src/agent/language/client.ts +429 -0
  71. package/coding/src/agent/language/framing.ts +190 -0
  72. package/coding/src/agent/language/index.ts +23 -0
  73. package/coding/src/agent/language/intelligence.ts +682 -0
  74. package/coding/src/agent/language/types.ts +187 -0
  75. package/coding/src/agent/lifecycle-events.ts +121 -0
  76. package/coding/src/agent/lifecycle.ts +166 -0
  77. package/coding/src/agent/limits.ts +214 -0
  78. package/coding/src/agent/move.ts +178 -0
  79. package/coding/src/agent/mutation-path.ts +52 -0
  80. package/coding/src/agent/output-accumulator.ts +304 -0
  81. package/coding/src/agent/path-utils.ts +120 -0
  82. package/coding/src/agent/process/index.ts +58 -0
  83. package/coding/src/agent/process/recovery.ts +508 -0
  84. package/coding/src/agent/process/sessions-host.ts +222 -0
  85. package/coding/src/agent/process/sessions-monitor.ts +141 -0
  86. package/coding/src/agent/process/sessions-recovery.ts +241 -0
  87. package/coding/src/agent/process/sessions-spawn.ts +613 -0
  88. package/coding/src/agent/process/sessions-teardown.ts +281 -0
  89. package/coding/src/agent/process/sessions.ts +30 -0
  90. package/coding/src/agent/process/types.ts +358 -0
  91. package/coding/src/agent/read-path-set.ts +126 -0
  92. package/coding/src/agent/read.ts +713 -0
  93. package/coding/src/agent/repository/glob.ts +147 -0
  94. package/coding/src/agent/repository/indexed-search.ts +480 -0
  95. package/coding/src/agent/repository/list.ts +131 -0
  96. package/coding/src/agent/repository/operations.ts +22 -0
  97. package/coding/src/agent/repository/path.ts +98 -0
  98. package/coding/src/agent/repository/search.ts +277 -0
  99. package/coding/src/agent/repository/types.ts +243 -0
  100. package/coding/src/agent/repository/walk.ts +126 -0
  101. package/coding/src/agent/repository.ts +12 -0
  102. package/coding/src/agent/shell-background.ts +264 -0
  103. package/coding/src/agent/shell-output.ts +75 -0
  104. package/coding/src/agent/shell.ts +526 -0
  105. package/coding/src/agent/todo.ts +399 -0
  106. package/coding/src/agent/truncate.ts +251 -0
  107. package/coding/src/agent/write.ts +170 -0
  108. package/coding/src/ask-user-host.ts +48 -0
  109. package/coding/src/config.ts +278 -0
  110. package/coding/src/hard-deny.ts +97 -0
  111. package/coding/src/index.ts +318 -0
  112. package/coding/src/principal-guard.ts +84 -0
  113. package/coding/src/sandbox.ts +92 -0
  114. package/coding/src/security/approval.ts +144 -0
  115. package/coding/src/security/command-rules.ts +57 -0
  116. package/coding/src/security/docker-cli.ts +222 -0
  117. package/coding/src/security/docker-sandbox.ts +1205 -0
  118. package/coding/src/security/e2b-sandbox.ts +853 -0
  119. package/coding/src/security/egress/dns-pin.ts +88 -0
  120. package/coding/src/security/egress/index.ts +32 -0
  121. package/coding/src/security/egress/limits.ts +57 -0
  122. package/coding/src/security/egress/policy.ts +137 -0
  123. package/coding/src/security/egress/proxy.ts +599 -0
  124. package/coding/src/security/egress/types.ts +30 -0
  125. package/coding/src/security/index.ts +199 -0
  126. package/coding/src/security/native-sandbox.ts +639 -0
  127. package/coding/src/security/path-containment.ts +55 -0
  128. package/coding/src/security/sandbox-coding-operations.ts +392 -0
  129. package/coding/src/security/sandbox-fs-operations.ts +644 -0
  130. package/coding/src/security/sandbox-limits.ts +147 -0
  131. package/coding/src/security/sandbox-tar.ts +308 -0
  132. package/coding/src/security/sandbox.ts +179 -0
  133. package/coding/src/security/semaphore.ts +55 -0
  134. package/coding/src/targets.ts +110 -0
  135. package/coding/src/workspace/diff.ts +78 -0
  136. package/coding/src/workspace/errors.ts +29 -0
  137. package/coding/src/workspace/index.ts +5 -0
  138. package/coding/src/workspace/merge.ts +151 -0
  139. package/coding/src/workspace/routing.ts +76 -0
  140. package/coding/src/workspace/service.ts +584 -0
  141. package/computer-use/README.md +105 -0
  142. package/computer-use/skills/computer-use-linux/SKILL.md +17 -0
  143. package/computer-use/src/classify.ts +53 -0
  144. package/computer-use/src/command.ts +29 -0
  145. package/computer-use/src/config.ts +69 -0
  146. package/computer-use/src/create.ts +170 -0
  147. package/computer-use/src/devices.ts +247 -0
  148. package/computer-use/src/env.ts +28 -0
  149. package/computer-use/src/index.ts +157 -0
  150. package/computer-use/src/skill.ts +21 -0
  151. package/openapi/README.md +97 -0
  152. package/openapi/src/compile.ts +386 -0
  153. package/openapi/src/config.ts +73 -0
  154. package/openapi/src/errors.ts +16 -0
  155. package/openapi/src/execute.ts +241 -0
  156. package/openapi/src/index.ts +124 -0
  157. package/openapi/src/limits.ts +63 -0
  158. package/openapi/src/specs.ts +86 -0
  159. package/openapi/src/tools.ts +60 -0
  160. package/openapi/src/types.ts +61 -0
  161. package/package.json +171 -4
  162. package/research/README.md +72 -0
  163. package/research/skills/research-report/SKILL.md +12 -0
  164. package/research/skills/research-scoping/SKILL.md +10 -0
  165. package/research/skills/research-synthesis/SKILL.md +10 -0
  166. package/research/skills/source-triage/SKILL.md +10 -0
  167. package/research/src/check.ts +71 -0
  168. package/research/src/config.ts +41 -0
  169. package/research/src/index.ts +147 -0
  170. package/research/src/ledger.ts +157 -0
  171. package/research/src/urls.ts +21 -0
  172. package/web/README.md +287 -0
  173. package/web/skills/web-research/SKILL.md +17 -0
  174. package/web/src/brave.ts +66 -0
  175. package/web/src/cache.ts +151 -0
  176. package/web/src/config.ts +210 -0
  177. package/web/src/controls.ts +128 -0
  178. package/web/src/domains.ts +114 -0
  179. package/web/src/exa.ts +60 -0
  180. package/web/src/firecrawl.ts +160 -0
  181. package/web/src/index.ts +387 -0
  182. package/web/src/kagi.ts +73 -0
  183. package/web/src/limits.ts +55 -0
  184. package/web/src/native/convert.ts +84 -0
  185. package/web/src/native/fetch.ts +226 -0
  186. package/web/src/normalize.ts +131 -0
  187. package/web/src/obscura/cdp.ts +201 -0
  188. package/web/src/obscura/classify.ts +35 -0
  189. package/web/src/obscura/cli.ts +254 -0
  190. package/web/src/obscura/errors.ts +8 -0
  191. package/web/src/obscura/index.ts +59 -0
  192. package/web/src/obscura/limits.ts +92 -0
  193. package/web/src/obscura/mcp.ts +104 -0
  194. package/web/src/obscura/playwright.ts +133 -0
  195. package/web/src/obscura/process.ts +235 -0
  196. package/web/src/obscura/search-profile.ts +73 -0
  197. package/web/src/obscura/types.ts +48 -0
  198. package/web/src/obscura/web.ts +419 -0
  199. package/web/src/prompt-fetch.ts +88 -0
  200. package/web/src/render.ts +75 -0
  201. package/web/src/searxng.ts +78 -0
  202. package/web/src/slice.ts +139 -0
  203. package/web/src/tavily.ts +77 -0
  204. package/web/src/tools.ts +182 -0
  205. package/web/src/transport.ts +310 -0
  206. package/web/src/types.ts +199 -0
  207. package/work/README.md +77 -0
  208. package/work/THIRD_PARTY_NOTICES +24 -0
  209. package/work/docling/ocr.py +150 -0
  210. package/work/sandbox/Dockerfile +36 -0
  211. package/work/sandbox/soffice.sh +12 -0
  212. package/work/src/command.ts +29 -0
  213. package/work/src/config.ts +138 -0
  214. package/work/src/connectors/cli.ts +343 -0
  215. package/work/src/connectors/drafts.ts +647 -0
  216. package/work/src/connectors/errors.ts +8 -0
  217. package/work/src/connectors/file-bytes.ts +149 -0
  218. package/work/src/connectors/google-workspace-http.ts +399 -0
  219. package/work/src/connectors/google-workspace.ts +465 -0
  220. package/work/src/connectors/gws-tools.ts +378 -0
  221. package/work/src/connectors/http.ts +123 -0
  222. package/work/src/connectors/idempotency.ts +235 -0
  223. package/work/src/connectors/identity.ts +34 -0
  224. package/work/src/connectors/index.ts +93 -0
  225. package/work/src/connectors/limits.ts +50 -0
  226. package/work/src/connectors/m365-tools.ts +308 -0
  227. package/work/src/connectors/microsoft365-http.ts +428 -0
  228. package/work/src/connectors/microsoft365.ts +402 -0
  229. package/work/src/connectors/normalize.ts +120 -0
  230. package/work/src/connectors/tool-helpers.ts +398 -0
  231. package/work/src/connectors/tools.ts +42 -0
  232. package/work/src/connectors/types.ts +399 -0
  233. package/work/src/diagrams/canonicalize.ts +166 -0
  234. package/work/src/diagrams/caps.ts +52 -0
  235. package/work/src/diagrams/embed.ts +340 -0
  236. package/work/src/diagrams/errors.ts +76 -0
  237. package/work/src/diagrams/index.ts +81 -0
  238. package/work/src/diagrams/messages.ts +150 -0
  239. package/work/src/diagrams/origin.ts +52 -0
  240. package/work/src/diagrams/telemetry.ts +34 -0
  241. package/work/src/diagrams/xml.ts +267 -0
  242. package/work/src/document-extraction/index.ts +563 -0
  243. package/work/src/document-reader/ambient.d.ts +2 -0
  244. package/work/src/document-reader/errors.ts +7 -0
  245. package/work/src/document-reader/index.ts +181 -0
  246. package/work/src/document-reader/mistral-ocr.ts +318 -0
  247. package/work/src/document-reader/parsers.ts +171 -0
  248. package/work/src/documents/caps.ts +135 -0
  249. package/work/src/documents/diff.ts +269 -0
  250. package/work/src/documents/errors.ts +44 -0
  251. package/work/src/documents/fidelity.ts +98 -0
  252. package/work/src/documents/generate.ts +96 -0
  253. package/work/src/documents/hash.ts +8 -0
  254. package/work/src/documents/index.ts +14 -0
  255. package/work/src/documents/model-schema.ts +639 -0
  256. package/work/src/documents/parse.ts +252 -0
  257. package/work/src/documents/patch-history.ts +81 -0
  258. package/work/src/documents/patch.ts +476 -0
  259. package/work/src/documents/preview-html.ts +245 -0
  260. package/work/src/documents/preview.ts +227 -0
  261. package/work/src/documents/telemetry.ts +36 -0
  262. package/work/src/documents/translate/docx.ts +292 -0
  263. package/work/src/documents/translate/pptx.ts +304 -0
  264. package/work/src/documents/translate/xlsx.ts +137 -0
  265. package/work/src/documents/types.ts +188 -0
  266. package/work/src/index.ts +311 -0
  267. package/work/src/runtime/worker-pool-entry.ts +102 -0
  268. package/work/src/runtime/worker-pool.ts +267 -0
  269. package/work/src/sandbox/composition.ts +212 -0
  270. package/work/src/sandbox/image.ts +6 -0
  271. package/work/src/sandbox/index.ts +14 -0
  272. package/work/src/sheets/caps.ts +68 -0
  273. package/work/src/sheets/csv.ts +351 -0
  274. package/work/src/sheets/decimal.ts +388 -0
  275. package/work/src/sheets/errors.ts +52 -0
  276. package/work/src/sheets/index.ts +62 -0
  277. package/work/src/sheets/inference.ts +378 -0
  278. package/work/src/sheets/telemetry.ts +34 -0
  279. package/work/src/sheets/types.ts +162 -0
  280. package/work/src/sheets/xlsx.ts +388 -0
  281. package/work/src/skills/index.ts +8 -0
  282. package/work/src/skills/load.ts +43 -0
  283. package/work/src/tools/filesystem.ts +21 -0
  284. package/work/src/tools/index.ts +1 -0
  285. package/work/src/tools/local-filesystem.ts +33 -0
  286. package/work/src/tools/office.ts +311 -0
  287. package/work/vendor/hermes-agent/LICENSE +21 -0
  288. package/work/vendor/hermes-agent/skills/productivity/docx/LICENSE +21 -0
  289. package/work/vendor/hermes-agent/skills/productivity/docx/SKILL.md +196 -0
  290. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_comments.py +289 -0
  291. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_common.py +94 -0
  292. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_create.py +177 -0
  293. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_edit.py +250 -0
  294. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_read.py +149 -0
  295. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_revisions.py +147 -0
  296. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_template.py +70 -0
  297. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_validate.py +156 -0
  298. package/work/vendor/hermes-agent/skills/productivity/pdf/LICENSE +21 -0
  299. package/work/vendor/hermes-agent/skills/productivity/pdf/SKILL.md +125 -0
  300. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/_raster.py +76 -0
  301. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_marker.py +88 -0
  302. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_pymupdf.py +101 -0
  303. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_create.py +130 -0
  304. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_fill_form.py +97 -0
  305. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_form_layout.py +168 -0
  306. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_make_form.py +145 -0
  307. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_merge.py +50 -0
  308. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_meta.py +115 -0
  309. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_page_image.py +99 -0
  310. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_read.py +153 -0
  311. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_secure.py +71 -0
  312. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_split.py +84 -0
  313. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_stamp.py +143 -0
  314. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_watermark.py +51 -0
  315. package/work/vendor/hermes-agent/skills/productivity/powerpoint/LICENSE +21 -0
  316. package/work/vendor/hermes-agent/skills/productivity/powerpoint/SKILL.md +220 -0
  317. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_create.py +214 -0
  318. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_edit.py +436 -0
  319. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_from_template.py +88 -0
  320. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_read.py +131 -0
  321. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_render.py +93 -0
  322. package/work/vendor/hermes-agent/skills/productivity/xlsx/LICENSE +21 -0
  323. package/work/vendor/hermes-agent/skills/productivity/xlsx/SKILL.md +196 -0
  324. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/csv_to_xlsx.py +104 -0
  325. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_create.py +259 -0
  326. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_edit.py +263 -0
  327. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_read.py +160 -0
  328. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_recalc.py +111 -0
  329. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_restructure.py +337 -0
  330. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_to_csv.py +69 -0
  331. package/work/vendor-lock.json +11 -0
@@ -0,0 +1,385 @@
1
+ /**
2
+ * Thin goal→verify composition: plan Markdown + named checks + workflow
3
+ * suspend/approve + bounded handoff. Not a second agent/workflow engine.
4
+ */
5
+ import type { JsonObject, OwnershipScope, SecretRedactor } from "@arnilo/prism";
6
+ import {
7
+ defineWorkflow,
8
+ functionNode,
9
+ resumeWorkflow,
10
+ runWorkflow,
11
+ suspend,
12
+ type WorkflowCheckpointAdapter,
13
+ type WorkflowResumeValidator,
14
+ type WorkflowRunResult,
15
+ } from "@arnilo/prism-extensions/workflows";
16
+ import {
17
+ assertCodingResumeAllowed,
18
+ buildCodingCheckpointMetadata,
19
+ CODING_STATE_KEY,
20
+ type CodingCheckpointMetadata,
21
+ type CodingCheckSummary,
22
+ type CodingFingerprints,
23
+ type CodingHandoffSummary,
24
+ type CodingTodoItem,
25
+ codingCheckpointStatePatch,
26
+ codingPlanPathForTask,
27
+ createCodingPlanMarkdown,
28
+ fingerprintJson,
29
+ parseCodingPlanTodos,
30
+ readCodingCheckpointFromState,
31
+ readCodingPlanFile,
32
+ writeCodingPlanFile,
33
+ } from "./coding-checkpoint.js";
34
+ import { DEFAULT_MAX_CHECK_SUMMARY_BYTES, DEFAULT_MAX_PR_HANDOFF_BYTES } from "./limits.js";
35
+
36
+ export const CODING_GOAL_VERIFY_WORKFLOW_ID = "coding-goal-verify" as const;
37
+ export const CODING_GOAL_VERIFY_REVISION = "1" as const;
38
+ export const CODING_GOAL_VERIFY_SUSPEND_REASON = "approve-coding-goal-verify" as const;
39
+
40
+ export class CodingGoalVerifyError extends Error {
41
+ readonly code = "ERR_PRISM_CODING_GOAL_VERIFY";
42
+ constructor(message: string) {
43
+ super(message);
44
+ this.name = "CodingGoalVerifyError";
45
+ }
46
+ }
47
+
48
+ export interface CodingGoalVerifyApproval {
49
+ /** Host validator; required — helper fails closed without it. */
50
+ readonly validateResume: WorkflowResumeValidator;
51
+ readonly reason?: string;
52
+ }
53
+
54
+ export interface RunCodingGoalVerifyOptions {
55
+ readonly goal: string;
56
+ readonly cwd: string;
57
+ readonly taskId?: string;
58
+ readonly title?: string;
59
+ readonly baseBranch?: string;
60
+ readonly branch?: string;
61
+ /** Named checks to execute via `runCheck` (host-declared; no free-form shell). */
62
+ readonly checks: readonly string[];
63
+ readonly runCheck: (name: string) => Promise<CodingCheckSummary>;
64
+ /** Host-owned bounded handoff; required before completion. */
65
+ readonly buildHandoff: (input: {
66
+ readonly coding: CodingCheckpointMetadata;
67
+ readonly checks: readonly CodingCheckSummary[];
68
+ }) => Promise<CodingHandoffSummary>;
69
+ readonly approval: CodingGoalVerifyApproval;
70
+ readonly checkpoints: WorkflowCheckpointAdapter;
71
+ readonly ownership?: OwnershipScope;
72
+ readonly redactor?: SecretRedactor;
73
+ readonly signal?: AbortSignal;
74
+ readonly transitions?: import("@arnilo/prism-extensions/workflows").WorkflowTransitionChannel;
75
+ /** Second call after suspension — mirrors workflow resume. */
76
+ readonly resume?: {
77
+ readonly runId: string;
78
+ readonly decision: "approve" | "deny";
79
+ readonly expectedVersion: number;
80
+ readonly input?: unknown;
81
+ };
82
+ }
83
+
84
+ function requireCoding(state: Readonly<JsonObject>): CodingCheckpointMetadata {
85
+ const coding = readCodingCheckpointFromState(state);
86
+ if (!coding) throw new CodingGoalVerifyError("missing state.coding");
87
+ return coding;
88
+ }
89
+
90
+ function clipSummary(summary: string): string {
91
+ const max = DEFAULT_MAX_CHECK_SUMMARY_BYTES;
92
+ const bytes = Buffer.from(summary, "utf8");
93
+ if (bytes.length <= max) return summary;
94
+ return bytes.subarray(0, max).toString("utf8");
95
+ }
96
+
97
+ function normalizeChecks(checks: readonly CodingCheckSummary[]): CodingCheckSummary[] {
98
+ return checks.map((check) => ({
99
+ name: check.name,
100
+ exitCode: check.exitCode,
101
+ summary: clipSummary(check.summary),
102
+ }));
103
+ }
104
+
105
+ function assertHandoffBounded(handoff: CodingHandoffSummary): void {
106
+ const encoded = Buffer.byteLength(JSON.stringify(handoff), "utf8");
107
+ if (encoded > DEFAULT_MAX_PR_HANDOFF_BYTES) {
108
+ throw new CodingGoalVerifyError(`handoff exceeds ${DEFAULT_MAX_PR_HANDOFF_BYTES} byte limit (${encoded} bytes)`);
109
+ }
110
+ }
111
+
112
+ function fingerprintsFor(checks: readonly string[]): CodingFingerprints {
113
+ return {
114
+ workflowRevision: CODING_GOAL_VERIFY_REVISION,
115
+ toolFingerprint: fingerprintJson({ tools: ["coding_check", "git_pr_handoff"], checks }),
116
+ policyFingerprint: fingerprintJson({ requireApproval: [CODING_GOAL_VERIFY_SUSPEND_REASON] }),
117
+ };
118
+ }
119
+
120
+ function defaultTodos(checkNames: readonly string[]): CodingTodoItem[] {
121
+ return [
122
+ { id: "plan", text: "Write goal plan Markdown", done: false },
123
+ ...checkNames.map((name) => ({ id: `check-${name}`, text: `Run named check ${name}`, done: false })),
124
+ { id: "handoff", text: "Emit bounded PR handoff", done: false },
125
+ ];
126
+ }
127
+
128
+ function markTodos(todos: readonly CodingTodoItem[], doneIds: ReadonlySet<string>): CodingTodoItem[] {
129
+ return todos.map((todo) => (doneIds.has(todo.id) ? { ...todo, done: true } : todo));
130
+ }
131
+
132
+ /** Build the durable DAG used by `runCodingGoalVerify` (exported for hosts that want the definition alone). */
133
+ export function createCodingGoalVerifyWorkflow(options: {
134
+ readonly goal: string;
135
+ readonly cwd: string;
136
+ readonly taskId: string;
137
+ readonly title: string;
138
+ readonly baseBranch: string;
139
+ readonly branch: string;
140
+ readonly checks: readonly string[];
141
+ readonly runCheck: (name: string) => Promise<CodingCheckSummary>;
142
+ readonly buildHandoff: RunCodingGoalVerifyOptions["buildHandoff"];
143
+ readonly suspendReason: string;
144
+ }) {
145
+ const planPath = codingPlanPathForTask(options.taskId);
146
+ const fps = () => fingerprintsFor(options.checks);
147
+
148
+ const planNode = functionNode({
149
+ execute: async (ctx) => {
150
+ const todos = defaultTodos(options.checks);
151
+ const markdown = createCodingPlanMarkdown({
152
+ title: options.title,
153
+ taskId: options.taskId,
154
+ status: "planned",
155
+ todos,
156
+ notes: options.goal,
157
+ });
158
+ const plan = await writeCodingPlanFile({
159
+ workspaceRoot: options.cwd,
160
+ planPath,
161
+ markdown,
162
+ });
163
+ const metadata = buildCodingCheckpointMetadata({
164
+ taskId: options.taskId,
165
+ workspaceRoot: options.cwd,
166
+ baseBranch: options.baseBranch,
167
+ branch: options.branch,
168
+ planPath,
169
+ plan,
170
+ fingerprints: fps(),
171
+ todos: parseCodingPlanTodos(markdown),
172
+ status: "planned",
173
+ });
174
+ await ctx.updateState(codingCheckpointStatePatch(metadata), { mode: "merge" });
175
+ return { planPath, planSha256: plan.sha256 };
176
+ },
177
+ });
178
+
179
+ const verifyNode = functionNode({
180
+ execute: async (ctx) => {
181
+ const coding = requireCoding(ctx.state);
182
+ const checks = normalizeChecks(await Promise.all(options.checks.map((name) => options.runCheck(name))));
183
+ const failed = checks.some((check) => check.exitCode !== 0);
184
+ const done = new Set<string>(["plan", ...options.checks.map((name) => `check-${name}`)]);
185
+ const todos = markTodos(coding.todos.length ? coding.todos : defaultTodos(options.checks), done);
186
+ const markdown = createCodingPlanMarkdown({
187
+ title: options.title,
188
+ taskId: options.taskId,
189
+ status: failed ? "awaiting_approval" : "ready_for_handoff",
190
+ todos,
191
+ notes: options.goal,
192
+ });
193
+ const plan = await writeCodingPlanFile({
194
+ workspaceRoot: options.cwd,
195
+ planPath,
196
+ markdown,
197
+ });
198
+ const next = buildCodingCheckpointMetadata({
199
+ ...coding,
200
+ plan,
201
+ checks,
202
+ todos: parseCodingPlanTodos(markdown),
203
+ status: failed ? "awaiting_approval" : "ready_for_handoff",
204
+ fingerprints: fps(),
205
+ updatedAt: new Date().toISOString(),
206
+ });
207
+ await ctx.updateState(codingCheckpointStatePatch(next), { mode: "merge" });
208
+ return { checks, failed };
209
+ },
210
+ });
211
+
212
+ const reviewNode = functionNode({
213
+ execute: async (ctx) => {
214
+ const coding = requireCoding(ctx.state);
215
+ const failed = coding.checks.some((check) => check.exitCode !== 0);
216
+ if (!failed) return { approved: true, skipped: true };
217
+ if (!ctx.resume) {
218
+ return suspend({
219
+ reason: options.suspendReason,
220
+ data: {
221
+ taskId: coding.taskId,
222
+ branch: coding.branch,
223
+ planSha256: coding.plan.sha256,
224
+ checks: coding.checks,
225
+ },
226
+ resumeSchema: {
227
+ type: "object",
228
+ required: ["reviewer"],
229
+ properties: { reviewer: { type: "string" } },
230
+ },
231
+ });
232
+ }
233
+ const reviewer = (ctx.resume.input as { reviewer?: string } | undefined)?.reviewer ?? "unknown";
234
+ return { approved: true, reviewer, planSha256: coding.plan.sha256 };
235
+ },
236
+ });
237
+
238
+ const handoffNode = functionNode({
239
+ execute: async (ctx) => {
240
+ const coding = requireCoding(ctx.state);
241
+ const planFile = await readCodingPlanFile({
242
+ workspaceRoot: options.cwd,
243
+ planPath: coding.planPath,
244
+ expected: coding.plan,
245
+ });
246
+ assertCodingResumeAllowed({
247
+ metadata: coding,
248
+ expected: fps(),
249
+ expectedWorkspaceRoot: options.cwd,
250
+ expectedBaseBranch: options.baseBranch,
251
+ planBytes: Buffer.from(planFile.markdown, "utf8"),
252
+ });
253
+
254
+ const handoff = await options.buildHandoff({ coding, checks: coding.checks });
255
+ assertHandoffBounded(handoff);
256
+
257
+ const todos = markTodos(
258
+ coding.todos.length ? coding.todos : defaultTodos(options.checks),
259
+ new Set(["plan", "handoff", ...options.checks.map((name) => `check-${name}`)]),
260
+ );
261
+ const markdown = createCodingPlanMarkdown({
262
+ title: options.title,
263
+ taskId: options.taskId,
264
+ status: "completed",
265
+ todos,
266
+ notes: options.goal,
267
+ });
268
+ const plan = await writeCodingPlanFile({
269
+ workspaceRoot: options.cwd,
270
+ planPath,
271
+ markdown,
272
+ });
273
+ const next = buildCodingCheckpointMetadata({
274
+ ...coding,
275
+ plan,
276
+ handoff,
277
+ todos: parseCodingPlanTodos(markdown),
278
+ status: "completed",
279
+ fingerprints: fps(),
280
+ updatedAt: new Date().toISOString(),
281
+ });
282
+ await ctx.updateState(codingCheckpointStatePatch(next), { mode: "merge" });
283
+ return { handoff, codingStatus: next.status };
284
+ },
285
+ });
286
+
287
+ return defineWorkflow({
288
+ revision: CODING_GOAL_VERIFY_REVISION,
289
+ id: CODING_GOAL_VERIFY_WORKFLOW_ID,
290
+ nodes: {
291
+ plan: planNode,
292
+ verify: verifyNode,
293
+ review: reviewNode,
294
+ handoff: handoffNode,
295
+ },
296
+ edges: [
297
+ ["plan", "verify"],
298
+ ["verify", "review"],
299
+ ["review", "handoff"],
300
+ ],
301
+ limits: { maxConcurrency: 1, maxStateBytes: 64 * 1024 },
302
+ });
303
+ }
304
+
305
+ /**
306
+ * Run (or resume) a thin goal→verify coding composition.
307
+ * Fails closed when `approval` / `approval.validateResume` is missing.
308
+ */
309
+ export async function runCodingGoalVerify(options: RunCodingGoalVerifyOptions): Promise<WorkflowRunResult> {
310
+ if (!options.approval?.validateResume) {
311
+ throw new CodingGoalVerifyError("approval.validateResume is required");
312
+ }
313
+ if (!Array.isArray(options.checks) || options.checks.length < 1) {
314
+ throw new CodingGoalVerifyError("checks must declare at least one named check");
315
+ }
316
+ for (const name of options.checks) {
317
+ if (typeof name !== "string" || !/^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(name)) {
318
+ throw new CodingGoalVerifyError(`invalid check name: ${String(name)}`);
319
+ }
320
+ }
321
+ if (typeof options.runCheck !== "function") {
322
+ throw new CodingGoalVerifyError("runCheck is required");
323
+ }
324
+ if (typeof options.buildHandoff !== "function") {
325
+ throw new CodingGoalVerifyError("buildHandoff is required");
326
+ }
327
+ if (typeof options.goal !== "string" || options.goal.trim().length < 1) {
328
+ throw new CodingGoalVerifyError("goal is required");
329
+ }
330
+ if (typeof options.cwd !== "string" || options.cwd.length < 1) {
331
+ throw new CodingGoalVerifyError("cwd is required");
332
+ }
333
+
334
+ const taskId = options.taskId ?? "goal";
335
+ const title = options.title ?? options.goal.slice(0, 120);
336
+ const baseBranch = options.baseBranch ?? "main";
337
+ const branch = options.branch ?? `codex/${taskId}`;
338
+ const suspendReason = options.approval.reason ?? CODING_GOAL_VERIFY_SUSPEND_REASON;
339
+
340
+ const workflow = createCodingGoalVerifyWorkflow({
341
+ goal: options.goal,
342
+ cwd: options.cwd,
343
+ taskId,
344
+ title,
345
+ baseBranch,
346
+ branch,
347
+ checks: options.checks,
348
+ runCheck: options.runCheck,
349
+ buildHandoff: options.buildHandoff,
350
+ suspendReason,
351
+ });
352
+
353
+ const validateState = async (input: { readonly value: JsonObject }) => {
354
+ if (CODING_STATE_KEY in input.value) {
355
+ readCodingCheckpointFromState(input.value);
356
+ }
357
+ };
358
+
359
+ const shared = {
360
+ checkpoints: options.checkpoints,
361
+ redactor: options.redactor,
362
+ ownership: options.ownership,
363
+ validateState,
364
+ validateResume: options.approval.validateResume,
365
+ signal: options.signal,
366
+ transitions: options.transitions,
367
+ };
368
+
369
+ if (options.resume) {
370
+ return resumeWorkflow(
371
+ workflow,
372
+ { runId: options.resume.runId, workflowId: workflow.id },
373
+ {
374
+ ...shared,
375
+ resume: {
376
+ decision: options.resume.decision,
377
+ expectedVersion: options.resume.expectedVersion,
378
+ input: options.resume.input,
379
+ },
380
+ },
381
+ );
382
+ }
383
+
384
+ return runWorkflow(workflow, { goal: options.goal, baseBranch }, shared);
385
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Worker entry for the `grep` tool's regex mode (plan 189 Task 4).
3
+ *
4
+ * Compiles the pattern once and matches one file's text per message, so a pattern with
5
+ * catastrophic backtracking runs off the main thread and stays killable with `terminate()`.
6
+ * Only file text is ever posted in — the main thread resolves and contains paths.
7
+ */
8
+ import { matchLines } from "./repository/search.js";
9
+
10
+ interface CompileMessage {
11
+ readonly type: "compile";
12
+ readonly pattern: string;
13
+ readonly flags: string;
14
+ readonly maxLineBytes: number;
15
+ }
16
+
17
+ interface MatchMessage {
18
+ readonly type: "match";
19
+ readonly id: number;
20
+ readonly text: string;
21
+ readonly context: number;
22
+ }
23
+
24
+ type Request = CompileMessage | MatchMessage;
25
+
26
+ interface WorkerScope {
27
+ onmessage: ((event: { data: Request }) => void) | null;
28
+ postMessage: (value: unknown) => void;
29
+ }
30
+
31
+ const scope = globalThis as unknown as WorkerScope;
32
+
33
+ let compiled: RegExp | null = null;
34
+ let maxLineBytes = 0;
35
+
36
+ function reason(error: unknown): string {
37
+ return error instanceof Error ? error.message : String(error);
38
+ }
39
+
40
+ scope.onmessage = (event) => {
41
+ const message = event.data;
42
+
43
+ if (message.type === "compile") {
44
+ try {
45
+ // No "g"/"y": the matcher probes each line from the start, so state between lines would lie.
46
+ compiled = new RegExp(message.pattern, message.flags);
47
+ maxLineBytes = message.maxLineBytes;
48
+ scope.postMessage({ type: "ready" });
49
+ } catch (error) {
50
+ scope.postMessage({ type: "invalid", message: reason(error) });
51
+ }
52
+ return;
53
+ }
54
+
55
+ const regex = compiled;
56
+ if (regex === null) {
57
+ scope.postMessage({ type: "error", id: message.id, message: "pattern was not compiled" });
58
+ return;
59
+ }
60
+ try {
61
+ const matches = matchLines(
62
+ message.text,
63
+ (line) => {
64
+ const hit = regex.exec(line);
65
+ return hit ? { column: hit.index + 1 } : null;
66
+ },
67
+ message.context,
68
+ maxLineBytes,
69
+ );
70
+ scope.postMessage({ type: "matches", id: message.id, matches });
71
+ } catch (error) {
72
+ scope.postMessage({ type: "error", id: message.id, message: reason(error) });
73
+ }
74
+ };