@sema-agent/core 7.54.1 → 7.56.0

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 (621) hide show
  1. package/CHANGELOG.md +950 -0
  2. package/dist/agents/agent-transcript-tool.js +2 -1
  3. package/dist/agents/builtin-agents.d.ts +12 -14
  4. package/dist/agents/cascade.js +1 -1
  5. package/dist/agents/cc-peer-directory.d.ts +36 -0
  6. package/dist/agents/cc-peer-directory.js +139 -0
  7. package/dist/agents/cc-peer-wire.d.ts +105 -0
  8. package/dist/agents/cc-peer-wire.js +98 -0
  9. package/dist/agents/cc-uds-peer-channel.d.ts +40 -0
  10. package/dist/agents/cc-uds-peer-channel.js +457 -0
  11. package/dist/agents/child-model-seat.d.ts +0 -11
  12. package/dist/agents/child-model-seat.js +0 -3
  13. package/dist/agents/cross-session-envelope.d.ts +4 -1
  14. package/dist/agents/cross-session-envelope.js +8 -1
  15. package/dist/agents/cross-session-judge.d.ts +2 -2
  16. package/dist/agents/list-agents-tool.d.ts +3 -1
  17. package/dist/agents/list-agents-tool.js +9 -8
  18. package/dist/agents/observer.d.ts +4 -5
  19. package/dist/agents/observer.js +2 -1
  20. package/dist/agents/peer-admission.d.ts +6 -0
  21. package/dist/agents/peer-admission.js +4 -1
  22. package/dist/agents/peer-directory.d.ts +65 -13
  23. package/dist/agents/peer-directory.js +90 -25
  24. package/dist/agents/peer-notices.d.ts +1 -1
  25. package/dist/agents/peer-session-drain.d.ts +3 -1
  26. package/dist/agents/peer-session-drain.js +3 -2
  27. package/dist/agents/read-inbox-tool.js +2 -1
  28. package/dist/agents/repair-loop.js +2 -2
  29. package/dist/agents/retain-ledger.d.ts +1 -1
  30. package/dist/agents/roster-store.d.ts +1 -1
  31. package/dist/agents/send-message-tool.d.ts +10 -0
  32. package/dist/agents/send-message-tool.js +37 -8
  33. package/dist/agents/subagent.d.ts +39 -82
  34. package/dist/agents/subagent.js +109 -106
  35. package/dist/agents/tool-filter.d.ts +31 -46
  36. package/dist/agents/tool-filter.js +13 -33
  37. package/dist/agents/verify.d.ts +6 -5
  38. package/dist/agents/verify.js +3 -3
  39. package/dist/brain/anthropic.js +43 -81
  40. package/dist/brain/errors.d.ts +15 -0
  41. package/dist/brain/errors.js +10 -0
  42. package/dist/brain/media-degrade.d.ts +18 -7
  43. package/dist/brain/media-degrade.js +13 -2
  44. package/dist/brain/model-capability.d.ts +37 -0
  45. package/dist/brain/model-capability.js +34 -0
  46. package/dist/brain/model-presets.d.ts +6 -12
  47. package/dist/brain/model-presets.js +1 -6
  48. package/dist/brain/open-responses.js +27 -35
  49. package/dist/brain/openai.js +30 -98
  50. package/dist/brain/provider-dialect.d.ts +39 -3
  51. package/dist/brain/provider-dialect.js +28 -0
  52. package/dist/brain/reasoning-request.d.ts +96 -0
  53. package/dist/brain/reasoning-request.js +174 -0
  54. package/dist/brain/reasoning.d.ts +12 -12
  55. package/dist/brain/reasoning.js +4 -3
  56. package/dist/brain/request-params.d.ts +62 -9
  57. package/dist/brain/request-params.js +42 -7
  58. package/dist/brain/retry.d.ts +1 -1
  59. package/dist/brain/route-adjudicator.d.ts +15 -0
  60. package/dist/brain/route-adjudicator.js +15 -0
  61. package/dist/brain/status-sink.d.ts +20 -0
  62. package/dist/brain/status-sink.js +7 -0
  63. package/dist/brain/stream-engine.js +6 -5
  64. package/dist/brain/stream-shared.d.ts +1 -1
  65. package/dist/core/a2a.d.ts +2 -1
  66. package/dist/core/a2a.js +19 -13
  67. package/dist/core/advisor-verdict.d.ts +120 -0
  68. package/dist/core/advisor-verdict.js +92 -0
  69. package/dist/core/agent-definition.d.ts +17 -8
  70. package/dist/core/allow-entry.d.ts +69 -36
  71. package/dist/core/allow-entry.js +81 -52
  72. package/dist/core/allow-rule-shadow.d.ts +10 -3
  73. package/dist/core/approval-object.d.ts +2 -1
  74. package/dist/core/approval-object.js +6 -6
  75. package/dist/core/ask-origin.d.ts +127 -29
  76. package/dist/core/ask-origin.js +87 -25
  77. package/dist/core/ask-question.d.ts +51 -8
  78. package/dist/core/ask-question.js +12 -7
  79. package/dist/core/ask-unresolvable-notice.d.ts +8 -3
  80. package/dist/core/ask-unresolvable-notice.js +16 -2
  81. package/dist/core/auto-compaction.d.ts +11 -8
  82. package/dist/core/auto-compaction.js +4 -2
  83. package/dist/core/auto-mode-arming.d.ts +2 -2
  84. package/dist/core/auto-mode-defaults.d.ts +8 -8
  85. package/dist/core/auto-mode-prompt-assets.d.ts +3 -3
  86. package/dist/core/auto-mode-prompt.d.ts +1 -1
  87. package/dist/core/auto-mode.d.ts +17 -9
  88. package/dist/core/auto-mode.js +9 -6
  89. package/dist/core/background-agent-store.d.ts +3 -3
  90. package/dist/core/canonical-json.d.ts +1 -1
  91. package/dist/core/canonical-json.js +2 -2
  92. package/dist/core/checkpoint-generation.d.ts +53 -0
  93. package/dist/core/checkpoint-generation.js +35 -0
  94. package/dist/core/checkpoint-queries.d.ts +180 -0
  95. package/dist/core/checkpoint-queries.js +272 -0
  96. package/dist/core/checkpoint-requirements.d.ts +19 -4
  97. package/dist/core/checkpoint-requirements.js +8 -14
  98. package/dist/core/checkpoint-store.d.ts +165 -72
  99. package/dist/core/checkpoint-store.js +79 -82
  100. package/dist/core/child-clamp-seats.d.ts +6 -0
  101. package/dist/core/child-clamp-seats.js +3 -16
  102. package/dist/core/compliance.d.ts +2 -2
  103. package/dist/core/context-edit.d.ts +6 -7
  104. package/dist/core/cross-boundary-taint.d.ts +11 -4
  105. package/dist/core/cross-boundary-taint.js +3 -3
  106. package/dist/core/decision-receipt.d.ts +37 -3
  107. package/dist/core/decision-receipt.js +19 -19
  108. package/dist/core/delegation-not-started.d.ts +6 -0
  109. package/dist/core/delegation-not-started.js +17 -0
  110. package/dist/core/effective-path-target.d.ts +1 -1
  111. package/dist/core/engine-attestation.d.ts +93 -0
  112. package/dist/core/engine-attestation.js +70 -0
  113. package/dist/core/engine-capabilities.d.ts +4 -1
  114. package/dist/core/engine-capabilities.js +1 -1
  115. package/dist/core/engine-notice.d.ts +45 -12
  116. package/dist/core/exec-output-tail.d.ts +1 -1
  117. package/dist/core/file-history-retention.d.ts +1 -1
  118. package/dist/core/file-history-store.d.ts +147 -21
  119. package/dist/core/file-history-store.js +58 -32
  120. package/dist/core/gate-fold.d.ts +1 -1
  121. package/dist/core/gate-fold.js +24 -11
  122. package/dist/core/gate-lanes.js +81 -68
  123. package/dist/core/gate-outcome.d.ts +40 -6
  124. package/dist/core/gate-outcome.js +56 -0
  125. package/dist/core/governance-codes.d.ts +17 -3
  126. package/dist/core/governance-codes.js +16 -0
  127. package/dist/core/hands-band.d.ts +1 -1
  128. package/dist/core/hooks.d.ts +21 -20
  129. package/dist/core/hooks.js +3 -1
  130. package/dist/core/host-floor.d.ts +128 -0
  131. package/dist/core/host-floor.js +206 -0
  132. package/dist/core/host-target.d.ts +84 -0
  133. package/dist/core/host-target.js +92 -0
  134. package/dist/core/image-downsample.d.ts +1 -1
  135. package/dist/core/lsp-diagnostics.d.ts +4 -4
  136. package/dist/core/lsp.d.ts +3 -3
  137. package/dist/core/mailbox-store.d.ts +4 -0
  138. package/dist/core/mcp-connection-pool.d.ts +18 -2
  139. package/dist/core/mcp-connection-pool.js +53 -6
  140. package/dist/core/mcp-failure.d.ts +23 -4
  141. package/dist/core/mcp-failure.js +26 -11
  142. package/dist/core/mcp-listing-drift.d.ts +10 -0
  143. package/dist/core/mcp-listing-drift.js +6 -0
  144. package/dist/core/mcp-server-link.d.ts +173 -0
  145. package/dist/core/mcp-server-link.js +127 -0
  146. package/dist/core/mcp-server-spec.d.ts +4 -2
  147. package/dist/core/mcp-session-end.d.ts +26 -0
  148. package/dist/core/mcp-session-end.js +29 -0
  149. package/dist/core/mcp-startup-request.d.ts +17 -0
  150. package/dist/core/mcp-startup-request.js +17 -0
  151. package/dist/core/mcp.d.ts +17 -13
  152. package/dist/core/mcp.js +240 -189
  153. package/dist/core/media-byte-cap.d.ts +1 -1
  154. package/dist/core/memory-engine/delegation-settlement.js +15 -24
  155. package/dist/core/memory-engine/engine.d.ts +9 -9
  156. package/dist/core/memory-engine/engine.js +4 -4
  157. package/dist/core/memory-engine/layout.d.ts +60 -8
  158. package/dist/core/memory-engine/layout.js +65 -6
  159. package/dist/core/memory-engine/provenance-wording.d.ts +1 -1
  160. package/dist/core/memory-engine/tools.js +4 -1
  161. package/dist/core/mode-policy.d.ts +1 -1
  162. package/dist/core/model-seat.d.ts +10 -3
  163. package/dist/core/mods/classic-events.d.ts +67 -0
  164. package/dist/core/mods/classic-events.js +1 -0
  165. package/dist/core/mods/dollar.d.ts +13 -0
  166. package/dist/core/mods/extension-call.d.ts +31 -0
  167. package/dist/core/mods/extension-call.js +43 -0
  168. package/dist/core/mods/kernel/dispatch.d.ts +20 -3
  169. package/dist/core/mods/kernel/dispatch.js +140 -69
  170. package/dist/core/mods/kernel/events.d.ts +47 -11
  171. package/dist/core/mods/kernel/events.js +66 -42
  172. package/dist/core/mods/kernel/index.d.ts +4 -4
  173. package/dist/core/mods/kernel/index.js +2 -2
  174. package/dist/core/mods/kernel/receive.d.ts +39 -5
  175. package/dist/core/mods/kernel/receive.js +290 -17
  176. package/dist/core/mods/kernel/registration.d.ts +33 -2
  177. package/dist/core/mods/kernel/registration.js +6 -7
  178. package/dist/core/mods/kernel/site-rules.d.ts +44 -16
  179. package/dist/core/mods/kernel/site-rules.js +24 -42
  180. package/dist/core/mods/spec-seats.d.ts +69 -0
  181. package/dist/core/mods/spec-seats.js +114 -0
  182. package/dist/core/mods/stations.d.ts +28 -8
  183. package/dist/core/mods/stations.js +29 -13
  184. package/dist/core/mods/tool-call.d.ts +79 -0
  185. package/dist/core/mods/tool-call.js +152 -0
  186. package/dist/core/namespaced-rule-name.d.ts +44 -24
  187. package/dist/core/namespaced-rule-name.js +50 -43
  188. package/dist/core/output-style.d.ts +1 -1
  189. package/dist/core/param-rule-reach.d.ts +15 -0
  190. package/dist/core/param-rule-reach.js +30 -0
  191. package/dist/core/parent-spec-seat.d.ts +13 -1
  192. package/dist/core/parent-spec-seat.js +6 -0
  193. package/dist/core/park-selfcheck.js +1 -0
  194. package/dist/core/pause-registry.d.ts +16 -5
  195. package/dist/core/pause-registry.js +6 -2
  196. package/dist/core/peer-channel.d.ts +70 -0
  197. package/dist/core/peer-channel.js +1 -0
  198. package/dist/core/permission-rule-consent.d.ts +30 -5
  199. package/dist/core/permission-rule-consent.js +147 -50
  200. package/dist/core/permission-rule-model.d.ts +245 -65
  201. package/dist/core/permission-rule-model.js +421 -107
  202. package/dist/core/permission-rule-org.d.ts +6 -2
  203. package/dist/core/permission-rule-org.js +7 -3
  204. package/dist/core/permission-rule-provider.d.ts +6 -2
  205. package/dist/core/permission-rule-provider.js +41 -11
  206. package/dist/core/permission-rule-store.d.ts +22 -26
  207. package/dist/core/permission-rule-store.js +12 -6
  208. package/dist/core/permission-rule-sync.d.ts +11 -2
  209. package/dist/core/permission-rule-sync.js +11 -3
  210. package/dist/core/permission-rule-syntax.d.ts +5 -4
  211. package/dist/core/permission-rule-syntax.js +2 -2
  212. package/dist/core/permission-rules.d.ts +53 -15
  213. package/dist/core/permission-rules.js +125 -100
  214. package/dist/core/persisted-rule-arms.d.ts +6 -4
  215. package/dist/core/persisted-rule-arms.js +10 -12
  216. package/dist/core/present-plan-tool.js +3 -1
  217. package/dist/core/principal-name.d.ts +20 -0
  218. package/dist/core/principal-name.js +22 -0
  219. package/dist/core/prompt-section-seat.js +4 -6
  220. package/dist/core/protocol-http-auth.d.ts +26 -5
  221. package/dist/core/protocol-http-auth.js +137 -4
  222. package/dist/core/protocol-naming.d.ts +2 -2
  223. package/dist/core/read-only-shell-table.d.ts +1 -1
  224. package/dist/core/read-only-shell.d.ts +1 -1
  225. package/dist/core/retired-keys.d.ts +16 -0
  226. package/dist/core/retired-keys.js +16 -4
  227. package/dist/core/rewrite-rejudge.d.ts +60 -0
  228. package/dist/core/rewrite-rejudge.js +36 -0
  229. package/dist/core/roles.d.ts +34 -3
  230. package/dist/core/roles.js +66 -53
  231. package/dist/core/rule-lane-reads.d.ts +20 -15
  232. package/dist/core/rule-lane-reads.js +45 -17
  233. package/dist/core/rule-offer-read.d.ts +53 -0
  234. package/dist/core/rule-offer-read.js +146 -0
  235. package/dist/core/rule-owner.d.ts +46 -0
  236. package/dist/core/rule-owner.js +29 -0
  237. package/dist/core/runner/advisor-instructions.d.ts +70 -0
  238. package/dist/core/runner/advisor-instructions.js +61 -0
  239. package/dist/core/runner/advisor-tool.d.ts +33 -0
  240. package/dist/core/runner/advisor-tool.js +112 -0
  241. package/dist/core/runner/announce-once-ledger.d.ts +18 -26
  242. package/dist/core/runner/announce-once-ledger.js +19 -46
  243. package/dist/core/runner/approval-feedback.js +6 -3
  244. package/dist/core/runner/assemble-result.d.ts +2 -1
  245. package/dist/core/runner/assemble-result.js +1 -1
  246. package/dist/core/runner/call-hook-stations.d.ts +3 -2
  247. package/dist/core/runner/caller-roster.d.ts +21 -2
  248. package/dist/core/runner/caller-roster.js +38 -0
  249. package/dist/core/runner/capability-withheld-seat.d.ts +5 -0
  250. package/dist/core/runner/capability-withheld-seat.js +24 -0
  251. package/dist/core/runner/classifier-ladder.d.ts +33 -13
  252. package/dist/core/runner/classifier-ladder.js +15 -14
  253. package/dist/core/runner/compaction-restate.d.ts +10 -6
  254. package/dist/core/runner/compaction-restate.js +9 -3
  255. package/dist/core/runner/construction-doors.js +3 -0
  256. package/dist/core/runner/contracts.d.ts +40 -33
  257. package/dist/core/runner/conversation-segment.d.ts +28 -0
  258. package/dist/core/runner/conversation-segment.js +42 -0
  259. package/dist/core/runner/cross-boundary-lane.d.ts +21 -16
  260. package/dist/core/runner/cross-boundary-lane.js +58 -34
  261. package/dist/core/runner/decide-continuation.d.ts +7 -4
  262. package/dist/core/runner/decide-continuation.js +2 -2
  263. package/dist/core/runner/denial-limit-arms.d.ts +4 -4
  264. package/dist/core/runner/denial-limit-arms.js +1 -1
  265. package/dist/core/runner/derived-route-fallback.d.ts +24 -24
  266. package/dist/core/runner/derived-route-fallback.js +9 -7
  267. package/dist/core/runner/file-history-request.d.ts +18 -0
  268. package/dist/core/runner/file-history-request.js +21 -13
  269. package/dist/core/runner/file-history-restore.d.ts +45 -0
  270. package/dist/core/runner/file-history-restore.js +46 -0
  271. package/dist/core/runner/gate-exit.d.ts +9 -3
  272. package/dist/core/runner/gate-exit.js +11 -5
  273. package/dist/core/runner/image.d.ts +7 -17
  274. package/dist/core/runner/image.js +9 -60
  275. package/dist/core/runner/initial-run-state.js +1 -1
  276. package/dist/core/runner/permission-rule-lanes.d.ts +6 -6
  277. package/dist/core/runner/permission-rule-lanes.js +38 -15
  278. package/dist/core/runner/person-path-rows.d.ts +12 -9
  279. package/dist/core/runner/person-path-rows.js +19 -8
  280. package/dist/core/runner/prepare-advisor.d.ts +63 -0
  281. package/dist/core/runner/prepare-advisor.js +77 -0
  282. package/dist/core/runner/prepare-ask-lane.d.ts +2 -2
  283. package/dist/core/runner/prepare-ask-lane.js +5 -2
  284. package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -6
  285. package/dist/core/runner/prepare-caps-and-workflow.js +5 -4
  286. package/dist/core/runner/prepare-config-doors.d.ts +31 -38
  287. package/dist/core/runner/prepare-config-doors.js +57 -34
  288. package/dist/core/runner/prepare-defer-classify.d.ts +4 -3
  289. package/dist/core/runner/prepare-defer-classify.js +7 -8
  290. package/dist/core/runner/prepare-delegation-surface.d.ts +2 -2
  291. package/dist/core/runner/prepare-delegation-surface.js +1 -1
  292. package/dist/core/runner/prepare-file-history.d.ts +48 -8
  293. package/dist/core/runner/prepare-file-history.js +41 -73
  294. package/dist/core/runner/prepare-gate-stations.d.ts +2 -5
  295. package/dist/core/runner/prepare-gate-stations.js +12 -8
  296. package/dist/core/runner/prepare-hands-readface.d.ts +2 -8
  297. package/dist/core/runner/prepare-hands-readface.js +15 -14
  298. package/dist/core/runner/prepare-inherited-gate.d.ts +11 -7
  299. package/dist/core/runner/prepare-inherited-gate.js +8 -6
  300. package/dist/core/runner/prepare-memory-engine-session.js +1 -1
  301. package/dist/core/runner/prepare-park-ask.js +12 -12
  302. package/dist/core/runner/prepare-policy-chain.d.ts +7 -4
  303. package/dist/core/runner/prepare-policy-chain.js +68 -81
  304. package/dist/core/runner/prepare-project-context.d.ts +5 -2
  305. package/dist/core/runner/prepare-project-context.js +6 -3
  306. package/dist/core/runner/prepare-prompt-assembly.d.ts +5 -7
  307. package/dist/core/runner/prepare-prompt-assembly.js +10 -8
  308. package/dist/core/runner/prepare-prompt-inputs.d.ts +11 -9
  309. package/dist/core/runner/prepare-prompt-inputs.js +4 -6
  310. package/dist/core/runner/prepare-protocol-tools.d.ts +4 -2
  311. package/dist/core/runner/prepare-protocol-tools.js +5 -4
  312. package/dist/core/runner/prepare-safety-scan.d.ts +9 -12
  313. package/dist/core/runner/prepare-safety-scan.js +8 -23
  314. package/dist/core/runner/prepare-suspend-saga.d.ts +2 -0
  315. package/dist/core/runner/prepare-suspend-saga.js +5 -6
  316. package/dist/core/runner/prepare-task.d.ts +1 -1
  317. package/dist/core/runner/prepare-task.js +41 -35
  318. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +7 -4
  319. package/dist/core/runner/prepare-tool-disclosure-mount.js +24 -18
  320. package/dist/core/runner/prepare-turn-wiring.d.ts +0 -4
  321. package/dist/core/runner/prepare-turn-wiring.js +2 -7
  322. package/dist/core/runner/prepare-wiring-manifest.d.ts +11 -4
  323. package/dist/core/runner/prepare-wiring-manifest.js +3 -3
  324. package/dist/core/runner/resume-admission.js +1 -1
  325. package/dist/core/runner/resume-apply.js +11 -12
  326. package/dist/core/runner/resume-checkpoint-screen.js +3 -0
  327. package/dist/core/runner/resume-claim.d.ts +4 -2
  328. package/dist/core/runner/resume-claim.js +15 -8
  329. package/dist/core/runner/resume-policy-outcome.js +1 -1
  330. package/dist/core/runner/retired-runner-deps.js +2 -1
  331. package/dist/core/runner/rewind-files.d.ts +15 -0
  332. package/dist/core/runner/rewind-files.js +132 -0
  333. package/dist/core/runner/run-attachment-seats.js +2 -2
  334. package/dist/core/runner/run-brain-sinks.d.ts +4 -1
  335. package/dist/core/runner/run-brain-sinks.js +4 -2
  336. package/dist/core/runner/run-compaction-machinery.d.ts +1 -1
  337. package/dist/core/runner/run-compaction-machinery.js +2 -12
  338. package/dist/core/runner/run-git-lane.d.ts +1 -0
  339. package/dist/core/runner/run-harness-handlers.js +14 -7
  340. package/dist/core/runner/run-leg.d.ts +1 -1
  341. package/dist/core/runner/run-leg.js +43 -18
  342. package/dist/core/runner/run-settle-and-teardown.js +3 -2
  343. package/dist/core/runner/run-telemetry-and-budget-seats.js +1 -1
  344. package/dist/core/runner/run-turn-boundary.d.ts +1 -0
  345. package/dist/core/runner/run-turn-boundary.js +15 -22
  346. package/dist/core/runner/runtask.d.ts +3 -0
  347. package/dist/core/runner/runtask.js +8 -9
  348. package/dist/core/runner/session-read-file-states.d.ts +15 -0
  349. package/dist/core/runner/session-read-file-states.js +28 -0
  350. package/dist/core/runner/session-rule-policy.d.ts +22 -21
  351. package/dist/core/runner/session-rule-policy.js +17 -31
  352. package/dist/core/runner/shell-env-withheld.d.ts +33 -0
  353. package/dist/core/runner/shell-env-withheld.js +51 -0
  354. package/dist/core/runner/side-call-account.d.ts +32 -8
  355. package/dist/core/runner/side-call-account.js +23 -1
  356. package/dist/core/runner/skills-seat.js +6 -2
  357. package/dist/core/runner/stream-settle-backstop.js +1 -1
  358. package/dist/core/runner/strict-output-schema.d.ts +1 -1
  359. package/dist/core/runner/sub-agent-deny-lists.js +4 -6
  360. package/dist/core/runner/synthetic-tools.d.ts +16 -13
  361. package/dist/core/runner/synthetic-tools.js +8 -3
  362. package/dist/core/runner/tool-disclosure.d.ts +10 -12
  363. package/dist/core/runner/tool-disclosure.js +3 -4
  364. package/dist/core/runner/tool-end-body.d.ts +1 -1
  365. package/dist/core/runner/tool-end-body.js +10 -9
  366. package/dist/core/runner/tool-face-overlay.d.ts +2 -1
  367. package/dist/core/runner/tool-face-overlay.js +17 -1
  368. package/dist/core/runner/tool-not-executed.d.ts +5 -0
  369. package/dist/core/runner/tool-not-executed.js +11 -0
  370. package/dist/core/runner/tool-occurrence.d.ts +8 -0
  371. package/dist/core/runner/tool-occurrence.js +7 -0
  372. package/dist/core/runner/tool-progress-lane.d.ts +2 -2
  373. package/dist/core/runner/tool-turn-repair-seat.d.ts +3 -2
  374. package/dist/core/runner/turn-attachments.d.ts +91 -80
  375. package/dist/core/runner/turn-attachments.js +62 -37
  376. package/dist/core/runner-deps.d.ts +42 -42
  377. package/dist/core/runtime-caps.d.ts +4 -4
  378. package/dist/core/safety-axis-vocab.d.ts +6 -4
  379. package/dist/core/safety-axis-vocab.js +6 -5
  380. package/dist/core/safety-merge-corpus.js +26 -2
  381. package/dist/core/same-plain-value.d.ts +40 -0
  382. package/dist/core/same-plain-value.js +49 -0
  383. package/dist/core/scheduler.d.ts +1 -1
  384. package/dist/core/secret-env.d.ts +26 -3
  385. package/dist/core/secret-env.js +44 -8
  386. package/dist/core/select-model.js +3 -3
  387. package/dist/core/sensitive-path-policy.d.ts +1 -1
  388. package/dist/core/sensitive-path-policy.js +1 -1
  389. package/dist/core/session-policy-store.d.ts +102 -35
  390. package/dist/core/session-policy-store.js +210 -48
  391. package/dist/core/session-reconcile.d.ts +2 -2
  392. package/dist/core/session-store.d.ts +106 -37
  393. package/dist/core/session-store.js +165 -91
  394. package/dist/core/session.d.ts +101 -57
  395. package/dist/core/session.js +53 -0
  396. package/dist/core/shared-memory/tools.js +3 -1
  397. package/dist/core/shared-memory/types.d.ts +1 -1
  398. package/dist/core/shell-read-silence.d.ts +11 -12
  399. package/dist/core/shell-read-silence.js +9 -5
  400. package/dist/core/shell-run-candidates.js +3 -1
  401. package/dist/core/shell-wrapper-projection.js +1 -1
  402. package/dist/core/shell-wrapper-table.d.ts +14 -7
  403. package/dist/core/shell-wrapper-table.js +5 -4
  404. package/dist/core/side-query.d.ts +10 -0
  405. package/dist/core/side-query.js +15 -1
  406. package/dist/core/skill-grant.d.ts +7 -2
  407. package/dist/core/skill-grant.js +5 -0
  408. package/dist/core/skills-directory.js +6 -2
  409. package/dist/core/store-contracts/checkpoint-store-contract.d.ts +11 -1
  410. package/dist/core/store-contracts/checkpoint-store-contract.js +168 -3
  411. package/dist/core/store-contracts/file-history-store-contract.js +74 -4
  412. package/dist/core/store-contracts/peer-directory-contract.d.ts +7 -2
  413. package/dist/core/store-contracts/peer-directory-contract.js +14 -2
  414. package/dist/core/store-contracts/session-policy-store-contract.d.ts +7 -0
  415. package/dist/core/store-contracts/session-policy-store-contract.js +130 -0
  416. package/dist/core/store-contracts/session-repo-contract.js +176 -0
  417. package/dist/core/store-contracts/session-store-contract.d.ts +6 -8
  418. package/dist/core/store-contracts/session-store-contract.js +361 -51
  419. package/dist/core/store-contracts/workflow-journal-store-contract.js +26 -1
  420. package/dist/core/stub-env.d.ts +2 -0
  421. package/dist/core/stub-env.js +1 -0
  422. package/dist/core/surrogate-safe-slice.d.ts +3 -3
  423. package/dist/core/synthetic-read-verdict.js +3 -3
  424. package/dist/core/task-event.d.ts +42 -8
  425. package/dist/core/task-notification.d.ts +19 -15
  426. package/dist/core/task-registry-agent.d.ts +4 -4
  427. package/dist/core/task-registry-shared.d.ts +4 -4
  428. package/dist/core/task-registry-shared.js +1 -0
  429. package/dist/core/task-registry.d.ts +13 -4
  430. package/dist/core/task-registry.js +14 -2
  431. package/dist/core/task-result.d.ts +21 -3
  432. package/dist/core/task-spec.d.ts +69 -64
  433. package/dist/core/task-stream.d.ts +6 -6
  434. package/dist/core/task-tool-shape.d.ts +4 -4
  435. package/dist/core/tighten-task-spec.d.ts +1 -1
  436. package/dist/core/tighten-task-spec.js +2 -1
  437. package/dist/core/tool-catalog-entries.d.ts +36 -2
  438. package/dist/core/tool-catalog-entries.js +69 -43
  439. package/dist/core/tool-check-reading.d.ts +11 -0
  440. package/dist/core/tool-check-reading.js +11 -6
  441. package/dist/core/tool-conformance.js +1 -0
  442. package/dist/core/tool-errors.d.ts +2 -2
  443. package/dist/core/tool-face-reader.js +5 -3
  444. package/dist/core/tool-face.d.ts +21 -2
  445. package/dist/core/tool-face.js +1 -1
  446. package/dist/core/tool-model-gate.d.ts +5 -5
  447. package/dist/core/tool-name-aliases.d.ts +29 -8
  448. package/dist/core/tool-name-aliases.js +22 -4
  449. package/dist/core/tool-name-readings.d.ts +10 -43
  450. package/dist/core/tool-name-readings.js +2 -11
  451. package/dist/core/tool-policy.d.ts +85 -196
  452. package/dist/core/tool-policy.js +150 -175
  453. package/dist/core/tool-registry.d.ts +14 -7
  454. package/dist/core/tool-registry.js +17 -7
  455. package/dist/core/tool-result-store.js +5 -1
  456. package/dist/core/tool-roster.d.ts +57 -33
  457. package/dist/core/tool-roster.js +56 -68
  458. package/dist/core/tool-spec-members.js +8 -3
  459. package/dist/core/tool-spec.d.ts +53 -31
  460. package/dist/core/tools.js +51 -10
  461. package/dist/core/trace.d.ts +6 -2
  462. package/dist/core/types.d.ts +1 -1
  463. package/dist/core/untrusted-egress.d.ts +1 -1
  464. package/dist/core/untrusted-text.d.ts +1 -1
  465. package/dist/core/user-attachment.d.ts +8 -1
  466. package/dist/core/user-attachment.js +64 -4
  467. package/dist/core/warm-resume.d.ts +1 -1
  468. package/dist/core/wiring-manifest.d.ts +58 -0
  469. package/dist/core/wiring-manifest.js +14 -5
  470. package/dist/core/workflow-journal-store.d.ts +62 -0
  471. package/dist/core/workflow-journal-store.js +78 -2
  472. package/dist/core/workflow-run-store.d.ts +6 -0
  473. package/dist/core/workflow-run-store.js +2 -0
  474. package/dist/engine/compaction/compaction.d.ts +9 -9
  475. package/dist/engine/compaction/compaction.js +3 -2
  476. package/dist/engine/execution-env/node-execution-env.d.ts +26 -8
  477. package/dist/engine/execution-env/node-execution-env.js +54 -24
  478. package/dist/engine/harness/agent-harness.d.ts +39 -9
  479. package/dist/engine/harness/agent-harness.js +87 -33
  480. package/dist/engine/harness/types.d.ts +58 -9
  481. package/dist/engine/harness/types.js +12 -1
  482. package/dist/engine/llm/types.d.ts +36 -19
  483. package/dist/engine/llm/validation.d.ts +4 -1
  484. package/dist/engine/llm/validation.js +13 -1
  485. package/dist/engine/loop/agent-loop.d.ts +23 -1
  486. package/dist/engine/loop/agent-loop.js +26 -34
  487. package/dist/engine/loop/types.d.ts +31 -19
  488. package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
  489. package/dist/engine/session/memory-repo.d.ts +18 -12
  490. package/dist/engine/session/memory-repo.js +24 -9
  491. package/dist/engine/session/parent-chain-guard.d.ts +3 -2
  492. package/dist/engine/session/parent-chain-guard.js +1 -1
  493. package/dist/engine/session/repo-utils.d.ts +32 -3
  494. package/dist/engine/session/repo-utils.js +50 -5
  495. package/dist/index.d.ts +47 -23
  496. package/dist/index.js +35 -17
  497. package/dist/internal/harness-types.d.ts +1 -1
  498. package/dist/internal/harness.d.ts +3 -3
  499. package/dist/internal/harness.js +2 -2
  500. package/dist/internal/llm.d.ts +2 -2
  501. package/dist/internal/llm.js +1 -1
  502. package/dist/orchestration/goal.js +2 -2
  503. package/dist/orchestration/run-workflow-tool.d.ts +8 -6
  504. package/dist/orchestration/run-workflow-tool.js +10 -6
  505. package/dist/orchestration/workflow-size-guideline.d.ts +4 -4
  506. package/dist/orchestration/workflow-types.d.ts +18 -0
  507. package/dist/orchestration/workflow-types.js +6 -0
  508. package/dist/orchestration/workflow.d.ts +5 -13
  509. package/dist/orchestration/workflow.js +57 -49
  510. package/dist/prompt-assembly/artifact.d.ts +2 -2
  511. package/dist/prompt-assembly/artifact.js +5 -3
  512. package/dist/prompt-assembly/assemble.d.ts +3 -2
  513. package/dist/prompt-assembly/assemble.js +1 -1
  514. package/dist/prompt-assembly/catalog/schema.d.ts +43 -12
  515. package/dist/prompt-assembly/catalog/schema.js +34 -2
  516. package/dist/prompt-assembly/catalog/sections.js +0 -1
  517. package/dist/prompt-assembly/composer.d.ts +3 -1
  518. package/dist/prompt-assembly/composer.js +1 -1
  519. package/dist/prompt-assembly/event-registry.js +2 -0
  520. package/dist/prompt-assembly/overlay.js +3 -3
  521. package/dist/prompt-assembly/renderers.d.ts +1 -1
  522. package/dist/prompt-assembly/renderers.js +0 -3
  523. package/dist/prompt-assembly/role-base.d.ts +15 -0
  524. package/dist/prompt-assembly/role-base.js +9 -0
  525. package/dist/prompt-assembly/select.d.ts +39 -14
  526. package/dist/prompt-assembly/select.js +47 -16
  527. package/dist/prompt-assembly/sugar.d.ts +17 -11
  528. package/dist/prompt-assembly/sugar.js +8 -3
  529. package/dist/prompt-assembly/tool-catalog.d.ts +39 -2
  530. package/dist/prompt-assembly/tool-catalog.js +117 -4
  531. package/dist/prompt-assembly/turn-snapshot.d.ts +4 -10
  532. package/dist/prompt-assembly/turn-snapshot.js +0 -3
  533. package/dist/prompt-assembly/types.d.ts +0 -7
  534. package/dist/prompts/default.d.ts +14 -14
  535. package/dist/scenarios/full-body.d.ts +15 -15
  536. package/dist/scenarios/full-body.js +4 -3
  537. package/dist/shell/lex.js +10 -1
  538. package/dist/stores/file/adoption/adopt.d.ts +4 -3
  539. package/dist/stores/file/adoption/adopt.js +27 -33
  540. package/dist/stores/file/adoption/marker.d.ts +6 -13
  541. package/dist/stores/file/adoption/marker.js +9 -17
  542. package/dist/stores/file/checkpoint-store.d.ts +24 -0
  543. package/dist/stores/file/checkpoint-store.js +45 -7
  544. package/dist/stores/file/file-history-store.d.ts +20 -19
  545. package/dist/stores/file/file-history-store.js +157 -141
  546. package/dist/stores/file/fs-atomic.d.ts +15 -0
  547. package/dist/stores/file/fs-atomic.js +89 -14
  548. package/dist/stores/file/index.d.ts +1 -1
  549. package/dist/stores/file/index.js +2 -1
  550. package/dist/stores/file/mailbox-store.d.ts +3 -0
  551. package/dist/stores/file/mailbox-store.js +3 -1
  552. package/dist/stores/file/permission-rule-adopt.d.ts +1 -1
  553. package/dist/stores/file/permission-rule-adopt.js +18 -18
  554. package/dist/stores/file/permission-rule-store.d.ts +18 -2
  555. package/dist/stores/file/permission-rule-store.js +31 -18
  556. package/dist/stores/file/session-policy-store.d.ts +3 -3
  557. package/dist/stores/file/session-store.d.ts +54 -16
  558. package/dist/stores/file/session-store.js +114 -85
  559. package/dist/stores/file/workflow-journal-store.d.ts +10 -4
  560. package/dist/stores/file/workflow-journal-store.js +28 -13
  561. package/dist/tools/artifact/artifact-text.d.ts +1 -1
  562. package/dist/tools/artifact/artifact-tool.js +5 -3
  563. package/dist/tools/fs/bash-program-position.d.ts +19 -2
  564. package/dist/tools/fs/bash-program-position.js +56 -9
  565. package/dist/tools/fs/bash-readonly-classifier.d.ts +3 -3
  566. package/dist/tools/fs/fs-bash.d.ts +2 -2
  567. package/dist/tools/fs/fs-bash.js +8 -6
  568. package/dist/tools/fs/fs-glob.d.ts +86 -0
  569. package/dist/tools/fs/fs-glob.js +226 -0
  570. package/dist/tools/fs/fs-read.js +14 -14
  571. package/dist/tools/fs/fs-search-tools.js +7 -7
  572. package/dist/tools/fs/fs-shared.d.ts +8 -8
  573. package/dist/tools/fs/gh-rate-limit.d.ts +1 -1
  574. package/dist/tools/fs/notebook.d.ts +2 -2
  575. package/dist/tools/fs/pattern-kill-guard.d.ts +22 -0
  576. package/dist/tools/fs/pattern-kill-guard.js +397 -0
  577. package/dist/tools/fs/pdf.d.ts +9 -6
  578. package/dist/tools/fs/pdf.js +3 -3
  579. package/dist/tools/fs/program-read-model.d.ts +57 -7
  580. package/dist/tools/fs/program-read-model.js +11 -1
  581. package/dist/tools/fs/program-read-model.rows.js +78 -21
  582. package/dist/tools/fs/read-deny-home.js +3 -2
  583. package/dist/tools/fs/read-deny.d.ts +29 -7
  584. package/dist/tools/fs/read-deny.js +63 -22
  585. package/dist/tools/fs/removal-targets.d.ts +18 -8
  586. package/dist/tools/fs/removal-targets.js +47 -20
  587. package/dist/tools/fs/safety.d.ts +9 -9
  588. package/dist/tools/fs/search.d.ts +16 -6
  589. package/dist/tools/fs/search.js +20 -26
  590. package/dist/tools/fs/shell-read-argv.js +89 -12
  591. package/dist/tools/fs/shell-read-bindings.d.ts +31 -0
  592. package/dist/tools/fs/shell-read-bindings.js +41 -0
  593. package/dist/tools/fs/shell-read-check.js +12 -20
  594. package/dist/tools/fs/shell-read-environment.d.ts +5 -1
  595. package/dist/tools/fs/shell-read-environment.js +3 -2
  596. package/dist/tools/fs/shell-read-establish.d.ts +15 -0
  597. package/dist/tools/fs/shell-read-establish.js +19 -20
  598. package/dist/tools/fs/shell-read-judge.d.ts +4 -0
  599. package/dist/tools/fs/shell-read-judge.js +5 -2
  600. package/dist/tools/fs/shell-read-plan.js +24 -16
  601. package/dist/tools/fs/shell-read-start.d.ts +6 -1
  602. package/dist/tools/fs/shell-read-write-targets.d.ts +5 -1
  603. package/dist/tools/fs/shell-read-write-targets.js +2 -3
  604. package/dist/tools/fs/shell-reentry-text.d.ts +9 -0
  605. package/dist/tools/fs/shell-reentry-text.js +40 -2
  606. package/dist/tools/loop-tick.d.ts +2 -2
  607. package/dist/tools/scheduler-tools.js +5 -1
  608. package/dist/tools/task-list.d.ts +7 -7
  609. package/dist/tools/task-list.js +5 -1
  610. package/dist/tools/todo.js +65 -64
  611. package/dist/tools/web.d.ts +20 -15
  612. package/dist/tools/web.js +55 -69
  613. package/dist/tools/worktree.d.ts +3 -3
  614. package/dist/tools/worktree.js +3 -1
  615. package/package.json +1 -1
  616. package/test/export-surface.snapshot.json +5894 -5638
  617. package/wire-changes/core@7.55.0.json +3318 -0
  618. package/wire-changes/core@7.56.0.json +3891 -0
  619. package/wire-changes/mods-kernel@7.56.0.json +303 -0
  620. package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +0 -39
  621. package/dist/core/store-contracts/session-store-incarnation-contract.js +0 -95
@@ -150,11 +150,16 @@ function readHandsFact(fact) {
150
150
  }
151
151
  return mounted ? { mounted } : { mounted, reason };
152
152
  }
153
- function readFileHistoryFact(word) {
154
- if (word !== "on" && word !== "disabled")
155
- throw new Error(`the file-history wiring fact ${JSON.stringify(word)} is not one of on|disabled`);
153
+ function readWordFact(word, words, label) {
154
+ if (!words.includes(word))
155
+ throw new Error(`the ${label} wiring fact ${JSON.stringify(word)} is not one of ${words.join("|")}`);
156
156
  return word;
157
157
  }
158
+ function readSessionRulesFact(fact) {
159
+ if (typeof fact !== "boolean")
160
+ throw new Error(`the session-rules wiring fact ${JSON.stringify(fact)} is not a boolean`);
161
+ return { childrenReadLive: fact };
162
+ }
158
163
  export function deriveWiringManifest(facts) {
159
164
  if (facts.half === "static" && facts.leg !== undefined) {
160
165
  throw new Error("a static wiring manifest has no leg — leg identity is an effective-half fact");
@@ -219,14 +224,18 @@ export function deriveWiringManifest(facts) {
219
224
  ? { readDeny: { builtinTiers: [...facts.readDenyBuiltinTiersActive] } }
220
225
  : {}),
221
226
  ...(facts.half === "effective" && facts.autoConsolidationOnRecommendation === true ? { autoConsolidation: { onRecommendation: true } } : {}),
222
- ...(facts.half === "effective" && facts.fileHistory !== undefined ? { fileHistory: readFileHistoryFact(facts.fileHistory) } : {}),
227
+ ...(facts.half === "effective" && facts.fileHistory !== undefined ? { fileHistory: readWordFact(facts.fileHistory, ["on", "disabled"], "file-history") } : {}),
228
+ ...(facts.half === "effective" && facts.projectMemory !== undefined ? { projectMemory: readWordFact(facts.projectMemory, ["on", "disabled", "absent"], "project-memory") } : {}),
229
+ ...(facts.half === "effective" && facts.sessionRulesChildrenReadLive !== undefined ? { sessionRules: readSessionRulesFact(facts.sessionRulesChildrenReadLive) } : {}),
230
+ ...(facts.half === "effective" && facts.advisor !== undefined ? { advisor: { ...facts.advisor, ...(facts.advisor.hold !== undefined ? { hold: { ...facts.advisor.hold } } : {}) } } : {}),
231
+ ...(facts.half === "effective" && facts.hostFloor !== undefined ? { hostFloor: { onlyMode: facts.hostFloor.onlyMode, denyCount: facts.hostFloor.denyCount, onlyCount: facts.hostFloor.onlyCount } } : {}),
223
232
  ...(facts.half === "effective" && facts.teamRole !== undefined ? { teamRole: facts.teamRole } : {}),
224
233
  ...(facts.half === "effective" && facts.peerPresence !== undefined && (facts.peerPresence.agent !== undefined || facts.peerPresence.intent !== undefined)
225
234
  ? { peerPresence: { ...(facts.peerPresence.agent !== undefined ? { agent: facts.peerPresence.agent } : {}), ...(facts.peerPresence.intent !== undefined ? { intent: facts.peerPresence.intent } : {}) } }
226
235
  : {}),
227
236
  };
228
237
  if (facts.half === "effective") {
229
- const { leg: _leg, mcp: _mcp, tools: _tools, lsp: _lsp, mods: _mods, teamRole: _teamRole, peerPresence: _peerPresence, fileHistory: _fileHistory, permissionMode: _permissionMode, ...assembly } = manifest;
238
+ const { leg: _leg, mcp: _mcp, tools: _tools, lsp: _lsp, mods: _mods, teamRole: _teamRole, peerPresence: _peerPresence, fileHistory: _fileHistory, projectMemory: _projectMemory, permissionMode: _permissionMode, sessionRules: _sessionRules, advisor: _advisor, ...assembly } = manifest;
230
239
  const { provenance: _askSeat, ...askForHash } = assembly.ask;
231
240
  const { provenance: _questionSeat, ...questionForHash } = assembly.question;
232
241
  manifest.configFingerprint = createHash("sha256")
@@ -1,4 +1,5 @@
1
1
  import type { TaskResult } from "./types.js";
2
+ import { type CorruptBodyForm } from "./store-contracts/read-back-shape-contract.js";
2
3
  /**
3
4
  * design/97 CORE-7 — one recorded `ctx.agent` result in a workflow's RESUME journal. Unlike the observation-only
4
5
  * {@link WorkflowRunStore} (best-effort, swallowed on throw), the journal is LOAD-BEARING: a resume replays the
@@ -30,6 +31,67 @@ export type WorkflowJournalEntry = {
30
31
  }>;
31
32
  };
32
33
  };
34
+ /** What {@link readWorkflowJournalEntry} answers: the entry, or the corrupt form the row takes plus a clause
35
+ * naming what is wrong with it (worded to follow "journal entry #N"; it quotes no stored value). */
36
+ export type WorkflowJournalEntryReading = {
37
+ entry: WorkflowJournalEntry;
38
+ } | {
39
+ corrupt: CorruptBodyForm;
40
+ why: string;
41
+ };
42
+ /**
43
+ * The ONE reading of a journal row read back from a store: which arm it is, and whether the arm carries what a
44
+ * resume reads from it — an object result, or a paused terminal with its checkpoint token (the payload's other
45
+ * members, `sessionId` / `gate` / `stats` among them, are not judged here). `raw` is the DECODED LOGICAL ROW — an object carrying
46
+ * `callKey` and exactly one of `result` / `parked`; how a backend encodes that row on its medium (a JSONL
47
+ * line with its own `scope` / `ordinal` members, a SQL column holding an envelope) is the backend's format
48
+ * and is decoded before this is asked. Members other than those three are not read and are not carried into
49
+ * the entry, which is minted fresh from them.
50
+ *
51
+ * Corrupt, by form:
52
+ * - `not-an-object` — the row is not an object;
53
+ * - `missing-required` — no `callKey`; neither arm; a parked arm whose result carries no `terminal`, or
54
+ * whose paused terminal carries no `token`;
55
+ * - `wrong-type` — a non-string `callKey`; BOTH arms (the union admits one); a `result` that is not an
56
+ * object; a `parked` that is not an object; a parked arm whose terminal is not `paused`, or whose token
57
+ * is not a non-empty string.
58
+ *
59
+ * The parked arm's paused terminal and its checkpoint token are judged here because the type requires them
60
+ * and the arm is load-bearing: a row that says it parked but holds no paused result with a token can neither
61
+ * be driven nor be replayed as a finished call, and answering it as either would let a resume run that
62
+ * ordinal again beside the child pinned under its pending checkpoint. Whether a COMPLETED result carries a
63
+ * terminal cause the engine can replay is the resume's own admission (a journal written before
64
+ * `TaskResult.terminal` is incompatible, not damaged).
65
+ */
66
+ export declare function readWorkflowJournalEntry(raw: unknown): WorkflowJournalEntryReading;
67
+ /**
68
+ * Clamp an externally-supplied run identifier before it lands in a persisted field or an error message:
69
+ * `resumeFromRunId` is LLM-controlled text and a resume claim's `holder` is store-supplied, so neither may
70
+ * carry control characters / unbounded length into a record a human or a model reads.
71
+ */
72
+ export declare function clampRunIdText(raw: string): string;
73
+ /** The code of {@link WorkflowJournalIncompatibleError} — the word the journal store kit asserts on a refused `load`. */
74
+ export declare const JOURNAL_INCOMPATIBLE_ERROR_CODE = "workflow.journal_incompatible";
75
+ /** A resume journal entry the resume cannot admit is INCOMPATIBLE, and the resume is refused before any work is
76
+ * dispatched: a row whose result carries no terminal cause (a journal written before `TaskResult.terminal`), or
77
+ * a row {@link readWorkflowJournalEntry} reads as corrupt — refused by the engine's admission, or by a store's
78
+ * own `load` (the journal store kit holds a backend's refused `load` to this code). The alternative (letting the
79
+ * entry diverge into a live re-run) would execute the already-completed prefix again, side effects included.
80
+ *
81
+ * `entry` is the row as read: when the journal reader finds it corrupt, the message carries that reader's clause
82
+ * (fixed text that quotes no stored value), so no caller-supplied text reaches it; absent, or a row the reader
83
+ * admits, the clause is the missing terminal cause. A backend whose own medium holds a line that is not one of the
84
+ * run's records refuses with {@link WorkflowJournalIncompatibleError.ledgerLine}. `ordinal` is `-1` when the refusal
85
+ * names no entry ordinal: a row with no readable call key, or a ledger line. The run id is clamped here. */
86
+ export declare class WorkflowJournalIncompatibleError extends Error {
87
+ readonly ordinal: number;
88
+ readonly code = "workflow.journal_incompatible";
89
+ readonly fromRunId: string;
90
+ constructor(fromRunId: string, ordinal: number, entry?: unknown);
91
+ /** The refusal for line `line` (1-based) of a backend's ledger that is not one of the run's records, judged `form`
92
+ * by the backend's line reader: dropping it would leave whatever it held looking never journaled. */
93
+ static ledgerLine(fromRunId: string, line: number, form: CorruptBodyForm): WorkflowJournalIncompatibleError;
94
+ }
33
95
  /** REF-D5: the resume-claim key triple — ONE shape for the interface pair and every implementation
34
96
  * (it was re-inlined seven times; a key-field rename must red every leg at once). */
35
97
  export interface ResumeClaimArgs {
@@ -1,4 +1,72 @@
1
1
  import { terminalProjection } from "./runner/terminal-projection.js";
2
+ import { CORRUPT_BODY_FORMS } from "./store-contracts/read-back-shape-contract.js";
3
+ const isRecordShaped = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
4
+ const ownMember = (o, key) => (Object.hasOwn(o, key) ? o[key] : undefined);
5
+ export function readWorkflowJournalEntry(raw) {
6
+ if (!isRecordShaped(raw))
7
+ return { corrupt: "not-an-object", why: "is not a journal entry (not an object)" };
8
+ const callKey = ownMember(raw, "callKey");
9
+ if (callKey === undefined)
10
+ return { corrupt: "missing-required", why: "carries no call key" };
11
+ if (typeof callKey !== "string")
12
+ return { corrupt: "wrong-type", why: "has a call key that is not a string" };
13
+ const result = ownMember(raw, "result");
14
+ const parked = ownMember(raw, "parked");
15
+ if (result === undefined && parked === undefined)
16
+ return { corrupt: "missing-required", why: "carries neither a result nor a parked arm" };
17
+ if (result !== undefined && parked !== undefined)
18
+ return { corrupt: "wrong-type", why: "carries both a result and a parked arm" };
19
+ if (parked === undefined) {
20
+ if (!isRecordShaped(result))
21
+ return { corrupt: "wrong-type", why: "has a result that is not an object" };
22
+ return { entry: { callKey, result: result } };
23
+ }
24
+ if (!isRecordShaped(parked))
25
+ return { corrupt: "wrong-type", why: "is recorded as parked but its parked arm is not an object" };
26
+ const terminal = ownMember(parked, "terminal");
27
+ if (terminal === undefined)
28
+ return { corrupt: "missing-required", why: "is recorded as parked but its parked result carries no terminal" };
29
+ if (!isRecordShaped(terminal) || ownMember(terminal, "kind") !== "paused") {
30
+ return { corrupt: "wrong-type", why: "is recorded as parked but its terminal is not a paused one" };
31
+ }
32
+ const token = ownMember(terminal, "token");
33
+ if (token === undefined)
34
+ return { corrupt: "missing-required", why: "is recorded as parked but its paused terminal carries no checkpoint token" };
35
+ if (typeof token !== "string" || token.length === 0)
36
+ return { corrupt: "wrong-type", why: "is recorded as parked but its paused terminal carries no checkpoint token" };
37
+ return { entry: { callKey, parked: parked } };
38
+ }
39
+ export function clampRunIdText(raw) {
40
+ return raw.replace(/[^A-Za-z0-9_.:-]/g, "").slice(0, 64);
41
+ }
42
+ export const JOURNAL_INCOMPATIBLE_ERROR_CODE = "workflow.journal_incompatible";
43
+ export class WorkflowJournalIncompatibleError extends Error {
44
+ ordinal;
45
+ code = JOURNAL_INCOMPATIBLE_ERROR_CODE;
46
+ fromRunId;
47
+ constructor(fromRunId, ordinal, entry) {
48
+ const runIdText = clampRunIdText(fromRunId);
49
+ super(`workflow run "${runIdText}": ${refusedSubjectOf(ordinal, entry)} — this journal cannot be resumed. ${REPAIR_COST}`);
50
+ this.ordinal = ordinal;
51
+ this.fromRunId = runIdText;
52
+ this.name = "WorkflowJournalIncompatibleError";
53
+ }
54
+ static ledgerLine(fromRunId, line, form) {
55
+ return new WorkflowJournalIncompatibleError(fromRunId, -1, { [LEDGER_LINE]: { line, form } });
56
+ }
57
+ }
58
+ const REPAIR_COST = "Deleting what is damaged does not repair it (whatever goes missing runs again, live); restoring it needs a copy of the ledger kept outside the engine; a fresh run executes every step again, side effects included.";
59
+ const LEDGER_LINE = Symbol("ledgerLine");
60
+ function refusedSubjectOf(ordinal, entry) {
61
+ const at = isRecordShaped(entry) ? entry[LEDGER_LINE] : undefined;
62
+ if (at !== undefined) {
63
+ const line = Number.isSafeInteger(at.line) && at.line > 0 ? at.line : "?";
64
+ const form = CORRUPT_BODY_FORMS.includes(at.form) ? at.form : "unreadable";
65
+ return `ledger line ${String(line)} is not one of the run's records (${String(form)})`;
66
+ }
67
+ const read = entry === undefined ? undefined : readWorkflowJournalEntry(entry);
68
+ return `journal entry #${ordinal} ${read !== undefined && "corrupt" in read ? read.why : "carries no terminal cause (a journal written before TaskResult.terminal, or a malformed entry)"}`;
69
+ }
2
70
  export const MAX_JOURNAL_RESULT_BYTES = 5 * 1024 * 1024;
3
71
  export function oversizeJournalResult(serialized) {
4
72
  return Buffer.byteLength(serialized, "utf8") > MAX_JOURNAL_RESULT_BYTES;
@@ -34,7 +102,7 @@ export function journalOversizeTombstone(result, bytes) {
34
102
  taskId: result.taskId,
35
103
  sessionId: result.sessionId,
36
104
  terminal: { kind: "failed", code: JOURNAL_OVERSIZE_ERROR_CODE, message },
37
- result: message,
105
+ result: message, resultEntryIds: [],
38
106
  stats: result.stats,
39
107
  };
40
108
  }
@@ -80,7 +148,15 @@ export class InMemoryWorkflowJournalStore {
80
148
  const rec = this.runs.get(runId);
81
149
  if (!rec || rec.scope !== scope)
82
150
  return [];
83
- return [...rec.byOrdinal.entries()].sort((a, b) => a[0] - b[0]).map(([, e]) => snapshot(e));
151
+ const out = [];
152
+ for (const [ordinal, e] of [...rec.byOrdinal.entries()].sort((a, b) => a[0] - b[0])) {
153
+ const row = snapshot(e);
154
+ const read = readWorkflowJournalEntry(row);
155
+ if ("corrupt" in read)
156
+ throw new WorkflowJournalIncompatibleError(runId, ordinal, row);
157
+ out.push(read.entry);
158
+ }
159
+ return out;
84
160
  }
85
161
  async append(runId, scope, entry) {
86
162
  assertJournalEntryFits(entry);
@@ -46,6 +46,12 @@ export interface WorkflowRunSummary {
46
46
  description?: string;
47
47
  /** Lifecycle status ({@link WorkflowRun.status}): running / completed / failed. */
48
48
  status: WorkflowRunStatus;
49
+ /** `true` while the run is still `running` AND at least one leg is parked at an approval gate — somebody is being
50
+ * waited on while `status` still says `running` ({@link runParkedOf}). ABSENT otherwise, never `false`: a run
51
+ * that has since suspended on the park reads `failed` + `errorCode: "workflow.agent_parked"` (that code is its
52
+ * "awaiting approval" word; a consumer shows both arms the same way), and a settled record never carries it.
53
+ * DERIVED from the agent rows on every projection — not stored on the run, so no second copy to drift. */
54
+ parked?: true;
49
55
  /** The MACHINE code of the failure that ended the run ({@link WorkflowRun.errorCode}) — the same word,
50
56
  * in the same vocabulary, that the full run carries; never re-derived and never a second taxonomy.
51
57
  * The fourth member of the same family as {@link agentFailures} / {@link budgetOvershoot} /
@@ -1,3 +1,4 @@
1
+ import { runParkedOf } from "../orchestration/workflow-types.js";
1
2
  import { assertRetentionPolicy } from "./retention-policy.js";
2
3
  export function summarizeWorkflowRun(run) {
3
4
  const latestPhase = run.phases.at(-1);
@@ -8,6 +9,7 @@ export function summarizeWorkflowRun(run) {
8
9
  ...(run.name !== undefined ? { name: run.name } : {}),
9
10
  ...(run.description !== undefined ? { description: run.description } : {}),
10
11
  status: run.status,
12
+ ...(runParkedOf(run) ? { parked: true } : {}),
11
13
  ...(run.errorCode !== undefined ? { errorCode: run.errorCode } : {}),
12
14
  ...(run.agentFailures !== undefined ? { agentFailures: run.agentFailures } : {}),
13
15
  ...(run.budgetOvershoot !== undefined ? { budgetOvershoot: { ...run.budgetOvershoot } } : {}),
@@ -17,7 +17,7 @@ export interface CompactionDetails {
17
17
  */
18
18
  modifiedFilesByRecency?: string[];
19
19
  /**
20
- * Invoked-skill retention area (CC 2.1.207 parity): the skills invoked in the COMPACTED range
20
+ * Invoked-skill retention area: the skills invoked in the COMPACTED range
21
21
  * (merged over the previous compaction's retained set), most recent invocation first, already
22
22
  * budgeted (per-skill truncation marker + total-area skip semantics — see compaction/utils.ts).
23
23
  * Rendered onto the compaction summary message by `buildSessionContext`; kept OUT of the summary
@@ -131,7 +131,7 @@ export declare const DEFAULT_CLAMP_TOLERANCE = 0.1;
131
131
  * [new user]`, and a within-turn boundary keeps `[emitting assistant][its tool results]` because
132
132
  * a trailing tool-result batch pulls the floor back to its call site.
133
133
  *
134
- * That is the CC posture, arrived at through a different knob. CC 2.1.223's LOCAL threshold
134
+ * That is the CC posture, arrived at through a different knob. the reference's LOCAL threshold
135
135
  * compaction always routes to the reactive pipeline (`y9s` :432704 — the `GNo` full-compaction
136
136
  * branch with `messagesToKeep: []` :431788 is reached only for a remote/in-process runner, and a
137
137
  * `source:"auto"` window makes the local threshold not fire at all, `hky` :432687 / `aYe` :242816).
@@ -159,7 +159,7 @@ export declare const DEFAULT_COMPACTION_SETTINGS: CompactionSettings;
159
159
  * never split (estimate vs cut-point vs defense); per-model override via `Model.charsPerToken`.
160
160
  *
161
161
  * 4 → 3 (design/374 slice 4, ruled 2026-08-28) — this is a RE-ANCHORING, not a divergence.
162
- * CC's coefficient is a two-branch function, not a constant: `sf(model)` (cli250.js, `Z6` table) is
162
+ * CC's coefficient is a two-branch function, not a constant: `sf(model)` is
163
163
  * `Z6.has(family) ? 4 : 3`
164
164
  * where `Z6` lists exactly the OLD families (claude-3.x, opus-4-0/4-1/4-5/4-6, sonnet-4-0/4-5/4-6,
165
165
  * haiku-4-5). **3 is CC's DEFAULT branch; 4 is the whitelist hit** — and CC's own current generation
@@ -189,7 +189,7 @@ export declare function calculateContextTokens(usage: Usage): number;
189
189
  *
190
190
  * design/123 D1 stale-anchor note (fable-m2, same-family point): this scans RAW session entries, so
191
191
  * unlike `buildSessionContext` (which shallow-strips the usage of kept-tail assistants replayed
192
- * across a compaction boundary — the anchor "naturally disappears", CC 198 parity) it CAN still see
192
+ * across a compaction boundary — the anchor "naturally disappears") it CAN still see
193
193
  * a pre-compaction anchor. Any consumer using this across a compaction boundary must treat such an
194
194
  * anchor as STALE: it reflects the pre-compaction request and overestimates the post-compaction
195
195
  * context. (Currently exported with no in-repo production consumer.)
@@ -265,7 +265,7 @@ export declare const SUMMARIZATION_SYSTEM_PROMPT = "You are a context summarizat
265
265
  */
266
266
  export declare function contextInstructionFilesSection(contextInstructionFiles?: string): string;
267
267
  /**
268
- * design/169-A (CC 220 :516490-516516 / :387325-387336) — the CC-form FORK context for a summary
268
+ * design/169-A — the CC-form FORK context for a summary
269
269
  * request: the main lane's latest REAL request. When present (and the summary model IS the main
270
270
  * model), the summary request is the main conversation itself — same `systemPrompt` bytes, same
271
271
  * message-list byte PREFIX, same tools — plus ONE appended user-role instruction message. The
@@ -310,7 +310,7 @@ export declare function extractForkSummaryEnvelope(text: string): string | undef
310
310
  * messages above, un-serialized) + the fork-only instruction-file authority clause (see
311
311
  * {@link FORK_CONTEXT_INSTRUCTION_AUTHORITY}) + the fork-only summary envelope (see
312
312
  * {@link FORK_SUMMARY_ENVELOPE_DEMAND}; the independent form keeps its envelope-free contract).
313
- * Instructions inject in the same CC-verbatim shape as the independent form so every channel keeps
313
+ * Instructions inject in the same shape as the independent form so every channel keeps
314
314
  * one injection grammar. */
315
315
  export declare function forkSummarizationInstruction(customInstructions?: string, contextInstructionFiles?: string): string;
316
316
  /**
@@ -327,7 +327,7 @@ export declare function forkSummarizationInstruction(customInstructions?: string
327
327
  * base = settings.summaryOutputBudgetTokens ?? settings.reserveTokens (explicit knob wins)
328
328
  * effective = min(base, summary model's max output) (never budget output
329
329
  * the model can't emit)
330
- * CC contrast (2.1.207): CC's summary output cap is purely model-derived (its summary call runs at
330
+ * Contrast: the reference's summary output cap is purely model-derived (its summary call runs at
331
331
  * the model's max output) and fully separate from the trigger deduction — the `min(model.maxTokens,…)`
332
332
  * leg IS that posture. The base deliberately stays reserve-derived rather than jumping to the raw
333
333
  * model max: sema (unlike CC) clamps the summarization INPUT pre-send, and the clamp budgets
@@ -396,7 +396,7 @@ export interface SummarizationClampDryRun {
396
396
  * "prior summary + new increment", not the original history.
397
397
  */
398
398
  export declare function dryRunSummarizationClamp(preparation: CompactionPreparation, model: Model, customInstructions?: string, charsPerToken?: number): SummarizationClampDryRun;
399
- /** CC 198 jNl — verbatim marker inserted where the oldest conversation groups were dropped. */
399
+ /** The marker inserted where the oldest conversation groups were dropped. */
400
400
  export declare const COMPACTION_PTL_RETRY_MARKER = "[earlier conversation truncated for compaction retry]";
401
401
  /** Generate or update a conversation summary for compaction.
402
402
  * `summaryBudgetTokens` — the OUTPUT budget base (history leg = 0.8× it). Callers going through
@@ -488,6 +488,6 @@ export declare function compact(preparation: CompactionPreparation, model: Model
488
488
  * the main model; an independent compaction model has no main prefix to share. */
489
489
  forkContext?: CompactionForkContext): Promise<Result<CompactionResult, CompactionError>>;
490
490
  /** The prefix leg's base prompt, with the caller's instructions injected in the SAME shape the
491
- * history leg uses (`\n\nAdditional Instructions:\n${…}`, CC 198 verbatim). Single source so the
491
+ * history leg uses (`\n\nAdditional Instructions:\n${…}`). Single source so the
492
492
  * dry-run clamp charges exactly what the real call sends. */
493
493
  export declare function turnPrefixSummarizationPrompt(customInstructions?: string): string;
@@ -7,6 +7,7 @@ import { budgetInvokedSkillsRetention, computeFileLists, createFileOps, extractF
7
7
  import { ENGINE_AUTHORITY_ENVELOPE_TAGS, sanitizeUntrustedText } from "../../core/untrusted-text.js";
8
8
  import { sliceHeadSafe } from "../../core/surrogate-safe-slice.js";
9
9
  import { thrownText } from "../../core/thrown-value.js";
10
+ import { capabilityHeld } from "../../brain/model-capability.js";
10
11
  function safeJsonStringify(value) {
11
12
  try {
12
13
  return JSON.stringify(value) ?? "undefined";
@@ -576,7 +577,7 @@ First, inside an <analysis>...</analysis> block, note what is new since the prev
576
577
  Keep each section concise. Preserve exact file paths, function names, and error messages.`;
577
578
  function createSummarizationOptions(model, maxTokens, apiKey, headers, signal, thinkingLevel) {
578
579
  const options = { maxTokens, signal, apiKey, headers };
579
- if (model.reasoning && thinkingLevel) {
580
+ if (capabilityHeld(model, "reasoning") && thinkingLevel) {
580
581
  options.reasoning = thinkingLevel;
581
582
  }
582
583
  return options;
@@ -868,7 +869,7 @@ async function summarizeWithLengthRecovery(label, model, context, baseMaxTokens,
868
869
  ? Math.max(baseMaxTokens, model.contextWindow - estimateSummarizationInputTokens(context, cpt) - SUMMARY_WINDOW_MARGIN)
869
870
  : Number.POSITIVE_INFINITY;
870
871
  const cap = Math.min(modelCap, windowCap);
871
- let maxTokens = Math.min(cap, model.reasoning ? Math.max(baseMaxTokens, SUMMARY_REASONING_FLOOR) : baseMaxTokens);
872
+ let maxTokens = Math.min(cap, capabilityHeld(model, "reasoning") ? Math.max(baseMaxTokens, SUMMARY_REASONING_FLOOR) : baseMaxTokens);
872
873
  for (let attempt = 0;; attempt++) {
873
874
  const canEscalate = attempt < SUMMARY_MAX_ESCALATIONS && maxTokens < cap;
874
875
  const response = await completeSummarization(model, context, createSummarizationOptions(model, maxTokens, apiKey, headers, signal, thinkingLevel), streamFn, runtime);
@@ -88,9 +88,13 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
88
88
  /** `ExecutionEnv.cdPath` = the `CDPATH` the shell child receives, read LIVE off the same merge each exec gets (never the
89
89
  * engine process's own environment): its entries, `[]` when the child gets none. Residual: a per-exec `env.CDPATH`. */
90
90
  get cdPath(): readonly string[];
91
- /** The environment the next shell child would receive, for a READ (the scrub seat is a no-op: a read reports nothing).
92
- * `undefined` when no child would be spawned at all — the policy is refused against the own credentials declared
93
- * since construction, and every spawn throws that reason — so a reader sees "the child gets none", never a throw. */
91
+ /** `ExecutionEnv.withheldEnv` = what the same merge withholds from the shell child (an entry `shellEnv` re-supplies is
92
+ * no loss), read LIVE; `[]` when no child would be spawned at all. Residual: a per-exec `env` re-supplying one. */
93
+ get withheldEnv(): readonly SecretEnvFinding[];
94
+ /** The environment the next shell child would receive, for a READ (the scrub seat is the reader's collector or a
95
+ * no-op: a read announces nothing). `undefined` when no child would be spawned at all — the policy is refused against
96
+ * the own credentials declared since construction, and every spawn throws that reason — so a reader sees "the child
97
+ * gets none", never a throw. */
94
98
  private childEnvForRead;
95
99
  private shellPath?;
96
100
  private shellEnv?;
@@ -101,8 +105,12 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
101
105
  private readonly retainBackgroundProcesses;
102
106
  private readonly onSecretEnvScrub?;
103
107
  private readonly onNotice?;
104
- /** design/128 T1-1: lazily-created env-owned spool dir (mkdtemp under os tmp — unpredictable, never the cwd). */
108
+ /** design/128 T1-1: the env-owned spool dir (mkdtemp under os tmp — unpredictable, never the cwd). It exists only while
109
+ * {@link spoolPairs} is non-empty: the last pair's release removes it, the next mint makes a fresh one. */
105
110
  private bgSpoolDir?;
111
+ /** The `outPath` of every spool pair this env minted and has not released — the one fact the dir's lifetime reads. A
112
+ * retain-lane bg pair is never released (its files outlive the run by design), so it keeps the dir. */
113
+ private readonly spoolPairs;
106
114
  readonly backgroundCapabilities: BackgroundShellCapability["backgroundCapabilities"];
107
115
  constructor(options: {
108
116
  cwd: string;
@@ -127,7 +135,8 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
127
135
  * env lane; `TaskSpec.retainBackgroundProcesses` is the task lane, without this spooling guarantee on
128
136
  * every platform — docs/background-process-lifetime.md). The 2h bg-timeout reaper and `killBackground` still work
129
137
  * while the host lives; after host exit, cleanup is the deployment's responsibility (e.g. the TB
130
- * container teardown). v1 covers processes spawned via `execBackground` only (a detach-adopted
138
+ * container teardown) — the retained shells' spool files, and the dir holding them, are never released
139
+ * by the env (every other spool pair is, and the dir goes with the last one). v1 covers processes spawned via `execBackground` only (a detach-adopted
131
140
  * foreground exec keeps pipe stdio — best-effort survival). Incompatible with durable-suspend
132
141
  * deployments (their pre-suspend dispose becomes a no-op too — do not combine).
133
142
  */
@@ -157,8 +166,8 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
157
166
  abortSignal?: AbortSignal;
158
167
  }): Promise<Result<string[], FileError>>;
159
168
  readBinaryFile(path: string, abortSignal?: AbortSignal): Promise<Result<Uint8Array, FileError>>;
160
- /** RB-221: whole-file replace via same-directory staging + fsync + rename (CC 2.1.220 `Q5`,
161
- * (pretty220.js:60808, historical; not relocated in 250 — see cc-250 anchors)). The former single-step `writeFile` was an in-place O_TRUNC: an abort mid-write
169
+ /** RB-221: whole-file replace via same-directory staging + fsync + rename.
170
+ * The former single-step `writeFile` was an in-place O_TRUNC: an abort mid-write
162
171
  * (Esc during a large Write — ctx.signal reaches here directly), ENOSPC, or a crash left the target as
163
172
  * a torn prefix of the NEW content with the original unrecoverable. Post-fix contract: the target is
164
173
  * either fully old or fully new; `aborted` means it was never touched. Known semantic change (same as
@@ -251,10 +260,19 @@ export declare class NodeExecutionEnv implements ExecutionEnv, BackgroundShellCa
251
260
  * the file), while poll slicing keeps using the logical stream totalBytes; the two advance in
252
261
  * lockstep here but are NOT interchangeable after a rotation. */
253
262
  private syncSpool;
263
+ /** The one seat that opens a spool pair (foreground exec and background spawn alike), inside the env's spool dir: made on
264
+ * the first mint after the dir was last removed, so a command never runs against a dir an idle reap or a temp cleaner took. */
265
+ private mintSpoolPair;
266
+ /** The one seat that gives a spool pair back: unlinks both files (a descendant still writing keeps its fd into the unlinked
267
+ * inode — no EPIPE), forgets the pair, and removes the dir once no pair is left in it. Idempotent. */
268
+ private releaseSpoolPair;
269
+ /** Removes the spool dir (and whatever a failed unlink stranded in it) when no pair of this env lives in it. A retain-lane
270
+ * bg pair is never released, so it keeps its dir; the rest is gone with its last pair. Best-effort, never throws. */
271
+ private reapSpoolDirIfIdle;
254
272
  /** +: reclaim an EPHEMERAL spool (detach-adopted, or any non-retain bg
255
273
  * spawn — the whole unix bg lane is spool-backed now) — fold the final residue into the tails,
256
274
  * unlink both files, and drop the spool reference (later syncs become no-ops). Idempotent;
257
- * never touches design/128 retain-lane spools (no `ephemeral` flag). A still-writing detached
275
+ * never touches the spool of a design/128 retain-lane shell that has a process (no `ephemeral` flag). A still-writing detached
258
276
  * descendant keeps its fd into the unlinked inode (RB-26 posture — no EPIPE, auto-reclaim at
259
277
  * its exit). */
260
278
  private reclaimEphemeralSpool;
@@ -1,6 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { randomUUID } from "node:crypto";
3
- import { closeSync, constants, createReadStream, mkdtempSync, openSync, readSync, statSync, truncateSync, unlinkSync } from "node:fs";
3
+ import { closeSync, constants, createReadStream, mkdtempSync, openSync, readSync, rmSync, statSync, truncateSync, unlinkSync } from "node:fs";
4
4
  import { access, appendFile, lstat, mkdir, mkdtemp, open, readdir, readFile, readlink, rename, rm, stat, unlink, writeFile, } from "node:fs/promises";
5
5
  import { tmpdir } from "node:os";
6
6
  import { isAbsolute, join, resolve } from "node:path";
@@ -116,6 +116,10 @@ function toFileError(error, path) {
116
116
  return new FileError("not_directory", message, path, cause);
117
117
  case "EISDIR":
118
118
  return new FileError("is_directory", message, path, cause);
119
+ case "ENAMETOOLONG":
120
+ if (path !== undefined && path.split(/[\\/]/).some((part) => Buffer.byteLength(part, "utf8") > 255))
121
+ return new FileError("name_too_long", message, path, cause);
122
+ break;
119
123
  case "EINVAL":
120
124
  return new FileError("invalid", message, path, cause);
121
125
  default:
@@ -321,10 +325,15 @@ export class NodeExecutionEnv {
321
325
  const value = this.childEnvForRead()?.CDPATH;
322
326
  return value === undefined || value === "" ? [] : value.split(":");
323
327
  }
324
- childEnvForRead() {
328
+ get withheldEnv() {
329
+ let withheld = [];
330
+ this.childEnvForRead((f) => (withheld = f));
331
+ return withheld;
332
+ }
333
+ childEnvForRead(collect = () => { }) {
325
334
  if (inheritEnvPolicyProblem(this.inheritEnv) !== undefined)
326
335
  return undefined;
327
- return getShellEnv(this.inheritEnv, this.shellEnv, undefined, () => { });
336
+ return getShellEnv(this.inheritEnv, this.shellEnv, undefined, collect);
328
337
  }
329
338
  shellPath;
330
339
  shellEnv;
@@ -336,6 +345,7 @@ export class NodeExecutionEnv {
336
345
  onSecretEnvScrub;
337
346
  onNotice;
338
347
  bgSpoolDir;
348
+ spoolPairs = new Set();
339
349
  backgroundCapabilities;
340
350
  constructor(options) {
341
351
  this.cwd = options.cwd;
@@ -465,13 +475,7 @@ export class NodeExecutionEnv {
465
475
  if (spoolPumpRef.current)
466
476
  clearInterval(spoolPumpRef.current);
467
477
  if (execSpoolRef.current && !(result.ok && result.value.detached !== undefined)) {
468
- for (const path of [execSpoolRef.current.outPath, execSpoolRef.current.errPath]) {
469
- try {
470
- unlinkSync(path);
471
- }
472
- catch {
473
- }
474
- }
478
+ this.releaseSpoolPair(execSpoolRef.current);
475
479
  execSpoolRef.current = undefined;
476
480
  }
477
481
  resolvePromise(result);
@@ -479,9 +483,7 @@ export class NodeExecutionEnv {
479
483
  let execSpoolFds;
480
484
  if (process.platform !== "win32") {
481
485
  try {
482
- if (!this.bgSpoolDir)
483
- this.bgSpoolDir = mkdtempSync(join(tmpdir(), "sema-bg-"));
484
- const pair = openSpoolPair(join(this.bgSpoolDir, `fg_${randomUUID()}`));
486
+ const pair = this.mintSpoolPair(`fg_${randomUUID()}`);
485
487
  execSpoolRef.current = { outPath: pair.outPath, errPath: pair.errPath };
486
488
  execSpoolFds = pair.fds;
487
489
  }
@@ -1309,9 +1311,7 @@ export class NodeExecutionEnv {
1309
1311
  let spoolFds;
1310
1312
  if (this.retainBackgroundProcesses || process.platform !== "win32") {
1311
1313
  try {
1312
- if (!this.bgSpoolDir)
1313
- this.bgSpoolDir = mkdtempSync(join(tmpdir(), "sema-bg-"));
1314
- const pair = openSpoolPair(join(this.bgSpoolDir, `bg_${this.bgCounter + 1}_${randomUUID()}`));
1314
+ const pair = this.mintSpoolPair(`bg_${this.bgCounter + 1}_${randomUUID()}`);
1315
1315
  spool = {
1316
1316
  outPath: pair.outPath,
1317
1317
  errPath: pair.errPath,
@@ -1345,6 +1345,8 @@ export class NodeExecutionEnv {
1345
1345
  }
1346
1346
  }
1347
1347
  }
1348
+ if (spool)
1349
+ this.releaseSpoolPair(spool);
1348
1350
  const cause = toError(error);
1349
1351
  return err(new BackgroundShellError("spawn_failed", cause.message, cause));
1350
1352
  }
@@ -1533,23 +1535,51 @@ export class NodeExecutionEnv {
1533
1535
  }
1534
1536
  }
1535
1537
  }
1538
+ mintSpoolPair(name) {
1539
+ this.bgSpoolDir ??= mkdtempSync(join(tmpdir(), "sema-bg-"));
1540
+ try {
1541
+ const pair = openSpoolPair(join(this.bgSpoolDir, name));
1542
+ this.spoolPairs.add(pair.outPath);
1543
+ return pair;
1544
+ }
1545
+ catch (error) {
1546
+ this.reapSpoolDirIfIdle();
1547
+ throw error;
1548
+ }
1549
+ }
1550
+ releaseSpoolPair(pair) {
1551
+ for (const path of [pair.outPath, pair.errPath]) {
1552
+ try {
1553
+ unlinkSync(path);
1554
+ }
1555
+ catch {
1556
+ }
1557
+ }
1558
+ this.spoolPairs.delete(pair.outPath);
1559
+ this.reapSpoolDirIfIdle();
1560
+ }
1561
+ reapSpoolDirIfIdle() {
1562
+ const dir = this.bgSpoolDir;
1563
+ if (dir === undefined || this.spoolPairs.size > 0)
1564
+ return;
1565
+ this.bgSpoolDir = undefined;
1566
+ try {
1567
+ rmSync(dir, { recursive: true, force: true });
1568
+ }
1569
+ catch {
1570
+ }
1571
+ }
1536
1572
  reclaimEphemeralSpool(entry) {
1537
1573
  if (entry.spoolPump !== undefined) {
1538
1574
  clearInterval(entry.spoolPump);
1539
1575
  entry.spoolPump = undefined;
1540
1576
  }
1541
1577
  const spool = entry.spool;
1542
- if (!spool?.ephemeral)
1578
+ if (!spool || (!spool.ephemeral && entry.child.pid !== undefined))
1543
1579
  return;
1544
1580
  this.syncSpool(entry);
1545
1581
  entry.spool = undefined;
1546
- for (const path of [spool.outPath, spool.errPath]) {
1547
- try {
1548
- unlinkSync(path);
1549
- }
1550
- catch {
1551
- }
1552
- }
1582
+ this.releaseSpoolPair(spool);
1553
1583
  }
1554
1584
  async disposeBackgroundShells(opts) {
1555
1585
  if (this.retainBackgroundProcesses)