@timurproko/a1 0.1.8-dev.235df0e → 0.1.8-dev.259

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 (485) hide show
  1. package/README.md +107 -67
  2. package/bin/cli.js +28 -10
  3. package/bin/guardian.js +8 -3
  4. package/bin/module-identity.js +69 -35
  5. package/bin/pi-tui.d.ts +6 -0
  6. package/bin/pi-tui.js +28 -0
  7. package/bin/release-cleanup.js +8 -0
  8. package/bin/supervisor.js +2 -2
  9. package/bin/sync-pi-tui-proxy.js +97 -0
  10. package/bin/ui.js +47 -20
  11. package/bin/warmup.js +27 -0
  12. package/dist/cli/capabilities.d.ts +6 -0
  13. package/dist/{src/cli → cli}/capabilities.js +1 -1
  14. package/dist/{src/cli → cli}/dispatch.d.ts +15 -1
  15. package/dist/cli/dispatch.js +261 -0
  16. package/dist/cli/package-messages.d.ts +26 -0
  17. package/dist/cli/package-messages.js +71 -0
  18. package/dist/{src/cli → cli}/packages.d.ts +11 -2
  19. package/dist/{src/cli → cli}/packages.js +24 -27
  20. package/dist/{src/cli → cli}/version-stats.d.ts +6 -0
  21. package/dist/cli/version-stats.js +112 -0
  22. package/dist/composition/agent-engine-bridge.d.ts +3 -0
  23. package/dist/composition/agent-engine-bridge.js +108 -0
  24. package/dist/composition/index.d.ts +3 -0
  25. package/dist/composition/index.js +3 -0
  26. package/dist/composition/owned-ui.d.ts +31 -0
  27. package/dist/composition/owned-ui.js +66 -0
  28. package/dist/composition/process.d.ts +16 -0
  29. package/dist/composition/process.js +45 -0
  30. package/dist/composition/settings-route-host.d.ts +8 -0
  31. package/dist/composition/settings-route-host.js +75 -0
  32. package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/capability-ports.d.ts +2 -2
  33. package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/domain-validation.js +22 -4
  34. package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/domain.d.ts +17 -0
  35. package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/package-ports.d.ts +6 -0
  36. package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/model.d.ts +36 -0
  37. package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/validation.js +25 -0
  38. package/dist/{src/features → features}/launch/development-launch.js +11 -3
  39. package/dist/{src/features → features}/launch/index.d.ts +0 -1
  40. package/dist/{src/features → features}/launch/index.js +0 -1
  41. package/dist/features/launch/intent.d.ts +10 -0
  42. package/dist/features/launch/intent.js +8 -0
  43. package/dist/{src/features → features}/launch/prepare-launch.d.ts +0 -2
  44. package/dist/{src/features → features}/launch/prepare-launch.js +2 -9
  45. package/dist/{src/features → features}/launch/profile-paths.d.ts +1 -2
  46. package/dist/{src/features → features}/launch/profile-paths.js +2 -8
  47. package/dist/{src/features → features}/launch/runtime-selection.d.ts +2 -5
  48. package/dist/{src/features → features}/owned-ui/customization.d.ts +3 -1
  49. package/dist/{src/features → features}/owned-ui/customization.js +3 -1
  50. package/dist/{src/features → features}/owned-ui/diagnostics.d.ts +2 -1
  51. package/dist/{src/features → features}/owned-ui/diagnostics.js +1 -0
  52. package/dist/{src/features → features}/owned-ui/index.d.ts +2 -0
  53. package/dist/{src/features → features}/owned-ui/index.js +2 -0
  54. package/dist/features/owned-ui/project-trust-prompt.d.ts +25 -0
  55. package/dist/features/owned-ui/project-trust-prompt.js +149 -0
  56. package/dist/{src/features → features}/owned-ui/run.d.ts +2 -2
  57. package/dist/{src/features → features}/owned-ui/run.js +2 -0
  58. package/dist/features/owned-ui/session-fork-prompt.d.ts +8 -0
  59. package/dist/features/owned-ui/session-fork-prompt.js +34 -0
  60. package/dist/{src/features → features}/owned-ui/settings-app.d.ts +3 -3
  61. package/dist/{src/features → features}/owned-ui/settings-app.js +103 -54
  62. package/dist/{src/features → features}/workspace/capabilities.d.ts +1 -1
  63. package/dist/{src/features → features}/workspace/reducer.d.ts +2 -1
  64. package/dist/{src/features → features}/workspace/reducer.js +2 -1
  65. package/dist/{src/features → features}/workspace/router.d.ts +2 -1
  66. package/dist/{src/features → features}/workspace/router.js +1 -0
  67. package/dist/{src/features → features}/workspace/store.d.ts +2 -1
  68. package/dist/{src/features → features}/workspace/store.js +1 -0
  69. package/dist/{src/foundation → foundation}/launch-guardian/main.d.ts +2 -0
  70. package/dist/{src/foundation → foundation}/launch-guardian/main.js +18 -5
  71. package/dist/{src/foundation → foundation}/lifecycle/index.d.ts +2 -0
  72. package/dist/{src/foundation → foundation}/lifecycle/index.js +2 -0
  73. package/dist/{src/foundation → foundation}/lifecycle/model.d.ts +1 -1
  74. package/dist/{src/foundation → foundation}/lifecycle/model.js +1 -1
  75. package/dist/foundation/lifecycle/paths.d.ts +30 -0
  76. package/dist/{src/foundation → foundation}/lifecycle/paths.js +29 -1
  77. package/dist/foundation/lifecycle/session-selection.d.ts +9 -0
  78. package/dist/foundation/lifecycle/session-selection.js +39 -0
  79. package/dist/foundation/lifecycle/supervisor-startup.d.ts +30 -0
  80. package/dist/foundation/lifecycle/supervisor-startup.js +106 -0
  81. package/dist/{src/foundation → foundation}/native-host-protocol/codec.d.ts +2 -0
  82. package/dist/{src/foundation → foundation}/native-host-protocol/codec.js +2 -0
  83. package/dist/{src/foundation → foundation}/native-host-protocol/messages.d.ts +1 -1
  84. package/dist/{src/foundation → foundation}/native-host-protocol/messages.js +1 -1
  85. package/dist/foundation/process-containment/darwin-process-inspector.d.ts +5 -0
  86. package/dist/foundation/process-containment/darwin-process-inspector.js +7 -0
  87. package/dist/{src/foundation → foundation}/process-containment/index.d.ts +1 -0
  88. package/dist/{src/foundation → foundation}/process-containment/index.js +1 -0
  89. package/dist/{src/foundation → foundation}/process-containment/linux-process-inspector.d.ts +1 -0
  90. package/dist/{src/foundation → foundation}/process-containment/linux-process-inspector.js +1 -0
  91. package/dist/{src/foundation → foundation}/process-containment/native-guardian-containment.d.ts +1 -0
  92. package/dist/{src/foundation → foundation}/process-containment/native-guardian-containment.js +1 -0
  93. package/dist/{src/foundation → foundation}/process-containment/windows-process-inspector.d.ts +3 -1
  94. package/dist/{src/foundation → foundation}/process-containment/windows-process-inspector.js +5 -2
  95. package/dist/{src/foundation → foundation}/protocol/client.d.ts +1 -0
  96. package/dist/{src/foundation → foundation}/protocol/client.js +1 -0
  97. package/dist/{src/foundation → foundation}/protocol/messages.d.ts +1 -0
  98. package/dist/{src/foundation → foundation}/protocol/messages.js +1 -0
  99. package/dist/{src/foundation → foundation}/release/bootstrap.d.ts +23 -6
  100. package/dist/{src/foundation → foundation}/release/bootstrap.js +120 -34
  101. package/dist/foundation/release/cohort-state.d.ts +156 -0
  102. package/dist/foundation/release/cohort-state.js +471 -0
  103. package/dist/foundation/release/dependency-layer.d.ts +78 -0
  104. package/dist/foundation/release/dependency-layer.js +488 -0
  105. package/dist/foundation/release/endpoints.d.ts +20 -0
  106. package/dist/foundation/release/endpoints.js +50 -0
  107. package/dist/foundation/release/immutable-platform.d.ts +6 -0
  108. package/dist/foundation/release/immutable-platform.js +13 -0
  109. package/dist/{src/foundation → foundation}/release/index.d.ts +4 -0
  110. package/dist/{src/foundation → foundation}/release/index.js +4 -0
  111. package/dist/foundation/release/release-gc.d.ts +71 -0
  112. package/dist/foundation/release/release-gc.js +734 -0
  113. package/dist/{src/foundation → foundation}/release/release-store.d.ts +4 -2
  114. package/dist/{src/foundation → foundation}/release/release-store.js +64 -12
  115. package/dist/{src/foundation → foundation}/release/release.d.ts +4 -1
  116. package/dist/{src/foundation → foundation}/release/release.js +10 -3
  117. package/dist/foundation/release/restart-certification.d.ts +67 -0
  118. package/dist/foundation/release/restart-certification.js +211 -0
  119. package/dist/{src/foundation → foundation}/release/update-transaction.d.ts +1 -0
  120. package/dist/{src/foundation → foundation}/release/update-transaction.js +1 -0
  121. package/dist/{src/foundation → foundation}/release/update.d.ts +19 -3
  122. package/dist/{src/foundation → foundation}/release/update.js +116 -56
  123. package/dist/foundation/release/warmup.d.ts +3 -0
  124. package/dist/foundation/release/warmup.js +35 -0
  125. package/dist/foundation/startup/index.d.ts +1 -0
  126. package/dist/foundation/startup/index.js +1 -0
  127. package/dist/foundation/startup/startup-runtime.d.ts +36 -0
  128. package/dist/foundation/startup/startup-runtime.js +140 -0
  129. package/dist/{src/foundation → foundation}/storage/control-store.d.ts +2 -1
  130. package/dist/{src/foundation → foundation}/storage/control-store.js +39 -4
  131. package/dist/{src/foundation → foundation}/structured-agent-runtime/backpressure.d.ts +2 -1
  132. package/dist/{src/foundation → foundation}/structured-agent-runtime/backpressure.js +2 -1
  133. package/dist/{src/foundation → foundation}/structured-agent-runtime/commands.d.ts +2 -1
  134. package/dist/{src/foundation → foundation}/structured-agent-runtime/commands.js +2 -1
  135. package/dist/{src/foundation → foundation}/structured-agent-runtime/handshake.d.ts +1 -1
  136. package/dist/{src/foundation → foundation}/structured-agent-runtime/handshake.js +1 -1
  137. package/dist/{src/foundation → foundation}/structured-agent-runtime/reconnection.d.ts +2 -1
  138. package/dist/{src/foundation → foundation}/structured-agent-runtime/reconnection.js +2 -1
  139. package/dist/{src/foundation → foundation}/structured-agent-runtime/state.d.ts +2 -1
  140. package/dist/{src/foundation → foundation}/structured-agent-runtime/state.js +2 -1
  141. package/dist/foundation/supervision/index.d.ts +3 -0
  142. package/dist/foundation/supervision/index.js +3 -0
  143. package/dist/foundation/supervision/main.d.ts +1 -0
  144. package/dist/foundation/supervision/main.js +77 -0
  145. package/dist/foundation/supervision/paths.d.ts +1 -0
  146. package/dist/foundation/supervision/paths.js +1 -0
  147. package/dist/{src/foundation → foundation}/supervision/server.d.ts +19 -1
  148. package/dist/{src/foundation → foundation}/supervision/server.js +65 -3
  149. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/components.d.ts +1 -1
  150. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/conformance.d.ts +1 -0
  151. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/conformance.js +3 -2
  152. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/index.d.ts +1 -1
  153. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/index.js +1 -1
  154. package/dist/integrations/pi/components/owned-editor-ux.d.ts +55 -0
  155. package/dist/integrations/pi/components/owned-editor-ux.js +778 -0
  156. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-components.d.ts +1 -0
  157. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-components.js +1 -0
  158. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-editor-autocomplete.js +54 -6
  159. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-extension-ui.d.ts +1 -1
  160. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-footer-status.d.ts +3 -3
  161. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-footer-status.js +49 -18
  162. package/dist/integrations/pi/components/shell-presenters-info.d.ts +36 -0
  163. package/dist/integrations/pi/components/shell-presenters-info.js +78 -0
  164. package/dist/integrations/pi/components/shell-presenters-transcript.d.ts +25 -0
  165. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-presenters-transcript.js +92 -131
  166. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-selectors-dialogs.d.ts +5 -2
  167. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-selectors-dialogs.js +2 -1
  168. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-shared-facade.d.ts +57 -8
  169. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-shared-facade.js +4 -2
  170. package/dist/integrations/pi/components/submitted-prompt-adapter.d.ts +13 -0
  171. package/dist/integrations/pi/components/submitted-prompt-adapter.js +27 -0
  172. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/adjacent/core/keybindings.d.ts +10 -2
  173. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/adjacent/core/keybindings.js +36 -3
  174. package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-footer.d.ts +1 -1
  175. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/adapter.d.ts +28 -4
  176. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/adapter.js +714 -127
  177. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/conformance.d.ts +2 -0
  178. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/conformance.js +4 -2
  179. package/dist/integrations/pi/engine/http-dispatcher.d.ts +4 -0
  180. package/dist/integrations/pi/engine/http-dispatcher.js +25 -0
  181. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/index.d.ts +4 -0
  182. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/index.js +4 -0
  183. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/model-auth-integration.d.ts +2 -1
  184. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/model-auth-integration.js +1 -0
  185. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/package-integration.d.ts +1 -1
  186. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/package-integration.js +32 -26
  187. package/dist/integrations/pi/engine/project-trust-preflight.d.ts +22 -0
  188. package/dist/integrations/pi/engine/project-trust-preflight.js +50 -0
  189. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/resource-extension-integration.d.ts +2 -1
  190. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/resource-extension-integration.js +1 -0
  191. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/runtime-integration.d.ts +19 -1
  192. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/runtime-integration.js +47 -5
  193. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/session-integration.d.ts +4 -2
  194. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/session-integration.js +19 -4
  195. package/dist/integrations/pi/engine/session-selection.d.ts +28 -0
  196. package/dist/integrations/pi/engine/session-selection.js +90 -0
  197. package/dist/integrations/pi/engine/settings-effects.d.ts +66 -0
  198. package/dist/integrations/pi/engine/settings-effects.js +249 -0
  199. package/dist/integrations/pi/engine/settings-integration.d.ts +43 -0
  200. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/settings-integration.js +102 -108
  201. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/workflow-controllers.d.ts +3 -2
  202. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/workflow-controllers.js +1 -0
  203. package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/workflows.d.ts +18 -1
  204. package/dist/integrations/pi/session-ui/clipboard-image.d.ts +11 -0
  205. package/dist/integrations/pi/session-ui/clipboard-image.js +29 -0
  206. package/dist/{src/foundation/pi-owned-ui-integration → integrations/pi/session-ui}/index.d.ts +1 -0
  207. package/dist/{src/foundation/pi-owned-ui-integration → integrations/pi/session-ui}/index.js +1 -0
  208. package/dist/integrations/pi/session-ui/prompt-chips.d.ts +23 -0
  209. package/dist/integrations/pi/session-ui/prompt-chips.js +246 -0
  210. package/dist/integrations/pi/session-ui/route-host.d.ts +5 -0
  211. package/dist/integrations/pi/session-ui/session-shell-root.d.ts +141 -0
  212. package/dist/integrations/pi/session-ui/session-shell-root.js +1158 -0
  213. package/dist/integrations/pi/session-ui/session-shell.d.ts +55 -0
  214. package/dist/{src/foundation/pi-owned-ui-integration → integrations/pi/session-ui}/session-shell.js +479 -719
  215. package/dist/integrations/pi/session-ui/session-viewport-controller.d.ts +45 -0
  216. package/dist/integrations/pi/session-ui/session-viewport-controller.js +463 -0
  217. package/dist/integrations/pi/session-ui/stream-presentation-coalescer.d.ts +29 -0
  218. package/dist/integrations/pi/session-ui/stream-presentation-coalescer.js +79 -0
  219. package/dist/integrations/pi/session-ui/system-clipboard.d.ts +20 -0
  220. package/dist/integrations/pi/session-ui/system-clipboard.js +130 -0
  221. package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/adapter.d.ts +8 -1
  222. package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/adapter.js +216 -9
  223. package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/contracts.d.ts +29 -6
  224. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +74 -0
  225. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +380 -0
  226. package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/index.d.ts +2 -0
  227. package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/index.js +2 -0
  228. package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.d.ts +39 -0
  229. package/dist/integrations/pi/tui-runtime/input-presentation-coordinator.js +139 -0
  230. package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/presentation-adapter.d.ts +1 -1
  231. package/dist/native/darwin-arm64/manifest.json +4 -4
  232. package/dist/native/darwin-arm64/process-guardian +0 -0
  233. package/dist/native/linux-x64/manifest.json +3 -3
  234. package/dist/native/linux-x64/process-guardian +0 -0
  235. package/dist/native/win32-x64/manifest.json +3 -3
  236. package/dist/native/win32-x64/process-guardian.exe +0 -0
  237. package/dist/{src/product-identity.d.ts → product-identity.d.ts} +3 -3
  238. package/dist/{src/product-identity.js → product-identity.js} +7 -5
  239. package/dist/{src/product-identity.json → product-identity.json} +11 -6
  240. package/dist/runtime-payload-inventory.json +122328 -0
  241. package/dist/{src/foundation/ui-apps → ui/apps}/contracts.d.ts +23 -1
  242. package/dist/{src/foundation/ui-apps → ui/apps}/host.d.ts +1 -1
  243. package/dist/{src/foundation/ui-apps → ui/apps}/host.js +14 -10
  244. package/dist/{src/foundation/ui-apps → ui/apps}/registry.d.ts +1 -0
  245. package/dist/{src/foundation/ui-apps → ui/apps}/registry.js +1 -0
  246. package/dist/{src/foundation/ui-components → ui/components}/dialog-panel.js +5 -3
  247. package/dist/{src/foundation/ui-components → ui/components}/frame.d.ts +1 -0
  248. package/dist/{src/foundation/ui-components → ui/components}/frame.js +1 -0
  249. package/dist/{src/foundation/ui-components → ui/components}/index.d.ts +5 -0
  250. package/dist/{src/foundation/ui-components → ui/components}/index.js +5 -0
  251. package/dist/{src/foundation/ui-components → ui/components}/line-input.d.ts +1 -6
  252. package/dist/{src/foundation/ui-components → ui/components}/line-input.js +4 -9
  253. package/dist/{src/foundation/ui-components → ui/components}/list-view.d.ts +0 -6
  254. package/dist/{src/foundation/ui-components → ui/components}/list-view.js +14 -7
  255. package/dist/{src/foundation/ui-components → ui/components}/mouse.d.ts +10 -0
  256. package/dist/{src/foundation/ui-components → ui/components}/mouse.js +23 -0
  257. package/dist/ui/components/progress-status.d.ts +2 -0
  258. package/dist/ui/components/progress-status.js +4 -0
  259. package/dist/ui/components/prompt-row.d.ts +14 -0
  260. package/dist/ui/components/prompt-row.js +20 -0
  261. package/dist/{src/foundation/ui-components → ui/components}/scrollbar.d.ts +26 -0
  262. package/dist/{src/foundation/ui-components → ui/components}/scrollbar.js +35 -0
  263. package/dist/{src/foundation/ui-components → ui/components}/shortcuts.d.ts +1 -0
  264. package/dist/{src/foundation/ui-components → ui/components}/shortcuts.js +1 -0
  265. package/dist/ui/components/spans.d.ts +25 -0
  266. package/dist/ui/components/spans.js +257 -0
  267. package/dist/ui/components/submitted-prompt.d.ts +23 -0
  268. package/dist/ui/components/submitted-prompt.js +50 -0
  269. package/dist/{src/foundation/ui-components → ui/components}/surface.d.ts +0 -5
  270. package/dist/{src/foundation/ui-components → ui/components}/surface.js +1 -5
  271. package/dist/ui/components/text-selection.d.ts +62 -0
  272. package/dist/ui/components/text-selection.js +208 -0
  273. package/dist/{src/foundation/ui-components → ui/components}/text.d.ts +14 -0
  274. package/dist/{src/foundation/ui-components → ui/components}/text.js +66 -4
  275. package/dist/ui/components/transcript-viewport.d.ts +152 -0
  276. package/dist/ui/components/transcript-viewport.js +631 -0
  277. package/dist/ui/components/visible-hyperlinks.d.ts +19 -0
  278. package/dist/ui/components/visible-hyperlinks.js +64 -0
  279. package/dist/{src/foundation/owned-ui-settings → ui/settings}/declarations.d.ts +8 -1
  280. package/dist/{src/foundation/owned-ui-settings → ui/settings}/declarations.js +33 -5
  281. package/dist/{src/foundation/owned-ui-settings → ui/settings}/migrations.d.ts +1 -1
  282. package/dist/{src/foundation/owned-ui-settings → ui/settings}/migrations.js +21 -2
  283. package/dist/{src/foundation/owned-ui-settings → ui/settings}/sections.d.ts +6 -19
  284. package/dist/{src/foundation/owned-ui-settings → ui/settings}/sections.js +32 -23
  285. package/dist/{src/foundation/owned-ui-settings → ui/settings}/session.d.ts +9 -17
  286. package/dist/{src/foundation/owned-ui-settings → ui/settings}/session.js +65 -55
  287. package/dist/{src/foundation/owned-ui-settings → ui/settings}/store.d.ts +1 -0
  288. package/dist/{src/foundation/owned-ui-settings → ui/settings}/store.js +2 -1
  289. package/docs/architecture/boundaries.md +9 -9
  290. package/docs/architecture/code-documentation.md +77 -0
  291. package/docs/architecture/process-guardian-provenance.md +3 -1
  292. package/docs/architecture/project-structure.md +67 -30
  293. package/docs/architecture/resource-and-data-policy.md +1 -1
  294. package/docs/architecture/toolchain.md +10 -10
  295. package/docs/architecture/ui-reference-provenance.md +36 -5
  296. package/docs/ci-release-runbook.md +186 -79
  297. package/docs/features/launch-profiles.md +24 -17
  298. package/docs/manual-ghost-link-baseline.md +89 -0
  299. package/docs/manual-launch-instance-acceptance.md +12 -35
  300. package/docs/manual-owned-ui-checkpoint.md +78 -0
  301. package/docs/manual-pi-boundary-candidate.md +4 -5
  302. package/docs/manual-terminal-colour-check.md +4 -3
  303. package/docs/repository-governance-live-acceptance.md +77 -0
  304. package/package.json +37 -27
  305. package/dist/src/cli/capabilities.d.ts +0 -15
  306. package/dist/src/cli/dispatch.js +0 -177
  307. package/dist/src/cli/version-stats.js +0 -72
  308. package/dist/src/composition/index.d.ts +0 -48
  309. package/dist/src/composition/index.js +0 -258
  310. package/dist/src/features/launch/intent.d.ts +0 -7
  311. package/dist/src/features/launch/intent.js +0 -4
  312. package/dist/src/features/launch/profiles.d.ts +0 -12
  313. package/dist/src/features/launch/profiles.js +0 -26
  314. package/dist/src/foundation/lifecycle/paths.d.ts +0 -10
  315. package/dist/src/foundation/pi-component-adapter/shell-presenters-transcript.d.ts +0 -57
  316. package/dist/src/foundation/pi-engine-adapter/settings-integration.d.ts +0 -55
  317. package/dist/src/foundation/pi-owned-ui-integration/route-host.d.ts +0 -29
  318. package/dist/src/foundation/pi-owned-ui-integration/session-shell.d.ts +0 -106
  319. package/dist/src/foundation/release/cohort-state.d.ts +0 -70
  320. package/dist/src/foundation/release/cohort-state.js +0 -202
  321. package/dist/src/foundation/release/release-gc.d.ts +0 -5
  322. package/dist/src/foundation/release/release-gc.js +0 -16
  323. package/dist/src/foundation/supervision/index.d.ts +0 -3
  324. package/dist/src/foundation/supervision/index.js +0 -3
  325. package/dist/src/foundation/supervision/main.d.ts +0 -1
  326. package/dist/src/foundation/supervision/main.js +0 -41
  327. package/dist/src/foundation/supervision/paths.d.ts +0 -1
  328. package/dist/src/foundation/supervision/paths.js +0 -1
  329. package/dist/src/foundation/ui-components/spans.d.ts +0 -7
  330. package/dist/src/foundation/ui-components/spans.js +0 -59
  331. package/docs/manual-transparent-checkpoint.md +0 -53
  332. /package/dist/{src/cli → cli}/index.d.ts +0 -0
  333. /package/dist/{src/cli → cli}/index.js +0 -0
  334. /package/dist/{src/cli → cli}/version.d.ts +0 -0
  335. /package/dist/{src/cli → cli}/version.js +0 -0
  336. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/capability-ports.js +0 -0
  337. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/domain-validation.d.ts +0 -0
  338. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/domain.js +0 -0
  339. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/index.d.ts +0 -0
  340. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/index.js +0 -0
  341. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/model.d.ts +0 -0
  342. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/model.js +0 -0
  343. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/package-ports.js +0 -0
  344. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/ports.d.ts +0 -0
  345. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/ports.js +0 -0
  346. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/serialization.d.ts +0 -0
  347. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/serialization.js +0 -0
  348. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/validation.d.ts +0 -0
  349. /package/dist/{src/foundation/agent-engine-contracts → contracts/agent-engine}/validation.js +0 -0
  350. /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/extension-ui.d.ts +0 -0
  351. /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/extension-ui.js +0 -0
  352. /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/index.d.ts +0 -0
  353. /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/index.js +0 -0
  354. /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/model.js +0 -0
  355. /package/dist/{src/foundation/owned-ui-contracts → contracts/owned-ui}/validation.d.ts +0 -0
  356. /package/dist/{src/foundation/presentation-contracts → contracts/presentation}/index.d.ts +0 -0
  357. /package/dist/{src/foundation/presentation-contracts → contracts/presentation}/index.js +0 -0
  358. /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/index.d.ts +0 -0
  359. /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/index.js +0 -0
  360. /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/model.d.ts +0 -0
  361. /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/model.js +0 -0
  362. /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/validation.d.ts +0 -0
  363. /package/dist/{src/foundation/workspace-contracts → contracts/workspace}/validation.js +0 -0
  364. /package/dist/{src/features → features}/launch/development-launch.d.ts +0 -0
  365. /package/dist/{src/features → features}/launch/initialize-profile.d.ts +0 -0
  366. /package/dist/{src/features → features}/launch/initialize-profile.js +0 -0
  367. /package/dist/{src/features → features}/launch/runtime-selection.js +0 -0
  368. /package/dist/{src/features → features}/workspace/capabilities.js +0 -0
  369. /package/dist/{src/features → features}/workspace/index.d.ts +0 -0
  370. /package/dist/{src/features → features}/workspace/index.js +0 -0
  371. /package/dist/{src/features → features}/workspace/presentation.d.ts +0 -0
  372. /package/dist/{src/features → features}/workspace/presentation.js +0 -0
  373. /package/dist/{src/features → features}/workspace/reconciliation.d.ts +0 -0
  374. /package/dist/{src/features → features}/workspace/reconciliation.js +0 -0
  375. /package/dist/{src/foundation → foundation}/launch-guardian/index.d.ts +0 -0
  376. /package/dist/{src/foundation → foundation}/launch-guardian/index.js +0 -0
  377. /package/dist/{src/foundation → foundation}/lifecycle/commands.d.ts +0 -0
  378. /package/dist/{src/foundation → foundation}/lifecycle/commands.js +0 -0
  379. /package/dist/{src/foundation → foundation}/lifecycle/launch-instance.d.ts +0 -0
  380. /package/dist/{src/foundation → foundation}/lifecycle/launch-instance.js +0 -0
  381. /package/dist/{src/foundation → foundation}/native-host-protocol/evidence.d.ts +0 -0
  382. /package/dist/{src/foundation → foundation}/native-host-protocol/evidence.js +0 -0
  383. /package/dist/{src/foundation → foundation}/native-host-protocol/index.d.ts +0 -0
  384. /package/dist/{src/foundation → foundation}/native-host-protocol/index.js +0 -0
  385. /package/dist/{src/foundation → foundation}/native-host-protocol/proof-gate.d.ts +0 -0
  386. /package/dist/{src/foundation → foundation}/native-host-protocol/proof-gate.js +0 -0
  387. /package/dist/{src/foundation → foundation}/process-containment/artifact.d.ts +0 -0
  388. /package/dist/{src/foundation → foundation}/process-containment/artifact.js +0 -0
  389. /package/dist/{src/foundation → foundation}/process-containment/contracts.d.ts +0 -0
  390. /package/dist/{src/foundation → foundation}/process-containment/contracts.js +0 -0
  391. /package/dist/{src/foundation → foundation}/protocol/index.d.ts +0 -0
  392. /package/dist/{src/foundation → foundation}/protocol/index.js +0 -0
  393. /package/dist/{src/foundation → foundation}/release/cohort-selection.d.ts +0 -0
  394. /package/dist/{src/foundation → foundation}/release/cohort-selection.js +0 -0
  395. /package/dist/{src/foundation → foundation}/release/concurrency.d.ts +0 -0
  396. /package/dist/{src/foundation → foundation}/release/concurrency.js +0 -0
  397. /package/dist/{src/foundation → foundation}/release/process-cleanup.d.ts +0 -0
  398. /package/dist/{src/foundation → foundation}/release/process-cleanup.js +0 -0
  399. /package/dist/{src/foundation → foundation}/release/stable-release.d.ts +0 -0
  400. /package/dist/{src/foundation → foundation}/release/stable-release.js +0 -0
  401. /package/dist/{src/foundation → foundation}/storage/index.d.ts +0 -0
  402. /package/dist/{src/foundation → foundation}/storage/index.js +0 -0
  403. /package/dist/{src/foundation → foundation}/structured-agent-runtime/index.d.ts +0 -0
  404. /package/dist/{src/foundation → foundation}/structured-agent-runtime/index.js +0 -0
  405. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/components.js +0 -0
  406. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/resources/builtin-themes.d.ts +0 -0
  407. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/resources/builtin-themes.js +0 -0
  408. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-editor-autocomplete.d.ts +0 -0
  409. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/shell-extension-ui.js +0 -0
  410. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/theme.d.ts +0 -0
  411. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/theme.js +0 -0
  412. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/countdown-timer.d.ts +0 -0
  413. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/countdown-timer.js +0 -0
  414. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/custom-entry.d.ts +0 -0
  415. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/custom-entry.js +0 -0
  416. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/daxnuts.d.ts +0 -0
  417. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/daxnuts.js +0 -0
  418. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/earendil-announcement.d.ts +0 -0
  419. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/earendil-announcement.js +0 -0
  420. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/extension-editor.d.ts +0 -0
  421. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/extension-editor.js +0 -0
  422. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/first-time-setup.d.ts +0 -0
  423. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/first-time-setup.js +0 -0
  424. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/markdown-transform.d.ts +0 -0
  425. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/markdown-transform.js +0 -0
  426. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/mermaid.d.ts +0 -0
  427. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/mermaid.js +0 -0
  428. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/owned-editor.d.ts +0 -0
  429. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/owned-editor.js +0 -0
  430. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/scoped-models-selector.d.ts +0 -0
  431. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/scoped-models-selector.js +0 -0
  432. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-footer.js +0 -0
  433. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-selector-search.d.ts +0 -0
  434. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-selector-search.js +0 -0
  435. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-selector.d.ts +0 -0
  436. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/session-selector.js +0 -0
  437. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/skill-invocation-message.d.ts +0 -0
  438. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/skill-invocation-message.js +0 -0
  439. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/status-indicator.d.ts +0 -0
  440. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/status-indicator.js +0 -0
  441. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/tree-selector.d.ts +0 -0
  442. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/tree-selector.js +0 -0
  443. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/trust-selector.d.ts +0 -0
  444. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/components/trust-selector.js +0 -0
  445. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/external-editor.d.ts +0 -0
  446. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/external-editor.js +0 -0
  447. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/model-search.d.ts +0 -0
  448. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/model-search.js +0 -0
  449. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/theme/theme-controller.d.ts +0 -0
  450. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/theme/theme-controller.js +0 -0
  451. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/theme/theme.d.ts +0 -0
  452. /package/dist/{src/foundation/pi-component-adapter → integrations/pi/components}/upstream/theme/theme.js +0 -0
  453. /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/pi-settings-metadata.json +0 -0
  454. /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/public-main-entry.d.ts +0 -0
  455. /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/public-main-entry.js +0 -0
  456. /package/dist/{src/foundation/pi-engine-adapter → integrations/pi/engine}/workflows.js +0 -0
  457. /package/dist/{src/foundation/pi-owned-ui-integration → integrations/pi/session-ui}/route-host.js +0 -0
  458. /package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/conformance.d.ts +0 -0
  459. /package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/conformance.js +0 -0
  460. /package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/contracts.js +0 -0
  461. /package/dist/{src/foundation/pi-tui-runtime-adapter → integrations/pi/tui-runtime}/presentation-adapter.js +0 -0
  462. /package/dist/{src/foundation/ui-apps → ui/apps}/contracts.js +0 -0
  463. /package/dist/{src/foundation/ui-apps → ui/apps}/index.d.ts +0 -0
  464. /package/dist/{src/foundation/ui-apps → ui/apps}/index.js +0 -0
  465. /package/dist/{src/foundation/ui-components → ui/components}/dialog-panel.d.ts +0 -0
  466. /package/dist/{src/foundation/ui-components → ui/components}/label.d.ts +0 -0
  467. /package/dist/{src/foundation/ui-components → ui/components}/label.js +0 -0
  468. /package/dist/{src/foundation/ui-components → ui/components}/list-block.d.ts +0 -0
  469. /package/dist/{src/foundation/ui-components → ui/components}/list-block.js +0 -0
  470. /package/dist/{src/foundation/ui-components → ui/components}/pane.d.ts +0 -0
  471. /package/dist/{src/foundation/ui-components → ui/components}/pane.js +0 -0
  472. /package/dist/{src/foundation/ui-components → ui/components}/revision.d.ts +0 -0
  473. /package/dist/{src/foundation/ui-components → ui/components}/revision.js +0 -0
  474. /package/dist/{src/foundation/ui-components → ui/components}/status-line.d.ts +0 -0
  475. /package/dist/{src/foundation/ui-components → ui/components}/status-line.js +0 -0
  476. /package/dist/{src/foundation/ui-components → ui/components}/stepper.d.ts +0 -0
  477. /package/dist/{src/foundation/ui-components → ui/components}/stepper.js +0 -0
  478. /package/dist/{src/foundation/ui-components → ui/components}/theme.d.ts +0 -0
  479. /package/dist/{src/foundation/ui-components → ui/components}/theme.js +0 -0
  480. /package/dist/{src/foundation/ui-components → ui/components}/value-menu.d.ts +0 -0
  481. /package/dist/{src/foundation/ui-components → ui/components}/value-menu.js +0 -0
  482. /package/dist/{src/foundation/owned-ui-settings → ui/settings}/index.d.ts +0 -0
  483. /package/dist/{src/foundation/owned-ui-settings → ui/settings}/index.js +0 -0
  484. /package/dist/{src/foundation/owned-ui-settings → ui/settings}/resolution.d.ts +0 -0
  485. /package/dist/{src/foundation/owned-ui-settings → ui/settings}/resolution.js +0 -0
@@ -6,21 +6,16 @@ import crossSpawn from "cross-spawn";
6
6
  import { valid as validSemver } from "semver";
7
7
  import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
8
8
  import { certifyMaterializedRelease, probeOwnership, readEndpointMetadata, removeEndpointArtifacts, startSupervisor, waitForProcessExit, waitForVerifiedEndpoint, } from "./bootstrap.js";
9
- import { resolveProductPaths } from "../lifecycle/index.js";
9
+ import { resolveCohortEndpoint, resolveProductPaths } from "../lifecycle/index.js";
10
10
  import { encodeFrame, LineFrameDecoder } from "../protocol/index.js";
11
11
  import { CohortStateStore } from "./cohort-state.js";
12
12
  import { cleanupVerifiedOwner, processIsAlive } from "./process-cleanup.js";
13
13
  import { materializeRelease, readMaterializedRelease } from "./release-store.js";
14
+ import { scheduleReleaseCleanup } from "./release-gc.js";
15
+ import { warmMaterializedRelease } from "./warmup.js";
14
16
  import { UpdateTransactionStore } from "./update-transaction.js";
15
17
  export const PRODUCT_PACKAGE = PRODUCT_TEXT.packageName;
16
18
  const UPDATE_DIST_TAGS = { stable: "latest", next: "next" };
17
- /**
18
- * What each channel is called when A1 says it out loud. The internal name stays
19
- * `stable` because that is what the channel is, but what a reader is moving to is
20
- * a release, and that is the word the repository, its tags, and its GitHub
21
- * releases all use.
22
- */
23
- const UPDATE_CHANNEL_LABELS = { stable: "release", next: "next" };
24
19
  const defaultFileSystem = {
25
20
  async readFile(path) { return await readFile(path, "utf8"); },
26
21
  realpath,
@@ -47,6 +42,33 @@ export function createNpmProcessRunner(platform = process.platform) {
47
42
  } });
48
43
  });
49
44
  }
45
+ /**
46
+ * What an update does about the owner it found. A cohort running from retained immutable
47
+ * content keeps its work: the installation replaces files it does not read, and it listens on
48
+ * its own endpoint. A cohort running from the mutable installation is the one exception,
49
+ * because that installation is exactly what is about to be replaced under it.
50
+ */
51
+ export function planUpdateOwnership(ownership, runsFromRetainedRelease) {
52
+ if (ownership === "dead")
53
+ return "clean-dead-record";
54
+ return runsFromRetainedRelease ? "leave-running" : "end-session";
55
+ }
56
+ /**
57
+ * The endpoint of the active cohort, together with where it is recorded, so a caller that
58
+ * finds it can also clean it up. A release that predates cohort-scoped endpoints published
59
+ * one endpoint for the runtime directory, and that one is recognized too.
60
+ */
61
+ async function readActiveEndpoint(paths, activeReleaseId, environment) {
62
+ if (activeReleaseId !== null) {
63
+ const cohort = resolveCohortEndpoint(paths, activeReleaseId, environment);
64
+ const metadata = await readEndpointMetadata(cohort.endpointMetadataPath);
65
+ if (metadata)
66
+ return { metadata, paths: cohort };
67
+ }
68
+ const legacyPaths = { endpoint: paths.endpoint, endpointMetadataPath: paths.endpointMetadataPath };
69
+ const legacy = await readEndpointMetadata(legacyPaths.endpointMetadataPath);
70
+ return legacy ? { metadata: legacy, paths: legacyPaths } : null;
71
+ }
50
72
  export function createUpdateLifecycleCoordinator(environment = process.env, fileSystem = defaultFileSystem, output = defaultOutput) {
51
73
  const paths = resolveProductPaths(environment);
52
74
  const stateStore = new CohortStateStore(paths.dataDir);
@@ -56,45 +78,51 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
56
78
  const activeId = state.references.active;
57
79
  if (!activeId || state.releases[activeId]?.packageVersion !== targetVersion)
58
80
  return false;
59
- const endpoint = await readEndpointMetadata(paths.endpointMetadataPath);
60
- return endpoint?.releaseId === activeId && await probeOwnership(endpoint) === "live-verified";
81
+ const endpoint = await readActiveEndpoint(paths, activeId, environment);
82
+ return endpoint?.metadata.releaseId === activeId && await probeOwnership(endpoint.metadata) === "live-verified";
61
83
  },
62
84
  async shutdownVerifiedOwners(targetVersion) {
63
85
  const state = await stateStore.read();
64
- const priorActiveVersion = state.references.active ? state.releases[state.references.active]?.packageVersion ?? null : null;
65
- const endpoint = await readEndpointMetadata(paths.endpointMetadataPath);
66
- if (!endpoint)
86
+ const activeId = state.references.active;
87
+ const priorActiveVersion = activeId ? state.releases[activeId]?.packageVersion ?? null : null;
88
+ const owner = await readActiveEndpoint(paths, activeId, environment);
89
+ if (!owner)
67
90
  return { priorActiveVersion };
91
+ const endpoint = owner.metadata;
68
92
  const ownership = await probeOwnership(endpoint);
69
93
  if (ownership !== "live-verified" && ownership !== "dead") {
70
94
  throw new Error(PRODUCT_TEXT.diagnostic(`refused update shutdown because supervisor ownership is ${ownership}`));
71
95
  }
72
- const immutableRoot = await canonicalImmutableRoot(paths.dataDir, endpoint.releaseRoot);
73
- const legacyMutableInstall = ownership === "live-verified" && !immutableRoot;
74
- const identity = ownership === "dead"
75
- ? { accepted: false, reason: "recorded owner is dead" }
76
- : await requestUpdateShutdown(endpoint, targetVersion, 2_000);
96
+ const plan = planUpdateOwnership(ownership, await canonicalImmutableRoot(paths.dataDir, endpoint.releaseRoot));
97
+ if (plan === "clean-dead-record") {
98
+ await removeEndpointArtifacts(owner.paths.endpointMetadataPath, owner.paths.endpoint);
99
+ return { priorActiveVersion };
100
+ }
101
+ // Rationale: leaving sessions alone is the expected outcome, and saying so mid-update tears
102
+ // the progress bar; only ending a session (below) is worth interrupting it for.
103
+ if (plan === "leave-running")
104
+ return { priorActiveVersion };
105
+ // Rationale: say whose work is ending before it ends.
106
+ const live = endpoint.ownership.liveInstanceIds.length;
107
+ if (live > 0) {
108
+ output.stderr(`${PRODUCT_TEXT.diagnostic(`ending ${live === 1 ? "one session" : `${live} sessions`} that run from the installation being replaced; a session started by an installed release would have been left alone.`)}\n`);
109
+ }
110
+ const identity = await requestUpdateShutdown(endpoint, targetVersion, 2_000);
77
111
  if (!identity.accepted && processIsAlive(endpoint.pid)) {
78
- // Explicit update consent permits bounded cleanup of an authenticated
112
+ // Security: explicit update consent permits bounded cleanup of an authenticated
79
113
  // older owner that predates the update-shutdown message.
80
- const cleanup = await cleanupVerifiedOwner(endpoint, {
81
- allowLiveInstances: true,
82
- reason: legacyMutableInstall ? "legacy-mutable-install" : "explicit-update",
83
- });
114
+ const cleanup = await cleanupVerifiedOwner(endpoint, { allowLiveInstances: true, reason: "legacy-mutable-install" });
84
115
  if (!cleanup.terminated)
85
116
  throw new Error(`verified ${PRODUCT_TEXT.displayName} owner ${endpoint.pid} rejected shutdown and could not be terminated: ${identity.reason}`);
86
117
  }
87
118
  else if (identity.accepted) {
88
119
  await waitForProcessExit(endpoint.pid, 3_000).catch(async () => {
89
- const cleanup = await cleanupVerifiedOwner(endpoint, {
90
- allowLiveInstances: true,
91
- reason: legacyMutableInstall ? "legacy-mutable-install" : "explicit-update",
92
- });
120
+ const cleanup = await cleanupVerifiedOwner(endpoint, { allowLiveInstances: true, reason: "legacy-mutable-install" });
93
121
  if (!cleanup.terminated)
94
122
  throw new Error(`verified ${PRODUCT_TEXT.displayName} owner ${endpoint.pid} did not terminate`);
95
123
  });
96
124
  }
97
- await removeEndpointArtifacts(paths.endpointMetadataPath, paths.endpoint);
125
+ await removeEndpointArtifacts(owner.paths.endpointMetadataPath, owner.paths.endpoint);
98
126
  return { priorActiveVersion };
99
127
  },
100
128
  async verifyPackageUnlocked(packageRoot) {
@@ -107,12 +135,12 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
107
135
  await rename(probe, packageRoot);
108
136
  }
109
137
  catch (error) {
110
- // Best-effort rollback if the first rename succeeded and the second did not.
138
+ // Invariant: best-effort rollback runs if the first rename succeeded and the second did not.
111
139
  await rename(probe, packageRoot).catch(() => { });
112
140
  throw new Error(PRODUCT_TEXT.diagnostic(`package remains locked after verified shutdown: ${errorMessage(error)}`));
113
141
  }
114
142
  },
115
- async activateInstalled(packageRoot, targetVersion, phase, onMaterializing) {
143
+ async activateInstalled(packageRoot, targetVersion, phase, onMaterializing, onWarmup) {
116
144
  let total = 0;
117
145
  let completed = 0;
118
146
  const candidate = await materializeRelease(packageRoot, paths.dataDir, {
@@ -121,7 +149,7 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
121
149
  onMaterializing?.({ completed, total });
122
150
  },
123
151
  onOperation: event => {
124
- if (event.operation !== "candidate-write")
152
+ if (event.operation !== "candidate-write" && event.operation !== "layer-write")
125
153
  return;
126
154
  completed += 1;
127
155
  onMaterializing?.({ completed, total });
@@ -136,8 +164,11 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
136
164
  await phase("certified");
137
165
  await stateStore.activate(candidate.releaseId);
138
166
  await phase("active-reference-committed");
139
- await startSupervisor(candidate, environment);
140
- await waitForVerifiedEndpoint(paths.endpointMetadataPath, candidate, 8_000);
167
+ onWarmup?.("started");
168
+ await warmMaterializedRelease(candidate, environment);
169
+ onWarmup?.("completed");
170
+ const startup = await startSupervisor(candidate, environment);
171
+ await waitForVerifiedEndpoint(resolveCohortEndpoint(paths, candidate.releaseId, environment).endpointMetadataPath, candidate, 8_000, startup);
141
172
  },
142
173
  };
143
174
  }
@@ -188,7 +219,7 @@ function createUpdateProgress(output, enabled) {
188
219
  draw();
189
220
  if (creepTo <= current)
190
221
  return;
191
- // Creep asymptotically toward (but never reach) the next milestone so
222
+ // Rationale: creep asymptotically toward (but never reach) the next milestone so
192
223
  // long opaque phases such as npm install still show visible motion. The
193
224
  // ceiling stays a whole point below the milestone: settling on `creepTo`
194
225
  // itself would render as that milestone and make arriving at it invisible,
@@ -199,7 +230,7 @@ function createUpdateProgress(output, enabled) {
199
230
  }, PROGRESS_TICK_MS);
200
231
  timer.unref?.();
201
232
  },
202
- // The bar exists to say the update is still moving. Once it has finished
233
+ // Rationale: the bar exists to say the update is still moving. Once it has finished
203
234
  // there is a better line to occupy that row — the one naming what is now
204
235
  // installed — so the bar gives the row back rather than leaving a full
205
236
  // meter above a message that already implies it.
@@ -223,12 +254,13 @@ function createUpdateProgress(output, enabled) {
223
254
  }
224
255
  /** The newest version the channel points at, which is what an unqualified update takes. */
225
256
  async function resolveChannelHead(runner, distTag, output) {
226
- const lookup = await runNpm(runner, ["view", `${PRODUCT_PACKAGE}@${distTag}`, "version"], true, output, `query the npm ${distTag} channel`);
257
+ const publicChannel = distTag === "next" ? "development" : "release";
258
+ const lookup = await runNpm(runner, ["view", `${PRODUCT_PACKAGE}@${distTag}`, "version"], true, output, `query the npm ${publicChannel} channel`);
227
259
  if (lookup.result === null)
228
260
  return { version: null, exitCode: lookup.exitCode };
229
261
  const version = validSemver(lookup.result.stdout.trim());
230
262
  if (version === null) {
231
- output.stderr(`${PRODUCT_TEXT.diagnostic(`received a malformed ${distTag} version from npm: ${JSON.stringify(lookup.result.stdout.trim())}.`)}\n`);
263
+ output.stderr(`${PRODUCT_TEXT.diagnostic(`received a malformed ${publicChannel} channel version from npm: ${JSON.stringify(lookup.result.stdout.trim())}.`)}\n`);
232
264
  return { version: null, exitCode: 1 };
233
265
  }
234
266
  return { version, exitCode: 0 };
@@ -236,14 +268,10 @@ async function resolveChannelHead(runner, distTag, output) {
236
268
  /**
237
269
  * Resolve a preview the caller named.
238
270
  *
239
- * A preview is published as `<version>-dev.<commit>`, so its commit is enough to
240
- * say which one is wanted the version in front of it is not something anyone
241
- * should have to remember. A full version is accepted too, for anyone reading one
242
- * back from `a1 version` or a changelog.
243
- *
244
- * The published list is the authority: naming a commit that was never published,
245
- * or one published more than once under different versions, is an error rather
246
- * than a guess.
271
+ * A preview is published as `<version>-dev.<pull-request-number>`, so its decimal
272
+ * development number is enough to identify it. A full version is accepted too.
273
+ * The published list remains authoritative: nothing is constructed from the
274
+ * installed package's base version.
247
275
  */
248
276
  async function resolveRequestedPreview(runner, requested, output) {
249
277
  const lookup = await runNpm(runner, ["view", PRODUCT_PACKAGE, "versions", "--json"], true, output, "list the published versions");
@@ -260,9 +288,8 @@ async function resolveRequestedPreview(runner, requested, output) {
260
288
  const versions = (Array.isArray(published) ? published : [published]).filter((value) => typeof value === "string");
261
289
  const exact = versions.find(version => version === requested);
262
290
  if (exact !== undefined) {
263
- // Naming a release here would install it through the preview path, which is a
264
- // different command with a different meaning. The commit form cannot express
265
- // one, so only the fuller spelling of a preview reaches this.
291
+ // Rationale: naming a release here would install it through the preview path, which is a
292
+ // different command with a different meaning.
266
293
  if (!exact.includes("-dev.")) {
267
294
  output.stderr(`${PRODUCT_TEXT.diagnostic(`${exact} is a release, not a preview; run ${PRODUCT_TEXT.commandName} update to move to the current release.`)}\n`);
268
295
  return { version: null, exitCode: 1 };
@@ -314,9 +341,9 @@ export async function runSelfUpdate(options) {
314
341
  if (resolved.version === null)
315
342
  return resolved.exitCode;
316
343
  const targetVersion = resolved.version;
317
- // No full stop after a version: it already ends in a dot-separated identifier,
344
+ // Rationale: no full stop after a version: it already ends in a dot-separated identifier,
318
345
  // and a trailing one reads as part of the version rather than as punctuation.
319
- output.stdout(`${PRODUCT_TEXT.commandName} update (${UPDATE_CHANNEL_LABELS[channel]}): ${runningVersion} → ${targetVersion}\n`);
346
+ output.stdout(`${PRODUCT_TEXT.commandName} update: ${runningVersion} → ${targetVersion}\n`);
320
347
  const progress = createUpdateProgress(output, options.progress ?? (options.output === undefined && process.stdout.isTTY === true));
321
348
  const rootLookup = await measure("global-root", async () => await runNpm(runner, ["root", "--global"], true, output, "resolve npm's global package root"));
322
349
  if (rootLookup.result === null)
@@ -342,6 +369,9 @@ export async function runSelfUpdate(options) {
342
369
  const paths = resolveProductPaths(environment);
343
370
  const lifecycle = options.lifecycle ?? createUpdateLifecycleCoordinator(environment, fileSystem, output);
344
371
  const transactionStore = options.transactionStore ?? new UpdateTransactionStore(paths.dataDir);
372
+ const maintenance = options.maintenance ?? (options.lifecycle
373
+ ? async () => { }
374
+ : async () => await scheduleReleaseCleanup(paths.dataDir, paths));
345
375
  let transaction = await transactionStore.read();
346
376
  try {
347
377
  if (await lifecycle.targetIsActive(targetVersion)) {
@@ -349,11 +379,12 @@ export async function runSelfUpdate(options) {
349
379
  await transactionStore.advance("supervisor-verified");
350
380
  await transactionStore.finish("completed");
351
381
  }
382
+ await maintenance();
352
383
  await transactionStore.clearCompleted();
353
384
  output.stdout(`${PRODUCT_TEXT.commandName} is up to date — no update needed.\n`);
354
385
  return 0;
355
386
  }
356
- // The bar first appears here so a no-change run never flashes it.
387
+ // Rationale: the bar first appears here so a no-change run never flashes it.
357
388
  progress.set(3, 15);
358
389
  const cohortState = await new CohortStateStore(paths.dataDir).read();
359
390
  transaction = await transactionStore.begin({
@@ -381,8 +412,21 @@ export async function runSelfUpdate(options) {
381
412
  }
382
413
  transaction = await transactionStore.advance("package-installed");
383
414
  }
415
+ // Compatibility: npm 12 blocks install scripts unless allowScripts covers the package, so
416
+ // the postinstall that points the #pi-tui proxy at the tree npm just built
417
+ // may never have run. Run the shipped script directly: the proxy must be
418
+ // correct before the release store copies this tree. A failure is reported
419
+ // and left to the launch-time self-heal rather than failing the update.
420
+ try {
421
+ const proxySync = await runner(process.execPath, [resolve(packageRoot, "bin", "sync-pi-tui-proxy.js")], { captureStdout: true });
422
+ if (proxySync.code !== 0)
423
+ output.stderr(`${PRODUCT_TEXT.diagnostic(`could not point the #pi-tui proxy at the installed tree (exited ${formatExitCode(proxySync.code)}).`)}\n`);
424
+ }
425
+ catch (error) {
426
+ output.stderr(`${PRODUCT_TEXT.diagnostic(`could not point the #pi-tui proxy at the installed tree: ${errorMessage(error)}`)}\n`);
427
+ }
384
428
  progress.set(70, 75);
385
- // Ownership can be reacquired after an interrupted installation (for
429
+ // Concurrency: ownership can be reacquired after an interrupted installation (for
386
430
  // example, if bare A1 is launched before the update is resumed). Recheck
387
431
  // immediately before activation so recovery cannot start a second cohort.
388
432
  await measure("ownership-release", async () => { await lifecycle.shutdownVerifiedOwners(targetVersion); });
@@ -397,11 +441,24 @@ export async function runSelfUpdate(options) {
397
441
  const span = MATERIALIZE_PROGRESS.to - MATERIALIZE_PROGRESS.from;
398
442
  const done = total > 0 ? Math.min(1, completed / total) : 0;
399
443
  progress.set(MATERIALIZE_PROGRESS.from + span * done);
444
+ }, state => {
445
+ if (state === "started") {
446
+ activationPhaseStartedAt = now();
447
+ progress.set(98, 99);
448
+ }
449
+ else {
450
+ options.onPhaseTiming?.({ phase: "warmup", durationMs: Math.max(0, now() - activationPhaseStartedAt) });
451
+ activationPhaseStartedAt = now();
452
+ progress.set(99);
453
+ }
400
454
  });
401
455
  options.onPhaseTiming?.({ phase: "supervisor-verified", durationMs: Math.max(0, now() - activationPhaseStartedAt) });
402
456
  const transactionStartedAt = now();
403
457
  await transactionStore.advance("supervisor-verified");
404
458
  await transactionStore.finish("completed");
459
+ // Invariant: successful output follows the durable cleanup disposition. Slow recursive
460
+ // removal belongs to the detached worker started by this maintenance coordinator.
461
+ await maintenance();
405
462
  await transactionStore.clearCompleted();
406
463
  options.onPhaseTiming?.({ phase: "transaction-complete", durationMs: Math.max(0, now() - transactionStartedAt) });
407
464
  progress.finish();
@@ -426,8 +483,9 @@ export function assertUpdatePerformanceBudget(evidence, maximumPostNpmDurationMs
426
483
  failures.push("fixture contains no payload files");
427
484
  if (evidence.sourceReads !== evidence.fileCount)
428
485
  failures.push(`source payload read count is ${evidence.sourceReads} for ${evidence.fileCount} files`);
429
- if (evidence.candidateWrites !== evidence.fileCount)
430
- failures.push(`candidate payload write count is ${evidence.candidateWrites} for ${evidence.fileCount} files`);
486
+ const totalWrites = evidence.candidateWrites + (evidence.layerWrites ?? 0);
487
+ if (totalWrites !== evidence.fileCount)
488
+ failures.push(`runtime payload write count is ${totalWrites} for ${evidence.fileCount} files`);
431
489
  if (evidence.verificationReads > 0)
432
490
  failures.push(`fresh certification reread ${evidence.verificationReads} candidate files`);
433
491
  if (evidence.postNpmDurationMs > maximumPostNpmDurationMs)
@@ -495,8 +553,10 @@ async function rollbackPriorCohort(dataDir, environment, priorReleaseId) {
495
553
  }
496
554
  const release = await readMaterializedRelease(prior.releaseRoot);
497
555
  const paths = resolveProductPaths(environment);
498
- await startSupervisor(release, environment);
499
- await waitForVerifiedEndpoint(paths.endpointMetadataPath, release, 8_000);
556
+ // Invariant: rollback re-points the active reference and starts the prior cohort on its own endpoint;
557
+ // a cohort that survived the update keeps serving the work it already had.
558
+ const startup = await startSupervisor(release, environment);
559
+ await waitForVerifiedEndpoint(resolveCohortEndpoint(paths, release.releaseId, environment).endpointMetadataPath, release, 8_000, startup);
500
560
  return "rolled back";
501
561
  }
502
562
  function phaseBefore(current, target) {
@@ -0,0 +1,3 @@
1
+ import type { MaterializedRelease } from "./release-store.js";
2
+ /** Import the exact immutable startup graph in a terminal-free bounded child process. */
3
+ export declare function warmMaterializedRelease(release: MaterializedRelease, environment: NodeJS.ProcessEnv, timeoutMs?: number): Promise<void>;
@@ -0,0 +1,35 @@
1
+ import { spawn } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ import { releaseEnvironment } from "./bootstrap.js";
4
+ import { PRODUCT_IDENTITY } from "../../product-identity.js";
5
+ /** Import the exact immutable startup graph in a terminal-free bounded child process. */
6
+ export async function warmMaterializedRelease(release, environment, timeoutMs = 30_000) {
7
+ const entry = resolve(release.releaseRoot, "bin", "warmup.js");
8
+ await new Promise((resolvePromise, rejectPromise) => {
9
+ const child = spawn(process.execPath, [entry], {
10
+ env: { ...releaseEnvironment(environment, release), [PRODUCT_IDENTITY.environment.immutableWarmup]: "1" },
11
+ stdio: "ignore",
12
+ windowsHide: true,
13
+ });
14
+ let settled = false;
15
+ const finish = (error) => {
16
+ if (settled)
17
+ return;
18
+ settled = true;
19
+ clearTimeout(timer);
20
+ if (error)
21
+ rejectPromise(error);
22
+ else
23
+ resolvePromise();
24
+ };
25
+ child.once("error", error => finish(error));
26
+ child.once("close", (code, signal) => finish(code === 0
27
+ ? undefined
28
+ : new Error(`immutable startup warmup exited with ${code === null ? signal ?? "unknown status" : `status ${code}`}`)));
29
+ const timer = setTimeout(() => {
30
+ child.kill();
31
+ finish(new Error(`immutable startup warmup exceeded ${timeoutMs}ms`));
32
+ }, timeoutMs);
33
+ timer.unref?.();
34
+ });
35
+ }
@@ -0,0 +1 @@
1
+ export * from "./startup-runtime.js";
@@ -0,0 +1 @@
1
+ export * from "./startup-runtime.js";
@@ -0,0 +1,36 @@
1
+ import { PRODUCT_IDENTITY } from "../../product-identity.js";
2
+ export type StartupPhase = "command-invoked" | "bootstrap-start" | "bootstrap-selected" | "durable-validation-start" | "durable-validation-complete" | "replacement-supervisor-start" | "replacement-supervisor-ready" | "guardian-start" | "guardian-connected" | "ui-entry" | "ui-modules-loaded" | "pi-services" | "resource-discovery" | "session-created" | "settings-loaded" | "first-input-ready-render";
3
+ export interface StartupPerformanceEvidence {
4
+ readonly profileId: "a1" | "pi";
5
+ readonly launchKind: "post-update" | "no-live-supervisor" | "warm";
6
+ readonly events: readonly StartupTraceEvent[];
7
+ }
8
+ export interface StartupTraceEvent {
9
+ readonly schema: typeof PRODUCT_IDENTITY.evidence.startupTraceSchema;
10
+ readonly traceId: string;
11
+ readonly phase: StartupPhase;
12
+ readonly elapsedMs: number;
13
+ readonly processId: number;
14
+ readonly profileId: string;
15
+ readonly releaseId: string | null;
16
+ readonly dependencyLayerIds: readonly string[];
17
+ readonly nodeVersion: string;
18
+ readonly fileReadOperations: number;
19
+ }
20
+ /** Initialize opt-in startup tracing from a caller-provided evidence path. */
21
+ export declare function initializeStartupTrace(environment: NodeJS.ProcessEnv, profileId: string, startedAtMs?: number): void;
22
+ /** Append one redacted phase event; ordinary launches without trace context perform no I/O. */
23
+ export declare function markStartupPhase(environment: NodeJS.ProcessEnv, phase: StartupPhase): Promise<void>;
24
+ export declare function assertImmutableWarmupEnvironment(environment: NodeJS.ProcessEnv): void;
25
+ /** Enable the compile cache directly from launch environment without loading profile services. */
26
+ export declare function enableEnvironmentCompileCache(environment: NodeJS.ProcessEnv): string | null;
27
+ /** Enable Node's supported persistent compile cache in an immutable-identity namespace. */
28
+ export declare function enableStartupCompileCache(dataDir: string, releaseId: string | null, dependencyLayerIds: readonly string[]): string | null;
29
+ export declare function startupCompileCachePath(dataDir: string, releaseId: string | null, dependencyLayerIds: readonly string[]): string;
30
+ /** Retain current compile namespaces plus a bounded number of recent fallbacks. */
31
+ export declare function collectCompileCaches(dataDir: string, protectedPaths: readonly string[], keepRecent?: number): Promise<void>;
32
+ export declare function assertStartupPerformanceBudget(evidence: StartupPerformanceEvidence, budgets?: {
33
+ readonly postUpdateMs: number;
34
+ readonly warmMs: number;
35
+ }): void;
36
+ export declare function parseStartupTrace(source: string): readonly StartupTraceEvent[];
@@ -0,0 +1,140 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { appendFile, mkdir, readdir, rm } from "node:fs/promises";
3
+ import { constants as moduleConstants, enableCompileCache } from "node:module";
4
+ import { dirname, resolve } from "node:path";
5
+ import { homedir, platform } from "node:os";
6
+ import { performance } from "node:perf_hooks";
7
+ import { PRODUCT_IDENTITY } from "../../product-identity.js";
8
+ /** Initialize opt-in startup tracing from a caller-provided evidence path. */
9
+ export function initializeStartupTrace(environment, profileId, startedAtMs = performance.timeOrigin + performance.now()) {
10
+ const configured = environment[PRODUCT_IDENTITY.environment.startupTrace];
11
+ if (!configured || parseContext(configured) !== null)
12
+ return;
13
+ const context = {
14
+ path: resolve(configured),
15
+ traceId: randomUUID(),
16
+ startedAtMs,
17
+ profileId,
18
+ releaseId: environment[PRODUCT_IDENTITY.environment.releaseId] ?? null,
19
+ dependencyLayerIds: parseLayerIds(environment[PRODUCT_IDENTITY.environment.releaseLayers]),
20
+ };
21
+ environment[PRODUCT_IDENTITY.environment.startupTrace] = JSON.stringify(context);
22
+ }
23
+ /** Append one redacted phase event; ordinary launches without trace context perform no I/O. */
24
+ export async function markStartupPhase(environment, phase) {
25
+ const context = parseContext(environment[PRODUCT_IDENTITY.environment.startupTrace]);
26
+ if (context === null)
27
+ return;
28
+ const event = {
29
+ schema: PRODUCT_IDENTITY.evidence.startupTraceSchema,
30
+ traceId: context.traceId,
31
+ phase,
32
+ elapsedMs: Math.max(0, performance.timeOrigin + performance.now() - context.startedAtMs),
33
+ processId: process.pid,
34
+ profileId: context.profileId,
35
+ releaseId: environment[PRODUCT_IDENTITY.environment.releaseId] ?? context.releaseId,
36
+ dependencyLayerIds: parseLayerIds(environment[PRODUCT_IDENTITY.environment.releaseLayers]).length > 0
37
+ ? parseLayerIds(environment[PRODUCT_IDENTITY.environment.releaseLayers])
38
+ : context.dependencyLayerIds,
39
+ nodeVersion: process.version,
40
+ fileReadOperations: process.resourceUsage().fsRead,
41
+ };
42
+ await mkdir(dirname(context.path), { recursive: true, mode: 0o700 });
43
+ await appendFile(context.path, `${JSON.stringify(event)}\n`, { encoding: "utf8", mode: 0o600 });
44
+ }
45
+ export function assertImmutableWarmupEnvironment(environment) {
46
+ if (environment[PRODUCT_IDENTITY.environment.immutableWarmup] !== "1") {
47
+ throw new Error("warmup entry is private to verified update activation");
48
+ }
49
+ }
50
+ /** Enable the compile cache directly from launch environment without loading profile services. */
51
+ export function enableEnvironmentCompileCache(environment) {
52
+ const home = environment.HOME ?? environment.USERPROFILE ?? homedir();
53
+ const dataDir = resolve(environment[PRODUCT_IDENTITY.environment.dataDir]
54
+ ?? (platform() === "win32"
55
+ ? resolve(environment.LOCALAPPDATA ?? home, PRODUCT_IDENTITY.state.windowsControlDirectory)
56
+ : resolve(environment.XDG_DATA_HOME ?? resolve(home, ".local", "share"), PRODUCT_IDENTITY.state.unixControlDirectory)));
57
+ return enableStartupCompileCache(dataDir, environment[PRODUCT_IDENTITY.environment.releaseId] ?? null, parseLayerIds(environment[PRODUCT_IDENTITY.environment.releaseLayers]));
58
+ }
59
+ /** Enable Node's supported persistent compile cache in an immutable-identity namespace. */
60
+ export function enableStartupCompileCache(dataDir, releaseId, dependencyLayerIds) {
61
+ try {
62
+ const path = startupCompileCachePath(dataDir, releaseId, dependencyLayerIds);
63
+ const result = enableCompileCache(path);
64
+ return result.status === moduleConstants.compileCacheStatus.FAILED ? null : result.directory ?? path;
65
+ }
66
+ catch {
67
+ return null;
68
+ }
69
+ }
70
+ export function startupCompileCachePath(dataDir, releaseId, dependencyLayerIds) {
71
+ const layers = createHash("sha256").update(dependencyLayerIds.join("\0")).digest("hex").slice(0, 20);
72
+ const content = dependencyLayerIds.length > 0
73
+ ? `layers-${layers}`
74
+ : `release-${(releaseId ?? "mutable").replace(/[^0-9A-Za-z.+_-]/g, "_")}`;
75
+ // Performance: stable layer paths share compiled dependency entries across product releases;
76
+ // Node's own cache key still isolates each release-specific module path and source bytes.
77
+ return resolve(dataDir, "cache", "compile", `${process.versions.modules ?? "node"}-${process.version.replace(/[^0-9A-Za-z.-]/g, "_")}-${content}`);
78
+ }
79
+ /** Retain current compile namespaces plus a bounded number of recent fallbacks. */
80
+ export async function collectCompileCaches(dataDir, protectedPaths, keepRecent = 2) {
81
+ const root = resolve(dataDir, "cache", "compile");
82
+ const protectedSet = new Set(protectedPaths.map(path => resolve(path)));
83
+ const entries = await readdir(root, { withFileTypes: true }).catch(() => []);
84
+ const candidates = await Promise.all(entries.filter(entry => entry.isDirectory()).map(async (entry) => {
85
+ const path = resolve(root, entry.name);
86
+ const metadata = await import("node:fs/promises").then(fs => fs.stat(path));
87
+ return { path, mtimeMs: metadata.mtimeMs };
88
+ }));
89
+ const retainedRecent = new Set(candidates.filter(item => !protectedSet.has(item.path))
90
+ .sort((left, right) => right.mtimeMs - left.mtimeMs)
91
+ .slice(0, keepRecent)
92
+ .map(item => item.path));
93
+ for (const candidate of candidates) {
94
+ if (!protectedSet.has(candidate.path) && !retainedRecent.has(candidate.path))
95
+ await rm(candidate.path, { recursive: true, force: true });
96
+ }
97
+ }
98
+ export function assertStartupPerformanceBudget(evidence, budgets = { postUpdateMs: 5_000, warmMs: 3_000 }) {
99
+ const events = [...evidence.events].sort((left, right) => left.elapsedMs - right.elapsedMs);
100
+ const ready = events.findLast(event => event.phase === "first-input-ready-render");
101
+ if (!ready)
102
+ throw new Error(`startup budget failed for ${evidence.profileId}: first input-ready render was not recorded`);
103
+ const budget = evidence.launchKind === "warm" ? budgets.warmMs : budgets.postUpdateMs;
104
+ if (ready.elapsedMs <= budget)
105
+ return;
106
+ const intervals = events.map((event, index) => ({
107
+ phase: event.phase,
108
+ durationMs: event.elapsedMs - (events[index - 1]?.elapsedMs ?? 0),
109
+ })).sort((left, right) => right.durationMs - left.durationMs);
110
+ throw new Error(`startup budget failed for ${evidence.profileId} ${evidence.launchKind}: ${Math.round(ready.elapsedMs)}ms exceeds ${budget}ms; dominant phases: ${intervals.slice(0, 3).map(item => `${item.phase} ${Math.round(item.durationMs)}ms`).join(", ")}`);
111
+ }
112
+ export function parseStartupTrace(source) {
113
+ const events = source.split(/\r?\n/).filter(Boolean).map(line => JSON.parse(line));
114
+ for (const event of events) {
115
+ if (event.schema !== PRODUCT_IDENTITY.evidence.startupTraceSchema || typeof event.traceId !== "string"
116
+ || typeof event.phase !== "string" || !Number.isFinite(event.elapsedMs) || !Array.isArray(event.dependencyLayerIds)) {
117
+ throw new Error("startup trace contains an invalid event");
118
+ }
119
+ }
120
+ return events.sort((left, right) => left.elapsedMs - right.elapsedMs);
121
+ }
122
+ function parseContext(value) {
123
+ if (!value?.startsWith("{"))
124
+ return null;
125
+ try {
126
+ const context = JSON.parse(value);
127
+ if (typeof context.path !== "string" || typeof context.traceId !== "string" || !Number.isFinite(context.startedAtMs)
128
+ || typeof context.profileId !== "string" || !Array.isArray(context.dependencyLayerIds))
129
+ return null;
130
+ return context;
131
+ }
132
+ catch {
133
+ return null;
134
+ }
135
+ }
136
+ function parseLayerIds(value) {
137
+ if (!value)
138
+ return [];
139
+ return [...new Set(value.split(",").filter(id => /^dependencies-[a-f0-9]{32}$/.test(id)))].sort();
140
+ }
@@ -1,5 +1,5 @@
1
1
  import { DatabaseSync } from "node:sqlite";
2
- import type { ManagedAgentDescriptor, PaneId, AgentRecoveryAuthority, RecoveryReferenceId, TerminalSessionLaunch, TerminalTopologySnapshot } from "../workspace-contracts/index.js";
2
+ import type { ManagedAgentDescriptor, PaneId, AgentRecoveryAuthority, RecoveryReferenceId, TerminalSessionLaunch, TerminalTopologySnapshot } from "../../contracts/workspace/index.js";
3
3
  import type { LaunchInstance, LaunchInstanceId, LaunchInstanceOutcome, NativeProcessIdentity, ProcessContainmentIdentity } from "../lifecycle/index.js";
4
4
  export declare const DEFAULT_WORKSPACE_ID = "workspace-default";
5
5
  export interface WorkspaceAgentPresentation {
@@ -14,6 +14,7 @@ export interface StoredWorkspaceAgent {
14
14
  readonly agent: ManagedAgentDescriptor;
15
15
  readonly presentation: WorkspaceAgentPresentation;
16
16
  }
17
+ /** Owns WAL-backed control persistence and reconciles prior-boot records before current use. */
17
18
  export declare class ControlStore {
18
19
  #private;
19
20
  readonly bootNonce: string | null;