@omnitron-dev/omnitron 0.3.0 → 0.3.2

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 (1786) hide show
  1. package/README.md +579 -0
  2. package/data/operations/managed-kernel.mjs +302 -0
  3. package/data/operations/stage-kernel.mjs +125 -0
  4. package/dist/BUILD.json +4 -3
  5. package/dist/cli/exit-after-output.d.ts +3 -0
  6. package/dist/cli/exit-after-output.d.ts.map +1 -0
  7. package/dist/cli/exit-after-output.js +11 -0
  8. package/dist/cli/exit-after-output.js.map +1 -0
  9. package/dist/cli/installed.d.ts +3 -0
  10. package/dist/cli/installed.d.ts.map +1 -0
  11. package/dist/cli/installed.js +17 -0
  12. package/dist/cli/installed.js.map +1 -0
  13. package/dist/cli/omnitron.js +455 -99
  14. package/dist/cli/omnitron.js.map +1 -1
  15. package/dist/cli/output-command.d.ts +13 -0
  16. package/dist/cli/output-command.d.ts.map +1 -0
  17. package/dist/cli/output-command.js +48 -0
  18. package/dist/cli/output-command.js.map +1 -0
  19. package/dist/cluster/cluster.rpc-service.d.ts +9 -77
  20. package/dist/cluster/cluster.rpc-service.d.ts.map +1 -1
  21. package/dist/cluster/cluster.rpc-service.js +20 -107
  22. package/dist/cluster/cluster.rpc-service.js.map +1 -1
  23. package/dist/cluster/enrollment.d.ts +9 -0
  24. package/dist/cluster/enrollment.d.ts.map +1 -0
  25. package/dist/cluster/enrollment.js +49 -0
  26. package/dist/cluster/enrollment.js.map +1 -0
  27. package/dist/cluster/index.d.ts +1 -1
  28. package/dist/cluster/index.d.ts.map +1 -1
  29. package/dist/cluster/leader-election.d.ts +39 -211
  30. package/dist/cluster/leader-election.d.ts.map +1 -1
  31. package/dist/cluster/leader-election.js +235 -512
  32. package/dist/cluster/leader-election.js.map +1 -1
  33. package/dist/cluster/mesh-link.d.ts +18 -51
  34. package/dist/cluster/mesh-link.d.ts.map +1 -1
  35. package/dist/cluster/mesh-link.js +66 -78
  36. package/dist/cluster/mesh-link.js.map +1 -1
  37. package/dist/cluster/mesh.d.ts +3 -1
  38. package/dist/cluster/mesh.d.ts.map +1 -1
  39. package/dist/cluster/mesh.js +76 -60
  40. package/dist/cluster/mesh.js.map +1 -1
  41. package/dist/cluster/slave-connector.d.ts +42 -6
  42. package/dist/cluster/slave-connector.d.ts.map +1 -1
  43. package/dist/cluster/slave-connector.js +349 -196
  44. package/dist/cluster/slave-connector.js.map +1 -1
  45. package/dist/cluster/standalone-infrastructure.d.ts +3 -0
  46. package/dist/cluster/standalone-infrastructure.d.ts.map +1 -0
  47. package/dist/cluster/standalone-infrastructure.js +25 -0
  48. package/dist/cluster/standalone-infrastructure.js.map +1 -0
  49. package/dist/cluster/stop-authority.d.ts +45 -0
  50. package/dist/cluster/stop-authority.d.ts.map +1 -0
  51. package/dist/cluster/stop-authority.js +112 -0
  52. package/dist/cluster/stop-authority.js.map +1 -0
  53. package/dist/commands/access.d.ts +9 -0
  54. package/dist/commands/access.d.ts.map +1 -0
  55. package/dist/commands/access.js +45 -0
  56. package/dist/commands/access.js.map +1 -0
  57. package/dist/commands/audit.d.ts +2 -0
  58. package/dist/commands/audit.d.ts.map +1 -1
  59. package/dist/commands/audit.js +9 -4
  60. package/dist/commands/audit.js.map +1 -1
  61. package/dist/commands/backend.d.ts +17 -0
  62. package/dist/commands/backend.d.ts.map +1 -0
  63. package/dist/commands/backend.js +264 -0
  64. package/dist/commands/backend.js.map +1 -0
  65. package/dist/commands/backup.d.ts +5 -0
  66. package/dist/commands/backup.d.ts.map +1 -1
  67. package/dist/commands/backup.js +17 -2
  68. package/dist/commands/backup.js.map +1 -1
  69. package/dist/commands/cluster.d.ts.map +1 -1
  70. package/dist/commands/cluster.js +33 -42
  71. package/dist/commands/cluster.js.map +1 -1
  72. package/dist/commands/daemon-cmd.d.ts.map +1 -1
  73. package/dist/commands/daemon-cmd.js +14 -3
  74. package/dist/commands/daemon-cmd.js.map +1 -1
  75. package/dist/commands/deploy.d.ts +4 -4
  76. package/dist/commands/deploy.js +4 -4
  77. package/dist/commands/discover.d.ts +2 -2
  78. package/dist/commands/discover.js +2 -2
  79. package/dist/commands/doctor.d.ts +11 -29
  80. package/dist/commands/doctor.d.ts.map +1 -1
  81. package/dist/commands/doctor.js +47 -45
  82. package/dist/commands/doctor.js.map +1 -1
  83. package/dist/commands/files.d.ts +19 -0
  84. package/dist/commands/files.d.ts.map +1 -0
  85. package/dist/commands/files.js +226 -0
  86. package/dist/commands/files.js.map +1 -0
  87. package/dist/commands/fleet-asking.d.ts +2 -2
  88. package/dist/commands/fleet-asking.js +2 -2
  89. package/dist/commands/fleet-recover.d.ts +2 -0
  90. package/dist/commands/fleet-recover.d.ts.map +1 -0
  91. package/dist/commands/fleet-recover.js +30 -0
  92. package/dist/commands/fleet-recover.js.map +1 -0
  93. package/dist/commands/fleet-rollout.d.ts +25 -0
  94. package/dist/commands/fleet-rollout.d.ts.map +1 -0
  95. package/dist/commands/fleet-rollout.js +155 -0
  96. package/dist/commands/fleet-rollout.js.map +1 -0
  97. package/dist/commands/fleet.d.ts.map +1 -1
  98. package/dist/commands/fleet.js +1 -0
  99. package/dist/commands/fleet.js.map +1 -1
  100. package/dist/commands/health-check.d.ts.map +1 -1
  101. package/dist/commands/health-check.js +13 -6
  102. package/dist/commands/health-check.js.map +1 -1
  103. package/dist/commands/host-ingress.d.ts +3 -0
  104. package/dist/commands/host-ingress.d.ts.map +1 -0
  105. package/dist/commands/host-ingress.js +31 -0
  106. package/dist/commands/host-ingress.js.map +1 -0
  107. package/dist/commands/infra.d.ts +7 -4
  108. package/dist/commands/infra.d.ts.map +1 -1
  109. package/dist/commands/infra.js +152 -60
  110. package/dist/commands/infra.js.map +1 -1
  111. package/dist/commands/logs.d.ts +7 -24
  112. package/dist/commands/logs.d.ts.map +1 -1
  113. package/dist/commands/logs.js +117 -41
  114. package/dist/commands/logs.js.map +1 -1
  115. package/dist/commands/metrics.d.ts.map +1 -1
  116. package/dist/commands/metrics.js +7 -1
  117. package/dist/commands/metrics.js.map +1 -1
  118. package/dist/commands/migrate.d.ts +8 -0
  119. package/dist/commands/migrate.d.ts.map +1 -0
  120. package/dist/commands/migrate.js +64 -0
  121. package/dist/commands/migrate.js.map +1 -0
  122. package/dist/commands/node-reconcile.d.ts +8 -0
  123. package/dist/commands/node-reconcile.d.ts.map +1 -0
  124. package/dist/commands/node-reconcile.js +49 -0
  125. package/dist/commands/node-reconcile.js.map +1 -0
  126. package/dist/commands/node.d.ts +1 -21
  127. package/dist/commands/node.d.ts.map +1 -1
  128. package/dist/commands/node.js +35 -27
  129. package/dist/commands/node.js.map +1 -1
  130. package/dist/commands/output.d.ts +3 -9
  131. package/dist/commands/output.d.ts.map +1 -1
  132. package/dist/commands/output.js +34 -25
  133. package/dist/commands/output.js.map +1 -1
  134. package/dist/commands/pipeline.d.ts +11 -2
  135. package/dist/commands/pipeline.d.ts.map +1 -1
  136. package/dist/commands/pipeline.js +82 -15
  137. package/dist/commands/pipeline.js.map +1 -1
  138. package/dist/commands/project.d.ts +10 -2
  139. package/dist/commands/project.d.ts.map +1 -1
  140. package/dist/commands/project.js +69 -3
  141. package/dist/commands/project.js.map +1 -1
  142. package/dist/commands/release-store.js +1 -1
  143. package/dist/commands/release-store.js.map +1 -1
  144. package/dist/commands/release.d.ts +5 -12
  145. package/dist/commands/release.d.ts.map +1 -1
  146. package/dist/commands/release.js +144 -36
  147. package/dist/commands/release.js.map +1 -1
  148. package/dist/commands/remote.d.ts +3 -3
  149. package/dist/commands/remote.js +3 -3
  150. package/dist/commands/scale.d.ts +1 -4
  151. package/dist/commands/scale.d.ts.map +1 -1
  152. package/dist/commands/scale.js +39 -19
  153. package/dist/commands/scale.js.map +1 -1
  154. package/dist/commands/secret-input.d.ts +3 -0
  155. package/dist/commands/secret-input.d.ts.map +1 -0
  156. package/dist/commands/secret-input.js +36 -0
  157. package/dist/commands/secret-input.js.map +1 -0
  158. package/dist/commands/secret.d.ts +4 -2
  159. package/dist/commands/secret.d.ts.map +1 -1
  160. package/dist/commands/secret.js +12 -2
  161. package/dist/commands/secret.js.map +1 -1
  162. package/dist/commands/service-resident.d.ts +25 -0
  163. package/dist/commands/service-resident.d.ts.map +1 -0
  164. package/dist/commands/service-resident.js +236 -0
  165. package/dist/commands/service-resident.js.map +1 -0
  166. package/dist/commands/service-units.d.ts +13 -1
  167. package/dist/commands/service-units.d.ts.map +1 -1
  168. package/dist/commands/service-units.js +38 -16
  169. package/dist/commands/service-units.js.map +1 -1
  170. package/dist/commands/service.d.ts +2 -24
  171. package/dist/commands/service.d.ts.map +1 -1
  172. package/dist/commands/service.js +89 -7
  173. package/dist/commands/service.js.map +1 -1
  174. package/dist/commands/stack.d.ts +11 -6
  175. package/dist/commands/stack.d.ts.map +1 -1
  176. package/dist/commands/stack.js +212 -38
  177. package/dist/commands/stack.js.map +1 -1
  178. package/dist/commands/start.d.ts +0 -21
  179. package/dist/commands/start.d.ts.map +1 -1
  180. package/dist/commands/start.js +33 -43
  181. package/dist/commands/start.js.map +1 -1
  182. package/dist/commands/status.d.ts +1 -5
  183. package/dist/commands/status.d.ts.map +1 -1
  184. package/dist/commands/status.js +5 -1
  185. package/dist/commands/status.js.map +1 -1
  186. package/dist/commands/stop.d.ts +0 -22
  187. package/dist/commands/stop.d.ts.map +1 -1
  188. package/dist/commands/stop.js +26 -86
  189. package/dist/commands/stop.js.map +1 -1
  190. package/dist/commands/system.d.ts +4 -0
  191. package/dist/commands/system.d.ts.map +1 -0
  192. package/dist/commands/system.js +41 -0
  193. package/dist/commands/system.js.map +1 -0
  194. package/dist/commands/terminal.d.ts +7 -0
  195. package/dist/commands/terminal.d.ts.map +1 -0
  196. package/dist/commands/terminal.js +184 -0
  197. package/dist/commands/terminal.js.map +1 -0
  198. package/dist/commands/topology.d.ts +3 -0
  199. package/dist/commands/topology.d.ts.map +1 -0
  200. package/dist/commands/topology.js +107 -0
  201. package/dist/commands/topology.js.map +1 -0
  202. package/dist/commands/tor.d.ts +1 -1
  203. package/dist/commands/tor.js +2 -2
  204. package/dist/commands/up.d.ts +4 -54
  205. package/dist/commands/up.d.ts.map +1 -1
  206. package/dist/commands/up.js +41 -98
  207. package/dist/commands/up.js.map +1 -1
  208. package/dist/commands/webapp.d.ts +0 -9
  209. package/dist/commands/webapp.d.ts.map +1 -1
  210. package/dist/commands/webapp.js +116 -69
  211. package/dist/commands/webapp.js.map +1 -1
  212. package/dist/config/app-path.d.ts +4 -0
  213. package/dist/config/app-path.d.ts.map +1 -0
  214. package/dist/config/app-path.js +6 -0
  215. package/dist/config/app-path.js.map +1 -0
  216. package/dist/config/defaults.d.ts.map +1 -1
  217. package/dist/config/defaults.js +9 -3
  218. package/dist/config/defaults.js.map +1 -1
  219. package/dist/config/define-ecosystem.d.ts.map +1 -1
  220. package/dist/config/define-ecosystem.js +12 -0
  221. package/dist/config/define-ecosystem.js.map +1 -1
  222. package/dist/config/index.d.ts +3 -1
  223. package/dist/config/index.d.ts.map +1 -1
  224. package/dist/config/index.js +1 -1
  225. package/dist/config/index.js.map +1 -1
  226. package/dist/config/loader-child.d.ts +2 -0
  227. package/dist/config/loader-child.d.ts.map +1 -0
  228. package/dist/config/loader-child.js +56 -0
  229. package/dist/config/loader-child.js.map +1 -0
  230. package/dist/config/loader.d.ts +7 -2
  231. package/dist/config/loader.d.ts.map +1 -1
  232. package/dist/config/loader.js +14 -27
  233. package/dist/config/loader.js.map +1 -1
  234. package/dist/config/saved.d.ts +67 -0
  235. package/dist/config/saved.d.ts.map +1 -0
  236. package/dist/config/saved.js +81 -0
  237. package/dist/config/saved.js.map +1 -0
  238. package/dist/config/types.d.ts +105 -58
  239. package/dist/config/types.d.ts.map +1 -1
  240. package/dist/daemon/backend-candidate.d.ts +32 -0
  241. package/dist/daemon/backend-candidate.d.ts.map +1 -0
  242. package/dist/daemon/backend-candidate.js +129 -0
  243. package/dist/daemon/backend-candidate.js.map +1 -0
  244. package/dist/daemon/backend-child.d.ts +5 -0
  245. package/dist/daemon/backend-child.d.ts.map +1 -0
  246. package/dist/daemon/backend-child.js +13 -0
  247. package/dist/daemon/backend-child.js.map +1 -0
  248. package/dist/daemon/backend-control.d.ts +43 -0
  249. package/dist/daemon/backend-control.d.ts.map +1 -0
  250. package/dist/daemon/backend-control.js +155 -0
  251. package/dist/daemon/backend-control.js.map +1 -0
  252. package/dist/daemon/backend-crash-recovery.d.ts +4 -0
  253. package/dist/daemon/backend-crash-recovery.d.ts.map +1 -0
  254. package/dist/daemon/backend-crash-recovery.js +136 -0
  255. package/dist/daemon/backend-crash-recovery.js.map +1 -0
  256. package/dist/daemon/backend-handoff-types.d.ts +27 -0
  257. package/dist/daemon/backend-handoff-types.d.ts.map +1 -0
  258. package/dist/daemon/backend-handoff-types.js +33 -0
  259. package/dist/daemon/backend-handoff-types.js.map +1 -0
  260. package/dist/daemon/backend-recovery-journal.d.ts +30 -0
  261. package/dist/daemon/backend-recovery-journal.d.ts.map +1 -0
  262. package/dist/daemon/backend-recovery-journal.js +67 -0
  263. package/dist/daemon/backend-recovery-journal.js.map +1 -0
  264. package/dist/daemon/backend-recovery-monitor.d.ts +35 -0
  265. package/dist/daemon/backend-recovery-monitor.d.ts.map +1 -0
  266. package/dist/daemon/backend-recovery-monitor.js +113 -0
  267. package/dist/daemon/backend-recovery-monitor.js.map +1 -0
  268. package/dist/daemon/backend-supervisor-entry.d.ts +2 -0
  269. package/dist/daemon/backend-supervisor-entry.d.ts.map +1 -0
  270. package/dist/daemon/backend-supervisor-entry.js +3 -0
  271. package/dist/daemon/backend-supervisor-entry.js.map +1 -0
  272. package/dist/daemon/backend-supervisor-main.d.ts +2 -0
  273. package/dist/daemon/backend-supervisor-main.d.ts.map +1 -0
  274. package/dist/daemon/backend-supervisor-main.js +45 -0
  275. package/dist/daemon/backend-supervisor-main.js.map +1 -0
  276. package/dist/daemon/backend-supervisor.d.ts +61 -0
  277. package/dist/daemon/backend-supervisor.d.ts.map +1 -0
  278. package/dist/daemon/backend-supervisor.js +339 -0
  279. package/dist/daemon/backend-supervisor.js.map +1 -0
  280. package/dist/daemon/backend-upgrade.d.ts +41 -0
  281. package/dist/daemon/backend-upgrade.d.ts.map +1 -0
  282. package/dist/daemon/backend-upgrade.js +444 -0
  283. package/dist/daemon/backend-upgrade.js.map +1 -0
  284. package/dist/daemon/backend.rpc-service.d.ts +11 -0
  285. package/dist/daemon/backend.rpc-service.d.ts.map +1 -0
  286. package/dist/daemon/backend.rpc-service.js +44 -0
  287. package/dist/daemon/backend.rpc-service.js.map +1 -0
  288. package/dist/daemon/daemon-client.d.ts +12 -79
  289. package/dist/daemon/daemon-client.d.ts.map +1 -1
  290. package/dist/daemon/daemon-client.js +28 -270
  291. package/dist/daemon/daemon-client.js.map +1 -1
  292. package/dist/daemon/daemon-entry.d.ts +0 -7
  293. package/dist/daemon/daemon-entry.d.ts.map +1 -1
  294. package/dist/daemon/daemon-entry.js +2 -115
  295. package/dist/daemon/daemon-entry.js.map +1 -1
  296. package/dist/daemon/daemon-main.d.ts +9 -0
  297. package/dist/daemon/daemon-main.d.ts.map +1 -0
  298. package/dist/daemon/daemon-main.js +105 -0
  299. package/dist/daemon/daemon-main.js.map +1 -0
  300. package/dist/daemon/daemon-scheduler.d.ts +8 -5
  301. package/dist/daemon/daemon-scheduler.d.ts.map +1 -1
  302. package/dist/daemon/daemon-scheduler.js +45 -73
  303. package/dist/daemon/daemon-scheduler.js.map +1 -1
  304. package/dist/daemon/daemon-state-store.service.d.ts +5 -39
  305. package/dist/daemon/daemon-state-store.service.d.ts.map +1 -1
  306. package/dist/daemon/daemon-state-store.service.js +30 -17
  307. package/dist/daemon/daemon-state-store.service.js.map +1 -1
  308. package/dist/daemon/daemon.d.ts +50 -79
  309. package/dist/daemon/daemon.d.ts.map +1 -1
  310. package/dist/daemon/daemon.js +769 -442
  311. package/dist/daemon/daemon.js.map +1 -1
  312. package/dist/daemon/daemon.module.d.ts +13 -11
  313. package/dist/daemon/daemon.module.d.ts.map +1 -1
  314. package/dist/daemon/daemon.module.js +139 -106
  315. package/dist/daemon/daemon.module.js.map +1 -1
  316. package/dist/daemon/daemon.rpc-service.d.ts +11 -19
  317. package/dist/daemon/daemon.rpc-service.d.ts.map +1 -1
  318. package/dist/daemon/daemon.rpc-service.js +89 -28
  319. package/dist/daemon/daemon.rpc-service.js.map +1 -1
  320. package/dist/daemon/darwin-owner-evidence.d.ts +57 -0
  321. package/dist/daemon/darwin-owner-evidence.d.ts.map +1 -0
  322. package/dist/daemon/darwin-owner-evidence.js +131 -0
  323. package/dist/daemon/darwin-owner-evidence.js.map +1 -0
  324. package/dist/daemon/database-startup.d.ts +7 -0
  325. package/dist/daemon/database-startup.d.ts.map +1 -0
  326. package/dist/daemon/database-startup.js +40 -0
  327. package/dist/daemon/database-startup.js.map +1 -0
  328. package/dist/daemon/entry-guard.d.ts +2 -0
  329. package/dist/daemon/entry-guard.d.ts.map +1 -0
  330. package/dist/daemon/entry-guard.js +34 -0
  331. package/dist/daemon/entry-guard.js.map +1 -0
  332. package/dist/daemon/execution-capabilities.d.ts +7 -0
  333. package/dist/daemon/execution-capabilities.d.ts.map +1 -0
  334. package/dist/daemon/execution-capabilities.js +23 -0
  335. package/dist/daemon/execution-capabilities.js.map +1 -0
  336. package/dist/daemon/execution-client.d.ts +88 -0
  337. package/dist/daemon/execution-client.d.ts.map +1 -0
  338. package/dist/daemon/execution-client.js +433 -0
  339. package/dist/daemon/execution-client.js.map +1 -0
  340. package/dist/daemon/execution-config.d.ts +7 -0
  341. package/dist/daemon/execution-config.d.ts.map +1 -0
  342. package/dist/daemon/execution-config.js +61 -0
  343. package/dist/daemon/execution-config.js.map +1 -0
  344. package/dist/daemon/execution-entry.d.ts +2 -0
  345. package/dist/daemon/execution-entry.d.ts.map +1 -0
  346. package/dist/daemon/execution-entry.js +3 -0
  347. package/dist/daemon/execution-entry.js.map +1 -0
  348. package/dist/daemon/execution-host.d.ts +133 -0
  349. package/dist/daemon/execution-host.d.ts.map +1 -0
  350. package/dist/daemon/execution-host.js +308 -0
  351. package/dist/daemon/execution-host.js.map +1 -0
  352. package/dist/daemon/execution-journal.d.ts +17 -0
  353. package/dist/daemon/execution-journal.d.ts.map +1 -0
  354. package/dist/daemon/execution-journal.js +75 -0
  355. package/dist/daemon/execution-journal.js.map +1 -0
  356. package/dist/daemon/execution-launcher.d.ts +12 -0
  357. package/dist/daemon/execution-launcher.d.ts.map +1 -0
  358. package/dist/daemon/execution-launcher.js +110 -0
  359. package/dist/daemon/execution-launcher.js.map +1 -0
  360. package/dist/daemon/execution-main.d.ts +2 -0
  361. package/dist/daemon/execution-main.d.ts.map +1 -0
  362. package/dist/daemon/execution-main.js +48 -0
  363. package/dist/daemon/execution-main.js.map +1 -0
  364. package/dist/daemon/execution-owner.d.ts +16 -0
  365. package/dist/daemon/execution-owner.d.ts.map +1 -0
  366. package/dist/daemon/execution-owner.js +97 -0
  367. package/dist/daemon/execution-owner.js.map +1 -0
  368. package/dist/daemon/execution-platform.d.ts +3 -0
  369. package/dist/daemon/execution-platform.d.ts.map +1 -0
  370. package/dist/daemon/execution-platform.js +23 -0
  371. package/dist/daemon/execution-platform.js.map +1 -0
  372. package/dist/daemon/execution-shutdown.d.ts +13 -0
  373. package/dist/daemon/execution-shutdown.d.ts.map +1 -0
  374. package/dist/daemon/execution-shutdown.js +30 -0
  375. package/dist/daemon/execution-shutdown.js.map +1 -0
  376. package/dist/daemon/managed-entry.d.ts +2 -0
  377. package/dist/daemon/managed-entry.d.ts.map +1 -0
  378. package/dist/daemon/managed-entry.js +3 -0
  379. package/dist/daemon/managed-entry.js.map +1 -0
  380. package/dist/daemon/managed-main.d.ts +2 -0
  381. package/dist/daemon/managed-main.d.ts.map +1 -0
  382. package/dist/daemon/managed-main.js +29 -0
  383. package/dist/daemon/managed-main.js.map +1 -0
  384. package/dist/daemon/managed-owner-build.d.ts +17 -0
  385. package/dist/daemon/managed-owner-build.d.ts.map +1 -0
  386. package/dist/daemon/managed-owner-build.js +108 -0
  387. package/dist/daemon/managed-owner-build.js.map +1 -0
  388. package/dist/daemon/managed-owner-entry.d.ts +2 -0
  389. package/dist/daemon/managed-owner-entry.d.ts.map +1 -0
  390. package/dist/daemon/managed-owner-entry.js +3 -0
  391. package/dist/daemon/managed-owner-entry.js.map +1 -0
  392. package/dist/daemon/managed-owner-main.d.ts +2 -0
  393. package/dist/daemon/managed-owner-main.d.ts.map +1 -0
  394. package/dist/daemon/managed-owner-main.js +53 -0
  395. package/dist/daemon/managed-owner-main.js.map +1 -0
  396. package/dist/daemon/managed-runtime.d.ts +39 -0
  397. package/dist/daemon/managed-runtime.d.ts.map +1 -0
  398. package/dist/daemon/managed-runtime.js +137 -0
  399. package/dist/daemon/managed-runtime.js.map +1 -0
  400. package/dist/daemon/network-publication.d.ts +5 -0
  401. package/dist/daemon/network-publication.d.ts.map +1 -0
  402. package/dist/daemon/network-publication.js +25 -0
  403. package/dist/daemon/network-publication.js.map +1 -0
  404. package/dist/daemon/owner-reconciliation.d.ts +58 -0
  405. package/dist/daemon/owner-reconciliation.d.ts.map +1 -0
  406. package/dist/daemon/owner-reconciliation.js +265 -0
  407. package/dist/daemon/owner-reconciliation.js.map +1 -0
  408. package/dist/daemon/pid-manager.d.ts +2 -0
  409. package/dist/daemon/pid-manager.d.ts.map +1 -1
  410. package/dist/daemon/pid-manager.js +5 -0
  411. package/dist/daemon/pid-manager.js.map +1 -1
  412. package/dist/daemon/private-control-client.d.ts +8 -0
  413. package/dist/daemon/private-control-client.d.ts.map +1 -0
  414. package/dist/daemon/private-control-client.js +41 -0
  415. package/dist/daemon/private-control-client.js.map +1 -0
  416. package/dist/daemon/recovery-state.d.ts +20 -0
  417. package/dist/daemon/recovery-state.d.ts.map +1 -0
  418. package/dist/daemon/recovery-state.js +53 -0
  419. package/dist/daemon/recovery-state.js.map +1 -0
  420. package/dist/daemon/rpc-connection.d.ts +29 -0
  421. package/dist/daemon/rpc-connection.d.ts.map +1 -0
  422. package/dist/daemon/rpc-connection.js +137 -0
  423. package/dist/daemon/rpc-connection.js.map +1 -0
  424. package/dist/daemon/runtime-installation.d.ts +58 -0
  425. package/dist/daemon/runtime-installation.d.ts.map +1 -0
  426. package/dist/daemon/runtime-installation.js +346 -0
  427. package/dist/daemon/runtime-installation.js.map +1 -0
  428. package/dist/daemon/runtime-launcher.d.ts +6 -0
  429. package/dist/daemon/runtime-launcher.d.ts.map +1 -0
  430. package/dist/daemon/runtime-launcher.js +45 -0
  431. package/dist/daemon/runtime-launcher.js.map +1 -0
  432. package/dist/daemon/schema-transition.d.ts +43 -0
  433. package/dist/daemon/schema-transition.d.ts.map +1 -0
  434. package/dist/daemon/schema-transition.js +239 -0
  435. package/dist/daemon/schema-transition.js.map +1 -0
  436. package/dist/daemon/spawn-daemon.d.ts +2 -0
  437. package/dist/daemon/spawn-daemon.d.ts.map +1 -1
  438. package/dist/daemon/spawn-daemon.js +4 -0
  439. package/dist/daemon/spawn-daemon.js.map +1 -1
  440. package/dist/daemon/startup-config.d.ts +77 -0
  441. package/dist/daemon/startup-config.d.ts.map +1 -0
  442. package/dist/daemon/startup-config.js +31 -0
  443. package/dist/daemon/startup-config.js.map +1 -0
  444. package/dist/daemon/startup-failure-journal.d.ts +3 -0
  445. package/dist/daemon/startup-failure-journal.d.ts.map +1 -0
  446. package/dist/daemon/startup-failure-journal.js +29 -0
  447. package/dist/daemon/startup-failure-journal.js.map +1 -0
  448. package/dist/daemon/state-store.d.ts +16 -24
  449. package/dist/daemon/state-store.d.ts.map +1 -1
  450. package/dist/daemon/state-store.js +51 -9
  451. package/dist/daemon/state-store.js.map +1 -1
  452. package/dist/daemon/supervisor-transition.d.ts +101 -0
  453. package/dist/daemon/supervisor-transition.d.ts.map +1 -0
  454. package/dist/daemon/supervisor-transition.js +503 -0
  455. package/dist/daemon/supervisor-transition.js.map +1 -0
  456. package/dist/daemon/system-guardian-cgroup.d.ts +16 -0
  457. package/dist/daemon/system-guardian-cgroup.d.ts.map +1 -0
  458. package/dist/daemon/system-guardian-cgroup.js +202 -0
  459. package/dist/daemon/system-guardian-cgroup.js.map +1 -0
  460. package/dist/daemon/system-guardian-unit.d.ts +9 -0
  461. package/dist/daemon/system-guardian-unit.d.ts.map +1 -0
  462. package/dist/daemon/system-guardian-unit.js +41 -0
  463. package/dist/daemon/system-guardian-unit.js.map +1 -0
  464. package/dist/database/connection.d.ts.map +1 -1
  465. package/dist/database/connection.js +2 -6
  466. package/dist/database/connection.js.map +1 -1
  467. package/dist/database/log-durability.d.ts +5 -0
  468. package/dist/database/log-durability.d.ts.map +1 -0
  469. package/dist/database/log-durability.js +28 -0
  470. package/dist/database/log-durability.js.map +1 -0
  471. package/dist/database/migrate.js +2 -15
  472. package/dist/database/migrate.js.map +1 -1
  473. package/dist/database/migration-registry-compatibility.d.ts +13 -0
  474. package/dist/database/migration-registry-compatibility.d.ts.map +1 -0
  475. package/dist/database/migration-registry-compatibility.js +108 -0
  476. package/dist/database/migration-registry-compatibility.js.map +1 -0
  477. package/dist/database/migration-runner.d.ts +8 -42
  478. package/dist/database/migration-runner.d.ts.map +1 -1
  479. package/dist/database/migration-runner.js +114 -123
  480. package/dist/database/migration-runner.js.map +1 -1
  481. package/dist/database/migrations/014_replication_receipts.d.ts +5 -0
  482. package/dist/database/migrations/014_replication_receipts.d.ts.map +1 -0
  483. package/dist/database/migrations/014_replication_receipts.js +6 -0
  484. package/dist/database/migrations/014_replication_receipts.js.map +1 -0
  485. package/dist/database/migrations/015_persistent_metrics.d.ts +5 -0
  486. package/dist/database/migrations/015_persistent_metrics.d.ts.map +1 -0
  487. package/dist/database/migrations/015_persistent_metrics.js +7 -0
  488. package/dist/database/migrations/015_persistent_metrics.js.map +1 -0
  489. package/dist/database/migrations/016_cluster_lease.d.ts +4 -0
  490. package/dist/database/migrations/016_cluster_lease.d.ts.map +1 -0
  491. package/dist/database/migrations/016_cluster_lease.js +6 -0
  492. package/dist/database/migrations/016_cluster_lease.js.map +1 -0
  493. package/dist/database/migrations/index.d.ts +1 -1
  494. package/dist/database/migrations/index.d.ts.map +1 -1
  495. package/dist/database/migrations/index.js +22 -13
  496. package/dist/database/migrations/index.js.map +1 -1
  497. package/dist/database/schema-compatibility.d.ts +34 -0
  498. package/dist/database/schema-compatibility.d.ts.map +1 -0
  499. package/dist/database/schema-compatibility.js +109 -0
  500. package/dist/database/schema-compatibility.js.map +1 -0
  501. package/dist/database/schema-expansion-policy.d.ts +10 -0
  502. package/dist/database/schema-expansion-policy.d.ts.map +1 -0
  503. package/dist/database/schema-expansion-policy.js +21 -0
  504. package/dist/database/schema-expansion-policy.js.map +1 -0
  505. package/dist/database/schema-transition-plan.d.ts +53 -0
  506. package/dist/database/schema-transition-plan.d.ts.map +1 -0
  507. package/dist/database/schema-transition-plan.js +102 -0
  508. package/dist/database/schema-transition-plan.js.map +1 -0
  509. package/dist/database/schema-worker.d.ts +2 -0
  510. package/dist/database/schema-worker.d.ts.map +1 -0
  511. package/dist/database/schema-worker.js +55 -0
  512. package/dist/database/schema-worker.js.map +1 -0
  513. package/dist/database/schema.d.ts +6 -1
  514. package/dist/database/schema.d.ts.map +1 -1
  515. package/dist/database/slave-migrations/001_replication_evidence.d.ts +4 -0
  516. package/dist/database/slave-migrations/001_replication_evidence.d.ts.map +1 -0
  517. package/dist/database/slave-migrations/001_replication_evidence.js +89 -0
  518. package/dist/database/slave-migrations/001_replication_evidence.js.map +1 -0
  519. package/dist/database/slave-migrations/index.d.ts +6 -0
  520. package/dist/database/slave-migrations/index.d.ts.map +1 -0
  521. package/dist/database/slave-migrations/index.js +10 -0
  522. package/dist/database/slave-migrations/index.js.map +1 -0
  523. package/dist/diagnostics/index.d.ts +16 -0
  524. package/dist/diagnostics/index.d.ts.map +1 -0
  525. package/dist/diagnostics/index.js +22 -0
  526. package/dist/diagnostics/index.js.map +1 -0
  527. package/dist/execution/command-failure.d.ts +7 -0
  528. package/dist/execution/command-failure.d.ts.map +1 -0
  529. package/dist/execution/command-failure.js +29 -0
  530. package/dist/execution/command-failure.js.map +1 -0
  531. package/dist/execution/data-channel.d.ts +1 -1
  532. package/dist/execution/data-channel.js +1 -1
  533. package/dist/execution/execution.service.d.ts +16 -4
  534. package/dist/execution/execution.service.d.ts.map +1 -1
  535. package/dist/execution/execution.service.js +133 -74
  536. package/dist/execution/execution.service.js.map +1 -1
  537. package/dist/files/archive-codec.d.ts +57 -0
  538. package/dist/files/archive-codec.d.ts.map +1 -0
  539. package/dist/files/archive-codec.js +454 -0
  540. package/dist/files/archive-codec.js.map +1 -0
  541. package/dist/files/archive-node.d.ts +27 -0
  542. package/dist/files/archive-node.d.ts.map +1 -0
  543. package/dist/files/archive-node.js +379 -0
  544. package/dist/files/archive-node.js.map +1 -0
  545. package/dist/files/archive-publication.d.ts +26 -0
  546. package/dist/files/archive-publication.d.ts.map +1 -0
  547. package/dist/files/archive-publication.js +224 -0
  548. package/dist/files/archive-publication.js.map +1 -0
  549. package/dist/files/file-config.d.ts +7 -0
  550. package/dist/files/file-config.d.ts.map +1 -0
  551. package/dist/files/file-config.js +11 -0
  552. package/dist/files/file-config.js.map +1 -0
  553. package/dist/files/file-node.d.ts +65 -0
  554. package/dist/files/file-node.d.ts.map +1 -0
  555. package/dist/files/file-node.js +863 -0
  556. package/dist/files/file-node.js.map +1 -0
  557. package/dist/files/file-node.rpc-service.d.ts +12 -0
  558. package/dist/files/file-node.rpc-service.d.ts.map +1 -0
  559. package/dist/files/file-node.rpc-service.js +42 -0
  560. package/dist/files/file-node.rpc-service.js.map +1 -0
  561. package/dist/files/files.rpc-service.d.ts +107 -0
  562. package/dist/files/files.rpc-service.d.ts.map +1 -0
  563. package/dist/files/files.rpc-service.js +769 -0
  564. package/dist/files/files.rpc-service.js.map +1 -0
  565. package/dist/files/structural-policy.d.ts +3 -0
  566. package/dist/files/structural-policy.d.ts.map +1 -0
  567. package/dist/files/structural-policy.js +27 -0
  568. package/dist/files/structural-policy.js.map +1 -0
  569. package/dist/health/contracts.d.ts +30 -0
  570. package/dist/health/contracts.d.ts.map +1 -0
  571. package/dist/health/contracts.js +58 -0
  572. package/dist/health/contracts.js.map +1 -0
  573. package/dist/health/heartbeat.d.ts +11 -0
  574. package/dist/health/heartbeat.d.ts.map +1 -0
  575. package/dist/health/heartbeat.js +32 -0
  576. package/dist/health/heartbeat.js.map +1 -0
  577. package/dist/health/index.d.ts +4 -0
  578. package/dist/health/index.d.ts.map +1 -0
  579. package/dist/health/index.js +2 -0
  580. package/dist/health/index.js.map +1 -0
  581. package/dist/health/readiness.d.ts +15 -0
  582. package/dist/health/readiness.d.ts.map +1 -0
  583. package/dist/health/readiness.js +170 -0
  584. package/dist/health/readiness.js.map +1 -0
  585. package/dist/index.d.ts +1 -0
  586. package/dist/index.d.ts.map +1 -1
  587. package/dist/infrastructure/apt-packages.d.ts +34 -0
  588. package/dist/infrastructure/apt-packages.d.ts.map +1 -0
  589. package/dist/infrastructure/apt-packages.js +232 -0
  590. package/dist/infrastructure/apt-packages.js.map +1 -0
  591. package/dist/infrastructure/bare-metal-plan.d.ts +10 -1
  592. package/dist/infrastructure/bare-metal-plan.d.ts.map +1 -1
  593. package/dist/infrastructure/bare-metal-plan.js +22 -1
  594. package/dist/infrastructure/bare-metal-plan.js.map +1 -1
  595. package/dist/infrastructure/bare-metal-runner.d.ts.map +1 -1
  596. package/dist/infrastructure/bare-metal-runner.js +13 -2
  597. package/dist/infrastructure/bare-metal-runner.js.map +1 -1
  598. package/dist/infrastructure/config-normalizer.d.ts +4 -3
  599. package/dist/infrastructure/config-normalizer.d.ts.map +1 -1
  600. package/dist/infrastructure/config-normalizer.js +11 -3
  601. package/dist/infrastructure/config-normalizer.js.map +1 -1
  602. package/dist/infrastructure/config-payload.d.ts +4 -4
  603. package/dist/infrastructure/config-payload.js +4 -4
  604. package/dist/infrastructure/container-runtime.d.ts +39 -13
  605. package/dist/infrastructure/container-runtime.d.ts.map +1 -1
  606. package/dist/infrastructure/container-runtime.js +276 -84
  607. package/dist/infrastructure/container-runtime.js.map +1 -1
  608. package/dist/infrastructure/gateway-redis-db.d.ts +2 -2
  609. package/dist/infrastructure/gateway-redis-db.js +2 -2
  610. package/dist/infrastructure/health-recovery.d.ts +19 -0
  611. package/dist/infrastructure/health-recovery.d.ts.map +1 -0
  612. package/dist/infrastructure/health-recovery.js +39 -0
  613. package/dist/infrastructure/health-recovery.js.map +1 -0
  614. package/dist/infrastructure/host-ingress-config.d.ts +12 -0
  615. package/dist/infrastructure/host-ingress-config.d.ts.map +1 -0
  616. package/dist/infrastructure/host-ingress-config.js +200 -0
  617. package/dist/infrastructure/host-ingress-config.js.map +1 -0
  618. package/dist/infrastructure/host-ingress-lock.d.ts +3 -0
  619. package/dist/infrastructure/host-ingress-lock.d.ts.map +1 -0
  620. package/dist/infrastructure/host-ingress-lock.js +2 -0
  621. package/dist/infrastructure/host-ingress-lock.js.map +1 -0
  622. package/dist/infrastructure/host-ingress-runtime.d.ts +25 -0
  623. package/dist/infrastructure/host-ingress-runtime.d.ts.map +1 -0
  624. package/dist/infrastructure/host-ingress-runtime.js +114 -0
  625. package/dist/infrastructure/host-ingress-runtime.js.map +1 -0
  626. package/dist/infrastructure/host-ingress-takeover.d.ts +18 -0
  627. package/dist/infrastructure/host-ingress-takeover.d.ts.map +1 -0
  628. package/dist/infrastructure/host-ingress-takeover.js +142 -0
  629. package/dist/infrastructure/host-ingress-takeover.js.map +1 -0
  630. package/dist/infrastructure/host-ingress-types.d.ts +175 -0
  631. package/dist/infrastructure/host-ingress-types.d.ts.map +1 -0
  632. package/dist/infrastructure/host-ingress-types.js +2 -0
  633. package/dist/infrastructure/host-ingress-types.js.map +1 -0
  634. package/dist/infrastructure/host-ingress.service.d.ts +47 -0
  635. package/dist/infrastructure/host-ingress.service.d.ts.map +1 -0
  636. package/dist/infrastructure/host-ingress.service.js +514 -0
  637. package/dist/infrastructure/host-ingress.service.js.map +1 -0
  638. package/dist/infrastructure/host-inspection.d.ts +1 -0
  639. package/dist/infrastructure/host-inspection.d.ts.map +1 -1
  640. package/dist/infrastructure/host-inspection.js +3 -2
  641. package/dist/infrastructure/host-inspection.js.map +1 -1
  642. package/dist/infrastructure/infrastructure.service.d.ts +101 -34
  643. package/dist/infrastructure/infrastructure.service.d.ts.map +1 -1
  644. package/dist/infrastructure/infrastructure.service.js +631 -205
  645. package/dist/infrastructure/infrastructure.service.js.map +1 -1
  646. package/dist/infrastructure/merge-config.d.ts +10 -0
  647. package/dist/infrastructure/merge-config.d.ts.map +1 -0
  648. package/dist/infrastructure/merge-config.js +27 -0
  649. package/dist/infrastructure/merge-config.js.map +1 -0
  650. package/dist/infrastructure/orphan-containers.d.ts +8 -7
  651. package/dist/infrastructure/orphan-containers.d.ts.map +1 -1
  652. package/dist/infrastructure/orphan-containers.js +7 -7
  653. package/dist/infrastructure/orphan-containers.js.map +1 -1
  654. package/dist/infrastructure/owned-container.d.ts +4 -0
  655. package/dist/infrastructure/owned-container.d.ts.map +1 -0
  656. package/dist/infrastructure/owned-container.js +13 -0
  657. package/dist/infrastructure/owned-container.js.map +1 -0
  658. package/dist/infrastructure/phantom-endpoint-janitor.d.ts +4 -1
  659. package/dist/infrastructure/phantom-endpoint-janitor.d.ts.map +1 -1
  660. package/dist/infrastructure/phantom-endpoint-janitor.js +11 -2
  661. package/dist/infrastructure/phantom-endpoint-janitor.js.map +1 -1
  662. package/dist/infrastructure/presets/minio.d.ts.map +1 -1
  663. package/dist/infrastructure/presets/minio.js +15 -25
  664. package/dist/infrastructure/presets/minio.js.map +1 -1
  665. package/dist/infrastructure/presets/postgres.d.ts.map +1 -1
  666. package/dist/infrastructure/presets/postgres.js +35 -31
  667. package/dist/infrastructure/presets/postgres.js.map +1 -1
  668. package/dist/infrastructure/presets/tor.d.ts +1 -2
  669. package/dist/infrastructure/presets/tor.d.ts.map +1 -1
  670. package/dist/infrastructure/presets/tor.js +7 -13
  671. package/dist/infrastructure/presets/tor.js.map +1 -1
  672. package/dist/infrastructure/provisioning-outcome.d.ts +8 -1
  673. package/dist/infrastructure/provisioning-outcome.d.ts.map +1 -1
  674. package/dist/infrastructure/provisioning-outcome.js +42 -9
  675. package/dist/infrastructure/provisioning-outcome.js.map +1 -1
  676. package/dist/infrastructure/service-binding.js +1 -1
  677. package/dist/infrastructure/service-resolver.d.ts +11 -5
  678. package/dist/infrastructure/service-resolver.d.ts.map +1 -1
  679. package/dist/infrastructure/service-resolver.js +109 -54
  680. package/dist/infrastructure/service-resolver.js.map +1 -1
  681. package/dist/infrastructure/shipped-config.js +4 -4
  682. package/dist/infrastructure/stack-infra-manager.d.ts +35 -5
  683. package/dist/infrastructure/stack-infra-manager.d.ts.map +1 -1
  684. package/dist/infrastructure/stack-infra-manager.js +227 -57
  685. package/dist/infrastructure/stack-infra-manager.js.map +1 -1
  686. package/dist/infrastructure/types.d.ts +68 -9
  687. package/dist/infrastructure/types.d.ts.map +1 -1
  688. package/dist/mcp/mcp-bridge.js +1 -1
  689. package/dist/mcp/mcp-bridge.js.map +1 -1
  690. package/dist/mcp/monitoring-reading.d.ts +18 -0
  691. package/dist/mcp/monitoring-reading.d.ts.map +1 -0
  692. package/dist/mcp/monitoring-reading.js +84 -0
  693. package/dist/mcp/monitoring-reading.js.map +1 -0
  694. package/dist/mcp/tool-groups/apps.tools.d.ts.map +1 -1
  695. package/dist/mcp/tool-groups/apps.tools.js +6 -4
  696. package/dist/mcp/tool-groups/apps.tools.js.map +1 -1
  697. package/dist/mcp/tool-groups/management.tools.d.ts +2 -0
  698. package/dist/mcp/tool-groups/management.tools.d.ts.map +1 -1
  699. package/dist/mcp/tool-groups/management.tools.js +17 -38
  700. package/dist/mcp/tool-groups/management.tools.js.map +1 -1
  701. package/dist/mcp/tool-groups/monitoring.tools.d.ts.map +1 -1
  702. package/dist/mcp/tool-groups/monitoring.tools.js +45 -2
  703. package/dist/mcp/tool-groups/monitoring.tools.js.map +1 -1
  704. package/dist/mcp/unavailable-tools.js +2 -2
  705. package/dist/mcp/unavailable-tools.js.map +1 -1
  706. package/dist/migration/configuration.d.ts +8 -0
  707. package/dist/migration/configuration.d.ts.map +1 -0
  708. package/dist/migration/configuration.js +16 -0
  709. package/dist/migration/configuration.js.map +1 -0
  710. package/dist/migration/index.d.ts +25 -0
  711. package/dist/migration/index.d.ts.map +1 -0
  712. package/dist/migration/index.js +27 -0
  713. package/dist/migration/index.js.map +1 -0
  714. package/dist/migration/operation.d.ts +31 -0
  715. package/dist/migration/operation.d.ts.map +1 -0
  716. package/dist/migration/operation.js +67 -0
  717. package/dist/migration/operation.js.map +1 -0
  718. package/dist/migration/workspace.d.ts +28 -0
  719. package/dist/migration/workspace.d.ts.map +1 -0
  720. package/dist/migration/workspace.js +91 -0
  721. package/dist/migration/workspace.js.map +1 -0
  722. package/dist/monitoring/app-health.indicator.d.ts +1 -1
  723. package/dist/monitoring/app-health.indicator.d.ts.map +1 -1
  724. package/dist/monitoring/docker-health.indicator.d.ts +4 -2
  725. package/dist/monitoring/docker-health.indicator.d.ts.map +1 -1
  726. package/dist/monitoring/docker-health.indicator.js +66 -5
  727. package/dist/monitoring/docker-health.indicator.js.map +1 -1
  728. package/dist/monitoring/event-loop-watch.d.ts.map +1 -1
  729. package/dist/monitoring/event-loop-watch.js.map +1 -1
  730. package/dist/monitoring/infrastructure-health.d.ts +15 -0
  731. package/dist/monitoring/infrastructure-health.d.ts.map +1 -0
  732. package/dist/monitoring/infrastructure-health.js +2 -0
  733. package/dist/monitoring/infrastructure-health.js.map +1 -0
  734. package/dist/monitoring/log-entry.d.ts +7 -0
  735. package/dist/monitoring/log-entry.d.ts.map +1 -0
  736. package/dist/monitoring/log-entry.js +16 -0
  737. package/dist/monitoring/log-entry.js.map +1 -0
  738. package/dist/monitoring/log-journal.d.ts +40 -0
  739. package/dist/monitoring/log-journal.d.ts.map +1 -0
  740. package/dist/monitoring/log-journal.js +158 -0
  741. package/dist/monitoring/log-journal.js.map +1 -0
  742. package/dist/monitoring/log-line.d.ts +22 -17
  743. package/dist/monitoring/log-line.d.ts.map +1 -1
  744. package/dist/monitoring/log-line.js +73 -62
  745. package/dist/monitoring/log-line.js.map +1 -1
  746. package/dist/monitoring/log-manager.d.ts +37 -40
  747. package/dist/monitoring/log-manager.d.ts.map +1 -1
  748. package/dist/monitoring/log-manager.js +167 -66
  749. package/dist/monitoring/log-manager.js.map +1 -1
  750. package/dist/monitoring/log-sink-health.indicator.d.ts +10 -0
  751. package/dist/monitoring/log-sink-health.indicator.d.ts.map +1 -0
  752. package/dist/monitoring/log-sink-health.indicator.js +21 -0
  753. package/dist/monitoring/log-sink-health.indicator.js.map +1 -0
  754. package/dist/monitoring/metrics-storage.indicator.d.ts +9 -0
  755. package/dist/monitoring/metrics-storage.indicator.d.ts.map +1 -0
  756. package/dist/monitoring/metrics-storage.indicator.js +18 -0
  757. package/dist/monitoring/metrics-storage.indicator.js.map +1 -0
  758. package/dist/monitoring/process-lifetime.d.ts +11 -0
  759. package/dist/monitoring/process-lifetime.d.ts.map +1 -0
  760. package/dist/monitoring/process-lifetime.js +45 -0
  761. package/dist/monitoring/process-lifetime.js.map +1 -0
  762. package/dist/monitoring/runtime-diagnostics.d.ts +47 -0
  763. package/dist/monitoring/runtime-diagnostics.d.ts.map +1 -0
  764. package/dist/monitoring/runtime-diagnostics.js +88 -0
  765. package/dist/monitoring/runtime-diagnostics.js.map +1 -0
  766. package/dist/observability/metrics-bridge.d.ts +5 -1
  767. package/dist/observability/metrics-bridge.d.ts.map +1 -1
  768. package/dist/observability/metrics-bridge.js +11 -0
  769. package/dist/observability/metrics-bridge.js.map +1 -1
  770. package/dist/operations.d.ts +17 -0
  771. package/dist/operations.d.ts.map +1 -0
  772. package/dist/operations.js +13 -0
  773. package/dist/operations.js.map +1 -0
  774. package/dist/orchestrator/app-handle.d.ts +27 -9
  775. package/dist/orchestrator/app-handle.d.ts.map +1 -1
  776. package/dist/orchestrator/app-handle.js +42 -11
  777. package/dist/orchestrator/app-handle.js.map +1 -1
  778. package/dist/orchestrator/application-runtime-child.d.ts +2 -0
  779. package/dist/orchestrator/application-runtime-child.d.ts.map +1 -0
  780. package/dist/orchestrator/application-runtime-child.js +15 -0
  781. package/dist/orchestrator/application-runtime-child.js.map +1 -0
  782. package/dist/orchestrator/application-runtime-resolution.d.ts +4 -0
  783. package/dist/orchestrator/application-runtime-resolution.d.ts.map +1 -0
  784. package/dist/orchestrator/application-runtime-resolution.js +62 -0
  785. package/dist/orchestrator/application-runtime-resolution.js.map +1 -0
  786. package/dist/orchestrator/application-runtime.d.ts +3 -0
  787. package/dist/orchestrator/application-runtime.d.ts.map +1 -0
  788. package/dist/orchestrator/application-runtime.js +20 -0
  789. package/dist/orchestrator/application-runtime.js.map +1 -0
  790. package/dist/orchestrator/application-topology.d.ts +20 -0
  791. package/dist/orchestrator/application-topology.d.ts.map +1 -0
  792. package/dist/orchestrator/application-topology.js +90 -0
  793. package/dist/orchestrator/application-topology.js.map +1 -0
  794. package/dist/orchestrator/bootstrap-loader-child.d.ts +1 -1
  795. package/dist/orchestrator/bootstrap-loader-child.js +7 -16
  796. package/dist/orchestrator/bootstrap-loader-child.js.map +1 -1
  797. package/dist/orchestrator/bootstrap-loader.d.ts +10 -20
  798. package/dist/orchestrator/bootstrap-loader.d.ts.map +1 -1
  799. package/dist/orchestrator/bootstrap-loader.js +24 -207
  800. package/dist/orchestrator/bootstrap-loader.js.map +1 -1
  801. package/dist/orchestrator/bootstrap-process.d.ts +6 -6
  802. package/dist/orchestrator/bootstrap-process.d.ts.map +1 -1
  803. package/dist/orchestrator/bootstrap-process.js +40 -40
  804. package/dist/orchestrator/bootstrap-process.js.map +1 -1
  805. package/dist/orchestrator/build-service.d.ts +8 -14
  806. package/dist/orchestrator/build-service.d.ts.map +1 -1
  807. package/dist/orchestrator/build-service.js +144 -158
  808. package/dist/orchestrator/build-service.js.map +1 -1
  809. package/dist/orchestrator/call-exposed-service.d.ts +8 -0
  810. package/dist/orchestrator/call-exposed-service.d.ts.map +1 -1
  811. package/dist/orchestrator/call-exposed-service.js +1 -1
  812. package/dist/orchestrator/classic-launcher.d.ts +3 -2
  813. package/dist/orchestrator/classic-launcher.d.ts.map +1 -1
  814. package/dist/orchestrator/classic-launcher.js +32 -23
  815. package/dist/orchestrator/classic-launcher.js.map +1 -1
  816. package/dist/orchestrator/dependency-resolver.d.ts.map +1 -1
  817. package/dist/orchestrator/dependency-resolver.js +7 -38
  818. package/dist/orchestrator/dependency-resolver.js.map +1 -1
  819. package/dist/orchestrator/execution-contract.d.ts +67 -0
  820. package/dist/orchestrator/execution-contract.d.ts.map +1 -0
  821. package/dist/orchestrator/execution-contract.js +2 -0
  822. package/dist/orchestrator/execution-contract.js.map +1 -0
  823. package/dist/orchestrator/file-watcher.d.ts +2 -1
  824. package/dist/orchestrator/file-watcher.d.ts.map +1 -1
  825. package/dist/orchestrator/file-watcher.js +23 -5
  826. package/dist/orchestrator/file-watcher.js.map +1 -1
  827. package/dist/orchestrator/http-routes.d.ts +4 -0
  828. package/dist/orchestrator/http-routes.d.ts.map +1 -0
  829. package/dist/orchestrator/http-routes.js +19 -0
  830. package/dist/orchestrator/http-routes.js.map +1 -0
  831. package/dist/orchestrator/installed-execution.d.ts +7 -0
  832. package/dist/orchestrator/installed-execution.d.ts.map +1 -0
  833. package/dist/orchestrator/installed-execution.js +25 -0
  834. package/dist/orchestrator/installed-execution.js.map +1 -0
  835. package/dist/orchestrator/module-worker-process.d.ts.map +1 -1
  836. package/dist/orchestrator/module-worker-process.js +2 -1
  837. package/dist/orchestrator/module-worker-process.js.map +1 -1
  838. package/dist/orchestrator/orchestrator.service.d.ts +105 -80
  839. package/dist/orchestrator/orchestrator.service.d.ts.map +1 -1
  840. package/dist/orchestrator/orchestrator.service.js +1084 -571
  841. package/dist/orchestrator/orchestrator.service.js.map +1 -1
  842. package/dist/orchestrator/process-janitor.d.ts +3 -0
  843. package/dist/orchestrator/process-janitor.d.ts.map +1 -1
  844. package/dist/orchestrator/process-janitor.js +5 -1
  845. package/dist/orchestrator/process-janitor.js.map +1 -1
  846. package/dist/orchestrator/runtime-package-resolution.d.ts +8 -0
  847. package/dist/orchestrator/runtime-package-resolution.d.ts.map +1 -0
  848. package/dist/orchestrator/runtime-package-resolution.js +56 -0
  849. package/dist/orchestrator/runtime-package-resolution.js.map +1 -0
  850. package/dist/orchestrator/service-router.d.ts +4 -108
  851. package/dist/orchestrator/service-router.d.ts.map +1 -1
  852. package/dist/orchestrator/service-router.js +51 -237
  853. package/dist/orchestrator/service-router.js.map +1 -1
  854. package/dist/orchestrator/topology-query.d.ts +1 -1
  855. package/dist/orchestrator/topology-query.js +1 -1
  856. package/dist/orchestrator/ts-compiler.d.ts.map +1 -1
  857. package/dist/orchestrator/ts-compiler.js +9 -17
  858. package/dist/orchestrator/ts-compiler.js.map +1 -1
  859. package/dist/project/artifact-builder.d.ts +17 -7
  860. package/dist/project/artifact-builder.d.ts.map +1 -1
  861. package/dist/project/artifact-builder.js +91 -58
  862. package/dist/project/artifact-builder.js.map +1 -1
  863. package/dist/project/bootstrap-metadata.d.ts +42 -0
  864. package/dist/project/bootstrap-metadata.d.ts.map +1 -0
  865. package/dist/project/bootstrap-metadata.js +76 -0
  866. package/dist/project/bootstrap-metadata.js.map +1 -0
  867. package/dist/project/build-decision.d.ts +1 -1
  868. package/dist/project/build-decision.js +1 -1
  869. package/dist/project/config-resolver.js +4 -4
  870. package/dist/project/config-resolver.js.map +1 -1
  871. package/dist/project/configuration-catalog.d.ts +8 -0
  872. package/dist/project/configuration-catalog.d.ts.map +1 -0
  873. package/dist/project/configuration-catalog.js +29 -0
  874. package/dist/project/configuration-catalog.js.map +1 -0
  875. package/dist/project/declared-config.d.ts +4 -2
  876. package/dist/project/declared-config.d.ts.map +1 -1
  877. package/dist/project/declared-config.js +10 -7
  878. package/dist/project/declared-config.js.map +1 -1
  879. package/dist/project/dependency-topology.d.ts +10 -0
  880. package/dist/project/dependency-topology.d.ts.map +1 -0
  881. package/dist/project/dependency-topology.js +55 -0
  882. package/dist/project/dependency-topology.js.map +1 -0
  883. package/dist/project/deploy-phases.d.ts +1 -1
  884. package/dist/project/deploy-phases.js +1 -1
  885. package/dist/project/exec-in-group.d.ts +1 -1
  886. package/dist/project/exec-in-group.js +1 -1
  887. package/dist/project/infrastructure-ownership.d.ts +5 -0
  888. package/dist/project/infrastructure-ownership.d.ts.map +1 -0
  889. package/dist/project/infrastructure-ownership.js +26 -0
  890. package/dist/project/infrastructure-ownership.js.map +1 -0
  891. package/dist/project/installed-stack-resume.d.ts +62 -0
  892. package/dist/project/installed-stack-resume.d.ts.map +1 -0
  893. package/dist/project/installed-stack-resume.js +261 -0
  894. package/dist/project/installed-stack-resume.js.map +1 -0
  895. package/dist/project/launch-failure.d.ts +3 -0
  896. package/dist/project/launch-failure.d.ts.map +1 -0
  897. package/dist/project/launch-failure.js +32 -0
  898. package/dist/project/launch-failure.js.map +1 -0
  899. package/dist/project/local-release-selection.d.ts +18 -0
  900. package/dist/project/local-release-selection.d.ts.map +1 -0
  901. package/dist/project/local-release-selection.js +36 -0
  902. package/dist/project/local-release-selection.js.map +1 -0
  903. package/dist/project/node-app-config.d.ts +10 -3
  904. package/dist/project/node-app-config.d.ts.map +1 -1
  905. package/dist/project/node-app-config.js +22 -30
  906. package/dist/project/node-app-config.js.map +1 -1
  907. package/dist/project/node-app-health.d.ts +1 -1
  908. package/dist/project/node-app-health.js +1 -1
  909. package/dist/project/node-stack-stop.d.ts +83 -0
  910. package/dist/project/node-stack-stop.d.ts.map +1 -0
  911. package/dist/project/node-stack-stop.js +219 -0
  912. package/dist/project/node-stack-stop.js.map +1 -0
  913. package/dist/project/operator-account.d.ts +9 -3
  914. package/dist/project/operator-account.d.ts.map +1 -1
  915. package/dist/project/operator-account.js +9 -9
  916. package/dist/project/operator-account.js.map +1 -1
  917. package/dist/project/public-stack.d.ts +4 -0
  918. package/dist/project/public-stack.d.ts.map +1 -0
  919. package/dist/project/public-stack.js +29 -0
  920. package/dist/project/public-stack.js.map +1 -0
  921. package/dist/project/registry.d.ts +18 -27
  922. package/dist/project/registry.d.ts.map +1 -1
  923. package/dist/project/registry.js +248 -77
  924. package/dist/project/registry.js.map +1 -1
  925. package/dist/project/requirements-scanner.d.ts +4 -8
  926. package/dist/project/requirements-scanner.d.ts.map +1 -1
  927. package/dist/project/requirements-scanner.js +39 -146
  928. package/dist/project/requirements-scanner.js.map +1 -1
  929. package/dist/project/stack-diagnosis.d.ts +18 -0
  930. package/dist/project/stack-diagnosis.d.ts.map +1 -0
  931. package/dist/project/stack-diagnosis.js +94 -0
  932. package/dist/project/stack-diagnosis.js.map +1 -0
  933. package/dist/project/stack-env.d.ts +1 -1
  934. package/dist/project/stack-env.js +1 -1
  935. package/dist/project/stack-health.d.ts +12 -0
  936. package/dist/project/stack-health.d.ts.map +1 -0
  937. package/dist/project/stack-health.js +27 -0
  938. package/dist/project/stack-health.js.map +1 -0
  939. package/dist/project/stack-observation.d.ts +8 -0
  940. package/dist/project/stack-observation.d.ts.map +1 -0
  941. package/dist/project/stack-observation.js +126 -0
  942. package/dist/project/stack-observation.js.map +1 -0
  943. package/dist/project/stack-placement.d.ts +11 -0
  944. package/dist/project/stack-placement.d.ts.map +1 -0
  945. package/dist/project/stack-placement.js +57 -0
  946. package/dist/project/stack-placement.js.map +1 -0
  947. package/dist/project/stack-stop-review.d.ts +14 -0
  948. package/dist/project/stack-stop-review.d.ts.map +1 -0
  949. package/dist/project/stack-stop-review.js +22 -0
  950. package/dist/project/stack-stop-review.js.map +1 -0
  951. package/dist/project/stack-targets.d.ts +24 -0
  952. package/dist/project/stack-targets.d.ts.map +1 -0
  953. package/dist/project/stack-targets.js +67 -0
  954. package/dist/project/stack-targets.js.map +1 -0
  955. package/dist/project/stand-containers.d.ts +9 -2
  956. package/dist/project/stand-containers.d.ts.map +1 -1
  957. package/dist/project/stand-containers.js +17 -17
  958. package/dist/project/stand-containers.js.map +1 -1
  959. package/dist/project/topology-control.d.ts +41 -0
  960. package/dist/project/topology-control.d.ts.map +1 -0
  961. package/dist/project/topology-control.js +133 -0
  962. package/dist/project/topology-control.js.map +1 -0
  963. package/dist/project/topology-plan.d.ts +11 -0
  964. package/dist/project/topology-plan.d.ts.map +1 -0
  965. package/dist/project/topology-plan.js +154 -0
  966. package/dist/project/topology-plan.js.map +1 -0
  967. package/dist/project/topology-services.d.ts +7 -0
  968. package/dist/project/topology-services.d.ts.map +1 -0
  969. package/dist/project/topology-services.js +36 -0
  970. package/dist/project/topology-services.js.map +1 -0
  971. package/dist/project/topology-state.d.ts +27 -0
  972. package/dist/project/topology-state.d.ts.map +1 -0
  973. package/dist/project/topology-state.js +71 -0
  974. package/dist/project/topology-state.js.map +1 -0
  975. package/dist/project/workspace-kind.d.ts +3 -0
  976. package/dist/project/workspace-kind.d.ts.map +1 -0
  977. package/dist/project/workspace-kind.js +13 -0
  978. package/dist/project/workspace-kind.js.map +1 -0
  979. package/dist/readiness.d.ts +4 -0
  980. package/dist/readiness.d.ts.map +1 -0
  981. package/dist/readiness.js +3 -0
  982. package/dist/readiness.js.map +1 -0
  983. package/dist/release/application-closure.d.ts +4 -0
  984. package/dist/release/application-closure.d.ts.map +1 -0
  985. package/dist/release/application-closure.js +61 -0
  986. package/dist/release/application-closure.js.map +1 -0
  987. package/dist/release/archive.d.ts +3 -0
  988. package/dist/release/archive.d.ts.map +1 -0
  989. package/dist/release/archive.js +3 -0
  990. package/dist/release/archive.js.map +1 -0
  991. package/dist/release/artifact-inspection.d.ts +50 -0
  992. package/dist/release/artifact-inspection.d.ts.map +1 -0
  993. package/dist/release/artifact-inspection.js +169 -0
  994. package/dist/release/artifact-inspection.js.map +1 -0
  995. package/dist/release/artifact-store.d.ts +1 -1
  996. package/dist/release/artifact-store.d.ts.map +1 -1
  997. package/dist/release/artifact-store.js +1 -1
  998. package/dist/release/artifact-store.js.map +1 -1
  999. package/dist/release/artifact-volumes.d.ts +10 -0
  1000. package/dist/release/artifact-volumes.d.ts.map +1 -0
  1001. package/dist/release/artifact-volumes.js +112 -0
  1002. package/dist/release/artifact-volumes.js.map +1 -0
  1003. package/dist/release/attest-on-node.d.ts +3 -2
  1004. package/dist/release/attest-on-node.d.ts.map +1 -1
  1005. package/dist/release/attest-on-node.js +6 -6
  1006. package/dist/release/attest-on-node.js.map +1 -1
  1007. package/dist/release/attest.d.ts +3 -3
  1008. package/dist/release/attest.js +1 -1
  1009. package/dist/release/build-run.d.ts +14 -17
  1010. package/dist/release/build-run.d.ts.map +1 -1
  1011. package/dist/release/build-run.js +264 -77
  1012. package/dist/release/build-run.js.map +1 -1
  1013. package/dist/release/builder.d.ts +9 -3
  1014. package/dist/release/builder.d.ts.map +1 -1
  1015. package/dist/release/builder.js +19 -5
  1016. package/dist/release/builder.js.map +1 -1
  1017. package/dist/release/closure-library-path.d.ts +26 -0
  1018. package/dist/release/closure-library-path.d.ts.map +1 -0
  1019. package/dist/release/closure-library-path.js +160 -0
  1020. package/dist/release/closure-library-path.js.map +1 -0
  1021. package/dist/release/definition-inputs.d.ts +7 -4
  1022. package/dist/release/definition-inputs.d.ts.map +1 -1
  1023. package/dist/release/definition-inputs.js +146 -15
  1024. package/dist/release/definition-inputs.js.map +1 -1
  1025. package/dist/release/framework-source.d.ts +22 -0
  1026. package/dist/release/framework-source.d.ts.map +1 -0
  1027. package/dist/release/framework-source.js +54 -0
  1028. package/dist/release/framework-source.js.map +1 -0
  1029. package/dist/release/frozen-installation.d.ts +23 -0
  1030. package/dist/release/frozen-installation.d.ts.map +1 -0
  1031. package/dist/release/frozen-installation.js +159 -0
  1032. package/dist/release/frozen-installation.js.map +1 -0
  1033. package/dist/release/import-artifacts.d.ts +9 -0
  1034. package/dist/release/import-artifacts.d.ts.map +1 -0
  1035. package/dist/release/import-artifacts.js +60 -0
  1036. package/dist/release/import-artifacts.js.map +1 -0
  1037. package/dist/release/infrastructure.d.ts +6 -0
  1038. package/dist/release/infrastructure.d.ts.map +1 -0
  1039. package/dist/release/infrastructure.js +74 -0
  1040. package/dist/release/infrastructure.js.map +1 -0
  1041. package/dist/release/installed-artifacts.d.ts +12 -0
  1042. package/dist/release/installed-artifacts.d.ts.map +1 -0
  1043. package/dist/release/installed-artifacts.js +199 -0
  1044. package/dist/release/installed-artifacts.js.map +1 -0
  1045. package/dist/release/installed-graph.d.ts +28 -0
  1046. package/dist/release/installed-graph.d.ts.map +1 -0
  1047. package/dist/release/installed-graph.js +138 -0
  1048. package/dist/release/installed-graph.js.map +1 -0
  1049. package/dist/release/installed-origin.d.ts +42 -0
  1050. package/dist/release/installed-origin.d.ts.map +1 -0
  1051. package/dist/release/installed-origin.js +130 -0
  1052. package/dist/release/installed-origin.js.map +1 -0
  1053. package/dist/release/installed-release.d.ts +23 -0
  1054. package/dist/release/installed-release.d.ts.map +1 -0
  1055. package/dist/release/installed-release.js +141 -0
  1056. package/dist/release/installed-release.js.map +1 -0
  1057. package/dist/release/layout.d.ts +29 -34
  1058. package/dist/release/layout.d.ts.map +1 -1
  1059. package/dist/release/layout.js +164 -53
  1060. package/dist/release/layout.js.map +1 -1
  1061. package/dist/release/load.d.ts +3 -0
  1062. package/dist/release/load.d.ts.map +1 -1
  1063. package/dist/release/load.js +50 -8
  1064. package/dist/release/load.js.map +1 -1
  1065. package/dist/release/local-installation.d.ts +20 -0
  1066. package/dist/release/local-installation.d.ts.map +1 -0
  1067. package/dist/release/local-installation.js +298 -0
  1068. package/dist/release/local-installation.js.map +1 -0
  1069. package/dist/release/manifest.d.ts +87 -12
  1070. package/dist/release/manifest.d.ts.map +1 -1
  1071. package/dist/release/manifest.js +31 -7
  1072. package/dist/release/manifest.js.map +1 -1
  1073. package/dist/release/migration-programs.d.ts +12 -0
  1074. package/dist/release/migration-programs.d.ts.map +1 -0
  1075. package/dist/release/migration-programs.js +45 -0
  1076. package/dist/release/migration-programs.js.map +1 -0
  1077. package/dist/release/migrations.d.ts +12 -1
  1078. package/dist/release/migrations.d.ts.map +1 -1
  1079. package/dist/release/migrations.js +124 -9
  1080. package/dist/release/migrations.js.map +1 -1
  1081. package/dist/release/origin.d.ts +33 -0
  1082. package/dist/release/origin.d.ts.map +1 -0
  1083. package/dist/release/origin.js +253 -0
  1084. package/dist/release/origin.js.map +1 -0
  1085. package/dist/release/owner-admission.d.ts +15 -0
  1086. package/dist/release/owner-admission.d.ts.map +1 -0
  1087. package/dist/release/owner-admission.js +37 -0
  1088. package/dist/release/owner-admission.js.map +1 -0
  1089. package/dist/release/owner-executable.d.ts +3 -0
  1090. package/dist/release/owner-executable.d.ts.map +1 -0
  1091. package/dist/release/owner-executable.js +40 -0
  1092. package/dist/release/owner-executable.js.map +1 -0
  1093. package/dist/release/package-gates.d.ts +9 -0
  1094. package/dist/release/package-gates.d.ts.map +1 -0
  1095. package/dist/release/package-gates.js +42 -0
  1096. package/dist/release/package-gates.js.map +1 -0
  1097. package/dist/release/package-resolution.d.ts +4 -0
  1098. package/dist/release/package-resolution.d.ts.map +1 -0
  1099. package/dist/release/package-resolution.js +28 -0
  1100. package/dist/release/package-resolution.js.map +1 -0
  1101. package/dist/release/portable-archive.d.ts +12 -0
  1102. package/dist/release/portable-archive.d.ts.map +1 -0
  1103. package/dist/release/portable-archive.js +96 -0
  1104. package/dist/release/portable-archive.js.map +1 -0
  1105. package/dist/release/publish.d.ts +1 -1
  1106. package/dist/release/publish.js +1 -1
  1107. package/dist/release/registry-download.d.ts +2 -0
  1108. package/dist/release/registry-download.d.ts.map +1 -0
  1109. package/dist/release/registry-download.js +157 -0
  1110. package/dist/release/registry-download.js.map +1 -0
  1111. package/dist/release/registry-framework.d.ts +39 -0
  1112. package/dist/release/registry-framework.d.ts.map +1 -0
  1113. package/dist/release/registry-framework.js +279 -0
  1114. package/dist/release/registry-framework.js.map +1 -0
  1115. package/dist/release/registry-transport.d.ts +27 -0
  1116. package/dist/release/registry-transport.d.ts.map +1 -0
  1117. package/dist/release/registry-transport.js +96 -0
  1118. package/dist/release/registry-transport.js.map +1 -0
  1119. package/dist/release/repository-identity.d.ts +12 -0
  1120. package/dist/release/repository-identity.d.ts.map +1 -0
  1121. package/dist/release/repository-identity.js +62 -0
  1122. package/dist/release/repository-identity.js.map +1 -0
  1123. package/dist/release/runtime-extractor.d.ts +4 -0
  1124. package/dist/release/runtime-extractor.d.ts.map +1 -0
  1125. package/dist/release/runtime-extractor.js +15 -0
  1126. package/dist/release/runtime-extractor.js.map +1 -0
  1127. package/dist/release/runtime-provenance.d.ts +40 -0
  1128. package/dist/release/runtime-provenance.d.ts.map +1 -0
  1129. package/dist/release/runtime-provenance.js +229 -0
  1130. package/dist/release/runtime-provenance.js.map +1 -0
  1131. package/dist/release/source.d.ts +12 -0
  1132. package/dist/release/source.d.ts.map +1 -0
  1133. package/dist/release/source.js +168 -0
  1134. package/dist/release/source.js.map +1 -0
  1135. package/dist/release/store.d.ts +14 -5
  1136. package/dist/release/store.d.ts.map +1 -1
  1137. package/dist/release/store.js +73 -17
  1138. package/dist/release/store.js.map +1 -1
  1139. package/dist/release/target-runtime.d.ts +19 -0
  1140. package/dist/release/target-runtime.d.ts.map +1 -0
  1141. package/dist/release/target-runtime.js +41 -0
  1142. package/dist/release/target-runtime.js.map +1 -0
  1143. package/dist/release/vendored-framework.d.ts +28 -0
  1144. package/dist/release/vendored-framework.d.ts.map +1 -0
  1145. package/dist/release/vendored-framework.js +98 -0
  1146. package/dist/release/vendored-framework.js.map +1 -0
  1147. package/dist/release/workspace-source.d.ts +3 -0
  1148. package/dist/release/workspace-source.d.ts.map +1 -0
  1149. package/dist/release/workspace-source.js +33 -0
  1150. package/dist/release/workspace-source.js.map +1 -0
  1151. package/dist/runtime/context.d.ts +29 -0
  1152. package/dist/runtime/context.d.ts.map +1 -0
  1153. package/dist/runtime/context.js +111 -0
  1154. package/dist/runtime/context.js.map +1 -0
  1155. package/dist/runtime/identity.d.ts +15 -0
  1156. package/dist/runtime/identity.d.ts.map +1 -0
  1157. package/dist/runtime/identity.js +33 -0
  1158. package/dist/runtime/identity.js.map +1 -0
  1159. package/dist/runtime/index.d.ts +3 -0
  1160. package/dist/runtime/index.d.ts.map +1 -0
  1161. package/dist/runtime/index.js +3 -0
  1162. package/dist/runtime/index.js.map +1 -0
  1163. package/dist/services/access.rpc-service.d.ts +41 -0
  1164. package/dist/services/access.rpc-service.d.ts.map +1 -0
  1165. package/dist/services/access.rpc-service.js +248 -0
  1166. package/dist/services/access.rpc-service.js.map +1 -0
  1167. package/dist/services/alert.service.d.ts +3 -3
  1168. package/dist/services/alert.service.d.ts.map +1 -1
  1169. package/dist/services/alert.service.js +3 -3
  1170. package/dist/services/anonymous-input.d.ts +0 -21
  1171. package/dist/services/anonymous-input.d.ts.map +1 -1
  1172. package/dist/services/anonymous-input.js +1 -27
  1173. package/dist/services/anonymous-input.js.map +1 -1
  1174. package/dist/services/audit.service.d.ts +10 -30
  1175. package/dist/services/audit.service.d.ts.map +1 -1
  1176. package/dist/services/audit.service.js +72 -18
  1177. package/dist/services/audit.service.js.map +1 -1
  1178. package/dist/services/auth-context.d.ts +2 -0
  1179. package/dist/services/auth-context.d.ts.map +1 -1
  1180. package/dist/services/auth-context.js +4 -1
  1181. package/dist/services/auth-context.js.map +1 -1
  1182. package/dist/services/auth.rpc-service.d.ts +3 -1
  1183. package/dist/services/auth.rpc-service.d.ts.map +1 -1
  1184. package/dist/services/auth.rpc-service.js +13 -3
  1185. package/dist/services/auth.rpc-service.js.map +1 -1
  1186. package/dist/services/auth.service.d.ts +11 -21
  1187. package/dist/services/auth.service.d.ts.map +1 -1
  1188. package/dist/services/auth.service.js +125 -139
  1189. package/dist/services/auth.service.js.map +1 -1
  1190. package/dist/services/backup-pipeline.d.ts +1 -1
  1191. package/dist/services/backup-pipeline.js +1 -1
  1192. package/dist/services/backup-storage.d.ts +14 -0
  1193. package/dist/services/backup-storage.d.ts.map +1 -0
  1194. package/dist/services/backup-storage.js +195 -0
  1195. package/dist/services/backup-storage.js.map +1 -0
  1196. package/dist/services/backup.rpc-service.d.ts +2 -0
  1197. package/dist/services/backup.rpc-service.d.ts.map +1 -1
  1198. package/dist/services/backup.rpc-service.js +9 -0
  1199. package/dist/services/backup.rpc-service.js.map +1 -1
  1200. package/dist/services/backup.service.d.ts +36 -129
  1201. package/dist/services/backup.service.d.ts.map +1 -1
  1202. package/dist/services/backup.service.js +177 -156
  1203. package/dist/services/backup.service.js.map +1 -1
  1204. package/dist/services/bundle-builder.d.ts +27 -12
  1205. package/dist/services/bundle-builder.d.ts.map +1 -1
  1206. package/dist/services/bundle-builder.js +192 -101
  1207. package/dist/services/bundle-builder.js.map +1 -1
  1208. package/dist/services/bundle-overrides.d.ts +25 -0
  1209. package/dist/services/bundle-overrides.d.ts.map +1 -0
  1210. package/dist/services/bundle-overrides.js +96 -0
  1211. package/dist/services/bundle-overrides.js.map +1 -0
  1212. package/dist/services/daemon-authority.d.ts +16 -0
  1213. package/dist/services/daemon-authority.d.ts.map +1 -0
  1214. package/dist/services/daemon-authority.js +54 -0
  1215. package/dist/services/daemon-authority.js.map +1 -0
  1216. package/dist/services/daemon-principal.d.ts +31 -0
  1217. package/dist/services/daemon-principal.d.ts.map +1 -0
  1218. package/dist/services/daemon-principal.js +37 -0
  1219. package/dist/services/daemon-principal.js.map +1 -0
  1220. package/dist/services/deploy.service.d.ts +13 -57
  1221. package/dist/services/deploy.service.d.ts.map +1 -1
  1222. package/dist/services/deploy.service.js +15 -263
  1223. package/dist/services/deploy.service.js.map +1 -1
  1224. package/dist/services/discovery.service.d.ts +1 -1
  1225. package/dist/services/discovery.service.js +1 -1
  1226. package/dist/services/event-broadcaster.rpc-service.d.ts +7 -1
  1227. package/dist/services/event-broadcaster.rpc-service.d.ts.map +1 -1
  1228. package/dist/services/event-broadcaster.rpc-service.js +89 -11
  1229. package/dist/services/event-broadcaster.rpc-service.js.map +1 -1
  1230. package/dist/services/fleet.rpc-service.d.ts +0 -6
  1231. package/dist/services/fleet.rpc-service.d.ts.map +1 -1
  1232. package/dist/services/fleet.rpc-service.js +0 -13
  1233. package/dist/services/fleet.rpc-service.js.map +1 -1
  1234. package/dist/services/health-check.service.d.ts +1 -1
  1235. package/dist/services/health-check.service.d.ts.map +1 -1
  1236. package/dist/services/health-check.service.js +30 -5
  1237. package/dist/services/health-check.service.js.map +1 -1
  1238. package/dist/services/host-operation-barrier.d.ts +8 -0
  1239. package/dist/services/host-operation-barrier.d.ts.map +1 -0
  1240. package/dist/services/host-operation-barrier.js +44 -0
  1241. package/dist/services/host-operation-barrier.js.map +1 -0
  1242. package/dist/services/host-upgrade.d.ts +181 -0
  1243. package/dist/services/host-upgrade.d.ts.map +1 -0
  1244. package/dist/services/host-upgrade.js +503 -0
  1245. package/dist/services/host-upgrade.js.map +1 -0
  1246. package/dist/services/infrastructure.rpc-service.d.ts +24 -2
  1247. package/dist/services/infrastructure.rpc-service.d.ts.map +1 -1
  1248. package/dist/services/infrastructure.rpc-service.js +178 -36
  1249. package/dist/services/infrastructure.rpc-service.js.map +1 -1
  1250. package/dist/services/kernel-catalog.d.ts +14 -0
  1251. package/dist/services/kernel-catalog.d.ts.map +1 -0
  1252. package/dist/services/kernel-catalog.js +172 -0
  1253. package/dist/services/kernel-catalog.js.map +1 -0
  1254. package/dist/services/kernel-distribution.d.ts +5 -0
  1255. package/dist/services/kernel-distribution.d.ts.map +1 -0
  1256. package/dist/services/kernel-distribution.js +49 -0
  1257. package/dist/services/kernel-distribution.js.map +1 -0
  1258. package/dist/services/kernel-rollout.service.d.ts +55 -0
  1259. package/dist/services/kernel-rollout.service.d.ts.map +1 -0
  1260. package/dist/services/kernel-rollout.service.js +394 -0
  1261. package/dist/services/kernel-rollout.service.js.map +1 -0
  1262. package/dist/services/local-bundle.d.ts +9 -0
  1263. package/dist/services/local-bundle.d.ts.map +1 -1
  1264. package/dist/services/local-bundle.js +14 -3
  1265. package/dist/services/local-bundle.js.map +1 -1
  1266. package/dist/services/log-collector.rpc-service.d.ts +5 -11
  1267. package/dist/services/log-collector.rpc-service.d.ts.map +1 -1
  1268. package/dist/services/log-collector.rpc-service.js +6 -6
  1269. package/dist/services/log-collector.rpc-service.js.map +1 -1
  1270. package/dist/services/log-collector.service.d.ts +39 -109
  1271. package/dist/services/log-collector.service.d.ts.map +1 -1
  1272. package/dist/services/log-collector.service.js +286 -261
  1273. package/dist/services/log-collector.service.js.map +1 -1
  1274. package/dist/services/log-query.d.ts +6 -0
  1275. package/dist/services/log-query.d.ts.map +1 -0
  1276. package/dist/services/log-query.js +46 -0
  1277. package/dist/services/log-query.js.map +1 -0
  1278. package/dist/services/maintenance-lock.d.ts +2 -2
  1279. package/dist/services/maintenance-lock.d.ts.map +1 -1
  1280. package/dist/services/maintenance-lock.js +1 -1
  1281. package/dist/services/managed-rollout.d.ts +54 -0
  1282. package/dist/services/managed-rollout.d.ts.map +1 -0
  1283. package/dist/services/managed-rollout.js +124 -0
  1284. package/dist/services/managed-rollout.js.map +1 -0
  1285. package/dist/services/metrics.rpc-service.d.ts +23 -0
  1286. package/dist/services/metrics.rpc-service.d.ts.map +1 -0
  1287. package/dist/services/metrics.rpc-service.js +73 -0
  1288. package/dist/services/metrics.rpc-service.js.map +1 -0
  1289. package/dist/services/migration-output.d.ts +2 -2
  1290. package/dist/services/migration-output.js +2 -2
  1291. package/dist/services/migration-process.d.ts +32 -0
  1292. package/dist/services/migration-process.d.ts.map +1 -0
  1293. package/dist/services/migration-process.js +71 -0
  1294. package/dist/services/migration-process.js.map +1 -0
  1295. package/dist/services/migration-target.d.ts +57 -0
  1296. package/dist/services/migration-target.d.ts.map +1 -0
  1297. package/dist/services/migration-target.js +221 -0
  1298. package/dist/services/migration-target.js.map +1 -0
  1299. package/dist/services/node-deploy-lease.d.ts +19 -2
  1300. package/dist/services/node-deploy-lease.d.ts.map +1 -1
  1301. package/dist/services/node-deploy-lease.js +84 -10
  1302. package/dist/services/node-deploy-lease.js.map +1 -1
  1303. package/dist/services/node-health.repository.d.ts +2 -59
  1304. package/dist/services/node-health.repository.d.ts.map +1 -1
  1305. package/dist/services/node-health.repository.js.map +1 -1
  1306. package/dist/services/node-host-key.d.ts +9 -0
  1307. package/dist/services/node-host-key.d.ts.map +1 -0
  1308. package/dist/services/node-host-key.js +17 -0
  1309. package/dist/services/node-host-key.js.map +1 -0
  1310. package/dist/services/node-manager.rpc-service.d.ts +50 -38
  1311. package/dist/services/node-manager.rpc-service.d.ts.map +1 -1
  1312. package/dist/services/node-manager.rpc-service.js +233 -38
  1313. package/dist/services/node-manager.rpc-service.js.map +1 -1
  1314. package/dist/services/node-manager.service.d.ts +4 -1
  1315. package/dist/services/node-manager.service.d.ts.map +1 -1
  1316. package/dist/services/node-manager.service.js +79 -28
  1317. package/dist/services/node-manager.service.js.map +1 -1
  1318. package/dist/services/node-registration.d.ts +17 -0
  1319. package/dist/services/node-registration.d.ts.map +1 -0
  1320. package/dist/services/node-registration.js +73 -0
  1321. package/dist/services/node-registration.js.map +1 -0
  1322. package/dist/services/node-upgrade.d.ts +1 -1
  1323. package/dist/services/node-upgrade.service.d.ts +2 -28
  1324. package/dist/services/node-upgrade.service.d.ts.map +1 -1
  1325. package/dist/services/node-upgrade.service.js +2 -3
  1326. package/dist/services/node-upgrade.service.js.map +1 -1
  1327. package/dist/services/pipeline-definition.d.ts +14 -0
  1328. package/dist/services/pipeline-definition.d.ts.map +1 -0
  1329. package/dist/services/pipeline-definition.js +77 -0
  1330. package/dist/services/pipeline-definition.js.map +1 -0
  1331. package/dist/services/pipeline.rpc-service.d.ts +14 -3
  1332. package/dist/services/pipeline.rpc-service.d.ts.map +1 -1
  1333. package/dist/services/pipeline.rpc-service.js +45 -12
  1334. package/dist/services/pipeline.rpc-service.js.map +1 -1
  1335. package/dist/services/pipeline.service.d.ts +30 -44
  1336. package/dist/services/pipeline.service.d.ts.map +1 -1
  1337. package/dist/services/pipeline.service.js +402 -333
  1338. package/dist/services/pipeline.service.js.map +1 -1
  1339. package/dist/services/project.rpc-service.d.ts +219 -14
  1340. package/dist/services/project.rpc-service.d.ts.map +1 -1
  1341. package/dist/services/project.rpc-service.js +314 -31
  1342. package/dist/services/project.rpc-service.js.map +1 -1
  1343. package/dist/services/project.service.d.ts +195 -67
  1344. package/dist/services/project.service.d.ts.map +1 -1
  1345. package/dist/services/project.service.js +2029 -705
  1346. package/dist/services/project.service.js.map +1 -1
  1347. package/dist/services/redeploy-decision.d.ts +2 -2
  1348. package/dist/services/redeploy-decision.js +1 -1
  1349. package/dist/services/release.rpc-service.d.ts +6 -19
  1350. package/dist/services/release.rpc-service.d.ts.map +1 -1
  1351. package/dist/services/release.rpc-service.js +35 -12
  1352. package/dist/services/release.rpc-service.js.map +1 -1
  1353. package/dist/services/release.service.d.ts +2 -47
  1354. package/dist/services/release.service.d.ts.map +1 -1
  1355. package/dist/services/release.service.js +26 -2
  1356. package/dist/services/release.service.js.map +1 -1
  1357. package/dist/services/remote-deployer.service.d.ts +65 -126
  1358. package/dist/services/remote-deployer.service.d.ts.map +1 -1
  1359. package/dist/services/remote-deployer.service.js +671 -466
  1360. package/dist/services/remote-deployer.service.js.map +1 -1
  1361. package/dist/services/remote-provisioner.d.ts +3 -1
  1362. package/dist/services/remote-provisioner.d.ts.map +1 -1
  1363. package/dist/services/remote-provisioner.js +2 -2
  1364. package/dist/services/remote-provisioner.js.map +1 -1
  1365. package/dist/services/replication-evidence.d.ts +24 -0
  1366. package/dist/services/replication-evidence.d.ts.map +1 -0
  1367. package/dist/services/replication-evidence.js +61 -0
  1368. package/dist/services/replication-evidence.js.map +1 -0
  1369. package/dist/services/replication-history.d.ts +80 -0
  1370. package/dist/services/replication-history.d.ts.map +1 -0
  1371. package/dist/services/replication-history.js +279 -0
  1372. package/dist/services/replication-history.js.map +1 -0
  1373. package/dist/services/replication-reconciliation.d.ts +74 -0
  1374. package/dist/services/replication-reconciliation.d.ts.map +1 -0
  1375. package/dist/services/replication-reconciliation.js +351 -0
  1376. package/dist/services/replication-reconciliation.js.map +1 -0
  1377. package/dist/services/slave-storage.service.d.ts +2 -19
  1378. package/dist/services/slave-storage.service.d.ts.map +1 -1
  1379. package/dist/services/slave-storage.service.js +19 -6
  1380. package/dist/services/slave-storage.service.js.map +1 -1
  1381. package/dist/services/static-carry-forward.d.ts +28 -3
  1382. package/dist/services/static-carry-forward.d.ts.map +1 -1
  1383. package/dist/services/static-carry-forward.js +285 -4
  1384. package/dist/services/static-carry-forward.js.map +1 -1
  1385. package/dist/services/sync-summary.d.ts.map +1 -1
  1386. package/dist/services/sync-summary.js +1 -18
  1387. package/dist/services/sync-summary.js.map +1 -1
  1388. package/dist/services/sync.rpc-service.d.ts +17 -20
  1389. package/dist/services/sync.rpc-service.d.ts.map +1 -1
  1390. package/dist/services/sync.rpc-service.js +23 -37
  1391. package/dist/services/sync.rpc-service.js.map +1 -1
  1392. package/dist/services/sync.service.d.ts +53 -157
  1393. package/dist/services/sync.service.d.ts.map +1 -1
  1394. package/dist/services/sync.service.js +239 -337
  1395. package/dist/services/sync.service.js.map +1 -1
  1396. package/dist/services/system-info.rpc-service.d.ts +3 -1
  1397. package/dist/services/system-info.rpc-service.d.ts.map +1 -1
  1398. package/dist/services/system-info.rpc-service.js +5 -5
  1399. package/dist/services/system-info.rpc-service.js.map +1 -1
  1400. package/dist/services/system-info.service.d.ts +3 -1
  1401. package/dist/services/system-info.service.d.ts.map +1 -1
  1402. package/dist/services/system-info.service.js +17 -9
  1403. package/dist/services/system-info.service.js.map +1 -1
  1404. package/dist/services/telemetry.rpc-service.d.ts +4 -23
  1405. package/dist/services/telemetry.rpc-service.d.ts.map +1 -1
  1406. package/dist/services/telemetry.rpc-service.js +4 -32
  1407. package/dist/services/telemetry.rpc-service.js.map +1 -1
  1408. package/dist/services/telemetry.service.d.ts +2 -30
  1409. package/dist/services/telemetry.service.d.ts.map +1 -1
  1410. package/dist/services/telemetry.service.js +25 -131
  1411. package/dist/services/telemetry.service.js.map +1 -1
  1412. package/dist/services/terminal-ssh.d.ts +16 -0
  1413. package/dist/services/terminal-ssh.d.ts.map +1 -0
  1414. package/dist/services/terminal-ssh.js +101 -0
  1415. package/dist/services/terminal-ssh.js.map +1 -0
  1416. package/dist/services/terminal.rpc-service.d.ts +84 -0
  1417. package/dist/services/terminal.rpc-service.d.ts.map +1 -0
  1418. package/dist/services/terminal.rpc-service.js +508 -0
  1419. package/dist/services/terminal.rpc-service.js.map +1 -0
  1420. package/dist/services/trace-collector.rpc-service.js +3 -3
  1421. package/dist/services/trace-collector.rpc-service.js.map +1 -1
  1422. package/dist/services/wait-for-postgres.d.ts +1 -1
  1423. package/dist/services/wait-for-postgres.d.ts.map +1 -1
  1424. package/dist/services/wait-for-postgres.js +13 -28
  1425. package/dist/services/wait-for-postgres.js.map +1 -1
  1426. package/dist/shared/build-stamp.d.ts +4 -1
  1427. package/dist/shared/build-stamp.d.ts.map +1 -1
  1428. package/dist/shared/build-stamp.js +14 -6
  1429. package/dist/shared/build-stamp.js.map +1 -1
  1430. package/dist/shared/describe-error.d.ts +1 -21
  1431. package/dist/shared/describe-error.d.ts.map +1 -1
  1432. package/dist/shared/describe-error.js +1 -38
  1433. package/dist/shared/describe-error.js.map +1 -1
  1434. package/dist/shared/dto/access.d.ts +55 -0
  1435. package/dist/shared/dto/access.d.ts.map +1 -0
  1436. package/dist/shared/dto/access.js +2 -0
  1437. package/dist/shared/dto/access.js.map +1 -0
  1438. package/dist/shared/dto/audit.d.ts +32 -0
  1439. package/dist/shared/dto/audit.d.ts.map +1 -0
  1440. package/dist/shared/dto/audit.js +3 -0
  1441. package/dist/shared/dto/audit.js.map +1 -0
  1442. package/dist/shared/dto/auth.d.ts +2 -0
  1443. package/dist/shared/dto/auth.d.ts.map +1 -1
  1444. package/dist/shared/dto/auth.js +5 -1
  1445. package/dist/shared/dto/auth.js.map +1 -1
  1446. package/dist/shared/dto/backend.d.ts +50 -0
  1447. package/dist/shared/dto/backend.d.ts.map +1 -0
  1448. package/dist/shared/dto/backend.js +3 -0
  1449. package/dist/shared/dto/backend.js.map +1 -0
  1450. package/dist/shared/dto/backups.d.ts +99 -0
  1451. package/dist/shared/dto/backups.d.ts.map +1 -1
  1452. package/dist/shared/dto/cluster.d.ts +44 -0
  1453. package/dist/shared/dto/cluster.d.ts.map +1 -0
  1454. package/dist/shared/dto/cluster.js +3 -0
  1455. package/dist/shared/dto/cluster.js.map +1 -0
  1456. package/dist/shared/dto/files.d.ts +328 -0
  1457. package/dist/shared/dto/files.d.ts.map +1 -0
  1458. package/dist/shared/dto/files.js +2 -0
  1459. package/dist/shared/dto/files.js.map +1 -0
  1460. package/dist/shared/dto/health.d.ts +59 -0
  1461. package/dist/shared/dto/health.d.ts.map +1 -1
  1462. package/dist/shared/dto/installed-release.d.ts +40 -0
  1463. package/dist/shared/dto/installed-release.d.ts.map +1 -0
  1464. package/dist/shared/dto/installed-release.js +2 -0
  1465. package/dist/shared/dto/installed-release.js.map +1 -0
  1466. package/dist/shared/dto/kernel-catalog.d.ts +11 -0
  1467. package/dist/shared/dto/kernel-catalog.d.ts.map +1 -0
  1468. package/dist/shared/dto/kernel-catalog.js +2 -0
  1469. package/dist/shared/dto/kernel-catalog.js.map +1 -0
  1470. package/dist/shared/dto/logs.d.ts +21 -0
  1471. package/dist/shared/dto/logs.d.ts.map +1 -1
  1472. package/dist/shared/dto/metrics.d.ts +4 -64
  1473. package/dist/shared/dto/metrics.d.ts.map +1 -1
  1474. package/dist/shared/dto/metrics.js +0 -15
  1475. package/dist/shared/dto/metrics.js.map +1 -1
  1476. package/dist/shared/dto/nodes.d.ts +98 -24
  1477. package/dist/shared/dto/nodes.d.ts.map +1 -1
  1478. package/dist/shared/dto/pipelines.d.ts +22 -1
  1479. package/dist/shared/dto/pipelines.d.ts.map +1 -1
  1480. package/dist/shared/dto/project.d.ts +289 -30
  1481. package/dist/shared/dto/project.d.ts.map +1 -1
  1482. package/dist/shared/dto/releases.d.ts +59 -0
  1483. package/dist/shared/dto/releases.d.ts.map +1 -0
  1484. package/dist/shared/dto/releases.js +2 -0
  1485. package/dist/shared/dto/releases.js.map +1 -0
  1486. package/dist/shared/dto/services.d.ts +201 -37
  1487. package/dist/shared/dto/services.d.ts.map +1 -1
  1488. package/dist/shared/dto/services.js +15 -6
  1489. package/dist/shared/dto/services.js.map +1 -1
  1490. package/dist/shared/dto/stack-diagnosis.d.ts +20 -0
  1491. package/dist/shared/dto/stack-diagnosis.d.ts.map +1 -0
  1492. package/dist/shared/dto/stack-diagnosis.js +8 -0
  1493. package/dist/shared/dto/stack-diagnosis.js.map +1 -0
  1494. package/dist/shared/dto/stack-execution.d.ts +65 -0
  1495. package/dist/shared/dto/stack-execution.d.ts.map +1 -0
  1496. package/dist/shared/dto/stack-execution.js +33 -0
  1497. package/dist/shared/dto/stack-execution.js.map +1 -0
  1498. package/dist/shared/dto/system-info.d.ts +11 -0
  1499. package/dist/shared/dto/system-info.d.ts.map +1 -1
  1500. package/dist/shared/dto/system-info.js +7 -1
  1501. package/dist/shared/dto/system-info.js.map +1 -1
  1502. package/dist/shared/dto/terminal.d.ts +40 -0
  1503. package/dist/shared/dto/terminal.d.ts.map +1 -0
  1504. package/dist/shared/dto/terminal.js +2 -0
  1505. package/dist/shared/dto/terminal.js.map +1 -0
  1506. package/dist/shared/dto/topology.d.ts +96 -0
  1507. package/dist/shared/dto/topology.d.ts.map +1 -0
  1508. package/dist/shared/dto/topology.js +2 -0
  1509. package/dist/shared/dto/topology.js.map +1 -0
  1510. package/dist/shared/emergency-output.d.ts +3 -0
  1511. package/dist/shared/emergency-output.d.ts.map +1 -0
  1512. package/dist/shared/emergency-output.js +22 -0
  1513. package/dist/shared/emergency-output.js.map +1 -0
  1514. package/dist/shared/env-config.d.ts +2 -0
  1515. package/dist/shared/env-config.d.ts.map +1 -1
  1516. package/dist/shared/env-config.js +1 -0
  1517. package/dist/shared/env-config.js.map +1 -1
  1518. package/dist/shared/events.d.ts +2 -0
  1519. package/dist/shared/events.d.ts.map +1 -1
  1520. package/dist/shared/events.js.map +1 -1
  1521. package/dist/shared/execution-identity.d.ts +39 -0
  1522. package/dist/shared/execution-identity.d.ts.map +1 -0
  1523. package/dist/shared/execution-identity.js +160 -0
  1524. package/dist/shared/execution-identity.js.map +1 -0
  1525. package/dist/shared/file-policy.d.ts +5 -0
  1526. package/dist/shared/file-policy.d.ts.map +1 -0
  1527. package/dist/shared/file-policy.js +18 -0
  1528. package/dist/shared/file-policy.js.map +1 -0
  1529. package/dist/shared/framework-source.d.ts +11 -0
  1530. package/dist/shared/framework-source.d.ts.map +1 -0
  1531. package/dist/shared/framework-source.js +31 -0
  1532. package/dist/shared/framework-source.js.map +1 -0
  1533. package/dist/shared/fresh-module-reader.d.ts +40 -0
  1534. package/dist/shared/fresh-module-reader.d.ts.map +1 -0
  1535. package/dist/shared/fresh-module-reader.js +257 -0
  1536. package/dist/shared/fresh-module-reader.js.map +1 -0
  1537. package/dist/shared/host-boot-identity.d.ts +12 -0
  1538. package/dist/shared/host-boot-identity.d.ts.map +1 -0
  1539. package/dist/shared/host-boot-identity.js +89 -0
  1540. package/dist/shared/host-boot-identity.js.map +1 -0
  1541. package/dist/shared/kernel-file-lock.d.ts +3 -0
  1542. package/dist/shared/kernel-file-lock.d.ts.map +1 -0
  1543. package/dist/shared/kernel-file-lock.js +53 -0
  1544. package/dist/shared/kernel-file-lock.js.map +1 -0
  1545. package/dist/shared/linux-file-lock.d.ts +4 -0
  1546. package/dist/shared/linux-file-lock.d.ts.map +1 -0
  1547. package/dist/shared/linux-file-lock.js +36 -0
  1548. package/dist/shared/linux-file-lock.js.map +1 -0
  1549. package/dist/shared/local-infra-host.d.ts +2 -2
  1550. package/dist/shared/local-infra-host.js +2 -2
  1551. package/dist/shared/log-ingestion-reading.d.ts +9 -0
  1552. package/dist/shared/log-ingestion-reading.d.ts.map +1 -0
  1553. package/dist/shared/log-ingestion-reading.js +32 -0
  1554. package/dist/shared/log-ingestion-reading.js.map +1 -0
  1555. package/dist/shared/log-levels.d.ts +19 -0
  1556. package/dist/shared/log-levels.d.ts.map +1 -0
  1557. package/dist/shared/log-levels.js +23 -0
  1558. package/dist/shared/log-levels.js.map +1 -0
  1559. package/dist/shared/metrics-storage-reading.d.ts +8 -0
  1560. package/dist/shared/metrics-storage-reading.d.ts.map +1 -0
  1561. package/dist/shared/metrics-storage-reading.js +27 -0
  1562. package/dist/shared/metrics-storage-reading.js.map +1 -0
  1563. package/dist/shared/pnpm.d.ts.map +1 -1
  1564. package/dist/shared/pnpm.js +7 -0
  1565. package/dist/shared/pnpm.js.map +1 -1
  1566. package/dist/shared/pool-scale.d.ts +10 -0
  1567. package/dist/shared/pool-scale.d.ts.map +1 -0
  1568. package/dist/shared/pool-scale.js +25 -0
  1569. package/dist/shared/pool-scale.js.map +1 -0
  1570. package/dist/shared/private-files.d.ts +10 -22
  1571. package/dist/shared/private-files.d.ts.map +1 -1
  1572. package/dist/shared/private-files.js +95 -82
  1573. package/dist/shared/private-files.js.map +1 -1
  1574. package/dist/shared/relay-reading.d.ts +19 -0
  1575. package/dist/shared/relay-reading.d.ts.map +1 -0
  1576. package/dist/shared/relay-reading.js +22 -0
  1577. package/dist/shared/relay-reading.js.map +1 -0
  1578. package/dist/shared/release-reading.d.ts +124 -32
  1579. package/dist/shared/release-reading.d.ts.map +1 -1
  1580. package/dist/shared/release-reading.js +208 -28
  1581. package/dist/shared/release-reading.js.map +1 -1
  1582. package/dist/shared/roles.d.ts +19 -18
  1583. package/dist/shared/roles.d.ts.map +1 -1
  1584. package/dist/shared/roles.js +21 -26
  1585. package/dist/shared/roles.js.map +1 -1
  1586. package/dist/shared/runtime-artifact.d.ts +20 -0
  1587. package/dist/shared/runtime-artifact.d.ts.map +1 -0
  1588. package/dist/shared/runtime-artifact.js +83 -0
  1589. package/dist/shared/runtime-artifact.js.map +1 -0
  1590. package/dist/shared/stack-reading.d.ts +18 -0
  1591. package/dist/shared/stack-reading.d.ts.map +1 -0
  1592. package/dist/shared/stack-reading.js +15 -0
  1593. package/dist/shared/stack-reading.js.map +1 -0
  1594. package/dist/shared/sync-reading.d.ts +30 -38
  1595. package/dist/shared/sync-reading.d.ts.map +1 -1
  1596. package/dist/shared/sync-reading.js +90 -29
  1597. package/dist/shared/sync-reading.js.map +1 -1
  1598. package/dist/shared/tokens.d.ts +3 -1
  1599. package/dist/shared/tokens.d.ts.map +1 -1
  1600. package/dist/shared/tokens.js +1 -0
  1601. package/dist/shared/tokens.js.map +1 -1
  1602. package/dist/supervisor/restart-policy.d.ts.map +1 -1
  1603. package/dist/supervisor/restart-policy.js +7 -5
  1604. package/dist/supervisor/restart-policy.js.map +1 -1
  1605. package/dist/webapp/console-container.d.ts +7 -0
  1606. package/dist/webapp/console-container.d.ts.map +1 -0
  1607. package/dist/webapp/console-container.js +23 -0
  1608. package/dist/webapp/console-container.js.map +1 -0
  1609. package/dist/webapp/webapp.service.d.ts.map +1 -1
  1610. package/dist/webapp/webapp.service.js +71 -24
  1611. package/dist/webapp/webapp.service.js.map +1 -1
  1612. package/dist/workers/health-monitor.service.d.ts.map +1 -1
  1613. package/dist/workers/health-monitor.service.js +8 -1
  1614. package/dist/workers/health-monitor.service.js.map +1 -1
  1615. package/dist/workers/types.d.ts +2 -0
  1616. package/dist/workers/types.d.ts.map +1 -1
  1617. package/package.json +109 -43
  1618. package/webapp/dist/BUILD.json +4 -3
  1619. package/webapp/dist/assets/access-48hkC2-P.js +1 -0
  1620. package/webapp/dist/assets/access-jWkHxGc7.js +1 -0
  1621. package/webapp/dist/assets/admin-data-table-BKSDI8sU.js +1 -0
  1622. package/webapp/dist/assets/alert-expression-CSblScoa.js +1 -0
  1623. package/webapp/dist/assets/alert-notify-settings-C_CHZrFm.js +1 -0
  1624. package/webapp/dist/assets/alert-uBG6r9NW.js +1 -0
  1625. package/webapp/dist/assets/alerts-CuPQ9YQJ.js +1 -0
  1626. package/webapp/dist/assets/app-address-BCXfN59F.js +1 -0
  1627. package/webapp/dist/assets/apps-Drio028B.js +1 -0
  1628. package/webapp/dist/assets/audit-npSFJECe.js +1 -0
  1629. package/webapp/dist/assets/auth-CcgjP7hR.js +1 -0
  1630. package/webapp/dist/assets/card-DkH32gMY.js +1 -0
  1631. package/webapp/dist/assets/chart-BpGXlCJc.js +2 -0
  1632. package/webapp/dist/assets/charts-BY7qI6s2.js +41 -0
  1633. package/webapp/dist/assets/charts-CpBdHU_A.js +56 -0
  1634. package/webapp/dist/assets/client-DFnuv2z3.js +3 -0
  1635. package/webapp/dist/assets/code-editor-DK6Tmmxv.js +4 -0
  1636. package/webapp/dist/assets/comparison-bars-BtC0dHjF.js +1 -0
  1637. package/webapp/dist/assets/confirm-dialog-BbGsAz7_.js +1 -0
  1638. package/webapp/dist/assets/console-keyboard-D3YCA0yU.js +1 -0
  1639. package/webapp/dist/assets/constants-CyhngVXh.js +1 -0
  1640. package/webapp/dist/assets/containers-Bl8gAyZX.js +3 -0
  1641. package/webapp/dist/assets/context-FIuwpd9_.js +1 -0
  1642. package/webapp/dist/assets/controls-C5W8gHU4.js +1 -0
  1643. package/webapp/dist/assets/daemon-memory-BiEtr9jr.js +1 -0
  1644. package/webapp/dist/assets/dashboard-UHlet3H9.js +1 -0
  1645. package/webapp/dist/assets/dashboard-builder-67PZFqhE.js +1 -0
  1646. package/webapp/dist/assets/dayjs.min-DHwAvH5f.js +1 -0
  1647. package/webapp/dist/assets/deploy-release-dialog-BOXcD5Wo.js +1 -0
  1648. package/webapp/dist/assets/deployments-qV20Ak0P.js +1 -0
  1649. package/webapp/dist/assets/detail-B4TiBfxU.js +8 -0
  1650. package/webapp/dist/assets/detail-B85-Wees.js +2 -0
  1651. package/webapp/dist/assets/detail-CYS81K6Y.js +1 -0
  1652. package/webapp/dist/assets/dist-BUDn8hLh.js +11 -0
  1653. package/webapp/dist/assets/dist-Ci5pYRbx.js +1 -0
  1654. package/webapp/dist/assets/dist-DQmjHv4-.js +1 -0
  1655. package/webapp/dist/assets/dist-De9Fty7a.js +1 -0
  1656. package/webapp/dist/assets/dist-DsGmKwmk.js +23 -0
  1657. package/webapp/dist/assets/empty-content-7jOFhG4C.js +1 -0
  1658. package/webapp/dist/assets/error-boundary-CLLI8PWw.js +3 -0
  1659. package/webapp/dist/assets/event-fields-CiyqrRO8.js +1 -0
  1660. package/webapp/dist/assets/files-DigwXndm.js +2 -0
  1661. package/webapp/dist/assets/formatters-RnRy4bXm.js +1 -0
  1662. package/webapp/dist/assets/icons-OboZgWSt.js +1 -0
  1663. package/webapp/dist/assets/index-uq8Dkk4c.js +1 -0
  1664. package/webapp/dist/assets/label-B1SF0RTL.js +1 -0
  1665. package/webapp/dist/assets/log-level-filter-Bcn31D1F.js +1 -0
  1666. package/webapp/dist/assets/log-location-DuBjh6HQ.js +1 -0
  1667. package/webapp/dist/assets/logs-BqHOufk8.js +4 -0
  1668. package/webapp/dist/assets/metric-chart-M-kI-XOt.js +1 -0
  1669. package/webapp/dist/assets/metric-series-WxePniyw.js +1 -0
  1670. package/webapp/dist/assets/metrics-QIQaF7iS.js +1 -0
  1671. package/webapp/dist/assets/model-ZEXEHm0l.js +2 -0
  1672. package/webapp/dist/assets/mui-6ssfcZcz.js +1 -0
  1673. package/webapp/dist/assets/mui-AnEgAVjz.js +52 -0
  1674. package/webapp/dist/assets/mui-B1jrje6Z.js +1 -0
  1675. package/webapp/dist/assets/mui-BIz4LSVs.js +1 -0
  1676. package/webapp/dist/assets/mui-BTN91yBK.js +28 -0
  1677. package/webapp/dist/assets/mui-BXSXx9c9.js +124 -0
  1678. package/webapp/dist/assets/mui-BwsIrivo.js +37 -0
  1679. package/webapp/dist/assets/mui-C_hromOc.js +1 -0
  1680. package/webapp/dist/assets/mui-Cd711nOk.js +4 -0
  1681. package/webapp/dist/assets/mui-CdB_p2lt.js +10 -0
  1682. package/webapp/dist/assets/mui-DyT2n1lx.js +1 -0
  1683. package/webapp/dist/assets/mui-agG5dued.js +1 -0
  1684. package/webapp/dist/assets/mui-y44PQOfG.js +1 -0
  1685. package/webapp/dist/assets/nodes-BJPk02vv.js +7 -0
  1686. package/webapp/dist/assets/omnitron-logo-koMCbsCv.js +1 -0
  1687. package/webapp/dist/assets/operation-status-Bm1x1wTz.js +1 -0
  1688. package/webapp/dist/assets/page-breadcrumbs-fR7Jmpp4.js +1 -0
  1689. package/webapp/dist/assets/pipelines-T6Ch9LTw.js +3 -0
  1690. package/webapp/dist/assets/popper-m_9b0JRf.js +1 -0
  1691. package/webapp/dist/assets/preload-helper-DzCYNvzR.js +1 -0
  1692. package/webapp/dist/assets/project.store--G5pIF-J.js +1 -0
  1693. package/webapp/dist/assets/projects-YoBzcQ24.js +1 -0
  1694. package/webapp/dist/assets/react-BN8qLIAi.js +9 -0
  1695. package/webapp/dist/assets/react-CEuifcaQ.js +1 -0
  1696. package/webapp/dist/assets/react-apexcharts.esm-DoOt-pu4.js +1 -0
  1697. package/webapp/dist/assets/realtime.store-CBDO4Abj.js +1 -0
  1698. package/webapp/dist/assets/release-bits-B2a_wbft.js +1 -0
  1699. package/webapp/dist/assets/release-build-panel-BQmIdKW9.js +1 -0
  1700. package/webapp/dist/assets/release-deployment-state-DRrEI2pP.js +1 -0
  1701. package/webapp/dist/assets/release-wire-f2VuBoBF.js +1 -0
  1702. package/webapp/dist/assets/releases-Bp3CDgmo.js +2 -0
  1703. package/webapp/dist/assets/rolldown-runtime-CNOWq4Kh.js +1 -0
  1704. package/webapp/dist/assets/search-input-C0MHI8vO.js +1 -0
  1705. package/webapp/dist/assets/services-BddvcFi8.js +1 -0
  1706. package/webapp/dist/assets/settings-B3egRvbI.js +1 -0
  1707. package/webapp/dist/assets/settled-pair-B-wgSZl6.js +1 -0
  1708. package/webapp/dist/assets/shared-styles-C0vN3I7_.js +1 -0
  1709. package/webapp/dist/assets/shell-command-C3pXf1vi.js +1 -0
  1710. package/webapp/dist/assets/sign-in-9q-Nfy83.js +1 -0
  1711. package/webapp/dist/assets/skeleton-BmWDJWF9.js +1 -0
  1712. package/webapp/dist/assets/snackbar-DSPmjMyi.js +1 -0
  1713. package/webapp/dist/assets/stack-health-status-BIv2C10x.js +1 -0
  1714. package/webapp/dist/assets/stack-start-notice-BVnMOwRQ.js +1 -0
  1715. package/webapp/dist/assets/stacks-IZ1mfizi.js +1 -0
  1716. package/webapp/dist/assets/storage-CKXnhqkt.js +1 -0
  1717. package/webapp/dist/assets/store-bqUBn2A4.js +1 -0
  1718. package/webapp/dist/assets/sync-reading-CN0jPKAg.js +1 -0
  1719. package/webapp/dist/assets/system-info-BFKNM-hf.js +1 -0
  1720. package/webapp/dist/assets/table-BOWT6Y9d.js +1 -0
  1721. package/webapp/dist/assets/table-viewport-Bp4pq-c_.js +1 -0
  1722. package/webapp/dist/assets/tabs-k5NPGLnJ.js +1 -0
  1723. package/webapp/dist/assets/terminal-BrP-ENHg.css +1 -0
  1724. package/webapp/dist/assets/terminal-QWBau-Us.js +62 -0
  1725. package/webapp/dist/assets/terminal-input-b7f2VoE_.js +2 -0
  1726. package/webapp/dist/assets/topology-CPey5dP6.js +8 -0
  1727. package/webapp/dist/assets/topology-metadata-dialog-BivuU2y6.js +2 -0
  1728. package/webapp/dist/assets/topology-routes.worker-BoYrIzAH.js +1 -0
  1729. package/webapp/dist/assets/traces-By0rdfDC.js +1 -0
  1730. package/webapp/dist/assets/use-copy-to-clipboard-BWYpToS3.js +1 -0
  1731. package/webapp/dist/assets/use-polled-resource-B22hhr5L.js +1 -0
  1732. package/webapp/dist/assets/use-stack-context-UkBsF-l7.js +1 -0
  1733. package/webapp/dist/assets/webapp-BnxOVfrc.css +1 -0
  1734. package/webapp/dist/assets/webapp-D-UhjFhS.js +35 -0
  1735. package/webapp/dist/console-version.json +1 -0
  1736. package/webapp/dist/index.html +54 -7
  1737. package/dist/release/daemon-omni.d.ts +0 -41
  1738. package/dist/release/daemon-omni.d.ts.map +0 -1
  1739. package/dist/release/daemon-omni.js +0 -59
  1740. package/dist/release/daemon-omni.js.map +0 -1
  1741. package/dist/services/netron-telemetry-transport.d.ts +0 -42
  1742. package/dist/services/netron-telemetry-transport.d.ts.map +0 -1
  1743. package/dist/services/netron-telemetry-transport.js +0 -93
  1744. package/dist/services/netron-telemetry-transport.js.map +0 -1
  1745. package/webapp/dist/assets/FormControlLabel-BrH2diyl.js +0 -1
  1746. package/webapp/dist/assets/Grid-BZ7xhoHQ.js +0 -1
  1747. package/webapp/dist/assets/Switch-DGSAxQPM.js +0 -1
  1748. package/webapp/dist/assets/alerts-sXqHJbsa.js +0 -1
  1749. package/webapp/dist/assets/apps-B_Ah8Flh.js +0 -1
  1750. package/webapp/dist/assets/audit-YXihwyui.js +0 -1
  1751. package/webapp/dist/assets/client-CGbBvy9k.js +0 -1
  1752. package/webapp/dist/assets/constants-veKGFkC6.js +0 -1
  1753. package/webapp/dist/assets/containers-Di4NOTLf.js +0 -2
  1754. package/webapp/dist/assets/daemon-memory-CCPZ4cV_.js +0 -1
  1755. package/webapp/dist/assets/dashboard-Cfuf95N3.js +0 -1
  1756. package/webapp/dist/assets/dashboard-builder-CowaYb-M.js +0 -1
  1757. package/webapp/dist/assets/deploy-release-dialog-D6C-XcKY.js +0 -1
  1758. package/webapp/dist/assets/deployments-ChTq5kCw.js +0 -1
  1759. package/webapp/dist/assets/detail-BsGWv7Dj.js +0 -1
  1760. package/webapp/dist/assets/detail-CyVf_cw5.js +0 -2
  1761. package/webapp/dist/assets/detail-D027j6aO.js +0 -8
  1762. package/webapp/dist/assets/formatters-BqjL73N3.js +0 -1
  1763. package/webapp/dist/assets/fs-Ccl3sAcp.js +0 -1
  1764. package/webapp/dist/assets/index-B8AHIPc-.css +0 -1
  1765. package/webapp/dist/assets/index-DiZbrwxT.js +0 -414
  1766. package/webapp/dist/assets/logs-L2b8Oqmo.js +0 -12
  1767. package/webapp/dist/assets/maplibre-gl-MlmG2kbn.js +0 -801
  1768. package/webapp/dist/assets/metrics-CQgjz2Lz.js +0 -2
  1769. package/webapp/dist/assets/nodes-Nwia2Ty6.js +0 -7
  1770. package/webapp/dist/assets/pipelines-DCu_rXOr.js +0 -4
  1771. package/webapp/dist/assets/projects-Bb4aV76h.js +0 -1
  1772. package/webapp/dist/assets/react-CwJFpaho.js +0 -1
  1773. package/webapp/dist/assets/react-apexcharts.esm-Dy0Fez42.js +0 -1956
  1774. package/webapp/dist/assets/release-bits-Dj4EOhhb.js +0 -1
  1775. package/webapp/dist/assets/release-build-panel-D6OCVlhT.js +0 -1
  1776. package/webapp/dist/assets/releases-CnAt3yO6.js +0 -2
  1777. package/webapp/dist/assets/rolldown-runtime-hePW80VL.js +0 -1
  1778. package/webapp/dist/assets/settings-DU-mjiwb.js +0 -1
  1779. package/webapp/dist/assets/settled-pair-C7SjZuns.js +0 -1
  1780. package/webapp/dist/assets/sign-in-Bcvjrr4C.js +0 -1
  1781. package/webapp/dist/assets/stacks-B-e8p50I.js +0 -1
  1782. package/webapp/dist/assets/sync-reading-C3PnJ7AX.js +0 -1
  1783. package/webapp/dist/assets/system-info-BtE3dgfw.js +0 -1
  1784. package/webapp/dist/assets/topology-Cwch-uF1.js +0 -12
  1785. package/webapp/dist/assets/traces-BbShR-4P.js +0 -1
  1786. package/webapp/dist/assets/use-stack-context-CZUgPq88.js +0 -1
@@ -1,3 +1,10 @@
1
+ import { Errors } from '@omnitron-dev/titan/errors';
2
+ import { OWNER_CAPABILITIES } from '../daemon/execution-capabilities.js';
3
+ import { parsePoolScaleRequest, assertPoolScaleTarget } from '../shared/pool-scale.js';
4
+ import { installedEntryRevision, installedExecutable, requireInstalledBinding } from './installed-execution.js';
5
+ import { topologyRevision } from '../project/topology-plan.js';
6
+ import { createHash } from 'node:crypto';
7
+ import { stackExecutionKey, executionScopeKey, executionScopeOwns } from '../shared/dto/stack-execution.js';
1
8
  /**
2
9
  * OrchestratorService — Core orchestration logic
3
10
  *
@@ -7,7 +14,7 @@
7
14
  * - Each app gets a ProcessSupervisor via pm.supervisor(config)
8
15
  * - Supervisor manages all child lifecycle: spawn, health, metrics, crash recovery, restart
9
16
  * - Single or multi-instance (pool) — configured via ISupervisorChildConfig
10
- * - Scaling delegates to supervisor.scaleChild()
17
+ * - Runtime resizing addresses one declared topology pool
11
18
  *
12
19
  * Classic mode:
13
20
  * - child_process.fork() with manual exit handling (legacy compat)
@@ -26,13 +33,16 @@
26
33
  * → Full Titan Application inside each worker
27
34
  * → Two Netron instances: PM management plane + app HTTP data plane
28
35
  */
36
+ import { ReadinessMonitor } from '../health/readiness.js';
29
37
  import fs from 'node:fs';
30
38
  import { readDeclaredConfig, withDeclaredConfig } from '../project/declared-config.js';
31
39
  import path from 'node:path';
32
40
  import { fileURLToPath } from 'node:url';
33
- import { PoolStrategy, SupervisionStrategy, ProcessLifecycleQueue, LifecyclePreempted, computeBackoff, isAlive, discoverManagedProcesses, } from '@omnitron-dev/titan-pm';
41
+ import { PoolStrategy, SupervisionStrategy, ProcessLifecycleQueue, LifecyclePreempted, computeBackoff, RestartWindow, isAlive, killChildAndVerify, discoverManagedProcesses, } from '@omnitron-dev/titan-pm';
34
42
  import { EventEmitter } from '@omnitron-dev/eventemitter';
35
43
  import { AppHandle } from './app-handle.js';
44
+ import { verifyLaunchRelease } from '../release/runtime-provenance.js';
45
+ import { withClosureLibraryPath } from '../release/closure-library-path.js';
36
46
  import { parsePsLine, parsePsBatch } from './ps-metrics.js';
37
47
  import { launchClassic } from './classic-launcher.js';
38
48
  import { resolveStartupOrder, resolveShutdownOrder } from './dependency-resolver.js';
@@ -60,7 +70,9 @@ function qualifyChildName(appName, childName) {
60
70
  const TOPOLOGY_EXPOSE_TIMEOUT_MS = 30_000;
61
71
  const TOPOLOGY_EXPOSE_POLL_MS = 250;
62
72
  import { ServiceRouter } from './service-router.js';
63
- import { loadBootstrapConfig, clearCacheFor } from './bootstrap-loader.js';
73
+ import { ApplicationTopology } from './application-topology.js';
74
+ import { clearCacheFor } from './bootstrap-loader.js';
75
+ import { readBootstrapMetadata } from '../project/bootstrap-metadata.js';
64
76
  /** Levels a pino logger accepts. A child is spawned with nothing else. */
65
77
  const PINO_LEVELS = new Set(['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent']);
66
78
  /**
@@ -81,6 +93,7 @@ import { collectOwnedPids } from './owned-pids.js';
81
93
  import { combineProcessHealth, notRunningHealth, poolHealth } from './app-health.js';
82
94
  import { combineProcessTraffic } from './app-traffic.js';
83
95
  import { CLI_VERSION } from '../config/defaults.js';
96
+ import { applicationBootstrapRuntime } from './application-runtime.js';
84
97
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
85
98
  // Resolve bootstrap-process path — .ts in dev (tsx), .js when compiled
86
99
  function resolveBootstrapProcessPath() {
@@ -185,6 +198,7 @@ export class OrchestratorService extends EventEmitter {
185
198
  logger;
186
199
  pm;
187
200
  stateStore;
201
+ ownerOptions;
188
202
  handles = new Map();
189
203
  /**
190
204
  * Per-name in-flight start lock (T#57). When two `startApp()` calls
@@ -197,6 +211,8 @@ export class OrchestratorService extends EventEmitter {
197
211
  * for the same name isn't permanently locked out.
198
212
  */
199
213
  startingApps = new Map();
214
+ stoppingApps = null;
215
+ stopGeneration = 0;
200
216
  /**
201
217
  * Per-app async serial-execution queue covering start / stop / restart
202
218
  * / crash-restart-timer (P0-E + P0-I + P2-B in the audit). Pre-this-
@@ -212,15 +228,18 @@ export class OrchestratorService extends EventEmitter {
212
228
  * The queue collapses all four into one primitive ordered by
213
229
  * priority (stop > restart > start > crash-restart). The same-key
214
230
  * mutex means stop ALWAYS observes a completed start, and an
215
- * explicit stop ALWAYS preempts a pending crash-restart timer.
231
+ * explicit stop cancels recovery waits before joining the queue.
216
232
  */
217
233
  lifecycleQueue = new ProcessLifecycleQueue();
218
234
  /**
219
- * Pending post-escalation cool-down timers, keyed by app name.
235
+ * Pending crash backoff and post-escalation timers, keyed by app name.
220
236
  * Held here rather than inside a lifecycle-queue slot so that a
221
237
  * crashed app still answers operator commands while it waits.
222
238
  */
223
239
  coolDownTimers = new Map();
240
+ appStopIntents = new Map();
241
+ readinessMonitor = new ReadinessMonitor();
242
+ readinessSignatures = new WeakMap();
224
243
  config = null;
225
244
  cwd;
226
245
  metricsTimer = null;
@@ -229,6 +248,57 @@ export class OrchestratorService extends EventEmitter {
229
248
  devMode = false;
230
249
  /** esbuild bundling pipeline — pre-bundles TS entry points for child processes */
231
250
  buildService = null;
251
+ watchDisabled = false;
252
+ watchSelection = null;
253
+ bootstrapSources = new Map();
254
+ allowsWatch(entry) {
255
+ return this.devMode && !this.watchDisabled && !entry.releaseRoot && entry.watch !== false &&
256
+ (!this.watchSelection || this.watchSelection.has(entry.name));
257
+ }
258
+ /** One policy for both fs.watch and esbuild; disabling does not stop apps. */
259
+ async setWatchMode(enabled, apps) {
260
+ this.devMode = enabled;
261
+ this.watchDisabled = !enabled;
262
+ this.watchSelection = apps ? new Set(apps.map((name) => this.resolveAppName(name) ?? name)) : null;
263
+ for (const [name, state] of this.restartCoalescer) {
264
+ if (!enabled || !this.handles.get(name) || !this.allowsWatch(this.handles.get(name).entry))
265
+ state.watchSerial = 0;
266
+ }
267
+ await Promise.all([...this.bootstrapSources.keys()].map((name) => this.syncBootstrapWatch(name)));
268
+ }
269
+ getBuildWatchedApps() {
270
+ return [...this.bootstrapSources].filter(([name]) => this.buildService?.isWatching(name))
271
+ .map(([name, source]) => ({ name, directory: path.dirname(source.path) }));
272
+ }
273
+ async syncBootstrapWatch(name) {
274
+ const source = this.bootstrapSources.get(name);
275
+ const entry = this.handles.get(name)?.entry;
276
+ if (!this.buildService || !source)
277
+ return;
278
+ if (!entry || this.executionBusy(name) || !this.allowsWatch(entry) || !entry.bootstrap ||
279
+ path.resolve(entry.cwd ?? this.cwd, entry.bootstrap) !== source.path) {
280
+ const state = this.restartCoalescer.get(name);
281
+ if (state)
282
+ state.watchSerial = 0;
283
+ await this.buildService.unwatchApp(name);
284
+ return;
285
+ }
286
+ if (this.buildService.isWatching(name))
287
+ return;
288
+ await this.buildService.watchApp(name, source.path, source.definition, () => {
289
+ void this.restartAfterChange(name).catch((error) => {
290
+ this.logger.error({ app: name, error: error.message }, 'Restart after source change failed');
291
+ });
292
+ }, this.devMode);
293
+ }
294
+ /** Automatic triggers remain revocable while queued; manual restart is independent. */
295
+ async restartAfterChange(name) {
296
+ const canonical = this.resolveAppName(name) ?? name;
297
+ const handle = this.handles.get(canonical);
298
+ if (!handle || !this.allowsWatch(handle.entry))
299
+ return handle;
300
+ return this.restartAppCoalesced(canonical, true, 'watch');
301
+ }
232
302
  /** Cached build results per app name */
233
303
  buildResults = new Map();
234
304
  /**
@@ -279,19 +349,9 @@ export class OrchestratorService extends EventEmitter {
279
349
  */
280
350
  bootReconciled = false;
281
351
  bootReconcilePromise = null;
282
- /** Daemon's Netron instance for native service routing */
283
- daemonNetron = null;
284
- /** Daemon Unix socket path for child-to-daemon Netron connections */
285
- daemonSocketPath = null;
286
- /**
287
- * Promise that resolves once the daemon's Netron is wired up. Apps that
288
- * declare topology cannot launch until this is ready — instead of failing
289
- * with "daemon Netron not available" the launcher awaits this promise
290
- * (with a generous timeout) so transient startup-order interleavings
291
- * resolve themselves instead of becoming user-visible errors.
292
- */
293
- daemonNetronReady;
294
- resolveDaemonNetronReady = () => undefined;
352
+ topologyDirectory = null;
353
+ topologyReady;
354
+ resolveTopologyReady = () => undefined;
295
355
  /**
296
356
  * Optional metrics sink. Set by the daemon at boot via
297
357
  * `setMetricsBridge` so the orchestrator can forward janitor sweeps,
@@ -300,25 +360,32 @@ export class OrchestratorService extends EventEmitter {
300
360
  * bootstraps).
301
361
  */
302
362
  metricsBridge = null;
303
- constructor(logger, pm, stateStore, cwd) {
363
+ constructor(logger, pm, stateStore, cwd, ownerOptions = {}) {
304
364
  super();
305
365
  this.logger = logger;
306
366
  this.pm = pm;
307
367
  this.stateStore = stateStore;
368
+ this.ownerOptions = ownerOptions;
308
369
  this.cwd = cwd ?? process.cwd();
309
- this.daemonNetronReady = new Promise((resolve) => {
310
- this.resolveDaemonNetronReady = resolve;
370
+ if (pm.outputCaptureVersion === 1)
371
+ pm.on('process:output', (name, line, stream, context) => {
372
+ const app = [...this.handles.keys()].filter(key => name === key || name.startsWith(`${key}/`) || name.startsWith(`${key}-`))
373
+ .sort((a, b) => b.length - a.length)[0];
374
+ const handle = app ? this.handles.get(app) : undefined;
375
+ if (app && handle)
376
+ this.childLogForwarder(app, handle)(line, stream, context);
377
+ });
378
+ this.topologyReady = new Promise((resolve) => {
379
+ this.resolveTopologyReady = resolve;
311
380
  });
312
381
  }
313
- /**
314
- * Set the daemon Netron instance and socket path for native topology routing.
315
- * Called by the daemon after start when Netron is available.
316
- */
317
- setDaemonNetron(netron, socketPath) {
318
- this.daemonNetron = netron;
319
- this.daemonSocketPath = socketPath;
320
- this.resolveDaemonNetronReady();
321
- this.logger.info({ socketPath }, 'Daemon Netron set for native topology routing');
382
+ /** Application RPC listeners never share the owner's management namespace. */
383
+ setTopologyDirectory(directory) {
384
+ this.topologyDirectory = path.resolve(directory);
385
+ this.resolveTopologyReady();
386
+ }
387
+ async bootstrapRuntime(bootstrap) {
388
+ return applicationBootstrapRuntime(bootstrap, BOOTSTRAP_PROCESS_PATH, this.ownerOptions.allowSdklessBootstrap ?? true);
322
389
  }
323
390
  /**
324
391
  * Wire the metrics bridge. Called once during daemon bootstrap.
@@ -350,18 +417,20 @@ export class OrchestratorService extends EventEmitter {
350
417
  this.metricsBridge?.recordAppEscalated(app);
351
418
  });
352
419
  }
353
- /**
354
- * Wait until the daemon Netron is available, with a hard ceiling so we
355
- * never hang forever if `setDaemonNetron()` was never wired in.
356
- */
357
- async ensureDaemonNetronReady(timeoutMs = 30_000) {
358
- if (this.daemonNetron && this.daemonSocketPath)
420
+ async ensureTopologyReady(timeoutMs = 30_000) {
421
+ if (this.topologyDirectory)
359
422
  return;
423
+ let timer;
360
424
  const timeout = new Promise((_resolve, reject) => {
361
- const timer = setTimeout(() => reject(new Error(`Daemon Netron not initialized within ${timeoutMs}ms — wiring bug?`)), timeoutMs);
425
+ timer = setTimeout(() => reject(new Error(`Application topology directory not configured within ${timeoutMs}ms`)), timeoutMs);
362
426
  timer.unref?.();
363
427
  });
364
- await Promise.race([this.daemonNetronReady, timeout]);
428
+ try {
429
+ await Promise.race([this.topologyReady, timeout]);
430
+ }
431
+ finally {
432
+ clearTimeout(timer);
433
+ }
365
434
  }
366
435
  // ============================================================================
367
436
  // Lifecycle
@@ -517,6 +586,7 @@ export class OrchestratorService extends EventEmitter {
517
586
  if (this.janitor)
518
587
  return this.janitor;
519
588
  this.janitor = new ProcessJanitor({
589
+ reapForeignOrphans: this.ownerOptions.reapForeignOrphans ?? true,
520
590
  logger: this.logger,
521
591
  getOwnedPids: () => this.collectOwnedPids(),
522
592
  onMetrics: (m) => this.metricsBridge?.recordJanitorSweep(m),
@@ -635,14 +705,9 @@ export class OrchestratorService extends EventEmitter {
635
705
  return pids;
636
706
  }
637
707
  async startApp(entry, config) {
638
- // T#63: run the one-shot cold-start reconcile (orphan reap +
639
- // janitor arming) before ANY app spawns. Project-mode boots flow
640
- // through `projectService.startStack → orchestrator.startApp`
641
- // and historically bypassed the reap entirely — a previous
642
- // daemon's children (now reparented to init) kept their HTTP
643
- // listen ports and the fresh child failed to bind silently.
644
- // No-op after first call thanks to `bootReconciled`.
645
- await this.ensureBootReconciled(config);
708
+ const stopGeneration = this.stopGeneration;
709
+ if (this.stoppingApps)
710
+ throw new Error('Application stop is in progress; new starts are not admitted');
646
711
  // Defensive auto-namespacing — promotes a bare entry.name to the
647
712
  // canonical `${project}/${stack}/${name}` form when the env carries
648
713
  // OMNITRON_PROJECT + OMNITRON_STACK. Catches every code path that
@@ -651,8 +716,29 @@ export class OrchestratorService extends EventEmitter {
651
716
  // - legacy ecosystem configs without per-app namespace
652
717
  // - daemon startAll() flows over a not-yet-namespaced config
653
718
  entry = ensureNamespacedEntry(entry);
719
+ this.assertAppStartAllowed(this.resolveAppName(entry.name) ?? entry.name);
720
+ if (!this.appStopIntents.has(entry.name)) {
721
+ this.appStopIntents.set(entry.name, { revision: 0, stopped: false });
722
+ }
723
+ const stopRevision = this.appStopIntents.get(entry.name)?.revision;
724
+ // T#63: run the one-shot cold-start reconcile (orphan reap +
725
+ // janitor arming) before ANY app spawns. Project-mode boots flow
726
+ // through `projectService.startStack → orchestrator.startApp`
727
+ // and historically bypassed the reap entirely — a previous
728
+ // daemon's children (now reparented to init) kept their HTTP
729
+ // listen ports and the fresh child failed to bind silently.
730
+ // No-op after first call thanks to `bootReconciled`.
731
+ await this.ensureBootReconciled(config);
732
+ if (this.stoppingApps || stopGeneration !== this.stopGeneration ||
733
+ stopRevision !== this.appStopIntents.get(entry.name)?.revision) {
734
+ throw new Error('Application stop interrupted start admission');
735
+ }
736
+ const intent = this.appStopIntents.get(entry.name);
737
+ const wasStopped = intent?.stopped;
738
+ if (intent)
739
+ intent.stopped = false;
654
740
  const inflight = this.startingApps.get(entry.name);
655
- if (inflight) {
741
+ if (inflight && !wasStopped) {
656
742
  this.logger.debug({ app: entry.name }, 'Coalescing concurrent startApp into in-flight launch (T#57)');
657
743
  return inflight;
658
744
  }
@@ -661,12 +747,17 @@ export class OrchestratorService extends EventEmitter {
661
747
  // (or in-flight) now waits its turn instead of racing through
662
748
  // and leaving an orphan supervisor.
663
749
  const promise = this.lifecycleQueue.enqueue(entry.name, 'start', () => this.startAppInternal(entry, config)).finally(() => {
664
- this.startingApps.delete(entry.name);
750
+ if (this.startingApps.get(entry.name) === promise)
751
+ this.startingApps.delete(entry.name);
665
752
  });
666
753
  this.startingApps.set(entry.name, promise);
667
754
  return promise;
668
755
  }
669
- async startAppInternal(entry, config) {
756
+ async startAppInternal(entry, config, installed) {
757
+ if (!installed)
758
+ this.assertAppStartAllowed(entry.name);
759
+ else
760
+ this.assertApplicationFence(entry.name);
670
761
  // Persist ecosystem config for restartApp — stack mode passes config per-app,
671
762
  // but restartApp calls startApp without it.
672
763
  if (config && !this.config) {
@@ -686,7 +777,8 @@ export class OrchestratorService extends EventEmitter {
686
777
  // - exact key already exists, online → return it (idempotent)
687
778
  // - exact key already exists, not online → fall through and re-launch
688
779
  // under the same key
689
- // - DIFFERENT key with the same effective short name:
780
+ // - different fully qualified keys are distinct apps and coexist
781
+ // - bare/qualified keys with the same effective short name:
690
782
  // - new is MORE specific (namespaced) and existing is bare → stop
691
783
  // the bare one and re-launch under the namespaced key. Without
692
784
  // this, a boot-race where bare-name auto-start beats the
@@ -696,13 +788,22 @@ export class OrchestratorService extends EventEmitter {
696
788
  // restart by canonical name, not register an alias.
697
789
  const effective = effectiveAppName(entry.name);
698
790
  const newIsNamespaced = entry.name.includes('/');
791
+ if (!newIsNamespaced && [...this.handles.keys()].filter(key => key.includes('/') && effectiveAppName(key) === effective).length > 1) {
792
+ throw new Error(`Ambiguous app name '${entry.name}'; use its full project/stack/app identity`);
793
+ }
699
794
  for (const [key, h] of this.handles) {
700
795
  if (key === entry.name)
701
796
  continue;
702
797
  if (effectiveAppName(key) !== effective)
703
798
  continue;
704
799
  const existingIsNamespaced = key.includes('/');
705
- // Same effective app under a different key.
800
+ // Qualified identities are separate deployments, even when their basename matches.
801
+ if (newIsNamespaced && existingIsNamespaced)
802
+ continue;
803
+ if (installed)
804
+ throw new Error('Installed stack start cannot displace another application');
805
+ this.assertAppStartAllowed(key);
806
+ // A bare alias may still refer to the one qualified deployment.
706
807
  if (h.status === 'online') {
707
808
  if (newIsNamespaced && !existingIsNamespaced) {
708
809
  this.logger.info({ stale: key, replacing_with: entry.name, effective }, 'Stopping bare-name handle to re-register under namespaced key');
@@ -710,7 +811,8 @@ export class OrchestratorService extends EventEmitter {
710
811
  await this.stopApp(key);
711
812
  }
712
813
  catch (err) {
713
- this.logger.warn({ stale: key, error: err.message }, 'stopApp during dedup failed — clearing handle anyway');
814
+ this.logger.error({ stale: key, error: err.message }, 'Cannot replace app registration while its previous processes remain unconfirmed');
815
+ throw new Error(`Cannot replace '${key}' with '${entry.name}': the previous application did not stop`, { cause: err });
714
816
  }
715
817
  this.handles.delete(key);
716
818
  if (key !== entry.name)
@@ -728,8 +830,7 @@ export class OrchestratorService extends EventEmitter {
728
830
  // its services are still registered on the daemon's Netron. Dropping the
729
831
  // handle here is the last moment anything knows they exist — or that its
730
832
  // processes still run: an errored app's other children and its pools.
731
- await this.releaseExposedServices(h);
732
- await this.tearDownProcesses(h);
833
+ await this.tearDownApp(h);
733
834
  this.handles.delete(key);
734
835
  // Drop any metrics that were collected under the stale alias so it
735
836
  // doesn't haunt future snapshots as a ghost offline app.
@@ -746,12 +847,15 @@ export class OrchestratorService extends EventEmitter {
746
847
  // crashing leaves its siblings — the server among them — up; and its pools
747
848
  // were never any supervisor's to stop. Stopped before the new handle
748
849
  // starts, or the new one finds its own predecessor on its port: on
749
- // daos/test (2026-09-25) paysys's crash restarts failed five times on
850
+ // sample/test (2026-09-25) payments's crash restarts failed five times on
750
851
  // `EADDRINUSE :3004`, «held by … a child this daemon still accounts for».
751
- if (existing) {
752
- await this.releaseExposedServices(existing);
753
- await this.tearDownProcesses(existing);
852
+ if (existing && !installed) {
853
+ await this.tearDownApp(existing);
754
854
  }
855
+ // A sealed entry never inherits a former source build, including a
856
+ // bootstrap-to-classic transition. Retained resumes still reject pollution.
857
+ if (entry.releaseRoot && !installed)
858
+ await this.discardSourceBuild(entry.name);
755
859
  const mode = entry.bootstrap ? 'bootstrap' : 'classic';
756
860
  const handle = new AppHandle(entry, mode);
757
861
  // The restart budget belongs to the APP, not to this handle instance.
@@ -759,8 +863,10 @@ export class OrchestratorService extends EventEmitter {
759
863
  // can never reach `maxRestarts` — which made the budget, the escalation
760
864
  // and the cool-down unreachable even once the restart itself worked. The
761
865
  // window is enforced by the policy, not by forgetting.
762
- if (existing)
866
+ if (existing) {
763
867
  handle.restarts = existing.restarts;
868
+ handle.restartWindow = existing.restartWindow;
869
+ }
764
870
  this.handles.set(entry.name, handle);
765
871
  // Arm metrics sampling here — the one place an app enters the registry.
766
872
  //
@@ -777,16 +883,20 @@ export class OrchestratorService extends EventEmitter {
777
883
  this.ensureMetricsPolling();
778
884
  this.logger.info({ app: entry.name, mode }, 'Starting app');
779
885
  try {
780
- if (mode === 'classic') {
781
- await this.launchClassicMode(entry, handle, cfg);
782
- }
783
- else {
784
- await this.launchBootstrapMode(entry, handle, cfg);
886
+ if (entry.releaseRoot) {
887
+ // Bootstrap metadata executes application code. Authenticate the sealed
888
+ // tree before introspection on initial launches as well as resumes.
889
+ handle.release = await verifyLaunchRelease(entry, handle.generation, [installedExecutable(entry, this.cwd)]);
890
+ requireInstalledBinding(handle.release, installedEntryRevision(entry, cfg, this.cwd), installed);
785
891
  }
892
+ const launch = mode === 'classic' ? await this.launchClassicMode(entry, handle, cfg, installed)
893
+ : await this.launchBootstrapMode(entry, handle, cfg, installed);
786
894
  // «App started» only for an app that is. It was logged in the same
787
895
  // millisecond as a child's «Process failed to start», for an app whose
788
896
  // processes never all came up.
789
897
  if (handle.status === 'online') {
898
+ if (launch)
899
+ this.installedLaunches.set(handle, { binding: Object.freeze(launch), config: cfg });
790
900
  this.logger.info({ app: entry.name, pid: handle.pid, mode }, 'App started');
791
901
  }
792
902
  else {
@@ -811,11 +921,24 @@ export class OrchestratorService extends EventEmitter {
811
921
  // The counter is bumped by hand because `markErrored()` deliberately
812
922
  // does not (an app that never ran has not "restarted"), and without it
813
923
  // the budget below can never trip and the retry would be unbounded.
924
+ // A rejected topology is not a partially running application. Keep
925
+ // resource ownership if cleanup fails so a later stop can retry it.
926
+ handle.markStopping();
927
+ let failure = err;
928
+ try {
929
+ await this.tearDownApp(handle);
930
+ handle.markStopped();
931
+ }
932
+ catch (cleanupError) {
933
+ failure = new AggregateError([err, cleanupError], `Application '${entry.name}' startup failed and cleanup is incomplete: ${String(err)}; ${String(cleanupError)}`);
934
+ }
814
935
  handle.markErrored();
936
+ handle.recordExit({ code: null, signal: null, expected: false, message: String(failure) });
815
937
  handle.restarts++;
816
938
  this.persistState();
817
- this.scheduleRecovery(entry, handle, cfg);
818
- throw err;
939
+ if (!installed)
940
+ this.scheduleRecovery(entry, handle, cfg);
941
+ throw failure;
819
942
  }
820
943
  }
821
944
  /**
@@ -827,13 +950,14 @@ export class OrchestratorService extends EventEmitter {
827
950
  * `topologyPools` — so `supervisor.stop()` never reached them, and nothing
828
951
  * in the orchestrator destroyed a pool: only the daemon's own shutdown did.
829
952
  * Every restart of an app with `instances > 1` left the previous workers
830
- * running. On daos/test (2026-09-25): priceverse's `ohlcv-aggregator` and
953
+ * running. On sample/test (2026-09-25): quotes's `ohlcv-aggregator` and
831
954
  * storage's `transform` in three generations at once.
832
955
  *
833
956
  * The pools go even when the supervisor's stop throws: a stop that failed
834
957
  * half-way must not also leave the half nobody asked about.
835
958
  */
836
959
  async tearDownProcesses(handle, force = false, timeout = 10_000) {
960
+ const failures = [];
837
961
  try {
838
962
  if (handle.mode === 'bootstrap' && handle.supervisor) {
839
963
  await handle.supervisor.stop();
@@ -842,58 +966,472 @@ export class OrchestratorService extends EventEmitter {
842
966
  await this.stopChildProcess(handle, force, timeout);
843
967
  }
844
968
  }
845
- finally {
846
- for (const [name, pool] of handle.topologyPools) {
847
- try {
848
- await pool.destroy();
849
- }
850
- catch (err) {
851
- this.logger.warn({ app: handle.name, pool: name, error: err.message }, 'Destroying a topology pool failed — its workers may still run');
852
- }
969
+ catch (error) {
970
+ failures.push(error);
971
+ }
972
+ for (const [name, pool] of handle.topologyPools) {
973
+ try {
974
+ await pool.destroy();
975
+ handle.topologyPools.delete(name);
976
+ }
977
+ catch (error) {
978
+ failures.push(error);
979
+ this.logger.error({ app: handle.name, pool: name, error: String(error) }, 'Pool termination unconfirmed; retaining ownership for retry');
853
980
  }
854
- handle.topologyPools.clear();
981
+ }
982
+ if (failures.length) {
983
+ throw new AggregateError(failures, `Application stop incomplete: ${failures.map(String).join('; ')}`);
855
984
  }
856
985
  }
857
- /**
858
- * Give back every service an app exposed on the daemon's Netron.
859
- *
860
- * A registration outlives the process behind it: the daemon keeps answering
861
- * `queryInterface` with the full method list and every call through the name
862
- * fails at the socket. `takeOverExisting` rescues a name the next launch
863
- * re-exposes; one it does not stays advertised for the life of the daemon.
864
- */
986
+ /** Close only the listener and registrations owned by this launch. */
865
987
  async releaseExposedServices(handle) {
866
- if (!handle.serviceRouter)
988
+ if (!handle.topology)
867
989
  return;
990
+ await handle.topology.close();
991
+ handle.topology = null;
992
+ }
993
+ async tearDownApp(handle, force = false, timeout = 10_000) {
994
+ const failures = [];
868
995
  try {
869
- await handle.serviceRouter.releaseAll();
996
+ await this.releaseExposedServices(handle);
870
997
  }
871
- catch (err) {
872
- this.logger.warn({ app: handle.name, error: err.message }, 'Releasing exposed services failed — the daemon may still advertise them');
998
+ catch (error) {
999
+ failures.push(error);
1000
+ }
1001
+ try {
1002
+ await this.tearDownProcesses(handle, force, timeout);
1003
+ }
1004
+ catch (error) {
1005
+ failures.push(error);
1006
+ }
1007
+ if (failures.length)
1008
+ throw new AggregateError(failures, `Application '${handle.name}' stop incomplete: ${failures.map(String).join('; ')}`);
1009
+ }
1010
+ /** Historical launch identity stays private to the handle; membership changes can invalidate its live release observation. */
1011
+ installedLaunches = new WeakMap();
1012
+ executionOperations = new Map();
1013
+ getExecutionCapabilities() { return OWNER_CAPABILITIES; }
1014
+ executionBusy(name) {
1015
+ return [...this.executionOperations.keys()].some(key => name === key || name.startsWith(`${key}/`));
1016
+ }
1017
+ assertExecutionIdle(scope) {
1018
+ const key = executionScopeKey(scope);
1019
+ if ([...this.executionOperations.keys()].some(active => active === key || active.startsWith(`${key}/`) || key.startsWith(`${active}/`))) {
1020
+ throw new Error(`Execution scope '${key}' is busy; wait for its stop or reconciliation before starting another operation`);
1021
+ }
1022
+ }
1023
+ /** One in-flight boundary for whole-stack and child-scope lifecycle mutations. */
1024
+ executionOperation(scope, operationId, fingerprint, work) {
1025
+ const key = executionScopeKey(scope);
1026
+ if (typeof operationId !== 'string' || !/^[a-f0-9-]{36}$/.test(operationId))
1027
+ throw new Error('Invalid execution operation identity');
1028
+ const active = this.executionOperations.get(key);
1029
+ if (active?.id === operationId && active.fingerprint === fingerprint)
1030
+ return active.promise;
1031
+ this.assertExecutionIdle(scope);
1032
+ // Reserve before invoking work, including its synchronous checks and first write.
1033
+ const promise = Promise.resolve().then(work).finally(() => this.executionOperations.delete(key));
1034
+ this.executionOperations.set(key, { id: operationId, fingerprint, promise });
1035
+ return promise;
1036
+ }
1037
+ /**
1038
+ * Reconcile an explicitly selected graph behind its durable stop fence.
1039
+ * This neither stops nor starts a process and never deletes logs or artifacts.
1040
+ * The controller's existing release selection remains the desired-state source.
1041
+ */
1042
+ reconcileStoppedStack(request) {
1043
+ const input = structuredClone(request);
1044
+ const { plan, entries, operationId } = input;
1045
+ const key = stackExecutionKey(plan);
1046
+ if (plan.application !== undefined || plan.phase !== 'stopped') {
1047
+ throw new Error('Stack reconciliation requires a completed whole-stack stop');
1048
+ }
1049
+ if (!Array.isArray(entries))
1050
+ throw new Error('Stack reconciliation requires the complete target graph');
1051
+ const target = new Map();
1052
+ for (const entry of entries) {
1053
+ if (!entry || typeof entry.name !== 'string' || !entry.name.startsWith(`${key}/`) ||
1054
+ executionScopeKey({ ...plan, application: entry.name.slice(key.length + 1) }) !== entry.name || target.has(entry.name)) {
1055
+ throw new Error('Stack reconciliation requires unique canonical applications inside its scope');
1056
+ }
1057
+ target.set(entry.name, entry);
1058
+ }
1059
+ const fingerprint = topologyRevision({ kind: 'reconcile', ...input });
1060
+ return this.executionOperation(plan, operationId, fingerprint, async () => {
1061
+ if (topologyRevision(this.stackExecutionPlan(plan)) !== topologyRevision(plan)) {
1062
+ throw new Error('Stack changed; inspect its stopped generations before reconciling');
1063
+ }
1064
+ const retained = plan.apps.map(app => {
1065
+ const handle = this.handles.get(app.name);
1066
+ return { handle, definition: handle.definitionRevision };
1067
+ });
1068
+ const assertStopped = () => {
1069
+ if (this.stoppingApps)
1070
+ throw new Error('Global application shutdown is active; wait before reconciling the stack');
1071
+ for (const { handle, definition } of retained) {
1072
+ if (this.handles.get(handle.name) !== handle || handle.definitionRevision !== definition ||
1073
+ handle.status !== 'stopped' || handle.pid !== null || handle.childProcess || handle.supervisor ||
1074
+ handle.topology || handle.topologyPools.size || this.restartCoalescer.get(handle.name)?.inFlight) {
1075
+ throw new Error(`Application '${handle.name}' is not the reviewed, fully stopped generation`);
1076
+ }
1077
+ }
1078
+ };
1079
+ assertStopped();
1080
+ // Revoke old plans durably before changing watchers or the retained inventory.
1081
+ const intent = this.stateStore.updateStackIntent(plan, current => {
1082
+ if (current.phase !== 'stopped' || current.revision !== plan.revision || current.revision === Number.MAX_SAFE_INTEGER) {
1083
+ throw new Error('Stack stop changed before reconciliation');
1084
+ }
1085
+ return { phase: 'stopped', revision: current.revision + 1, operationId, fingerprint };
1086
+ });
1087
+ for (const { handle } of retained)
1088
+ await this.discardSourceBuild(handle.name);
1089
+ assertStopped();
1090
+ const expected = { ...plan, revision: intent.revision };
1091
+ if (topologyRevision(this.stackExecutionPlan(plan)) !== topologyRevision(expected)) {
1092
+ throw new Error('Stack changed during reconciliation; it has not been enabled');
1093
+ }
1094
+ const retired = [];
1095
+ // No await between final validation and the complete inventory change.
1096
+ for (const { handle } of retained) {
1097
+ const entry = target.get(handle.name);
1098
+ if (entry)
1099
+ handle.redefine(entry);
1100
+ else {
1101
+ this.handles.delete(handle.name);
1102
+ this.clearCoolDown(handle.name);
1103
+ this.restartCoalescer.delete(handle.name);
1104
+ this.appStopIntents.delete(handle.name);
1105
+ retired.push(handle.name);
1106
+ }
1107
+ }
1108
+ this.persistState();
1109
+ for (const name of retired) {
1110
+ this.emit('app:retired', name);
1111
+ this.metricsBridge?.evictApp(name);
1112
+ }
1113
+ await this.stateStore.flush();
1114
+ this.logger.info({ project: plan.project, stack: plan.stack, revision: intent.revision, retired }, 'Stopped stack membership reconciled');
1115
+ return { project: plan.project, stack: plan.stack, revision: intent.revision, retired,
1116
+ retained: retained.filter(({ handle }) => target.has(handle.name)).map(({ handle }) => handle.name),
1117
+ added: [...target.keys()].filter(name => !plan.apps.some(app => app.name === name)), observedAt: new Date().toISOString() };
1118
+ });
1119
+ }
1120
+ /** The owner supplies generations; backend caches cannot establish stop authority. */
1121
+ async inspectStackExecution(scope) {
1122
+ return this.stackExecutionPlan(scope);
1123
+ }
1124
+ stackExecutionPlan(scope) {
1125
+ return this.executionPlan({ project: scope.project, stack: scope.stack });
1126
+ }
1127
+ async inspectExecution(scope) {
1128
+ return this.executionPlan(scope);
1129
+ }
1130
+ executionPlan(scope) {
1131
+ const key = executionScopeKey(scope);
1132
+ const names = this.listHandleNames().filter(name => executionScopeOwns(scope, name)).sort();
1133
+ if (scope.application !== undefined && names.length !== 1)
1134
+ throw new Error(`Application '${key}' is not retained by this owner`);
1135
+ if (names.some(name => this.lifecycleQueue.isBusy(name)) ||
1136
+ [...this.startingApps.keys()].some(name => executionScopeOwns(scope, name))) {
1137
+ throw new Error(`Execution scope '${key}' has active application operations; retry after they finish`);
1138
+ }
1139
+ const { revision, phase } = this.stateStore.getExecutionIntent(scope);
1140
+ const parent = scope.application !== undefined ? this.stateStore.getStackIntent(scope) : undefined;
1141
+ if (parent?.phase === 'stopping' || parent?.phase === 'starting')
1142
+ throw new Error('Parent stack has an unfinished operation');
1143
+ return { project: scope.project, stack: scope.stack, revision, phase,
1144
+ ...(scope.application !== undefined && { application: scope.application, parentRevision: parent.revision }),
1145
+ apps: names.map(name => ({ name, generation: this.handles.get(name).generation })) };
1146
+ }
1147
+ retainedApp(name, generation) {
1148
+ const handle = this.handles.get(name);
1149
+ if (!handle || handle.generation !== generation || handle.status !== 'stopped' || handle.pid !== null ||
1150
+ handle.childProcess || handle.supervisor || handle.topology || handle.topologyPools.size) {
1151
+ throw new Error(`Application '${name}' is not the retained stopped generation`);
1152
+ }
1153
+ const bare = effectiveAppName(name);
1154
+ if (this.handles.has(bare) || this.startingApps.has(bare) || this.lifecycleQueue.isBusy(bare) ||
1155
+ this.buildResults.has(name) || !handle.entry.releaseRoot || !path.isAbsolute(handle.entry.cwd ?? '') ||
1156
+ (handle.entry.bootstrap && !handle.entry.env?.['OMNITRON_STACK'])) {
1157
+ throw new Error(`Application '${name}' requires an unambiguous precompiled installed release with retained launch configuration`);
1158
+ }
1159
+ const launch = this.installedLaunches.get(handle);
1160
+ if (!launch)
1161
+ throw new Error(`Application '${name}' has no verified installed launch recorded for its generation`);
1162
+ if (launch.binding.entrySha256 !== installedEntryRevision(handle.entry, launch.config, this.cwd)) {
1163
+ throw new Error(`Application '${name}' launch configuration changed since its verified launch`);
1164
+ }
1165
+ return { handle, ...launch };
1166
+ }
1167
+ /** A stopped intent is insufficient if its handles or their launch inputs disappeared. */
1168
+ async inspectInstalledStack(scope) {
1169
+ const plan = this.stackExecutionPlan(scope);
1170
+ if (plan.phase !== 'stopped' || !plan.apps.length)
1171
+ throw new Error('Installed stack start requires a completed stop with retained applications');
1172
+ for (const item of plan.apps)
1173
+ this.assertApplicationFence(item.name);
1174
+ const apps = [];
1175
+ for (const item of plan.apps) {
1176
+ const { handle, binding } = this.retainedApp(item.name, item.generation);
1177
+ const entry = handle.entry;
1178
+ const executable = installedExecutable(entry, this.cwd);
1179
+ const paths = [executable, ...(handle.topologyProcesses ?? []).map(child => path.resolve(path.dirname(executable), child.module))];
1180
+ const release = await verifyLaunchRelease(entry, item.generation, paths);
1181
+ requireInstalledBinding(release, binding.entrySha256, binding);
1182
+ apps.push({ ...item, installed: { ...binding } });
1183
+ }
1184
+ for (const item of plan.apps)
1185
+ this.retainedApp(item.name, item.generation);
1186
+ if (topologyRevision(this.stackExecutionPlan(scope)) !== topologyRevision(plan)) {
1187
+ throw new Error('Installed stack changed during inspection; prepare a new start');
1188
+ }
1189
+ return { ...plan, apps };
1190
+ }
1191
+ async openInstalledStack({ operationId, plan }) {
1192
+ if (typeof operationId !== 'string' || !/^[a-f0-9-]{36}$/.test(operationId))
1193
+ throw new Error('Invalid start operation identity');
1194
+ this.assertExecutionIdle(plan);
1195
+ const observed = this.stackExecutionPlan(plan);
1196
+ if (observed.phase !== 'stopped' || plan.phase !== 'stopped' || observed.revision !== plan.revision ||
1197
+ !observed.apps.length || observed.apps.length !== plan.apps.length ||
1198
+ observed.apps.some((item, index) => {
1199
+ const expected = plan.apps[index];
1200
+ if (!expected?.installed || expected.name !== item.name || expected.generation !== item.generation)
1201
+ return true;
1202
+ return topologyRevision(this.retainedApp(item.name, item.generation).binding) !== topologyRevision(expected.installed);
1203
+ }))
1204
+ throw new Error('Installed stack changed; prepare a new start');
1205
+ for (const item of plan.apps)
1206
+ this.assertApplicationFence(item.name);
1207
+ const fingerprint = topologyRevision(plan);
1208
+ this.stateStore.updateStackIntent(plan, current => {
1209
+ if (current.phase !== 'stopped' || current.revision !== plan.revision || current.revision === Number.MAX_SAFE_INTEGER) {
1210
+ throw new Error('Installed stack stop is no longer current');
1211
+ }
1212
+ return { phase: 'starting', revision: current.revision + 1, operationId, fingerprint, remaining: plan.apps.map(app => app.name) };
1213
+ });
1214
+ }
1215
+ async resumeInstalledApp({ operationId, plan, name }) {
1216
+ const app = plan.apps.find(item => item.name === name);
1217
+ if (!app?.installed || !name.startsWith(`${stackExecutionKey(plan)}/`))
1218
+ throw new Error('Application is outside the prepared installed stack');
1219
+ const expected = app.installed;
1220
+ const fingerprint = topologyRevision(plan);
1221
+ const stopGeneration = this.stopGeneration;
1222
+ const stopRevision = this.appStopIntents.get(name)?.revision;
1223
+ await this.lifecycleQueue.enqueue(name, 'start', async () => {
1224
+ const { handle, config } = this.retainedApp(name, app.generation);
1225
+ const entry = structuredClone(handle.entry);
1226
+ if (this.stoppingApps || this.stopGeneration !== stopGeneration ||
1227
+ installedEntryRevision(entry, config, this.cwd) !== expected.entrySha256) {
1228
+ throw new Error('Installed start admission changed');
1229
+ }
1230
+ // Reserve before the first effect. A crash or lost reply cannot authorize a second attempt.
1231
+ this.stateStore.updateStackIntent(plan, current => {
1232
+ if (current.phase !== 'starting' || current.operationId !== operationId || current.fingerprint !== fingerprint ||
1233
+ current.pendingApp || !current.remaining?.includes(name))
1234
+ throw new Error('Installed start is stale, busy or already consumed');
1235
+ return { ...current, pendingApp: name };
1236
+ });
1237
+ await this.ensureBootReconciled(config);
1238
+ this.retainedApp(name, app.generation);
1239
+ // Introspection loads bootstrap code. Verify it before reading the process topology;
1240
+ // the final launch verification binds the child modules discovered there.
1241
+ if (entry.bootstrap) {
1242
+ const evidence = await verifyLaunchRelease(entry, app.generation, [installedExecutable(entry, this.cwd)]);
1243
+ requireInstalledBinding(evidence, installedEntryRevision(entry, config, this.cwd), expected);
1244
+ this.retainedApp(name, app.generation);
1245
+ }
1246
+ if (this.stoppingApps || this.stopGeneration !== stopGeneration ||
1247
+ stopRevision !== this.appStopIntents.get(name)?.revision)
1248
+ throw new Error('Stop interrupted installed start admission');
1249
+ const intent = this.appStopIntents.get(name);
1250
+ if (intent)
1251
+ intent.stopped = false;
1252
+ const started = await this.startAppInternal(entry, config, expected);
1253
+ if (started.status !== 'online')
1254
+ throw new Error(`Installed application '${name}' did not come online`);
1255
+ requireInstalledBinding(started.release, installedEntryRevision(started.entry, config, this.cwd), expected);
1256
+ this.stateStore.updateStackIntent(plan, current => {
1257
+ if (current.phase !== 'starting' || current.operationId !== operationId || current.fingerprint !== fingerprint ||
1258
+ current.pendingApp !== name)
1259
+ throw new Error('Installed start was superseded');
1260
+ const remaining = current.remaining.filter(item => item !== name);
1261
+ if (!remaining.length && plan.apps.some(item => this.handles.get(item.name)?.status !== 'online')) {
1262
+ throw new Error('Installed start incomplete: previously started application is no longer online');
1263
+ }
1264
+ return remaining.length ? { phase: 'starting', revision: current.revision, operationId, fingerprint, remaining }
1265
+ : { phase: 'running', revision: current.revision };
1266
+ });
1267
+ });
1268
+ }
1269
+ async enableStackExecution(scope, options = {}) {
1270
+ return this.enableExecution({ project: scope.project, stack: scope.stack }, options);
1271
+ }
1272
+ async enableExecution(scope, options = {}) {
1273
+ const key = executionScopeKey(scope);
1274
+ this.assertExecutionIdle(scope);
1275
+ if (scope.application !== undefined && this.stateStore.getStackIntent(scope).phase !== 'running') {
1276
+ throw new Error('Parent stack must be running before admitting an application start');
1277
+ }
1278
+ this.stateStore.updateExecutionIntent(scope, current => {
1279
+ if (scope.application !== undefined && (!Number.isSafeInteger(options.expectedRevision) || options.expectedRevision !== current.revision)) {
1280
+ throw new Error('Application execution intent changed; inspect it before admitting a start');
1281
+ }
1282
+ if (current.phase === 'starting')
1283
+ throw new Error(`Stack '${key}' has an unfinished installed start; inspect and stop it before starting again`);
1284
+ if (current.phase === 'stopping')
1285
+ throw new Error(`Stack '${key}' has an unconfirmed stop; complete it before starting`);
1286
+ if (current.phase === 'running')
1287
+ return current;
1288
+ if (options.automatic)
1289
+ throw new Error(`Stack '${key}' was deliberately stopped; an explicit stack start is required`);
1290
+ if (current.revision === Number.MAX_SAFE_INTEGER)
1291
+ throw new Error('Stack execution revision exhausted');
1292
+ return { revision: current.revision + 1, phase: 'running' };
1293
+ });
1294
+ }
1295
+ stopStackExecution(request) {
1296
+ if (request.plan.application !== undefined)
1297
+ throw new Error('Use the scoped execution contract for an application stop');
1298
+ return this.stopExecution(request);
1299
+ }
1300
+ stopExecution(request) {
1301
+ const fingerprint = topologyRevision({ kind: 'stop', plan: request.plan });
1302
+ return this.executionOperation(request.plan, request.operationId, fingerprint, () => this.stopExecutionNow(request));
1303
+ }
1304
+ async stopExecutionNow({ operationId, plan }) {
1305
+ const key = executionScopeKey(plan);
1306
+ const fingerprint = createHash('sha256').update(JSON.stringify(plan)).digest('hex');
1307
+ const prior = this.stateStore.getExecutionIntent(plan);
1308
+ const retry = prior.operationId === operationId && prior.fingerprint === fingerprint;
1309
+ if (prior.operationId === operationId && !retry)
1310
+ throw new Error('Stop operation identity was reused with different arguments');
1311
+ if (!retry) {
1312
+ const observed = this.executionPlan(plan);
1313
+ if (JSON.stringify(observed) !== JSON.stringify(plan))
1314
+ throw new Error(`Stack '${key}' changed; prepare a new stop`);
1315
+ }
1316
+ // A durable stop fence also covers crash recovery and file-watch restarts.
1317
+ // No newly admitted start may pass it while this operation awaits exits.
1318
+ const assertParent = () => {
1319
+ if (plan.application === undefined)
1320
+ return;
1321
+ const parent = this.stateStore.getStackIntent(plan);
1322
+ if (parent.revision !== plan.parentRevision || parent.phase === 'starting' || parent.phase === 'stopping') {
1323
+ throw new Error('Parent stack intent changed; inspect before retrying the application operation');
1324
+ }
1325
+ };
1326
+ assertParent();
1327
+ const intent = this.stateStore.updateExecutionIntent(plan, current => {
1328
+ if (current.operationId === operationId && current.fingerprint === fingerprint)
1329
+ return current;
1330
+ if (current.revision !== plan.revision)
1331
+ throw new Error(`Stack '${key}' intent changed; prepare a new stop`);
1332
+ if (current.revision === Number.MAX_SAFE_INTEGER)
1333
+ throw new Error('Stack execution revision exhausted');
1334
+ return { revision: current.revision + 1, phase: 'stopping', operationId, fingerprint };
1335
+ });
1336
+ const failures = [];
1337
+ for (const expected of [...plan.apps].reverse()) {
1338
+ assertParent();
1339
+ const handle = this.handles.get(expected.name);
1340
+ if (!executionScopeOwns(plan, expected.name) || !handle || handle.generation !== expected.generation) {
1341
+ failures.push(new Error(`Application '${expected.name}' changed generation; inspect before retrying`));
1342
+ continue;
1343
+ }
1344
+ try {
1345
+ await this.stopApp(expected.name);
1346
+ }
1347
+ catch (error) {
1348
+ failures.push(error);
1349
+ }
1350
+ }
1351
+ const survivors = this.listHandleNames().filter(name => executionScopeOwns(plan, name) && this.handles.get(name)?.status !== 'stopped');
1352
+ if (survivors.length)
1353
+ failures.push(new Error(`Exit unconfirmed for: ${survivors.join(', ')}`));
1354
+ if (failures.length)
1355
+ throw new AggregateError(failures, `Stack '${key}' stop incomplete: ${failures.map(String).join('; ')}`);
1356
+ assertParent();
1357
+ this.stateStore.updateExecutionIntent(plan, current => {
1358
+ if (current.revision !== intent.revision || current.operationId !== operationId)
1359
+ throw new Error('Stack stop authority changed');
1360
+ return { ...current, phase: 'stopped' };
1361
+ });
1362
+ return { project: plan.project, stack: plan.stack, operationId, revision: intent.revision,
1363
+ ...(plan.application !== undefined && { application: plan.application }),
1364
+ stopped: plan.apps.map(app => app.name), observedAt: new Date().toISOString() };
1365
+ }
1366
+ assertAppStartAllowed(name) {
1367
+ const parts = name.split('/');
1368
+ // Stack stops own the whole prefix, including retained legacy nested names.
1369
+ // Admission must enforce the same boundary before recovery or watch can restart them.
1370
+ if (parts.length < 3)
1371
+ return;
1372
+ const scope = { project: parts[0], stack: parts[1] };
1373
+ this.assertExecutionIdle({ ...scope, ...(parts.length === 3 && { application: parts[2] }) });
1374
+ const phase = this.stateStore.getStackIntent(scope).phase;
1375
+ if (phase === 'starting')
1376
+ throw new Error(`Stack '${stackExecutionKey(scope)}' has an unfinished installed stack start; inspect its receipt and stop before retrying`);
1377
+ if (phase !== 'running') {
1378
+ throw new Error(`Stack '${stackExecutionKey(scope)}' is stopped or stopping; use stack start after confirming its stop`);
1379
+ }
1380
+ this.assertApplicationFence(name);
1381
+ }
1382
+ assertApplicationFence(name) {
1383
+ const parts = name.split('/');
1384
+ if (parts.length !== 3)
1385
+ return;
1386
+ const scope = { project: parts[0], stack: parts[1], application: parts[2] };
1387
+ if (this.stateStore.getExecutionIntent(scope).phase !== 'running') {
1388
+ throw new Error(`Application '${name}' is fenced; inspect and explicitly admit its start`);
873
1389
  }
874
- handle.serviceRouter = null;
875
1390
  }
876
1391
  async stopApp(name, force = false, timeout = 10_000) {
877
1392
  const canonical = this.resolveAppName(name) ?? name;
878
1393
  // Outside the queue on purpose: the operator's intent lands the
879
1394
  // moment the command arrives, not whenever the queue drains.
1395
+ // Unknown names need no retained intent. Start admission registers its
1396
+ // token before its first await, including before a handle exists.
1397
+ if (this.handles.has(canonical) || this.appStopIntents.has(canonical)) {
1398
+ this.appStopIntents.set(canonical, {
1399
+ revision: (this.appStopIntents.get(canonical)?.revision ?? 0) + 1,
1400
+ stopped: true,
1401
+ });
1402
+ }
880
1403
  this.clearCoolDown(canonical);
1404
+ const restart = this.restartCoalescer.get(canonical);
1405
+ if (restart) {
1406
+ restart.manualSerial = 0;
1407
+ restart.watchSerial = 0;
1408
+ restart.cooldownUntil = 0;
1409
+ }
881
1410
  return this.lifecycleQueue.enqueue(canonical, 'stop', async () => {
882
1411
  const handle = this.handles.get(canonical);
883
- if (!handle || handle.status === 'stopped')
1412
+ if (!handle || (handle.status === 'stopped' && !handle.topology && !handle.supervisor && !handle.childProcess && handle.topologyPools.size === 0))
884
1413
  return;
885
1414
  handle.markStopping();
886
- // Unexpose topology services from daemon Netron before stopping processes
887
- await this.releaseExposedServices(handle);
888
- await this.tearDownProcesses(handle, force, timeout);
1415
+ await this.tearDownApp(handle, force, timeout);
889
1416
  handle.markStopped();
890
1417
  this.persistState();
891
1418
  this.logger.info({ app: name }, 'App stopped');
892
1419
  });
893
1420
  }
894
- async stopAll(force = false) {
895
- if (!this.config)
896
- return 0;
1421
+ stopAll(force = false) {
1422
+ if (this.stoppingApps)
1423
+ return this.stoppingApps;
1424
+ this.stopGeneration++;
1425
+ for (const name of this.coolDownTimers.keys())
1426
+ this.clearCoolDown(name);
1427
+ const operation = Promise.resolve().then(() => this.stopAllOnce(force));
1428
+ this.stoppingApps = operation;
1429
+ const settled = () => { if (this.stoppingApps === operation)
1430
+ this.stoppingApps = null; };
1431
+ void operation.then(settled, settled);
1432
+ return operation;
1433
+ }
1434
+ async stopAllOnce(force) {
897
1435
  if (this.metricsTimer) {
898
1436
  clearInterval(this.metricsTimer);
899
1437
  this.metricsTimer = null;
@@ -904,34 +1442,65 @@ export class OrchestratorService extends EventEmitter {
904
1442
  this.janitor.stop();
905
1443
  }
906
1444
  let count = 0;
1445
+ const failures = [];
907
1446
  // When force=true (daemon shutdown), use short timeout per app (3s SIGTERM, then SIGKILL)
908
1447
  const perAppTimeout = force ? 3_000 : 10_000;
909
- for (const batch of resolveShutdownOrder(this.config.apps)) {
1448
+ // Registered projects need not belong to the daemon's root ecosystem.
1449
+ // Ownership is defined by handles, not by whichever config booted first.
1450
+ // Drain admitted starts before taking the shutdown graph snapshot.
1451
+ await Promise.allSettled([...this.startingApps.values()]);
1452
+ const entries = [...this.handles.values()].map((handle) => handle.entry);
1453
+ const names = new Set(entries.map((entry) => entry.name));
1454
+ const graph = entries.map((entry) => {
1455
+ const scope = entry.name.slice(0, entry.name.lastIndexOf('/') + 1);
1456
+ return {
1457
+ ...entry,
1458
+ dependsOn: (entry.dependsOn ?? []).flatMap((dependency) => {
1459
+ const name = !dependency.includes('/') && names.has(scope + dependency)
1460
+ ? scope + dependency : dependency;
1461
+ // A dependency never started here has no owned process to stop.
1462
+ return names.has(name) ? [name] : [];
1463
+ }),
1464
+ };
1465
+ });
1466
+ let batches;
1467
+ try {
1468
+ batches = resolveShutdownOrder(graph);
1469
+ }
1470
+ catch (error) {
1471
+ // Invalid reconfiguration must not turn shutdown into leaked children.
1472
+ this.logger.error({ error: error.message }, 'Invalid shutdown graph; stopping every owned app');
1473
+ batches = [entries];
1474
+ }
1475
+ for (const batch of batches) {
910
1476
  await Promise.all(batch.map(async (entry) => {
911
1477
  try {
912
1478
  await this.stopApp(entry.name, force, perAppTimeout);
913
1479
  count++;
914
1480
  }
915
1481
  catch (err) {
1482
+ failures.push(new Error(`Application '${entry.name}' stop failed: ${String(err)}`, { cause: err }));
916
1483
  this.logger.error({ app: entry.name, error: err.message }, 'Failed to stop');
917
1484
  }
918
1485
  }));
919
1486
  }
920
- try {
921
- await this.pm.shutdown({ force, timeout: force ? 5_000 : 30_000 });
922
- }
923
- catch {
924
- /* PM may have nothing left to clean up */
925
- }
1487
+ // Stop-all is a reversible application operation. The resident owner (or
1488
+ // Titan lifecycle) owns terminal ProcessManager shutdown, including workers
1489
+ // outside application handles. Keeping that boundary permits startAll later.
926
1490
  // Dispose esbuild watch contexts
927
1491
  if (this.buildService) {
928
1492
  try {
929
1493
  await this.buildService.dispose();
1494
+ this.buildService = null;
1495
+ }
1496
+ catch (error) {
1497
+ failures.push(error);
930
1498
  }
931
- catch { /* best-effort */ }
932
- this.buildService = null;
933
1499
  }
934
1500
  this.buildResults.clear();
1501
+ this.bootstrapSources.clear();
1502
+ if (failures.length)
1503
+ throw new AggregateError(failures, `Application shutdown incomplete: ${failures.map(String).join('; ')}`);
935
1504
  return count;
936
1505
  }
937
1506
  /**
@@ -940,11 +1509,23 @@ export class OrchestratorService extends EventEmitter {
940
1509
  * `restartApp` starts from this. `false` when nothing by that name runs
941
1510
  * here. See `AppHandle.redefine`.
942
1511
  */
943
- redefineApp(name, entry) {
1512
+ async redefineApp(name, entry) {
944
1513
  const handle = this.handles.get(this.resolveAppName(name) ?? name);
945
1514
  if (!handle)
946
1515
  return false;
1516
+ const [project, stack, app] = handle.name.split('/');
1517
+ if (project && stack && app)
1518
+ this.assertExecutionIdle({ project, stack });
1519
+ if (project && stack && app && this.stateStore.getStackIntent({ project, stack }).phase === 'starting') {
1520
+ throw new Error('An installed stack start is active; its application entry cannot be changed');
1521
+ }
947
1522
  handle.redefine(entry);
1523
+ if (!this.allowsWatch(entry)) {
1524
+ const state = this.restartCoalescer.get(handle.name);
1525
+ if (state)
1526
+ state.watchSerial = 0;
1527
+ }
1528
+ await this.syncBootstrapWatch(handle.name);
948
1529
  return true;
949
1530
  }
950
1531
  /**
@@ -980,7 +1561,7 @@ export class OrchestratorService extends EventEmitter {
980
1561
  * triggers, just continuations — they must not bump or the trailing
981
1562
  * coalesced restart would re-fire forever.
982
1563
  */
983
- async restartAppCoalesced(name, fromExternal) {
1564
+ async restartAppCoalesced(name, fromExternal, cause = 'manual') {
984
1565
  const canonical = this.resolveAppName(name) ?? name;
985
1566
  const handle = this.handles.get(canonical);
986
1567
  if (!handle) {
@@ -1036,10 +1617,21 @@ export class OrchestratorService extends EventEmitter {
1036
1617
  throw new Error(`Unknown app: ${name}`);
1037
1618
  }
1038
1619
  name = canonical;
1620
+ this.assertAppStartAllowed(name);
1039
1621
  const state = this.getCoalescerState(name);
1040
- if (fromExternal)
1622
+ if (fromExternal) {
1041
1623
  state.triggerSerial += 1;
1042
- const observedSerial = state.triggerSerial;
1624
+ if (cause === 'watch')
1625
+ state.watchSerial = state.triggerSerial;
1626
+ else
1627
+ state.manualSerial = state.triggerSerial;
1628
+ }
1629
+ if (!this.allowsWatch(handle.entry) || ['errored', 'crashed', 'stopped', 'stopping'].includes(handle.status)) {
1630
+ state.watchSerial = 0;
1631
+ }
1632
+ const observedSerial = Math.max(state.manualSerial, state.watchSerial);
1633
+ if (observedSerial <= state.firedSerial)
1634
+ return handle;
1043
1635
  // Cooldown: the app reported online recently. Wait it out, then
1044
1636
  // proceed as a non-external continuation (we already counted this
1045
1637
  // trigger when we first arrived).
@@ -1068,7 +1660,7 @@ export class OrchestratorService extends EventEmitter {
1068
1660
  }
1069
1661
  // Take the slot. Capture which serial this run is consuming —
1070
1662
  // anything bumped after this is the next run's problem.
1071
- const consumedSerial = state.triggerSerial;
1663
+ const consumedSerial = observedSerial;
1072
1664
  const promise = this.restartAppNow(name);
1073
1665
  state.inFlight = promise;
1074
1666
  try {
@@ -1084,7 +1676,7 @@ export class OrchestratorService extends EventEmitter {
1084
1676
  // trigger arrived between when we claimed the slot and now.
1085
1677
  // Two coalescer arms colliding can no longer cause this branch
1086
1678
  // to fire because they don't bump triggerSerial.
1087
- if (state.triggerSerial > consumedSerial) {
1679
+ if (Math.max(state.manualSerial, state.watchSerial) > consumedSerial) {
1088
1680
  this.restartAppCoalesced(name, /* fromExternal */ false).catch((err) => {
1089
1681
  this.logger.error({ app: name, error: err.message }, 'Trailing coalesced restart failed');
1090
1682
  });
@@ -1130,17 +1722,28 @@ export class OrchestratorService extends EventEmitter {
1130
1722
  const handle = this.handles.get(name);
1131
1723
  if (!handle)
1132
1724
  throw new Error(`Unknown app: ${name}`);
1725
+ this.assertAppStartAllowed(name);
1133
1726
  const entry = handle.entry;
1727
+ const definitionRevision = handle.definitionRevision;
1134
1728
  if (this.devMode && entry.bootstrap) {
1135
1729
  clearCacheFor(path.resolve(entry.cwd ?? this.cwd, entry.bootstrap));
1136
1730
  }
1137
- await this.stopApp(name);
1731
+ const stopped = this.stopApp(name);
1732
+ const intent = this.appStopIntents.get(name);
1733
+ const generation = this.stopGeneration;
1734
+ await stopped;
1735
+ if (this.stoppingApps || generation !== this.stopGeneration || intent !== this.appStopIntents.get(name)) {
1736
+ throw new Error('Application stop interrupted restart');
1737
+ }
1738
+ if (this.handles.get(name) !== handle || handle.definitionRevision !== definitionRevision || handle.entry !== entry) {
1739
+ throw new Error(`Application '${name}' definition changed while stopping; restart was cancelled. Inspect the current definition and start it explicitly.`);
1740
+ }
1138
1741
  return this.startApp(entry);
1139
1742
  }
1140
1743
  getCoalescerState(name) {
1141
1744
  let state = this.restartCoalescer.get(name);
1142
1745
  if (!state) {
1143
- state = { inFlight: null, triggerSerial: 0, firedSerial: 0, cooldownUntil: 0 };
1746
+ state = { inFlight: null, triggerSerial: 0, firedSerial: 0, manualSerial: 0, watchSerial: 0, cooldownUntil: 0 };
1144
1747
  this.restartCoalescer.set(name, state);
1145
1748
  }
1146
1749
  return state;
@@ -1179,7 +1782,7 @@ export class OrchestratorService extends EventEmitter {
1179
1782
  // is the one with that address. Falling through to the short-name match
1180
1783
  // answered a question about one deployment with another's data:
1181
1784
  //
1182
- // omnitron logs daos/deployed/main → daos/dev/main
1785
+ // omnitron logs sample/deployed/main → sample/dev/main
1183
1786
  //
1184
1787
  // — the node's app asked for, this laptop's app printed, with nothing
1185
1788
  // said. `startApp` already refuses this for the same reason ("a
@@ -1215,6 +1818,7 @@ export class OrchestratorService extends EventEmitter {
1215
1818
  if (!handle)
1216
1819
  throw new Error(`Unknown app: ${name}`);
1217
1820
  name = canonical;
1821
+ this.assertAppStartAllowed(name);
1218
1822
  // Classic mode or no supervisor — cannot do zero-downtime, fall back to restart
1219
1823
  if (handle.mode !== 'bootstrap' || !handle.supervisor) {
1220
1824
  return this.restartApp(name);
@@ -1223,33 +1827,39 @@ export class OrchestratorService extends EventEmitter {
1223
1827
  if (childNames.length === 0) {
1224
1828
  return this.restartApp(name);
1225
1829
  }
1226
- this.logger.info({ app: name, children: childNames.length }, 'Zero-downtime reload starting');
1227
- // For each child process, do a rolling restart via the supervisor.
1228
- // The supervisor's restartChild stops the old child and starts a new one.
1229
- // For pool children, the pool handles draining automatically.
1230
- // We restart one child at a time to maintain availability.
1231
- for (const childName of childNames) {
1232
- this.logger.info({ app: name, child: childName }, 'Reloading child process');
1233
- try {
1234
- await handle.supervisor.restartChild(childName);
1235
- // Wait for the new child to become healthy
1236
- const health = await this.waitForChildHealth(handle, childName, 30_000);
1237
- if (!health) {
1238
- this.logger.warn({ app: name, child: childName }, 'Child did not become healthy after reload — continuing with remaining children');
1830
+ return this.lifecycleQueue.enqueue(name, 'restart', async () => {
1831
+ this.assertAppStartAllowed(name);
1832
+ if (this.handles.get(name) !== handle)
1833
+ throw new Error('Application changed while queued; retry the operation');
1834
+ this.logger.info({ app: name, children: childNames.length }, 'Zero-downtime reload starting');
1835
+ handle.invalidateRelease();
1836
+ // For each child process, do a rolling restart via the supervisor.
1837
+ // The supervisor's restartChild stops the old child and starts a new one.
1838
+ // For pool children, the pool handles draining automatically.
1839
+ // We restart one child at a time to maintain availability.
1840
+ for (const childName of childNames) {
1841
+ this.logger.info({ app: name, child: childName }, 'Reloading child process');
1842
+ try {
1843
+ await handle.supervisor.restartChild(childName);
1844
+ // Wait for the new child to become healthy
1845
+ const health = await this.waitForChildHealth(handle, childName, 30_000);
1846
+ if (!health) {
1847
+ this.logger.warn({ app: name, child: childName }, 'Child did not become healthy after reload — continuing with remaining children');
1848
+ }
1849
+ this.logger.info({ app: name, child: childName }, 'Child reloaded successfully');
1850
+ }
1851
+ catch (err) {
1852
+ // `error: err`, not `error: err.message`: the logger aliases `error`
1853
+ // onto pino's error serializer, so the object arrives with its stack
1854
+ // and a string arrives as a string with nothing behind it.
1855
+ this.logger.error({ app: name, child: childName, error: err }, 'Failed to reload child — aborting zero-downtime reload');
1856
+ throw new Error(`Zero-downtime reload failed for '${name}' at child '${childName}': ${err.message}`, { cause: err });
1239
1857
  }
1240
- this.logger.info({ app: name, child: childName }, 'Child reloaded successfully');
1241
- }
1242
- catch (err) {
1243
- // `error: err`, not `error: err.message`: the logger aliases `error`
1244
- // onto pino's error serializer, so the object arrives with its stack
1245
- // and a string arrives as a string with nothing behind it.
1246
- this.logger.error({ app: name, child: childName, error: err }, 'Failed to reload child — aborting zero-downtime reload');
1247
- throw new Error(`Zero-downtime reload failed for '${name}' at child '${childName}': ${err.message}`, { cause: err });
1248
1858
  }
1249
- }
1250
- this.logger.info({ app: name }, 'Zero-downtime reload complete');
1251
- this.persistState();
1252
- return handle;
1859
+ this.logger.info({ app: name }, 'Zero-downtime reload complete');
1860
+ this.persistState();
1861
+ return handle;
1862
+ });
1253
1863
  }
1254
1864
  /**
1255
1865
  * Wait for a child process to report healthy status within a timeout.
@@ -1276,29 +1886,58 @@ export class OrchestratorService extends EventEmitter {
1276
1886
  // ============================================================================
1277
1887
  // Scaling — delegates to PM supervisor
1278
1888
  // ============================================================================
1279
- async scaleApp(name, instances) {
1280
- const canonical = this.resolveAppName(name) ?? name;
1889
+ async scaleApp(name, instances, process) {
1890
+ const request = parsePoolScaleRequest({ name, instances, process });
1891
+ const canonical = this.resolveAppName(request.name) ?? request.name;
1892
+ assertPoolScaleTarget(this.getApp(canonical), request);
1281
1893
  const handle = this.handles.get(canonical);
1282
- if (!handle)
1283
- throw new Error(`Unknown app: ${name}`);
1284
- name = canonical;
1285
- if (!this.config)
1286
- throw new Error('Ecosystem config not loaded');
1287
- if (handle.mode !== 'bootstrap') {
1288
- this.logger.warn({ app: name }, 'Classic mode apps do not support scaling');
1289
- return handle;
1290
- }
1291
- if (instances < 1)
1292
- throw new Error('Instance count must be at least 1');
1293
- if (instances === handle.instanceCount)
1894
+ const generation = handle.generation;
1895
+ this.assertAppStartAllowed(canonical);
1896
+ return this.lifecycleQueue.enqueue(canonical, 'restart', async () => {
1897
+ this.assertAppStartAllowed(canonical);
1898
+ if (this.handles.get(canonical) !== handle || handle.generation !== generation)
1899
+ throw new Error('Application changed while queued; retry the operation');
1900
+ assertPoolScaleTarget(this.getApp(canonical), request);
1901
+ if (handle.status !== 'online')
1902
+ throw Errors.conflict('Process pools can only be resized while the application is online');
1903
+ const declaration = handle.topologyProcesses.find(item => item.name === request.process);
1904
+ const pool = handle.topologyPools.get(request.process);
1905
+ if (!pool)
1906
+ throw Errors.conflict('Declared process pool is not running');
1907
+ const declared = declaration.instances;
1908
+ const automatic = declaration.scaling?.strategy === 'auto';
1909
+ const minimum = automatic ? declared : 1;
1910
+ const maximum = declaration.scaling?.maxInstances ?? (automatic ? declared * 4 : declared);
1911
+ if (!Number.isSafeInteger(declared) || declared < 2 || !Number.isSafeInteger(maximum) || maximum < declared)
1912
+ throw new Error('Process pool has invalid declared scaling limits');
1913
+ if (request.instances < minimum || request.instances > maximum)
1914
+ throw Errors.badRequest(`Process pool resize must stay within declared limits ${minimum}..${maximum}`);
1915
+ if (pool.size === request.instances)
1916
+ return handle;
1917
+ this.logger.info({ app: canonical, process: request.process, from: pool.size, to: request.instances,
1918
+ automatic, lifetime: 'until-restart' }, 'Resizing a declared process pool');
1919
+ handle.invalidateRelease();
1920
+ // PM owns membership serialization and waits for every admitted spawn/exit.
1921
+ // The source declaration and installed entry remain unchanged. Automatic
1922
+ // pools retain their policy and can subsequently resize within its limits.
1923
+ await pool.scale(request.instances);
1924
+ if (pool.size !== request.instances)
1925
+ throw new Error('Process pool resize is unconfirmed; inspect its observed membership');
1926
+ this.persistState(); // Observations only, never a durable desired-size override.
1294
1927
  return handle;
1295
- if (!handle.supervisor)
1296
- throw new Error(`No supervisor for app: ${name}`);
1297
- this.logger.info({ app: name, from: handle.instanceCount, to: instances }, 'Scaling app');
1298
- await handle.supervisor.scaleChild(name, instances);
1299
- handle.instanceCount = instances;
1300
- this.persistState();
1301
- return handle;
1928
+ });
1929
+ }
1930
+ async restartAppChild(name, child) {
1931
+ const canonical = this.resolveAppName(name) ?? name;
1932
+ this.assertAppStartAllowed(canonical);
1933
+ await this.lifecycleQueue.enqueue(canonical, 'restart', async () => {
1934
+ this.assertAppStartAllowed(canonical);
1935
+ const supervisor = this.handles.get(canonical)?.supervisor;
1936
+ if (!supervisor)
1937
+ throw new Error(`No supervisor for '${canonical}'`);
1938
+ this.handles.get(canonical)?.invalidateRelease();
1939
+ await supervisor.restartChild(child);
1940
+ });
1302
1941
  }
1303
1942
  // ============================================================================
1304
1943
  // Information
@@ -1379,7 +2018,7 @@ export class OrchestratorService extends EventEmitter {
1379
2018
  }
1380
2019
  /**
1381
2020
  * `name` is resolved like every other per-app question (`main` finds
1382
- * `daos/dev/main`); it was compared verbatim, so `omnitron metrics main`
2021
+ * `sample/dev/main`); it was compared verbatim, so `omnitron metrics main`
1383
2022
  * printed «(no data)». An unknown name answers `{}`, and the caller says so.
1384
2023
  */
1385
2024
  async getMetrics(name) {
@@ -1404,12 +2043,19 @@ export class OrchestratorService extends EventEmitter {
1404
2043
  }
1405
2044
  return result;
1406
2045
  }
2046
+ configureReadiness(declarations) {
2047
+ this.readinessMonitor.configure(declarations);
2048
+ }
2049
+ hasDeclaredReadiness(name) {
2050
+ const handle = this.getHandle(name);
2051
+ return Boolean(handle && this.readinessMonitor.isConfigured(handle.entry));
2052
+ }
1407
2053
  /**
1408
2054
  * Each app's health, asked of every process it runs — its supervisor
1409
2055
  * children and its worker pools — and combined (`app-health.ts`).
1410
2056
  *
1411
2057
  * `name` is resolved like every other per-app question: `main` finds
1412
- * `daos/dev/main`. It was compared verbatim, so `omnitron health main`
2058
+ * `sample/dev/main`. It was compared verbatim, so `omnitron health main`
1413
2059
  * matched nothing and the answer was empty. An unknown name answers `{}`,
1414
2060
  * and the caller says so.
1415
2061
  */
@@ -1418,12 +2064,11 @@ export class OrchestratorService extends EventEmitter {
1418
2064
  if (name !== undefined && wanted === undefined)
1419
2065
  return {};
1420
2066
  const result = {};
1421
- for (const [appName, handle] of this.handles) {
1422
- if (wanted && appName !== wanted)
1423
- continue;
2067
+ const entries = [...this.handles].filter(([appName]) => !wanted || appName === wanted);
2068
+ const measure = async ([appName, handle]) => {
1424
2069
  if (handle.status !== 'online') {
1425
2070
  result[appName] = notRunningHealth(handle.status);
1426
- continue;
2071
+ return;
1427
2072
  }
1428
2073
  if (handle.mode === 'bootstrap' && handle.supervisor) {
1429
2074
  const supervisor = handle.supervisor;
@@ -1431,14 +2076,40 @@ export class OrchestratorService extends EventEmitter {
1431
2076
  for (const [pool, instance] of handle.topologyPools) {
1432
2077
  answers.push([pool, poolHealth(instance.metrics)]);
1433
2078
  }
1434
- const health = answers.length > 0 ? combineProcessHealth(answers) : handle.lastHealth;
2079
+ if (handle.entry && this.readinessMonitor.isConfigured(handle.entry))
2080
+ answers.push(['readiness', await this.readinessMonitor.check(handle, handle.entry, handle.healthRunId)]);
2081
+ const health = handle.status !== 'online' ? notRunningHealth(handle.status)
2082
+ : answers.length > 0 ? combineProcessHealth(answers) : handle.lastHealth;
1435
2083
  handle.lastHealth = health;
1436
2084
  result[appName] = health;
1437
2085
  }
1438
2086
  else {
1439
- result[appName] = handle.lastHealth;
2087
+ const runId = handle.healthRunId;
2088
+ const declaration = handle.entry;
2089
+ const measured = await this.readinessMonitor.check(handle, declaration, runId);
2090
+ if (runId !== handle.healthRunId || declaration !== handle.entry) {
2091
+ result[appName] = { timestamp: Date.now(), status: 'degraded', checks: [{ name: 'readiness', status: 'warn', message: 'measurement_superseded: application restarted or its declaration changed during this probe; request a fresh measurement.' }] };
2092
+ return;
2093
+ }
2094
+ const health = handle.status === 'online' ? measured : notRunningHealth(handle.status);
2095
+ handle.lastHealth = health;
2096
+ result[appName] = health;
2097
+ const signature = JSON.stringify([health.status, health.checks.map(c => [c.name, c.status, c.status === 'pass' ? '' : c.message])]);
2098
+ if (this.readinessSignatures.get(handle) !== signature) {
2099
+ this.readinessSignatures.set(handle, signature);
2100
+ const details = { event: 'application.readiness.changed', app: appName, status: health.status, checks: health.checks };
2101
+ if (health.status === 'healthy')
2102
+ this.logger.info(details, 'Application readiness verified');
2103
+ else if (health.status === 'degraded')
2104
+ this.logger.warn(details, 'Application readiness needs attention');
2105
+ else
2106
+ this.logger.error(details, 'Application readiness failed');
2107
+ }
1440
2108
  }
1441
- }
2109
+ };
2110
+ // Keep a fleet of failed endpoints from serializing the entire health response.
2111
+ for (let offset = 0; offset < entries.length; offset += 4)
2112
+ await Promise.all(entries.slice(offset, offset + 4).map(measure));
1442
2113
  return result;
1443
2114
  }
1444
2115
  /**
@@ -1527,8 +2198,11 @@ export class OrchestratorService extends EventEmitter {
1527
2198
  // ============================================================================
1528
2199
  // Private — Launch
1529
2200
  // ============================================================================
1530
- async launchClassicMode(entry, handle, config) {
1531
- const child = await launchClassic(entry, handle, this.cwd, this.logger, this.appLogHandlers);
2201
+ async launchClassicMode(entry, handle, config, installed) {
2202
+ handle.release = await verifyLaunchRelease(entry, handle.generation, [installedExecutable(entry, this.cwd)]);
2203
+ const launch = entry.releaseRoot || installed || handle.release.state === 'confirmed'
2204
+ ? requireInstalledBinding(handle.release, installedEntryRevision(entry, config, this.cwd), installed) : undefined;
2205
+ const child = await launchClassic(entry, handle, this.cwd, this.logger, this.appLogHandlers, Boolean(installed));
1532
2206
  child.on('exit', (code, signal) => {
1533
2207
  if (handle.status === 'stopping') {
1534
2208
  handle.markStopped();
@@ -1540,6 +2214,7 @@ export class OrchestratorService extends EventEmitter {
1540
2214
  }
1541
2215
  this.persistState();
1542
2216
  });
2217
+ return launch;
1543
2218
  }
1544
2219
  /**
1545
2220
  * Launch bootstrap app via PM ProcessSupervisor.
@@ -1548,7 +2223,7 @@ export class OrchestratorService extends EventEmitter {
1548
2223
  * all topology children (server + worker pools) and wires IPC relay between them.
1549
2224
  * Otherwise, creates a single bootstrap-process as before.
1550
2225
  */
1551
- async launchBootstrapMode(entry, handle, config) {
2226
+ async launchBootstrapMode(entry, handle, config, installed) {
1552
2227
  handle.markStarting();
1553
2228
  const bootstrapAbsPath = path.resolve(entry.cwd ?? this.cwd, entry.bootstrap);
1554
2229
  // Load bootstrap definition to check for process topology and requirements.
@@ -1562,14 +2237,16 @@ export class OrchestratorService extends EventEmitter {
1562
2237
  let topology;
1563
2238
  let definition;
1564
2239
  try {
1565
- definition = await loadBootstrapConfig(bootstrapAbsPath, { devMode: this.devMode, freshModuleGraph: true });
2240
+ const captured = await readBootstrapMetadata(bootstrapAbsPath, this.devMode && !entry.releaseRoot, 60_000);
2241
+ definition = captured.definition;
2242
+ handle.bootstrapMetadata = captured.metadata;
1566
2243
  topology = definition.processes;
1567
2244
  }
1568
2245
  catch (err) {
1569
2246
  // Refused, with the reason. This fell back to «single-process mode» at
1570
2247
  // warn — but every definition declares its topology (IAppDefinition:
1571
2248
  // `processes` is required), so the fallback started the app in a shape
1572
- // it was never written for. Measured 2026-09-23 on the master: paysys
2249
+ // it was never written for. Measured 2026-09-23 on the master: payments
1573
2250
  // and messaging, whose definitions failed to load («Parameter
1574
2251
  // decorators only work when experimental decorators are enabled»), were
1575
2252
  // started that way and died on «Dependency 'AuthModule:JWTService' not
@@ -1604,7 +2281,7 @@ export class OrchestratorService extends EventEmitter {
1604
2281
  }
1605
2282
  // Resolve infrastructure config and inject as env vars.
1606
2283
  // Skip if already injected by project.service.ts (stack flow sets OMNITRON_STACK).
1607
- const alreadyResolved = !!(entry.env?.['OMNITRON_STACK'] && entry.env?.['DATABASE_URL']);
2284
+ const alreadyResolved = !!entry.env?.['OMNITRON_STACK'];
1608
2285
  if (!alreadyResolved && (definition?.requires || definition?.omnitronConfig)) {
1609
2286
  try {
1610
2287
  const { resolveStack, resolvedConfigToEnv } = await import('../project/config-resolver.js');
@@ -1620,7 +2297,7 @@ export class OrchestratorService extends EventEmitter {
1620
2297
  if (appConfig) {
1621
2298
  const envVars = resolvedConfigToEnv(appConfig, entry.name, stackName);
1622
2299
  if (Object.keys(envVars).length > 0) {
1623
- entry.env = { ...entry.env, ...envVars };
2300
+ entry.env = { ...envVars, ...entry.env };
1624
2301
  this.logger.debug({ app: entry.name, envCount: Object.keys(envVars).length }, 'Injected resolved infrastructure config as env vars');
1625
2302
  }
1626
2303
  }
@@ -1631,105 +2308,68 @@ export class OrchestratorService extends EventEmitter {
1631
2308
  }
1632
2309
  // Build all entry points via esbuild (dev mode bundles from source .ts)
1633
2310
  //
1634
- // On a *restart* (as opposed to a first start), buildResults already
1635
- // has a fresh entry — esbuild's watcher just produced the bundle
1636
- // that triggered us. Reusing it skips a redundant cold rebuild
1637
- // (which was costing ~500ms per restart and racing against the
1638
- // watcher's own incremental output). The watch context is also
1639
- // preserved (we never unwatched), so we don't re-arm it either.
1640
- if (definition && this.devMode) {
1641
- try {
1642
- if (!this.buildService) {
1643
- this.buildService = new BuildService(/* isDev */ true, {
1644
- onEsbuildReset: (info) => this.metricsBridge?.recordResilientHandleReset(info),
1645
- onBuildResult: ({ app, kind, durationMs, ok }) => this.metricsBridge?.recordEsbuildBuild(app, kind, durationMs, ok),
1646
- });
1647
- }
1648
- const existing = this.buildResults.get(entry.name);
1649
- const existingWatch = this.buildService.isWatching?.(entry.name);
1650
- // Bundle on-disk presence check. A restart can race against
1651
- // the user (or a script) removing `.omnitron-build/` between
1652
- // builds — without this stat the orchestrator hands the
1653
- // worker a path that no longer exists and the child dies
1654
- // with `ERR_MODULE_NOT_FOUND` before the supervisor can
1655
- // recover. Cheap stat, big DX win.
1656
- const bundlePresent = existing
1657
- ? fs.existsSync(existing.bootstrapPath)
1658
- : false;
1659
- if (existing && existingWatch && bundlePresent) {
1660
- // Restart path — keep the already-built bundle and live watch.
1661
- this.logger.debug({ app: entry.name, modules: existing.modulePaths.size }, 'Reusing existing esbuild bundle + watch (restart path)');
1662
- }
1663
- else {
1664
- if (existing && existingWatch && !bundlePresent) {
1665
- // Bundle was deleted out from under us. Clear the watch
1666
- // and the cached BuildResult so the next call rebuilds
1667
- // from cold and re-arms the watcher cleanly.
1668
- this.logger.warn({ app: entry.name, bootstrapPath: existing.bootstrapPath }, 'Cached bundle missing on disk — forcing rebuild');
1669
- try {
1670
- await this.buildService.unwatchApp?.(entry.name);
1671
- }
1672
- catch (err) {
1673
- this.logger.debug({ err, app: entry.name }, 'unwatchApp failed (non-fatal)');
1674
- }
1675
- this.buildResults.delete(entry.name);
1676
- }
1677
- // First-start path — build everything from cold and arm the watcher.
1678
- const buildResult = await this.buildService.buildApp(entry.name, bootstrapAbsPath, definition);
1679
- this.buildResults.set(entry.name, buildResult);
1680
- this.logger.info({ app: entry.name, modules: buildResult.modulePaths.size }, 'Built entry points via esbuild');
1681
- // Start esbuild watch for incremental rebuilds on source changes.
1682
- // On rebuild → fire a restart trigger; the coalescer takes it
1683
- // from there.
1684
- await this.buildService.watchApp(entry.name, bootstrapAbsPath, definition, () => {
1685
- // Gate: skip if the app is in a non-running state — repeated
1686
- // restarts of an escalated/errored process just churn forever
1687
- // without forward progress (Fix #248).
1688
- // Skip restart when the app is in a terminal non-running
1689
- // state. Includes 'crashed' (supervisor escalated after
1690
- // exceeding its restart budget) and 'errored' (start
1691
- // failed). 'stopped' means operator explicitly stopped it.
1692
- // In all three cases, restarting just churns a known-broken
1693
- // process; the operator must fix the underlying issue and
1694
- // call `omnitron start <app>` to clear the state.
1695
- const status = this.getAppStatus(entry.name);
1696
- if (status === 'errored' || status === 'crashed' || status === 'stopped') {
1697
- this.logger.warn({ app: entry.name, status }, 'esbuild rebuild detected but app is not running — skipping restart');
1698
- return;
1699
- }
1700
- this.logger.info({ app: entry.name }, 'esbuild rebuild detected — restarting');
1701
- this.metricsBridge?.recordEsbuildBuild(entry.name, 'rebuild', 0, true);
1702
- this.restartApp(entry.name).catch((err) => {
1703
- this.logger.error({ app: entry.name, error: err.message }, 'Restart after esbuild rebuild failed');
1704
- });
1705
- });
1706
- }
1707
- }
1708
- catch (err) {
1709
- // The "fall back to tsx" wording was misleading — the orchestrator
1710
- // does not inject a tsx loader into spawned children, so without
1711
- // a build the bootstrap-process will try to `import` the source
1712
- // .ts file (referenced as `./app.module.js` in the topology) and
1713
- // fail with a cryptic "Cannot find module" downstream. Surface
1714
- // the build error directly so the operator sees the actual
1715
- // problem on `omnitron start/restart`.
1716
- // esbuild's error carries an `errors[]` with file, line and column.
1717
- // `.message` is the summary; the locations are what an operator needs
1718
- // to fix the build, and they exist only on the original.
1719
- this.logger.error({ app: entry.name, error: err }, 'esbuild build failed — app cannot start without bundled output');
1720
- throw new Error(`Cannot launch '${entry.name}' in dev mode: esbuild build failed (${err.message}). ` +
1721
- `Fix the build error and retry, or run with bundled output present in apps/${entry.name}/.omnitron-build/.`, { cause: err });
1722
- }
2311
+ if (installed && this.buildResults.has(entry.name)) {
2312
+ throw new Error('Installed stack start cannot use a development build');
1723
2313
  }
2314
+ if (definition && !installed)
2315
+ await this.prepareBootstrapBuild(entry, bootstrapAbsPath, definition);
1724
2316
  const buildResult = this.buildResults.get(entry.name);
1725
2317
  // Use bundled bootstrap path for topology import when available
1726
2318
  const effectiveBootstrapPath = buildResult?.bootstrapPath ?? bootstrapAbsPath;
2319
+ handle.release = buildResult
2320
+ ? { state: 'unreported', reason: 'This launch uses a generated build; an installed release receipt cannot identify that executable.' }
2321
+ : await verifyLaunchRelease(entry, handle.generation, [bootstrapAbsPath, ...(topology ?? []).map(process => path.resolve(path.dirname(bootstrapAbsPath), process.module))]);
2322
+ const launch = entry.releaseRoot || installed || handle.release.state === 'confirmed'
2323
+ ? requireInstalledBinding(handle.release, installedEntryRevision(entry, config, this.cwd), installed) : undefined;
1727
2324
  if (topology && topology.length > 0) {
1728
2325
  await this.launchTopology(entry, handle, config, effectiveBootstrapPath, topology, buildResult);
1729
2326
  }
1730
2327
  else {
1731
2328
  await this.launchSingleProcess(entry, handle, config, effectiveBootstrapPath, buildResult);
1732
2329
  }
2330
+ return launch;
2331
+ }
2332
+ async discardSourceBuild(name) {
2333
+ const state = this.restartCoalescer.get(name);
2334
+ if (state)
2335
+ state.watchSerial = 0;
2336
+ await this.buildService?.unwatchApp(name);
2337
+ this.buildResults.delete(name);
2338
+ this.bootstrapSources.delete(name);
2339
+ }
2340
+ async prepareBootstrapBuild(entry, bootstrapAbsPath, definition) {
2341
+ const sourceTopology = /\.(?:[cm]?ts|tsx)$/.test(bootstrapAbsPath) ||
2342
+ definition.processes.some((process) => /\.(?:[cm]?ts|tsx)$/.test(process.module));
2343
+ if (entry.releaseRoot || (!this.devMode && !sourceTopology)) {
2344
+ // A prior source launch under this name must not redirect a prebuilt
2345
+ // release to a stale generated executable or leave its watcher active.
2346
+ await this.discardSourceBuild(entry.name);
2347
+ return;
2348
+ }
2349
+ try {
2350
+ this.buildService ??= new BuildService(this.devMode, {
2351
+ onEsbuildReset: (info) => this.metricsBridge?.recordResilientHandleReset(info),
2352
+ onBuildResult: ({ app, kind, durationMs, ok }) => this.metricsBridge?.recordEsbuildBuild(app, kind, durationMs, ok),
2353
+ });
2354
+ const existing = this.buildResults.get(entry.name);
2355
+ const current = this.handles.get(entry.name)?.entry ?? entry;
2356
+ const reusable = existing && this.allowsWatch(current) && this.buildService.isWatching(entry.name) &&
2357
+ this.buildService.canReuseBuild(existing, bootstrapAbsPath, definition, this.devMode);
2358
+ if (!reusable) {
2359
+ // A manual restart with watch:false deliberately compiles the current
2360
+ // sources. It must not reuse an artifact that stopped being maintained.
2361
+ await this.buildService.unwatchApp(entry.name);
2362
+ this.buildResults.delete(entry.name);
2363
+ this.buildResults.set(entry.name, await this.buildService.buildApp(entry.name, bootstrapAbsPath, definition, this.devMode));
2364
+ this.logger.info({ app: entry.name }, 'Built entry points via esbuild');
2365
+ }
2366
+ this.bootstrapSources.set(entry.name, { path: bootstrapAbsPath, definition });
2367
+ await this.syncBootstrapWatch(entry.name);
2368
+ }
2369
+ catch (error) {
2370
+ this.logger.error({ app: entry.name, error }, 'esbuild build failed — app cannot start without bundled output');
2371
+ throw new Error(`Cannot launch '${entry.name}': esbuild build failed (${error.message}). Fix the build error and retry.`, { cause: error });
2372
+ }
1733
2373
  }
1734
2374
  /**
1735
2375
  * Launch app with process topology — multiple children managed by Omnitron.
@@ -1738,30 +2378,34 @@ export class OrchestratorService extends EventEmitter {
1738
2378
  * The BootstrapProcess finds its own entry, imports the module, and wires transports.
1739
2379
  *
1740
2380
  * Processes with `instances > 1` are launched as PM pools with load balancing.
1741
- * Processes with `topology.access` get Netron-native proxies via daemon socket.
1742
- * Processes with `topology.expose` auto-expose their @Service on daemon Netron.
2381
+ * Processes with `topology.access` get native Netron proxies within this application.
2382
+ * Processes with `topology.expose` publish their @Service on its private listener.
1743
2383
  *
1744
2384
  * Service metadata is auto-discovered from pool workers — no manual `exports`
1745
2385
  * config needed. The @Service decorator on the worker IS the source of truth.
1746
2386
  */
1747
2387
  async launchTopology(entry, handle, config, bootstrapAbsPath, topology, buildResult) {
2388
+ // One fresh, aligned adapter for every pool and single process in this
2389
+ // application generation. Resolve before allocating topology resources.
2390
+ const runtime = await this.bootstrapRuntime(bootstrapAbsPath);
1748
2391
  const policy = buildRestartPolicy(entry, config);
1749
- // Wait for daemon Netron to be wired up. Cheap no-op if already ready;
1750
- // otherwise blocks (with timeout) instead of immediately failing — the
1751
- // race between daemon startup and stack auto-resume is benign and just
1752
- // needs a single rendezvous.
1753
- await this.ensureDaemonNetronReady();
1754
- const serviceRouter = new ServiceRouter(this.daemonNetron, this.logger);
1755
- const daemonSocketUrl = `unix://${this.daemonSocketPath}`;
2392
+ const spawnEnv = withClosureLibraryPath(entry.env, [entry.releaseRoot, entry.cwd, bootstrapAbsPath]);
2393
+ const needsRouting = topology.some(proc => proc.topology?.expose === true || proc.topology?.access?.length);
2394
+ handle.deferStartup();
2395
+ if (needsRouting) {
2396
+ await this.ensureTopologyReady();
2397
+ handle.topology = await ApplicationTopology.allocate(this.topologyDirectory, entry.name, this.logger);
2398
+ await handle.topology.start();
2399
+ }
2400
+ const serviceRouter = handle.topology?.router;
2401
+ const topologySocketUrl = handle.topology?.url;
1756
2402
  // Topology startup order: providers (topology.expose) before consumers (topology.access).
1757
- // Providers register their @Service on daemon Netron via ServiceRouter.
1758
- // Consumers connect to daemon and queryInterface() for those services.
1759
- // Currently only pool processes support topology.expose (ServiceRouter wraps pool.execute).
2403
+ // Each application's private namespace contains both pool and single providers.
1760
2404
  const poolEntries = topology.filter((p) => (p.instances ?? 1) > 1);
1761
2405
  const singleEntries = topology.filter((p) => (p.instances ?? 1) <= 1);
1762
2406
  // Step 1: Create PM pools — must complete before Step 2 so services are available
1763
2407
  // Pools with topology.expose auto-discover @Service metadata from the first
1764
- // worker via getExposedServices() and register on daemon Netron via ServiceRouter.
2408
+ // worker via getExposedServices() and publish within this application's namespace.
1765
2409
  const poolNames = [];
1766
2410
  for (const procEntry of poolEntries) {
1767
2411
  const instances = procEntry.instances;
@@ -1785,14 +2429,15 @@ export class OrchestratorService extends EventEmitter {
1785
2429
  allMethodsPublic: true,
1786
2430
  ...(handle.appLogLevel && { logLevel: handle.appLogLevel }),
1787
2431
  startupTimeout: procEntry.startupTimeout ?? entry.startupTimeout ?? DEFAULT_CHILD_STARTUP_TIMEOUT,
1788
- ...(entry.env && { env: entry.env }),
1789
- ...(entry.cwd && { cwd: entry.cwd }),
2432
+ ...(spawnEnv && { env: spawnEnv }),
2433
+ cwd: entry.cwd ?? this.cwd,
1790
2434
  dependencies: {
1791
2435
  bootstrapPath: bootstrapAbsPath,
1792
2436
  processName: procEntry.name,
1793
2437
  ...(bundledModulePath && { bundledModulePath }),
1794
2438
  ...(topologyAccess.length > 0 && {
1795
- __daemonSocketUrl: daemonSocketUrl,
2439
+ // Retain the bootstrap wire key for previously sealed SDKs.
2440
+ __daemonSocketUrl: topologySocketUrl,
1796
2441
  __topologyConnects: topologyAccess,
1797
2442
  }),
1798
2443
  },
@@ -1835,7 +2480,7 @@ export class OrchestratorService extends EventEmitter {
1835
2480
  };
1836
2481
  this.logger.info({ app: entry.name, process: procEntry.name, instances }, 'Creating topology process pool');
1837
2482
  // pm.pool() returns a Proxy wrapping ProcessPool — execute() dispatches to pool workers
1838
- const pool = await this.pm.pool(BOOTSTRAP_PROCESS_PATH, poolOptions);
2483
+ const pool = await this.pm.pool(runtime, poolOptions);
1839
2484
  poolNames.push(procEntry.name);
1840
2485
  // Track the pool on the AppHandle so `getInfo()` can report the
1841
2486
  // actual worker count for pool-managed topology entries. Without
@@ -1843,56 +2488,15 @@ export class OrchestratorService extends EventEmitter {
1843
2488
  // which returns null for pool workers (they aren't supervisor
1844
2489
  // children) and the entry is mis-reported as `status: 'stopped'`.
1845
2490
  handle.topologyPools.set(procEntry.name, pool);
2491
+ this.observePoolReleaseMembership(handle, pool);
1846
2492
  this.attachPoolLogCapture(entry.name, procEntry.name, handle, pool);
1847
2493
  // Auto-discover @Service metadata from pool workers and expose via ServiceRouter.
1848
2494
  // No manual `exports` needed — @Service decorator IS the source of truth.
1849
2495
  // Requires explicit `topology: { expose: true }` — opt-in for security.
1850
2496
  if (procEntry.topology?.expose === true) {
1851
- try {
1852
- // A pool worker reports ready before its Application has started, and
1853
- // `@Service` classes are exposed to Netron during start — so asking
1854
- // once, or once more 500ms later, asks a worker that is still booting.
1855
- // What it answers then is an empty list, or a service whose method
1856
- // list has not been filled in yet, and both used to end the same way:
1857
- // nothing registered on the daemon, the consumer process starting
1858
- // seconds later, querying, and being told the service does not exist.
1859
- // The consumer resolves its topology proxy exactly once, so that
1860
- // answer disabled the feature for the life of the process — in the
1861
- // case that surfaced this, every OHLCV candle aggregation.
1862
- //
1863
- // Poll instead, and treat "a service with no methods" as not ready
1864
- // rather than as a service, because an empty method list produces a
1865
- // proxy that can do nothing.
1866
- const usable = (list) => Array.isArray(list) && list.length > 0 && list.some((svc) => svc.methods?.length > 0);
1867
- let services = await pool.execute('getExposedServices');
1868
- const deadline = Date.now() + TOPOLOGY_EXPOSE_TIMEOUT_MS;
1869
- while (!usable(services) && Date.now() < deadline) {
1870
- await new Promise((r) => setTimeout(r, TOPOLOGY_EXPOSE_POLL_MS));
1871
- services = await pool.execute('getExposedServices');
1872
- }
1873
- if (!usable(services)) {
1874
- this.logger.warn({
1875
- app: entry.name,
1876
- process: procEntry.name,
1877
- waitedMs: TOPOLOGY_EXPOSE_TIMEOUT_MS,
1878
- reported: services?.map((svc) => `${svc.name}(${svc.methods?.length ?? 0})`) ?? [],
1879
- }, 'No usable @Service found on pool worker — topology.expose has no effect, and any ' +
1880
- 'process declaring topology.access on it will start without a proxy');
1881
- }
1882
- for (const svc of services ?? []) {
1883
- if (svc.methods.length === 0) {
1884
- // Silently skipped before. A consumer then failed to find a
1885
- // service its own declaration named, with nothing anywhere
1886
- // connecting the two facts.
1887
- this.logger.warn({ app: entry.name, process: procEntry.name, service: svc.name }, 'Pool service exposes no methods — not registered on the daemon');
1888
- continue;
1889
- }
1890
- await serviceRouter.exposePoolService(procEntry.name, svc.name, svc.version ?? '1.0.0', pool, svc.methods);
1891
- this.logger.info({ app: entry.name, process: procEntry.name, service: svc.name, methods: svc.methods.length }, 'Auto-discovered and exposed pool service on daemon Netron');
1892
- }
1893
- }
1894
- catch (err) {
1895
- this.logger.error({ app: entry.name, process: procEntry.name, error: err.message }, 'Failed to auto-discover/expose pool services');
2497
+ const services = await this.discoverTopologyServices(entry.name, procEntry.name, () => pool.execute('getExposedServices'));
2498
+ for (const svc of services) {
2499
+ await serviceRouter.exposePoolService(procEntry.name, svc.name, svc.version ?? '1.0.0', pool, svc.methods);
1896
2500
  }
1897
2501
  }
1898
2502
  }
@@ -1909,14 +2513,14 @@ export class OrchestratorService extends EventEmitter {
1909
2513
  // path beside it has always stated one. See CHILD_REQUEST_TIMEOUT.
1910
2514
  requestTimeout: CHILD_REQUEST_TIMEOUT,
1911
2515
  startupTimeout: procEntry.startupTimeout ?? entry.startupTimeout ?? DEFAULT_CHILD_STARTUP_TIMEOUT,
1912
- ...(entry.env && { env: entry.env }),
1913
- ...(entry.cwd && { cwd: entry.cwd }),
2516
+ ...(spawnEnv && { env: spawnEnv }),
2517
+ cwd: entry.cwd ?? this.cwd,
1914
2518
  dependencies: {
1915
2519
  bootstrapPath: bootstrapAbsPath,
1916
2520
  processName: procEntry.name,
1917
2521
  ...(bundledModulePath && { bundledModulePath }),
1918
2522
  ...(topologyAccess.length > 0 && {
1919
- __daemonSocketUrl: daemonSocketUrl,
2523
+ __daemonSocketUrl: topologySocketUrl,
1920
2524
  __topologyConnects: topologyAccess,
1921
2525
  }),
1922
2526
  },
@@ -1930,7 +2534,7 @@ export class OrchestratorService extends EventEmitter {
1930
2534
  };
1931
2535
  children.push({
1932
2536
  name: `${entry.name}/${procEntry.name}`,
1933
- process: BOOTSTRAP_PROCESS_PATH,
2537
+ process: runtime,
1934
2538
  spawnOptions: spawnOpts,
1935
2539
  critical: procEntry.critical ?? entry.critical ?? false,
1936
2540
  });
@@ -1938,7 +2542,7 @@ export class OrchestratorService extends EventEmitter {
1938
2542
  // Step 3: Create supervisor for single-instance children
1939
2543
  const supervisorConfig = {
1940
2544
  strategy: mapStrategy(config.supervision.strategy),
1941
- maxRestarts: policy.maxRestarts ?? config.supervision.maxRestarts,
2545
+ maxRestarts: policy.enabled === false ? 0 : policy.maxRestarts ?? config.supervision.maxRestarts,
1942
2546
  window: policy.window ?? config.supervision.window,
1943
2547
  backoff: policy.backoff ?? config.supervision.backoff,
1944
2548
  children,
@@ -1958,7 +2562,6 @@ export class OrchestratorService extends EventEmitter {
1958
2562
  this.onChildStarted(entry, handle, supervisor);
1959
2563
  // Set supervisor on handle BEFORE start so attachLogCapture can access it
1960
2564
  handle.supervisor = supervisor;
1961
- handle.serviceRouter = serviceRouter;
1962
2565
  handle.instanceCount = entry.instances ?? 1;
1963
2566
  handle.topologyProcesses = topology;
1964
2567
  this.wireSupervisorEvents(entry, handle, supervisor);
@@ -1969,7 +2572,7 @@ export class OrchestratorService extends EventEmitter {
1969
2572
  // This was a pool-only feature, ignored in silence everywhere else: a
1970
2573
  // process declaring `expose: true` got no registration and no warning,
1971
2574
  // and every consumer naming it in `topology.access` started without a
1972
- // proxy. Measured on priceverse, whose `collector` is a single process
2575
+ // proxy. Measured on quotes, whose `collector` is a single process
1973
2576
  // holding the only objects that know whether the exchange WebSockets are
1974
2577
  // up — the server process could not ask, and answered `ready: down —
1975
2578
  // exchanges unavailable` while three were connected.
@@ -1977,58 +2580,48 @@ export class OrchestratorService extends EventEmitter {
1977
2580
  // After `supervisor.start()` because there is no child to ask before it.
1978
2581
  // A consumer among these children may therefore start before the service
1979
2582
  // is registered; consumers re-resolve their proxy on use for exactly that
1980
- // reason (see priceverse's `OhlcvSchedulerService`).
1981
- await this.exposeChildTopologyServices(entry, supervisor, serviceRouter, singleEntries);
2583
+ // reason (see quotes's `OhlcvSchedulerService`).
2584
+ if (serviceRouter)
2585
+ await this.exposeChildTopologyServices(entry, supervisor, serviceRouter, singleEntries);
2586
+ if (handle.finishStartup())
2587
+ this.announceOnline(entry.name, handle);
2588
+ }
2589
+ /** Shared discovery contract for pools and supervisor children. */
2590
+ async discoverTopologyServices(application, provider, ask) {
2591
+ const deadline = Date.now() + TOPOLOGY_EXPOSE_TIMEOUT_MS;
2592
+ let reported;
2593
+ while (true) {
2594
+ try {
2595
+ reported = await ask();
2596
+ }
2597
+ catch (error) {
2598
+ throw new Error(`Application '${application}' topology provider '${provider}' discovery failed: ${String(error)}`, { cause: error });
2599
+ }
2600
+ if (Array.isArray(reported) && reported.length) {
2601
+ if (reported.some(service => !service || typeof service.name !== 'string' || !service.name ||
2602
+ (service.version !== undefined && typeof service.version !== 'string') ||
2603
+ !Array.isArray(service.methods) || service.methods.some((method) => typeof method !== 'string' || !method))) {
2604
+ throw new Error(`Application '${application}' topology provider '${provider}' returned invalid service metadata`);
2605
+ }
2606
+ const services = reported.filter(service => service.methods.length > 0);
2607
+ if (services.length)
2608
+ return services;
2609
+ }
2610
+ if (Date.now() >= deadline) {
2611
+ throw new Error(`Application '${application}' topology provider '${provider}' exposed no callable services within ${TOPOLOGY_EXPOSE_TIMEOUT_MS}ms`);
2612
+ }
2613
+ await new Promise(resolve => setTimeout(resolve, TOPOLOGY_EXPOSE_POLL_MS));
2614
+ }
1982
2615
  }
1983
- /**
1984
- * Register each single process's `@Service` classes on the daemon.
1985
- *
1986
- * Mirrors the pool path above, including its poll: a child reports ready
1987
- * before its Application has started, and `@Service` classes are exposed to
1988
- * Netron during start, so asking once asks a process that is still booting
1989
- * and gets an empty list back.
1990
- */
2616
+ /** Publish each single provider after its supervisor has started. */
1991
2617
  async exposeChildTopologyServices(entry, supervisor, serviceRouter, singleEntries) {
1992
2618
  for (const procEntry of singleEntries) {
1993
2619
  if (procEntry.topology?.expose !== true)
1994
2620
  continue;
1995
- const childName = `${entry.name}/${procEntry.name}`;
1996
- const getProxy = () => supervisor.getChildProxy(childName);
1997
- try {
1998
- const usable = (list) => Array.isArray(list) && list.length > 0 && list.some((svc) => svc.methods?.length > 0);
1999
- const ask = async () => {
2000
- const child = getProxy();
2001
- if (!child?.getExposedServices)
2002
- return undefined;
2003
- return (await child.getExposedServices());
2004
- };
2005
- let services = await ask();
2006
- const deadline = Date.now() + TOPOLOGY_EXPOSE_TIMEOUT_MS;
2007
- while (!usable(services) && Date.now() < deadline) {
2008
- await new Promise((r) => setTimeout(r, TOPOLOGY_EXPOSE_POLL_MS));
2009
- services = await ask();
2010
- }
2011
- if (!usable(services)) {
2012
- this.logger.warn({
2013
- app: entry.name,
2014
- process: procEntry.name,
2015
- waitedMs: TOPOLOGY_EXPOSE_TIMEOUT_MS,
2016
- reported: services?.map((svc) => `${svc.name}(${svc.methods?.length ?? 0})`) ?? [],
2017
- }, 'No usable @Service found on this process — topology.expose has no effect, and any ' +
2018
- 'process declaring topology.access on it will start without a proxy');
2019
- continue;
2020
- }
2021
- for (const svc of services ?? []) {
2022
- if (svc.methods.length === 0) {
2023
- this.logger.warn({ app: entry.name, process: procEntry.name, service: svc.name }, 'Process service exposes no methods — not registered on the daemon');
2024
- continue;
2025
- }
2026
- await serviceRouter.exposeChildService(procEntry.name, svc.name, svc.version ?? '1.0.0', getProxy, svc.methods);
2027
- this.logger.info({ app: entry.name, process: procEntry.name, service: svc.name, methods: svc.methods.length }, 'Auto-discovered and exposed process service on daemon Netron');
2028
- }
2029
- }
2030
- catch (err) {
2031
- this.logger.error({ app: entry.name, process: procEntry.name, error: err.message }, "Failed to auto-discover/expose this process's services");
2621
+ const getProxy = () => supervisor.getChildProxy(`${entry.name}/${procEntry.name}`);
2622
+ const services = await this.discoverTopologyServices(entry.name, procEntry.name, async () => getProxy()?.getExposedServices?.());
2623
+ for (const svc of services) {
2624
+ await serviceRouter.exposeChildService(procEntry.name, svc.name, svc.version ?? '1.0.0', getProxy, svc.methods);
2032
2625
  }
2033
2626
  }
2034
2627
  }
@@ -2038,6 +2631,7 @@ export class OrchestratorService extends EventEmitter {
2038
2631
  async launchSingleProcess(entry, handle, config, bootstrapAbsPath, buildResult) {
2039
2632
  const instances = entry.instances ?? 1;
2040
2633
  const policy = buildRestartPolicy(entry, config);
2634
+ const spawnEnv = withClosureLibraryPath(entry.env, [entry.releaseRoot, entry.cwd, bootstrapAbsPath]);
2041
2635
  // For single-process apps, use the first (only) process entry's bundled module
2042
2636
  const firstProcessName = buildResult?.modulePaths.keys().next().value;
2043
2637
  const bundledModulePath = firstProcessName
@@ -2046,9 +2640,12 @@ export class OrchestratorService extends EventEmitter {
2046
2640
  const spawnOpts = {
2047
2641
  name: entry.name,
2048
2642
  version: '1.0.0',
2643
+ // The execution owner's sealed runtime is never the application's
2644
+ // implicit working directory. Titan PM forwards this to native fork.
2645
+ cwd: entry.cwd ?? this.cwd,
2049
2646
  // As above: a single child's client otherwise runs on netron's default.
2050
2647
  requestTimeout: CHILD_REQUEST_TIMEOUT,
2051
- ...(entry.env && { env: entry.env }),
2648
+ ...(spawnEnv && { env: spawnEnv }),
2052
2649
  dependencies: {
2053
2650
  bootstrapPath: bootstrapAbsPath,
2054
2651
  ...(bundledModulePath && { bundledModulePath }),
@@ -2073,7 +2670,7 @@ export class OrchestratorService extends EventEmitter {
2073
2670
  };
2074
2671
  const childConfig = {
2075
2672
  name: entry.name,
2076
- process: BOOTSTRAP_PROCESS_PATH,
2673
+ process: await this.bootstrapRuntime(bootstrapAbsPath),
2077
2674
  spawnOptions: spawnOpts,
2078
2675
  critical: entry.critical ?? false,
2079
2676
  };
@@ -2082,6 +2679,7 @@ export class OrchestratorService extends EventEmitter {
2082
2679
  size: instances,
2083
2680
  strategy: PoolStrategy.ROUND_ROBIN,
2084
2681
  metrics: true,
2682
+ spawnOptions: spawnOpts,
2085
2683
  // See the note on the other pool: `replaceUnhealthy` is declared by
2086
2684
  // titan-pm and read by nothing.
2087
2685
  healthCheck: {
@@ -2090,25 +2688,16 @@ export class OrchestratorService extends EventEmitter {
2090
2688
  },
2091
2689
  spawnOptionsFactory: (index) => ({
2092
2690
  name: `${entry.name}-${index}`,
2093
- ...(entry.env && { env: entry.env }),
2094
- ...(entry.startupTimeout != null && { startupTimeout: entry.startupTimeout }),
2095
2691
  dependencies: {
2096
- bootstrapPath: bootstrapAbsPath,
2097
- ...(bundledModulePath && { bundledModulePath }),
2692
+ ...spawnOpts.dependencies,
2098
2693
  portOffset: index,
2099
2694
  },
2100
- health: {
2101
- enabled: true,
2102
- interval: config.monitoring.healthCheck.interval,
2103
- timeout: config.monitoring.healthCheck.timeout,
2104
- },
2105
- observability: { metrics: true },
2106
2695
  }),
2107
2696
  };
2108
2697
  }
2109
2698
  const supervisorConfig = {
2110
2699
  strategy: mapStrategy(config.supervision.strategy),
2111
- maxRestarts: policy.maxRestarts ?? config.supervision.maxRestarts,
2700
+ maxRestarts: policy.enabled === false ? 0 : policy.maxRestarts ?? config.supervision.maxRestarts,
2112
2701
  window: policy.window ?? config.supervision.window,
2113
2702
  backoff: policy.backoff ?? config.supervision.backoff,
2114
2703
  children: [childConfig],
@@ -2155,10 +2744,15 @@ export class OrchestratorService extends EventEmitter {
2155
2744
  this.persistState();
2156
2745
  if (!whole)
2157
2746
  return;
2158
- this.startPostOnlineCooldown(entry.name);
2159
- this.emit('app:online', entry.name);
2747
+ this.announceOnline(entry.name, handle);
2160
2748
  });
2161
2749
  }
2750
+ announceOnline(name, handle) {
2751
+ handle.clearLastExit();
2752
+ this.startPostOnlineCooldown(name);
2753
+ this.persistState();
2754
+ this.emit('app:online', name);
2755
+ }
2162
2756
  /**
2163
2757
  * Wire common supervisor events (crash, restart, escalate) and log capture.
2164
2758
  */
@@ -2169,7 +2763,8 @@ export class OrchestratorService extends EventEmitter {
2169
2763
  // The app re-entered a live state — drop the previous crash
2170
2764
  // context so a future `omnitron inspect` shows the *next*
2171
2765
  // crash, not the last one.
2172
- handle.clearLastExit();
2766
+ if (handle.status === 'online')
2767
+ handle.clearLastExit();
2173
2768
  });
2174
2769
  // A child that is down leaves the app partial until it is back — a
2175
2770
  // sibling's restart must not bring the app `online` around it.
@@ -2252,20 +2847,19 @@ export class OrchestratorService extends EventEmitter {
2252
2847
  // module that throws on import does — so the streams below are often
2253
2848
  // empty and the only account of what happened is on the error.
2254
2849
  this.persistChildFailure(entry.name, childName, error);
2255
- this.persistChildOutput(entry.name, childName, details?.stdout, 'stdout');
2256
- this.persistChildOutput(entry.name, childName, details?.stderr, 'stderr');
2850
+ if (this.pm.outputCaptureVersion !== 1) {
2851
+ this.persistChildOutput(entry.name, childName, details?.stdout, 'stdout');
2852
+ this.persistChildOutput(entry.name, childName, details?.stderr, 'stderr');
2853
+ }
2257
2854
  handle.recordExit({
2258
2855
  code: null,
2259
2856
  signal: null,
2260
2857
  expected: false,
2261
2858
  message: error.message,
2262
2859
  });
2263
- // The supervisor gives up on a non-critical child whose start failed (a
2264
- // critical one throws, and `startApp` says so). That went unseen while
2265
- // the first child's start made the app `online`; now the app would wait
2266
- // for a child that is not coming, in `starting` — which `omnitron start`
2267
- // takes for a start in progress and leaves alone. A declared process
2268
- // that did not start is an app that did not start.
2860
+ // The supervisor retries within its configured budget. Until a real
2861
+ // ready event arrives, the application is unavailable, not still booting.
2862
+ handle.childGone(childName);
2269
2863
  if (handle.status === 'starting')
2270
2864
  handle.markErrored();
2271
2865
  this.logger.error({ app: entry.name, child: childName, err: error.message }, 'Process failed to start');
@@ -2276,6 +2870,12 @@ export class OrchestratorService extends EventEmitter {
2276
2870
  this.logger.info({ app: entry.name, child: childName, attempt }, 'Process restarting');
2277
2871
  this.emit('app:restart', entry.name, attempt);
2278
2872
  });
2873
+ supervisor.on('child:recovery-stopped', (childName, error) => {
2874
+ handle.status = 'crashed';
2875
+ this.logger.error({ app: entry.name, child: childName, reason: error.message }, 'Process recovery stopped by restart policy; inspect the last failure before retrying');
2876
+ this.persistState();
2877
+ this.emit('app:escalated', entry.name, childName);
2878
+ });
2279
2879
  supervisor.on('escalate', (childName, _error) => {
2280
2880
  handle.status = 'crashed';
2281
2881
  this.logger.error({ app: entry.name, child: childName }, 'App exceeded max restarts — escalated');
@@ -2288,6 +2888,8 @@ export class OrchestratorService extends EventEmitter {
2288
2888
  * Routes child stdout/stderr lines to AppHandle ring buffer for `getLogs()`.
2289
2889
  */
2290
2890
  attachLogCapture(appName, childName, handle) {
2891
+ if (this.pm.outputCaptureVersion === 1)
2892
+ return;
2291
2893
  const supervisor = handle.supervisor;
2292
2894
  if (!supervisor)
2293
2895
  return;
@@ -2299,6 +2901,21 @@ export class OrchestratorService extends EventEmitter {
2299
2901
  return;
2300
2902
  workerHandle.onLog(this.childLogForwarder(appName, handle));
2301
2903
  }
2904
+ /** Pool initialization is complete; every later membership change supersedes this launch proof. */
2905
+ observePoolReleaseMembership(handle, pool) {
2906
+ const invalidate = () => handle.invalidateRelease();
2907
+ for (const event of ['worker:spawned', 'worker:shutdown', 'worker:replaced', 'pool:scaled', 'pool:destroyed'])
2908
+ pool.on(event, invalidate);
2909
+ // A crash precedes the pool's health check and replacement; stop confirming
2910
+ // the old membership as soon as the initial worker reports its exit.
2911
+ for (const id of pool.getWorkerIds()) {
2912
+ const worker = pool.getWorkerHandle(id);
2913
+ if (worker?.onExit)
2914
+ worker.onExit(invalidate);
2915
+ else
2916
+ invalidate();
2917
+ }
2918
+ }
2302
2919
  /**
2303
2920
  * Attach log capture to the workers of a topology POOL.
2304
2921
  *
@@ -2314,6 +2931,8 @@ export class OrchestratorService extends EventEmitter {
2314
2931
  * alternative is an event this package does not expose yet.
2315
2932
  */
2316
2933
  attachPoolLogCapture(appName, processName, handle, pool) {
2934
+ if (this.pm.outputCaptureVersion === 1)
2935
+ return;
2317
2936
  const forward = this.childLogForwarder(appName, handle);
2318
2937
  let attached = 0;
2319
2938
  for (const workerId of pool.getWorkerIds()) {
@@ -2327,8 +2946,12 @@ export class OrchestratorService extends EventEmitter {
2327
2946
  }
2328
2947
  /** The one place a child's line becomes an app's line. */
2329
2948
  childLogForwarder(appName, handle) {
2330
- return (line, stream) => {
2949
+ return (line, stream, context) => {
2331
2950
  // In-memory ring buffer (for live CLI tailing)
2951
+ // Accept durable capture before updating volatile views: a retry keeps
2952
+ // the same ID and must not duplicate the diagnostic ring.
2953
+ for (const handler of this.appLogHandlers)
2954
+ handler(appName, line, context);
2332
2955
  handle.appendLog(line);
2333
2956
  // Separate stderr ring — feeds `lastExit.stderrTail` on death.
2334
2957
  // Without this, the operator running `omnitron inspect` after
@@ -2336,15 +2959,6 @@ export class OrchestratorService extends EventEmitter {
2336
2959
  if (stream === 'stderr') {
2337
2960
  handle.appendStderr(line);
2338
2961
  }
2339
- // Persist to disk via registered log handlers (LogManager)
2340
- for (const handler of this.appLogHandlers) {
2341
- try {
2342
- handler(appName, line);
2343
- }
2344
- catch {
2345
- // Log handler failure must not break the app
2346
- }
2347
- }
2348
2962
  };
2349
2963
  }
2350
2964
  /**
@@ -2454,46 +3068,11 @@ export class OrchestratorService extends EventEmitter {
2454
3068
  // ============================================================================
2455
3069
  async stopChildProcess(handle, force, timeout) {
2456
3070
  const child = handle.childProcess;
2457
- if (!child || !child.pid)
3071
+ if (!child)
2458
3072
  return;
2459
- const pid = child.pid;
2460
- // P0-D — Signal the whole process group, not just the direct
2461
- // child. classic-launcher spawns with `detached: true` so the
2462
- // child becomes group leader (pgid === pid). `process.kill(-pid)`
2463
- // delivers the signal to every process in the group, reaping
2464
- // grandchildren (ffmpeg, docker, worker pools …) that ignore the
2465
- // direct-child kill. Falls back to `child.kill` when the negative-
2466
- // pid call fails (test environments, restricted permissions, the
2467
- // child wasn't started detached — bootstrap-mode currently isn't).
2468
- const sendSignal = (sig) => {
2469
- try {
2470
- process.kill(-pid, sig);
2471
- return;
2472
- }
2473
- catch (err) {
2474
- const code = err.code;
2475
- if (code !== 'ESRCH' && code !== 'EPERM') {
2476
- // ESRCH/EPERM = group already gone or not a group leader.
2477
- // Anything else (EINVAL etc.) → log via best-effort.
2478
- this.logger.debug({ app: handle.name, pid, sig, code }, 'process.kill(-pid) fallback');
2479
- }
2480
- }
2481
- try {
2482
- child.kill(sig);
2483
- }
2484
- catch { /* best-effort */ }
2485
- };
2486
- await new Promise((resolve) => {
2487
- const timer = setTimeout(() => {
2488
- sendSignal('SIGKILL');
2489
- resolve();
2490
- }, timeout);
2491
- child.once('exit', () => {
2492
- clearTimeout(timer);
2493
- resolve();
2494
- });
2495
- sendSignal(force ? 'SIGKILL' : 'SIGTERM');
2496
- });
3073
+ const stopped = await killChildAndVerify(child, this.logger, { app: handle.name }, timeout, { force, processGroup: true });
3074
+ if (!stopped)
3075
+ throw new Error(`Application '${handle.name}' (pid ${child.pid}) did not confirm process-group exit`);
2497
3076
  }
2498
3077
  /**
2499
3078
  * Cancel a pending crash cool-down for `name`, if one is armed.
@@ -2508,131 +3087,63 @@ export class OrchestratorService extends EventEmitter {
2508
3087
  }
2509
3088
  }
2510
3089
  async scheduleRecovery(entry, handle, config) {
3090
+ const generation = this.stopGeneration;
3091
+ const revision = this.appStopIntents.get(entry.name)?.revision;
3092
+ const eligible = () => !this.stoppingApps && generation === this.stopGeneration &&
3093
+ revision === this.appStopIntents.get(entry.name)?.revision &&
3094
+ !this.appStopIntents.get(entry.name)?.stopped &&
3095
+ this.handles.get(entry.name) === handle &&
3096
+ (handle.status === 'crashed' || handle.status === 'errored');
3097
+ if (!eligible())
3098
+ return;
2511
3099
  const policy = buildRestartPolicy(entry, config);
3100
+ const maxRestarts = policy.maxRestarts ?? 5;
2512
3101
  if (!policy.enabled)
2513
3102
  return;
2514
- if (handle.restarts >= (policy.maxRestarts ?? 5)) {
3103
+ if (maxRestarts <= 0) {
2515
3104
  handle.status = 'crashed';
2516
- this.logger.error({ app: entry.name }, 'Max restarts exceeded');
2517
3105
  this.emit('app:escalated', entry.name);
2518
- // P1-I — auto-recovery after a cool-down. pm2 has this as
2519
- // `restart_delay` + a fresh attempt window; pre-fix omnitron
2520
- // left the app permanently 'crashed' until human intervention.
2521
- // We reset the counter + schedule one fresh attempt 10 minutes
2522
- // out. If THAT attempt also crashes through maxRestarts we
2523
- // land back here and pause another 10 minutes — bounded
2524
- // self-healing without thrashing.
2525
- //
2526
- // The wait happens OUTSIDE the lifecycle queue, and that is the
2527
- // whole point. It used to be a queued `crash-restart` whose
2528
- // `run()` slept for the entire cool-down — but `enqueue` will
2529
- // not preempt a RUNNING head, and with an empty queue the
2530
- // sleeper always became the head immediately. So the `onPreempt`
2531
- // hook meant to cancel it could never fire, and an operator's
2532
- // `stop` or `restart` simply queued behind ten minutes of sleep:
2533
- // the CLI's RPC timed out after 60s while the op stayed queued,
2534
- // to fire whenever the cool-down finally elapsed. An app that
2535
- // exhausted its restart budget was unreachable by every command
2536
- // the CLI offers — `restart` hung, `stop` hung, `stack start`
2537
- // skipped it — and the only recovery was restarting the daemon.
2538
- const COOL_DOWN_MS = 10 * 60_000;
2539
- this.clearCoolDown(entry.name);
2540
- const timer = setTimeout(() => {
2541
- this.coolDownTimers.delete(entry.name);
2542
- // Re-read the handle: every start replaces it (see
2543
- // `startAppInternal`), so the one captured above is stale the
2544
- // moment anything restarts this app. Only a still-crashed app
2545
- // wants this attempt — an operator who started it meanwhile
2546
- // has already settled the question.
2547
- const current = this.handles.get(entry.name);
2548
- if (!current || current.status !== 'crashed')
2549
- return;
2550
- this.logger.info({ app: entry.name }, 'Cool-down elapsed — attempting fresh recovery');
2551
- current.restarts = 0; // fresh attempt window
2552
- current.status = 'stopped';
2553
- void this.lifecycleQueue
2554
- .enqueue(entry.name, 'crash-restart', () => this.startAppInternal(entry, config))
2555
- .catch((err) => {
2556
- if (err instanceof LifecyclePreempted)
2557
- return;
2558
- this.logger.error({ app: entry.name, err: err.message }, 'Cool-down recovery failed');
2559
- });
2560
- }, COOL_DOWN_MS);
2561
- timer.unref?.();
2562
- this.coolDownTimers.set(entry.name, timer);
2563
3106
  return;
2564
3107
  }
2565
- const backoff = policy.backoff ?? config.supervision.backoff;
2566
- const delay = this.calculateBackoff(handle.restarts, backoff);
2567
- this.logger.info({ app: entry.name, delay, attempt: handle.restarts + 1 }, 'Scheduling restart');
2568
- // P0-I — schedule the crash-restart through the lifecycle queue
2569
- // so an explicit stop preempts the pending restart before it
2570
- // fires. The setTimeout is still the timing source, but the
2571
- // queue.enqueue with `onPreempt` guarantees the timer is cleared
2572
- // (and the promise rejected with LifecyclePreempted) the moment a
2573
- // higher-priority op for the same app arrives. Pre-fix the timer
2574
- // could fire during stopApp's `await stopChild(...)` window and
2575
- // spawn a zombie under the same handle.
2576
- let timer = null;
2577
- const restartPromise = this.lifecycleQueue.enqueue(entry.name, 'crash-restart', () => new Promise((resolve, reject) => {
2578
- timer = setTimeout(async () => {
2579
- timer = null;
2580
- // Guard: don't restart if orchestrator was stopped during backoff
2581
- if (handle.status === 'stopping' || handle.status === 'stopped') {
2582
- resolve();
2583
- return;
2584
- }
2585
- try {
2586
- handle.status = 'stopped';
2587
- // `startAppInternal`, not `startApp`.
2588
- //
2589
- // This task holds the lifecycle-queue slot for `entry.name`.
2590
- // `startApp` enqueues 'start' on that same key, and the queue
2591
- // cannot run it until this task returns — so the await never
2592
- // settles and the restart silently never happens. Measured:
2593
- // `startApp:enter` with no matching exit, and the app left in
2594
- // whatever state the crash put it in.
2595
- //
2596
- // This is why the whole policy below — bounded attempts,
2597
- // exponential backoff, the ten-minute cool-down described in its
2598
- // own comment as "bounded self-healing" — had never restarted
2599
- // anything. The queue was introduced (P0-I) to stop a restart
2600
- // timer racing a stop; it also made the restart unreachable, and
2601
- // nothing failed loudly enough to say so.
2602
- await this.startAppInternal(entry, config);
2603
- resolve();
2604
- }
2605
- catch (err) {
2606
- const message = err.message;
2607
- this.logger.error({ app: entry.name, error: message }, 'Restart failed');
2608
- // Said separately and after, because reading the process table
2609
- // takes a moment and the failure itself must not wait for it.
2610
- void this.explainPortConflict(message).then((held) => {
2611
- if (held)
2612
- this.logger.error({ app: entry.name }, `Restart failed — ${held}`);
2613
- });
2614
- reject(err);
2615
- }
2616
- }, delay);
2617
- }), () => {
2618
- // onPreempt — explicit stop / restart arrived. Cancel the
2619
- // pending timer so the restart never fires.
2620
- if (timer) {
2621
- clearTimeout(timer);
2622
- timer = null;
2623
- }
2624
- });
2625
- // Swallow LifecyclePreempted — that's the explicit-stop happy
2626
- // path, not an error. Anything else gets logged.
2627
- restartPromise.catch((err) => {
2628
- if (err instanceof LifecyclePreempted)
3108
+ const window = handle.restartWindow ??= new RestartWindow();
3109
+ const recent = window.recent(policy.window);
3110
+ const exhausted = recent >= maxRestarts;
3111
+ if (exhausted) {
3112
+ handle.status = 'crashed';
3113
+ this.logger.error({ app: entry.name }, 'Max restarts exceeded');
3114
+ this.emit('app:escalated', entry.name);
3115
+ }
3116
+ const delay = exhausted ? 10 * 60_000 : this.calculateBackoff(recent, policy.backoff ?? config.supervision.backoff);
3117
+ this.logger.info({ app: entry.name, delay, attempt: exhausted ? 1 : recent + 1 }, 'Scheduling restart');
3118
+ this.clearCoolDown(entry.name);
3119
+ // Waiting must not occupy the lifecycle queue: a running queue head
3120
+ // cannot be preempted. Only the actual launch takes the queue slot.
3121
+ const timer = setTimeout(() => {
3122
+ this.coolDownTimers.delete(entry.name);
3123
+ if (!eligible())
2629
3124
  return;
2630
- this.logger.warn({ app: entry.name, err: err.message }, 'Crash restart task rejected');
2631
- });
2632
- // Legacy field — callers still poke handle.crashRestartTimer to
2633
- // check "is a restart pending"; keep it in sync with the queued
2634
- // timer so existing inspect / status code paths don't break.
2635
- handle.crashRestartTimer = timer;
3125
+ void this.lifecycleQueue.enqueue(entry.name, 'crash-restart', async () => {
3126
+ // A stop can arrive after the timer fires but before this job runs.
3127
+ if (!eligible())
3128
+ return;
3129
+ if (exhausted)
3130
+ window.clear();
3131
+ window.record(policy.window);
3132
+ handle.status = 'stopped';
3133
+ await this.startAppInternal(entry, config);
3134
+ }).catch((err) => {
3135
+ if (err instanceof LifecyclePreempted)
3136
+ return;
3137
+ const message = err.message;
3138
+ this.logger.error({ app: entry.name, error: message }, 'Restart failed');
3139
+ void this.explainPortConflict(message).then((held) => {
3140
+ if (held)
3141
+ this.logger.error({ app: entry.name }, `Restart failed — ${held}`);
3142
+ });
3143
+ });
3144
+ }, delay);
3145
+ timer.unref?.();
3146
+ this.coolDownTimers.set(entry.name, timer);
2636
3147
  }
2637
3148
  calculateBackoff(attempt, backoff) {
2638
3149
  // Delegate to the shared backoff library in titan-pm. Pre-fix the
@@ -2923,6 +3434,7 @@ export class OrchestratorService extends EventEmitter {
2923
3434
  }
2924
3435
  const info = {
2925
3436
  name: handle.name,
3437
+ generation: handle.generation,
2926
3438
  pid: handle.pid,
2927
3439
  status,
2928
3440
  cpu: handle.cpu,
@@ -2932,6 +3444,7 @@ export class OrchestratorService extends EventEmitter {
2932
3444
  instances: handle.instanceCount,
2933
3445
  port: handle.port,
2934
3446
  mode: handle.mode,
3447
+ release: handle.release,
2935
3448
  critical: handle.entry.critical ?? false,
2936
3449
  };
2937
3450
  // Include sub-process topology if present