@stigmer/runner 3.15.1 → 3.15.2-dev.20260913223433

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 (518) hide show
  1. package/README.md +2 -4
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/__test-utils__/execution-record-fixture.d.ts +14 -0
  4. package/dist/__test-utils__/execution-record-fixture.js +4 -0
  5. package/dist/__test-utils__/execution-record-fixture.js.map +1 -1
  6. package/dist/__test-utils__/file-review-projection.d.ts +40 -0
  7. package/dist/__test-utils__/file-review-projection.js +136 -0
  8. package/dist/__test-utils__/file-review-projection.js.map +1 -0
  9. package/dist/__test-utils__/harness-contract/types.d.ts +23 -1
  10. package/dist/__test-utils__/harness-contract/types.js +15 -0
  11. package/dist/__test-utils__/harness-contract/types.js.map +1 -1
  12. package/dist/__test-utils__/hermetic-activity.d.ts +44 -12
  13. package/dist/__test-utils__/hermetic-activity.js +52 -14
  14. package/dist/__test-utils__/hermetic-activity.js.map +1 -1
  15. package/dist/__test-utils__/model-registry-fixture.d.ts +32 -7
  16. package/dist/__test-utils__/model-registry-fixture.js +31 -7
  17. package/dist/__test-utils__/model-registry-fixture.js.map +1 -1
  18. package/dist/__test-utils__/turn-input-fixture.d.ts +1 -1
  19. package/dist/__test-utils__/turn-input-fixture.js +1 -1
  20. package/dist/__test-utils__/turn-input-fixture.js.map +1 -1
  21. package/dist/activities/call-agent.js +2 -2
  22. package/dist/activities/call-agent.js.map +1 -1
  23. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js +45 -3
  24. package/dist/activities/execute-cursor/__test-utils__/contract-subject.js.map +1 -1
  25. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.d.ts +0 -9
  26. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js +2 -41
  27. package/dist/activities/execute-cursor/__test-utils__/hermetic-cursor.js.map +1 -1
  28. package/dist/activities/execute-cursor/adapter.d.ts +7 -5
  29. package/dist/activities/execute-cursor/adapter.js +7 -5
  30. package/dist/activities/execute-cursor/adapter.js.map +1 -1
  31. package/dist/activities/execute-cursor/approval-policy.d.ts +5 -2
  32. package/dist/activities/execute-cursor/approval-policy.js +5 -2
  33. package/dist/activities/execute-cursor/approval-policy.js.map +1 -1
  34. package/dist/activities/execute-cursor/approval-state.d.ts +16 -8
  35. package/dist/activities/execute-cursor/approval-state.js +6 -3
  36. package/dist/activities/execute-cursor/approval-state.js.map +1 -1
  37. package/dist/activities/execute-cursor/cas-observations.d.ts +14 -2
  38. package/dist/activities/execute-cursor/cas-observations.js +19 -2
  39. package/dist/activities/execute-cursor/cas-observations.js.map +1 -1
  40. package/dist/activities/execute-cursor/cursor-capabilities.d.ts +8 -4
  41. package/dist/activities/execute-cursor/cursor-capabilities.js +21 -4
  42. package/dist/activities/execute-cursor/cursor-capabilities.js.map +1 -1
  43. package/dist/activities/execute-cursor/message-translator.d.ts +12 -20
  44. package/dist/activities/execute-cursor/message-translator.js +19 -32
  45. package/dist/activities/execute-cursor/message-translator.js.map +1 -1
  46. package/dist/activities/execute-cursor/prompt-builder.d.ts +48 -58
  47. package/dist/activities/execute-cursor/prompt-builder.js +76 -95
  48. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  49. package/dist/activities/execute-cursor/turn-boundary.d.ts +27 -55
  50. package/dist/activities/execute-cursor/turn-boundary.js +30 -90
  51. package/dist/activities/execute-cursor/turn-boundary.js.map +1 -1
  52. package/dist/activities/execute-cursor/turn-settle.d.ts +11 -7
  53. package/dist/activities/execute-cursor/turn-settle.js +37 -49
  54. package/dist/activities/execute-cursor/turn-settle.js.map +1 -1
  55. package/dist/activities/execute-cursor/turn-setup.d.ts +16 -24
  56. package/dist/activities/execute-cursor/turn-setup.js +29 -59
  57. package/dist/activities/execute-cursor/turn-setup.js.map +1 -1
  58. package/dist/activities/execute-cursor/turn-stream.d.ts +3 -8
  59. package/dist/activities/execute-cursor/turn-stream.js +9 -22
  60. package/dist/activities/execute-cursor/turn-stream.js.map +1 -1
  61. package/dist/activities/execute-cursor/turn.js +5 -1
  62. package/dist/activities/execute-cursor/turn.js.map +1 -1
  63. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.d.ts +93 -0
  64. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js +348 -0
  65. package/dist/activities/execute-deep-agent/__test-utils__/contract-subject.js.map +1 -0
  66. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.d.ts +170 -0
  67. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js +225 -0
  68. package/dist/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.js.map +1 -0
  69. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.d.ts +24 -0
  70. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js +41 -0
  71. package/dist/activities/execute-deep-agent/__test-utils__/hitl-script.js.map +1 -0
  72. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.d.ts +54 -0
  73. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js +72 -0
  74. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model-module.js.map +1 -0
  75. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.d.ts +187 -23
  76. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js +238 -27
  77. package/dist/activities/execute-deep-agent/__test-utils__/scripted-model.js.map +1 -1
  78. package/dist/activities/execute-deep-agent/adapter.d.ts +41 -0
  79. package/dist/activities/execute-deep-agent/adapter.js +78 -0
  80. package/dist/activities/execute-deep-agent/adapter.js.map +1 -0
  81. package/dist/activities/execute-deep-agent/cas-capture-observer.d.ts +8 -0
  82. package/dist/activities/execute-deep-agent/cas-capture-observer.js +9 -0
  83. package/dist/activities/execute-deep-agent/cas-capture-observer.js.map +1 -1
  84. package/dist/activities/execute-deep-agent/deep-agent-capabilities.d.ts +31 -0
  85. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js +40 -0
  86. package/dist/activities/execute-deep-agent/deep-agent-capabilities.js.map +1 -0
  87. package/dist/activities/execute-deep-agent/execution-state.d.ts +4 -11
  88. package/dist/activities/execute-deep-agent/execution-state.js +4 -12
  89. package/dist/activities/execute-deep-agent/execution-state.js.map +1 -1
  90. package/dist/activities/execute-deep-agent/hitl.d.ts +49 -47
  91. package/dist/activities/execute-deep-agent/hitl.js +77 -103
  92. package/dist/activities/execute-deep-agent/hitl.js.map +1 -1
  93. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +51 -23
  94. package/dist/activities/execute-deep-agent/prompt-builder.js +115 -76
  95. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  96. package/dist/activities/execute-deep-agent/status-builder-shared.d.ts +18 -32
  97. package/dist/activities/execute-deep-agent/status-builder-shared.js +10 -65
  98. package/dist/activities/execute-deep-agent/status-builder-shared.js.map +1 -1
  99. package/dist/activities/execute-deep-agent/streaming-side-effects.d.ts +10 -8
  100. package/dist/activities/execute-deep-agent/streaming-side-effects.js +12 -14
  101. package/dist/activities/execute-deep-agent/streaming-side-effects.js.map +1 -1
  102. package/dist/activities/execute-deep-agent/subagent-tracker.d.ts +36 -13
  103. package/dist/activities/execute-deep-agent/subagent-tracker.js +76 -39
  104. package/dist/activities/execute-deep-agent/subagent-tracker.js.map +1 -1
  105. package/dist/activities/execute-deep-agent/subagent-transformer.d.ts +25 -28
  106. package/dist/activities/execute-deep-agent/subagent-transformer.js +29 -82
  107. package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
  108. package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -2
  109. package/dist/activities/execute-deep-agent/subagent-wiring.js +2 -2
  110. package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
  111. package/dist/activities/execute-deep-agent/turn-settle.d.ts +42 -0
  112. package/dist/activities/execute-deep-agent/turn-settle.js +146 -0
  113. package/dist/activities/execute-deep-agent/turn-settle.js.map +1 -0
  114. package/dist/activities/execute-deep-agent/turn-setup.d.ts +212 -0
  115. package/dist/activities/execute-deep-agent/turn-setup.js +430 -0
  116. package/dist/activities/execute-deep-agent/turn-setup.js.map +1 -0
  117. package/dist/activities/execute-deep-agent/turn-stream.d.ts +97 -0
  118. package/dist/activities/execute-deep-agent/turn-stream.js +242 -0
  119. package/dist/activities/execute-deep-agent/turn-stream.js.map +1 -0
  120. package/dist/activities/execute-deep-agent/turn.d.ts +42 -0
  121. package/dist/activities/execute-deep-agent/turn.js +116 -0
  122. package/dist/activities/execute-deep-agent/turn.js.map +1 -0
  123. package/dist/activities/execute-deep-agent/v3-event-recorder.d.ts +6 -5
  124. package/dist/activities/execute-deep-agent/v3-event-recorder.js +6 -5
  125. package/dist/activities/execute-deep-agent/v3-event-recorder.js.map +1 -1
  126. package/dist/activities/execute-deep-agent/v3-events.d.ts +1 -1
  127. package/dist/activities/execute-deep-agent/v3-events.js +1 -1
  128. package/dist/activities/execute-deep-agent/v3-status-builder.d.ts +60 -17
  129. package/dist/activities/execute-deep-agent/v3-status-builder.js +72 -57
  130. package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
  131. package/dist/harness/approval-decisions.d.ts +61 -0
  132. package/dist/harness/approval-decisions.js +102 -0
  133. package/dist/harness/approval-decisions.js.map +1 -0
  134. package/dist/harness/capabilities.d.ts +16 -5
  135. package/dist/harness/capabilities.js +9 -0
  136. package/dist/harness/capabilities.js.map +1 -1
  137. package/dist/harness/capture.d.ts +144 -0
  138. package/dist/harness/capture.js +219 -0
  139. package/dist/harness/capture.js.map +1 -0
  140. package/dist/harness/persist-chokepoint.d.ts +19 -4
  141. package/dist/harness/persist-chokepoint.js +17 -4
  142. package/dist/harness/persist-chokepoint.js.map +1 -1
  143. package/dist/harness/run-turn.js +115 -29
  144. package/dist/harness/run-turn.js.map +1 -1
  145. package/dist/harness/terminal-table.d.ts +40 -11
  146. package/dist/harness/terminal-table.js +58 -19
  147. package/dist/harness/terminal-table.js.map +1 -1
  148. package/dist/harness/turn-context.d.ts +141 -76
  149. package/dist/harness/turn-context.js +194 -99
  150. package/dist/harness/turn-context.js.map +1 -1
  151. package/dist/harness/types.d.ts +65 -12
  152. package/dist/harness/types.js +8 -2
  153. package/dist/harness/types.js.map +1 -1
  154. package/dist/harness-adapters.d.ts +12 -8
  155. package/dist/harness-adapters.js +17 -9
  156. package/dist/harness-adapters.js.map +1 -1
  157. package/dist/middleware/approval-gate.d.ts +1 -1
  158. package/dist/middleware/approval-gate.js +1 -1
  159. package/dist/middleware/approval-gate.js.map +1 -1
  160. package/dist/middleware/cost-advisory.d.ts +39 -0
  161. package/dist/middleware/{cost-cap.js → cost-advisory.js} +37 -55
  162. package/dist/middleware/cost-advisory.js.map +1 -0
  163. package/dist/middleware/index.d.ts +23 -12
  164. package/dist/middleware/index.js +26 -18
  165. package/dist/middleware/index.js.map +1 -1
  166. package/dist/middleware/types.d.ts +3 -2
  167. package/dist/runner-manager.js +1 -5
  168. package/dist/runner-manager.js.map +1 -1
  169. package/dist/runner.js +1 -5
  170. package/dist/runner.js.map +1 -1
  171. package/dist/shared/attachment-resolver.d.ts +41 -18
  172. package/dist/shared/attachment-resolver.js +178 -46
  173. package/dist/shared/attachment-resolver.js.map +1 -1
  174. package/dist/shared/attachment-zip.d.ts +85 -0
  175. package/dist/shared/attachment-zip.js +185 -0
  176. package/dist/shared/attachment-zip.js.map +1 -0
  177. package/dist/shared/connect-backfill.js +5 -4
  178. package/dist/shared/connect-backfill.js.map +1 -1
  179. package/dist/shared/cost-guard.d.ts +3 -3
  180. package/dist/shared/cost-guard.js +3 -3
  181. package/dist/shared/execution-status-writer.d.ts +5 -5
  182. package/dist/shared/execution-status-writer.js +5 -5
  183. package/dist/shared/extract-structured-output.d.ts +8 -7
  184. package/dist/shared/extract-structured-output.js +8 -7
  185. package/dist/shared/extract-structured-output.js.map +1 -1
  186. package/dist/shared/filereview/cas-progress.d.ts +1 -18
  187. package/dist/shared/filereview/cas-progress.js +4 -0
  188. package/dist/shared/filereview/cas-progress.js.map +1 -1
  189. package/dist/shared/filereview/cas-touched.d.ts +56 -0
  190. package/dist/shared/filereview/cas-touched.js +63 -0
  191. package/dist/shared/filereview/cas-touched.js.map +1 -0
  192. package/dist/shared/filereview/index.d.ts +2 -1
  193. package/dist/shared/filereview/index.js +2 -1
  194. package/dist/shared/filereview/index.js.map +1 -1
  195. package/dist/shared/mcp-resolver.d.ts +4 -5
  196. package/dist/shared/mcp-resolver.js +4 -5
  197. package/dist/shared/mcp-resolver.js.map +1 -1
  198. package/dist/shared/persist-decision.d.ts +3 -4
  199. package/dist/shared/persist-decision.js +3 -4
  200. package/dist/shared/persist-decision.js.map +1 -1
  201. package/dist/shared/plan-mode-permissions.d.ts +2 -2
  202. package/dist/shared/plan-mode-permissions.js +2 -2
  203. package/dist/shared/plan-mode-prompt.d.ts +1 -1
  204. package/dist/shared/plan-mode-prompt.js +1 -1
  205. package/dist/shared/prompt-sections.d.ts +163 -0
  206. package/dist/shared/prompt-sections.js +164 -0
  207. package/dist/shared/prompt-sections.js.map +1 -0
  208. package/dist/shared/skill-resolver.d.ts +4 -2
  209. package/dist/shared/skill-resolver.js +4 -2
  210. package/dist/shared/skill-resolver.js.map +1 -1
  211. package/dist/shared/tool-rounds.d.ts +32 -0
  212. package/dist/shared/tool-rounds.js +43 -0
  213. package/dist/shared/tool-rounds.js.map +1 -1
  214. package/dist/shared/tool-row.d.ts +34 -0
  215. package/dist/shared/tool-row.js +52 -0
  216. package/dist/shared/tool-row.js.map +1 -1
  217. package/dist/shared/workspace/session-provision.d.ts +3 -3
  218. package/dist/shared/workspace/session-provision.js +3 -3
  219. package/dist/shared/workspace/stigmer-link.d.ts +3 -3
  220. package/dist/shared/workspace/stigmer-link.js +3 -3
  221. package/dist/shared/workspace/writeback-coordinator.d.ts +15 -22
  222. package/dist/shared/workspace/writeback-coordinator.js +16 -53
  223. package/dist/shared/workspace/writeback-coordinator.js.map +1 -1
  224. package/dist/tools/index.d.ts +1 -1
  225. package/dist/tools/index.js +1 -1
  226. package/package.json +4 -4
  227. package/src/__test-utils__/__tests__/harness-contract-self-check.test.ts +1 -0
  228. package/src/__test-utils__/execution-record-fixture.ts +18 -2
  229. package/src/__test-utils__/file-review-projection.ts +156 -0
  230. package/src/__test-utils__/git-workspace-fixture.ts +58 -0
  231. package/src/__test-utils__/harness-boot-order-child.ts +7 -2
  232. package/src/__test-utils__/harness-contract/contract.ts +33 -20
  233. package/src/__test-utils__/harness-contract/recording-sink.ts +11 -1
  234. package/src/__test-utils__/harness-contract/runtime-contract.ts +328 -10
  235. package/src/__test-utils__/harness-contract/scripted-adapter.ts +38 -6
  236. package/src/__test-utils__/harness-contract/types.ts +27 -3
  237. package/src/__test-utils__/hermetic-activity.ts +52 -14
  238. package/src/__test-utils__/model-registry-fixture.ts +32 -7
  239. package/src/__test-utils__/module-specifiers.ts +24 -0
  240. package/src/__test-utils__/turn-input-fixture.ts +2 -2
  241. package/src/__tests__/harness-boot-order.test.ts +9 -2
  242. package/src/activities/call-agent.ts +2 -2
  243. package/src/activities/execute-cursor/__test-utils__/contract-subject.ts +47 -3
  244. package/src/activities/execute-cursor/__test-utils__/hermetic-cursor.ts +2 -48
  245. package/src/activities/execute-cursor/__tests__/approval-decisions-agree.test.ts +1 -1
  246. package/src/activities/execute-cursor/__tests__/approval-gate.test.ts +6 -1
  247. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +52 -27
  248. package/src/activities/execute-cursor/__tests__/cas-observations.test.ts +25 -0
  249. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.everything.prompt.md +166 -0
  250. package/src/activities/execute-cursor/__tests__/goldens/prompt.enhanced.plan-mode.prompt.md +186 -0
  251. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.recovery.prompt.md +191 -0
  252. package/src/activities/execute-cursor/__tests__/goldens/prompt.hitl.reinvocation.prompt.md +13 -0
  253. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.prefixed.prompt.md +32 -0
  254. package/src/activities/execute-cursor/__tests__/goldens/prompt.resumed.raw.prompt.md +1 -0
  255. package/src/activities/execute-cursor/__tests__/hermetic/file-review-capture.test.ts +1 -2
  256. package/src/activities/execute-cursor/__tests__/hermetic/goldens/sdk-error-at-create.status.json +4 -0
  257. package/src/activities/execute-cursor/__tests__/hermetic/harness-contract.test.ts +24 -4
  258. package/src/activities/execute-cursor/__tests__/hermetic/stream-self-stop-arms.test.ts +6 -5
  259. package/src/activities/execute-cursor/__tests__/hermetic/thrown-error-arms.test.ts +9 -0
  260. package/src/activities/execute-cursor/__tests__/hitl-resume-history.test.ts +11 -8
  261. package/src/activities/execute-cursor/__tests__/prompt-goldens.test.ts +229 -0
  262. package/src/activities/execute-cursor/__tests__/same-identity-reproposal.test.ts +3 -3
  263. package/src/activities/execute-cursor/__tests__/sequential-gate-resume.test.ts +2 -2
  264. package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +78 -234
  265. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +1 -26
  266. package/src/activities/execute-cursor/adapter.ts +7 -5
  267. package/src/activities/execute-cursor/approval-policy.ts +5 -2
  268. package/src/activities/execute-cursor/approval-state.ts +16 -8
  269. package/src/activities/execute-cursor/cas-observations.ts +20 -2
  270. package/src/activities/execute-cursor/cursor-capabilities.ts +24 -5
  271. package/src/activities/execute-cursor/message-translator.ts +29 -41
  272. package/src/activities/execute-cursor/prompt-builder.ts +99 -157
  273. package/src/activities/execute-cursor/turn-boundary.ts +34 -140
  274. package/src/activities/execute-cursor/turn-settle.ts +37 -51
  275. package/src/activities/execute-cursor/turn-setup.ts +30 -70
  276. package/src/activities/execute-cursor/turn-stream.ts +8 -31
  277. package/src/activities/execute-cursor/turn.ts +5 -1
  278. package/src/activities/execute-deep-agent/__test-utils__/contract-subject.ts +391 -0
  279. package/src/activities/execute-deep-agent/__test-utils__/hermetic-deep-agent.ts +313 -0
  280. package/src/activities/execute-deep-agent/__test-utils__/hitl-script.ts +48 -0
  281. package/src/activities/execute-deep-agent/__test-utils__/scripted-model-module.ts +85 -0
  282. package/src/activities/execute-deep-agent/__test-utils__/scripted-model.ts +383 -36
  283. package/src/activities/execute-deep-agent/__tests__/adapter-graph-is-sdk-free.test.ts +76 -0
  284. package/src/activities/execute-deep-agent/__tests__/adapter-is-temporal-free.test.ts +47 -0
  285. package/src/activities/execute-deep-agent/__tests__/adapter.test.ts +80 -0
  286. package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +1 -1
  287. package/src/activities/execute-deep-agent/__tests__/execution-state-extended.test.ts +0 -2
  288. package/src/activities/execute-deep-agent/__tests__/execution-state.test.ts +0 -3
  289. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.build-from-plan.prompt.md +172 -0
  290. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.everything.prompt.md +167 -0
  291. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.minimal.prompt.md +36 -0
  292. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.plan-mode.prompt.md +178 -0
  293. package/src/activities/execute-deep-agent/__tests__/goldens/system-prompt.skills-below-threshold.prompt.md +158 -0
  294. package/src/activities/execute-deep-agent/__tests__/hermetic/file-review-capture.test.ts +210 -0
  295. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn1.status.json +74 -0
  296. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve-all-lease.turn2.status.json +104 -0
  297. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/approve.turn2.status.json +78 -0
  298. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/file-review-capture.status.json +138 -0
  299. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/gate.turn1.status.json +68 -0
  300. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn1.status.json +154 -0
  301. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/inline-artifact.turn2.status.json +116 -0
  302. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.after-tool.status.json +69 -0
  303. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/pause.loop.mid-tool.status.json +67 -0
  304. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/plain-turn.status.json +47 -0
  305. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/platform-stop.status.json +68 -0
  306. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/recursion-limit.persisted.status.json +280 -0
  307. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/reject.turn2.status.json +77 -0
  308. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/resolution-error.status.json +18 -0
  309. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn2.status.json +99 -0
  310. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sequential-gates.turn3.status.json +109 -0
  311. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/skip.turn2.status.json +76 -0
  312. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.text-fallback.status.json +51 -0
  313. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tier2.status.json +51 -0
  314. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/structured-output.tool-strategy.status.json +56 -0
  315. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/sub-agent-delegation.status.json +90 -0
  316. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/tool-call.status.json +70 -0
  317. package/src/activities/execute-deep-agent/__tests__/hermetic/goldens/worker-shutdown.status.json +71 -0
  318. package/src/activities/execute-deep-agent/__tests__/hermetic/harness-contract.test.ts +144 -0
  319. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-approve-all-lease.test.ts +184 -0
  320. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-round-trips.test.ts +203 -0
  321. package/src/activities/execute-deep-agent/__tests__/hermetic/hitl-sequential-gates.test.ts +170 -0
  322. package/src/activities/execute-deep-agent/__tests__/hermetic/inline-artifact-across-gate.test.ts +175 -0
  323. package/src/activities/execute-deep-agent/__tests__/hermetic/pause-vs-shutdown.test.ts +206 -0
  324. package/src/activities/execute-deep-agent/__tests__/hermetic/plain-turn.test.ts +142 -0
  325. package/src/activities/execute-deep-agent/__tests__/hermetic/platform-stop.test.ts +126 -0
  326. package/src/activities/execute-deep-agent/__tests__/hermetic/recursion-limit.test.ts +139 -0
  327. package/src/activities/execute-deep-agent/__tests__/hermetic/resolution-error.test.ts +122 -0
  328. package/src/activities/execute-deep-agent/__tests__/hermetic/structured-output.test.ts +236 -0
  329. package/src/activities/execute-deep-agent/__tests__/hermetic/sub-agent-delegation.test.ts +161 -0
  330. package/src/activities/execute-deep-agent/__tests__/hermetic/tool-call.test.ts +157 -0
  331. package/src/activities/execute-deep-agent/__tests__/hermetic/workspace-lock-timeout.test.ts +152 -0
  332. package/src/activities/execute-deep-agent/__tests__/hitl.test.ts +50 -122
  333. package/src/activities/execute-deep-agent/__tests__/inline-publisher.test.ts +8 -6
  334. package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +2 -2
  335. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +35 -35
  336. package/src/activities/execute-deep-agent/__tests__/prompt-goldens.test.ts +247 -0
  337. package/src/activities/execute-deep-agent/__tests__/scripted-model.test.ts +329 -0
  338. package/src/activities/execute-deep-agent/__tests__/status-builder-shared.test.ts +1 -20
  339. package/src/activities/execute-deep-agent/__tests__/streaming-side-effects.test.ts +78 -0
  340. package/src/activities/execute-deep-agent/__tests__/subagent-gitignored-capture.test.ts +1 -1
  341. package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +2 -2
  342. package/src/activities/execute-deep-agent/__tests__/subagent-tracker.test.ts +57 -31
  343. package/src/activities/execute-deep-agent/__tests__/subagent-transformer.test.ts +19 -79
  344. package/src/activities/execute-deep-agent/__tests__/subagent-wiring.test.ts +15 -15
  345. package/src/activities/execute-deep-agent/__tests__/summarization-verification.test.ts +1 -1
  346. package/src/activities/execute-deep-agent/__tests__/turn-stream.test.ts +391 -0
  347. package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +343 -38
  348. package/src/activities/execute-deep-agent/__tests__/vision-input.test.ts +5 -5
  349. package/src/activities/execute-deep-agent/adapter.ts +94 -0
  350. package/src/activities/execute-deep-agent/cas-capture-observer.ts +11 -0
  351. package/src/activities/execute-deep-agent/deep-agent-capabilities.ts +43 -0
  352. package/src/activities/execute-deep-agent/execution-state.ts +4 -13
  353. package/src/activities/execute-deep-agent/hitl.ts +100 -123
  354. package/src/activities/execute-deep-agent/prompt-builder.ts +141 -115
  355. package/src/activities/execute-deep-agent/status-builder-shared.ts +21 -84
  356. package/src/activities/execute-deep-agent/streaming-side-effects.ts +13 -19
  357. package/src/activities/execute-deep-agent/subagent-tracker.ts +77 -42
  358. package/src/activities/execute-deep-agent/subagent-transformer.ts +46 -105
  359. package/src/activities/execute-deep-agent/subagent-wiring.ts +5 -4
  360. package/src/activities/execute-deep-agent/turn-settle.ts +164 -0
  361. package/src/activities/execute-deep-agent/turn-setup.ts +541 -0
  362. package/src/activities/execute-deep-agent/turn-stream.ts +313 -0
  363. package/src/activities/execute-deep-agent/turn.ts +131 -0
  364. package/src/activities/execute-deep-agent/v3-event-recorder.ts +6 -5
  365. package/src/activities/execute-deep-agent/v3-events.ts +1 -1
  366. package/src/activities/execute-deep-agent/v3-status-builder.ts +84 -63
  367. package/src/harness/__tests__/approval-decisions.test.ts +116 -0
  368. package/src/harness/__tests__/capture.test.ts +268 -0
  369. package/src/harness/__tests__/mount-skills.test.ts +169 -0
  370. package/src/harness/__tests__/persist-chokepoint.test.ts +38 -2
  371. package/src/harness/__tests__/run-turn-deterministic.test.ts +94 -0
  372. package/src/harness/__tests__/run-turn.test.ts +39 -23
  373. package/src/harness/__tests__/turn-attachments-vision.test.ts +80 -0
  374. package/src/harness/__tests__/turn-context.test.ts +73 -26
  375. package/src/harness/approval-decisions.ts +104 -0
  376. package/src/harness/capabilities.ts +16 -5
  377. package/src/harness/capture.ts +301 -0
  378. package/src/harness/persist-chokepoint.ts +24 -4
  379. package/src/harness/run-turn.ts +120 -29
  380. package/src/harness/terminal-table.ts +61 -20
  381. package/src/harness/turn-context.ts +208 -111
  382. package/src/harness/types.ts +66 -12
  383. package/src/harness-adapters.ts +17 -9
  384. package/src/middleware/__tests__/approval-gate.test.ts +1 -1
  385. package/src/middleware/__tests__/cost-advisory.test.ts +113 -0
  386. package/src/middleware/approval-gate.ts +2 -2
  387. package/src/middleware/{cost-cap.ts → cost-advisory.ts} +40 -70
  388. package/src/middleware/index.ts +29 -29
  389. package/src/middleware/types.ts +3 -2
  390. package/src/runner-manager.ts +0 -8
  391. package/src/runner.ts +0 -8
  392. package/src/shared/__tests__/attachment-naming.test.ts +6 -19
  393. package/src/shared/__tests__/attachment-resolver.test.ts +158 -8
  394. package/src/shared/__tests__/attachment-zip.test.ts +236 -0
  395. package/src/shared/__tests__/bedrock-adapter.test.ts +1 -1
  396. package/src/shared/__tests__/blueprint-resolver.test.ts +43 -0
  397. package/src/shared/__tests__/cost-guard.test.ts +3 -3
  398. package/src/shared/__tests__/prompt-sections.test.ts +167 -0
  399. package/src/shared/__tests__/secret-leak-scan.test.ts +2 -2
  400. package/src/{activities/execute-deep-agent → shared}/__tests__/stamp-flowed-rows.test.ts +33 -10
  401. package/src/shared/__tests__/vertex-adapter.test.ts +1 -1
  402. package/src/shared/attachment-resolver.ts +218 -55
  403. package/src/shared/attachment-zip.ts +281 -0
  404. package/src/shared/connect-backfill.ts +9 -11
  405. package/src/shared/cost-guard.ts +3 -3
  406. package/src/shared/execution-status-writer.ts +5 -5
  407. package/src/shared/extract-structured-output.ts +8 -7
  408. package/src/shared/filereview/__tests__/capture.test.ts +86 -4
  409. package/src/shared/filereview/__tests__/cas-progress.test.ts +2 -1
  410. package/src/shared/filereview/cas-progress.ts +5 -19
  411. package/src/shared/filereview/cas-touched.ts +89 -0
  412. package/src/shared/filereview/index.ts +4 -2
  413. package/src/shared/mcp-resolver.ts +4 -5
  414. package/src/shared/persist-decision.ts +3 -4
  415. package/src/shared/plan-mode-permissions.ts +2 -2
  416. package/src/shared/plan-mode-prompt.ts +1 -1
  417. package/src/shared/prompt-sections.ts +256 -0
  418. package/src/shared/skill-resolver.ts +4 -2
  419. package/src/shared/tool-rounds.ts +48 -0
  420. package/src/shared/tool-row.ts +61 -0
  421. package/src/shared/workspace/__tests__/stigmer-link.test.ts +7 -22
  422. package/src/shared/workspace/__tests__/writeback-coordinator.test.ts +20 -61
  423. package/src/shared/workspace/session-provision.ts +3 -3
  424. package/src/shared/workspace/stigmer-link.ts +3 -3
  425. package/src/shared/workspace/writeback-coordinator.ts +16 -64
  426. package/src/tools/index.ts +1 -1
  427. package/dist/activities/execute-cursor/capture-flow.d.ts +0 -142
  428. package/dist/activities/execute-cursor/capture-flow.js +0 -285
  429. package/dist/activities/execute-cursor/capture-flow.js.map +0 -1
  430. package/dist/activities/execute-cursor/command-provenance.d.ts +0 -48
  431. package/dist/activities/execute-cursor/command-provenance.js +0 -38
  432. package/dist/activities/execute-cursor/command-provenance.js.map +0 -1
  433. package/dist/activities/execute-deep-agent/attachment-injector.d.ts +0 -134
  434. package/dist/activities/execute-deep-agent/attachment-injector.js +0 -386
  435. package/dist/activities/execute-deep-agent/attachment-injector.js.map +0 -1
  436. package/dist/activities/execute-deep-agent/command-provenance.d.ts +0 -61
  437. package/dist/activities/execute-deep-agent/command-provenance.js +0 -72
  438. package/dist/activities/execute-deep-agent/command-provenance.js.map +0 -1
  439. package/dist/activities/execute-deep-agent/environment.d.ts +0 -24
  440. package/dist/activities/execute-deep-agent/environment.js +0 -58
  441. package/dist/activities/execute-deep-agent/environment.js.map +0 -1
  442. package/dist/activities/execute-deep-agent/event-recorder.d.ts +0 -21
  443. package/dist/activities/execute-deep-agent/event-recorder.js +0 -67
  444. package/dist/activities/execute-deep-agent/event-recorder.js.map +0 -1
  445. package/dist/activities/execute-deep-agent/index.d.ts +0 -15
  446. package/dist/activities/execute-deep-agent/index.js +0 -918
  447. package/dist/activities/execute-deep-agent/index.js.map +0 -1
  448. package/dist/activities/execute-deep-agent/mcp-gate.d.ts +0 -28
  449. package/dist/activities/execute-deep-agent/mcp-gate.js +0 -22
  450. package/dist/activities/execute-deep-agent/mcp-gate.js.map +0 -1
  451. package/dist/activities/execute-deep-agent/post-stream.d.ts +0 -23
  452. package/dist/activities/execute-deep-agent/post-stream.js +0 -71
  453. package/dist/activities/execute-deep-agent/post-stream.js.map +0 -1
  454. package/dist/activities/execute-deep-agent/setup.d.ts +0 -136
  455. package/dist/activities/execute-deep-agent/setup.js +0 -767
  456. package/dist/activities/execute-deep-agent/setup.js.map +0 -1
  457. package/dist/activities/execute-deep-agent/stamp-flowed-rows.d.ts +0 -36
  458. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js +0 -56
  459. package/dist/activities/execute-deep-agent/stamp-flowed-rows.js.map +0 -1
  460. package/dist/activities/execute-deep-agent/status-builder.d.ts +0 -93
  461. package/dist/activities/execute-deep-agent/status-builder.js +0 -365
  462. package/dist/activities/execute-deep-agent/status-builder.js.map +0 -1
  463. package/dist/activities/execute-deep-agent/streaming-terminal.d.ts +0 -21
  464. package/dist/activities/execute-deep-agent/streaming-terminal.js +0 -80
  465. package/dist/activities/execute-deep-agent/streaming-terminal.js.map +0 -1
  466. package/dist/activities/execute-deep-agent/streaming-v3.d.ts +0 -13
  467. package/dist/activities/execute-deep-agent/streaming-v3.js +0 -174
  468. package/dist/activities/execute-deep-agent/streaming-v3.js.map +0 -1
  469. package/dist/activities/execute-deep-agent/streaming.d.ts +0 -81
  470. package/dist/activities/execute-deep-agent/streaming.js +0 -160
  471. package/dist/activities/execute-deep-agent/streaming.js.map +0 -1
  472. package/dist/middleware/cost-cap.d.ts +0 -22
  473. package/dist/middleware/cost-cap.js.map +0 -1
  474. package/dist/middleware/graceful-stop.d.ts +0 -17
  475. package/dist/middleware/graceful-stop.js +0 -63
  476. package/dist/middleware/graceful-stop.js.map +0 -1
  477. package/dist/shared/skill-writer.d.ts +0 -75
  478. package/dist/shared/skill-writer.js +0 -207
  479. package/dist/shared/skill-writer.js.map +0 -1
  480. package/src/activities/execute-cursor/__tests__/capture-flow.test.ts +0 -1032
  481. package/src/activities/execute-cursor/__tests__/command-provenance.test.ts +0 -240
  482. package/src/activities/execute-cursor/__tests__/progress-substrate.test.ts +0 -169
  483. package/src/activities/execute-cursor/capture-flow.ts +0 -379
  484. package/src/activities/execute-cursor/command-provenance.ts +0 -73
  485. package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +0 -1161
  486. package/src/activities/execute-deep-agent/__tests__/command-provenance.test.ts +0 -252
  487. package/src/activities/execute-deep-agent/__tests__/environment.test.ts +0 -108
  488. package/src/activities/execute-deep-agent/__tests__/event-recorder.test.ts +0 -150
  489. package/src/activities/execute-deep-agent/__tests__/hitl-integration.test.ts +0 -226
  490. package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +0 -318
  491. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +0 -351
  492. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +0 -293
  493. package/src/activities/execute-deep-agent/__tests__/index.test.ts +0 -99
  494. package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +0 -44
  495. package/src/activities/execute-deep-agent/__tests__/post-stream.test.ts +0 -112
  496. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +0 -358
  497. package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +0 -1933
  498. package/src/activities/execute-deep-agent/__tests__/streaming-terminal.test.ts +0 -40
  499. package/src/activities/execute-deep-agent/__tests__/streaming-v3.test.ts +0 -597
  500. package/src/activities/execute-deep-agent/__tests__/streaming.test.ts +0 -508
  501. package/src/activities/execute-deep-agent/attachment-injector.ts +0 -627
  502. package/src/activities/execute-deep-agent/command-provenance.ts +0 -102
  503. package/src/activities/execute-deep-agent/environment.ts +0 -76
  504. package/src/activities/execute-deep-agent/event-recorder.ts +0 -95
  505. package/src/activities/execute-deep-agent/index.ts +0 -1072
  506. package/src/activities/execute-deep-agent/mcp-gate.ts +0 -37
  507. package/src/activities/execute-deep-agent/post-stream.ts +0 -109
  508. package/src/activities/execute-deep-agent/setup.ts +0 -1081
  509. package/src/activities/execute-deep-agent/stamp-flowed-rows.ts +0 -64
  510. package/src/activities/execute-deep-agent/status-builder.ts +0 -481
  511. package/src/activities/execute-deep-agent/streaming-terminal.ts +0 -106
  512. package/src/activities/execute-deep-agent/streaming-v3.ts +0 -277
  513. package/src/activities/execute-deep-agent/streaming.ts +0 -313
  514. package/src/middleware/__tests__/cost-cap.test.ts +0 -192
  515. package/src/middleware/__tests__/graceful-stop.test.ts +0 -105
  516. package/src/middleware/graceful-stop.ts +0 -86
  517. package/src/shared/__tests__/skill-writer.test.ts +0 -372
  518. package/src/shared/skill-writer.ts +0 -266
@@ -0,0 +1,391 @@
1
+ /**
2
+ * The native deep-agent harness as a `HarnessContractSubject` — the REAL
3
+ * `createDeepAgentAdapter()` driven through the harness contract kit, with
4
+ * the kit's engine-neutral scenario vocabulary translated onto the
5
+ * `ScriptedModel` double that every native hermetic golden already runs on.
6
+ *
7
+ * The sibling of `execute-cursor/__test-utils__/contract-subject.ts` (the
8
+ * mold) and of `gateway-substrate.ts` (the native side of the approval
9
+ * contract kit): the kit owns the invariants and the runtime stand-in, this
10
+ * module owns the ENGINE — what the model will do on its next call — and
11
+ * reports what really happened. The adapter under test is the production
12
+ * one, untouched; the model client is the one module doubled
13
+ * (`scripted-model-module.ts`, S3 M0 ruling Q-M0-1), and the tools the model
14
+ * calls are deepagents' real built-ins over the real gate.
15
+ *
16
+ * ── The engine is per execution, and its memory is the conversation ────────
17
+ * One `ScriptedModel` per execution, minted at the first `arrange` and handed
18
+ * out by the double for every build production requests under that
19
+ * execution's `headerScope.executionId` — the attribution header the proxy
20
+ * already carries, so concurrent executions each reach their own engine
21
+ * through an id nothing was added to send. The kit arranges a turn as a
22
+ * PLAN, and on every model call the engine plays the first step the
23
+ * conversation does not yet show: a `propose` or `read` whose tool-call id
24
+ * already has a `ToolMessage` anywhere on the thread (executed, or the
25
+ * gate's denial) is done; a `say` already spoken in THIS turn's segment
26
+ * (after the last human message) is done; `usage` folds into the turn's
27
+ * first model call only. Nothing is remembered on the subject: the sqlite
28
+ * checkpoint IS the engine's memory, which is why the same plan is right on
29
+ * a `Command(resume)` (the tool result is in the transcript before the model
30
+ * is asked) and on a later turn of the same thread (an approved-and-run call
31
+ * is not proposed again — Cursor's "obedient model" of Q-M4-4, derived
32
+ * instead of stored).
33
+ *
34
+ * ── The translation, one rule per word ──────────────────────────────────────
35
+ * - `say(text)` → the turn's text. A second `say` before any tool step
36
+ * inserts an ungated `think` call as the step boundary:
37
+ * a LangGraph agent cannot speak twice without acting
38
+ * (only the cost-cap arm's `[say, usage, say]` needs it).
39
+ * - `propose(id, a)` → ONE gated built-in whose execution is counted by a
40
+ * REAL side effect the subject reads back:
41
+ * `write r` → `edit_file` appending `id` as a line to a
42
+ * ledger the subject seeded at the path the backend
43
+ * resolves `r` to (`resolveWorkspacePath`, the virtual
44
+ * root). FILE_EDIT and FILE_WRITE are one `write`
45
+ * category by design (`tool-kind.ts`); unlike
46
+ * `write_file`, which refuses an existing path and so
47
+ * leaves no trace of a second execution, an edit
48
+ * counts EVERY execution.
49
+ * `shell r` → `execute` appending `id` to the session's
50
+ * shell ledger, `r` riding as a trailing comment.
51
+ * `delete` and `mcp` are refused as test bugs: no kit
52
+ * invariant asks for them here.
53
+ * `executionCount(id)` is the number of ledger lines
54
+ * equal to `id` — the safety-critical observable, read
55
+ * off disk, independent of anything the adapter wrote.
56
+ * - `read(id, path)` → `read_file` of a file the subject seeds; the ungated
57
+ * tool call every harness flushes a persist on.
58
+ * - `usage(delta)` → the model turn's `usage_metadata` (the cache buckets
59
+ * under `input_token_details`); consecutive deltas sum,
60
+ * the kit judges sums.
61
+ * - `hang` → the turn parks on the run's abort signal after its
62
+ * chunks (`ScriptedTurn.ends`); the park resolves
63
+ * `whenHanging()`. Never a timer.
64
+ * - `fail(msg, s)` → the turn throws `msg` after its chunks. `engine` and
65
+ * `internal` are one act here: the native adapter has
66
+ * ONE failure surface (`turn.ts` classifies every
67
+ * escaped error `internal`); `actionable` is refused.
68
+ * - `limit` → a `think` call under a fresh id on every model call,
69
+ * until the graph's recursion limit stops the run.
70
+ * - `cancelled` → refused: this harness has no engine-side cancel (the
71
+ * runtime arm is declared off for it).
72
+ */
73
+
74
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
75
+ import { dirname, join } from "node:path";
76
+ import { isAIMessage, isHumanMessage, isToolMessage, type BaseMessage } from "@langchain/core/messages";
77
+
78
+ import type { Config } from "../../../config.js";
79
+ import type { HarnessAdapter } from "../../../harness/types.js";
80
+ import type { ProposedAction } from "../../../__test-utils__/approval-contract/types.js";
81
+ import type {
82
+ EngineView,
83
+ HarnessContractSubject,
84
+ ScenarioStep,
85
+ SubjectInputOverrides,
86
+ TurnScenario,
87
+ } from "../../../__test-utils__/harness-contract/types.js";
88
+ import type { HermeticEnvironment } from "../../../__test-utils__/hermetic-activity.js";
89
+ import { resolveWorkspacePath } from "../../../shared/file-change.js";
90
+ import { createDeepAgentAdapter } from "../adapter.js";
91
+ import { hermeticDeepAgentConfig } from "./hermetic-deep-agent.js";
92
+ import { ScriptedModel, type ScriptedToolCall, type ScriptedTurn, type ScriptedUsage } from "./scripted-model.js";
93
+ import { bindScriptedModel } from "./scripted-model-module.js";
94
+
95
+ /** The user's message every kit turn asks; the prompt builder needs one and the kit has none to give. */
96
+ const KIT_USER_MESSAGE = "Do what the scenario says.";
97
+
98
+ /** The one line a write ledger starts with; every execution appends its id under it, so the edit's anchor stays unique. */
99
+ const WRITE_LEDGER_MARK = "KIT-LEDGER";
100
+
101
+ /** What a seeded `read` target contains; the content is never asserted, the completed row is. */
102
+ const READ_FILE_CONTENT = "seeded by the harness contract kit\n";
103
+
104
+ export interface DeepAgentContractSubject extends HarnessContractSubject {
105
+ readonly adapter: HarnessAdapter;
106
+ /** The engine minted for an execution, once the kit has arranged a turn for it. */
107
+ engineFor(executionId: string): ScriptedModel | undefined;
108
+ /** The conversation the engine was last asked with, for the subject file's observations of what the graph shows the model. */
109
+ lastTranscriptOf(executionId: string): readonly BaseMessage[] | undefined;
110
+ /** The session's workspace directory, as the runtime's provisioner resolves it and as this subject seeds it. */
111
+ workspaceDirOf(sessionId: string): string;
112
+ }
113
+
114
+ /**
115
+ * Build the subject over one hermetic environment (the temp `HOME` the sqlite
116
+ * checkpoints land under, the temp workspace root). The environment is the
117
+ * caller's to create before and dispose after; the model-client double is
118
+ * bound for the module here, so a file holds one subject.
119
+ */
120
+ export function createDeepAgentContractSubject(env: HermeticEnvironment): DeepAgentContractSubject {
121
+ return new DeepAgentSubject(env);
122
+ }
123
+
124
+ /** Where one proposal's executions are counted; recorded at `arrange`, read by `executionCount`. */
125
+ type LedgerRef = { readonly kind: "write"; readonly file: string } | { readonly kind: "shell"; readonly file: string };
126
+
127
+ /** The turn the kit arranged for an execution, and the view it was arranged from. */
128
+ interface ArrangedTurn {
129
+ readonly steps: TurnScenario;
130
+ readonly view: EngineView;
131
+ }
132
+
133
+ class DeepAgentSubject implements DeepAgentContractSubject {
134
+ readonly name = "deep-agent";
135
+ readonly harness = "deep-agent" as const;
136
+ readonly adapter: HarnessAdapter;
137
+ readonly config: Config;
138
+
139
+ private readonly engines = new Map<string, ScriptedModel>();
140
+ private readonly arranged = new Map<string, ArrangedTurn>();
141
+ private readonly lastTranscripts = new Map<string, readonly BaseMessage[]>();
142
+ private readonly ledgers = new Map<string, LedgerRef>();
143
+ private readonly hangWaiters: Array<() => void> = [];
144
+ private mintCounter = 0;
145
+
146
+ constructor(private readonly env: HermeticEnvironment) {
147
+ this.config = hermeticDeepAgentConfig(env, "sqlite");
148
+ this.adapter = createDeepAgentAdapter();
149
+ bindScriptedModel((opts) => {
150
+ const executionId = opts.headerScope?.executionId;
151
+ const engine = executionId ? this.engines.get(executionId) : undefined;
152
+ if (!engine) {
153
+ throw new Error(`${this.name}: buildChatModel asked for execution '${executionId ?? "<none>"}' but no turn was arranged for it (kit bug)`);
154
+ }
155
+ return engine;
156
+ });
157
+ }
158
+
159
+ // ── HarnessContractSubject ────────────────────────────────────────────────
160
+
161
+ arrange(turn: TurnScenario, view: EngineView): void {
162
+ // A word this subject cannot translate is refused HERE, as a test bug:
163
+ // refused at play time it would surface as an engine failure and read as
164
+ // the adapter's behaviour.
165
+ for (const step of turn) this.refuseUnproducible(step);
166
+ mkdirSync(this.workspaceDirOf(view.sessionId), { recursive: true });
167
+ for (const step of turn) this.seedFor(step, view);
168
+ this.arranged.set(view.executionId, { steps: turn, view });
169
+ if (!this.engines.has(view.executionId)) this.engines.set(view.executionId, this.mintEngine(view.executionId));
170
+ }
171
+
172
+ inputOverrides(view: EngineView): SubjectInputOverrides {
173
+ // No model is named: the adapter resolves the registry's featured native
174
+ // model, which is the fixture's — the production "no model named" path.
175
+ return { workspaceDir: this.workspaceDirOf(view.sessionId), message: KIT_USER_MESSAGE };
176
+ }
177
+
178
+ whenHanging(): Promise<void> {
179
+ return new Promise((resolve) => this.hangWaiters.push(resolve));
180
+ }
181
+
182
+ executionCount(toolCallId: string): number {
183
+ const ledger = this.ledgers.get(toolCallId);
184
+ if (!ledger || !existsSync(ledger.file)) return 0;
185
+ return readFileSync(ledger.file, "utf8")
186
+ .split("\n")
187
+ .filter((line) => line === toolCallId).length;
188
+ }
189
+
190
+ // ── The subject file's observations ──────────────────────────────────────
191
+
192
+ engineFor(executionId: string): ScriptedModel | undefined {
193
+ return this.engines.get(executionId);
194
+ }
195
+
196
+ lastTranscriptOf(executionId: string): readonly BaseMessage[] | undefined {
197
+ return this.lastTranscripts.get(executionId);
198
+ }
199
+
200
+ /** The directory the runtime's provisioner gives a session with no workspace entries (`session-root.ts`). */
201
+ workspaceDirOf(sessionId: string): string {
202
+ return join(this.env.workspaceRootDir, "sessions", sessionId);
203
+ }
204
+
205
+ // ── The engine ────────────────────────────────────────────────────────────
206
+
207
+ private mintEngine(executionId: string): ScriptedModel {
208
+ return new ScriptedModel(() => (transcript) => this.play(executionId, transcript), [], {
209
+ onPark: () => {
210
+ for (const waiter of this.hangWaiters.splice(0)) waiter();
211
+ },
212
+ });
213
+ }
214
+
215
+ /** The words this subject has no honest translation for (see the header); each is a kit-file bug, named. */
216
+ private refuseUnproducible(step: ScenarioStep): void {
217
+ switch (step.kind) {
218
+ case "propose":
219
+ if (step.action.kind !== "write" && step.action.kind !== "shell") {
220
+ throw new Error(`${this.name}: propose(${step.action.kind}) is not translated by this subject (no kit invariant asks for it); test bug`);
221
+ }
222
+ return;
223
+ case "fail":
224
+ if (step.surface === "actionable") {
225
+ throw new Error(`${this.name}: fail(..., "actionable") is not producible by this subject (the native adapter has one failure surface, internal); test bug`);
226
+ }
227
+ return;
228
+ case "cancelled":
229
+ throw new Error(`${this.name}: cancelled() is not producible by this subject (this harness has no engine-side cancel; the runtime arm is declared off for it); test bug`);
230
+ case "say":
231
+ case "read":
232
+ case "usage":
233
+ case "hang":
234
+ case "limit":
235
+ return;
236
+ default: {
237
+ const exhaustive: never = step;
238
+ throw new Error(`${this.name}: unknown scenario step ${JSON.stringify(exhaustive)}`);
239
+ }
240
+ }
241
+ }
242
+
243
+ /** The shell ledger of one session; outside the session's workspace so the engine's tree holds only what the engine wrote. */
244
+ private shellLedgerOf(sessionId: string): string {
245
+ return join(this.env.workspaceRootDir, "kit-ledgers", `${sessionId}.log`);
246
+ }
247
+
248
+ /** Put on disk what a step's tool will find there: the write ledger under its mark, the read target. */
249
+ private seedFor(step: ScenarioStep, view: EngineView): void {
250
+ const workspaceDir = this.workspaceDirOf(view.sessionId);
251
+ if (step.kind === "propose" && step.action.kind === "write") {
252
+ const file = resolveWorkspacePath(step.action.resource, workspaceDir, true).absolutePath;
253
+ seedFile(file, `${WRITE_LEDGER_MARK}\n`);
254
+ this.ledgers.set(step.toolCallId, { kind: "write", file });
255
+ } else if (step.kind === "propose" && step.action.kind === "shell") {
256
+ const file = this.shellLedgerOf(view.sessionId);
257
+ mkdirSync(dirname(file), { recursive: true });
258
+ this.ledgers.set(step.toolCallId, { kind: "shell", file });
259
+ } else if (step.kind === "read") {
260
+ seedFile(resolveWorkspacePath(step.path, workspaceDir, true).absolutePath, READ_FILE_CONTENT);
261
+ }
262
+ }
263
+
264
+ /**
265
+ * The one turn to play now: the plan's steps in order, each skipped when
266
+ * the conversation already shows it, until a step closes the turn (a tool
267
+ * call, a hang, a failure) or the plan runs out (an empty message, which
268
+ * ends the graph run).
269
+ */
270
+ private play(executionId: string, transcript: readonly BaseMessage[]): ScriptedTurn {
271
+ const plan = this.arranged.get(executionId);
272
+ if (!plan) throw new Error(`${this.name}: the model was asked for execution '${executionId}' with no turn arranged (kit bug)`);
273
+ this.lastTranscripts.set(executionId, transcript);
274
+ const settled = settledToolCallIds(transcript);
275
+ const segment = messagesOfThisTurn(transcript);
276
+ const spoken = new Set(segment.filter((m) => isAIMessage(m)).map((m) => m.text));
277
+ const firstCallOfTurn = !segment.some((m) => isAIMessage(m));
278
+
279
+ let text: string | undefined;
280
+ let usage: ScriptedUsage | undefined;
281
+ const close = (rest: Partial<ScriptedTurn>): ScriptedTurn => ({ text, usage, ...rest });
282
+
283
+ for (const step of plan.steps) {
284
+ switch (step.kind) {
285
+ case "say":
286
+ if (spoken.has(step.text)) break;
287
+ if (text !== undefined) return close({ toolCalls: [this.thinkCall("boundary")] });
288
+ text = step.text;
289
+ break;
290
+ case "propose":
291
+ if (settled.has(step.toolCallId)) break;
292
+ return close({ toolCalls: [this.gatedCall(step.toolCallId, step.action, plan.view)] });
293
+ case "read":
294
+ if (settled.has(step.toolCallId)) break;
295
+ return close({ toolCalls: [{ id: step.toolCallId, name: "read_file", args: { file_path: step.path } }] });
296
+ case "usage":
297
+ if (!firstCallOfTurn) break;
298
+ usage = addUsage(usage, step.delta);
299
+ break;
300
+ case "hang":
301
+ return close({ ends: { kind: "hang" } });
302
+ case "fail":
303
+ return close({ ends: { kind: "fail", error: new Error(step.message) } });
304
+ case "limit":
305
+ return close({ toolCalls: [this.thinkCall("limit")] });
306
+ case "cancelled":
307
+ // Refused at `arrange`; unreachable in a plan that got this far.
308
+ throw new Error(`${this.name}: cancelled() reached the engine (arrange should have refused it)`);
309
+ default: {
310
+ const exhaustive: never = step;
311
+ throw new Error(`${this.name}: unknown scenario step ${JSON.stringify(exhaustive)}`);
312
+ }
313
+ }
314
+ }
315
+ return close({});
316
+ }
317
+
318
+ /** An ungated, effect-free tool call: the step boundary a LangGraph agent needs between two texts, and the loop a `limit` spins. */
319
+ private thinkCall(why: "boundary" | "limit"): ScriptedToolCall {
320
+ return { id: `kit-think-${why}-${++this.mintCounter}`, name: "think", args: { thought: `kit: ${why}` } };
321
+ }
322
+
323
+ private gatedCall(toolCallId: string, action: ProposedAction, view: EngineView): ScriptedToolCall {
324
+ switch (action.kind) {
325
+ case "write":
326
+ return {
327
+ id: toolCallId,
328
+ name: "edit_file",
329
+ args: {
330
+ file_path: action.resource,
331
+ old_string: WRITE_LEDGER_MARK,
332
+ new_string: `${WRITE_LEDGER_MARK}\n${toolCallId}`,
333
+ },
334
+ };
335
+ case "shell":
336
+ return {
337
+ id: toolCallId,
338
+ name: "execute",
339
+ args: { command: `printf '%s\\n' '${toolCallId}' >> '${this.shellLedgerOf(view.sessionId)}' # ${action.resource}` },
340
+ };
341
+ case "delete":
342
+ case "read":
343
+ case "mcp":
344
+ // Refused at `arrange`; unreachable in a plan that got this far.
345
+ throw new Error(`${this.name}: propose(${action.kind}) reached the engine (arrange should have refused it)`);
346
+ default: {
347
+ const exhaustive: never = action.kind;
348
+ throw new Error(`${this.name}: unknown action kind ${String(exhaustive)}`);
349
+ }
350
+ }
351
+ }
352
+ }
353
+
354
+ // ── Reading the conversation ────────────────────────────────────────────────
355
+
356
+ /** Every tool call the thread has an answer for — executed, or answered by the gate's denial. */
357
+ function settledToolCallIds(transcript: readonly BaseMessage[]): ReadonlySet<string> {
358
+ const ids = new Set<string>();
359
+ for (const m of transcript) if (isToolMessage(m)) ids.add(m.tool_call_id);
360
+ return ids;
361
+ }
362
+
363
+ /** The messages after the last human message: what this kit turn has said and done so far. */
364
+ function messagesOfThisTurn(transcript: readonly BaseMessage[]): readonly BaseMessage[] {
365
+ let start = 0;
366
+ transcript.forEach((m, i) => {
367
+ if (isHumanMessage(m)) start = i + 1;
368
+ });
369
+ return transcript.slice(start);
370
+ }
371
+
372
+ function addUsage(total: ScriptedUsage | undefined, delta: { inputTokens?: number; outputTokens?: number; cacheReadTokens?: number; cacheWriteTokens?: number }): ScriptedUsage {
373
+ const carriesCache = total?.cacheReadTokens !== undefined || delta.cacheReadTokens !== undefined || delta.cacheWriteTokens !== undefined;
374
+ return {
375
+ inputTokens: (total?.inputTokens ?? 0) + (delta.inputTokens ?? 0),
376
+ outputTokens: (total?.outputTokens ?? 0) + (delta.outputTokens ?? 0),
377
+ ...(carriesCache
378
+ ? {
379
+ cacheReadTokens: (total?.cacheReadTokens ?? 0) + (delta.cacheReadTokens ?? 0),
380
+ cacheWriteTokens: (total?.cacheWriteTokens ?? 0) + (delta.cacheWriteTokens ?? 0),
381
+ }
382
+ : {}),
383
+ };
384
+ }
385
+
386
+ /** Create `file` with `content` unless it exists — a ledger keeps what earlier turns appended. */
387
+ function seedFile(file: string, content: string): void {
388
+ if (existsSync(file)) return;
389
+ mkdirSync(dirname(file), { recursive: true });
390
+ writeFileSync(file, content);
391
+ }