lorenz 0.1.4 → 0.1.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 (249) hide show
  1. package/README.md +83 -20
  2. package/RELEASE-MANIFEST.json +6 -1
  3. package/node_modules/@lorenz/agent-sdk/dist/index.d.ts +1 -0
  4. package/node_modules/@lorenz/agent-sdk/dist/index.d.ts.map +1 -1
  5. package/node_modules/@lorenz/agent-sdk/dist/index.js +1 -0
  6. package/node_modules/@lorenz/agent-sdk/dist/index.js.map +1 -1
  7. package/node_modules/@lorenz/agent-sdk/dist/module.d.ts +38 -0
  8. package/node_modules/@lorenz/agent-sdk/dist/module.d.ts.map +1 -0
  9. package/node_modules/@lorenz/agent-sdk/dist/module.js +41 -0
  10. package/node_modules/@lorenz/agent-sdk/dist/module.js.map +1 -0
  11. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.d.ts +30 -0
  12. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.d.ts.map +1 -0
  13. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.js +63 -0
  14. package/node_modules/@lorenz/cli/dist/agentExecutorLoader.js.map +1 -0
  15. package/node_modules/@lorenz/cli/dist/daemon.d.ts +42 -19
  16. package/node_modules/@lorenz/cli/dist/daemon.d.ts.map +1 -1
  17. package/node_modules/@lorenz/cli/dist/daemon.js +72 -23
  18. package/node_modules/@lorenz/cli/dist/daemon.js.map +1 -1
  19. package/node_modules/@lorenz/cli/dist/daemonLock.d.ts +59 -0
  20. package/node_modules/@lorenz/cli/dist/daemonLock.d.ts.map +1 -0
  21. package/node_modules/@lorenz/cli/dist/daemonLock.js +304 -0
  22. package/node_modules/@lorenz/cli/dist/daemonLock.js.map +1 -0
  23. package/node_modules/@lorenz/cli/dist/daemonStatus.d.ts +16 -0
  24. package/node_modules/@lorenz/cli/dist/daemonStatus.d.ts.map +1 -0
  25. package/node_modules/@lorenz/cli/dist/daemonStatus.js +21 -0
  26. package/node_modules/@lorenz/cli/dist/daemonStatus.js.map +1 -0
  27. package/node_modules/@lorenz/cli/dist/doctor.d.ts +6 -0
  28. package/node_modules/@lorenz/cli/dist/doctor.d.ts.map +1 -1
  29. package/node_modules/@lorenz/cli/dist/doctor.js +39 -2
  30. package/node_modules/@lorenz/cli/dist/doctor.js.map +1 -1
  31. package/node_modules/@lorenz/cli/dist/extensionLoader.d.ts +126 -0
  32. package/node_modules/@lorenz/cli/dist/extensionLoader.d.ts.map +1 -0
  33. package/node_modules/@lorenz/cli/dist/extensionLoader.js +187 -0
  34. package/node_modules/@lorenz/cli/dist/extensionLoader.js.map +1 -0
  35. package/node_modules/@lorenz/cli/dist/flags-manifest.d.ts +42 -0
  36. package/node_modules/@lorenz/cli/dist/flags-manifest.d.ts.map +1 -0
  37. package/node_modules/@lorenz/cli/dist/flags-manifest.js +67 -0
  38. package/node_modules/@lorenz/cli/dist/flags-manifest.js.map +1 -0
  39. package/node_modules/@lorenz/cli/dist/index.d.ts +6 -0
  40. package/node_modules/@lorenz/cli/dist/index.d.ts.map +1 -1
  41. package/node_modules/@lorenz/cli/dist/index.js +4 -0
  42. package/node_modules/@lorenz/cli/dist/index.js.map +1 -1
  43. package/node_modules/@lorenz/cli/dist/leadershipStore.d.ts +42 -0
  44. package/node_modules/@lorenz/cli/dist/leadershipStore.d.ts.map +1 -0
  45. package/node_modules/@lorenz/cli/dist/leadershipStore.js +2 -0
  46. package/node_modules/@lorenz/cli/dist/leadershipStore.js.map +1 -0
  47. package/node_modules/@lorenz/cli/dist/main.d.ts +11 -7
  48. package/node_modules/@lorenz/cli/dist/main.d.ts.map +1 -1
  49. package/node_modules/@lorenz/cli/dist/main.js +58 -8
  50. package/node_modules/@lorenz/cli/dist/main.js.map +1 -1
  51. package/node_modules/@lorenz/cli/dist/toolLoader.d.ts +28 -0
  52. package/node_modules/@lorenz/cli/dist/toolLoader.d.ts.map +1 -0
  53. package/node_modules/@lorenz/cli/dist/toolLoader.js +62 -0
  54. package/node_modules/@lorenz/cli/dist/toolLoader.js.map +1 -0
  55. package/node_modules/@lorenz/cli/dist/trackerLoader.d.ts +24 -0
  56. package/node_modules/@lorenz/cli/dist/trackerLoader.d.ts.map +1 -0
  57. package/node_modules/@lorenz/cli/dist/trackerLoader.js +34 -0
  58. package/node_modules/@lorenz/cli/dist/trackerLoader.js.map +1 -0
  59. package/node_modules/@lorenz/cli/dist/workerDriverLoader.d.ts +15 -55
  60. package/node_modules/@lorenz/cli/dist/workerDriverLoader.d.ts.map +1 -1
  61. package/node_modules/@lorenz/cli/dist/workerDriverLoader.js +26 -203
  62. package/node_modules/@lorenz/cli/dist/workerDriverLoader.js.map +1 -1
  63. package/node_modules/@lorenz/cli/package.json +1 -0
  64. package/node_modules/@lorenz/config/dist/index.d.ts +1 -1
  65. package/node_modules/@lorenz/config/dist/index.d.ts.map +1 -1
  66. package/node_modules/@lorenz/config/dist/index.js +1 -1
  67. package/node_modules/@lorenz/config/dist/index.js.map +1 -1
  68. package/node_modules/@lorenz/config/dist/parse.d.ts +17 -0
  69. package/node_modules/@lorenz/config/dist/parse.d.ts.map +1 -1
  70. package/node_modules/@lorenz/config/dist/parse.js +107 -11
  71. package/node_modules/@lorenz/config/dist/parse.js.map +1 -1
  72. package/node_modules/@lorenz/config/dist/schemas.d.ts +0 -2
  73. package/node_modules/@lorenz/config/dist/schemas.d.ts.map +1 -1
  74. package/node_modules/@lorenz/config/dist/schemas.js +5 -1
  75. package/node_modules/@lorenz/config/dist/schemas.js.map +1 -1
  76. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.d.ts +55 -21
  77. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.d.ts.map +1 -1
  78. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.js +187 -82
  79. package/node_modules/@lorenz/dispatch-coordinator/dist/coordinator.js.map +1 -1
  80. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.d.ts +6 -4
  81. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.d.ts.map +1 -1
  82. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.js +9 -6
  83. package/node_modules/@lorenz/dispatch-coordinator/dist/gate.js.map +1 -1
  84. package/node_modules/@lorenz/dispatch-coordinator/dist/index.d.ts +1 -1
  85. package/node_modules/@lorenz/dispatch-coordinator/dist/index.d.ts.map +1 -1
  86. package/node_modules/@lorenz/dispatch-coordinator/dist/index.js +5 -6
  87. package/node_modules/@lorenz/dispatch-coordinator/dist/index.js.map +1 -1
  88. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.d.ts +7 -5
  89. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.d.ts.map +1 -1
  90. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.js +12 -10
  91. package/node_modules/@lorenz/dispatch-coordinator/dist/mcpEndpointManager.js.map +1 -1
  92. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.d.ts +11 -10
  93. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.d.ts.map +1 -1
  94. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.js +15 -22
  95. package/node_modules/@lorenz/dispatch-coordinator/dist/nullEndpointManager.js.map +1 -1
  96. package/node_modules/@lorenz/dispatch-coordinator/dist/types.d.ts +16 -15
  97. package/node_modules/@lorenz/dispatch-coordinator/dist/types.d.ts.map +1 -1
  98. package/node_modules/@lorenz/dispatch-coordinator/dist/types.js +6 -7
  99. package/node_modules/@lorenz/dispatch-coordinator/dist/types.js.map +1 -1
  100. package/node_modules/@lorenz/domain/dist/index.d.ts +75 -9
  101. package/node_modules/@lorenz/domain/dist/index.d.ts.map +1 -1
  102. package/node_modules/@lorenz/domain/dist/index.js +40 -0
  103. package/node_modules/@lorenz/domain/dist/index.js.map +1 -1
  104. package/node_modules/@lorenz/flags/dist/coerce.d.ts +12 -0
  105. package/node_modules/@lorenz/flags/dist/coerce.d.ts.map +1 -0
  106. package/node_modules/@lorenz/flags/dist/coerce.js +44 -0
  107. package/node_modules/@lorenz/flags/dist/coerce.js.map +1 -0
  108. package/node_modules/@lorenz/flags/dist/default.d.ts +6 -0
  109. package/node_modules/@lorenz/flags/dist/default.d.ts.map +1 -0
  110. package/node_modules/@lorenz/flags/dist/default.js +22 -0
  111. package/node_modules/@lorenz/flags/dist/default.js.map +1 -0
  112. package/node_modules/@lorenz/flags/dist/deprecations.d.ts +20 -0
  113. package/node_modules/@lorenz/flags/dist/deprecations.d.ts.map +1 -0
  114. package/node_modules/@lorenz/flags/dist/deprecations.js +42 -0
  115. package/node_modules/@lorenz/flags/dist/deprecations.js.map +1 -0
  116. package/node_modules/@lorenz/flags/dist/env.d.ts +17 -0
  117. package/node_modules/@lorenz/flags/dist/env.d.ts.map +1 -0
  118. package/node_modules/@lorenz/flags/dist/env.js +90 -0
  119. package/node_modules/@lorenz/flags/dist/env.js.map +1 -0
  120. package/node_modules/@lorenz/flags/dist/errors.d.ts +22 -0
  121. package/node_modules/@lorenz/flags/dist/errors.d.ts.map +1 -0
  122. package/node_modules/@lorenz/flags/dist/errors.js +61 -0
  123. package/node_modules/@lorenz/flags/dist/errors.js.map +1 -0
  124. package/node_modules/@lorenz/flags/dist/index.d.ts +8 -0
  125. package/node_modules/@lorenz/flags/dist/index.d.ts.map +1 -0
  126. package/node_modules/@lorenz/flags/dist/index.js +11 -0
  127. package/node_modules/@lorenz/flags/dist/index.js.map +1 -0
  128. package/node_modules/@lorenz/flags/dist/keys.d.ts +6 -0
  129. package/node_modules/@lorenz/flags/dist/keys.d.ts.map +1 -0
  130. package/node_modules/@lorenz/flags/dist/keys.js +15 -0
  131. package/node_modules/@lorenz/flags/dist/keys.js.map +1 -0
  132. package/node_modules/@lorenz/flags/dist/layers.d.ts +14 -0
  133. package/node_modules/@lorenz/flags/dist/layers.d.ts.map +1 -0
  134. package/node_modules/@lorenz/flags/dist/layers.js +107 -0
  135. package/node_modules/@lorenz/flags/dist/layers.js.map +1 -0
  136. package/node_modules/@lorenz/flags/dist/manifest.d.ts +71 -0
  137. package/node_modules/@lorenz/flags/dist/manifest.d.ts.map +1 -0
  138. package/node_modules/@lorenz/flags/dist/manifest.js +137 -0
  139. package/node_modules/@lorenz/flags/dist/manifest.js.map +1 -0
  140. package/node_modules/@lorenz/flags/dist/resolve.d.ts +8 -0
  141. package/node_modules/@lorenz/flags/dist/resolve.d.ts.map +1 -0
  142. package/node_modules/@lorenz/flags/dist/resolve.js +178 -0
  143. package/node_modules/@lorenz/flags/dist/resolve.js.map +1 -0
  144. package/node_modules/@lorenz/flags/dist/testing.d.ts +19 -0
  145. package/node_modules/@lorenz/flags/dist/testing.d.ts.map +1 -0
  146. package/node_modules/@lorenz/flags/dist/testing.js +68 -0
  147. package/node_modules/@lorenz/flags/dist/testing.js.map +1 -0
  148. package/node_modules/@lorenz/flags/dist/types.d.ts +93 -0
  149. package/node_modules/@lorenz/flags/dist/types.d.ts.map +1 -0
  150. package/node_modules/@lorenz/flags/dist/types.js +2 -0
  151. package/node_modules/@lorenz/flags/dist/types.js.map +1 -0
  152. package/node_modules/@lorenz/flags/package.json +16 -0
  153. package/node_modules/@lorenz/mcp/dist/agentEndpoint.d.ts +16 -3
  154. package/node_modules/@lorenz/mcp/dist/agentEndpoint.d.ts.map +1 -1
  155. package/node_modules/@lorenz/mcp/dist/agentEndpoint.js +105 -17
  156. package/node_modules/@lorenz/mcp/dist/agentEndpoint.js.map +1 -1
  157. package/node_modules/@lorenz/mcp/dist/auth.d.ts +88 -0
  158. package/node_modules/@lorenz/mcp/dist/auth.d.ts.map +1 -1
  159. package/node_modules/@lorenz/mcp/dist/auth.js +53 -0
  160. package/node_modules/@lorenz/mcp/dist/auth.js.map +1 -1
  161. package/node_modules/@lorenz/mcp/dist/index.d.ts +3 -2
  162. package/node_modules/@lorenz/mcp/dist/index.d.ts.map +1 -1
  163. package/node_modules/@lorenz/mcp/dist/index.js +1 -1
  164. package/node_modules/@lorenz/mcp/dist/index.js.map +1 -1
  165. package/node_modules/@lorenz/mcp/dist/server.d.ts +22 -0
  166. package/node_modules/@lorenz/mcp/dist/server.d.ts.map +1 -1
  167. package/node_modules/@lorenz/mcp/dist/server.js +85 -12
  168. package/node_modules/@lorenz/mcp/dist/server.js.map +1 -1
  169. package/node_modules/@lorenz/orchestrator/dist/claimStore.d.ts +157 -0
  170. package/node_modules/@lorenz/orchestrator/dist/claimStore.d.ts.map +1 -0
  171. package/node_modules/@lorenz/orchestrator/dist/claimStore.js +621 -0
  172. package/node_modules/@lorenz/orchestrator/dist/claimStore.js.map +1 -0
  173. package/node_modules/@lorenz/orchestrator/dist/codec.d.ts +38 -0
  174. package/node_modules/@lorenz/orchestrator/dist/codec.d.ts.map +1 -0
  175. package/node_modules/@lorenz/orchestrator/dist/codec.js +176 -0
  176. package/node_modules/@lorenz/orchestrator/dist/codec.js.map +1 -0
  177. package/node_modules/@lorenz/orchestrator/dist/index.d.ts +55 -51
  178. package/node_modules/@lorenz/orchestrator/dist/index.d.ts.map +1 -1
  179. package/node_modules/@lorenz/orchestrator/dist/index.js +285 -45
  180. package/node_modules/@lorenz/orchestrator/dist/index.js.map +1 -1
  181. package/node_modules/@lorenz/orchestrator/dist/sqlite.d.ts +34 -0
  182. package/node_modules/@lorenz/orchestrator/dist/sqlite.d.ts.map +1 -0
  183. package/node_modules/@lorenz/orchestrator/dist/sqlite.js +142 -0
  184. package/node_modules/@lorenz/orchestrator/dist/sqlite.js.map +1 -0
  185. package/node_modules/@lorenz/orchestrator/dist/state.d.ts +47 -0
  186. package/node_modules/@lorenz/orchestrator/dist/state.d.ts.map +1 -0
  187. package/node_modules/@lorenz/orchestrator/dist/state.js +15 -0
  188. package/node_modules/@lorenz/orchestrator/dist/state.js.map +1 -0
  189. package/node_modules/@lorenz/orchestrator/dist/turso.d.ts +28 -0
  190. package/node_modules/@lorenz/orchestrator/dist/turso.d.ts.map +1 -0
  191. package/node_modules/@lorenz/orchestrator/dist/turso.js +125 -0
  192. package/node_modules/@lorenz/orchestrator/dist/turso.js.map +1 -0
  193. package/node_modules/@lorenz/orchestrator/package.json +6 -2
  194. package/node_modules/@lorenz/presenter/dist/index.d.ts +14 -0
  195. package/node_modules/@lorenz/presenter/dist/index.d.ts.map +1 -1
  196. package/node_modules/@lorenz/presenter/dist/index.js +18 -0
  197. package/node_modules/@lorenz/presenter/dist/index.js.map +1 -1
  198. package/node_modules/@lorenz/projections/dist/index.d.ts.map +1 -1
  199. package/node_modules/@lorenz/projections/dist/index.js +1 -0
  200. package/node_modules/@lorenz/projections/dist/index.js.map +1 -1
  201. package/node_modules/@lorenz/runtime/dist/index.d.ts +27 -8
  202. package/node_modules/@lorenz/runtime/dist/index.d.ts.map +1 -1
  203. package/node_modules/@lorenz/runtime/dist/index.js +422 -98
  204. package/node_modules/@lorenz/runtime/dist/index.js.map +1 -1
  205. package/node_modules/@lorenz/runtime-events/dist/index.d.ts +14 -0
  206. package/node_modules/@lorenz/runtime-events/dist/index.d.ts.map +1 -1
  207. package/node_modules/@lorenz/server/dist/index.js +1 -1
  208. package/node_modules/@lorenz/server/dist/index.js.map +1 -1
  209. package/node_modules/@lorenz/ssh/dist/index.d.ts +2 -0
  210. package/node_modules/@lorenz/ssh/dist/index.d.ts.map +1 -1
  211. package/node_modules/@lorenz/ssh/dist/index.js +2 -1
  212. package/node_modules/@lorenz/ssh/dist/index.js.map +1 -1
  213. package/node_modules/@lorenz/tool-sdk/dist/index.d.ts +1 -0
  214. package/node_modules/@lorenz/tool-sdk/dist/index.d.ts.map +1 -1
  215. package/node_modules/@lorenz/tool-sdk/dist/index.js +1 -0
  216. package/node_modules/@lorenz/tool-sdk/dist/index.js.map +1 -1
  217. package/node_modules/@lorenz/tool-sdk/dist/module.d.ts +38 -0
  218. package/node_modules/@lorenz/tool-sdk/dist/module.d.ts.map +1 -0
  219. package/node_modules/@lorenz/tool-sdk/dist/module.js +42 -0
  220. package/node_modules/@lorenz/tool-sdk/dist/module.js.map +1 -0
  221. package/node_modules/@lorenz/tracker-sdk/dist/index.d.ts +1 -0
  222. package/node_modules/@lorenz/tracker-sdk/dist/index.d.ts.map +1 -1
  223. package/node_modules/@lorenz/tracker-sdk/dist/index.js +1 -0
  224. package/node_modules/@lorenz/tracker-sdk/dist/index.js.map +1 -1
  225. package/node_modules/@lorenz/tracker-sdk/dist/module.d.ts +37 -0
  226. package/node_modules/@lorenz/tracker-sdk/dist/module.d.ts.map +1 -0
  227. package/node_modules/@lorenz/tracker-sdk/dist/module.js +38 -0
  228. package/node_modules/@lorenz/tracker-sdk/dist/module.js.map +1 -0
  229. package/node_modules/@lorenz/worker-host-pool/dist/index.d.ts +34 -6
  230. package/node_modules/@lorenz/worker-host-pool/dist/index.d.ts.map +1 -1
  231. package/node_modules/@lorenz/worker-host-pool/dist/index.js +110 -143
  232. package/node_modules/@lorenz/worker-host-pool/dist/index.js.map +1 -1
  233. package/node_modules/@lorenz/worker-sdk/dist/index.d.ts +1 -0
  234. package/node_modules/@lorenz/worker-sdk/dist/index.d.ts.map +1 -1
  235. package/node_modules/@lorenz/worker-sdk/dist/index.js +1 -0
  236. package/node_modules/@lorenz/worker-sdk/dist/index.js.map +1 -1
  237. package/node_modules/@lorenz/worker-sdk/dist/local.d.ts +74 -0
  238. package/node_modules/@lorenz/worker-sdk/dist/local.d.ts.map +1 -0
  239. package/node_modules/@lorenz/worker-sdk/dist/local.js +112 -0
  240. package/node_modules/@lorenz/worker-sdk/dist/local.js.map +1 -0
  241. package/node_modules/@lorenz/worker-sdk/dist/module.d.ts +8 -16
  242. package/node_modules/@lorenz/worker-sdk/dist/module.d.ts.map +1 -1
  243. package/node_modules/@lorenz/worker-sdk/dist/module.js +15 -35
  244. package/node_modules/@lorenz/worker-sdk/dist/module.js.map +1 -1
  245. package/node_modules/@lorenz/workflow/dist/index.d.ts +11 -0
  246. package/node_modules/@lorenz/workflow/dist/index.d.ts.map +1 -1
  247. package/node_modules/@lorenz/workflow/dist/index.js +3 -0
  248. package/node_modules/@lorenz/workflow/dist/index.js.map +1 -1
  249. package/package.json +4 -1
@@ -1,64 +1,24 @@
1
1
  import { type WorkerDriverRegistry } from "@lorenz/worker-sdk";
2
+ import { type EnsureExtensionLoadedOptions, type ExtensionRef } from "./extensionLoader.js";
2
3
  /**
3
- * Out-of-tree worker-driver loading: the configured worker-pool driver accepts a MODULE
4
- * SPECIFIER (an npm package name, `@scope/name`, `./relative` or `/absolute`
5
- * path, with an optional `#exportName` suffix) in addition to a registered
6
- * kind. The daemon dynamic-imports the module at startup (and on a reload that
7
- * changes the specifier) and registers it into the worker-driver registry under
8
- * the EXACT configured string, so the pool's existing registry resolution
9
- * (`registry.require(settings.driver)`) needs no changes and third parties
10
- * ship drivers without forking the repo.
11
- *
12
- * Trust: a dynamic import runs arbitrary code in the daemon process - the same
13
- * trust boundary as workspace hooks. Loads happen ONLY here (startup/reload),
14
- * never on the acquire path, and the `worker_pool_driver_loaded` audit event
15
- * records exactly which code went live from where.
16
- *
17
- * Module pinning: Node's ESM cache loads a given specifier's code once per
18
- * daemon lifetime. Changing driver CODE requires a daemon restart; changing
19
- * the CONFIG to a different specifier hot-loads the new module. A reload that
20
- * re-encounters an already-loaded specifier emits
21
- * `worker_pool_driver_module_pinned` so the pin is observable, and cache-busting
22
- * query strings are rejected (unbounded module-graph growth, half-initialized
23
- * module hazards).
4
+ * Out-of-tree worker-driver loading: `worker.worker_pool.driver` accepts a module
5
+ * specifier in addition to a registered kind. Instantiates the axis-generic
6
+ * {@link createExtensionLoader}; identity field is the driver `kind`. See
7
+ * {@link createExtensionLoader} for the trust boundary, module pinning, and
8
+ * exact-kind-wins resolution shared by every axis.
24
9
  */
25
10
  /** A parsed configured worker-pool driver value that is not a registered kind. */
26
- export interface WorkerDriverRef {
27
- /** The module specifier with any `#exportName` suffix removed. */
28
- specifier: string;
29
- /** The named export selected by a `#name` suffix; undefined means default. */
30
- exportName?: string | undefined;
31
- }
32
- /**
33
- * Parses a configured driver string into its module-specifier form. Resolution
34
- * rule (the single authority for the one-field-two-grammars overload): an
35
- * EXACT registered kind always wins - {@link ensureWorkerDriverLoaded} checks
36
- * `registry.get(driver)` BEFORE calling this, so a published npm package named
37
- * `docker` can never shadow the built-in. A `#name` suffix selects a named
38
- * export; everything else is the specifier itself.
39
- */
40
- export declare function parseWorkerDriverRef(driver: string): WorkerDriverRef;
11
+ export type WorkerDriverRef = ExtensionRef;
41
12
  /** Options for {@link ensureWorkerDriverLoaded}. */
42
- export interface EnsureWorkerDriverLoadedOptions {
43
- /** Anchor for `./relative` specifiers; the daemon passes `dirname(workflow.path)`. */
44
- baseDir?: string | undefined;
45
- /** Structured-event sink for the loaded/pinned audit events. */
46
- logEvent?: ((event: Record<string, unknown>) => void) | undefined;
47
- }
13
+ export type EnsureWorkerDriverLoadedOptions = EnsureExtensionLoadedOptions;
14
+ /** Parses a configured driver string into its module-specifier form. */
15
+ export declare function parseWorkerDriverRef(driver: string): WorkerDriverRef;
48
16
  /**
49
- * Idempotently makes the configured worker-pool driver resolvable in
50
- * `registry`. A registry hit (a built-in kind, an extension, or a specifier a
51
- * previous call already loaded) is a no-op - except that a re-encountered
52
- * loader-registered specifier emits `worker_pool_driver_module_pinned` so the
53
- * code-is-pinned semantic is observable on reload. A miss parses the driver as
54
- * a module reference, dynamic-imports it, and registers a factory whose kind
55
- * IS the configured specifier string, emitting `worker_pool_driver_loaded`.
56
- *
57
- * Called by the daemon BEFORE `createWorkerPool` at startup and (via the
58
- * coordinator's injected `driverLoader`) BEFORE `pool.reconcile` on reload, so
59
- * the pool's registry resolution stays synchronous and transactional. A module
60
- * registered for a reconcile that later fails is harmless: the registry is a
61
- * catalog, and an unused entry is inert.
17
+ * Idempotently makes the configured worker-pool driver resolvable in `registry`
18
+ * (see {@link createExtensionLoader} for the load/pin semantics). Called by the
19
+ * daemon BEFORE `createWorkerPool` at startup and (via the coordinator's injected
20
+ * `driverLoader`) BEFORE `pool.reconcile` on reload, so the pool's registry
21
+ * resolution stays synchronous and transactional.
62
22
  */
63
23
  export declare function ensureWorkerDriverLoaded(driver: string, registry: WorkerDriverRegistry, options?: EnsureWorkerDriverLoadedOptions): Promise<void>;
64
24
  //# sourceMappingURL=workerDriverLoader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"workerDriverLoader.d.ts","sourceRoot":"","sources":["../src/workerDriverLoader.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,kFAAkF;AAClF,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CAsBpE;AAgLD,oDAAoD;AACpD,MAAM,WAAW,+BAA+B;IAC9C,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,gEAAgE;IAChE,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACnE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,IAAI,CAAC,CAoCf"}
1
+ {"version":3,"file":"workerDriverLoader.d.ts","sourceRoot":"","sources":["../src/workerDriverLoader.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAE9B;;;;;;GAMG;AAEH,kFAAkF;AAClF,MAAM,MAAM,eAAe,GAAG,YAAY,CAAC;AAE3C,oDAAoD;AACpD,MAAM,MAAM,+BAA+B,GAAG,4BAA4B,CAAC;AAmB3E,wEAAwE;AACxE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,CAEpE;AAED;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,oBAAoB,EAC9B,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,IAAI,CAAC,CAEf"}
@@ -1,211 +1,34 @@
1
- import path from "node:path";
2
- import { pathToFileURL } from "node:url";
1
+ import { isRecord } from "@lorenz/domain";
3
2
  import { assertWorkerDriverModule, } from "@lorenz/worker-sdk";
4
- /**
5
- * Parses a configured driver string into its module-specifier form. Resolution
6
- * rule (the single authority for the one-field-two-grammars overload): an
7
- * EXACT registered kind always wins - {@link ensureWorkerDriverLoaded} checks
8
- * `registry.get(driver)` BEFORE calling this, so a published npm package named
9
- * `docker` can never shadow the built-in. A `#name` suffix selects a named
10
- * export; everything else is the specifier itself.
11
- */
3
+ import { createExtensionLoader, } from "./extensionLoader.js";
4
+ const workerDriverLoader = createExtensionLoader({
5
+ errorPrefix: "worker_pool_driver",
6
+ eventNames: {
7
+ loaded: "worker_pool_driver_loaded",
8
+ pinned: "worker_pool_driver_module_pinned",
9
+ },
10
+ defineHelperName: "defineWorkerDriver",
11
+ unitNoun: "worker drivers",
12
+ assertModule: assertWorkerDriverModule,
13
+ looksLikeModule: (value) => isRecord(value) && typeof value["create"] === "function",
14
+ toFactory: (specifier, module) => ({
15
+ kind: specifier,
16
+ create: (driverOptions, deps) => module.create(driverOptions, deps),
17
+ }),
18
+ describeModule: (module) => ({ kind: module.kind, sdkVersion: module.sdkVersion }),
19
+ });
20
+ /** Parses a configured driver string into its module-specifier form. */
12
21
  export function parseWorkerDriverRef(driver) {
13
- const hashIndex = driver.lastIndexOf("#");
14
- const specifier = hashIndex === -1 ? driver : driver.slice(0, hashIndex);
15
- const exportName = hashIndex === -1 ? undefined : driver.slice(hashIndex + 1);
16
- if (specifier === "") {
17
- throw new Error(`worker_pool_driver_invalid_specifier: ${driver} has an empty module specifier`);
18
- }
19
- if (exportName === "") {
20
- throw new Error(`worker_pool_driver_invalid_specifier: ${driver} has an empty #exportName suffix`);
21
- }
22
- if (specifier.includes("?")) {
23
- throw new Error(`worker_pool_driver_invalid_specifier: ${specifier} - cache-busting query strings are not ` +
24
- `supported (module code is pinned for the daemon lifetime; restart the daemon to pick ` +
25
- `up driver code changes)`);
26
- }
27
- return { specifier, exportName };
28
- }
29
- /** Whether a specifier is a filesystem path (vs a bare npm package name). */
30
- function isPathSpecifier(specifier) {
31
- return (specifier.startsWith("./") ||
32
- specifier.startsWith("../") ||
33
- path.isAbsolute(specifier) ||
34
- specifier.startsWith("file:"));
35
- }
36
- /**
37
- * Dynamic-imports a worker-driver module and validates it. Relative and absolute
38
- * paths resolve against `baseDir` via `pathToFileURL`; bare names resolve
39
- * through the daemon's module graph (the operator installs the driver package
40
- * next to lorenz; `./path` is the escape hatch). The imported namespace is
41
- * unwrapped (`default`, the transpiled-CJS `default.default` shape, or the
42
- * selected named export) and passed through `assertWorkerDriverModule`, so a
43
- * malformed module or an SDK version mismatch fails loud here - before the
44
- * pool, the runtime, or any provision exists.
45
- */
46
- async function loadWorkerDriverModule(specifier, options) {
47
- const { baseDir, exportName, knownKinds } = options;
48
- const resolvedFrom = isPathSpecifier(specifier) && !specifier.startsWith("file:")
49
- ? pathToFileURL(path.resolve(baseDir, specifier)).href
50
- : specifier;
51
- let namespace;
52
- try {
53
- namespace = (await import(resolvedFrom));
54
- }
55
- catch (error) {
56
- throw moduleResolutionError(specifier, resolvedFrom, error, knownKinds ?? []);
57
- }
58
- const source = exportName === undefined ? specifier : `${specifier}#${exportName}`;
59
- const candidate = selectExport(namespace, exportName);
60
- if (candidate === undefined) {
61
- const available = Object.keys(namespace)
62
- .filter((key) => key !== "__esModule")
63
- .sort();
64
- throw new Error(exportName === undefined
65
- ? `worker_pool_driver_module_invalid: ${source} has no default export` +
66
- (available.length > 0 ? ` (named exports: ${available.join(", ")})` : "") +
67
- `; export defineWorkerDriver(...) as the default export or select a named export with #name`
68
- : `worker_pool_driver_module_invalid: ${source} has no export named "${exportName}"` +
69
- (available.length > 0 ? ` (available: ${available.join(", ")})` : ""));
70
- }
71
- assertWorkerDriverModule(candidate, source);
72
- return { module: candidate, resolvedFrom };
73
- }
74
- /**
75
- * Unwraps the driver module from the imported namespace: the selected named
76
- * export (falling back through a transpiled-CJS `default` object), or the
77
- * default export including the `default.default` shape some transpilers emit.
78
- */
79
- function selectExport(namespace, exportName) {
80
- if (exportName !== undefined) {
81
- const named = namespace[exportName];
82
- if (named !== undefined)
83
- return named;
84
- const viaDefault = namespace["default"];
85
- if (typeof viaDefault === "object" && viaDefault !== null) {
86
- return viaDefault[exportName];
87
- }
88
- return undefined;
89
- }
90
- let candidate = namespace["default"];
91
- if (candidate === undefined) {
92
- // A CJS module's exports are hoisted onto the namespace itself; accept the
93
- // namespace only when it already looks like a driver module, so an ESM
94
- // module that simply lacks a default export gets the no-default error.
95
- return typeof namespace["create"] === "function" ? namespace : undefined;
96
- }
97
- // Transpiled-CJS double default: `module.exports = { default: <module> }`
98
- // imported as `{ default: { default: <module> } }`. A real driver module has
99
- // a `create` function, so only unwrap when the outer layer does not.
100
- if (typeof candidate === "object" &&
101
- candidate !== null &&
102
- "default" in candidate &&
103
- typeof candidate.create !== "function") {
104
- candidate = candidate["default"];
105
- }
106
- return candidate;
107
- }
108
- /** Builds the actionable error for a failed module import. */
109
- function moduleResolutionError(specifier, resolvedFrom, cause, knownKinds) {
110
- const message = cause instanceof Error ? cause.message : String(cause);
111
- if (isPathSpecifier(specifier)) {
112
- return new Error(`worker_pool_driver_unavailable: ${specifier} (failed to import ${resolvedFrom}: ${message})`);
113
- }
114
- const kinds = knownKinds.length > 0
115
- ? ` (known kinds: ${[...knownKinds].sort().join(", ")})`
116
- : " (no worker drivers registered)";
117
- const close = closestKind(specifier, knownKinds);
118
- const hint = close === undefined ? "" : ` - did you mean "${close}"?`;
119
- return new Error(`worker_pool_driver_unavailable: ${specifier} is not a registered kind and could not be ` +
120
- `resolved as a module${kinds}${hint} [${message}]`);
22
+ return workerDriverLoader.parseRef(driver);
121
23
  }
122
24
  /**
123
- * The registered kind within a small edit distance of a mistyped bare
124
- * specifier, or undefined when nothing is close. Mitigates the typo detection
125
- * a closed config enum used to provide: `driver: dokcer` now reads as a module
126
- * specifier, so the resolution failure points back at the built-in.
127
- */
128
- function closestKind(specifier, kinds) {
129
- let best;
130
- for (const kind of kinds) {
131
- const distance = editDistance(specifier.toLowerCase(), kind.toLowerCase());
132
- if (distance <= 2 && (best === undefined || distance < best.distance)) {
133
- best = { kind, distance };
134
- }
135
- }
136
- return best?.kind;
137
- }
138
- /** Levenshtein distance (small inputs only: driver kinds and specifiers). */
139
- function editDistance(a, b) {
140
- if (a === b)
141
- return 0;
142
- const rows = a.length + 1;
143
- const cols = b.length + 1;
144
- let prev = Array.from({ length: cols }, (_, j) => j);
145
- for (let i = 1; i < rows; i += 1) {
146
- const current = [i, ...new Array(cols - 1).fill(0)];
147
- for (let j = 1; j < cols; j += 1) {
148
- const substitution = (prev[j - 1] ?? 0) + (a[i - 1] === b[j - 1] ? 0 : 1);
149
- current[j] = Math.min((prev[j] ?? 0) + 1, (current[j - 1] ?? 0) + 1, substitution);
150
- }
151
- prev = current;
152
- }
153
- return prev[cols - 1] ?? Math.max(a.length, b.length);
154
- }
155
- /**
156
- * Specifiers THIS loader registered, per registry. Distinguishes a reload that
157
- * re-encounters an already-loaded specifier (emit the module-pinned audit
158
- * event) from an ordinary built-in/extension hit (silent no-op).
159
- */
160
- const loadedSpecifiers = new WeakMap();
161
- /**
162
- * Idempotently makes the configured worker-pool driver resolvable in
163
- * `registry`. A registry hit (a built-in kind, an extension, or a specifier a
164
- * previous call already loaded) is a no-op - except that a re-encountered
165
- * loader-registered specifier emits `worker_pool_driver_module_pinned` so the
166
- * code-is-pinned semantic is observable on reload. A miss parses the driver as
167
- * a module reference, dynamic-imports it, and registers a factory whose kind
168
- * IS the configured specifier string, emitting `worker_pool_driver_loaded`.
169
- *
170
- * Called by the daemon BEFORE `createWorkerPool` at startup and (via the
171
- * coordinator's injected `driverLoader`) BEFORE `pool.reconcile` on reload, so
172
- * the pool's registry resolution stays synchronous and transactional. A module
173
- * registered for a reconcile that later fails is harmless: the registry is a
174
- * catalog, and an unused entry is inert.
25
+ * Idempotently makes the configured worker-pool driver resolvable in `registry`
26
+ * (see {@link createExtensionLoader} for the load/pin semantics). Called by the
27
+ * daemon BEFORE `createWorkerPool` at startup and (via the coordinator's injected
28
+ * `driverLoader`) BEFORE `pool.reconcile` on reload, so the pool's registry
29
+ * resolution stays synchronous and transactional.
175
30
  */
176
31
  export async function ensureWorkerDriverLoaded(driver, registry, options = {}) {
177
- const logEvent = options.logEvent ?? (() => { });
178
- if (registry.get(driver) !== undefined) {
179
- if (loadedSpecifiers.get(registry)?.has(driver)) {
180
- logEvent({ event: "worker_pool_driver_module_pinned", specifier: driver });
181
- }
182
- return;
183
- }
184
- const ref = parseWorkerDriverRef(driver);
185
- const { module, resolvedFrom } = await loadWorkerDriverModule(ref.specifier, {
186
- baseDir: options.baseDir ?? process.cwd(),
187
- exportName: ref.exportName,
188
- knownKinds: registry.kinds(),
189
- });
190
- // Register under the EXACT configured string: the pool resolves
191
- // `settings.driver` verbatim, so the factory's kind must be the specifier,
192
- // not the module's self-declared kind (which is logged for the audit trail).
193
- registry.register({
194
- kind: driver,
195
- create: (driverOptions, deps) => module.create(driverOptions, deps),
196
- });
197
- let loaded = loadedSpecifiers.get(registry);
198
- if (loaded === undefined) {
199
- loaded = new Set();
200
- loadedSpecifiers.set(registry, loaded);
201
- }
202
- loaded.add(driver);
203
- logEvent({
204
- event: "worker_pool_driver_loaded",
205
- specifier: driver,
206
- kind: module.kind,
207
- sdkVersion: module.sdkVersion,
208
- resolvedFrom,
209
- });
32
+ return workerDriverLoader.ensureLoaded(driver, registry, options);
210
33
  }
211
34
  //# sourceMappingURL=workerDriverLoader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"workerDriverLoader.js","sourceRoot":"","sources":["../src/workerDriverLoader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workerDriverLoader.js","sourceRoot":"","sources":["../src/workerDriverLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EACL,wBAAwB,GAIzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,qBAAqB,GAGtB,MAAM,sBAAsB,CAAC;AAgB9B,MAAM,kBAAkB,GAAG,qBAAqB,CAA0C;IACxF,WAAW,EAAE,oBAAoB;IACjC,UAAU,EAAE;QACV,MAAM,EAAE,2BAA2B;QACnC,MAAM,EAAE,kCAAkC;KAC3C;IACD,gBAAgB,EAAE,oBAAoB;IACtC,QAAQ,EAAE,gBAAgB;IAC1B,YAAY,EAAE,wBAAwB;IACtC,eAAe,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,QAAQ,CAAC,KAAK,UAAU;IACpF,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACjC,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,CAAC,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,IAAI,CAAC;KACpE,CAAC;IACF,cAAc,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC;CACnF,CAAC,CAAC;AAEH,wEAAwE;AACxE,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,OAAO,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,MAAc,EACd,QAA8B,EAC9B,UAA2C,EAAE;IAE7C,OAAO,kBAAkB,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AACpE,CAAC"}
@@ -22,6 +22,7 @@
22
22
  "@lorenz/dispatch-coordinator": "0.1.1",
23
23
  "@lorenz/docker-worker": "0.1.1",
24
24
  "@lorenz/domain": "0.1.1",
25
+ "@lorenz/flags": "0.1.0",
25
26
  "@lorenz/humanize": "0.1.1",
26
27
  "@lorenz/issue": "0.1.1",
27
28
  "@lorenz/jira-tracker": "0.1.1",
@@ -1,7 +1,7 @@
1
1
  export { PORT_MAX, ONE_WEEK_MS, RENDER_INTERVAL_MAX_MS, CONCURRENCY_MAX, MAX_TURNS_MAX, ENSEMBLE_SIZE_MAX, } from "@lorenz/domain";
2
2
  export { defaultSettings } from "./defaults.js";
3
3
  export type { DefaultSettingsOptions } from "./defaults.js";
4
- export { parseConfig, settingsForIssueState, validateDispatchConfig, normalizeStateName, normalizeRouteName, } from "./parse.js";
4
+ export { parseConfig, settingsForIssueState, validateDispatchConfig, trackerSpecifierFromConfig, normalizeStateName, normalizeRouteName, } from "./parse.js";
5
5
  export type { ConfigDeprecationContext } from "./parse.js";
6
6
  export { collectConfigDeprecations, formatConfigDeprecation, warnConfigDeprecations, } from "./deprecations.js";
7
7
  export type { ConfigDeprecation } from "./deprecations.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,aAAa,EACb,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,aAAa,EACb,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,sBAAsB,EACtB,0BAA0B,EAC1B,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  export { PORT_MAX, ONE_WEEK_MS, RENDER_INTERVAL_MAX_MS, CONCURRENCY_MAX, MAX_TURNS_MAX, ENSEMBLE_SIZE_MAX, } from "@lorenz/domain";
2
2
  export { defaultSettings } from "./defaults.js";
3
- export { parseConfig, settingsForIssueState, validateDispatchConfig, normalizeStateName, normalizeRouteName, } from "./parse.js";
3
+ export { parseConfig, settingsForIssueState, validateDispatchConfig, trackerSpecifierFromConfig, normalizeStateName, normalizeRouteName, } from "./parse.js";
4
4
  export { collectConfigDeprecations, formatConfigDeprecation, warnConfigDeprecations, } from "./deprecations.js";
5
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,aAAa,EACb,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,sBAAsB,EACtB,eAAe,EACf,aAAa,EACb,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,sBAAsB,EACtB,0BAA0B,EAC1B,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
@@ -16,6 +16,23 @@ export interface ConfigDeprecationContext {
16
16
  warn: (message: string) => void;
17
17
  }
18
18
  export declare function validateDispatchConfig(settings: Settings, trackers?: TrackerRegistry, executors?: AgentExecutorRegistry, tools?: ToolRegistry, deprecations?: ConfigDeprecationContext): void;
19
+ /**
20
+ * The effective tracker selector a raw workflow config resolves to - the value
21
+ * that becomes `settings.tracker.kind` - WITHOUT running the rest of config
22
+ * parsing. The out-of-tree extension loader needs this BEFORE {@link parseConfig}
23
+ * so it can dynamic-import a tracker module named by `tracker.kind` and register
24
+ * it (under that exact string) into the registry the parser then resolves
25
+ * `parseOptions`/`validateDispatch` against. Returns undefined when no tracker is
26
+ * configured (the default tracker applies) or when a `trackers.<name>` bundle is
27
+ * selected (a bundle is an in-repo composition, never a module specifier).
28
+ *
29
+ * Mirrors {@link parseTracker}'s selection: `tracker.kind` is the selector; an
30
+ * empty/blank value yields undefined. This reads only the selector, so a tracker
31
+ * module specifier in `tracker.kind` (e.g. `./acme-tracker.mjs`) surfaces here
32
+ * verbatim for the loader, while a bundle selection is left to the registry's
33
+ * built-ins.
34
+ */
35
+ export declare function trackerSpecifierFromConfig(raw?: Record<string, unknown>): string | undefined;
19
36
  export declare function normalizeStateName(value: string): string;
20
37
  export declare function normalizeRouteName(value: unknown): string;
21
38
  //# sourceMappingURL=parse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAMV,QAAQ,EAKT,MAAM,gBAAgB,CAAC;AAOxB,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAInF,OAAO,EAAwC,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AA4BlG,wBAAgB,WAAW,CACzB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACjC,GAAG,GAAE,MAAM,CAAC,UAAe,EAC3B,QAAQ,GAAE,sBAA2B,EACrC,QAAQ,GAAE,eAAwC,EAClD,SAAS,GAAE,qBAAoD,GAC9D,QAAQ,CAmFV;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAcjF;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,QAAQ,EAClB,QAAQ,GAAE,eAAwC,EAClD,SAAS,GAAE,qBAAoD,EAC/D,KAAK,CAAC,EAAE,YAAY,EACpB,YAAY,CAAC,EAAE,wBAAwB,GACtC,IAAI,CAoCN;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIzD"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAMV,QAAQ,EAKT,MAAM,gBAAgB,CAAC;AAOxB,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAInF,OAAO,EAAwC,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AA4BlG,wBAAgB,WAAW,CACzB,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACjC,GAAG,GAAE,MAAM,CAAC,UAAe,EAC3B,QAAQ,GAAE,sBAA2B,EACrC,QAAQ,GAAE,eAAwC,EAClD,SAAS,GAAE,qBAAoD,GAC9D,QAAQ,CA6FV;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,QAAQ,CAcjF;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,QAAQ,EAClB,QAAQ,GAAE,eAAwC,EAClD,SAAS,GAAE,qBAAoD,EAC/D,KAAK,CAAC,EAAE,YAAY,EACpB,YAAY,CAAC,EAAE,wBAAwB,GACtC,IAAI,CAoCN;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAChC,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAIzD"}
@@ -35,12 +35,14 @@ export function parseConfig(raw = {}, env = {}, defaults = {}, registry = defaul
35
35
  if (workerRaw.kind !== undefined && settings.worker.sshHosts.length > 0) {
36
36
  throw new Error("worker.kind cannot be combined with worker.ssh_hosts");
37
37
  }
38
- const workerPool = parseWorkerPool(workerRaw.workerPool, workerRaw, parsed.workers ?? {});
39
- if (workerPool)
40
- settings.worker.workerPool = workerPool;
41
- if (workerPool?.enabled && settings.worker.sshHosts.length > 0) {
42
- throw new Error("worker.worker_pool.enabled cannot be combined with worker.ssh_hosts");
43
- }
38
+ // The pool is the single dispatch path; parseWorkerPool always returns one. The static-ssh
39
+ // fold-in caps per-host concurrency at `max_concurrent_agents_per_host ?? agent.max_concurrent_agents`.
40
+ // The agent override is applied later (parseAgentSettings), so resolve it here from the raw config,
41
+ // falling back to the value already on settings.agent.
42
+ const perHostConcurrency = settings.worker.maxConcurrentAgentsPerHost ??
43
+ parsed.agent?.maxConcurrentAgents ??
44
+ settings.agent.maxConcurrentAgents;
45
+ settings.worker.workerPool = parseWorkerPool(workerRaw.workerPool, workerRaw, parsed.workers ?? {}, settings.worker.sshHosts, perHostConcurrency);
44
46
  settings.hooks = parseHooks(settings.hooks, parsed.hooks ?? {});
45
47
  if (settings.workspace.isolation === "none")
46
48
  assertNoWorkspaceHooks(settings.hooks);
@@ -121,6 +123,35 @@ export function validateDispatchConfig(settings, trackers = defaultTrackerRegist
121
123
  executorProvider.validateAgent?.(kind, agent, settings);
122
124
  }
123
125
  }
126
+ /**
127
+ * The effective tracker selector a raw workflow config resolves to - the value
128
+ * that becomes `settings.tracker.kind` - WITHOUT running the rest of config
129
+ * parsing. The out-of-tree extension loader needs this BEFORE {@link parseConfig}
130
+ * so it can dynamic-import a tracker module named by `tracker.kind` and register
131
+ * it (under that exact string) into the registry the parser then resolves
132
+ * `parseOptions`/`validateDispatch` against. Returns undefined when no tracker is
133
+ * configured (the default tracker applies) or when a `trackers.<name>` bundle is
134
+ * selected (a bundle is an in-repo composition, never a module specifier).
135
+ *
136
+ * Mirrors {@link parseTracker}'s selection: `tracker.kind` is the selector; an
137
+ * empty/blank value yields undefined. This reads only the selector, so a tracker
138
+ * module specifier in `tracker.kind` (e.g. `./acme-tracker.mjs`) surfaces here
139
+ * verbatim for the loader, while a bundle selection is left to the registry's
140
+ * built-ins.
141
+ */
142
+ export function trackerSpecifierFromConfig(raw = {}) {
143
+ const parsed = parseWorkflowConfig(raw);
144
+ const trackersRaw = parsed.trackers ?? {};
145
+ const selectorRecord = parseTrackerRecord(parsed.tracker ?? {}, "tracker");
146
+ const selected = trackerKindValue(selectorRecord.kind);
147
+ if (selected === undefined)
148
+ return undefined;
149
+ // A `trackers.<name>` bundle selection composes an in-repo provider via the
150
+ // bundle's `provider:` key; it is never an out-of-tree module specifier.
151
+ if (trackersRaw[selected] !== undefined)
152
+ return undefined;
153
+ return selected;
154
+ }
124
155
  export function normalizeStateName(value) {
125
156
  return value.trim().toLowerCase();
126
157
  }
@@ -279,14 +310,22 @@ function assertNoWorkspaceHooks(hooks) {
279
310
  return;
280
311
  throw new Error(`workspace.isolation = "none" does not support hooks; remove ${configured.join(", ")}`);
281
312
  }
282
- function parseWorkerPool(raw, workerRaw, workersRaw) {
313
+ function parseWorkerPool(raw, workerRaw, workersRaw, sshHosts, perHostConcurrency) {
283
314
  const selectedWorker = selectedWorkerProfile(workerRaw.kind, workersRaw);
284
- if ((raw === undefined || raw === null) && selectedWorker === undefined)
285
- return undefined;
315
+ // No explicit worker_pool and no named worker profile: defaultDispatchWorkerPool supplies the
316
+ // implicit pool (a `local` pool, or a `static-ssh` pool when `ssh_hosts` is set).
317
+ if ((raw === undefined || raw === null) && selectedWorker === undefined) {
318
+ return defaultDispatchWorkerPool(sshHosts, perHostConcurrency);
319
+ }
286
320
  if (selectedWorker !== undefined && raw?.driver !== undefined) {
287
321
  throw new Error("worker.kind cannot be combined with worker.worker_pool.driver");
288
322
  }
289
- const enabled = raw?.enabled ?? selectedWorker !== undefined;
323
+ // The `ssh_hosts` fold-in only auto-selects static-ssh when no driver is named; a named driver
324
+ // wins, so an explicit `worker_pool.driver` alongside `ssh_hosts` is ambiguous and rejected
325
+ // rather than dropping the hosts.
326
+ if (raw?.driver !== undefined && sshHosts.length > 0) {
327
+ throw new Error("worker.worker_pool.driver cannot be combined with worker.ssh_hosts");
328
+ }
290
329
  const driver = selectedWorker?.driver ?? raw?.driver ?? "fake";
291
330
  const min = raw?.min ?? 0;
292
331
  const max = raw?.max ?? 1;
@@ -301,7 +340,9 @@ function parseWorkerPool(raw, workerRaw, workersRaw) {
301
340
  // so the constructed object carries exactly ONE own field (`slotsPerMachine`). The config key
302
341
  // `worker.worker_pool.max_in_flight` is unchanged; it parses into `slotsPerMachine`.
303
342
  const input = {
304
- enabled,
343
+ // A configured pool (an explicit worker_pool block or a named worker.kind) is always enabled;
344
+ // `enabled` is an internal liveness flag the reload-drain flips, not an operator config key.
345
+ enabled: true,
305
346
  driver,
306
347
  min,
307
348
  max,
@@ -335,6 +376,61 @@ function parseWorkerPool(raw, workerRaw, workersRaw) {
335
376
  // fail-loud startup point as an unregistered kind.
336
377
  return settings;
337
378
  }
379
+ /**
380
+ * The implicit dispatch pool produced when no `worker_pool` and no `worker.kind` are configured:
381
+ * - empty `sshHosts` -> an enabled `local` pool, slotsPerMachine=1, min=0/warm=0/max=1 so nothing
382
+ * provisions eagerly and the single local worker is minted on first acquire. The local driver
383
+ * yields an empty `workerHost`, so the per-run endpoint manager mints no tunnel and acp keeps its
384
+ * own in-process MCP endpoint.
385
+ * - non-empty `sshHosts` -> an enabled `static-ssh` pool whose driverOptions carry the configured
386
+ * hosts (the `ssh_hosts` spelling the driver's `readSshHosts` expects). `max` is the host count
387
+ * and slotsPerMachine is the per-host cap (`max_concurrent_agents_per_host ??
388
+ * agent.max_concurrent_agents`), so total capacity is hosts * perHostConcurrency. `co_residence`
389
+ * is auto-enabled when that cap is >1, since each co-resident run owns its own per-run Token B
390
+ * claim plus the shared per-host reverse tunnel. The provision policy is round-robin first-free
391
+ * (static-ssh `provision`).
392
+ */
393
+ function defaultDispatchWorkerPool(sshHosts, perHostConcurrency) {
394
+ if (sshHosts.length > 0) {
395
+ const slotsPerMachine = Math.max(1, perHostConcurrency);
396
+ const input = {
397
+ enabled: true,
398
+ driver: "static-ssh",
399
+ min: 0,
400
+ max: sshHosts.length,
401
+ warm: 0,
402
+ slotsPerMachine,
403
+ ttlMs: 3_600_000,
404
+ idleReapMs: 300_000,
405
+ acquireTimeoutMs: 30_000,
406
+ reapIntervalMs: 15_000,
407
+ staleHeartbeatMs: 600_000,
408
+ drainDeadlineMs: 30_000,
409
+ driverOptions: { ssh_hosts: [...sshHosts] },
410
+ };
411
+ const settings = withDerivedMaxInFlight(input);
412
+ // A per-host cap >1 co-resides runs on one host (guarded by the slots-per-machine gate), so
413
+ // auto-enable the co_residence opt-in. A cap of 1 stays single-tenant and never trips the gate.
414
+ if (slotsPerMachine > 1)
415
+ settings.coResidence = true;
416
+ return settings;
417
+ }
418
+ const input = {
419
+ enabled: true,
420
+ driver: "local",
421
+ min: 0,
422
+ max: 1,
423
+ warm: 0,
424
+ slotsPerMachine: 1,
425
+ ttlMs: 3_600_000,
426
+ idleReapMs: 300_000,
427
+ acquireTimeoutMs: 30_000,
428
+ reapIntervalMs: 15_000,
429
+ staleHeartbeatMs: 600_000,
430
+ drainDeadlineMs: 30_000,
431
+ };
432
+ return withDerivedMaxInFlight(input);
433
+ }
338
434
  function selectedWorkerProfile(workerKind, workersRaw) {
339
435
  if (workerKind === undefined)
340
436
  return undefined;