@omnitron-dev/omnitron 0.3.5 → 0.4.6

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 (267) hide show
  1. package/README.md +296 -6
  2. package/bin/{pnpmfile-sdk.mjs → pnpmfile-sdk.js} +13 -0
  3. package/bin/sdk.d.ts +19 -0
  4. package/bin/sdk.js +932 -0
  5. package/dist/BUILD.json +2 -2
  6. package/dist/cli/omnitron.js +14 -6
  7. package/dist/cli/omnitron.js.map +1 -1
  8. package/dist/commands/stack.d.ts +2 -5
  9. package/dist/commands/stack.d.ts.map +1 -1
  10. package/dist/commands/stack.js +32 -0
  11. package/dist/commands/stack.js.map +1 -1
  12. package/dist/commands/status.d.ts.map +1 -1
  13. package/dist/commands/status.js +1 -0
  14. package/dist/commands/status.js.map +1 -1
  15. package/dist/daemon/daemon-client.d.ts +3 -15
  16. package/dist/daemon/daemon-client.d.ts.map +1 -1
  17. package/dist/daemon/daemon-client.js +4 -0
  18. package/dist/daemon/daemon-client.js.map +1 -1
  19. package/dist/daemon/daemon.d.ts +5 -11
  20. package/dist/daemon/daemon.d.ts.map +1 -1
  21. package/dist/daemon/daemon.js +28 -42
  22. package/dist/daemon/daemon.js.map +1 -1
  23. package/dist/daemon/daemon.rpc-service.d.ts +3 -15
  24. package/dist/daemon/daemon.rpc-service.d.ts.map +1 -1
  25. package/dist/daemon/daemon.rpc-service.js +27 -3
  26. package/dist/daemon/daemon.rpc-service.js.map +1 -1
  27. package/dist/daemon/darwin-owner-evidence.js +1 -1
  28. package/dist/daemon/darwin-owner-evidence.js.map +1 -1
  29. package/dist/daemon/execution-capabilities.d.ts +1 -1
  30. package/dist/daemon/execution-capabilities.d.ts.map +1 -1
  31. package/dist/daemon/execution-capabilities.js +3 -3
  32. package/dist/daemon/execution-capabilities.js.map +1 -1
  33. package/dist/daemon/execution-client.d.ts +4 -0
  34. package/dist/daemon/execution-client.d.ts.map +1 -1
  35. package/dist/daemon/execution-client.js +28 -6
  36. package/dist/daemon/execution-client.js.map +1 -1
  37. package/dist/daemon/execution-host.d.ts +4 -11
  38. package/dist/daemon/execution-host.d.ts.map +1 -1
  39. package/dist/daemon/execution-host.js +3 -9
  40. package/dist/daemon/execution-host.js.map +1 -1
  41. package/dist/daemon/execution-owner.d.ts.map +1 -1
  42. package/dist/daemon/execution-owner.js +2 -16
  43. package/dist/daemon/execution-owner.js.map +1 -1
  44. package/dist/daemon/execution-shutdown.d.ts +1 -1
  45. package/dist/daemon/execution-shutdown.d.ts.map +1 -1
  46. package/dist/daemon/managed-owner-build.d.ts +4 -0
  47. package/dist/daemon/managed-owner-build.d.ts.map +1 -1
  48. package/dist/daemon/managed-owner-build.js +14 -2
  49. package/dist/daemon/managed-owner-build.js.map +1 -1
  50. package/dist/daemon/managed-runtime.js +1 -1
  51. package/dist/daemon/managed-runtime.js.map +1 -1
  52. package/dist/daemon/owner-reconciliation.d.ts.map +1 -1
  53. package/dist/daemon/owner-reconciliation.js +1 -2
  54. package/dist/daemon/owner-reconciliation.js.map +1 -1
  55. package/dist/daemon/system-guardian-cgroup.js +1 -1
  56. package/dist/daemon/system-guardian-cgroup.js.map +1 -1
  57. package/dist/infrastructure/existing-containers.d.ts +25 -0
  58. package/dist/infrastructure/existing-containers.d.ts.map +1 -0
  59. package/dist/infrastructure/existing-containers.js +183 -0
  60. package/dist/infrastructure/existing-containers.js.map +1 -0
  61. package/dist/infrastructure/infrastructure.service.d.ts +14 -1
  62. package/dist/infrastructure/infrastructure.service.d.ts.map +1 -1
  63. package/dist/infrastructure/infrastructure.service.js +118 -9
  64. package/dist/infrastructure/infrastructure.service.js.map +1 -1
  65. package/dist/infrastructure/stack-infra-manager.d.ts +8 -2
  66. package/dist/infrastructure/stack-infra-manager.d.ts.map +1 -1
  67. package/dist/infrastructure/stack-infra-manager.js +46 -9
  68. package/dist/infrastructure/stack-infra-manager.js.map +1 -1
  69. package/dist/monitoring/log-journal.d.ts.map +1 -1
  70. package/dist/monitoring/log-journal.js +1 -2
  71. package/dist/monitoring/log-journal.js.map +1 -1
  72. package/dist/operations.d.ts +1 -0
  73. package/dist/operations.d.ts.map +1 -1
  74. package/dist/operations.js +1 -0
  75. package/dist/operations.js.map +1 -1
  76. package/dist/orchestrator/bootstrap-loader.d.ts +2 -0
  77. package/dist/orchestrator/bootstrap-loader.d.ts.map +1 -1
  78. package/dist/orchestrator/bootstrap-loader.js +2 -1
  79. package/dist/orchestrator/bootstrap-loader.js.map +1 -1
  80. package/dist/orchestrator/classic-launcher.d.ts.map +1 -1
  81. package/dist/orchestrator/classic-launcher.js +2 -1
  82. package/dist/orchestrator/classic-launcher.js.map +1 -1
  83. package/dist/orchestrator/execution-contract.d.ts +2 -3
  84. package/dist/orchestrator/execution-contract.d.ts.map +1 -1
  85. package/dist/orchestrator/file-watcher.d.ts +11 -23
  86. package/dist/orchestrator/file-watcher.d.ts.map +1 -1
  87. package/dist/orchestrator/file-watcher.js +57 -42
  88. package/dist/orchestrator/file-watcher.js.map +1 -1
  89. package/dist/orchestrator/orchestrator.service.d.ts +10 -5
  90. package/dist/orchestrator/orchestrator.service.d.ts.map +1 -1
  91. package/dist/orchestrator/orchestrator.service.js +117 -20
  92. package/dist/orchestrator/orchestrator.service.js.map +1 -1
  93. package/dist/project/bootstrap-metadata.d.ts +1 -1
  94. package/dist/project/bootstrap-metadata.d.ts.map +1 -1
  95. package/dist/project/bootstrap-metadata.js +3 -2
  96. package/dist/project/bootstrap-metadata.js.map +1 -1
  97. package/dist/project/node-stack-stop.d.ts +2 -1
  98. package/dist/project/node-stack-stop.d.ts.map +1 -1
  99. package/dist/project/node-stack-stop.js +5 -1
  100. package/dist/project/node-stack-stop.js.map +1 -1
  101. package/dist/release/closure-library-path.d.ts +8 -2
  102. package/dist/release/closure-library-path.d.ts.map +1 -1
  103. package/dist/release/closure-library-path.js +72 -28
  104. package/dist/release/closure-library-path.js.map +1 -1
  105. package/dist/release/local-installation.d.ts +2 -0
  106. package/dist/release/local-installation.d.ts.map +1 -1
  107. package/dist/release/local-installation.js +1 -1
  108. package/dist/release/local-installation.js.map +1 -1
  109. package/dist/release/portable-archive.d.ts +3 -0
  110. package/dist/release/portable-archive.d.ts.map +1 -1
  111. package/dist/release/portable-archive.js +13 -7
  112. package/dist/release/portable-archive.js.map +1 -1
  113. package/dist/release/registry-framework.d.ts +25 -0
  114. package/dist/release/registry-framework.d.ts.map +1 -1
  115. package/dist/release/registry-framework.js +51 -3
  116. package/dist/release/registry-framework.js.map +1 -1
  117. package/dist/release/target-runtime.d.ts +4 -0
  118. package/dist/release/target-runtime.d.ts.map +1 -1
  119. package/dist/release/target-runtime.js +9 -0
  120. package/dist/release/target-runtime.js.map +1 -1
  121. package/dist/services/host-upgrade.d.ts +2 -0
  122. package/dist/services/host-upgrade.d.ts.map +1 -1
  123. package/dist/services/host-upgrade.js +6 -2
  124. package/dist/services/host-upgrade.js.map +1 -1
  125. package/dist/services/infrastructure.rpc-service.d.ts +8 -0
  126. package/dist/services/infrastructure.rpc-service.d.ts.map +1 -1
  127. package/dist/services/infrastructure.rpc-service.js +90 -10
  128. package/dist/services/infrastructure.rpc-service.js.map +1 -1
  129. package/dist/services/kernel-rollout.service.d.ts.map +1 -1
  130. package/dist/services/kernel-rollout.service.js +1 -2
  131. package/dist/services/kernel-rollout.service.js.map +1 -1
  132. package/dist/services/migration-process.d.ts +1 -0
  133. package/dist/services/migration-process.d.ts.map +1 -1
  134. package/dist/services/migration-process.js +4 -2
  135. package/dist/services/migration-process.js.map +1 -1
  136. package/dist/services/pipeline-definition.d.ts.map +1 -1
  137. package/dist/services/pipeline-definition.js +32 -6
  138. package/dist/services/pipeline-definition.js.map +1 -1
  139. package/dist/services/pipeline.service.d.ts +7 -1
  140. package/dist/services/pipeline.service.d.ts.map +1 -1
  141. package/dist/services/pipeline.service.js +106 -13
  142. package/dist/services/pipeline.service.js.map +1 -1
  143. package/dist/services/project.rpc-service.d.ts +6 -5
  144. package/dist/services/project.rpc-service.d.ts.map +1 -1
  145. package/dist/services/project.rpc-service.js +13 -0
  146. package/dist/services/project.rpc-service.js.map +1 -1
  147. package/dist/services/project.service.d.ts +24 -6
  148. package/dist/services/project.service.d.ts.map +1 -1
  149. package/dist/services/project.service.js +327 -59
  150. package/dist/services/project.service.js.map +1 -1
  151. package/dist/services/remote-deployer.service.d.ts.map +1 -1
  152. package/dist/services/remote-deployer.service.js +3 -0
  153. package/dist/services/remote-deployer.service.js.map +1 -1
  154. package/dist/shared/dto/backend.d.ts +3 -0
  155. package/dist/shared/dto/backend.d.ts.map +1 -1
  156. package/dist/shared/dto/backend.js.map +1 -1
  157. package/dist/shared/dto/pipelines.d.ts +54 -5
  158. package/dist/shared/dto/pipelines.d.ts.map +1 -1
  159. package/dist/shared/dto/pipelines.js +0 -7
  160. package/dist/shared/dto/pipelines.js.map +1 -1
  161. package/dist/shared/dto/project.d.ts +60 -0
  162. package/dist/shared/dto/project.d.ts.map +1 -1
  163. package/dist/shared/dto/services.d.ts +26 -17
  164. package/dist/shared/dto/services.d.ts.map +1 -1
  165. package/dist/shared/dto/services.js.map +1 -1
  166. package/dist/workers/system-worker-manager.d.ts +1 -2
  167. package/dist/workers/system-worker-manager.d.ts.map +1 -1
  168. package/dist/workers/system-worker-manager.js +5 -3
  169. package/dist/workers/system-worker-manager.js.map +1 -1
  170. package/package.json +17 -16
  171. package/webapp/dist/BUILD.json +2 -2
  172. package/webapp/dist/assets/{access-DUjabwNX.js → access-B2gXuoMG.js} +1 -1
  173. package/webapp/dist/assets/{access-BvKK9dEv.js → access-I0f72P9m.js} +1 -1
  174. package/webapp/dist/assets/{admin-data-table-BKSDI8sU.js → admin-data-table-CAEL2f-m.js} +1 -1
  175. package/webapp/dist/assets/{alert-uBG6r9NW.js → alert-BdJ2uaY0.js} +1 -1
  176. package/webapp/dist/assets/{alerts-CzN6OqX5.js → alerts-DeVkMXWo.js} +1 -1
  177. package/webapp/dist/assets/{apps-G_Lm6m4F.js → apps-9SuDvyGQ.js} +1 -1
  178. package/webapp/dist/assets/{audit-CLMpdBzG.js → audit-DT8cY7Ys.js} +1 -1
  179. package/webapp/dist/assets/backend-status.store-BbBE9cn8.js +4 -0
  180. package/webapp/dist/assets/{card-DkH32gMY.js → card-DaUEmUI5.js} +1 -1
  181. package/webapp/dist/assets/{chart-BpGXlCJc.js → chart-BKXP2ter.js} +1 -1
  182. package/webapp/dist/assets/{client-DFnuv2z3.js → client-CgyTwq9g.js} +1 -1
  183. package/webapp/dist/assets/{code-editor-DK6Tmmxv.js → code-editor-JVuQ4m-z.js} +1 -1
  184. package/webapp/dist/assets/{comparison-bars-BtC0dHjF.js → comparison-bars-Ds5Dt1oj.js} +1 -1
  185. package/webapp/dist/assets/{confirm-dialog-BbGsAz7_.js → confirm-dialog-BayExVbF.js} +1 -1
  186. package/webapp/dist/assets/{console-keyboard-D3YCA0yU.js → console-keyboard-uSLt92dB.js} +1 -1
  187. package/webapp/dist/assets/{containers-BsFwprq4.js → containers-DkXTgcrY.js} +1 -1
  188. package/webapp/dist/assets/{controls-C5W8gHU4.js → controls-CqeGPnaF.js} +1 -1
  189. package/webapp/dist/assets/{dashboard-BN7rKE5n.js → dashboard-By5yPuOf.js} +1 -1
  190. package/webapp/dist/assets/{dashboard-builder-BXFxWjXP.js → dashboard-builder-C0hvBwkd.js} +1 -1
  191. package/webapp/dist/assets/{deploy-progress-CUUwlYtQ.js → deploy-progress-B39cvvCE.js} +1 -1
  192. package/webapp/dist/assets/{deploy-release-dialog-58lGZDNk.js → deploy-release-dialog-CnzaO_xL.js} +1 -1
  193. package/webapp/dist/assets/{deployments-DEzjHerg.js → deployments-BXP943hA.js} +1 -1
  194. package/webapp/dist/assets/{detail-pXPk4O0E.js → detail-B84RgiOb.js} +1 -1
  195. package/webapp/dist/assets/{detail-Dj3gxaH0.js → detail-CVXDks9-.js} +1 -1
  196. package/webapp/dist/assets/{detail-CBn9pjJU.js → detail-D9DixtaK.js} +1 -1
  197. package/webapp/dist/assets/{empty-content-7jOFhG4C.js → empty-content-eyDOuOVp.js} +1 -1
  198. package/webapp/dist/assets/{error-boundary-CLLI8PWw.js → error-boundary-CQmDr_HS.js} +1 -1
  199. package/webapp/dist/assets/{event-fields-CiyqrRO8.js → event-fields-C7p2a2HY.js} +1 -1
  200. package/webapp/dist/assets/{files-DigwXndm.js → files-BsfGT3t6.js} +2 -2
  201. package/webapp/dist/assets/{icons-OboZgWSt.js → icons-B9Ct8PJ9.js} +1 -1
  202. package/webapp/dist/assets/index-BEfv96EF.js +1 -0
  203. package/webapp/dist/assets/{label-B1SF0RTL.js → label-avMhe08g.js} +1 -1
  204. package/webapp/dist/assets/{log-level-filter-Bcn31D1F.js → log-level-filter-oaUGdbpk.js} +1 -1
  205. package/webapp/dist/assets/{logs-DrsBbLfb.js → logs-iC1OEDv3.js} +1 -1
  206. package/webapp/dist/assets/{metric-chart-M-kI-XOt.js → metric-chart-CSa_qv4F.js} +1 -1
  207. package/webapp/dist/assets/{metrics-D5cDZTEo.js → metrics-CKCmcGKw.js} +1 -1
  208. package/webapp/dist/assets/{mui-Cd711nOk.js → mui-B3fJdIMc.js} +1 -1
  209. package/webapp/dist/assets/{mui-CdB_p2lt.js → mui-Bdr6Ks5j.js} +1 -1
  210. package/webapp/dist/assets/{mui-Db5J-QUd.js → mui-CADnFGCx.js} +1 -1
  211. package/webapp/dist/assets/{mui-AnEgAVjz.js → mui-CMWGTMXv.js} +1 -1
  212. package/webapp/dist/assets/{mui-DyT2n1lx.js → mui-CN3dT7bb.js} +1 -1
  213. package/webapp/dist/assets/{mui-BwsIrivo.js → mui-CPEkFAPo.js} +1 -1
  214. package/webapp/dist/assets/{mui-dLCwWoMw.js → mui-D3qAWvfZ.js} +1 -1
  215. package/webapp/dist/assets/{mui-D5m7fDCh.js → mui-D7tBU80e.js} +1 -1
  216. package/webapp/dist/assets/{mui-59N0OVRa.js → mui-DaJavAoc.js} +1 -1
  217. package/webapp/dist/assets/{mui-BXSXx9c9.js → mui-SNRRJ_vi.js} +1 -1
  218. package/webapp/dist/assets/{nodes-CwwZZuu4.js → nodes-DtLyXH0V.js} +1 -1
  219. package/webapp/dist/assets/{operation-status-Bm1x1wTz.js → operation-status-DHyYOT7G.js} +1 -1
  220. package/webapp/dist/assets/{page-breadcrumbs-fR7Jmpp4.js → page-breadcrumbs-3R8RZ3nA.js} +1 -1
  221. package/webapp/dist/assets/pipelines-Do2NAAqK.js +3 -0
  222. package/webapp/dist/assets/{project.store-DuCgv6Eq.js → project.store-D5IR3fo9.js} +1 -1
  223. package/webapp/dist/assets/{projects-TBAdpCeX.js → projects-BqlGbzeG.js} +1 -1
  224. package/webapp/dist/assets/{realtime.store-hfxZD2DU.js → realtime.store-C8D235-B.js} +1 -1
  225. package/webapp/dist/assets/{release-bits-BJ6i23y0.js → release-bits-IehuBssK.js} +1 -1
  226. package/webapp/dist/assets/{release-build-panel-BNXkwNE1.js → release-build-panel-C48hP_9w.js} +1 -1
  227. package/webapp/dist/assets/{release-deployment-state-gN8ZT3aq.js → release-deployment-state-BfmxZP4Y.js} +1 -1
  228. package/webapp/dist/assets/{releases-CXXKUh-v.js → releases-Cm0RV5Xu.js} +1 -1
  229. package/webapp/dist/assets/{search-input-C0MHI8vO.js → search-input-SWD1dXxD.js} +1 -1
  230. package/webapp/dist/assets/settings-DwuEPQGg.js +1 -0
  231. package/webapp/dist/assets/sign-in-CQ-WeS5A.js +1 -0
  232. package/webapp/dist/assets/{skeleton-BmWDJWF9.js → skeleton-BnVxAoeX.js} +1 -1
  233. package/webapp/dist/assets/{snackbar-DSPmjMyi.js → snackbar-CRX6eqRT.js} +1 -1
  234. package/webapp/dist/assets/{stack-health-status-BIv2C10x.js → stack-health-status-DfErRNb1.js} +1 -1
  235. package/webapp/dist/assets/{stack-start-notice-D-AH_bzn.js → stack-start-notice-NkYDjR-f.js} +1 -1
  236. package/webapp/dist/assets/{stacks-WY_ynkON.js → stacks-BOGCfW90.js} +1 -1
  237. package/webapp/dist/assets/{store-bqUBn2A4.js → store-DtTtbc9H.js} +1 -1
  238. package/webapp/dist/assets/{system-info-DXMwo6gl.js → system-info-Cw-xywgI.js} +1 -1
  239. package/webapp/dist/assets/{table-BOWT6Y9d.js → table-D-so_B1p.js} +1 -1
  240. package/webapp/dist/assets/{table-viewport-Bp4pq-c_.js → table-viewport-DdZ1yAKm.js} +1 -1
  241. package/webapp/dist/assets/{tabs-k5NPGLnJ.js → tabs-DGqBkXh_.js} +1 -1
  242. package/webapp/dist/assets/{terminal-QWBau-Us.js → terminal-Bbl0XNeB.js} +1 -1
  243. package/webapp/dist/assets/{topology-C_Qp1RqW.js → topology-DmrRy7nN.js} +1 -1
  244. package/webapp/dist/assets/{topology-metadata-dialog-BivuU2y6.js → topology-metadata-dialog-Dpfp4YF1.js} +1 -1
  245. package/webapp/dist/assets/{traces-By0rdfDC.js → traces-CKHsOabJ.js} +1 -1
  246. package/webapp/dist/assets/{use-stack-context-8yaHaN8L.js → use-stack-context-BuraYaeY.js} +1 -1
  247. package/webapp/dist/assets/webapp-D8h_eabt.js +35 -0
  248. package/webapp/dist/console-version.json +1 -1
  249. package/webapp/dist/index.html +34 -34
  250. package/webapp/dist/logo.svg +1 -80
  251. package/bin/sdk.d.mts +0 -8
  252. package/bin/sdk.mjs +0 -580
  253. package/dist/monitoring/process-lifetime.d.ts +0 -11
  254. package/dist/monitoring/process-lifetime.d.ts.map +0 -1
  255. package/dist/monitoring/process-lifetime.js +0 -45
  256. package/dist/monitoring/process-lifetime.js.map +0 -1
  257. package/dist/shared/host-boot-identity.d.ts +0 -12
  258. package/dist/shared/host-boot-identity.d.ts.map +0 -1
  259. package/dist/shared/host-boot-identity.js +0 -89
  260. package/dist/shared/host-boot-identity.js.map +0 -1
  261. package/webapp/dist/assets/index-Bo9An3pJ.js +0 -1
  262. package/webapp/dist/assets/omnitron-logo-koMCbsCv.js +0 -1
  263. package/webapp/dist/assets/pipelines-BrfTjf6Y.js +0 -3
  264. package/webapp/dist/assets/settings-B3egRvbI.js +0 -1
  265. package/webapp/dist/assets/sign-in-9q-Nfy83.js +0 -1
  266. package/webapp/dist/assets/webapp-BO_WoB_z.js +0 -35
  267. package/webapp/dist/favicon.png +0 -0
@@ -35,6 +35,7 @@ import { stackExecutionKey, executionScopeKey, executionScopeOwns } from '../sha
35
35
  * → Two Netron instances: PM management plane + app HTTP data plane
36
36
  */
37
37
  import { ReadinessMonitor } from '../health/readiness.js';
38
+ import { FileWatcher } from './file-watcher.js';
38
39
  import fs from 'node:fs';
39
40
  import { readDeclaredConfig, withDeclaredConfig } from '../project/declared-config.js';
40
41
  import path from 'node:path';
@@ -210,6 +211,7 @@ export class OrchestratorService extends EventEmitter {
210
211
  devMode = false;
211
212
  /** esbuild bundling pipeline — pre-bundles TS entry points for child processes */
212
213
  buildService = null;
214
+ fileWatcher = null;
213
215
  watchDisabled = false;
214
216
  watchSelection = null;
215
217
  bootstrapSources = new Map();
@@ -226,11 +228,42 @@ export class OrchestratorService extends EventEmitter {
226
228
  if (!enabled || !this.handles.get(name) || !this.allowsWatch(this.handles.get(name).entry))
227
229
  state.watchSerial = 0;
228
230
  }
231
+ this.syncClassicWatches();
229
232
  await Promise.all([...this.bootstrapSources.keys()].map((name) => this.syncBootstrapWatch(name)));
230
233
  }
231
- getBuildWatchedApps() {
232
- return [...this.bootstrapSources].filter(([name]) => this.buildService?.isWatching(name))
233
- .map(([name, source]) => ({ name, directory: path.dirname(source.path) }));
234
+ getWatchedApps() {
235
+ const registrations = [...(this.fileWatcher?.getWatchedApps() ?? []),
236
+ ...[...this.bootstrapSources].filter(([name]) => this.buildService?.isWatching(name))
237
+ .map(([name, source]) => ({ name, directory: path.dirname(source.path) }))];
238
+ return registrations.flatMap(watch => {
239
+ const handle = this.handles.get(watch.name);
240
+ return handle ? [{ ...watch, generation: handle.generation, definitionRevision: handle.definitionRevision }] : [];
241
+ });
242
+ }
243
+ /** Native subscriptions follow the same owned handles and policy as esbuild. */
244
+ syncClassicWatches() {
245
+ if (!this.devMode || this.watchDisabled || this.stoppingApps || !this.config) {
246
+ this.fileWatcher?.stop();
247
+ this.fileWatcher = null;
248
+ return;
249
+ }
250
+ const apps = [...this.handles.values()].filter(handle => {
251
+ if (handle.entry.bootstrap || !this.allowsWatch(handle.entry) || this.executionBusy(handle.name))
252
+ return false;
253
+ if (handle.status === 'online' && !this.appStopIntents.get(handle.name)?.stopped)
254
+ return true;
255
+ // An internal restart keeps its existing source subscription and pending
256
+ // edits. Re-arming fs.watch on every child generation loses macOS events.
257
+ return !['crashed', 'errored'].includes(handle.status) &&
258
+ Boolean(this.restartCoalescer.get(handle.name)?.inFlight) && this.fileWatcher?.isWatching(handle.entry);
259
+ }).map(handle => handle.entry);
260
+ const config = { ...this.config, apps };
261
+ if (this.fileWatcher)
262
+ this.fileWatcher.applyConfig(config);
263
+ else {
264
+ this.fileWatcher = new FileWatcher(this.logger, this, config, this.cwd);
265
+ this.fileWatcher.start();
266
+ }
234
267
  }
235
268
  async syncBootstrapWatch(name) {
236
269
  const source = this.bootstrapSources.get(name);
@@ -254,12 +287,42 @@ export class OrchestratorService extends EventEmitter {
254
287
  }, this.devMode);
255
288
  }
256
289
  /** Automatic triggers remain revocable while queued; manual restart is independent. */
257
- async restartAfterChange(name) {
290
+ async restartAfterChange(name, expected) {
258
291
  const canonical = this.resolveAppName(name) ?? name;
292
+ if (expected && canonical !== name)
293
+ throw Errors.badRequest(`Source refresh requires the observed canonical application name '${canonical}'`);
259
294
  const handle = this.handles.get(canonical);
260
- if (!handle || !this.allowsWatch(handle.entry))
261
- return handle;
262
- return this.restartAppCoalesced(canonical, true, 'watch');
295
+ if (expected && (!handle || handle.generation !== expected.generation || handle.definitionRevision !== expected.definitionRevision))
296
+ throw Errors.conflict(`Application '${canonical}' source binding changed; observe its watch status before retrying`);
297
+ if (!handle || !this.allowsWatch(handle.entry)) {
298
+ if (expected)
299
+ throw Errors.conflict(`Source refresh of '${canonical}' is excluded by the current watch policy`);
300
+ return undefined;
301
+ }
302
+ if (expected && !this.getWatchedApps().some(app => app.name === canonical &&
303
+ app.generation === expected.generation && app.definitionRevision === expected.definitionRevision))
304
+ throw Errors.conflict(`Source watcher for '${canonical}' is unavailable; SDK refresh was not started`);
305
+ const entry = handle.entry;
306
+ const definitionRevision = handle.definitionRevision;
307
+ const generation = handle.generation;
308
+ const result = await this.restartAppCoalesced(canonical, true, 'watch');
309
+ if (handle.definitionRevision !== definitionRevision || result.entry !== entry ||
310
+ result.generation === generation || result.status !== 'online') {
311
+ if (expected)
312
+ throw Errors.conflict(`Source refresh of '${canonical}' was cancelled or its source binding changed`);
313
+ return undefined;
314
+ }
315
+ const source = this.getWatchedApps().find(app => app.name === canonical &&
316
+ app.generation === result.generation && app.definitionRevision === result.definitionRevision);
317
+ if (expected && !source)
318
+ throw Errors.conflict(`Source watcher for '${canonical}' is unavailable after restart; SDK readiness is not confirmed`);
319
+ const process = this.getApp(canonical);
320
+ if (!source || !process || process.status !== 'online' || process.generation !== source.generation) {
321
+ if (expected)
322
+ throw Errors.conflict(`Source refresh of '${canonical}' has no matching online observation`);
323
+ return undefined;
324
+ }
325
+ return { process, source };
263
326
  }
264
327
  /** Cached build results per app name */
265
328
  buildResults = new Map();
@@ -411,6 +474,7 @@ export class OrchestratorService extends EventEmitter {
411
474
  */
412
475
  setConfig(config) {
413
476
  this.config = config;
477
+ this.syncClassicWatches();
414
478
  // Metrics polling is armed here rather than in `startAll` alone.
415
479
  //
416
480
  // It used to run only from `startAll`, which is the `omnitron start`
@@ -777,6 +841,7 @@ export class OrchestratorService extends EventEmitter {
777
841
  throw new Error(`Cannot replace '${key}' with '${entry.name}': the previous application did not stop`, { cause: err });
778
842
  }
779
843
  this.handles.delete(key);
844
+ this.syncClassicWatches();
780
845
  if (key !== entry.name)
781
846
  this.metricsBridge?.evictApp(key);
782
847
  continue;
@@ -794,6 +859,7 @@ export class OrchestratorService extends EventEmitter {
794
859
  // processes still run: an errored app's other children and its pools.
795
860
  await this.tearDownApp(h);
796
861
  this.handles.delete(key);
862
+ this.syncClassicWatches();
797
863
  // Drop any metrics that were collected under the stale alias so it
798
864
  // doesn't haunt future snapshots as a ghost offline app.
799
865
  if (key !== entry.name)
@@ -830,6 +896,7 @@ export class OrchestratorService extends EventEmitter {
830
896
  handle.restartWindow = existing.restartWindow;
831
897
  }
832
898
  this.handles.set(entry.name, handle);
899
+ this.syncClassicWatches();
833
900
  // Arm metrics sampling here — the one place an app enters the registry.
834
901
  //
835
902
  // It used to be armed only from `startAll` (the `omnitron start` path).
@@ -902,6 +969,9 @@ export class OrchestratorService extends EventEmitter {
902
969
  this.scheduleRecovery(entry, handle, cfg);
903
970
  throw failure;
904
971
  }
972
+ finally {
973
+ this.syncClassicWatches();
974
+ }
905
975
  }
906
976
  /**
907
977
  * Everything a handle still runs, stopped: its supervisor's children (or its
@@ -992,8 +1062,12 @@ export class OrchestratorService extends EventEmitter {
992
1062
  return active.promise;
993
1063
  this.assertExecutionIdle(scope);
994
1064
  // Reserve before invoking work, including its synchronous checks and first write.
995
- const promise = Promise.resolve().then(work).finally(() => this.executionOperations.delete(key));
1065
+ const promise = Promise.resolve().then(work).finally(() => {
1066
+ this.executionOperations.delete(key);
1067
+ this.syncClassicWatches();
1068
+ });
996
1069
  this.executionOperations.set(key, { id: operationId, fingerprint, promise });
1070
+ this.syncClassicWatches();
997
1071
  return promise;
998
1072
  }
999
1073
  /**
@@ -1068,6 +1142,7 @@ export class OrchestratorService extends EventEmitter {
1068
1142
  }
1069
1143
  }
1070
1144
  this.persistState();
1145
+ this.syncClassicWatches();
1071
1146
  for (const name of retired) {
1072
1147
  this.emit('app:retired', name);
1073
1148
  this.metricsBridge?.evictApp(name);
@@ -1351,7 +1426,12 @@ export class OrchestratorService extends EventEmitter {
1351
1426
  }
1352
1427
  }
1353
1428
  async stopApp(name, force = false, timeout = 10_000) {
1429
+ return this.stopAppQueued(name, force, timeout);
1430
+ }
1431
+ async stopAppQueued(name, force = false, timeout = 10_000, preserveWatch = false) {
1354
1432
  const canonical = this.resolveAppName(name) ?? name;
1433
+ if (!preserveWatch)
1434
+ this.fileWatcher?.removeApp(canonical);
1355
1435
  // Outside the queue on purpose: the operator's intent lands the
1356
1436
  // moment the command arrives, not whenever the queue drains.
1357
1437
  // Unknown names need no retained intent. Start admission registers its
@@ -1388,6 +1468,7 @@ export class OrchestratorService extends EventEmitter {
1388
1468
  this.clearCoolDown(name);
1389
1469
  const operation = Promise.resolve().then(() => this.stopAllOnce(force));
1390
1470
  this.stoppingApps = operation;
1471
+ this.syncClassicWatches();
1391
1472
  const settled = () => { if (this.stoppingApps === operation)
1392
1473
  this.stoppingApps = null; };
1393
1474
  void operation.then(settled, settled);
@@ -1482,11 +1563,13 @@ export class OrchestratorService extends EventEmitter {
1482
1563
  throw new Error('An installed stack start is active; its application entry cannot be changed');
1483
1564
  }
1484
1565
  handle.redefine(entry);
1485
- if (!this.allowsWatch(entry)) {
1486
- const state = this.restartCoalescer.get(handle.name);
1487
- if (state)
1488
- state.watchSerial = 0;
1489
- }
1566
+ this.fileWatcher?.revokePending(handle.name);
1567
+ // A pending source event belongs to the previous definition, even when
1568
+ // the replacement also enables watching or restores the original path.
1569
+ const state = this.restartCoalescer.get(handle.name);
1570
+ if (state)
1571
+ state.watchSerial = 0;
1572
+ this.syncClassicWatches();
1490
1573
  await this.syncBootstrapWatch(handle.name);
1491
1574
  return true;
1492
1575
  }
@@ -1527,6 +1610,10 @@ export class OrchestratorService extends EventEmitter {
1527
1610
  const canonical = this.resolveAppName(name) ?? name;
1528
1611
  const handle = this.handles.get(canonical);
1529
1612
  if (!handle) {
1613
+ // A queued source event cannot resurrect a registration removed while
1614
+ // awaiting a cooldown or another lifecycle operation.
1615
+ if (!fromExternal || cause === 'watch')
1616
+ throw new Error(`Application '${canonical}' was removed before restart`);
1530
1617
  // A PROJECT-QUALIFIED name with no live handle is not this daemon's to
1531
1618
  // start, and matching it against the daemon's own config starts the
1532
1619
  // WRONG APP.
@@ -1562,12 +1649,17 @@ export class OrchestratorService extends EventEmitter {
1562
1649
  const state = this.getCoalescerState(name);
1563
1650
  if (fromExternal) {
1564
1651
  state.triggerSerial += 1;
1565
- if (cause === 'watch')
1652
+ if (cause === 'watch') {
1566
1653
  state.watchSerial = state.triggerSerial;
1654
+ state.watchBinding = { handle, entry: handle.entry, definitionRevision: handle.definitionRevision };
1655
+ }
1567
1656
  else
1568
1657
  state.manualSerial = state.triggerSerial;
1569
1658
  }
1570
- if (!this.allowsWatch(handle.entry) || ['errored', 'crashed', 'stopped', 'stopping'].includes(handle.status)) {
1659
+ if (!this.allowsWatch(handle.entry) || ['errored', 'crashed'].includes(handle.status) ||
1660
+ (!state.inFlight && ['stopped', 'stopping'].includes(handle.status)) ||
1661
+ !state.watchBinding || state.watchBinding.entry !== handle.entry ||
1662
+ state.watchBinding.handle.definitionRevision !== state.watchBinding.definitionRevision) {
1571
1663
  state.watchSerial = 0;
1572
1664
  }
1573
1665
  const observedSerial = Math.max(state.manualSerial, state.watchSerial);
@@ -1669,7 +1761,7 @@ export class OrchestratorService extends EventEmitter {
1669
1761
  if (this.devMode && entry.bootstrap) {
1670
1762
  clearCacheFor(path.resolve(entry.cwd ?? this.cwd, entry.bootstrap));
1671
1763
  }
1672
- const stopped = this.stopApp(name);
1764
+ const stopped = this.stopAppQueued(name, false, 10_000, true);
1673
1765
  const intent = this.appStopIntents.get(name);
1674
1766
  const generation = this.stopGeneration;
1675
1767
  await stopped;
@@ -1684,7 +1776,7 @@ export class OrchestratorService extends EventEmitter {
1684
1776
  getCoalescerState(name) {
1685
1777
  let state = this.restartCoalescer.get(name);
1686
1778
  if (!state) {
1687
- state = { inFlight: null, triggerSerial: 0, firedSerial: 0, manualSerial: 0, watchSerial: 0, cooldownUntil: 0 };
1779
+ state = { inFlight: null, triggerSerial: 0, firedSerial: 0, manualSerial: 0, watchSerial: 0, watchBinding: null, cooldownUntil: 0 };
1688
1780
  this.restartCoalescer.set(name, state);
1689
1781
  }
1690
1782
  return state;
@@ -2134,6 +2226,7 @@ export class OrchestratorService extends EventEmitter {
2134
2226
  this.scheduleRecovery(entry, handle, config);
2135
2227
  }
2136
2228
  this.persistState();
2229
+ this.syncClassicWatches();
2137
2230
  });
2138
2231
  return launch;
2139
2232
  }
@@ -2158,7 +2251,7 @@ export class OrchestratorService extends EventEmitter {
2158
2251
  let topology;
2159
2252
  let definition;
2160
2253
  try {
2161
- const captured = await readBootstrapMetadata(bootstrapAbsPath, this.devMode && !entry.releaseRoot, 60_000);
2254
+ const captured = await readBootstrapMetadata(bootstrapAbsPath, this.devMode && !entry.releaseRoot, 60_000, entry.releaseRoot);
2162
2255
  definition = captured.definition;
2163
2256
  handle.bootstrapMetadata = captured.metadata;
2164
2257
  topology = definition.processes;
@@ -2251,6 +2344,7 @@ export class OrchestratorService extends EventEmitter {
2251
2344
  return launch;
2252
2345
  }
2253
2346
  async discardSourceBuild(name) {
2347
+ this.fileWatcher?.removeApp(name);
2254
2348
  const state = this.restartCoalescer.get(name);
2255
2349
  if (state)
2256
2350
  state.watchSerial = 0;
@@ -2310,7 +2404,8 @@ export class OrchestratorService extends EventEmitter {
2310
2404
  // application generation. Resolve before allocating topology resources.
2311
2405
  const runtime = await this.bootstrapRuntime(bootstrapAbsPath);
2312
2406
  const policy = buildRestartPolicy(entry, config);
2313
- const spawnEnv = withClosureLibraryPath(entry.env, [entry.releaseRoot, entry.cwd, bootstrapAbsPath]);
2407
+ const spawnEnv = withClosureLibraryPath(entry.env, entry.releaseRoot
2408
+ ? { verifiedRoot: entry.releaseRoot } : [entry.cwd, bootstrapAbsPath]);
2314
2409
  const needsRouting = topology.some(proc => proc.topology?.expose === true || proc.topology?.access?.length);
2315
2410
  handle.deferStartup();
2316
2411
  if (needsRouting) {
@@ -2552,7 +2647,8 @@ export class OrchestratorService extends EventEmitter {
2552
2647
  async launchSingleProcess(entry, handle, config, bootstrapAbsPath, buildResult) {
2553
2648
  const instances = entry.instances ?? 1;
2554
2649
  const policy = buildRestartPolicy(entry, config);
2555
- const spawnEnv = withClosureLibraryPath(entry.env, [entry.releaseRoot, entry.cwd, bootstrapAbsPath]);
2650
+ const spawnEnv = withClosureLibraryPath(entry.env, entry.releaseRoot
2651
+ ? { verifiedRoot: entry.releaseRoot } : [entry.cwd, bootstrapAbsPath]);
2556
2652
  // For single-process apps, use the first (only) process entry's bundled module
2557
2653
  const firstProcessName = buildResult?.modulePaths.keys().next().value;
2558
2654
  const bundledModulePath = firstProcessName
@@ -2672,6 +2768,7 @@ export class OrchestratorService extends EventEmitter {
2672
2768
  handle.clearLastExit();
2673
2769
  this.startPostOnlineCooldown(name);
2674
2770
  this.persistState();
2771
+ this.syncClassicWatches();
2675
2772
  this.emit('app:online', name);
2676
2773
  }
2677
2774
  /**