@llblab/pi-kit 0.38.3 → 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 (430) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +2 -2
  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/@llblab/pi-codex-usage/AGENTS.md +2 -2
  188. package/node_modules/@llblab/pi-codex-usage/CHANGELOG.md +6 -0
  189. package/node_modules/@llblab/pi-codex-usage/README.md +9 -5
  190. package/node_modules/@llblab/pi-codex-usage/lib/query.ts +229 -50
  191. package/node_modules/@llblab/pi-codex-usage/lib/usage.ts +9 -1
  192. package/node_modules/@llblab/pi-codex-usage/package.json +1 -1
  193. package/node_modules/yaml/LICENSE +13 -0
  194. package/node_modules/yaml/README.md +172 -0
  195. package/node_modules/yaml/bin.mjs +11 -0
  196. package/node_modules/yaml/browser/dist/compose/compose-collection.js +88 -0
  197. package/node_modules/yaml/browser/dist/compose/compose-doc.js +43 -0
  198. package/node_modules/yaml/browser/dist/compose/compose-node.js +109 -0
  199. package/node_modules/yaml/browser/dist/compose/compose-scalar.js +86 -0
  200. package/node_modules/yaml/browser/dist/compose/composer.js +219 -0
  201. package/node_modules/yaml/browser/dist/compose/resolve-block-map.js +115 -0
  202. package/node_modules/yaml/browser/dist/compose/resolve-block-scalar.js +198 -0
  203. package/node_modules/yaml/browser/dist/compose/resolve-block-seq.js +49 -0
  204. package/node_modules/yaml/browser/dist/compose/resolve-end.js +37 -0
  205. package/node_modules/yaml/browser/dist/compose/resolve-flow-collection.js +207 -0
  206. package/node_modules/yaml/browser/dist/compose/resolve-flow-scalar.js +225 -0
  207. package/node_modules/yaml/browser/dist/compose/resolve-props.js +146 -0
  208. package/node_modules/yaml/browser/dist/compose/util-contains-newline.js +34 -0
  209. package/node_modules/yaml/browser/dist/compose/util-empty-scalar-position.js +26 -0
  210. package/node_modules/yaml/browser/dist/compose/util-flow-indent-check.js +15 -0
  211. package/node_modules/yaml/browser/dist/compose/util-map-includes.js +13 -0
  212. package/node_modules/yaml/browser/dist/doc/Document.js +335 -0
  213. package/node_modules/yaml/browser/dist/doc/anchors.js +71 -0
  214. package/node_modules/yaml/browser/dist/doc/applyReviver.js +55 -0
  215. package/node_modules/yaml/browser/dist/doc/createNode.js +88 -0
  216. package/node_modules/yaml/browser/dist/doc/directives.js +176 -0
  217. package/node_modules/yaml/browser/dist/errors.js +57 -0
  218. package/node_modules/yaml/browser/dist/index.js +17 -0
  219. package/node_modules/yaml/browser/dist/log.js +11 -0
  220. package/node_modules/yaml/browser/dist/nodes/Alias.js +116 -0
  221. package/node_modules/yaml/browser/dist/nodes/Collection.js +147 -0
  222. package/node_modules/yaml/browser/dist/nodes/Node.js +38 -0
  223. package/node_modules/yaml/browser/dist/nodes/Pair.js +36 -0
  224. package/node_modules/yaml/browser/dist/nodes/Scalar.js +24 -0
  225. package/node_modules/yaml/browser/dist/nodes/YAMLMap.js +144 -0
  226. package/node_modules/yaml/browser/dist/nodes/YAMLSeq.js +113 -0
  227. package/node_modules/yaml/browser/dist/nodes/addPairToJSMap.js +63 -0
  228. package/node_modules/yaml/browser/dist/nodes/identity.js +36 -0
  229. package/node_modules/yaml/browser/dist/nodes/toJS.js +37 -0
  230. package/node_modules/yaml/browser/dist/parse/cst-scalar.js +214 -0
  231. package/node_modules/yaml/browser/dist/parse/cst-stringify.js +61 -0
  232. package/node_modules/yaml/browser/dist/parse/cst-visit.js +97 -0
  233. package/node_modules/yaml/browser/dist/parse/cst.js +98 -0
  234. package/node_modules/yaml/browser/dist/parse/lexer.js +721 -0
  235. package/node_modules/yaml/browser/dist/parse/line-counter.js +39 -0
  236. package/node_modules/yaml/browser/dist/parse/parser.js +975 -0
  237. package/node_modules/yaml/browser/dist/public-api.js +102 -0
  238. package/node_modules/yaml/browser/dist/schema/Schema.js +37 -0
  239. package/node_modules/yaml/browser/dist/schema/common/map.js +17 -0
  240. package/node_modules/yaml/browser/dist/schema/common/null.js +15 -0
  241. package/node_modules/yaml/browser/dist/schema/common/seq.js +17 -0
  242. package/node_modules/yaml/browser/dist/schema/common/string.js +14 -0
  243. package/node_modules/yaml/browser/dist/schema/core/bool.js +19 -0
  244. package/node_modules/yaml/browser/dist/schema/core/float.js +43 -0
  245. package/node_modules/yaml/browser/dist/schema/core/int.js +38 -0
  246. package/node_modules/yaml/browser/dist/schema/core/schema.js +23 -0
  247. package/node_modules/yaml/browser/dist/schema/json/schema.js +62 -0
  248. package/node_modules/yaml/browser/dist/schema/tags.js +96 -0
  249. package/node_modules/yaml/browser/dist/schema/yaml-1.1/binary.js +58 -0
  250. package/node_modules/yaml/browser/dist/schema/yaml-1.1/bool.js +26 -0
  251. package/node_modules/yaml/browser/dist/schema/yaml-1.1/float.js +46 -0
  252. package/node_modules/yaml/browser/dist/schema/yaml-1.1/int.js +71 -0
  253. package/node_modules/yaml/browser/dist/schema/yaml-1.1/merge.js +67 -0
  254. package/node_modules/yaml/browser/dist/schema/yaml-1.1/omap.js +74 -0
  255. package/node_modules/yaml/browser/dist/schema/yaml-1.1/pairs.js +78 -0
  256. package/node_modules/yaml/browser/dist/schema/yaml-1.1/schema.js +39 -0
  257. package/node_modules/yaml/browser/dist/schema/yaml-1.1/set.js +93 -0
  258. package/node_modules/yaml/browser/dist/schema/yaml-1.1/timestamp.js +101 -0
  259. package/node_modules/yaml/browser/dist/stringify/foldFlowLines.js +146 -0
  260. package/node_modules/yaml/browser/dist/stringify/stringify.js +129 -0
  261. package/node_modules/yaml/browser/dist/stringify/stringifyCollection.js +153 -0
  262. package/node_modules/yaml/browser/dist/stringify/stringifyComment.js +20 -0
  263. package/node_modules/yaml/browser/dist/stringify/stringifyDocument.js +85 -0
  264. package/node_modules/yaml/browser/dist/stringify/stringifyNumber.js +25 -0
  265. package/node_modules/yaml/browser/dist/stringify/stringifyPair.js +150 -0
  266. package/node_modules/yaml/browser/dist/stringify/stringifyString.js +336 -0
  267. package/node_modules/yaml/browser/dist/util.js +11 -0
  268. package/node_modules/yaml/browser/dist/visit.js +233 -0
  269. package/node_modules/yaml/browser/index.js +5 -0
  270. package/node_modules/yaml/browser/package.json +3 -0
  271. package/node_modules/yaml/dist/cli.d.ts +8 -0
  272. package/node_modules/yaml/dist/cli.mjs +201 -0
  273. package/node_modules/yaml/dist/compose/compose-collection.d.ts +11 -0
  274. package/node_modules/yaml/dist/compose/compose-collection.js +90 -0
  275. package/node_modules/yaml/dist/compose/compose-doc.d.ts +7 -0
  276. package/node_modules/yaml/dist/compose/compose-doc.js +45 -0
  277. package/node_modules/yaml/dist/compose/compose-node.d.ts +29 -0
  278. package/node_modules/yaml/dist/compose/compose-node.js +112 -0
  279. package/node_modules/yaml/dist/compose/compose-scalar.d.ts +5 -0
  280. package/node_modules/yaml/dist/compose/compose-scalar.js +88 -0
  281. package/node_modules/yaml/dist/compose/composer.d.ts +63 -0
  282. package/node_modules/yaml/dist/compose/composer.js +224 -0
  283. package/node_modules/yaml/dist/compose/resolve-block-map.d.ts +6 -0
  284. package/node_modules/yaml/dist/compose/resolve-block-map.js +117 -0
  285. package/node_modules/yaml/dist/compose/resolve-block-scalar.d.ts +11 -0
  286. package/node_modules/yaml/dist/compose/resolve-block-scalar.js +200 -0
  287. package/node_modules/yaml/dist/compose/resolve-block-seq.d.ts +6 -0
  288. package/node_modules/yaml/dist/compose/resolve-block-seq.js +51 -0
  289. package/node_modules/yaml/dist/compose/resolve-end.d.ts +6 -0
  290. package/node_modules/yaml/dist/compose/resolve-end.js +39 -0
  291. package/node_modules/yaml/dist/compose/resolve-flow-collection.d.ts +7 -0
  292. package/node_modules/yaml/dist/compose/resolve-flow-collection.js +209 -0
  293. package/node_modules/yaml/dist/compose/resolve-flow-scalar.d.ts +10 -0
  294. package/node_modules/yaml/dist/compose/resolve-flow-scalar.js +227 -0
  295. package/node_modules/yaml/dist/compose/resolve-props.d.ts +23 -0
  296. package/node_modules/yaml/dist/compose/resolve-props.js +148 -0
  297. package/node_modules/yaml/dist/compose/util-contains-newline.d.ts +2 -0
  298. package/node_modules/yaml/dist/compose/util-contains-newline.js +36 -0
  299. package/node_modules/yaml/dist/compose/util-empty-scalar-position.d.ts +2 -0
  300. package/node_modules/yaml/dist/compose/util-empty-scalar-position.js +28 -0
  301. package/node_modules/yaml/dist/compose/util-flow-indent-check.d.ts +3 -0
  302. package/node_modules/yaml/dist/compose/util-flow-indent-check.js +17 -0
  303. package/node_modules/yaml/dist/compose/util-map-includes.d.ts +4 -0
  304. package/node_modules/yaml/dist/compose/util-map-includes.js +15 -0
  305. package/node_modules/yaml/dist/doc/Document.d.ts +141 -0
  306. package/node_modules/yaml/dist/doc/Document.js +337 -0
  307. package/node_modules/yaml/dist/doc/anchors.d.ts +24 -0
  308. package/node_modules/yaml/dist/doc/anchors.js +76 -0
  309. package/node_modules/yaml/dist/doc/applyReviver.d.ts +9 -0
  310. package/node_modules/yaml/dist/doc/applyReviver.js +57 -0
  311. package/node_modules/yaml/dist/doc/createNode.d.ts +17 -0
  312. package/node_modules/yaml/dist/doc/createNode.js +90 -0
  313. package/node_modules/yaml/dist/doc/directives.d.ts +49 -0
  314. package/node_modules/yaml/dist/doc/directives.js +178 -0
  315. package/node_modules/yaml/dist/errors.d.ts +21 -0
  316. package/node_modules/yaml/dist/errors.js +62 -0
  317. package/node_modules/yaml/dist/index.d.ts +25 -0
  318. package/node_modules/yaml/dist/index.js +50 -0
  319. package/node_modules/yaml/dist/log.d.ts +3 -0
  320. package/node_modules/yaml/dist/log.js +19 -0
  321. package/node_modules/yaml/dist/nodes/Alias.d.ts +29 -0
  322. package/node_modules/yaml/dist/nodes/Alias.js +118 -0
  323. package/node_modules/yaml/dist/nodes/Collection.d.ts +73 -0
  324. package/node_modules/yaml/dist/nodes/Collection.js +151 -0
  325. package/node_modules/yaml/dist/nodes/Node.d.ts +53 -0
  326. package/node_modules/yaml/dist/nodes/Node.js +40 -0
  327. package/node_modules/yaml/dist/nodes/Pair.d.ts +22 -0
  328. package/node_modules/yaml/dist/nodes/Pair.js +39 -0
  329. package/node_modules/yaml/dist/nodes/Scalar.d.ts +47 -0
  330. package/node_modules/yaml/dist/nodes/Scalar.js +27 -0
  331. package/node_modules/yaml/dist/nodes/YAMLMap.d.ts +53 -0
  332. package/node_modules/yaml/dist/nodes/YAMLMap.js +147 -0
  333. package/node_modules/yaml/dist/nodes/YAMLSeq.d.ts +60 -0
  334. package/node_modules/yaml/dist/nodes/YAMLSeq.js +115 -0
  335. package/node_modules/yaml/dist/nodes/addPairToJSMap.d.ts +4 -0
  336. package/node_modules/yaml/dist/nodes/addPairToJSMap.js +65 -0
  337. package/node_modules/yaml/dist/nodes/identity.d.ts +23 -0
  338. package/node_modules/yaml/dist/nodes/identity.js +53 -0
  339. package/node_modules/yaml/dist/nodes/toJS.d.ts +29 -0
  340. package/node_modules/yaml/dist/nodes/toJS.js +39 -0
  341. package/node_modules/yaml/dist/options.d.ts +350 -0
  342. package/node_modules/yaml/dist/parse/cst-scalar.d.ts +64 -0
  343. package/node_modules/yaml/dist/parse/cst-scalar.js +218 -0
  344. package/node_modules/yaml/dist/parse/cst-stringify.d.ts +8 -0
  345. package/node_modules/yaml/dist/parse/cst-stringify.js +63 -0
  346. package/node_modules/yaml/dist/parse/cst-visit.d.ts +39 -0
  347. package/node_modules/yaml/dist/parse/cst-visit.js +99 -0
  348. package/node_modules/yaml/dist/parse/cst.d.ts +109 -0
  349. package/node_modules/yaml/dist/parse/cst.js +112 -0
  350. package/node_modules/yaml/dist/parse/lexer.d.ts +87 -0
  351. package/node_modules/yaml/dist/parse/lexer.js +723 -0
  352. package/node_modules/yaml/dist/parse/line-counter.d.ts +22 -0
  353. package/node_modules/yaml/dist/parse/line-counter.js +41 -0
  354. package/node_modules/yaml/dist/parse/parser.d.ts +84 -0
  355. package/node_modules/yaml/dist/parse/parser.js +980 -0
  356. package/node_modules/yaml/dist/public-api.d.ts +44 -0
  357. package/node_modules/yaml/dist/public-api.js +107 -0
  358. package/node_modules/yaml/dist/schema/Schema.d.ts +17 -0
  359. package/node_modules/yaml/dist/schema/Schema.js +39 -0
  360. package/node_modules/yaml/dist/schema/common/map.d.ts +2 -0
  361. package/node_modules/yaml/dist/schema/common/map.js +19 -0
  362. package/node_modules/yaml/dist/schema/common/null.d.ts +4 -0
  363. package/node_modules/yaml/dist/schema/common/null.js +17 -0
  364. package/node_modules/yaml/dist/schema/common/seq.d.ts +2 -0
  365. package/node_modules/yaml/dist/schema/common/seq.js +19 -0
  366. package/node_modules/yaml/dist/schema/common/string.d.ts +2 -0
  367. package/node_modules/yaml/dist/schema/common/string.js +16 -0
  368. package/node_modules/yaml/dist/schema/core/bool.d.ts +4 -0
  369. package/node_modules/yaml/dist/schema/core/bool.js +21 -0
  370. package/node_modules/yaml/dist/schema/core/float.d.ts +4 -0
  371. package/node_modules/yaml/dist/schema/core/float.js +47 -0
  372. package/node_modules/yaml/dist/schema/core/int.d.ts +4 -0
  373. package/node_modules/yaml/dist/schema/core/int.js +42 -0
  374. package/node_modules/yaml/dist/schema/core/schema.d.ts +1 -0
  375. package/node_modules/yaml/dist/schema/core/schema.js +25 -0
  376. package/node_modules/yaml/dist/schema/json/schema.d.ts +2 -0
  377. package/node_modules/yaml/dist/schema/json/schema.js +64 -0
  378. package/node_modules/yaml/dist/schema/json-schema.d.ts +69 -0
  379. package/node_modules/yaml/dist/schema/tags.d.ts +48 -0
  380. package/node_modules/yaml/dist/schema/tags.js +99 -0
  381. package/node_modules/yaml/dist/schema/types.d.ts +92 -0
  382. package/node_modules/yaml/dist/schema/yaml-1.1/binary.d.ts +2 -0
  383. package/node_modules/yaml/dist/schema/yaml-1.1/binary.js +70 -0
  384. package/node_modules/yaml/dist/schema/yaml-1.1/bool.d.ts +7 -0
  385. package/node_modules/yaml/dist/schema/yaml-1.1/bool.js +29 -0
  386. package/node_modules/yaml/dist/schema/yaml-1.1/float.d.ts +4 -0
  387. package/node_modules/yaml/dist/schema/yaml-1.1/float.js +50 -0
  388. package/node_modules/yaml/dist/schema/yaml-1.1/int.d.ts +5 -0
  389. package/node_modules/yaml/dist/schema/yaml-1.1/int.js +76 -0
  390. package/node_modules/yaml/dist/schema/yaml-1.1/merge.d.ts +9 -0
  391. package/node_modules/yaml/dist/schema/yaml-1.1/merge.js +71 -0
  392. package/node_modules/yaml/dist/schema/yaml-1.1/omap.d.ts +22 -0
  393. package/node_modules/yaml/dist/schema/yaml-1.1/omap.js +77 -0
  394. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.d.ts +10 -0
  395. package/node_modules/yaml/dist/schema/yaml-1.1/pairs.js +82 -0
  396. package/node_modules/yaml/dist/schema/yaml-1.1/schema.d.ts +1 -0
  397. package/node_modules/yaml/dist/schema/yaml-1.1/schema.js +41 -0
  398. package/node_modules/yaml/dist/schema/yaml-1.1/set.d.ts +28 -0
  399. package/node_modules/yaml/dist/schema/yaml-1.1/set.js +96 -0
  400. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.d.ts +6 -0
  401. package/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js +105 -0
  402. package/node_modules/yaml/dist/stringify/foldFlowLines.d.ts +34 -0
  403. package/node_modules/yaml/dist/stringify/foldFlowLines.js +151 -0
  404. package/node_modules/yaml/dist/stringify/stringify.d.ts +21 -0
  405. package/node_modules/yaml/dist/stringify/stringify.js +132 -0
  406. package/node_modules/yaml/dist/stringify/stringifyCollection.d.ts +17 -0
  407. package/node_modules/yaml/dist/stringify/stringifyCollection.js +155 -0
  408. package/node_modules/yaml/dist/stringify/stringifyComment.d.ts +10 -0
  409. package/node_modules/yaml/dist/stringify/stringifyComment.js +24 -0
  410. package/node_modules/yaml/dist/stringify/stringifyDocument.d.ts +4 -0
  411. package/node_modules/yaml/dist/stringify/stringifyDocument.js +87 -0
  412. package/node_modules/yaml/dist/stringify/stringifyNumber.d.ts +2 -0
  413. package/node_modules/yaml/dist/stringify/stringifyNumber.js +27 -0
  414. package/node_modules/yaml/dist/stringify/stringifyPair.d.ts +3 -0
  415. package/node_modules/yaml/dist/stringify/stringifyPair.js +152 -0
  416. package/node_modules/yaml/dist/stringify/stringifyString.d.ts +9 -0
  417. package/node_modules/yaml/dist/stringify/stringifyString.js +338 -0
  418. package/node_modules/yaml/dist/test-events.d.ts +4 -0
  419. package/node_modules/yaml/dist/test-events.js +134 -0
  420. package/node_modules/yaml/dist/util.d.ts +16 -0
  421. package/node_modules/yaml/dist/util.js +28 -0
  422. package/node_modules/yaml/dist/visit.d.ts +102 -0
  423. package/node_modules/yaml/dist/visit.js +236 -0
  424. package/node_modules/yaml/package.json +97 -0
  425. package/node_modules/yaml/util.js +2 -0
  426. package/package.json +3 -3
  427. package/node_modules/@llblab/pi-actors/banner.jpg +0 -0
  428. package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.d.ts +0 -16
  429. package/node_modules/@llblab/pi-actors/dist/lib/inspector-actions.js +0 -57
  430. package/node_modules/@llblab/pi-actors/lib/inspector-actions.ts +0 -79
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Async run state-directory ownership.
3
- * Owns: the marker proof required before launch and destructive retention.
3
+ * Owns: marker proof for lifecycle/retention and optional bounded readonly identity admission.
4
4
  */
5
5
 
6
6
  import {
@@ -16,6 +16,7 @@ import { tmpdir } from "node:os";
16
16
  import { isAbsolute, join, relative, resolve } from "node:path";
17
17
 
18
18
  import { writeJsonAtomic } from "./file-state.ts";
19
+ import { readJsonFileResilient } from "./state-readers.ts";
19
20
 
20
21
  export const RUN_STATE_OWNERSHIP_FILE = ".pi-actors-run-state.json";
21
22
 
@@ -66,11 +67,15 @@ function assertCanonicalDirectory(stateDir: string): string {
66
67
  return resolved;
67
68
  }
68
69
 
69
- function readMarker(stateDir: string): RunStateOwnershipMarker | undefined {
70
+ function readMarker(stateDir: string, maxBytes?: number): RunStateOwnershipMarker | undefined {
70
71
  try {
71
- const value = JSON.parse(readFileSync(markerPath(stateDir), "utf8")) as Partial<RunStateOwnershipMarker>;
72
+ const path = markerPath(stateDir);
73
+ if (!lstatSync(path).isFile()) return undefined;
74
+ const value = maxBytes === undefined
75
+ ? JSON.parse(readFileSync(path, "utf8")) as Partial<RunStateOwnershipMarker>
76
+ : readJsonFileResilient<Partial<RunStateOwnershipMarker> | undefined>(path, undefined, { maxBytes, strictUtf8: true }).value;
72
77
  if (
73
- value.version !== 1 ||
78
+ !value || value.version !== 1 ||
74
79
  typeof value.run !== "string" ||
75
80
  typeof value.state_dir !== "string" ||
76
81
  typeof value.ownership_token !== "string" ||
@@ -98,6 +103,20 @@ function assertMarkerMatches(
98
103
  return marker;
99
104
  }
100
105
 
106
+ /** Avoid acquiring the same lifecycle resource through a second path while its parent lock is held. */
107
+ export function assertDistinctRunStateDirectories(parentStateDir: string, childStateDir: string): void {
108
+ const parent = realpathSync.native(resolve(parentStateDir));
109
+ let child: string;
110
+ try { child = realpathSync.native(resolve(childStateDir)); }
111
+ catch (error) {
112
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") return;
113
+ throw error;
114
+ }
115
+ if (comparablePath(parent) === comparablePath(child)) {
116
+ throw new Error("Run descendant preparation cannot target its parent state directory.");
117
+ }
118
+ }
119
+
101
120
  export function claimRunStateDirectory(stateDir: string, run: string): string {
102
121
  const resolved = resolve(stateDir);
103
122
  if (existsSync(resolved) && lstatSync(resolved).isSymbolicLink()) {
@@ -126,6 +145,20 @@ export function claimRunStateDirectory(stateDir: string, run: string): string {
126
145
  return canonical;
127
146
  }
128
147
 
148
+ /** Read only the public marker identity, never its private ownership token. */
149
+ export function readOwnedRunStateDirectory(
150
+ stateDir: string,
151
+ options: { maxBytes?: number } = {},
152
+ ): { run: string; stateDir: string } {
153
+ if (options.maxBytes !== undefined && (!Number.isSafeInteger(options.maxBytes) || options.maxBytes < 0)) {
154
+ throw new Error("Run state ownership read budget must be a nonnegative safe integer.");
155
+ }
156
+ const canonical = assertCanonicalDirectory(stateDir);
157
+ const marker = readMarker(canonical, options.maxBytes);
158
+ const checked = assertMarkerMatches(marker, canonical, marker?.run ?? "");
159
+ return { run: checked.run, stateDir: canonical };
160
+ }
161
+
129
162
  export function assertOwnedRunStateDirectory(
130
163
  stateDir: string,
131
164
  run: string,
@@ -0,0 +1,113 @@
1
+ // Owns: Bounded raw MI wire decoding, query inputs and unadmitted provenance fragments, subordinate to process acquisition.
2
+ // Excludes: Identity construction/digest/comparison, status/liveness/lifecycle/publication/admission,
3
+ // fallback, native invocation and asset loading. Decoded data never admits a representation profile.
4
+
5
+ type NativeStage = 'application' | 'session' | 'input' | 'retrieval' | 'operation' | 'representation' | 'cleanup';
6
+ type RawTimestamp = {
7
+ readonly profile: 'mi-timestamp-v1';
8
+ readonly year: number; readonly month: number; readonly day: number;
9
+ readonly hour: number; readonly minute: number; readonly second: number;
10
+ readonly microseconds: number; readonly utc: number;
11
+ };
12
+ type RawRow = { readonly pid: number; readonly date: RawTimestamp; readonly exe: string; readonly cmd: string };
13
+ type DecodeOutcome =
14
+ | { readonly kind: 'decoded_unadmitted'; readonly rows: readonly RawRow[] }
15
+ | { readonly kind: 'unusable'; readonly reason: 'invalid_query' | 'invalid_wire' | 'unsupported_optional_fields' }
16
+ | { readonly kind: 'unusable'; readonly reason: 'native_stage'; readonly stage: NativeStage };
17
+
18
+ export function queryArguments(profile: unknown, pids: unknown): string[] | undefined {
19
+ if ((profile !== 'scalar' && profile !== 'shared') || !Array.isArray(pids) ||
20
+ pids.length < 1 || pids.length > 64 || (profile === 'scalar' && pids.length !== 1)) return undefined;
21
+ const selected: number[] = [];
22
+ for (const pid of pids) {
23
+ if (typeof pid !== 'number' || !Number.isSafeInteger(pid) || pid <= 0 || selected.includes(pid)) return undefined;
24
+ selected.push(pid);
25
+ }
26
+ const query = `SELECT ${profile === 'shared' ? 'ProcessId,' : ''}CreationDate,ExecutablePath,CommandLine FROM Win32_Process WHERE ${selected.map(pid => `ProcessId = ${pid}`).join(' OR ')}`;
27
+ if (query.length > 4096 || !/^[\x00-\x7f]+$/.test(query)) return undefined;
28
+ return [profile, ...selected.map(String)];
29
+ }
30
+
31
+ function exactKeys(value: unknown, keys: readonly string[]): value is Record<string, unknown> {
32
+ return value !== null && typeof value === 'object' && !Array.isArray(value) &&
33
+ Object.keys(value).length === keys.length && keys.every(key => Object.hasOwn(value, key));
34
+ }
35
+
36
+ type ProvenanceBinding = {
37
+ readonly source_sha256: string;
38
+ readonly executable_sha256: string;
39
+ readonly executable_bytes: number;
40
+ readonly originating_source_commit: string;
41
+ readonly originating_build_job: string;
42
+ };
43
+
44
+ export function decodeProvenanceBinding(value: unknown):
45
+ | { readonly kind: 'decoded_binding_unadmitted'; readonly binding: ProvenanceBinding }
46
+ | { readonly kind: 'unusable'; readonly reason: 'invalid_binding' } {
47
+ const invalid = { kind: 'unusable', reason: 'invalid_binding' } as const;
48
+ if (!exactKeys(value, ['source_sha256', 'executable_sha256', 'executable_bytes', 'originating_source_commit', 'originating_build_job'])) return invalid;
49
+ const { source_sha256, executable_sha256, executable_bytes, originating_source_commit, originating_build_job } = value;
50
+ if (typeof source_sha256 !== 'string' || !/^[0-9a-f]{64}$(?![\s\S])/.test(source_sha256) ||
51
+ typeof executable_sha256 !== 'string' || !/^[0-9a-f]{64}$(?![\s\S])/.test(executable_sha256) ||
52
+ typeof originating_source_commit !== 'string' || !/^[0-9a-f]{40}$(?![\s\S])/.test(originating_source_commit) ||
53
+ typeof originating_build_job !== 'string' || !/^[1-9][0-9]*$(?![\s\S])/.test(originating_build_job) ||
54
+ typeof executable_bytes !== 'number' || !Number.isSafeInteger(executable_bytes) || executable_bytes <= 0) return invalid;
55
+ // These data claims verify neither the asset, its origin nor a representation profile.
56
+ return { kind: 'decoded_binding_unadmitted', binding: { source_sha256, executable_sha256, executable_bytes, originating_source_commit, originating_build_job } };
57
+ }
58
+
59
+ function timestamp(value: unknown): RawTimestamp | undefined {
60
+ if (!exactKeys(value, ['profile', 'year', 'month', 'day', 'hour', 'minute', 'second', 'microseconds', 'utc']) || value.profile !== 'mi-timestamp-v1') return undefined;
61
+ const { year, month, day, hour, minute, second, microseconds, utc } = value;
62
+ if (typeof year !== 'number' || typeof month !== 'number' || typeof day !== 'number' ||
63
+ typeof hour !== 'number' || typeof minute !== 'number' || typeof second !== 'number' ||
64
+ typeof microseconds !== 'number' || typeof utc !== 'number' ||
65
+ ![year, month, day, hour, minute, second, microseconds, utc].every(Number.isInteger)) return undefined;
66
+ if (year < 1601 || year > 9999 || month < 1 || month > 12 || day < 1 ||
67
+ hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59 ||
68
+ microseconds < 0 || microseconds > 999999 || utc < -720 || utc > 840) return undefined;
69
+ const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
70
+ const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
71
+ if (day > days[month - 1]!) return undefined;
72
+ return { profile: 'mi-timestamp-v1', year, month, day, hour, minute, second, microseconds, utc };
73
+ }
74
+
75
+ export function decodeResponse(bytes: Uint8Array, profile: unknown, pids: unknown): DecodeOutcome {
76
+ const args = queryArguments(profile, pids);
77
+ if (!args) return { kind: 'unusable', reason: 'invalid_query' };
78
+ const invalid: DecodeOutcome = { kind: 'unusable', reason: 'invalid_wire' };
79
+ if (!(bytes instanceof Uint8Array) || bytes.byteLength > 1024 * 1024 ||
80
+ (bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf)) return invalid;
81
+ let value: unknown;
82
+ try { value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes)); }
83
+ catch { return invalid; }
84
+ if (exactKeys(value, ['schema', 'status']) && value.schema === 'native-mi-v1') {
85
+ switch (value.status) {
86
+ case 'application': case 'session': case 'input': case 'retrieval': case 'operation': case 'representation': case 'cleanup':
87
+ return { kind: 'unusable', reason: 'native_stage', stage: value.status };
88
+ default: return invalid;
89
+ }
90
+ }
91
+ const selected = args.slice(1).map(Number);
92
+ if (!exactKeys(value, ['schema', 'status', 'profile', 'complete', 'rows']) || value.schema !== 'native-mi-v1' ||
93
+ value.status !== 'ok' || value.profile !== profile || value.complete !== true || !Array.isArray(value.rows) ||
94
+ value.rows.length > selected.length) return invalid;
95
+ const rows: RawRow[] = [];
96
+ const seen = new Set<number>();
97
+ let optionalNull = false;
98
+ for (const row of value.rows) {
99
+ if (!exactKeys(row, profile === 'shared' ? ['pid', 'date', 'exe', 'cmd'] : ['date', 'exe', 'cmd'])) return invalid;
100
+ const pid = profile === 'shared' ? row.pid : selected[0];
101
+ if (typeof pid !== 'number' || !Number.isSafeInteger(pid) || !selected.includes(pid) || seen.has(pid)) return invalid;
102
+ seen.add(pid);
103
+ // Preserve the raw optional-field distinction; no normalization or profile admission occurs here.
104
+ if (row.exe === null || row.cmd === null) optionalNull = true;
105
+ if ((row.exe !== null && typeof row.exe !== 'string') || (row.cmd !== null && typeof row.cmd !== 'string')) return invalid;
106
+ const date = timestamp(row.date);
107
+ if (!date) return invalid;
108
+ // Null rows are never returned, even if the other rows are well formed.
109
+ if (typeof row.exe === 'string' && typeof row.cmd === 'string') rows.push({ pid, date, exe: row.exe, cmd: row.cmd });
110
+ }
111
+ if (optionalNull) return { kind: 'unusable', reason: 'unsupported_optional_fields' };
112
+ return { kind: 'decoded_unadmitted', rows };
113
+ }
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * Async run process identity helpers.
3
- * Owns: cross-platform liveness and stable runner process identity proofs.
3
+ * Owns: cross-platform liveness, stable runner identity, and single-process exit observations.
4
+ * Excludes: stop claims, signal dispatch, descendant/group cleanup, and lifecycle finalization.
4
5
  */
5
6
 
6
- import { spawnSync } from "node:child_process";
7
+ import { spawnSync, type ChildProcess } from "node:child_process";
8
+ import { createHash } from "node:crypto";
7
9
  import { existsSync, readFileSync, readlinkSync, realpathSync } from "node:fs";
8
10
  import { platform } from "node:os";
9
11
  import { posix, win32 } from "node:path";
@@ -31,15 +33,37 @@ type ProcessIdentityReader = (
31
33
  runtimePlatform: NodeJS.Platform,
32
34
  ) => RunProcessIdentity | undefined;
33
35
 
34
- export function isAlive(pid: number): boolean {
36
+ export type ProcessLiveness = "alive" | "dead" | "unknown";
37
+
38
+ type ProcessLivenessProbe = (pid: number, signal: 0) => boolean;
39
+
40
+ export function readProcessLiveness(
41
+ pid: number,
42
+ probe: ProcessLivenessProbe = process.kill.bind(process),
43
+ ): ProcessLiveness {
44
+ if (!Number.isSafeInteger(pid) || pid <= 0) return "unknown";
35
45
  try {
36
- process.kill(pid, 0);
37
- return true;
38
- } catch {
39
- return false;
46
+ return probe(pid, 0) === true ? "alive" : "unknown";
47
+ } catch (error) {
48
+ return (error as NodeJS.ErrnoException | undefined)?.code === "ESRCH" ? "dead" : "unknown";
40
49
  }
41
50
  }
42
51
 
52
+ /** POSIX group presence only: neither ownership, membership completeness, nor whole-Run stop proof. */
53
+ export function readProcessGroupLiveness(
54
+ processGroupId: number,
55
+ runtimePlatform: NodeJS.Platform = platform(),
56
+ probe: ProcessLivenessProbe = process.kill.bind(process),
57
+ ): ProcessLiveness {
58
+ if (runtimePlatform !== "linux" && runtimePlatform !== "darwin") return "unknown";
59
+ return readProcessLiveness(processGroupId, (validatedId, signal) => probe(-validatedId, signal));
60
+ }
61
+
62
+ /** Unknown liveness must retain active-state guards, never authorize state reuse. */
63
+ export function isAlive(pid: number): boolean {
64
+ return readProcessLiveness(pid) !== "dead";
65
+ }
66
+
43
67
  function readLinuxIdentity(pid: number): RunProcessIdentity | undefined {
44
68
  if (!existsSync(`/proc/${pid}`)) return undefined;
45
69
  try {
@@ -77,8 +101,8 @@ function readDarwinIdentity(pid: number): RunProcessIdentity | undefined {
77
101
 
78
102
  function readWindowsIdentity(pid: number): RunProcessIdentity | undefined {
79
103
  const command = [
80
- `$p = Get-CimInstance Win32_Process -Filter \"ProcessId = ${pid}\";`,
81
- "if ($null -eq $p) { exit 3 };",
104
+ `$p = Get-CimInstance Win32_Process -Property CreationDate,ExecutablePath,CommandLine -Filter \"ProcessId = ${pid}\";`,
105
+ "if ($null -eq $p) { exit 3 }; [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false, $true);",
82
106
  "$p | Select-Object CreationDate,ExecutablePath,CommandLine | ConvertTo-Json -Compress",
83
107
  ].join(" ");
84
108
  const result = spawnSync(
@@ -88,20 +112,55 @@ function readWindowsIdentity(pid: number): RunProcessIdentity | undefined {
88
112
  );
89
113
  if (result.status !== 0) return undefined;
90
114
  try {
91
- const value = JSON.parse(result.stdout) as Record<string, unknown>;
92
- if (typeof value.CreationDate !== "string") return undefined;
93
- const executable = typeof value.ExecutablePath === "string" ? value.ExecutablePath : "";
94
- const commandLine = typeof value.CommandLine === "string" ? value.CommandLine : "";
95
- return {
96
- command: `${executable}\n${commandLine}`.trim(),
97
- platform: "win32",
98
- start_time: value.CreationDate,
99
- };
115
+ return decodeWindowsIdentity(JSON.parse(result.stdout));
100
116
  } catch {
101
117
  return undefined;
102
118
  }
103
119
  }
104
120
 
121
+ function decodeWindowsIdentity(value: unknown): RunProcessIdentity | undefined {
122
+ if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
123
+ const row = value as Record<string, unknown>;
124
+ if (typeof row.CreationDate !== "string") return undefined;
125
+ const executable = typeof row.ExecutablePath === "string" ? row.ExecutablePath : "";
126
+ const commandLine = typeof row.CommandLine === "string" ? row.CommandLine : "";
127
+ return { command: `${executable}\n${commandLine}`.trim(), platform: "win32", start_time: row.CreationDate };
128
+ }
129
+
130
+ export const WINDOWS_IDENTITY_QUERY_PID_LIMIT = 64;
131
+ const WINDOWS_IDENTITY_QUERY_MAX_BYTES = 1024 * 1024;
132
+
133
+ /** One bounded, complete CIM observation; undefined means query failure, never process absence. */
134
+ export function readWindowsProcessIdentities(pids: readonly number[]): Map<number, RunProcessIdentity> | undefined {
135
+ if (!pids.length || pids.length > WINDOWS_IDENTITY_QUERY_PID_LIMIT || new Set(pids).size !== pids.length ||
136
+ pids.some(pid => !Number.isSafeInteger(pid) || pid <= 0)) return undefined;
137
+ // 64 safe integers (at most 16 digits) keep this ASCII command below 4096 characters,
138
+ // independently of native output. No shell, encoded command, or widened process scan.
139
+ const command = ['$ErrorActionPreference = "Stop";',
140
+ `$p = Get-CimInstance Win32_Process -Property ProcessId,CreationDate,ExecutablePath,CommandLine -Filter "${pids.map(pid => `ProcessId = ${pid}`).join(" OR ")}";`,
141
+ "[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false, $true); ConvertTo-Json -InputObject @($p | Select-Object ProcessId,CreationDate,ExecutablePath,CommandLine) -Compress"].join(" ");
142
+ if (command.length > 4096) return undefined;
143
+ try {
144
+ const result = spawnSync("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", command],
145
+ { encoding: "utf8", windowsHide: true, maxBuffer: WINDOWS_IDENTITY_QUERY_MAX_BYTES });
146
+ if (result.error || result.signal || result.status !== 0 || typeof result.stdout !== "string" ||
147
+ result.stdout.length > WINDOWS_IDENTITY_QUERY_MAX_BYTES || Buffer.byteLength(result.stdout) > WINDOWS_IDENTITY_QUERY_MAX_BYTES) return undefined;
148
+ // Parse the entire bounded output, not a clipped prefix. Every row must correlate exactly once.
149
+ const rows: unknown = JSON.parse(result.stdout);
150
+ if (!Array.isArray(rows) || rows.length > pids.length) return undefined;
151
+ const selected = new Set(pids); const identities = new Map<number, RunProcessIdentity>();
152
+ for (const row of rows) {
153
+ if (!row || typeof row !== "object" || Array.isArray(row)) return undefined;
154
+ const pid = (row as Record<string, unknown>).ProcessId;
155
+ if (typeof pid !== "number" || !selected.has(pid) || identities.has(pid)) return undefined;
156
+ const identity = decodeWindowsIdentity(row);
157
+ if (!identity) return undefined;
158
+ identities.set(pid, identity);
159
+ }
160
+ return identities;
161
+ } catch { return undefined; }
162
+ }
163
+
105
164
  export function readProcessIdentity(
106
165
  pid: number,
107
166
  runtimePlatform: NodeJS.Platform = platform(),
@@ -112,6 +171,29 @@ export function readProcessIdentity(
112
171
  return undefined;
113
172
  }
114
173
 
174
+ export function runProcessIdentityDigest(value: unknown): string | undefined {
175
+ if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
176
+ const identity = value as Record<string, unknown>;
177
+ if (typeof identity.platform !== "string" || !["linux", "darwin", "win32"].includes(identity.platform) ||
178
+ typeof identity.start_time !== "string" || !identity.start_time ||
179
+ typeof identity.command !== "string" || !identity.command ||
180
+ (identity.cwd !== undefined && typeof identity.cwd !== "string")) return undefined;
181
+ return createHash("sha256").update(JSON.stringify([
182
+ identity.platform, identity.start_time, identity.command, identity.cwd ?? null,
183
+ ])).digest("hex");
184
+ }
185
+
186
+ function matchesRunCwd(identity: RunProcessIdentity, cwd: string, runtimePlatform: NodeJS.Platform): boolean {
187
+ const pathApi = runtimePlatform === "win32" ? win32 : posix;
188
+ const resolvedCwd = pathApi.resolve(cwd);
189
+ const canonicalCwd = runtimePlatform === platform() && existsSync(resolvedCwd)
190
+ ? realpathSync.native(resolvedCwd)
191
+ : resolvedCwd;
192
+ const expectedCwd = runtimePlatform === "win32" ? canonicalCwd.toLowerCase() : canonicalCwd;
193
+ const actualCwd = runtimePlatform === "win32" && identity.cwd ? identity.cwd.toLowerCase() : identity.cwd;
194
+ return !actualCwd || actualCwd === expectedCwd;
195
+ }
196
+
115
197
  export function captureRunProcessIdentity(
116
198
  pid: number,
117
199
  cwd: string,
@@ -121,25 +203,78 @@ export function captureRunProcessIdentity(
121
203
  reader: ProcessIdentityReader = readProcessIdentity,
122
204
  ): RunProcessIdentity | undefined {
123
205
  const identity = reader(pid, runtimePlatform);
124
- if (!identity) return undefined;
125
- if (!identity.command.includes(runnerPath) || !identity.command.includes(stateDir)) {
126
- return undefined;
127
- }
128
- const pathApi = runtimePlatform === "win32" ? win32 : posix;
129
- const resolvedCwd = pathApi.resolve(cwd);
130
- const canonicalCwd = runtimePlatform === platform() && existsSync(resolvedCwd)
131
- ? realpathSync.native(resolvedCwd)
132
- : resolvedCwd;
133
- const expectedCwd =
134
- runtimePlatform === "win32" ? canonicalCwd.toLowerCase() : canonicalCwd;
135
- const actualCwd =
136
- runtimePlatform === "win32" && identity.cwd
137
- ? identity.cwd.toLowerCase()
138
- : identity.cwd;
139
- if (actualCwd && actualCwd !== expectedCwd) return undefined;
206
+ if (!identity || !identity.command.includes(runnerPath) || !identity.command.includes(stateDir) ||
207
+ !matchesRunCwd(identity, cwd, runtimePlatform)) return undefined;
140
208
  return identity;
141
209
  }
142
210
 
211
+ export interface SpawnIdentityCaptureDeps {
212
+ runtimePlatform?: NodeJS.Platform;
213
+ readIdentity?: ProcessIdentityReader;
214
+ now?: () => number;
215
+ wait?: (milliseconds: number) => void;
216
+ }
217
+
218
+ /** Fresh spawn only, while its lifecycle lock/child handle is retained and workload is not admitted. */
219
+ export function captureSpawnedRunProcessIdentity(
220
+ child: Pick<ChildProcess, "pid" | "exitCode" | "signalCode">,
221
+ cwd: string,
222
+ stateDir: string,
223
+ runnerPath: string,
224
+ deps: SpawnIdentityCaptureDeps = {},
225
+ ): RunProcessIdentity | undefined {
226
+ return captureFreshProcessIdentity(child, deps,
227
+ (current, runtimePlatform) => captureRunProcessIdentity(child.pid!, cwd, stateDir, runnerPath, runtimePlatform, () => current),
228
+ (current, runtimePlatform) => matchesRunCwd(current, cwd, runtimePlatform),
229
+ );
230
+ }
231
+
232
+ /** Immediate managed-native callback only; this observation is not complete membership or termination authority. */
233
+ export function captureSpawnedNativeProcessIdentity(
234
+ child: Pick<ChildProcess, "pid" | "exitCode" | "signalCode">,
235
+ deps: SpawnIdentityCaptureDeps = {},
236
+ ): RunProcessIdentity | undefined {
237
+ const runtimePlatform = deps.runtimePlatform ?? platform();
238
+ if (!["linux", "darwin", "win32"].includes(runtimePlatform)) return undefined;
239
+ return captureFreshProcessIdentity(child, deps, (current) => current, () => true);
240
+ }
241
+
242
+ function captureFreshProcessIdentity(
243
+ child: Pick<ChildProcess, "pid" | "exitCode" | "signalCode">,
244
+ deps: SpawnIdentityCaptureDeps,
245
+ accept: (current: RunProcessIdentity, runtimePlatform: NodeJS.Platform) => RunProcessIdentity | undefined,
246
+ acceptEmpty: (current: RunProcessIdentity, runtimePlatform: NodeJS.Platform) => boolean,
247
+ ): RunProcessIdentity | undefined {
248
+ const pid = child.pid;
249
+ if (!Number.isSafeInteger(pid) || !pid || pid <= 0) return undefined;
250
+ const runtimePlatform = deps.runtimePlatform ?? platform();
251
+ const read = deps.readIdentity ?? readProcessIdentity;
252
+ const now = deps.now ?? (() => performance.now());
253
+ const wait = deps.wait ?? ((ms) => { Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms); });
254
+ const started = now();
255
+ let birth: string | undefined;
256
+ // Bound startup retries, not OS probe latency; never retry an observed contradiction.
257
+ for (let attempt = 0; attempt <= 100; attempt++) {
258
+ if (child.pid !== pid || child.exitCode !== null || child.signalCode !== null) return undefined;
259
+ const current = read(pid, runtimePlatform);
260
+ if (child.pid !== pid || child.exitCode !== null || child.signalCode !== null) return undefined;
261
+ if (current) {
262
+ if (current.platform !== runtimePlatform || typeof current.start_time !== "string" || !current.start_time ||
263
+ typeof current.command !== "string" || (current.cwd !== undefined && (typeof current.cwd !== "string" || !current.cwd)) ||
264
+ (birth !== undefined && current.start_time !== birth)) return undefined;
265
+ birth = current.start_time;
266
+ if (current.command) {
267
+ return accept({ ...current }, runtimePlatform);
268
+ }
269
+ if (!acceptEmpty(current, runtimePlatform)) return undefined;
270
+ }
271
+ const elapsed = now() - started;
272
+ if (!Number.isFinite(elapsed) || elapsed < 0 || elapsed >= 500) return undefined;
273
+ wait(Math.min(5, 500 - elapsed));
274
+ }
275
+ return undefined;
276
+ }
277
+
143
278
  export function verifyRunProcessIdentity(
144
279
  pid: number,
145
280
  expected: RunProcessIdentity | undefined,
@@ -160,6 +295,47 @@ export function verifyRunProcessIdentity(
160
295
  return { status: valid ? "valid" : "owner_mismatch", valid };
161
296
  }
162
297
 
298
+ export interface RunProcessExitObservation {
299
+ status: "exited" | "running" | "unproven";
300
+ process_identity_status: RunProcessIdentityStatus;
301
+ }
302
+
303
+ export interface RunProcessExitDeps {
304
+ probe?: ProcessLivenessProbe;
305
+ readIdentity?: ProcessIdentityReader;
306
+ runtimePlatform?: NodeJS.Platform;
307
+ }
308
+
309
+ /** Observes one captured process only; signal dispatch and descendant cleanup are separate facts. */
310
+ export function observeRunProcessExit(
311
+ pid: number,
312
+ expected: RunProcessIdentity | undefined,
313
+ deps: RunProcessExitDeps = {},
314
+ ): RunProcessExitObservation {
315
+ const runtimePlatform = deps.runtimePlatform ?? platform();
316
+ if (!expected || expected.platform !== runtimePlatform ||
317
+ typeof expected.command !== "string" || !expected.command ||
318
+ typeof expected.start_time !== "string" || !expected.start_time ||
319
+ (expected.cwd !== undefined && typeof expected.cwd !== "string")) {
320
+ return { status: "unproven", process_identity_status: "unsupported_proof" };
321
+ }
322
+ const liveness = readProcessLiveness(pid, deps.probe);
323
+ if (liveness === "unknown") {
324
+ return { status: "unproven", process_identity_status: "unsupported_proof" };
325
+ }
326
+ const identity = verifyRunProcessIdentity(
327
+ pid,
328
+ expected,
329
+ runtimePlatform,
330
+ deps.readIdentity ?? readProcessIdentity,
331
+ () => liveness === "alive",
332
+ );
333
+ return {
334
+ status: identity.status === "dead_pid" ? "exited" : identity.valid ? "running" : "unproven",
335
+ process_identity_status: identity.status,
336
+ };
337
+ }
338
+
163
339
  export function isWithinRunnerIdentityGrace(
164
340
  meta: Record<string, unknown>,
165
341
  graceMs: number,