@llblab/pi-kit 0.38.4 → 0.39.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 (424) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +1 -1
  3. package/node_modules/@llblab/pi-actors/AGENTS.md +108 -20
  4. package/node_modules/@llblab/pi-actors/BACKLOG.md +207 -4
  5. package/node_modules/@llblab/pi-actors/CHANGELOG.md +13 -0
  6. package/node_modules/@llblab/pi-actors/README.md +31 -1
  7. package/node_modules/@llblab/pi-actors/dist/index.js +1 -1
  8. package/node_modules/@llblab/pi-actors/dist/lib/async-runs.d.ts +37 -0
  9. package/node_modules/@llblab/pi-actors/dist/lib/async-runs.js +131 -62
  10. package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.d.ts +2 -0
  11. package/node_modules/@llblab/pi-actors/dist/lib/automatic-review-runtime.js +3 -2
  12. package/node_modules/@llblab/pi-actors/dist/lib/command-templates.d.ts +37 -0
  13. package/node_modules/@llblab/pi-actors/dist/lib/command-templates.js +263 -129
  14. package/node_modules/@llblab/pi-actors/dist/lib/execution-files.d.ts +32 -0
  15. package/node_modules/@llblab/pi-actors/dist/lib/execution-files.js +128 -0
  16. package/node_modules/@llblab/pi-actors/dist/lib/execution-output.js +5 -4
  17. package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.d.ts +19 -1
  18. package/node_modules/@llblab/pi-actors/dist/lib/execution-sessions.js +62 -26
  19. package/node_modules/@llblab/pi-actors/dist/lib/execution.d.ts +4 -1
  20. package/node_modules/@llblab/pi-actors/dist/lib/execution.js +6 -1
  21. package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.d.ts +9 -2
  22. package/node_modules/@llblab/pi-actors/dist/lib/extension-runtime.js +92 -14
  23. package/node_modules/@llblab/pi-actors/dist/lib/file-state.js +21 -2
  24. package/node_modules/@llblab/pi-actors/dist/lib/inspector-command.js +2 -2
  25. package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.d.ts +25 -7
  26. package/node_modules/@llblab/pi-actors/dist/lib/inspector-overlay.js +562 -262
  27. package/node_modules/@llblab/pi-actors/dist/lib/inspector.d.ts +20 -10
  28. package/node_modules/@llblab/pi-actors/dist/lib/inspector.js +80 -91
  29. package/node_modules/@llblab/pi-actors/dist/lib/limits.d.ts +1 -0
  30. package/node_modules/@llblab/pi-actors/dist/lib/limits.js +1 -0
  31. package/node_modules/@llblab/pi-actors/dist/lib/observability.d.ts +15 -1
  32. package/node_modules/@llblab/pi-actors/dist/lib/observability.js +216 -99
  33. package/node_modules/@llblab/pi-actors/dist/lib/pi.d.ts +5 -4
  34. package/node_modules/@llblab/pi-actors/dist/lib/pi.js +64 -10
  35. package/node_modules/@llblab/pi-actors/dist/lib/recipe-projection.d.ts +18 -0
  36. package/node_modules/@llblab/pi-actors/dist/lib/recipe-projection.js +220 -0
  37. package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.d.ts +2 -0
  38. package/node_modules/@llblab/pi-actors/dist/lib/recipes-context.js +30 -6
  39. package/node_modules/@llblab/pi-actors/dist/lib/registry.js +270 -36
  40. package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.d.ts +213 -5
  41. package/node_modules/@llblab/pi-actors/dist/lib/run-delivery.js +1909 -40
  42. package/node_modules/@llblab/pi-actors/dist/lib/run-supervision.d.ts +107 -0
  43. package/node_modules/@llblab/pi-actors/dist/lib/run-supervision.js +412 -0
  44. package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.d.ts +9 -2
  45. package/node_modules/@llblab/pi-actors/dist/lib/run-ui-runtime.js +283 -60
  46. package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.d.ts +26 -1
  47. package/node_modules/@llblab/pi-actors/dist/lib/runs-artifacts.js +68 -2
  48. package/node_modules/@llblab/pi-actors/dist/lib/runs-context-exports.d.ts +451 -0
  49. package/node_modules/@llblab/pi-actors/dist/lib/runs-context-exports.js +2315 -0
  50. package/node_modules/@llblab/pi-actors/dist/lib/runs-context-index.d.ts +97 -0
  51. package/node_modules/@llblab/pi-actors/dist/lib/runs-context-index.js +368 -0
  52. package/node_modules/@llblab/pi-actors/dist/lib/runs-control-delivery.js +46 -7
  53. package/node_modules/@llblab/pi-actors/dist/lib/runs-control.d.ts +78 -2
  54. package/node_modules/@llblab/pi-actors/dist/lib/runs-control.js +334 -2
  55. package/node_modules/@llblab/pi-actors/dist/lib/runs-controls.js +4 -1
  56. package/node_modules/@llblab/pi-actors/dist/lib/runs-descendant-launches.d.ts +80 -0
  57. package/node_modules/@llblab/pi-actors/dist/lib/runs-descendant-launches.js +287 -0
  58. package/node_modules/@llblab/pi-actors/dist/lib/runs-execution-evidence.d.ts +110 -0
  59. package/node_modules/@llblab/pi-actors/dist/lib/runs-execution-evidence.js +282 -0
  60. package/node_modules/@llblab/pi-actors/dist/lib/runs-index.d.ts +66 -1
  61. package/node_modules/@llblab/pi-actors/dist/lib/runs-index.js +349 -13
  62. package/node_modules/@llblab/pi-actors/dist/lib/runs-native-launches.d.ts +73 -0
  63. package/node_modules/@llblab/pi-actors/dist/lib/runs-native-launches.js +227 -0
  64. package/node_modules/@llblab/pi-actors/dist/lib/runs-outcomes.d.ts +141 -0
  65. package/node_modules/@llblab/pi-actors/dist/lib/runs-outcomes.js +292 -0
  66. package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.d.ts +10 -1
  67. package/node_modules/@llblab/pi-actors/dist/lib/runs-ownership.js +36 -4
  68. package/node_modules/@llblab/pi-actors/dist/lib/runs-process-windows-mi.d.ts +46 -0
  69. package/node_modules/@llblab/pi-actors/dist/lib/runs-process-windows-mi.js +114 -0
  70. package/node_modules/@llblab/pi-actors/dist/lib/runs-process.d.ts +34 -1
  71. package/node_modules/@llblab/pi-actors/dist/lib/runs-process.js +158 -26
  72. package/node_modules/@llblab/pi-actors/dist/lib/runs-results.d.ts +116 -0
  73. package/node_modules/@llblab/pi-actors/dist/lib/runs-results.js +518 -0
  74. package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.d.ts +15 -2
  75. package/node_modules/@llblab/pi-actors/dist/lib/runs-retention.js +148 -9
  76. package/node_modules/@llblab/pi-actors/dist/lib/runs-session-exports.d.ts +95 -0
  77. package/node_modules/@llblab/pi-actors/dist/lib/runs-session-exports.js +470 -0
  78. package/node_modules/@llblab/pi-actors/dist/lib/runs-snapshot.d.ts +58 -0
  79. package/node_modules/@llblab/pi-actors/dist/lib/runs-snapshot.js +92 -0
  80. package/node_modules/@llblab/pi-actors/dist/lib/runs-start.d.ts +2 -0
  81. package/node_modules/@llblab/pi-actors/dist/lib/runs-start.js +44 -3
  82. package/node_modules/@llblab/pi-actors/dist/lib/runs-status.d.ts +15 -1
  83. package/node_modules/@llblab/pi-actors/dist/lib/runs-status.js +337 -13
  84. package/node_modules/@llblab/pi-actors/dist/lib/runs-supervision.d.ts +105 -0
  85. package/node_modules/@llblab/pi-actors/dist/lib/runs-supervision.js +501 -0
  86. package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.d.ts +1 -0
  87. package/node_modules/@llblab/pi-actors/dist/lib/runs-trace.js +14 -3
  88. package/node_modules/@llblab/pi-actors/dist/lib/runtime.js +22 -3
  89. package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.d.ts +37 -0
  90. package/node_modules/@llblab/pi-actors/dist/lib/session-evidence.js +59 -3
  91. package/node_modules/@llblab/pi-actors/dist/lib/state-readers.d.ts +4 -1
  92. package/node_modules/@llblab/pi-actors/dist/lib/state-readers.js +14 -8
  93. package/node_modules/@llblab/pi-actors/dist/lib/temp.d.ts +2 -4
  94. package/node_modules/@llblab/pi-actors/dist/lib/temp.js +4 -56
  95. package/node_modules/@llblab/pi-actors/dist/lib/tools-access.d.ts +3 -0
  96. package/node_modules/@llblab/pi-actors/dist/lib/tools-access.js +13 -0
  97. package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.d.ts +1 -0
  98. package/node_modules/@llblab/pi-actors/dist/lib/tools-inspect.js +110 -43
  99. package/node_modules/@llblab/pi-actors/dist/lib/tools-local.d.ts +3 -0
  100. package/node_modules/@llblab/pi-actors/dist/lib/tools-local.js +18 -6
  101. package/node_modules/@llblab/pi-actors/dist/lib/tools-message.d.ts +4 -1
  102. package/node_modules/@llblab/pi-actors/dist/lib/tools-message.js +126 -31
  103. package/node_modules/@llblab/pi-actors/dist/lib/tools-response.d.ts +31 -3
  104. package/node_modules/@llblab/pi-actors/dist/lib/tools-response.js +311 -47
  105. package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.d.ts +3 -0
  106. package/node_modules/@llblab/pi-actors/dist/lib/tools-spawn.js +29 -7
  107. package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.d.ts +20 -0
  108. package/node_modules/@llblab/pi-actors/dist/lib/trace-projection.js +192 -43
  109. package/node_modules/@llblab/pi-actors/dist/scripts/async-runner.mjs +272 -194
  110. package/node_modules/@llblab/pi-actors/dist/scripts/conformance.mjs +14 -2
  111. package/node_modules/@llblab/pi-actors/dist/skills/actors/SKILL.md +46 -2
  112. package/node_modules/@llblab/pi-actors/dist/skills/actors/references/diagnostics.md +40 -0
  113. package/node_modules/@llblab/pi-actors/dist/skills/actors/references/runs.md +55 -1
  114. package/node_modules/@llblab/pi-actors/docs/README.md +9 -1
  115. package/node_modules/@llblab/pi-actors/docs/actor-inspector.md +84 -15
  116. package/node_modules/@llblab/pi-actors/docs/agent-experience.md +216 -0
  117. package/node_modules/@llblab/pi-actors/docs/async-runs.md +18 -2
  118. package/node_modules/@llblab/pi-actors/docs/composition-transport.md +103 -0
  119. package/node_modules/@llblab/pi-actors/docs/coordinator-delivery.md +204 -4
  120. package/node_modules/@llblab/pi-actors/docs/inspection.md +38 -2
  121. package/node_modules/@llblab/pi-actors/docs/output-projection-map.md +130 -0
  122. package/node_modules/@llblab/pi-actors/docs/releasing.md +19 -2
  123. package/node_modules/@llblab/pi-actors/docs/run-supervision.md +1622 -0
  124. package/node_modules/@llblab/pi-actors/docs/template-recipes.md +4 -0
  125. package/node_modules/@llblab/pi-actors/docs/windows-process-observation.md +248 -0
  126. package/node_modules/@llblab/pi-actors/index.ts +1 -1
  127. package/node_modules/@llblab/pi-actors/lib/async-runs.ts +164 -73
  128. package/node_modules/@llblab/pi-actors/lib/automatic-review-runtime.ts +4 -2
  129. package/node_modules/@llblab/pi-actors/lib/command-templates.ts +287 -138
  130. package/node_modules/@llblab/pi-actors/lib/execution-files.ts +118 -0
  131. package/node_modules/@llblab/pi-actors/lib/execution-output.ts +4 -4
  132. package/node_modules/@llblab/pi-actors/lib/execution-sessions.ts +57 -27
  133. package/node_modules/@llblab/pi-actors/lib/execution.ts +8 -0
  134. package/node_modules/@llblab/pi-actors/lib/extension-runtime.ts +102 -12
  135. package/node_modules/@llblab/pi-actors/lib/file-state.ts +16 -2
  136. package/node_modules/@llblab/pi-actors/lib/inspector-command.ts +2 -2
  137. package/node_modules/@llblab/pi-actors/lib/inspector-overlay.ts +524 -261
  138. package/node_modules/@llblab/pi-actors/lib/inspector.ts +101 -130
  139. package/node_modules/@llblab/pi-actors/lib/limits.ts +1 -0
  140. package/node_modules/@llblab/pi-actors/lib/observability.ts +235 -116
  141. package/node_modules/@llblab/pi-actors/lib/pi.ts +59 -11
  142. package/node_modules/@llblab/pi-actors/lib/recipe-projection.ts +232 -0
  143. package/node_modules/@llblab/pi-actors/lib/recipes-context.ts +27 -6
  144. package/node_modules/@llblab/pi-actors/lib/registry.ts +266 -36
  145. package/node_modules/@llblab/pi-actors/lib/run-delivery.ts +1737 -49
  146. package/node_modules/@llblab/pi-actors/lib/run-supervision.ts +411 -0
  147. package/node_modules/@llblab/pi-actors/lib/run-ui-runtime.ts +237 -73
  148. package/node_modules/@llblab/pi-actors/lib/runs-artifacts.ts +73 -1
  149. package/node_modules/@llblab/pi-actors/lib/runs-context-exports.ts +1871 -0
  150. package/node_modules/@llblab/pi-actors/lib/runs-context-index.ts +372 -0
  151. package/node_modules/@llblab/pi-actors/lib/runs-control-delivery.ts +36 -18
  152. package/node_modules/@llblab/pi-actors/lib/runs-control.ts +297 -1
  153. package/node_modules/@llblab/pi-actors/lib/runs-controls.ts +3 -1
  154. package/node_modules/@llblab/pi-actors/lib/runs-descendant-launches.ts +338 -0
  155. package/node_modules/@llblab/pi-actors/lib/runs-execution-evidence.ts +302 -0
  156. package/node_modules/@llblab/pi-actors/lib/runs-index.ts +345 -17
  157. package/node_modules/@llblab/pi-actors/lib/runs-native-launches.ts +270 -0
  158. package/node_modules/@llblab/pi-actors/lib/runs-outcomes.ts +377 -0
  159. package/node_modules/@llblab/pi-actors/lib/runs-ownership.ts +37 -4
  160. package/node_modules/@llblab/pi-actors/lib/runs-process-windows-mi.ts +113 -0
  161. package/node_modules/@llblab/pi-actors/lib/runs-process.ts +210 -34
  162. package/node_modules/@llblab/pi-actors/lib/runs-results.ts +601 -0
  163. package/node_modules/@llblab/pi-actors/lib/runs-retention.ts +134 -10
  164. package/node_modules/@llblab/pi-actors/lib/runs-session-exports.ts +406 -0
  165. package/node_modules/@llblab/pi-actors/lib/runs-snapshot.ts +143 -0
  166. package/node_modules/@llblab/pi-actors/lib/runs-start.ts +44 -2
  167. package/node_modules/@llblab/pi-actors/lib/runs-status.ts +252 -10
  168. package/node_modules/@llblab/pi-actors/lib/runs-supervision.ts +394 -0
  169. package/node_modules/@llblab/pi-actors/lib/runs-trace.ts +14 -3
  170. package/node_modules/@llblab/pi-actors/lib/runtime.ts +22 -3
  171. package/node_modules/@llblab/pi-actors/lib/session-evidence.ts +76 -4
  172. package/node_modules/@llblab/pi-actors/lib/state-readers.ts +16 -7
  173. package/node_modules/@llblab/pi-actors/lib/temp.ts +3 -56
  174. package/node_modules/@llblab/pi-actors/lib/tools-access.ts +13 -0
  175. package/node_modules/@llblab/pi-actors/lib/tools-inspect.ts +110 -51
  176. package/node_modules/@llblab/pi-actors/lib/tools-local.ts +37 -24
  177. package/node_modules/@llblab/pi-actors/lib/tools-message.ts +120 -37
  178. package/node_modules/@llblab/pi-actors/lib/tools-response.ts +273 -50
  179. package/node_modules/@llblab/pi-actors/lib/tools-spawn.ts +31 -10
  180. package/node_modules/@llblab/pi-actors/lib/trace-projection.ts +165 -42
  181. package/node_modules/@llblab/pi-actors/package.json +10 -6
  182. package/node_modules/@llblab/pi-actors/scripts/async-runner.mjs +272 -194
  183. package/node_modules/@llblab/pi-actors/scripts/conformance.mjs +14 -2
  184. package/node_modules/@llblab/pi-actors/skills/actors/SKILL.md +46 -2
  185. package/node_modules/@llblab/pi-actors/skills/actors/references/diagnostics.md +40 -0
  186. package/node_modules/@llblab/pi-actors/skills/actors/references/runs.md +55 -1
  187. package/node_modules/yaml/LICENSE +13 -0
  188. package/node_modules/yaml/README.md +172 -0
  189. package/node_modules/yaml/bin.mjs +11 -0
  190. package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
  191. package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
  192. package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
  193. package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
  194. package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
  195. package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
  196. package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  197. package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
  198. package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
  199. package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
  200. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +225 -0
  201. package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
  202. package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  203. package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
  204. package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  205. package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
  206. package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
  207. package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
  208. package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
  209. package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
  210. package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
  211. package/node_modules/yaml/browser/dist/errors.js +57 -0
  212. package/node_modules/yaml/browser/dist/index.js +17 -0
  213. package/node_modules/yaml/browser/dist/log.js +11 -0
  214. package/node_modules/yaml/browser/dist/nodes/Alias.js +116 -0
  215. package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
  216. package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
  217. package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
  218. package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
  219. package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  220. package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  221. package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
  222. package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
  223. package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
  224. package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
  225. package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
  226. package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
  227. package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
  228. package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
  229. package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
  230. package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
  231. package/node_modules/yaml/browser/dist/public-api.js +102 -0
  232. package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
  233. package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
  234. package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
  235. package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
  236. package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
  237. package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
  238. package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
  239. package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
  240. package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
  241. package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
  242. package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
  243. package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
  244. package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  245. package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  246. package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  247. package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
  248. package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  249. package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  250. package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
  251. package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  252. package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  253. package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  254. package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
  255. package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
  256. package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  257. package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  258. package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
  259. package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  260. package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
  261. package/node_modules/yaml/browser/dist/util.js +11 -0
  262. package/node_modules/yaml/browser/dist/visit.js +233 -0
  263. package/node_modules/yaml/browser/index.js +5 -0
  264. package/node_modules/yaml/browser/package.json +3 -0
  265. package/node_modules/yaml/dist/cli.d.ts +8 -0
  266. package/node_modules/yaml/dist/cli.mjs +201 -0
  267. package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  268. package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  269. package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  270. package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  271. package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
  272. package/node_modules/yaml/dist/compose/compose-node.js +112 -0
  273. package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  274. package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  275. package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
  276. package/node_modules/yaml/dist/compose/composer.js +224 -0
  277. package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  278. package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  279. package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  280. package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  281. package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  282. package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  283. package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  284. package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  285. package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  286. package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  287. package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  288. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
  289. package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  290. package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  291. package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  292. package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  293. package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  294. package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  295. package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  296. package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  297. package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  298. package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  299. package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  300. package/node_modules/yaml/dist/doc/Document.js +337 -0
  301. package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  302. package/node_modules/yaml/dist/doc/anchors.js +76 -0
  303. package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  304. package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  305. package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  306. package/node_modules/yaml/dist/doc/createNode.js +90 -0
  307. package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  308. package/node_modules/yaml/dist/doc/directives.js +178 -0
  309. package/node_modules/yaml/dist/errors.d.ts +21 -0
  310. package/node_modules/yaml/dist/errors.js +62 -0
  311. package/node_modules/yaml/dist/index.d.ts +25 -0
  312. package/node_modules/yaml/dist/index.js +50 -0
  313. package/node_modules/yaml/dist/log.d.ts +3 -0
  314. package/node_modules/yaml/dist/log.js +19 -0
  315. package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
  316. package/node_modules/yaml/dist/nodes/Alias.js +118 -0
  317. package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  318. package/node_modules/yaml/dist/nodes/Collection.js +151 -0
  319. package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
  320. package/node_modules/yaml/dist/nodes/Node.js +40 -0
  321. package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
  322. package/node_modules/yaml/dist/nodes/Pair.js +39 -0
  323. package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
  324. package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  325. package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  326. package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  327. package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  328. package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  329. package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  330. package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  331. package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  332. package/node_modules/yaml/dist/nodes/identity.js +53 -0
  333. package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
  334. package/node_modules/yaml/dist/nodes/toJS.js +39 -0
  335. package/node_modules/yaml/dist/options.d.ts +350 -0
  336. package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  337. package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  338. package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  339. package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  340. package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  341. package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  342. package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
  343. package/node_modules/yaml/dist/parse/cst.js +112 -0
  344. package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  345. package/node_modules/yaml/dist/parse/lexer.js +723 -0
  346. package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  347. package/node_modules/yaml/dist/parse/line-counter.js +41 -0
  348. package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  349. package/node_modules/yaml/dist/parse/parser.js +980 -0
  350. package/node_modules/yaml/dist/public-api.d.ts +44 -0
  351. package/node_modules/yaml/dist/public-api.js +107 -0
  352. package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
  353. package/node_modules/yaml/dist/schema/Schema.js +39 -0
  354. package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  355. package/node_modules/yaml/dist/schema/common/map.js +19 -0
  356. package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  357. package/node_modules/yaml/dist/schema/common/null.js +17 -0
  358. package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  359. package/node_modules/yaml/dist/schema/common/seq.js +19 -0
  360. package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  361. package/node_modules/yaml/dist/schema/common/string.js +16 -0
  362. package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  363. package/node_modules/yaml/dist/schema/core/bool.js +21 -0
  364. package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  365. package/node_modules/yaml/dist/schema/core/float.js +47 -0
  366. package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  367. package/node_modules/yaml/dist/schema/core/int.js +42 -0
  368. package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  369. package/node_modules/yaml/dist/schema/core/schema.js +25 -0
  370. package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  371. package/node_modules/yaml/dist/schema/json/schema.js +64 -0
  372. package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  373. package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
  374. package/node_modules/yaml/dist/schema/tags.js +99 -0
  375. package/node_modules/yaml/dist/schema/types.d.ts +92 -0
  376. package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  377. package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  378. package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  379. package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  380. package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  381. package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  382. package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  383. package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  384. package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  385. package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  386. package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
  387. package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  388. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  389. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  390. package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  391. package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  392. package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  393. package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  394. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  395. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  396. package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  397. package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  398. package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  399. package/node_modules/yaml/dist/stringify/stringify.js +132 -0
  400. package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  401. package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  402. package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  403. package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  404. package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  405. package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  406. package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  407. package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  408. package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  409. package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  410. package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  411. package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  412. package/node_modules/yaml/dist/test-events.d.ts +4 -0
  413. package/node_modules/yaml/dist/test-events.js +134 -0
  414. package/node_modules/yaml/dist/util.d.ts +16 -0
  415. package/node_modules/yaml/dist/util.js +28 -0
  416. package/node_modules/yaml/dist/visit.d.ts +102 -0
  417. package/node_modules/yaml/dist/visit.js +236 -0
  418. package/node_modules/yaml/package.json +97 -0
  419. package/node_modules/yaml/util.js +2 -0
  420. package/package.json +2 -2
  421. package/node_modules/@llblab/pi-actors/banner.jpg +0 -0
  422. package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.d.ts +0 -16
  423. package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.js +0 -57
  424. package/node_modules/@llblab/pi-actors/lib/inspector-actions.ts +0 -79
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Native launch evidence persistence.
3
+ * Owns: generation-bound intent/birth/settlement records and unresolved-scope mutation fences.
4
+ * Excludes: runtime-local admission/acquisition, complete membership, termination, and restart execution.
5
+ */
6
+ import { randomUUID } from "node:crypto";
7
+ import { lstatSync } from "node:fs";
8
+ import { join } from "node:path";
9
+ import { writeJsonAtomic } from "./file-state.js";
10
+ import { assertOwnedRunStateDirectory } from "./runs-ownership.js";
11
+ import { runProcessIdentityDigest } from "./runs-process.js";
12
+ import { readJsonFileResilient } from "./state-readers.js";
13
+ export const RUN_NATIVE_LAUNCH_FILE = "native-launches.json";
14
+ const SCHEMA = "run-native-launches-v1";
15
+ function record(value) {
16
+ return value !== null && typeof value === "object" && !Array.isArray(value);
17
+ }
18
+ function onlyKeys(value, keys) {
19
+ return Object.keys(value).every((key) => keys.includes(key));
20
+ }
21
+ function text(value) {
22
+ return typeof value === "string" && value.length > 0;
23
+ }
24
+ function intentId(value) {
25
+ return typeof value === "string" &&
26
+ /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.exec(value)?.[0] === value;
27
+ }
28
+ function canonicalTimestamp(value) {
29
+ if (!text(value))
30
+ return false;
31
+ try {
32
+ return new Date(value).toISOString() === value;
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ function validRequest(value) {
39
+ if (!record(value))
40
+ return false;
41
+ return typeof value.commandId === "string" &&
42
+ /^command-[0-9]{3,}$/.exec(value.commandId)?.[0] === value.commandId &&
43
+ Number.isSafeInteger(value.attempt) && Number(value.attempt) > 0;
44
+ }
45
+ function validOwner(owner) {
46
+ return !!owner && text(owner.run) && text(owner.runInstanceId) &&
47
+ Number.isSafeInteger(owner.pid) && owner.pid > 0 &&
48
+ (owner.ownerId === undefined || text(owner.ownerId)) &&
49
+ (owner.processIdentityDigest === undefined ||
50
+ (typeof owner.processIdentityDigest === "string" && /^[a-f0-9]{64}$/.exec(owner.processIdentityDigest)?.[0] === owner.processIdentityDigest));
51
+ }
52
+ function decodeBirth(value, runnerPid) {
53
+ if (!record(value) || !onlyKeys(value, ["pid", "observed_at", "process_identity"]) ||
54
+ !Number.isSafeInteger(value.pid) || Number(value.pid) <= 0 || value.pid === runnerPid ||
55
+ !canonicalTimestamp(value.observed_at) || !record(value.process_identity))
56
+ return undefined;
57
+ const identity = value.process_identity;
58
+ if (!onlyKeys(identity, ["platform", "start_time", "command", "cwd"]) || !runProcessIdentityDigest(identity) ||
59
+ (identity.cwd !== undefined && !text(identity.cwd)))
60
+ return undefined;
61
+ return Object.freeze({
62
+ pid: Number(value.pid), observed_at: value.observed_at,
63
+ process_identity: Object.freeze({
64
+ platform: identity.platform, start_time: String(identity.start_time), command: String(identity.command),
65
+ ...(identity.cwd === undefined ? {} : { cwd: String(identity.cwd) }),
66
+ }),
67
+ });
68
+ }
69
+ function decodeSettlement(value) {
70
+ if (!record(value) || !canonicalTimestamp(value.observed_at))
71
+ return undefined;
72
+ if (value.basis === "verified_absence") {
73
+ return onlyKeys(value, ["basis", "observed_at"])
74
+ ? Object.freeze({ basis: "verified_absence", observed_at: value.observed_at }) : undefined;
75
+ }
76
+ if (!onlyKeys(value, ["observed_at", "native_exit_code", "native_signal"]))
77
+ return undefined;
78
+ const code = value.native_exit_code;
79
+ const signal = value.native_signal;
80
+ if (!((Number.isSafeInteger(code) && signal === null) ||
81
+ (code === null && typeof signal === "string" && /^SIG[A-Z0-9]+$/.exec(signal)?.[0] === signal)))
82
+ return undefined;
83
+ return Object.freeze({
84
+ observed_at: value.observed_at, native_exit_code: code, native_signal: signal,
85
+ });
86
+ }
87
+ function decode(value, owner) {
88
+ if (!record(value) || !onlyKeys(value, ["schema", "run", "run_instance_id", "ownerId", "runner_pid", "runner_identity_digest", "intents"]) ||
89
+ value.schema !== SCHEMA || value.run !== owner.run ||
90
+ value.run_instance_id !== owner.runInstanceId || value.ownerId !== owner.ownerId ||
91
+ value.runner_pid !== owner.pid || value.runner_identity_digest !== (owner.processIdentityDigest ?? null) ||
92
+ !Array.isArray(value.intents))
93
+ return undefined;
94
+ const ids = new Set();
95
+ const attempts = new Map();
96
+ const births = new Set();
97
+ const intents = [];
98
+ for (const item of value.intents) {
99
+ if (!record(item) || !onlyKeys(item, ["intent_id", "command_id", "attempt", "admitted_at", "birth", "settlement"]) ||
100
+ !intentId(item.intent_id) || ids.has(item.intent_id) ||
101
+ !validRequest({ commandId: item.command_id, attempt: item.attempt }) || !canonicalTimestamp(item.admitted_at))
102
+ return undefined;
103
+ const command = String(item.command_id);
104
+ const attempt = Number(item.attempt);
105
+ if (attempt !== (attempts.get(command) ?? 0) + 1)
106
+ return undefined;
107
+ const birth = item.birth === undefined ? undefined : decodeBirth(item.birth, owner.pid);
108
+ if (item.birth !== undefined && !birth)
109
+ return undefined;
110
+ if (birth) {
111
+ const key = JSON.stringify([birth.process_identity.platform, birth.pid, birth.process_identity.start_time]);
112
+ if (births.has(key))
113
+ return undefined;
114
+ births.add(key);
115
+ }
116
+ const settlement = item.settlement === undefined ? undefined : decodeSettlement(item.settlement);
117
+ if (item.settlement !== undefined && (!birth || !settlement))
118
+ return undefined;
119
+ ids.add(item.intent_id);
120
+ attempts.set(command, attempt);
121
+ intents.push(Object.freeze({ intent_id: item.intent_id, command_id: command, attempt, admitted_at: item.admitted_at,
122
+ ...(birth ? { birth } : {}), ...(settlement ? { settlement } : {}) }));
123
+ }
124
+ return Object.freeze({
125
+ schema: SCHEMA, run: owner.run, run_instance_id: owner.runInstanceId,
126
+ ...(owner.ownerId === undefined ? {} : { ownerId: owner.ownerId }),
127
+ runner_pid: owner.pid, runner_identity_digest: owner.processIdentityDigest ?? null,
128
+ intents: Object.freeze(intents),
129
+ });
130
+ }
131
+ /** Even every recorded member's settlement is not complete-scope closure or mutation authority. */
132
+ export function assertNoRetainedNativeLaunchScope(stateDir) {
133
+ try {
134
+ lstatSync(join(stateDir, RUN_NATIVE_LAUNCH_FILE));
135
+ }
136
+ catch (error) {
137
+ if (error.code === "ENOENT")
138
+ return;
139
+ }
140
+ throw new Error("Run native launch scope is unproven; confirm the complete owned scope before replacing or retiring its state.");
141
+ }
142
+ /** Absence or an available admission list never proves no child was born or complete scope membership. */
143
+ export function readRunNativeLaunchLedger(stateDir, owner) {
144
+ if (!validOwner(owner))
145
+ return { state: "invalid" };
146
+ let path;
147
+ try {
148
+ path = join(assertOwnedRunStateDirectory(stateDir, owner.run), RUN_NATIVE_LAUNCH_FILE);
149
+ }
150
+ catch {
151
+ return { state: "invalid" };
152
+ }
153
+ try {
154
+ if (!lstatSync(path).isFile())
155
+ return { state: "invalid" };
156
+ }
157
+ catch (error) {
158
+ return { state: error.code === "ENOENT" ? "absent" : "invalid" };
159
+ }
160
+ const read = readJsonFileResilient(path, undefined);
161
+ if (read.diagnostics.length)
162
+ return { state: "invalid" };
163
+ const ledger = decode(read.value, owner);
164
+ return ledger ? { state: "available", ledger } : { state: "invalid" };
165
+ }
166
+ /** Storage only: caller must hold lifecycle admission and supply a kernel-acquired birth, never replayed runtime authority. */
167
+ export function recordRunNativeLaunchBirthUnderLock(stateDir, owner, intent, birth) {
168
+ if (!validOwner(owner))
169
+ throw new Error("Run native launch identity or request is invalid.");
170
+ const canonical = assertOwnedRunStateDirectory(stateDir, owner.run);
171
+ const current = readRunNativeLaunchLedger(canonical, owner);
172
+ if (current.state !== "available")
173
+ throw new Error("Run native launch evidence is unavailable or invalid.");
174
+ const index = current.ledger.intents.findIndex((item) => item.intent_id === intent.intent_id);
175
+ const prior = current.ledger.intents[index];
176
+ if (!prior || prior.birth || prior.command_id !== intent.command_id || prior.attempt !== intent.attempt ||
177
+ prior.admitted_at !== intent.admitted_at)
178
+ throw new Error("Run native launch birth binding changed or is already retained.");
179
+ const updated = decode({ ...current.ledger, intents: current.ledger.intents.map((item, i) => i === index ? { ...item, birth } : item) }, owner);
180
+ if (!updated)
181
+ throw new Error("Run native launch birth evidence is unavailable or invalid.");
182
+ writeJsonAtomic(join(canonical, RUN_NATIVE_LAUNCH_FILE), updated);
183
+ return updated.intents[index].birth;
184
+ }
185
+ /** Storage only: exact retained birth plus admitted native-close or verified-absence evidence, never work authority. */
186
+ export function recordRunNativeLaunchSettlementUnderLock(stateDir, owner, update) {
187
+ if (!validOwner(owner))
188
+ throw new Error("Run native launch identity or request is invalid.");
189
+ const canonical = assertOwnedRunStateDirectory(stateDir, owner.run);
190
+ const current = readRunNativeLaunchLedger(canonical, owner);
191
+ if (current.state !== "available")
192
+ throw new Error("Run native launch evidence is unavailable or invalid.");
193
+ const { intent, birth, settlement } = update;
194
+ const index = current.ledger.intents.findIndex((item) => item.intent_id === intent.intent_id);
195
+ const prior = current.ledger.intents[index];
196
+ if (!prior?.birth || prior.settlement || prior.command_id !== intent.command_id || prior.attempt !== intent.attempt ||
197
+ prior.admitted_at !== intent.admitted_at || prior.birth.pid !== birth.pid || prior.birth.observed_at !== birth.observed_at ||
198
+ runProcessIdentityDigest(prior.birth.process_identity) !== runProcessIdentityDigest(birth.process_identity)) {
199
+ throw new Error("Run native launch settlement binding changed or is already retained.");
200
+ }
201
+ const updated = decode({ ...current.ledger, intents: current.ledger.intents.map((item, i) => i === index ? { ...item, settlement } : item) }, owner);
202
+ if (!updated)
203
+ throw new Error("Run native launch settlement evidence is unavailable or invalid.");
204
+ writeJsonAtomic(join(canonical, RUN_NATIVE_LAUNCH_FILE), updated);
205
+ return updated.intents[index].settlement;
206
+ }
207
+ /** Kernel storage only: caller must hold lifecycle/work admission. No reset or rollback of existing intents. */
208
+ export function recordRunNativeLaunchIntentUnderLock(stateDir, owner, request) {
209
+ if (!validOwner(owner) || !validRequest(request))
210
+ throw new Error("Run native launch identity or request is invalid.");
211
+ const canonical = assertOwnedRunStateDirectory(stateDir, owner.run);
212
+ const current = readRunNativeLaunchLedger(canonical, owner);
213
+ if (current.state === "invalid")
214
+ throw new Error("Run native launch evidence is unavailable or invalid.");
215
+ const prior = current.state === "available" ? current.ledger.intents : [];
216
+ const last = prior.filter((item) => item.command_id === request.commandId).at(-1)?.attempt ?? 0;
217
+ if (request.attempt !== last + 1)
218
+ throw new Error("Run native launch attempt is duplicate or out of order.");
219
+ const intent = Object.freeze({ intent_id: randomUUID(), command_id: request.commandId, attempt: request.attempt, admitted_at: new Date().toISOString() });
220
+ writeJsonAtomic(join(canonical, RUN_NATIVE_LAUNCH_FILE), {
221
+ schema: SCHEMA, run: owner.run, run_instance_id: owner.runInstanceId,
222
+ ...(owner.ownerId === undefined ? {} : { ownerId: owner.ownerId }),
223
+ runner_pid: owner.pid, runner_identity_digest: owner.processIdentityDigest ?? null,
224
+ intents: [...prior, intent],
225
+ });
226
+ return intent;
227
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Generation-bound outcome protocol and durable stop-request state.
3
+ * Owns: bounded stop records, process binding, lifecycle-locked stop persistence, canonical result classification and primary/artifact binding data schemas.
4
+ * Excludes: lock acquisition, primary body admission/publication, deadline eligibility, signals, exit proof and delivery.
5
+ */
6
+ export declare const RUN_PRIMARY_TEXT_PROTOCOL = "run-primary-text-v1";
7
+ export declare const RUN_ARTIFACT_INVENTORY_PROTOCOL = "run-artifact-inventory-v1";
8
+ export declare const RUN_RESULT_DIAGNOSTICS_PROTOCOL = "run-result-diagnostics-v1";
9
+ export declare const RUN_RESULT_DIAGNOSTIC_FIELDS: readonly ["command", "error", "failure_reason"];
10
+ export type RunResultDiagnosticField = typeof RUN_RESULT_DIAGNOSTIC_FIELDS[number];
11
+ export type RunResultDiagnosticCandidate = Readonly<Partial<Record<RunResultDiagnosticField, string>>>;
12
+ export declare const RUN_RESULT_DIAGNOSTIC_EXCERPT_CHARS = 1000;
13
+ export interface RunResultDiagnosticExcerpt {
14
+ readonly text: string;
15
+ readonly bytes_total: number;
16
+ readonly shown_bytes: Readonly<{
17
+ start: number;
18
+ end: number;
19
+ }>;
20
+ readonly chars_total: number;
21
+ readonly chars_shown: number;
22
+ readonly chars_omitted: number;
23
+ readonly truncated: boolean;
24
+ }
25
+ export type RunResultDiagnosticPacketExcerpt = Readonly<RunResultDiagnosticExcerpt & {
26
+ field: RunResultDiagnosticField;
27
+ }>;
28
+ export interface RunResultDiagnosticsReference {
29
+ readonly source: Readonly<{
30
+ path: string;
31
+ run_instance_id: string;
32
+ sha256: string;
33
+ }>;
34
+ readonly bytes_total: number;
35
+ readonly fields: readonly RunResultDiagnosticField[];
36
+ }
37
+ export type RunResultDiagnosticsBinding = {
38
+ readonly result_diagnostics: Readonly<RunResultDiagnosticsReference>;
39
+ } | {
40
+ readonly result_diagnostics: null;
41
+ readonly result_diagnostics_unavailable: string;
42
+ };
43
+ export interface RunArtifactInventoryReference {
44
+ readonly source: Readonly<{
45
+ path: string;
46
+ run_instance_id: string;
47
+ sha256: string;
48
+ }>;
49
+ readonly bytes_total: number;
50
+ readonly declarations_total: number;
51
+ }
52
+ export type RunArtifactInventoryBinding = {
53
+ readonly artifact_inventory: Readonly<RunArtifactInventoryReference>;
54
+ } | {
55
+ readonly artifact_inventory: null;
56
+ readonly artifact_inventory_unavailable: string;
57
+ };
58
+ export interface RunPrimaryTextOutput {
59
+ readonly text_basis?: "actor_response";
60
+ readonly upstream_truncated?: boolean;
61
+ readonly source: {
62
+ readonly path: string;
63
+ readonly run_instance_id: string;
64
+ readonly sha256: string;
65
+ };
66
+ readonly bytes_total: number;
67
+ readonly shown_bytes: {
68
+ readonly start: number;
69
+ readonly end: number;
70
+ };
71
+ readonly chars_total: number;
72
+ readonly chars_shown: number;
73
+ readonly chars_omitted: number;
74
+ readonly preview: string;
75
+ readonly truncated: boolean;
76
+ readonly redacted: boolean;
77
+ }
78
+ /** Completion-only admitted source text; this data is not an independent publication or read grant. */
79
+ export interface RunCompletionText {
80
+ readonly text: string;
81
+ readonly shown_bytes: Readonly<{
82
+ start: number;
83
+ end: number;
84
+ }>;
85
+ }
86
+ /** Prefix presentation only; preserve Unicode scalars and never split an admitted CRLF. */
87
+ export declare function projectRunCompletionText(text: string, maxBytes: number): Readonly<RunCompletionText>;
88
+ export declare function decodeRunCompletionText(primary: Readonly<RunPrimaryTextBinding> | undefined, value: unknown): Readonly<RunCompletionText>;
89
+ export type RunPrimaryTextBinding = {
90
+ readonly output: Readonly<RunPrimaryTextOutput>;
91
+ } | {
92
+ readonly output: null;
93
+ readonly output_unavailable: string;
94
+ };
95
+ /** Curated JSON-data schema only; neither decoding nor a protocol marker admits a body, producer or work. */
96
+ export declare function decodeRunPrimaryTextBinding(stateDir: string, generation: string, value: unknown): Readonly<RunPrimaryTextBinding>;
97
+ /** Data schema only; copied actor fields/markers cannot publish or authorize inventory/body reads. */
98
+ export declare function decodeRunArtifactInventoryBinding(stateDir: string, generation: string, value: unknown): Readonly<RunArtifactInventoryBinding>;
99
+ /** Curated diagnostic reference data only, never candidate/producer/publication/body permission. */
100
+ export declare function decodeRunResultDiagnosticsBinding(stateDir: string, generation: string, value: unknown): Readonly<RunResultDiagnosticsBinding>;
101
+ /** Frozen literal prefix metadata only; a valid excerpt/reference DTO does not authorize source publication. */
102
+ export declare function decodeRunResultDiagnosticExcerpt(reference: Readonly<RunResultDiagnosticsReference>, value: unknown): RunResultDiagnosticPacketExcerpt;
103
+ export declare const RUN_OUTCOME_PROTOCOL: "run-outcome-v1";
104
+ export declare const RUN_STOP_CLAIM_FILE = "stop-claim.json";
105
+ export type RunStopReason = "manual_kill" | "max_runtime";
106
+ export interface RunStopClaim {
107
+ version: 1;
108
+ claim_id: string;
109
+ run: string;
110
+ run_instance_id: string;
111
+ ownerId?: string;
112
+ pid: number;
113
+ process_identity_digest: string;
114
+ reason: RunStopReason;
115
+ requested_at: string;
116
+ }
117
+ export type RunStopClaimReading = {
118
+ state: "absent" | "stale" | "invalid";
119
+ } | {
120
+ state: "pending";
121
+ claim: Readonly<RunStopClaim>;
122
+ };
123
+ export declare function readRunStopClaim(stateDir: string, meta: Record<string, unknown>): RunStopClaimReading;
124
+ /** Only the control owner may call this after admission under the canonical lifecycle lock. */
125
+ export declare function writeRunStopClaimUnderLock(stateDir: string, meta: Record<string, unknown>, reason: RunStopReason): Readonly<RunStopClaim>;
126
+ /** Capture markers never imply terminal acceptance, even when their claim is unavailable. */
127
+ export declare function isRunStopResultCapture(result: Record<string, unknown> | undefined): boolean;
128
+ export type RunNaturalOutcomeReading = {
129
+ state: "absent" | "invalid" | "captured";
130
+ } | {
131
+ state: "accepted";
132
+ status: "done" | "failed";
133
+ };
134
+ export interface RunNaturalOutcomeSnapshot {
135
+ readonly result: Record<string, unknown> | undefined;
136
+ readonly outcome: RunNaturalOutcomeReading;
137
+ }
138
+ /** Read one regular-file result snapshot for both precedence and rendering; data never grants work/stop authority. */
139
+ export declare function readRunNaturalOutcomeSnapshot(stateDir: string, meta: Record<string, unknown>, readResult?: (path: string) => unknown): Readonly<RunNaturalOutcomeSnapshot>;
140
+ /** Result bodies remain in their existing canonical file; this is admission, not a second store. */
141
+ export declare function readRunNaturalOutcome(stateDir: string, meta: Record<string, unknown>): RunNaturalOutcomeReading;
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Generation-bound outcome protocol and durable stop-request state.
3
+ * Owns: bounded stop records, process binding, lifecycle-locked stop persistence, canonical result classification and primary/artifact binding data schemas.
4
+ * Excludes: lock acquisition, primary body admission/publication, deadline eligibility, signals, exit proof and delivery.
5
+ */
6
+ import { createHash, randomUUID } from "node:crypto";
7
+ import { lstatSync } from "node:fs";
8
+ import { basename, dirname, isAbsolute, join, resolve } from "node:path";
9
+ import { writeJsonAtomic } from "./file-state.js";
10
+ import { RUN_COMPLETION_MODEL_MAX_BYTES, RUN_DELIVERY_MODEL_MAX_BYTES } from "./limits.js";
11
+ import { runProcessIdentityDigest } from "./runs-process.js";
12
+ import { readJsonFileResilient } from "./state-readers.js";
13
+ export const RUN_PRIMARY_TEXT_PROTOCOL = "run-primary-text-v1";
14
+ export const RUN_ARTIFACT_INVENTORY_PROTOCOL = "run-artifact-inventory-v1";
15
+ export const RUN_RESULT_DIAGNOSTICS_PROTOCOL = "run-result-diagnostics-v1";
16
+ export const RUN_RESULT_DIAGNOSTIC_FIELDS = ["command", "error", "failure_reason"];
17
+ export const RUN_RESULT_DIAGNOSTIC_EXCERPT_CHARS = 1_000;
18
+ /** Prefix presentation only; preserve Unicode scalars and never split an admitted CRLF. */
19
+ export function projectRunCompletionText(text, maxBytes) {
20
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 0 || maxBytes > RUN_COMPLETION_MODEL_MAX_BYTES ||
21
+ Buffer.from(text).toString("utf8") !== text)
22
+ throw new Error("Completion text prefix is invalid.");
23
+ const bytes = Buffer.from(text);
24
+ let end = Math.min(bytes.length, maxBytes);
25
+ while (end > 0 && end < bytes.length && (bytes[end] & 0xc0) === 0x80)
26
+ end--;
27
+ if (end < bytes.length && bytes[end - 1] === 13 && bytes[end] === 10)
28
+ end--;
29
+ return Object.freeze({ text: bytes.subarray(0, end).toString("utf8"), shown_bytes: Object.freeze({ start: 0, end }) });
30
+ }
31
+ export function decodeRunCompletionText(primary, value) {
32
+ const data = primaryData(value), range = primaryData(data?.shown_bytes), output = primary?.output;
33
+ if (!data || Object.keys(data).some(key => key !== "text" && key !== "shown_bytes") || !range ||
34
+ Object.keys(range).some(key => key !== "start" && key !== "end") || !output || typeof data.text !== "string" ||
35
+ range.start !== 0 || !Number.isSafeInteger(range.end) || Number(range.end) < 0 ||
36
+ Number(range.end) > Math.min(output.bytes_total, RUN_COMPLETION_MODEL_MAX_BYTES) ||
37
+ Buffer.byteLength(data.text) !== range.end || Buffer.from(data.text).toString("utf8") !== data.text ||
38
+ [...data.text].length > output.chars_total ||
39
+ (range.end === output.bytes_total && (createHash("sha256").update(data.text).digest("hex") !== output.source.sha256 ||
40
+ [...data.text].length !== output.chars_total)))
41
+ throw new Error("Completion source text is invalid.");
42
+ const end = Math.min(Number(range.end), output.shown_bytes.end), start = output.shown_bytes.start;
43
+ if (end > start && !Buffer.from(data.text).subarray(start, end).equals(Buffer.from(output.preview).subarray(0, end - start))) {
44
+ throw new Error("Completion source text does not match its recorded preview.");
45
+ }
46
+ return Object.freeze({ text: data.text, shown_bytes: Object.freeze({ start: 0, end: Number(range.end) }) });
47
+ }
48
+ function primaryData(value) {
49
+ if (!value || typeof value !== "object" || Array.isArray(value))
50
+ return undefined;
51
+ const descriptors = Object.getOwnPropertyDescriptors(value);
52
+ return Object.values(descriptors).every(field => Object.hasOwn(field, "value"))
53
+ ? Object.fromEntries(Object.entries(descriptors).map(([key, field]) => [key, field.value])) : undefined;
54
+ }
55
+ /** Curated JSON-data schema only; neither decoding nor a protocol marker admits a body, producer or work. */
56
+ export function decodeRunPrimaryTextBinding(stateDir, generation, value) {
57
+ const input = primaryData(value);
58
+ if (input?.output === null && typeof input.output_unavailable === "string" && /^[a-z_]{1,80}$/.exec(input.output_unavailable)?.[0] === input.output_unavailable) {
59
+ return Object.freeze({ output: null, output_unavailable: input.output_unavailable });
60
+ }
61
+ const output = primaryData(input?.output);
62
+ if (!output || typeof output !== "object")
63
+ throw new Error("Run primary text binding is invalid.");
64
+ const source = primaryData(output.source);
65
+ const range = primaryData(output.shown_bytes);
66
+ const { preview, bytes_total: bytes, chars_total: total, chars_shown: shown, chars_omitted: omitted } = output;
67
+ if ((output.text_basis !== undefined && output.text_basis !== "actor_response") ||
68
+ (output.text_basis === "actor_response" ? typeof output.upstream_truncated !== "boolean" : output.upstream_truncated !== undefined) ||
69
+ !source || typeof source.path !== "string" || !isAbsolute(source.path) || resolve(source.path) !== source.path ||
70
+ dirname(source.path) !== join(stateDir, "evidence") || /^primary-[a-f0-9]{64}\.txt$/.exec(basename(source.path))?.[0] !== basename(source.path) || source.run_instance_id !== generation ||
71
+ typeof source.sha256 !== "string" || source.sha256.length !== 64 || !/^[a-f0-9]{64}$/.test(source.sha256) || !range ||
72
+ ![bytes, total, shown, omitted, range.start, range.end].every(number => typeof number === "number" && Number.isSafeInteger(number) && number >= 0) ||
73
+ Number(range.start) > Number(range.end) || Number(range.end) > Number(bytes) || typeof preview !== "string" || Buffer.byteLength(preview) !== Number(range.end) - Number(range.start) ||
74
+ Buffer.from(preview).toString("utf8") !== preview || [...preview].length !== shown || Number(shown) + Number(omitted) !== total || Number(total) > Number(bytes) || typeof output.redacted !== "boolean" || output.truncated !== (Number(omitted) > 0)) {
75
+ throw new Error("Run primary text binding is invalid.");
76
+ }
77
+ const binding = { output: { ...(output.text_basis === "actor_response" ? { text_basis: "actor_response", upstream_truncated: output.upstream_truncated } : {}),
78
+ source: Object.freeze({ path: source.path, run_instance_id: generation, sha256: source.sha256 }),
79
+ bytes_total: Number(bytes), shown_bytes: Object.freeze({ start: Number(range.start), end: Number(range.end) }), chars_total: Number(total), chars_shown: Number(shown), chars_omitted: Number(omitted),
80
+ preview, truncated: output.truncated, redacted: output.redacted } };
81
+ if (Buffer.byteLength(JSON.stringify(binding)) > RUN_DELIVERY_MODEL_MAX_BYTES)
82
+ throw new Error("Run primary text binding is too large.");
83
+ return Object.freeze({ output: Object.freeze(binding.output) });
84
+ }
85
+ /** Inspect completion shape without invoking getters/custom thenables; this grants no source authority. */
86
+ function synchronousBindingData(value, label) {
87
+ for (let target = value && typeof value === "object" ? value : null; target; target = Object.getPrototypeOf(target)) {
88
+ const then = Object.getOwnPropertyDescriptor(target, "then");
89
+ if (then && (!Object.hasOwn(then, "value") || typeof then.value === "function"))
90
+ throw new Error(`${label} binding must complete synchronously.`);
91
+ }
92
+ const input = primaryData(value);
93
+ if (input && Object.hasOwn(input, "then"))
94
+ throw new Error(`${label} binding must complete synchronously.`);
95
+ return input;
96
+ }
97
+ /** Data schema only; copied actor fields/markers cannot publish or authorize inventory/body reads. */
98
+ export function decodeRunArtifactInventoryBinding(stateDir, generation, value) {
99
+ const input = synchronousBindingData(value, "Run artifact inventory");
100
+ if (input?.artifact_inventory === null && typeof input.artifact_inventory_unavailable === "string" &&
101
+ /^[a-z_]{1,80}$/u.exec(input.artifact_inventory_unavailable)?.[0] === input.artifact_inventory_unavailable) {
102
+ return Object.freeze({ artifact_inventory: null, artifact_inventory_unavailable: input.artifact_inventory_unavailable });
103
+ }
104
+ const inventory = primaryData(input?.artifact_inventory);
105
+ const source = primaryData(inventory?.source);
106
+ if (!inventory || !source || typeof source.path !== "string" || !isAbsolute(source.path) || resolve(source.path) !== source.path ||
107
+ dirname(source.path) !== join(stateDir, "evidence") || /^artifact-inventory-[a-f0-9]{64}\.json$/u.exec(basename(source.path))?.[0] !== basename(source.path) ||
108
+ source.run_instance_id !== generation || typeof source.sha256 !== "string" || source.sha256.length !== 64 || !/^[a-f0-9]{64}$/u.test(source.sha256) ||
109
+ typeof inventory.bytes_total !== "number" || !Number.isSafeInteger(inventory.bytes_total) || inventory.bytes_total <= 0 ||
110
+ typeof inventory.declarations_total !== "number" || !Number.isSafeInteger(inventory.declarations_total) || inventory.declarations_total <= 0 || inventory.declarations_total > inventory.bytes_total) {
111
+ throw new Error("Run artifact inventory binding is invalid.");
112
+ }
113
+ const binding = Object.freeze({ artifact_inventory: Object.freeze({ source: Object.freeze({ path: source.path, run_instance_id: generation, sha256: source.sha256 }),
114
+ bytes_total: inventory.bytes_total, declarations_total: inventory.declarations_total }) });
115
+ if (Buffer.byteLength(JSON.stringify(binding)) > RUN_DELIVERY_MODEL_MAX_BYTES)
116
+ throw new Error("Run artifact inventory binding is too large.");
117
+ return binding;
118
+ }
119
+ /** Curated diagnostic reference data only, never candidate/producer/publication/body permission. */
120
+ export function decodeRunResultDiagnosticsBinding(stateDir, generation, value) {
121
+ const input = synchronousBindingData(value, "Run result diagnostics");
122
+ if (input?.result_diagnostics === null && typeof input.result_diagnostics_unavailable === "string" &&
123
+ /^[a-z_]{1,80}$/u.exec(input.result_diagnostics_unavailable)?.[0] === input.result_diagnostics_unavailable) {
124
+ return Object.freeze({ result_diagnostics: null, result_diagnostics_unavailable: input.result_diagnostics_unavailable });
125
+ }
126
+ const reference = primaryData(input?.result_diagnostics);
127
+ const source = primaryData(reference?.source);
128
+ const list = Array.isArray(reference?.fields) ? Object.getOwnPropertyDescriptors(reference.fields) : undefined;
129
+ const fields = list && Object.values(list).every(field => Object.hasOwn(field, "value")) &&
130
+ Number.isSafeInteger(list.length?.value) && list.length.value > 0 && list.length.value <= RUN_RESULT_DIAGNOSTIC_FIELDS.length
131
+ ? Array.from({ length: list.length.value }, (_, index) => list[String(index)]?.value) : undefined;
132
+ if (!reference || !source || typeof source.path !== "string" || !isAbsolute(source.path) || resolve(source.path) !== source.path ||
133
+ dirname(source.path) !== join(stateDir, "evidence") || /^result-diagnostics-[a-f0-9]{64}\.json$/u.exec(basename(source.path))?.[0] !== basename(source.path) ||
134
+ source.run_instance_id !== generation || typeof source.sha256 !== "string" || source.sha256.length !== 64 || !/^[a-f0-9]{64}$/u.test(source.sha256) ||
135
+ typeof reference.bytes_total !== "number" || !Number.isSafeInteger(reference.bytes_total) || reference.bytes_total <= 0 || !fields ||
136
+ fields.some((field, index) => !RUN_RESULT_DIAGNOSTIC_FIELDS.includes(field) || fields.indexOf(field) !== index) ||
137
+ JSON.stringify(fields) !== JSON.stringify(RUN_RESULT_DIAGNOSTIC_FIELDS.filter(field => fields.includes(field))))
138
+ throw new Error("Run result diagnostics binding is invalid.");
139
+ const binding = Object.freeze({ result_diagnostics: Object.freeze({ source: Object.freeze({ path: source.path, run_instance_id: generation, sha256: source.sha256 }),
140
+ bytes_total: reference.bytes_total, fields: Object.freeze(fields) }) });
141
+ if (Buffer.byteLength(JSON.stringify(binding)) > RUN_DELIVERY_MODEL_MAX_BYTES)
142
+ throw new Error("Run result diagnostics binding is too large.");
143
+ return binding;
144
+ }
145
+ /** Frozen literal prefix metadata only; a valid excerpt/reference DTO does not authorize source publication. */
146
+ export function decodeRunResultDiagnosticExcerpt(reference, value) {
147
+ const input = primaryData(value);
148
+ const range = primaryData(input?.shown_bytes);
149
+ if (!input || !range || !reference.fields.includes(input.field) || typeof input.text !== "string" ||
150
+ Buffer.from(input.text, "utf8").toString("utf8") !== input.text || ![input.bytes_total, input.chars_total, input.chars_shown, input.chars_omitted, range.start, range.end]
151
+ .every(number => typeof number === "number" && Number.isSafeInteger(number) && number >= 0) ||
152
+ range.start !== 0 || Number(range.end) > Number(input.bytes_total) || Buffer.byteLength(input.text) !== range.end ||
153
+ Array.from(input.text).length !== input.chars_shown || Number(input.chars_shown) > RUN_RESULT_DIAGNOSTIC_EXCERPT_CHARS ||
154
+ Number(input.chars_shown) + Number(input.chars_omitted) !== input.chars_total || Number(input.chars_total) > Number(input.bytes_total) ||
155
+ input.truncated !== (Number(input.chars_omitted) > 0))
156
+ throw new Error("Run result diagnostic excerpt is invalid.");
157
+ const excerpt = Object.freeze({ field: input.field, text: input.text, bytes_total: Number(input.bytes_total),
158
+ shown_bytes: Object.freeze({ start: 0, end: Number(range.end) }), chars_total: Number(input.chars_total), chars_shown: Number(input.chars_shown),
159
+ chars_omitted: Number(input.chars_omitted), truncated: input.truncated });
160
+ if (Buffer.byteLength(JSON.stringify(excerpt)) > RUN_DELIVERY_MODEL_MAX_BYTES)
161
+ throw new Error("Run result diagnostic excerpt is too large.");
162
+ return excerpt;
163
+ }
164
+ export const RUN_OUTCOME_PROTOCOL = "run-outcome-v1";
165
+ export const RUN_STOP_CLAIM_FILE = "stop-claim.json";
166
+ const MAX_STOP_CLAIM_BYTES = 16_384;
167
+ function isCanonicalTimestamp(value) {
168
+ if (typeof value !== "string")
169
+ return false;
170
+ const time = Date.parse(value);
171
+ return Number.isSafeInteger(time) && new Date(time).toISOString() === value;
172
+ }
173
+ function decodeStopClaim(value) {
174
+ if (!value || typeof value !== "object" || Array.isArray(value))
175
+ return undefined;
176
+ const record = value;
177
+ if (record.version !== 1 ||
178
+ typeof record.claim_id !== "string" || !/^[0-9a-f-]{36}$/.test(record.claim_id) ||
179
+ typeof record.run !== "string" || !record.run ||
180
+ typeof record.run_instance_id !== "string" || !record.run_instance_id ||
181
+ (record.ownerId !== undefined && (typeof record.ownerId !== "string" || !record.ownerId)) ||
182
+ !Number.isSafeInteger(record.pid) || Number(record.pid) <= 0 ||
183
+ typeof record.process_identity_digest !== "string" || !/^[0-9a-f]{64}$/.test(record.process_identity_digest) ||
184
+ (record.reason !== "manual_kill" && record.reason !== "max_runtime") ||
185
+ !isCanonicalTimestamp(record.requested_at))
186
+ return undefined;
187
+ return {
188
+ version: 1,
189
+ claim_id: record.claim_id,
190
+ run: record.run,
191
+ run_instance_id: record.run_instance_id,
192
+ ...(typeof record.ownerId === "string" ? { ownerId: record.ownerId } : {}),
193
+ pid: Number(record.pid),
194
+ process_identity_digest: record.process_identity_digest,
195
+ reason: record.reason,
196
+ requested_at: record.requested_at,
197
+ };
198
+ }
199
+ export function readRunStopClaim(stateDir, meta) {
200
+ const path = join(stateDir, RUN_STOP_CLAIM_FILE);
201
+ try {
202
+ if (!lstatSync(path).isFile())
203
+ return { state: "invalid" };
204
+ }
205
+ catch (error) {
206
+ return { state: error.code === "ENOENT" ? "absent" : "invalid" };
207
+ }
208
+ const read = readJsonFileResilient(path, undefined, { maxBytes: MAX_STOP_CLAIM_BYTES });
209
+ if (read.diagnostics.length)
210
+ return { state: "invalid" };
211
+ if (read.value && typeof read.value === "object" && !Array.isArray(read.value)) {
212
+ const generation = read.value.run_instance_id;
213
+ if (typeof generation === "string" && generation && typeof meta.run_instance_id === "string" &&
214
+ generation !== meta.run_instance_id)
215
+ return { state: "stale" };
216
+ }
217
+ const claim = decodeStopClaim(read.value);
218
+ if (!claim || meta.outcome_protocol !== RUN_OUTCOME_PROTOCOL ||
219
+ claim.run !== meta.run || claim.run_instance_id !== meta.run_instance_id ||
220
+ claim.ownerId !== meta.ownerId || claim.pid !== meta.pid ||
221
+ claim.process_identity_digest !== runProcessIdentityDigest(meta.process_identity)) {
222
+ return { state: "invalid" };
223
+ }
224
+ return { state: "pending", claim: Object.freeze(claim) };
225
+ }
226
+ /** Only the control owner may call this after admission under the canonical lifecycle lock. */
227
+ export function writeRunStopClaimUnderLock(stateDir, meta, reason) {
228
+ if (readRunStopClaim(stateDir, meta).state !== "absent") {
229
+ throw new Error("Run stop claim cannot replace existing evidence.");
230
+ }
231
+ const claim = {
232
+ version: 1,
233
+ claim_id: randomUUID(),
234
+ run: meta.run,
235
+ run_instance_id: meta.run_instance_id,
236
+ ...(meta.ownerId !== undefined ? { ownerId: meta.ownerId } : {}),
237
+ pid: meta.pid,
238
+ process_identity_digest: runProcessIdentityDigest(meta.process_identity),
239
+ reason,
240
+ requested_at: new Date().toISOString(),
241
+ };
242
+ const decoded = decodeStopClaim(claim);
243
+ if (!decoded || meta.outcome_protocol !== RUN_OUTCOME_PROTOCOL ||
244
+ Buffer.byteLength(JSON.stringify(claim, null, 2), "utf8") > MAX_STOP_CLAIM_BYTES) {
245
+ throw new Error("Run stop claim identity is unavailable or invalid.");
246
+ }
247
+ writeJsonAtomic(join(stateDir, RUN_STOP_CLAIM_FILE), decoded);
248
+ return Object.freeze(decoded);
249
+ }
250
+ /** Capture markers never imply terminal acceptance, even when their claim is unavailable. */
251
+ export function isRunStopResultCapture(result) {
252
+ return result?.terminal_acceptance === "after_stop_claim" || result?.stop_claim_id !== undefined;
253
+ }
254
+ function classifyNaturalOutcome(result, meta) {
255
+ if (typeof meta.run_instance_id !== "string" || !meta.run_instance_id || !Object.hasOwn(result, "code") ||
256
+ result.run_instance_id !== meta.run_instance_id || !Number.isSafeInteger(result.code) ||
257
+ !isCanonicalTimestamp(result.completedAt))
258
+ return { state: "invalid" };
259
+ if (result.terminal_acceptance === "after_stop_claim" && typeof result.stop_claim_id === "string") {
260
+ return { state: "captured" };
261
+ }
262
+ if (result.terminal_acceptance !== "natural" || Object.hasOwn(result, "stop_claim_id")) {
263
+ return { state: "invalid" };
264
+ }
265
+ return { state: "accepted", status: result.code === 0 ? "done" : "failed" };
266
+ }
267
+ function readResultJson(path) {
268
+ const read = readJsonFileResilient(path, undefined);
269
+ return read.diagnostics.length ? undefined : read.value;
270
+ }
271
+ /** Read one regular-file result snapshot for both precedence and rendering; data never grants work/stop authority. */
272
+ export function readRunNaturalOutcomeSnapshot(stateDir, meta, readResult = readResultJson) {
273
+ const path = join(stateDir, "result.json");
274
+ try {
275
+ if (!lstatSync(path).isFile())
276
+ return Object.freeze({ result: undefined, outcome: { state: "invalid" } });
277
+ }
278
+ catch (error) {
279
+ return Object.freeze({ result: undefined,
280
+ outcome: { state: error.code === "ENOENT" ? "absent" : "invalid" } });
281
+ }
282
+ const value = readResult(path);
283
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
284
+ return Object.freeze({ result: undefined, outcome: { state: "invalid" } });
285
+ }
286
+ const result = value;
287
+ return Object.freeze({ result, outcome: classifyNaturalOutcome(result, meta) });
288
+ }
289
+ /** Result bodies remain in their existing canonical file; this is admission, not a second store. */
290
+ export function readRunNaturalOutcome(stateDir, meta) {
291
+ return readRunNaturalOutcomeSnapshot(stateDir, meta).outcome;
292
+ }