@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
@@ -0,0 +1,470 @@
1
+ /**
2
+ * Run session context: fixed privacy previews and generation-bound publication/selection.
3
+ * Owns: assistant-only projection, recorded-session preview admission, producer-bound preview/catalog/index commits and selected published reads.
4
+ * Excludes: private-role exposure, raw session export/discovery, primary-source completeness, native authority and multi-file transactions.
5
+ */
6
+ import { createHash } from "node:crypto";
7
+ import { lstatSync, mkdirSync } from "node:fs";
8
+ import { join, resolve } from "node:path";
9
+ import { writeTextAtomic } from "./file-state.js";
10
+ import { DEFAULT_INSPECT_LINES, SESSION_EVIDENCE_TEXT_CHARS } from "./limits.js";
11
+ import { createRunRecipeEvidenceRedactor, createRunRecipeBodyRedactor, createContextIdentityPrivacyCheck } from "./recipe-projection.js";
12
+ import { readRunContextIdentity, readRunContextIndex, runContextExportPath, writeRunContextIndexUnderLock, RUN_CONTEXT_INDEX_FILE, RUN_CONTEXT_SOURCE_METADATA_MAX_BYTES } from "./runs-context-index.js";
13
+ import { readRunExecutionReference } from "./runs-execution-evidence.js";
14
+ import { readExecutionSessionText } from "./execution-files.js";
15
+ import { readRunProducerCapturedMetadata, withRunProducerEvidence } from "./runs-results.js";
16
+ import { selectLastRecordedSessionBranch } from "./session-evidence.js";
17
+ import { readJsonFileResilient } from "./state-readers.js";
18
+ // --- Fixed privacy projection ---
19
+ export const SESSION_ASSISTANT_PREVIEW_MAX_BYTES = 64 * 1024;
20
+ /** Preview clipping happens after origin/secret projection, never by slicing raw/private session fields. */
21
+ export function projectSessionAssistantPreview(source, recipe = {}, redactEvidence) {
22
+ const invalid = () => Object.freeze({ state: "unavailable", reason: "session_invalid" });
23
+ let rows;
24
+ try {
25
+ const parsed = source.split("\n").filter(line => line.trim()).map(line => JSON.parse(line));
26
+ if (!parsed.length || parsed.some(value => !record(value)))
27
+ return invalid();
28
+ rows = parsed;
29
+ }
30
+ catch {
31
+ return invalid();
32
+ }
33
+ const header = rows[0];
34
+ if (header.type !== "session" || header.version !== 3 || typeof header.id !== "string" || !header.id)
35
+ return invalid();
36
+ const ids = new Set();
37
+ for (const row of rows.slice(1)) {
38
+ if (row.type === "session" || typeof row.type !== "string" || !row.type || typeof row.id !== "string" || !row.id || ids.has(row.id) ||
39
+ !(row.parentId === null || typeof row.parentId === "string"))
40
+ return invalid();
41
+ ids.add(row.id);
42
+ }
43
+ const diagnostics = [];
44
+ const branch = selectLastRecordedSessionBranch(rows, "session", diagnostics);
45
+ if (diagnostics.length)
46
+ return invalid();
47
+ const redact = redactEvidence ?? createRunRecipeEvidenceRedactor(recipe, Number.MAX_SAFE_INTEGER);
48
+ const messages = [];
49
+ let total = 0;
50
+ for (const entry of branch) {
51
+ if (entry.type !== "message")
52
+ continue;
53
+ const message = record(entry.message);
54
+ if (!message || message.role !== "assistant")
55
+ continue;
56
+ if (!Array.isArray(message.content))
57
+ return invalid();
58
+ const texts = [];
59
+ for (const value of message.content) {
60
+ const block = record(value);
61
+ if (block?.type !== "text")
62
+ continue;
63
+ if (typeof block.text !== "string")
64
+ return invalid();
65
+ texts.push(block.text);
66
+ }
67
+ if (!texts.length || !texts.join("\n"))
68
+ continue;
69
+ const authorized = redact(texts.join("\n"));
70
+ const points = Array.from(authorized);
71
+ const shown = points.slice(0, SESSION_EVIDENCE_TEXT_CHARS);
72
+ total++;
73
+ messages.push(Object.freeze({ ordinal: total, assistant_text: shown.join(""), text_chars_observed: points.length,
74
+ text_chars_shown: shown.length, text_chars_omitted: points.length - shown.length, preview_clipped: shown.length < points.length }));
75
+ if (messages.length > DEFAULT_INSPECT_LINES)
76
+ messages.shift();
77
+ }
78
+ const encode = () => Object.freeze({ content_scope: "assistant_visible_text_preview", source_scope: "last_recorded_branch",
79
+ primary_text: "not_exported", order: "oldest_first", coverage: Object.freeze({ truncated: true, redacted: true, history_complete: false }),
80
+ text_limit_chars: SESSION_EVIDENCE_TEXT_CHARS, messages_total: total, messages_shown: messages.length, messages_omitted: total - messages.length,
81
+ messages: Object.freeze([...messages]) });
82
+ let preview = encode();
83
+ while (messages.length && Buffer.byteLength(JSON.stringify(preview), "utf8") > SESSION_ASSISTANT_PREVIEW_MAX_BYTES) {
84
+ messages.shift();
85
+ preview = encode();
86
+ }
87
+ if (Buffer.byteLength(JSON.stringify(preview), "utf8") > SESSION_ASSISTANT_PREVIEW_MAX_BYTES)
88
+ return Object.freeze({ state: "unavailable", reason: "preview_too_large" });
89
+ return Object.freeze({ state: "available", preview });
90
+ }
91
+ function previewUnavailable(reason) { return Object.freeze({ state: "unavailable", reason }); }
92
+ /** This policy is fixed in the kernel; serialized reference DTOs or actor visibility flags cannot widen it. */
93
+ export function readRunSessionPreview(stateDir, expected, query) {
94
+ return readSelectedSessionPreview(stateDir, expected, query);
95
+ }
96
+ /** Internal projection data, not a new input capability: only the admitted writer supplies original Recipe privacy. */
97
+ function readSelectedSessionPreview(stateDir, expected, query, recipePrivacy) {
98
+ const request = record(query);
99
+ if (!request || Object.getOwnPropertyDescriptor(request, "kind")?.value !== "session")
100
+ return previewUnavailable("request_invalid");
101
+ const admitted = readRunExecutionReference(stateDir, expected, query);
102
+ if (admitted.state === "unavailable")
103
+ return admitted;
104
+ try {
105
+ const metaPath = join(stateDir, "run.json");
106
+ const before = lstatSync(metaPath, { bigint: true });
107
+ if (!before.isFile() || before.size > BigInt(RUN_CONTEXT_SOURCE_METADATA_MAX_BYTES))
108
+ return previewUnavailable("session_metadata_unavailable");
109
+ const reading = readJsonFileResilient(metaPath, undefined, { maxBytes: RUN_CONTEXT_SOURCE_METADATA_MAX_BYTES, strictUtf8: true });
110
+ const meta = record(reading.value);
111
+ if (!admitted.unchanged() || !sameFile(before, lstatSync(metaPath, { bigint: true })))
112
+ return previewUnavailable("observation_changed");
113
+ if (reading.diagnostics.length || !meta || meta.run !== admitted.identity.run || meta.run_instance_id !== admitted.identity.run_instance_id ||
114
+ meta.ownerId !== admitted.identity.ownerId || meta.state_dir !== resolve(stateDir))
115
+ return previewUnavailable("session_metadata_unavailable");
116
+ if (recipePrivacy && !createContextIdentityPrivacyCheck(recipePrivacy)({ source_updated_at: admitted.source_updated_at })) {
117
+ return previewUnavailable("session_metadata_redacted");
118
+ }
119
+ const source = readExecutionSessionText(stateDir, admitted.reference.path);
120
+ if (!admitted.unchanged())
121
+ return previewUnavailable("observation_changed");
122
+ if (source.availability === "unavailable")
123
+ return previewUnavailable(source.reason === "reference_too_large" ? "session_too_large"
124
+ : source.reason === "reference_invalid_text" ? "session_invalid" : "session_unavailable");
125
+ const unchanged = () => {
126
+ try {
127
+ return admitted.unchanged() && source.reference.unchanged() && sameFile(before, lstatSync(metaPath, { bigint: true }));
128
+ }
129
+ catch {
130
+ return false;
131
+ }
132
+ };
133
+ if (!unchanged())
134
+ return previewUnavailable("observation_changed");
135
+ const projected = recipePrivacy ? projectSessionAssistantPreview(source.text, recipePrivacy, createRunRecipeBodyRedactor(recipePrivacy, Number.MAX_SAFE_INTEGER))
136
+ : projectSessionAssistantPreview(source.text, meta);
137
+ if (projected.state === "unavailable")
138
+ return projected;
139
+ if (!unchanged())
140
+ return previewUnavailable("observation_changed");
141
+ const result = Object.freeze({ state: "available", identity: admitted.identity, command_id: admitted.reference.command_id,
142
+ source_updated_at: admitted.source_updated_at, preview: projected.preview, unchanged });
143
+ if (Buffer.byteLength(JSON.stringify(result), "utf8") > SESSION_ASSISTANT_PREVIEW_MAX_BYTES)
144
+ return previewUnavailable("preview_too_large");
145
+ return result;
146
+ }
147
+ catch {
148
+ return previewUnavailable("session_unavailable");
149
+ }
150
+ }
151
+ // --- Publication and selected exported previews ---
152
+ export const RUN_CONTEXT_SESSIONS_MAX_BYTES = 64 * 1024;
153
+ const PREVIEW_SCHEMA = "run-context-session-preview-v1";
154
+ const CATALOG_SCHEMA = "run-context-sessions-v1";
155
+ const COVERAGE = Object.freeze({ truncated: true, redacted: true, history_complete: false });
156
+ function previewMetadata(entry) {
157
+ return { export_id: entry.export_id, command_id: entry.command_id, captured_at: entry.captured_at,
158
+ ...(typeof entry.path === "string" ? { path: entry.path } : {}) };
159
+ }
160
+ function record(value) { return value && typeof value === "object" && !Array.isArray(value) ? value : undefined; }
161
+ function known(value, keys) { return Object.keys(value).every(key => keys.includes(key)); }
162
+ function count(value) { return typeof value === "number" && Number.isSafeInteger(value) && value >= 0; }
163
+ function command(value) { return typeof value === "string" && /^command-[0-9]{3,}$/u.test(value) && Number.isSafeInteger(Number(value.slice(8))) && Number(value.slice(8)) > 0; }
164
+ function timestamp(value) { const time = typeof value === "string" ? Date.parse(value) : NaN; return Number.isSafeInteger(time) && new Date(time).toISOString() === value; }
165
+ function coverage(value) { const item = record(value); return !!item && known(item, ["truncated", "redacted", "history_complete"]) && item.truncated === true && item.redacted === true && item.history_complete === false; }
166
+ function sameObject(a, b) { return a.dev === b.dev && a.ino === b.ino; }
167
+ function sameFile(a, b) { return b.isFile() && sameObject(a, b) && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs; }
168
+ function stamp(path) { try {
169
+ return lstatSync(path, { bigint: true });
170
+ }
171
+ catch (error) {
172
+ if (error.code === "ENOENT")
173
+ return undefined;
174
+ throw error;
175
+ } }
176
+ function previewPath(id) { return `evidence/sessions/session-${id}.json`; }
177
+ function selection(value) {
178
+ const source = record(value);
179
+ if (!source || !known(source, ["kind", "command_id", "path"]))
180
+ return undefined;
181
+ const own = (key) => Object.getOwnPropertyDescriptor(source, key)?.value;
182
+ const id = own("command_id");
183
+ const path = own("path");
184
+ return own("kind") === "session" && command(id) && typeof path === "string" && !!path ? Object.freeze({ kind: "session", command_id: id, path }) : undefined;
185
+ }
186
+ function bound(value, schema, binding) {
187
+ return value.schema === schema && value.run === binding.run && value.run_instance_id === binding.runInstanceId;
188
+ }
189
+ function readBounded(path) {
190
+ const before = stamp(path);
191
+ if (!before?.isFile() || before.size > BigInt(RUN_CONTEXT_SESSIONS_MAX_BYTES))
192
+ return undefined;
193
+ const read = readJsonFileResilient(path, undefined, { maxBytes: RUN_CONTEXT_SESSIONS_MAX_BYTES, strictUtf8: true });
194
+ const value = record(read.value);
195
+ const after = stamp(path);
196
+ return !read.diagnostics.length && value && after && sameFile(before, after) ? { value, stamp: after } : undefined;
197
+ }
198
+ function validPreview(value) {
199
+ const view = record(value);
200
+ if (!view || !known(view, ["content_scope", "source_scope", "primary_text", "order", "coverage", "text_limit_chars", "messages_total", "messages_shown", "messages_omitted", "messages"]) ||
201
+ view.content_scope !== "assistant_visible_text_preview" || view.source_scope !== "last_recorded_branch" || view.primary_text !== "not_exported" || view.order !== "oldest_first" ||
202
+ !coverage(view.coverage) || view.text_limit_chars !== SESSION_EVIDENCE_TEXT_CHARS || !count(view.messages_total) || !count(view.messages_shown) || !count(view.messages_omitted) ||
203
+ !Array.isArray(view.messages) || view.messages.length > DEFAULT_INSPECT_LINES || view.messages.length !== view.messages_shown || view.messages_shown + view.messages_omitted !== view.messages_total)
204
+ return false;
205
+ let ordinal = 0;
206
+ for (const value of view.messages) {
207
+ const row = record(value);
208
+ if (!row || !known(row, ["ordinal", "assistant_text", "text_chars_observed", "text_chars_shown", "text_chars_omitted", "preview_clipped"]) ||
209
+ !count(row.ordinal) || row.ordinal <= ordinal || row.ordinal > view.messages_total || typeof row.assistant_text !== "string" || !count(row.text_chars_observed) ||
210
+ !count(row.text_chars_shown) || !count(row.text_chars_omitted) || row.text_chars_shown > SESSION_EVIDENCE_TEXT_CHARS || Array.from(row.assistant_text).length !== row.text_chars_shown ||
211
+ row.text_chars_shown + row.text_chars_omitted !== row.text_chars_observed || row.preview_clipped !== (row.text_chars_omitted > 0))
212
+ return false;
213
+ ordinal = row.ordinal;
214
+ }
215
+ return true;
216
+ }
217
+ function inspectPreview(root, base, binding) {
218
+ try {
219
+ for (const directory of [join(root, "evidence"), join(root, "evidence", "sessions")]) {
220
+ const current = stamp(directory);
221
+ if (!current?.isDirectory() || current.isSymbolicLink())
222
+ return undefined;
223
+ }
224
+ const relative = previewPath(base.export_id);
225
+ const path = join(root, relative);
226
+ const read = readBounded(path);
227
+ if (!read)
228
+ return undefined;
229
+ const view = read.value;
230
+ if (!bound(view, PREVIEW_SCHEMA, binding) || !known(view, ["schema", "run", "run_instance_id", "command_id", "export_id", "captured_at", "source_updated_at", "coverage", "preview"]) ||
231
+ view.command_id !== base.command_id || view.export_id !== base.export_id || !timestamp(view.captured_at) || !timestamp(view.source_updated_at) || !coverage(view.coverage) || !validPreview(view.preview))
232
+ return undefined;
233
+ const parsed = view.preview;
234
+ const preview = Object.freeze({ ...parsed, coverage: COVERAGE, messages: Object.freeze(parsed.messages.map(message => Object.freeze({ ...message }))) });
235
+ return { path, stamp: read.stamp, preview, entry: Object.freeze({ export_id: base.export_id, command_id: base.command_id, captured_at: view.captured_at,
236
+ availability: "available", path: relative, media_type: "application/json", bytes_total: Number(read.stamp.size), mutable: true, coverage: COVERAGE }) };
237
+ }
238
+ catch {
239
+ return undefined;
240
+ }
241
+ }
242
+ function readCatalog(root, binding) {
243
+ const evidence = stamp(join(root, "evidence"));
244
+ if (evidence && (!evidence.isDirectory() || evidence.isSymbolicLink()))
245
+ throw new Error("Run session catalog directory is unavailable or invalid.");
246
+ const path = join(root, runContextExportPath("sessions"));
247
+ const existing = stamp(path);
248
+ if (!existing)
249
+ return { entries: [] };
250
+ const read = readBounded(path);
251
+ const value = read?.value;
252
+ const invalid = () => new Error("Run session catalog is unavailable, invalid or belongs to another generation.");
253
+ if (!read || !value || !bound(value, CATALOG_SCHEMA, binding) || !known(value, ["schema", "run", "run_instance_id", "updated_at", "inventory_scope", "inventory_complete", "coverage", "previews_total", "previews"]) ||
254
+ !timestamp(value.updated_at) || value.inventory_scope !== "published_previews" || value.inventory_complete !== false || !coverage(value.coverage) ||
255
+ !Array.isArray(value.previews) || value.previews_total !== value.previews.length)
256
+ throw invalid();
257
+ const ids = new Set();
258
+ const entries = [];
259
+ for (const item of value.previews) {
260
+ const row = record(item);
261
+ if (!row || typeof row.export_id !== "string" || !/^[a-f0-9]{64}$/u.test(row.export_id) || ids.has(row.export_id) || !command(row.command_id) || !timestamp(row.captured_at))
262
+ throw invalid();
263
+ ids.add(row.export_id);
264
+ const base = { export_id: row.export_id, command_id: row.command_id, captured_at: row.captured_at };
265
+ if (row.availability === "available" && known(row, ["export_id", "command_id", "captured_at", "availability", "path", "media_type", "bytes_total", "mutable", "coverage"]) &&
266
+ row.path === previewPath(row.export_id) && row.media_type === "application/json" && count(row.bytes_total) && row.bytes_total <= RUN_CONTEXT_SESSIONS_MAX_BYTES && row.mutable === true && coverage(row.coverage)) {
267
+ entries.push(Object.freeze({ ...base, availability: "available", path: row.path, media_type: "application/json", bytes_total: row.bytes_total, mutable: true, coverage: COVERAGE }));
268
+ }
269
+ else if (row.availability === "unavailable" && known(row, ["export_id", "command_id", "captured_at", "availability", "path", "reason"]) && row.path === null && row.reason === "preview_export_unavailable") {
270
+ entries.push(Object.freeze({ ...base, availability: "unavailable", path: null, reason: "preview_export_unavailable" }));
271
+ }
272
+ else
273
+ throw invalid();
274
+ }
275
+ return { entries, stamp: read.stamp };
276
+ }
277
+ function directory(path) {
278
+ let value = stamp(path);
279
+ if (!value) {
280
+ mkdirSync(path);
281
+ value = lstatSync(path, { bigint: true });
282
+ }
283
+ if (!value.isDirectory() || value.isSymbolicLink())
284
+ throw new Error("Run session export directory is unavailable or invalid.");
285
+ return value;
286
+ }
287
+ function targetUnchanged(path, expected) { const current = stamp(path); return expected ? !!current && sameFile(expected, current) : current === undefined; }
288
+ /** A real producer is required for both privacy capture and each subsequent evidence commit. */
289
+ export function writeRunSessionContextExport(stateDir, producer, query) {
290
+ const captured = withRunProducerEvidence(stateDir, producer, () => {
291
+ const selected = selection(query);
292
+ if (!selected)
293
+ return { status: "unavailable", reason: "request_invalid" };
294
+ const recipePrivacy = readRunProducerCapturedMetadata(producer, RUN_CONTEXT_SOURCE_METADATA_MAX_BYTES);
295
+ if (!recipePrivacy)
296
+ return { status: "unavailable", reason: "session_admission_unavailable" };
297
+ const identity = { run: producer.run, run_instance_id: producer.runInstanceId, ...(producer.ownerId !== undefined ? { ownerId: producer.ownerId } : {}) };
298
+ const metadataUnredacted = createContextIdentityPrivacyCheck(recipePrivacy);
299
+ if (!metadataUnredacted(identity))
300
+ return { status: "unavailable", reason: "session_identity_redacted" };
301
+ if (!metadataUnredacted({ command_id: selected.command_id }))
302
+ return { status: "unavailable", reason: "session_metadata_redacted" };
303
+ const read = readSelectedSessionPreview(stateDir, identity, selected, recipePrivacy);
304
+ if (read.state === "unavailable")
305
+ return { status: "unavailable", reason: read.reason };
306
+ const id = createHash("sha256").update(JSON.stringify([selected.command_id, selected.path])).digest("hex");
307
+ const capturedAt = new Date().toISOString();
308
+ const base = { export_id: id, command_id: selected.command_id, captured_at: capturedAt };
309
+ if (!metadataUnredacted(previewMetadata({ ...base, path: previewPath(id) })))
310
+ return { status: "unavailable", reason: "session_metadata_redacted" };
311
+ const content = JSON.stringify({ schema: PREVIEW_SCHEMA, run: producer.run, run_instance_id: producer.runInstanceId, command_id: selected.command_id,
312
+ export_id: id, captured_at: capturedAt, source_updated_at: read.source_updated_at, coverage: COVERAGE, preview: read.preview }, null, 2) + "\n";
313
+ if (Buffer.byteLength(content, "utf8") > RUN_CONTEXT_SESSIONS_MAX_BYTES)
314
+ return { status: "unavailable", reason: "session_view_too_large" };
315
+ return { status: "captured", content, base, unchanged: read.unchanged, metadataUnredacted };
316
+ });
317
+ if (captured.status === "unavailable")
318
+ return Object.freeze(captured);
319
+ return withRunProducerEvidence(stateDir, producer, () => {
320
+ const owner = readRunContextIdentity(stateDir, { run: producer.run, run_instance_id: producer.runInstanceId, ...(producer.ownerId !== undefined ? { ownerId: producer.ownerId } : {}) });
321
+ if (owner.state === "unavailable" || !captured.unchanged())
322
+ throw new Error("Run session export source or generation changed.");
323
+ const root = owner.local_path;
324
+ const evidencePath = join(root, "evidence");
325
+ const evidence = directory(evidencePath);
326
+ const prior = readCatalog(root, producer);
327
+ const retained = prior.entries.find(entry => entry.export_id === captured.base.export_id);
328
+ if (retained && retained.command_id !== captured.base.command_id)
329
+ throw new Error("Run session catalog binding contradicts the selected preview.");
330
+ // Only these bound peer fields survive every observation; old times/paths may legitimately refresh or disappear.
331
+ if (prior.entries.some(entry => entry.export_id !== captured.base.export_id &&
332
+ !captured.metadataUnredacted({ export_id: entry.export_id, command_id: entry.command_id }))) {
333
+ return Object.freeze({ status: "unavailable", reason: "session_metadata_redacted" });
334
+ }
335
+ const previewDirectory = join(evidencePath, "sessions");
336
+ const previews = directory(previewDirectory);
337
+ const frameUnchanged = () => {
338
+ const currentEvidence = lstatSync(evidencePath, { bigint: true });
339
+ const currentPreviews = lstatSync(previewDirectory, { bigint: true });
340
+ return owner.unchanged() && currentEvidence.isDirectory() && sameObject(evidence, currentEvidence) && currentPreviews.isDirectory() && sameObject(previews, currentPreviews);
341
+ };
342
+ const path = join(root, previewPath(captured.base.export_id));
343
+ const target = stamp(path);
344
+ if (target && !inspectPreview(root, captured.base, producer))
345
+ throw new Error("Run session preview binding is unavailable or invalid.");
346
+ writeTextAtomic(path, captured.content, { onBeforeReplace() {
347
+ if (!frameUnchanged() || !captured.unchanged() || !targetUnchanged(path, target))
348
+ throw new Error("Run session export binding or source changed before publication.");
349
+ } });
350
+ const bases = [...prior.entries.filter(entry => entry.export_id !== captured.base.export_id), captured.base];
351
+ const observations = [];
352
+ const entries = bases.map(base => {
353
+ const observed = inspectPreview(root, base, producer);
354
+ if (observed) {
355
+ observations.push(observed);
356
+ return observed.entry;
357
+ }
358
+ return Object.freeze({ export_id: base.export_id, command_id: base.command_id, captured_at: base.captured_at, availability: "unavailable", path: null, reason: "preview_export_unavailable" });
359
+ });
360
+ if (!observations.some(observed => observed.entry.export_id === captured.base.export_id))
361
+ throw new Error("Run session preview binding changed after publication.");
362
+ // The selected preview may already be committed; preserve it and the prior catalog on this distinct refusal.
363
+ if (entries.some(entry => !captured.metadataUnredacted(previewMetadata(entry)))) {
364
+ return Object.freeze({ status: "unavailable", reason: "session_metadata_redacted" });
365
+ }
366
+ const content = JSON.stringify({ schema: CATALOG_SCHEMA, run: producer.run, run_instance_id: producer.runInstanceId, updated_at: captured.base.captured_at,
367
+ inventory_scope: "published_previews", inventory_complete: false, coverage: COVERAGE, previews_total: entries.length, previews: entries }, null, 2) + "\n";
368
+ if (Buffer.byteLength(content, "utf8") > RUN_CONTEXT_SESSIONS_MAX_BYTES)
369
+ throw new Error("Run session catalog exceeds its bounded metadata limit.");
370
+ const catalogPath = join(root, runContextExportPath("sessions"));
371
+ writeTextAtomic(catalogPath, content, { onBeforeReplace() {
372
+ if (!frameUnchanged() || !captured.unchanged() || !targetUnchanged(catalogPath, prior.stamp) || observations.some(view => !sameFile(view.stamp, lstatSync(view.path, { bigint: true })))) {
373
+ throw new Error("Run session catalog references or source changed before publication.");
374
+ }
375
+ } });
376
+ const entry = Object.freeze({ availability: "available", path: runContextExportPath("sessions"), media_type: "application/json", bytes_total: Buffer.byteLength(content, "utf8"), mutable: true, coverage: COVERAGE });
377
+ return Object.freeze({ status: "written", captured_at: captured.base.captured_at, entry });
378
+ });
379
+ }
380
+ /** Preview, catalog and context index are separate effects; no failed phase rolls earlier commits back. */
381
+ export function writeRunSessionContextIndex(stateDir, producer, query) {
382
+ const view = writeRunSessionContextExport(stateDir, producer, query);
383
+ return withRunProducerEvidence(stateDir, producer, () => {
384
+ if (view.status === "written") {
385
+ const catalog = readCatalog(stateDir, producer);
386
+ for (const entry of catalog.entries) {
387
+ if (entry.availability !== "available")
388
+ continue;
389
+ const observed = inspectPreview(stateDir, entry, producer);
390
+ if (!observed || observed.entry.bytes_total !== entry.bytes_total || observed.entry.captured_at !== entry.captured_at) {
391
+ throw new Error("Run session catalog references changed before index publication.");
392
+ }
393
+ }
394
+ }
395
+ const entry = view.status === "written" ? view.entry : view.reason === "manifest_absent" ? { availability: "pending", path: null } : { availability: "unavailable", path: null, reason: view.reason };
396
+ const publication = writeRunContextIndexUnderLock(stateDir, { run: producer.run, run_instance_id: producer.runInstanceId, ...(producer.ownerId !== undefined ? { ownerId: producer.ownerId } : {}) }, { sessions: entry });
397
+ return Object.freeze({ status: "published", ...publication });
398
+ });
399
+ }
400
+ function readUnavailable(reason) { return Object.freeze({ state: "unavailable", reason }); }
401
+ /** Read only the selected published body: index metadata never substitutes for nested format/generation admission. */
402
+ export function readRunSessionContextPreview(stateDir, expected, exportId) {
403
+ if (typeof exportId !== "string" || !/^[a-f0-9]{64}$/u.test(exportId))
404
+ return readUnavailable("selection_invalid");
405
+ const owner = readRunContextIdentity(stateDir, expected);
406
+ if (owner.state === "unavailable")
407
+ return readUnavailable(owner.reason);
408
+ try {
409
+ const root = owner.local_path;
410
+ const indexPath = join(root, RUN_CONTEXT_INDEX_FILE);
411
+ const indexBefore = stamp(indexPath);
412
+ if (!indexBefore?.isFile())
413
+ return readUnavailable("index_unavailable");
414
+ const evidencePath = join(root, "evidence");
415
+ const evidence = stamp(evidencePath);
416
+ if (!evidence?.isDirectory() || evidence.isSymbolicLink())
417
+ return readUnavailable("sessions_unavailable");
418
+ const catalogPath = join(root, runContextExportPath("sessions"));
419
+ const catalogBefore = stamp(catalogPath);
420
+ const indexed = readRunContextIndex(root, owner.identity);
421
+ if (!owner.unchanged() || !targetUnchanged(indexPath, indexBefore))
422
+ return readUnavailable("observation_changed");
423
+ if (indexed.state === "unavailable")
424
+ return readUnavailable("index_unavailable");
425
+ const role = indexed.index.entries.sessions;
426
+ if (role.availability !== "available" || role.mutable !== true || !coverage(role.coverage))
427
+ return readUnavailable("sessions_unavailable");
428
+ if (!catalogBefore?.isFile() || catalogBefore.size !== BigInt(role.bytes_total))
429
+ return readUnavailable("catalog_unavailable");
430
+ const binding = { run: owner.identity.run, runInstanceId: owner.identity.run_instance_id };
431
+ const catalog = readCatalog(root, binding);
432
+ if (!catalog.stamp || !sameFile(catalogBefore, catalog.stamp))
433
+ return readUnavailable("observation_changed");
434
+ const selected = catalog.entries.find(entry => entry.export_id === exportId);
435
+ if (!selected)
436
+ return readUnavailable("preview_not_listed");
437
+ if (selected.availability !== "available")
438
+ return readUnavailable("preview_unavailable");
439
+ const previewDirectory = join(evidencePath, "sessions");
440
+ const previews = stamp(previewDirectory);
441
+ if (!previews?.isDirectory() || previews.isSymbolicLink())
442
+ return readUnavailable("preview_invalid");
443
+ const observed = inspectPreview(root, selected, binding);
444
+ if (!observed || observed.entry.bytes_total !== selected.bytes_total || observed.entry.captured_at !== selected.captured_at)
445
+ return readUnavailable("preview_invalid");
446
+ const unchanged = () => {
447
+ try {
448
+ const currentEvidence = lstatSync(evidencePath, { bigint: true });
449
+ const currentPreviews = lstatSync(previewDirectory, { bigint: true });
450
+ return owner.unchanged() && targetUnchanged(indexPath, indexBefore) && targetUnchanged(catalogPath, catalog.stamp) &&
451
+ currentEvidence.isDirectory() && sameObject(evidence, currentEvidence) && currentPreviews.isDirectory() && sameObject(previews, currentPreviews) &&
452
+ sameFile(observed.stamp, lstatSync(observed.path, { bigint: true }));
453
+ }
454
+ catch {
455
+ return false;
456
+ }
457
+ };
458
+ if (!unchanged())
459
+ return readUnavailable("observation_changed");
460
+ const result = Object.freeze({ state: "available", identity: owner.identity, export_id: selected.export_id, command_id: selected.command_id,
461
+ captured_at: selected.captured_at, path: observed.entry.path, media_type: observed.entry.media_type, bytes_total: observed.entry.bytes_total,
462
+ mutable: observed.entry.mutable, coverage: COVERAGE, preview: observed.preview, unchanged });
463
+ if (Buffer.byteLength(JSON.stringify(result), "utf8") > RUN_CONTEXT_SESSIONS_MAX_BYTES)
464
+ return readUnavailable("preview_too_large");
465
+ return result;
466
+ }
467
+ catch {
468
+ return readUnavailable("catalog_unavailable");
469
+ }
470
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Bounded Run observation projection.
3
+ * Owns: one data-only snapshot shape from already-admitted identity/lifecycle/timing facts.
4
+ * Excludes: evidence reads/admission, reference authorization/redaction, clocks, exports,
5
+ * lifecycle mutation, delivery acceptance, and native work/control/scope authority.
6
+ */
7
+ export interface RunSnapshotIdentity {
8
+ readonly run: string;
9
+ readonly run_instance_id: string;
10
+ readonly ownerId?: string;
11
+ }
12
+ /** Kernel read-model inputs, not raw Run metadata or serialized proof capabilities. */
13
+ export interface RunSnapshotFacts {
14
+ readonly identity: RunSnapshotIdentity;
15
+ readonly captured_at: string;
16
+ readonly timing: {
17
+ readonly basis: "live" | "terminal";
18
+ readonly elapsed_ms: number;
19
+ } | {
20
+ readonly basis: "unproven";
21
+ };
22
+ readonly lifecycle: {
23
+ readonly status: "running";
24
+ readonly phase?: "stopping";
25
+ } | {
26
+ readonly status: "done" | "failed";
27
+ } | {
28
+ readonly status: "unproven";
29
+ };
30
+ readonly cwd: string;
31
+ readonly context_index?: {
32
+ readonly identity: RunSnapshotIdentity;
33
+ readonly path: string;
34
+ };
35
+ }
36
+ export interface RunSnapshot {
37
+ readonly kind: "run_snapshot";
38
+ readonly run: string;
39
+ readonly run_instance_id: string;
40
+ readonly captured_at: string;
41
+ readonly elapsed_ms: number;
42
+ readonly status: "running" | "done" | "failed";
43
+ readonly phase?: "stopping";
44
+ readonly cwd: string;
45
+ readonly evidence: string | null;
46
+ readonly evidence_error?: "index_unavailable";
47
+ }
48
+ type SnapshotUnavailableReason = "identity_unavailable" | "identity_mismatch" | "observation_unavailable" | "lifecycle_unproven" | "timing_unproven" | "references_unavailable" | "snapshot_too_large";
49
+ export type RunSnapshotProjection = {
50
+ readonly state: "available";
51
+ readonly snapshot: Readonly<RunSnapshot>;
52
+ } | {
53
+ readonly state: "unavailable";
54
+ readonly reason: SnapshotUnavailableReason;
55
+ };
56
+ /** Facts and curated references must be admitted by their owners before projection; no I/O or authority is acquired here. */
57
+ export declare function projectRunSnapshot(expected: unknown, facts: unknown): Readonly<RunSnapshotProjection>;
58
+ export {};
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Bounded Run observation projection.
3
+ * Owns: one data-only snapshot shape from already-admitted identity/lifecycle/timing facts.
4
+ * Excludes: evidence reads/admission, reference authorization/redaction, clocks, exports,
5
+ * lifecycle mutation, delivery acceptance, and native work/control/scope authority.
6
+ */
7
+ import { RUN_DELIVERY_MODEL_MAX_BYTES } from "./limits.js";
8
+ function record(value) {
9
+ return value && typeof value === "object" && !Array.isArray(value)
10
+ ? value
11
+ : undefined;
12
+ }
13
+ function own(value, key) {
14
+ return value && Object.hasOwn(value, key) ? value[key] : undefined;
15
+ }
16
+ function boundedText(value) {
17
+ return typeof value === "string" && value.length > 0 && value.length <= RUN_DELIVERY_MODEL_MAX_BYTES;
18
+ }
19
+ function readIdentity(value) {
20
+ const source = record(value);
21
+ const run = own(source, "run");
22
+ const generation = own(source, "run_instance_id");
23
+ if (!boundedText(run) || /[^A-Za-z0-9_.-]/u.test(run) || !boundedText(generation))
24
+ return undefined;
25
+ if (source && Object.hasOwn(source, "ownerId")) {
26
+ if (!boundedText(source.ownerId))
27
+ return undefined;
28
+ return { run, run_instance_id: generation, ownerId: source.ownerId };
29
+ }
30
+ if (source?.ownerId !== undefined)
31
+ return undefined;
32
+ return { run, run_instance_id: generation };
33
+ }
34
+ function sameIdentity(left, right) {
35
+ return left.run === right.run && left.run_instance_id === right.run_instance_id && left.ownerId === right.ownerId;
36
+ }
37
+ function readableReference(value) {
38
+ return boundedText(value) && !/[\u0000-\u001f\u007f]/u.test(value);
39
+ }
40
+ function unavailable(reason) {
41
+ return Object.freeze({ state: "unavailable", reason });
42
+ }
43
+ /** Facts and curated references must be admitted by their owners before projection; no I/O or authority is acquired here. */
44
+ export function projectRunSnapshot(expected, facts) {
45
+ const expectedIdentity = readIdentity(expected);
46
+ const source = record(facts);
47
+ const identity = readIdentity(own(source, "identity"));
48
+ if (!expectedIdentity || !identity)
49
+ return unavailable("identity_unavailable");
50
+ if (!sameIdentity(expectedIdentity, identity))
51
+ return unavailable("identity_mismatch");
52
+ const capturedAt = own(source, "captured_at");
53
+ if (!boundedText(capturedAt))
54
+ return unavailable("observation_unavailable");
55
+ const capturedMs = Date.parse(capturedAt);
56
+ if (!Number.isSafeInteger(capturedMs) || new Date(capturedMs).toISOString() !== capturedAt) {
57
+ return unavailable("observation_unavailable");
58
+ }
59
+ const lifecycle = record(own(source, "lifecycle"));
60
+ const status = own(lifecycle, "status");
61
+ const phase = own(lifecycle, "phase");
62
+ if ((status !== "running" && status !== "done" && status !== "failed") ||
63
+ (phase !== undefined && (status !== "running" || phase !== "stopping"))) {
64
+ return unavailable("lifecycle_unproven");
65
+ }
66
+ const timing = record(own(source, "timing"));
67
+ const elapsedMs = own(timing, "elapsed_ms");
68
+ if (own(timing, "basis") !== (status === "running" ? "live" : "terminal") ||
69
+ typeof elapsedMs !== "number" || !Number.isSafeInteger(elapsedMs) || elapsedMs < 0) {
70
+ return unavailable("timing_unproven");
71
+ }
72
+ const cwd = own(source, "cwd");
73
+ if (typeof cwd === "string" && cwd.length > RUN_DELIVERY_MODEL_MAX_BYTES)
74
+ return unavailable("snapshot_too_large");
75
+ if (!readableReference(cwd))
76
+ return unavailable("references_unavailable");
77
+ const index = record(own(source, "context_index"));
78
+ const indexIdentity = readIdentity(own(index, "identity"));
79
+ const indexPath = own(index, "path");
80
+ const evidence = indexIdentity && sameIdentity(identity, indexIdentity) && readableReference(indexPath) ? indexPath : null;
81
+ const snapshot = Object.freeze({
82
+ kind: "run_snapshot", run: identity.run, run_instance_id: identity.run_instance_id,
83
+ captured_at: capturedAt, elapsed_ms: elapsedMs, status,
84
+ ...(phase === "stopping" ? { phase } : {}), cwd, evidence,
85
+ ...(evidence === null ? { evidence_error: "index_unavailable" } : {}),
86
+ });
87
+ // This is a row ceiling, not a second allowance: delivery still bounds the combined packet.
88
+ if (Buffer.byteLength(JSON.stringify(snapshot), "utf8") > RUN_DELIVERY_MODEL_MAX_BYTES) {
89
+ return unavailable("snapshot_too_large");
90
+ }
91
+ return Object.freeze({ state: "available", snapshot });
92
+ }
@@ -7,6 +7,8 @@ import { type FileMutationLockOptions } from "./file-state.ts";
7
7
  type RunJsonReader = (path: string) => Record<string, unknown> | undefined;
8
8
  export declare function readActiveOwnedRunState(stateDir: string, readJson: RunJsonReader, _runnerPath: string): Record<string, unknown> | undefined;
9
9
  export declare function assertNoActiveRunState(stateDir: string, readJson: RunJsonReader, runnerPath: string): void;
10
+ /** Prepare-only metadata must neither replace an earlier Run nor erase unrelated retained evidence. */
11
+ export declare function assertFreshRunPreparationState(stateDir: string): void;
10
12
  export declare function acquireStateStartLock(stateDir: string, options?: FileMutationLockOptions): () => void;
11
13
  export declare function prepareStateDirForStart(stateDir: string, readJson: RunJsonReader, _runnerPath: string): void;
12
14
  export {};