@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
@@ -4,8 +4,9 @@
4
4
  * Owns portable command-template parsing, expansion, risk checks, retries, timeouts, and direct execution.
5
5
  */
6
6
 
7
- import { spawn, spawnSync } from "node:child_process";
8
- import { accessSync, appendFileSync, constants, mkdirSync, mkdtempSync, statSync, writeFileSync } from "node:fs";
7
+ import { spawn, spawnSync, type ChildProcess } from "node:child_process";
8
+ import { createHash } from "node:crypto";
9
+ import { accessSync, appendFileSync, constants, lstatSync, mkdirSync, mkdtempSync, statSync, writeFileSync } from "node:fs";
9
10
  import { homedir, tmpdir } from "node:os";
10
11
  import { basename, delimiter, extname, isAbsolute, join, resolve as resolvePath } from "node:path";
11
12
 
@@ -56,6 +57,12 @@ export interface CommandTemplateInvocation {
56
57
  }
57
58
 
58
59
  export interface CommandTemplateExecOptions {
60
+ /** Kernel-only synchronous admission around each native spawn, including retries. */
61
+ admitSpawn?: (start: () => ChildProcess) => ChildProcess;
62
+ /** Kernel-only fresh handle after capture/exit management, inside synchronous spawn admission. Not birth proof. */
63
+ onAttemptManaged?: (context: CommandTemplateManagedAttempt) => void;
64
+ /** Kernel observation of settled attempts only; no receipt exists for a denied spawn. */
65
+ onAttemptComplete?: (receipt: CommandTemplateAttemptReceipt) => void;
59
66
  cwd?: string;
60
67
  timeout?: number;
61
68
  signal?: AbortSignal;
@@ -77,6 +84,68 @@ export interface CommandTemplateExecResult {
77
84
  stderrFile?: string;
78
85
  stdoutTruncated?: boolean;
79
86
  stderrTruncated?: boolean;
87
+ stdoutCaptureIncomplete?: true;
88
+ stderrCaptureIncomplete?: true;
89
+ stdoutFileBytes?: number;
90
+ stderrFileBytes?: number;
91
+ }
92
+
93
+ export interface CommandTemplateManagedAttempt {
94
+ readonly attempt: number;
95
+ readonly process: ChildProcess;
96
+ }
97
+
98
+ export interface CommandTemplateSpawnAdmission { readonly attempt: number; }
99
+
100
+ let pendingSpawnAdmission: CommandTemplateSpawnAdmission | undefined;
101
+ const freshManagedAttempts = new WeakMap<CommandTemplateManagedAttempt, { process: ChildProcess; pid: number | undefined; admission: CommandTemplateSpawnAdmission }>();
102
+
103
+ /** Available only before this synchronous admission invokes its factory; never retroactively adopt a born process. */
104
+ export function readPendingCommandSpawnAdmission(): CommandTemplateSpawnAdmission | undefined {
105
+ return pendingSpawnAdmission;
106
+ }
107
+
108
+ /** Kernel-only launch observation capability; copies and references retained past the callback are not authority. */
109
+ export function requireFreshManagedCommandAttempt(context: CommandTemplateManagedAttempt, admission?: CommandTemplateSpawnAdmission): CommandTemplateManagedAttempt {
110
+ const actual = freshManagedAttempts.get(context);
111
+ if (!actual || (admission !== undefined && actual.admission !== admission) || context.process !== actual.process || actual.process.pid !== actual.pid) {
112
+ throw new Error("Native process observation requires a fresh managed attempt from this runtime.");
113
+ }
114
+ return context;
115
+ }
116
+
117
+ export interface CommandTemplateAttemptReceipt {
118
+ readonly attempt: number;
119
+ /** Kernel-only digest of observed stdout bytes after complete capture persistence; not exposure/native authority. */
120
+ readonly stdoutSha256?: string;
121
+ readonly result: Readonly<CommandTemplateExecResult>;
122
+ readonly nativeExitCode?: number | null;
123
+ readonly nativeSignal?: NodeJS.Signals | null;
124
+ }
125
+
126
+ export interface CommandTemplateNativeClose {
127
+ readonly pid: number;
128
+ readonly nativeExitCode: number | null;
129
+ readonly nativeSignal: NodeJS.Signals | null;
130
+ }
131
+
132
+ const nativeCloseReceipts = new WeakMap<CommandTemplateAttemptReceipt, {
133
+ admission: CommandTemplateSpawnAdmission;
134
+ process: ChildProcess;
135
+ close: CommandTemplateNativeClose;
136
+ }>();
137
+
138
+ /** Exact retained process close during its synchronous receipt callback, never a serialized terminal claim. */
139
+ export function requireNativeCommandAttemptClose(
140
+ receipt: CommandTemplateAttemptReceipt,
141
+ admission: CommandTemplateSpawnAdmission,
142
+ child: ChildProcess,
143
+ ): CommandTemplateNativeClose {
144
+ const actual = nativeCloseReceipts.get(receipt);
145
+ if (!actual || actual.admission !== admission || actual.process !== child || child.pid !== actual.close.pid) {
146
+ throw new Error("Native settlement requires its exact runtime-local process-close receipt.");
147
+ }
148
+ return actual.close;
80
149
  }
81
150
 
82
151
  export type CommandTemplateRiskLabel =
@@ -901,7 +970,7 @@ export async function execCommandTemplate(
901
970
  ),
902
971
  }
903
972
  : options;
904
- const result = await execCommandTemplateOnce(command, args, attemptOptions);
973
+ const result = await execCommandTemplateOnce(command, args, attemptOptions, attempt);
905
974
  if (result.code === 0) return result;
906
975
  lastResult = result;
907
976
  }
@@ -914,6 +983,9 @@ interface BoundedCommandCapture {
914
983
  bytes: number;
915
984
  content: string;
916
985
  file?: string;
986
+ fileBytes?: number;
987
+ incomplete?: boolean;
988
+ sha256?: string;
917
989
  truncated: boolean;
918
990
  };
919
991
  }
@@ -930,39 +1002,54 @@ function createBoundedCommandCapture(
930
1002
  limit: number,
931
1003
  getCaptureDir: () => string,
932
1004
  persistCompleteStream: boolean,
1005
+ onFailure: (error: unknown) => void,
933
1006
  ): BoundedCommandCapture {
934
1007
  let bytes = 0;
1008
+ const digest = stream === "stdout" && persistCompleteStream ? createHash("sha256") : undefined;
935
1009
  let content: Buffer = Buffer.alloc(0);
936
1010
  let file = persistCompleteStream
937
1011
  ? join(getCaptureDir(), `${stream}.log`)
938
1012
  : undefined;
939
1013
  if (file) writeFileSync(file, Buffer.alloc(0));
940
1014
  let truncated = false;
1015
+ let incomplete = false;
941
1016
  return {
942
1017
  append(value) {
943
1018
  const chunk = Buffer.isBuffer(value) ? value : Buffer.from(value);
944
1019
  bytes += chunk.length;
1020
+ digest?.update(chunk);
945
1021
  if (bytes > limit) truncated = true;
946
- if (!file && bytes <= limit) {
947
- content = Buffer.concat([content, chunk]);
948
- return;
949
- }
950
- if (!file) {
951
- file = join(getCaptureDir(), `${stream}.log`);
952
- writeFileSync(file, content);
953
- }
954
- appendFileSync(file, chunk);
1022
+ const previous = content;
955
1023
  content = trimCaptureTail(Buffer.concat([content, chunk]), limit);
1024
+ if (!file && bytes <= limit) return;
1025
+ if (incomplete) return;
1026
+ try {
1027
+ if (!file) {
1028
+ file = join(getCaptureDir(), `${stream}.log`);
1029
+ writeFileSync(file, previous);
1030
+ }
1031
+ appendFileSync(file, chunk);
1032
+ } catch (error) {
1033
+ incomplete = true;
1034
+ onFailure(error);
1035
+ }
956
1036
  },
957
1037
  result() {
958
- if (!file && persistCompleteStream) {
959
- file = join(getCaptureDir(), `${stream}.log`);
960
- writeFileSync(file, content);
1038
+ let retainedFile = file;
1039
+ let fileBytes: number | undefined;
1040
+ if (incomplete && file) {
1041
+ try {
1042
+ const stat = lstatSync(file);
1043
+ if (stat.isFile()) fileBytes = stat.size;
1044
+ else retainedFile = undefined;
1045
+ } catch { retainedFile = undefined; }
961
1046
  }
962
1047
  return {
963
1048
  bytes,
964
1049
  content: content.toString("utf8"),
965
- ...(file ? { file } : {}),
1050
+ ...(retainedFile ? { file: retainedFile } : {}),
1051
+ ...(digest && !incomplete && retainedFile ? { sha256: digest.digest("hex") } : {}),
1052
+ ...(incomplete ? { incomplete: true, ...(fileBytes === undefined ? {} : { fileBytes }) } : {}),
966
1053
  truncated,
967
1054
  };
968
1055
  },
@@ -972,134 +1059,196 @@ function createBoundedCommandCapture(
972
1059
  function execCommandTemplateOnce(
973
1060
  command: string,
974
1061
  args: string[],
975
- options: CommandTemplateExecOptions = {},
1062
+ options: CommandTemplateExecOptions,
1063
+ attempt: number,
976
1064
  ): Promise<CommandTemplateExecResult> {
977
- return new Promise((resolve) => {
978
- const proc = spawn(command, args, {
979
- cwd: options.cwd,
980
- shell: false,
981
- stdio: [options.stdin === undefined ? "ignore" : "pipe", "pipe", "pipe"],
982
- });
983
- const captureLimit = Math.max(
984
- 1,
985
- options.captureLimitBytes ?? DEFAULT_COMMAND_CAPTURE_LIMIT_BYTES,
986
- );
987
- let captureDir: string | undefined;
988
- const getCaptureDir = (): string => {
989
- if (captureDir) return captureDir;
990
- captureDir = options.captureDir
991
- ? resolvePath(options.captureDir)
992
- : mkdtempSync(join(tmpdir(), "pi-actors-command-"));
993
- mkdirSync(captureDir, { recursive: true });
994
- return captureDir;
995
- };
996
- const persistCompleteStreams = options.captureDir !== undefined;
997
- const stdoutCapture = createBoundedCommandCapture(
998
- "stdout",
999
- captureLimit,
1000
- getCaptureDir,
1001
- persistCompleteStreams,
1002
- );
1003
- const stderrCapture = createBoundedCommandCapture(
1004
- "stderr",
1005
- captureLimit,
1006
- getCaptureDir,
1007
- persistCompleteStreams,
1008
- );
1009
- let killed = false;
1010
- let settled = false;
1011
- let timeoutId: NodeJS.Timeout | undefined;
1012
- let killTimeoutId: NodeJS.Timeout | undefined;
1013
- const signalProcessTree = (signal: NodeJS.Signals): void => {
1014
- if (proc.pid === undefined) return;
1015
- if (process.platform === "win32") {
1016
- spawnSync("taskkill", [
1017
- "/PID",
1018
- String(proc.pid),
1019
- "/T",
1020
- ...(signal === "SIGKILL" ? ["/F"] : []),
1021
- ]);
1022
- return;
1023
- }
1024
- const snapshot = spawnSync("ps", ["-eo", "pid=,ppid="], { encoding: "utf8" });
1025
- const children = new Map<number, number[]>();
1026
- for (const line of snapshot.stdout?.split(/\r?\n/u) ?? []) {
1027
- const [pidText, parentText] = line.trim().split(/\s+/u);
1028
- const pid = Number(pidText);
1029
- const parent = Number(parentText);
1030
- if (!Number.isSafeInteger(pid) || !Number.isSafeInteger(parent)) continue;
1031
- const siblings = children.get(parent) ?? [];
1032
- siblings.push(pid);
1033
- children.set(parent, siblings);
1034
- }
1035
- const descendants: number[] = [];
1036
- const collect = (parent: number): void => {
1037
- for (const child of children.get(parent) ?? []) {
1038
- collect(child);
1039
- descendants.push(child);
1065
+ return new Promise((resolve, reject) => {
1066
+ let failure: { error: unknown } | undefined;
1067
+ let managed: ChildProcess | undefined;
1068
+ let invoked = false;
1069
+ let admissionOpen = true;
1070
+ const spawnAdmission = Object.freeze({ attempt });
1071
+ const rememberFailure = (error: unknown): void => { failure ??= { error }; };
1072
+ const start = (): ChildProcess => {
1073
+ if (!admissionOpen) throw new Error("Native spawn admission window is closed.");
1074
+ if (invoked) throw new Error("Native spawn factory may be invoked only once per attempt.");
1075
+ invoked = true;
1076
+ pendingSpawnAdmission = undefined;
1077
+ const captureLimit = Math.max(
1078
+ 1,
1079
+ options.captureLimitBytes ?? DEFAULT_COMMAND_CAPTURE_LIMIT_BYTES,
1080
+ );
1081
+ let captureDir: string | undefined;
1082
+ const getCaptureDir = (): string => {
1083
+ if (captureDir) return captureDir;
1084
+ captureDir = options.captureDir
1085
+ ? resolvePath(options.captureDir)
1086
+ : mkdtempSync(join(tmpdir(), "pi-actors-command-"));
1087
+ mkdirSync(captureDir, { recursive: true });
1088
+ return captureDir;
1089
+ };
1090
+ const persistCompleteStreams = options.captureDir !== undefined;
1091
+ const stdoutCapture = createBoundedCommandCapture(
1092
+ "stdout",
1093
+ captureLimit,
1094
+ getCaptureDir,
1095
+ persistCompleteStreams,
1096
+ rememberFailure,
1097
+ );
1098
+ const stderrCapture = createBoundedCommandCapture(
1099
+ "stderr",
1100
+ captureLimit,
1101
+ getCaptureDir,
1102
+ persistCompleteStreams,
1103
+ rememberFailure,
1104
+ );
1105
+ let killed = false;
1106
+ let settled = false;
1107
+ let timeoutId: NodeJS.Timeout | undefined;
1108
+ let killTimeoutId: NodeJS.Timeout | undefined;
1109
+ const signalProcessTree = (signal: NodeJS.Signals): void => {
1110
+ if (proc.pid === undefined) return;
1111
+ if (process.platform === "win32") {
1112
+ spawnSync("taskkill", [
1113
+ "/PID",
1114
+ String(proc.pid),
1115
+ "/T",
1116
+ ...(signal === "SIGKILL" ? ["/F"] : []),
1117
+ ]);
1118
+ return;
1119
+ }
1120
+ const snapshot = spawnSync("ps", ["-eo", "pid=,ppid="], { encoding: "utf8" });
1121
+ const children = new Map<number, number[]>();
1122
+ for (const line of snapshot.stdout?.split(/\r?\n/u) ?? []) {
1123
+ const [pidText, parentText] = line.trim().split(/\s+/u);
1124
+ const pid = Number(pidText);
1125
+ const parent = Number(parentText);
1126
+ if (!Number.isSafeInteger(pid) || !Number.isSafeInteger(parent)) continue;
1127
+ const siblings = children.get(parent) ?? [];
1128
+ siblings.push(pid);
1129
+ children.set(parent, siblings);
1130
+ }
1131
+ const descendants: number[] = [];
1132
+ const collect = (parent: number): void => {
1133
+ for (const child of children.get(parent) ?? []) {
1134
+ collect(child);
1135
+ descendants.push(child);
1136
+ }
1137
+ };
1138
+ collect(proc.pid);
1139
+ for (const pid of [...descendants, proc.pid]) {
1140
+ try {
1141
+ process.kill(pid, signal);
1142
+ } catch (error) {
1143
+ if ((error as NodeJS.ErrnoException).code !== "ESRCH") throw error;
1144
+ }
1040
1145
  }
1041
1146
  };
1042
- collect(proc.pid);
1043
- for (const pid of [...descendants, proc.pid]) {
1147
+ const killProcess = (): void => {
1148
+ if (killed) return;
1149
+ killed = true;
1150
+ signalProcessTree("SIGTERM");
1151
+ killTimeoutId = setTimeout(() => {
1152
+ if (!settled) signalProcessTree("SIGKILL");
1153
+ }, options.killGrace ?? 5000);
1154
+ };
1155
+ const settle = (code: number, nativeExitCode?: number | null, nativeSignal?: NodeJS.Signals | null): void => {
1156
+ if (settled) return;
1157
+ settled = true;
1158
+ if (timeoutId) clearTimeout(timeoutId);
1159
+ if (killTimeoutId) clearTimeout(killTimeoutId);
1160
+ if (options.signal)
1161
+ options.signal.removeEventListener("abort", killProcess);
1162
+ const stdout = stdoutCapture.result();
1163
+ const stderr = stderrCapture.result();
1164
+ const result = {
1165
+ stdout: stdout.content,
1166
+ stderr: stderr.content,
1167
+ code,
1168
+ killed,
1169
+ stdoutBytes: stdout.bytes,
1170
+ stderrBytes: stderr.bytes,
1171
+ ...(stdout.file ? { stdoutFile: stdout.file } : {}),
1172
+ ...(stderr.file ? { stderrFile: stderr.file } : {}),
1173
+ ...(stdout.truncated ? { stdoutTruncated: true } : {}),
1174
+ ...(stderr.truncated ? { stderrTruncated: true } : {}),
1175
+ ...(stdout.incomplete ? { stdoutCaptureIncomplete: true as const, ...(stdout.fileBytes === undefined ? {} : { stdoutFileBytes: stdout.fileBytes }) } : {}),
1176
+ ...(stderr.incomplete ? { stderrCaptureIncomplete: true as const, ...(stderr.fileBytes === undefined ? {} : { stderrFileBytes: stderr.fileBytes }) } : {}),
1177
+ };
1044
1178
  try {
1045
- process.kill(pid, signal);
1046
- } catch (error) {
1047
- if ((error as NodeJS.ErrnoException).code !== "ESRCH") throw error;
1048
- }
1049
- }
1050
- };
1051
- const killProcess = (): void => {
1052
- if (killed) return;
1053
- killed = true;
1054
- signalProcessTree("SIGTERM");
1055
- killTimeoutId = setTimeout(() => {
1056
- if (!settled) signalProcessTree("SIGKILL");
1057
- }, options.killGrace ?? 5000);
1058
- };
1059
- const settle = (code: number): void => {
1060
- if (settled) return;
1061
- settled = true;
1062
- if (timeoutId) clearTimeout(timeoutId);
1063
- if (killTimeoutId) clearTimeout(killTimeoutId);
1064
- if (options.signal)
1065
- options.signal.removeEventListener("abort", killProcess);
1066
- const stdout = stdoutCapture.result();
1067
- const stderr = stderrCapture.result();
1068
- resolve({
1069
- stdout: stdout.content,
1070
- stderr: stderr.content,
1071
- code,
1072
- killed,
1073
- stdoutBytes: stdout.bytes,
1074
- stderrBytes: stderr.bytes,
1075
- ...(stdout.file ? { stdoutFile: stdout.file } : {}),
1076
- ...(stderr.file ? { stderrFile: stderr.file } : {}),
1077
- ...(stdout.truncated ? { stdoutTruncated: true } : {}),
1078
- ...(stderr.truncated ? { stderrTruncated: true } : {}),
1179
+ if (options.onAttemptComplete) {
1180
+ const receipt = Object.freeze({
1181
+ attempt, result: Object.freeze({ ...result }),
1182
+ ...(stdout.sha256 ? { stdoutSha256: stdout.sha256 } : {}),
1183
+ ...(nativeExitCode !== undefined ? { nativeExitCode } : {}),
1184
+ ...(nativeSignal !== undefined ? { nativeSignal } : {}),
1185
+ });
1186
+ const exitObserved = (Number.isSafeInteger(nativeExitCode) && nativeSignal === null) ||
1187
+ (nativeExitCode === null && typeof nativeSignal === "string" && /^SIG[A-Z0-9]+$/.exec(nativeSignal)?.[0] === nativeSignal);
1188
+ if (exitObserved && Number.isSafeInteger(proc.pid) && Number(proc.pid) > 0 &&
1189
+ proc.exitCode === nativeExitCode && proc.signalCode === nativeSignal) {
1190
+ nativeCloseReceipts.set(receipt, {
1191
+ admission: spawnAdmission, process: proc,
1192
+ close: Object.freeze({ pid: proc.pid!, nativeExitCode: nativeExitCode!, nativeSignal: nativeSignal! }),
1193
+ });
1194
+ }
1195
+ try { options.onAttemptComplete(receipt); }
1196
+ finally { nativeCloseReceipts.delete(receipt); }
1197
+ }
1198
+ } catch (error) { rememberFailure(error); }
1199
+ if (failure) reject(failure.error);
1200
+ else resolve(result);
1201
+ };
1202
+ const proc = spawn(command, args, {
1203
+ cwd: options.cwd,
1204
+ shell: false,
1205
+ stdio: [options.stdin === undefined ? "ignore" : "pipe", "pipe", "pipe"],
1206
+ });
1207
+ proc.stdout?.on("data", (data: Buffer) => {
1208
+ stdoutCapture.append(data);
1209
+ });
1210
+ proc.stderr?.on("data", (data: Buffer) => {
1211
+ stderrCapture.append(data);
1212
+ });
1213
+ proc.stdin?.on("error", () => {});
1214
+ proc.on("error", (error) => {
1215
+ const liveHandle = Number.isSafeInteger(proc.pid) && Number(proc.pid) > 0;
1216
+ if (liveHandle) rememberFailure(error);
1217
+ stderrCapture.append(error instanceof Error ? error.message : String(error));
1218
+ if (!liveHandle) settle(1);
1079
1219
  });
1220
+ proc.on("close", (code, signal) => {
1221
+ settle(code ?? 1, code, signal);
1222
+ });
1223
+ managed = proc;
1224
+ try {
1225
+ if (options.signal) {
1226
+ if (options.signal.aborted) killProcess();
1227
+ else
1228
+ options.signal.addEventListener("abort", killProcess, { once: true });
1229
+ }
1230
+ if (options.timeout !== undefined && options.timeout > 0)
1231
+ timeoutId = setTimeout(killProcess, options.timeout);
1232
+ if (options.stdin !== undefined) proc.stdin?.end(options.stdin);
1233
+ if (options.onAttemptManaged) {
1234
+ const context = Object.freeze({ attempt, process: proc });
1235
+ freshManagedAttempts.set(context, { process: proc, pid: proc.pid, admission: spawnAdmission });
1236
+ try { options.onAttemptManaged(context); }
1237
+ finally { freshManagedAttempts.delete(context); }
1238
+ }
1239
+ } catch (error) { rememberFailure(error); }
1240
+ return proc;
1080
1241
  };
1081
- if (options.signal) {
1082
- if (options.signal.aborted) killProcess();
1083
- else
1084
- options.signal.addEventListener("abort", killProcess, { once: true });
1085
- }
1086
- if (options.timeout !== undefined && options.timeout > 0)
1087
- timeoutId = setTimeout(killProcess, options.timeout);
1088
- proc.stdout?.on("data", (data: Buffer) => {
1089
- stdoutCapture.append(data);
1090
- });
1091
- proc.stderr?.on("data", (data: Buffer) => {
1092
- stderrCapture.append(data);
1093
- });
1094
- proc.stdin?.on("error", () => {});
1095
- if (options.stdin !== undefined) proc.stdin?.end(options.stdin);
1096
- proc.on("error", (error) => {
1097
- stderrCapture.append(error instanceof Error ? error.message : String(error));
1098
- settle(1);
1099
- });
1100
- proc.on("close", (code) => {
1101
- settle(code ?? (killed ? 1 : 0));
1102
- });
1242
+ const parentAdmission = pendingSpawnAdmission;
1243
+ try {
1244
+ pendingSpawnAdmission = spawnAdmission;
1245
+ const proc = options.admitSpawn ? options.admitSpawn(start) : start();
1246
+ if (!managed) throw new Error("Native spawn admission must invoke its managed factory.");
1247
+ if (proc !== managed) throw new Error("Native spawn admission must return its managed process.");
1248
+ } catch (error) {
1249
+ if (managed) rememberFailure(error);
1250
+ else reject(error);
1251
+ } finally { admissionOpen = false; pendingSpawnAdmission = parentAdmission; }
1103
1252
  });
1104
1253
  }
1105
1254
 
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Execution-file layout and metadata observation beneath a caller-admitted Run state root.
3
+ * Owns: capture/session/canonical-runner stream layout, metadata and bounded strict text inputs through a checked descriptor.
4
+ * Excludes: Run/generation admission, unrestricted body exposure, discovery, privacy projection, historical-content or native authority.
5
+ */
6
+ import { closeSync, constants, fstatSync, lstatSync, openSync, readSync, realpathSync, type BigIntStats } from "node:fs";
7
+ import { isAbsolute, join, resolve, win32 } from "node:path";
8
+ import { SESSION_EVIDENCE_MAX_BYTES } from "./limits.ts";
9
+
10
+ export type ExecutionFileReferenceReading =
11
+ | { readonly availability: "available"; readonly path: string; readonly local_path: string;
12
+ readonly bytes_total: number; readonly mutable: true; readonly unchanged: () => boolean }
13
+ | { readonly availability: "unavailable"; readonly reason: "invalid_reference" | "reference_missing" |
14
+ "reference_unavailable" | "reference_changed" | "reference_size_unrepresentable" };
15
+ export const RUN_STREAM_SOURCE_MAX_BYTES = 4 * 1024 * 1024;
16
+ export type ExecutionTextReading =
17
+ | { readonly availability: "available"; readonly reference: Extract<ExecutionFileReferenceReading, { availability: "available" }>; readonly text: string }
18
+ | { readonly availability: "unavailable"; readonly reason: Extract<ExecutionFileReferenceReading, { availability: "unavailable" }>["reason"] |
19
+ "reference_too_large" | "reference_invalid_text" };
20
+ type Unavailable = Extract<ExecutionFileReferenceReading, { availability: "unavailable" }>;
21
+ function unavailable(reason: Unavailable["reason"]): Readonly<Unavailable> { return Object.freeze({ availability: "unavailable", reason }); }
22
+ function sameObject(left: BigIntStats, right: BigIntStats): boolean { return left.dev === right.dev && left.ino === right.ino; }
23
+ function sameFile(left: BigIntStats, right: BigIntStats): boolean {
24
+ return right.isFile() && sameObject(left, right) && left.size === right.size && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
25
+ }
26
+ function referencePath(request: unknown): string | undefined {
27
+ if (!request || typeof request !== "object" || Array.isArray(request)) return undefined;
28
+ const kind = Object.getOwnPropertyDescriptor(request, "kind")?.value;
29
+ const path = Object.getOwnPropertyDescriptor(request, "path")?.value;
30
+ if ((kind !== "session" && kind !== "capture" && kind !== "runner_stream") || typeof path !== "string" || !path || isAbsolute(path) || win32.isAbsolute(path) ||
31
+ /[\\\u0000-\u001f\u007f]/u.test(path) || (process.platform === "win32" && path.includes(":"))) return undefined;
32
+ const parts = path.split("/");
33
+ if (parts.some(part => !part || part === "." || part === "..")) return undefined;
34
+ if (kind === "runner_stream") return path === "stdout.log" || path === "stderr.log" ? path : undefined;
35
+ if (kind === "session") return parts[0] === "sessions" && parts.length >= 2 && parts.at(-1)!.endsWith(".jsonl") ? path : undefined;
36
+ const capture = /^captures\/command-([0-9]{3,})\/attempt-([0-9]{3,})\/(stdout|stderr)\.log$/u.exec(path);
37
+ return capture && capture.slice(1, 3).every(number => Number.isSafeInteger(Number(number)) && Number(number) > 0) ? path : undefined;
38
+ }
39
+
40
+ function inspectExecutionFile(stateDir: string, request: unknown): Readonly<ExecutionFileReferenceReading>;
41
+ function inspectExecutionFile(stateDir: string, request: unknown, maxTextBytes: number): Readonly<ExecutionTextReading>;
42
+ function inspectExecutionFile(stateDir: string, request: unknown, maxTextBytes?: number): Readonly<ExecutionFileReferenceReading | ExecutionTextReading> {
43
+ const relative = referencePath(request);
44
+ if (!relative) return unavailable("invalid_reference");
45
+ try {
46
+ const requestedRoot = resolve(stateDir);
47
+ const root = lstatSync(requestedRoot, { bigint: true });
48
+ if (!root.isDirectory() || root.isSymbolicLink()) return unavailable("reference_unavailable");
49
+ const canonicalRoot = realpathSync(requestedRoot);
50
+ const canonical = lstatSync(canonicalRoot, { bigint: true });
51
+ if (!canonical.isDirectory() || !sameObject(root, canonical)) return unavailable("reference_changed");
52
+ const directories = [{ path: requestedRoot, stamp: root }, { path: canonicalRoot, stamp: canonical }];
53
+ const parts = relative.split("/");
54
+ let directory = canonicalRoot;
55
+ for (const part of parts.slice(0, -1)) {
56
+ directory = join(directory, part);
57
+ const stamp = lstatSync(directory, { bigint: true });
58
+ if (!stamp.isDirectory() || stamp.isSymbolicLink()) return unavailable("reference_unavailable");
59
+ directories.push({ path: directory, stamp });
60
+ }
61
+ const path = join(canonicalRoot, ...parts);
62
+ const before = lstatSync(path, { bigint: true });
63
+ if (!before.isFile()) return unavailable("reference_unavailable");
64
+ if (before.size < 0n || before.size > BigInt(Number.MAX_SAFE_INTEGER)) return unavailable("reference_size_unrepresentable");
65
+ if (maxTextBytes !== undefined && before.size > BigInt(maxTextBytes)) return Object.freeze({ availability: "unavailable", reason: "reference_too_large" });
66
+ // Nonblocking/nofollow flags avoid waiting on a leaf replaced with a FIFO or following a leaf alias when supported.
67
+ const fd = openSync(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
68
+ try {
69
+ const opened = fstatSync(fd, { bigint: true });
70
+ if (!sameFile(before, opened)) return unavailable("reference_changed");
71
+ const unchanged = (): boolean => {
72
+ try {
73
+ return directories.every(directory => {
74
+ const current = lstatSync(directory.path, { bigint: true });
75
+ return current.isDirectory() && sameObject(directory.stamp, current);
76
+ }) && sameFile(opened, lstatSync(path, { bigint: true }));
77
+ } catch { return false; }
78
+ };
79
+ let text: string | undefined;
80
+ if (maxTextBytes !== undefined) {
81
+ const bytes = Buffer.alloc(Number(opened.size)); let offset = 0;
82
+ while (offset < bytes.length) {
83
+ const count = readSync(fd, bytes, offset, bytes.length - offset, offset);
84
+ if (!count) return unavailable("reference_changed");
85
+ offset += count;
86
+ }
87
+ try { text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: !relative.startsWith("sessions/") }).decode(bytes); }
88
+ catch { return Object.freeze({ availability: "unavailable", reason: "reference_invalid_text" }); }
89
+ }
90
+ if (!sameFile(opened, fstatSync(fd, { bigint: true })) || !unchanged()) return unavailable("reference_changed");
91
+ const reference = Object.freeze({ availability: "available" as const, path: relative, local_path: path, bytes_total: Number(opened.size), mutable: true as const, unchanged });
92
+ return text === undefined ? reference : Object.freeze({ availability: "available", reference, text });
93
+ } finally { closeSync(fd); }
94
+ } catch (error) {
95
+ return unavailable((error as NodeJS.ErrnoException).code === "ENOENT" ? "reference_missing" : "reference_unavailable");
96
+ }
97
+ }
98
+
99
+ /** Metadata-only: never reads body bytes, regardless of file size. */
100
+ export function observeExecutionFileReference(stateDir: string, request: unknown): Readonly<ExecutionFileReferenceReading> {
101
+ return inspectExecutionFile(stateDir, request);
102
+ }
103
+
104
+ /** Raw text is kernel-local input to an authorized projection, never a tool/model result. */
105
+ export function readExecutionSessionText(stateDir: string, path: string): Readonly<ExecutionTextReading> {
106
+ return inspectExecutionFile(stateDir, { kind: "session", path }, SESSION_EVIDENCE_MAX_BYTES);
107
+ }
108
+
109
+ /** Explicit command capture input only; neither this read nor its path authorizes publication. */
110
+ export function readExecutionCaptureText(stateDir: string, path: string): Readonly<ExecutionTextReading> {
111
+ return inspectExecutionFile(stateDir, { kind: "capture", path }, RUN_STREAM_SOURCE_MAX_BYTES);
112
+ }
113
+
114
+ /** Canonical runner text is kernel-local input, not complete command capture or a model-visible privacy projection. */
115
+ export function readExecutionRunnerStreamText(stateDir: string, stream: unknown): Readonly<ExecutionTextReading> {
116
+ if (stream !== "stdout" && stream !== "stderr") return unavailable("invalid_reference");
117
+ return inspectExecutionFile(stateDir, { kind: "runner_stream", path: `${stream}.log` }, RUN_STREAM_SOURCE_MAX_BYTES);
118
+ }
@@ -50,10 +50,10 @@ export function byteLength(value: string): number {
50
50
  export function trimToTailBytes(value: string, maxBytes: number): string {
51
51
  const buffer = Buffer.from(value, "utf8");
52
52
  if (buffer.length <= maxBytes) return value;
53
- return buffer
54
- .subarray(buffer.length - maxBytes)
55
- .toString("utf8")
56
- .replace(/^\uFFFD+/, "");
53
+ let start = Math.ceil(buffer.length - maxBytes);
54
+ // Skip only the cut code point's continuation bytes, not genuine U+FFFD text.
55
+ while (start < buffer.length && (buffer[start] & 0xc0) === 0x80) start++;
56
+ return buffer.subarray(start).toString("utf8");
57
57
  }
58
58
 
59
59
  export function truncateTailContent(content: string): {