@openrig/cli 0.3.0 → 0.3.1

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 (282) hide show
  1. package/daemon/assets/plugins/openrig-core/.claude-plugin/plugin.json +15 -0
  2. package/daemon/assets/plugins/openrig-core/.codex-plugin/plugin.json +24 -0
  3. package/daemon/assets/plugins/openrig-core/LICENSE +200 -0
  4. package/daemon/assets/plugins/openrig-core/README.md +42 -0
  5. package/daemon/assets/plugins/openrig-core/hooks/claude.json +78 -0
  6. package/daemon/assets/plugins/openrig-core/hooks/codex.json +37 -0
  7. package/daemon/assets/{openrig-activity-hook-relay.cjs → plugins/openrig-core/hooks/scripts/activity-relay.cjs} +12 -0
  8. package/daemon/assets/plugins/openrig-core/hooks/scripts/compaction-restore-bridge.cjs +172 -0
  9. package/daemon/assets/plugins/openrig-core/skills/agent-startup-and-context-ingestion/SKILL.md +104 -0
  10. package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/SKILL.md +131 -0
  11. package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/scripts/precompact-hook.mjs +174 -0
  12. package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/scripts/restore-from-jsonl.mjs +433 -0
  13. package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/templates/compact-instruction.md +1 -0
  14. package/daemon/assets/plugins/openrig-core/skills/claude-compaction-restore/templates/post-compact-restore-instruction.md +1 -0
  15. package/daemon/assets/plugins/openrig-core/skills/forming-an-openrig-mental-model/SKILL.md +305 -0
  16. package/daemon/{specs/agents/shared/skills/rig-architect → assets/plugins/openrig-core/skills/openrig-architect}/SKILL.md +38 -19
  17. package/daemon/assets/plugins/openrig-core/skills/openrig-operator/SKILL.md +222 -0
  18. package/daemon/assets/plugins/openrig-core/skills/openrig-user/SKILL.md +597 -0
  19. package/daemon/assets/plugins/openrig-core/skills/queue-handoff/SKILL.md +122 -0
  20. package/daemon/assets/plugins/openrig-core/skills/seat-continuity-and-handover/SKILL.md +137 -0
  21. package/daemon/assets/vm-preview-fixtures/README.md +48 -0
  22. package/daemon/assets/vm-preview-fixtures/workflows/sample-basic-loop.yaml +79 -0
  23. package/daemon/dist/adapters/claude-code-adapter.d.ts +1 -3
  24. package/daemon/dist/adapters/claude-code-adapter.d.ts.map +1 -1
  25. package/daemon/dist/adapters/claude-code-adapter.js +17 -57
  26. package/daemon/dist/adapters/claude-code-adapter.js.map +1 -1
  27. package/daemon/dist/adapters/cmux-transport.d.ts.map +1 -1
  28. package/daemon/dist/adapters/cmux-transport.js +81 -2
  29. package/daemon/dist/adapters/cmux-transport.js.map +1 -1
  30. package/daemon/dist/adapters/cmux.d.ts +4 -0
  31. package/daemon/dist/adapters/cmux.d.ts.map +1 -1
  32. package/daemon/dist/adapters/cmux.js +87 -0
  33. package/daemon/dist/adapters/cmux.js.map +1 -1
  34. package/daemon/dist/adapters/codex-runtime-adapter.d.ts +14 -3
  35. package/daemon/dist/adapters/codex-runtime-adapter.d.ts.map +1 -1
  36. package/daemon/dist/adapters/codex-runtime-adapter.js +43 -57
  37. package/daemon/dist/adapters/codex-runtime-adapter.js.map +1 -1
  38. package/daemon/dist/db/migrations/040_workflow_specs_diagnostic.d.ts +32 -0
  39. package/daemon/dist/db/migrations/040_workflow_specs_diagnostic.d.ts.map +1 -0
  40. package/daemon/dist/db/migrations/040_workflow_specs_diagnostic.js +37 -0
  41. package/daemon/dist/db/migrations/040_workflow_specs_diagnostic.js.map +1 -0
  42. package/daemon/dist/domain/agent-manifest.d.ts.map +1 -1
  43. package/daemon/dist/domain/agent-manifest.js +116 -37
  44. package/daemon/dist/domain/agent-manifest.js.map +1 -1
  45. package/daemon/dist/domain/agent-resolver.js +1 -1
  46. package/daemon/dist/domain/agent-resolver.js.map +1 -1
  47. package/daemon/dist/domain/claude-compaction-enforcer.d.ts +81 -0
  48. package/daemon/dist/domain/claude-compaction-enforcer.d.ts.map +1 -0
  49. package/daemon/dist/domain/claude-compaction-enforcer.js +242 -0
  50. package/daemon/dist/domain/claude-compaction-enforcer.js.map +1 -0
  51. package/daemon/dist/domain/cmux-layout-service.d.ts +41 -0
  52. package/daemon/dist/domain/cmux-layout-service.d.ts.map +1 -0
  53. package/daemon/dist/domain/cmux-layout-service.js +184 -0
  54. package/daemon/dist/domain/cmux-layout-service.js.map +1 -0
  55. package/daemon/dist/domain/context-monitor.d.ts +15 -1
  56. package/daemon/dist/domain/context-monitor.d.ts.map +1 -1
  57. package/daemon/dist/domain/context-monitor.js +38 -3
  58. package/daemon/dist/domain/context-monitor.js.map +1 -1
  59. package/daemon/dist/domain/kernel-boot-tracker.d.ts +74 -0
  60. package/daemon/dist/domain/kernel-boot-tracker.d.ts.map +1 -0
  61. package/daemon/dist/domain/kernel-boot-tracker.js +213 -0
  62. package/daemon/dist/domain/kernel-boot-tracker.js.map +1 -0
  63. package/daemon/dist/domain/kernel-boot.d.ts +50 -0
  64. package/daemon/dist/domain/kernel-boot.d.ts.map +1 -0
  65. package/daemon/dist/domain/kernel-boot.js +147 -0
  66. package/daemon/dist/domain/kernel-boot.js.map +1 -0
  67. package/daemon/dist/domain/mission-control/mission-control-read-layer.d.ts +5 -0
  68. package/daemon/dist/domain/mission-control/mission-control-read-layer.d.ts.map +1 -1
  69. package/daemon/dist/domain/mission-control/mission-control-read-layer.js +16 -2
  70. package/daemon/dist/domain/mission-control/mission-control-read-layer.js.map +1 -1
  71. package/daemon/dist/domain/mission-control/mission-control-write-contract.d.ts.map +1 -1
  72. package/daemon/dist/domain/mission-control/mission-control-write-contract.js +3 -1
  73. package/daemon/dist/domain/mission-control/mission-control-write-contract.js.map +1 -1
  74. package/daemon/dist/domain/plugin-discovery-service.d.ts +150 -0
  75. package/daemon/dist/domain/plugin-discovery-service.d.ts.map +1 -0
  76. package/daemon/dist/domain/plugin-discovery-service.js +468 -0
  77. package/daemon/dist/domain/plugin-discovery-service.js.map +1 -0
  78. package/daemon/dist/domain/plugin-vendor-service.d.ts +54 -0
  79. package/daemon/dist/domain/plugin-vendor-service.d.ts.map +1 -0
  80. package/daemon/dist/domain/plugin-vendor-service.js +111 -0
  81. package/daemon/dist/domain/plugin-vendor-service.js.map +1 -0
  82. package/daemon/dist/domain/profile-resolver.d.ts +3 -3
  83. package/daemon/dist/domain/profile-resolver.d.ts.map +1 -1
  84. package/daemon/dist/domain/profile-resolver.js +7 -7
  85. package/daemon/dist/domain/profile-resolver.js.map +1 -1
  86. package/daemon/dist/domain/projection-planner.d.ts +7 -1
  87. package/daemon/dist/domain/projection-planner.d.ts.map +1 -1
  88. package/daemon/dist/domain/projection-planner.js +44 -4
  89. package/daemon/dist/domain/projection-planner.js.map +1 -1
  90. package/daemon/dist/domain/queue-repository.d.ts +8 -1
  91. package/daemon/dist/domain/queue-repository.d.ts.map +1 -1
  92. package/daemon/dist/domain/queue-repository.js +14 -5
  93. package/daemon/dist/domain/queue-repository.js.map +1 -1
  94. package/daemon/dist/domain/session-transport.d.ts.map +1 -1
  95. package/daemon/dist/domain/session-transport.js +33 -0
  96. package/daemon/dist/domain/session-transport.js.map +1 -1
  97. package/daemon/dist/domain/skill-library-discovery.d.ts +68 -0
  98. package/daemon/dist/domain/skill-library-discovery.d.ts.map +1 -0
  99. package/daemon/dist/domain/skill-library-discovery.js +144 -0
  100. package/daemon/dist/domain/skill-library-discovery.js.map +1 -0
  101. package/daemon/dist/domain/slices/slice-indexer.d.ts +19 -0
  102. package/daemon/dist/domain/slices/slice-indexer.d.ts.map +1 -1
  103. package/daemon/dist/domain/slices/slice-indexer.js +88 -6
  104. package/daemon/dist/domain/slices/slice-indexer.js.map +1 -1
  105. package/daemon/dist/domain/spec-library-service.d.ts +6 -0
  106. package/daemon/dist/domain/spec-library-service.d.ts.map +1 -1
  107. package/daemon/dist/domain/spec-library-service.js.map +1 -1
  108. package/daemon/dist/domain/spec-library-workflow-scanner.d.ts +43 -0
  109. package/daemon/dist/domain/spec-library-workflow-scanner.d.ts.map +1 -1
  110. package/daemon/dist/domain/spec-library-workflow-scanner.js +157 -3
  111. package/daemon/dist/domain/spec-library-workflow-scanner.js.map +1 -1
  112. package/daemon/dist/domain/spec-review-service.d.ts +1 -1
  113. package/daemon/dist/domain/spec-review-service.d.ts.map +1 -1
  114. package/daemon/dist/domain/spec-review-service.js +14 -1
  115. package/daemon/dist/domain/spec-review-service.js.map +1 -1
  116. package/daemon/dist/domain/types.d.ts +27 -7
  117. package/daemon/dist/domain/types.d.ts.map +1 -1
  118. package/daemon/dist/domain/types.js.map +1 -1
  119. package/daemon/dist/domain/user-settings/settings-store.d.ts +25 -1
  120. package/daemon/dist/domain/user-settings/settings-store.d.ts.map +1 -1
  121. package/daemon/dist/domain/user-settings/settings-store.js +186 -4
  122. package/daemon/dist/domain/user-settings/settings-store.js.map +1 -1
  123. package/daemon/dist/domain/workflow-spec-cache.d.ts +27 -0
  124. package/daemon/dist/domain/workflow-spec-cache.d.ts.map +1 -1
  125. package/daemon/dist/domain/workflow-spec-cache.js +59 -0
  126. package/daemon/dist/domain/workflow-spec-cache.js.map +1 -1
  127. package/daemon/dist/domain/workspace/default-workspace-scaffold.d.ts.map +1 -1
  128. package/daemon/dist/domain/workspace/default-workspace-scaffold.js +45 -0
  129. package/daemon/dist/domain/workspace/default-workspace-scaffold.js.map +1 -1
  130. package/daemon/dist/domain/workspace/getting-started-narrative.d.ts +15 -0
  131. package/daemon/dist/domain/workspace/getting-started-narrative.d.ts.map +1 -0
  132. package/daemon/dist/domain/workspace/getting-started-narrative.js +237 -0
  133. package/daemon/dist/domain/workspace/getting-started-narrative.js.map +1 -0
  134. package/daemon/dist/index.d.ts +2 -1
  135. package/daemon/dist/index.d.ts.map +1 -1
  136. package/daemon/dist/index.js +52 -17
  137. package/daemon/dist/index.js.map +1 -1
  138. package/daemon/dist/lib/pane-envelope.d.ts +7 -0
  139. package/daemon/dist/lib/pane-envelope.d.ts.map +1 -0
  140. package/daemon/dist/lib/pane-envelope.js +38 -0
  141. package/daemon/dist/lib/pane-envelope.js.map +1 -0
  142. package/daemon/dist/middleware/auth-bearer-token.d.ts +47 -5
  143. package/daemon/dist/middleware/auth-bearer-token.d.ts.map +1 -1
  144. package/daemon/dist/middleware/auth-bearer-token.js +109 -8
  145. package/daemon/dist/middleware/auth-bearer-token.js.map +1 -1
  146. package/daemon/dist/routes/kernel-status.d.ts +3 -0
  147. package/daemon/dist/routes/kernel-status.d.ts.map +1 -0
  148. package/daemon/dist/routes/kernel-status.js +40 -0
  149. package/daemon/dist/routes/kernel-status.js.map +1 -0
  150. package/daemon/dist/routes/mission-control.d.ts.map +1 -1
  151. package/daemon/dist/routes/mission-control.js +25 -2
  152. package/daemon/dist/routes/mission-control.js.map +1 -1
  153. package/daemon/dist/routes/missions.d.ts +3 -0
  154. package/daemon/dist/routes/missions.d.ts.map +1 -0
  155. package/daemon/dist/routes/missions.js +195 -0
  156. package/daemon/dist/routes/missions.js.map +1 -0
  157. package/daemon/dist/routes/plugins.d.ts +3 -0
  158. package/daemon/dist/routes/plugins.d.ts.map +1 -0
  159. package/daemon/dist/routes/plugins.js +223 -0
  160. package/daemon/dist/routes/plugins.js.map +1 -0
  161. package/daemon/dist/routes/rig-cmux.d.ts +3 -0
  162. package/daemon/dist/routes/rig-cmux.d.ts.map +1 -0
  163. package/daemon/dist/routes/rig-cmux.js +121 -0
  164. package/daemon/dist/routes/rig-cmux.js.map +1 -0
  165. package/daemon/dist/routes/skills.d.ts +3 -0
  166. package/daemon/dist/routes/skills.d.ts.map +1 -0
  167. package/daemon/dist/routes/skills.js +147 -0
  168. package/daemon/dist/routes/skills.js.map +1 -0
  169. package/daemon/dist/routes/slices.d.ts.map +1 -1
  170. package/daemon/dist/routes/slices.js +15 -0
  171. package/daemon/dist/routes/slices.js.map +1 -1
  172. package/daemon/dist/routes/spec-library.d.ts.map +1 -1
  173. package/daemon/dist/routes/spec-library.js +16 -1
  174. package/daemon/dist/routes/spec-library.js.map +1 -1
  175. package/daemon/dist/server.d.ts +31 -0
  176. package/daemon/dist/server.d.ts.map +1 -1
  177. package/daemon/dist/server.js +30 -0
  178. package/daemon/dist/server.js.map +1 -1
  179. package/daemon/dist/startup.d.ts.map +1 -1
  180. package/daemon/dist/startup.js +194 -5
  181. package/daemon/dist/startup.js.map +1 -1
  182. package/daemon/specs/agents/apps/vault-specialist/agent.yaml +0 -1
  183. package/daemon/specs/agents/conveyor/builder/agent.yaml +0 -1
  184. package/daemon/specs/agents/conveyor/lead/agent.yaml +0 -1
  185. package/daemon/specs/agents/conveyor/planner/agent.yaml +0 -1
  186. package/daemon/specs/agents/conveyor/reviewer/agent.yaml +0 -1
  187. package/daemon/specs/agents/design/product-designer/agent.yaml +0 -1
  188. package/daemon/specs/agents/development/implementer/agent.yaml +0 -1
  189. package/daemon/specs/agents/development/qa/agent.yaml +0 -1
  190. package/daemon/specs/agents/development/qa/guidance/role.md +0 -2
  191. package/daemon/specs/agents/orchestration/orchestrator/agent.yaml +0 -1
  192. package/daemon/specs/agents/research/analyst/agent.yaml +0 -1
  193. package/daemon/specs/agents/research/synthesizer/agent.yaml +0 -1
  194. package/daemon/specs/agents/review/independent-reviewer/agent.yaml +0 -1
  195. package/daemon/specs/agents/shared/agent.yaml +6 -6
  196. package/daemon/specs/agents/shared/skills/core/openrig-architect/SKILL.md +361 -0
  197. package/daemon/specs/agents/shared/skills/core/openrig-installer/SKILL.md +142 -0
  198. package/daemon/specs/agents/shared/skills/core/openrig-user/SKILL.md +6 -1
  199. package/daemon/specs/agents/shared/skills/core/openrig-user-settings/SKILL.md +4 -4
  200. package/daemon/specs/agents/shared/skills/core/rig-lifecycle/SKILL.md +116 -0
  201. package/daemon/specs/agents/shared/skills/pods/development-team/SKILL.md +0 -1
  202. package/daemon/specs/agents/shared/skills/pods/orchestration-team/SKILL.md +2 -2
  203. package/daemon/specs/agents/shared/skills/process/agent-browser/LOCAL-INSIGHTS.md +6 -6
  204. package/daemon/specs/agents/shared/skills/process/agent-browser/OPENRIG.md +40 -0
  205. package/daemon/specs/agents/shared/skills/process/agent-browser/SKILL.md +10 -0
  206. package/daemon/specs/agents/shared/skills/process/brainstorming/OPENRIG.md +48 -0
  207. package/daemon/specs/agents/shared/skills/process/brainstorming/SKILL.md +11 -0
  208. package/daemon/specs/agents/shared/skills/process/dogfood/SKILL.md +5 -0
  209. package/daemon/specs/agents/shared/skills/process/executing-plans/OPENRIG.md +56 -0
  210. package/daemon/specs/agents/shared/skills/process/executing-plans/SKILL.md +10 -0
  211. package/daemon/specs/agents/shared/skills/process/frontend-design/SKILL.md +5 -0
  212. package/daemon/specs/agents/shared/skills/process/systematic-debugging/SKILL.md +5 -0
  213. package/daemon/specs/agents/shared/skills/process/test-driven-development/SKILL.md +5 -0
  214. package/daemon/specs/agents/shared/skills/process/using-superpowers/OPENRIG.md +48 -0
  215. package/daemon/specs/agents/shared/skills/process/using-superpowers/SKILL.md +11 -0
  216. package/daemon/specs/agents/shared/skills/process/verification-before-completion/SKILL.md +5 -0
  217. package/daemon/specs/agents/shared/skills/process/writing-plans/OPENRIG.md +52 -0
  218. package/daemon/specs/agents/shared/skills/process/writing-plans/SKILL.md +12 -2
  219. package/daemon/specs/rigs/launch/kernel/agents/advisor/lead/agent.yaml +35 -0
  220. package/daemon/specs/rigs/launch/kernel/agents/advisor/lead/guidance/role.md +50 -0
  221. package/daemon/specs/rigs/launch/kernel/agents/advisor/lead/startup/context.md +37 -0
  222. package/daemon/specs/rigs/launch/kernel/agents/operator/agent/agent.yaml +35 -0
  223. package/daemon/specs/rigs/launch/kernel/agents/operator/agent/guidance/role.md +49 -0
  224. package/daemon/specs/rigs/launch/kernel/agents/operator/agent/startup/context.md +63 -0
  225. package/daemon/specs/rigs/launch/kernel/agents/queue/worker/agent.yaml +35 -0
  226. package/daemon/specs/rigs/launch/kernel/agents/queue/worker/guidance/role.md +33 -0
  227. package/daemon/specs/rigs/launch/kernel/agents/queue/worker/startup/context.md +30 -0
  228. package/daemon/specs/rigs/launch/kernel/culture/CULTURE.md +69 -0
  229. package/daemon/specs/rigs/launch/kernel/rig-claude-only.yaml +59 -0
  230. package/daemon/specs/rigs/launch/kernel/rig-codex-only.yaml +59 -0
  231. package/daemon/specs/rigs/launch/kernel/rig.yaml +69 -0
  232. package/dist/commands/config-init-workspace.d.ts.map +1 -1
  233. package/dist/commands/config-init-workspace.js +253 -0
  234. package/dist/commands/config-init-workspace.js.map +1 -1
  235. package/dist/commands/config.d.ts.map +1 -1
  236. package/dist/commands/config.js +11 -3
  237. package/dist/commands/config.js.map +1 -1
  238. package/dist/commands/daemon.d.ts.map +1 -1
  239. package/dist/commands/daemon.js +53 -1
  240. package/dist/commands/daemon.js.map +1 -1
  241. package/dist/commands/heartbeat.d.ts.map +1 -1
  242. package/dist/commands/heartbeat.js +0 -5
  243. package/dist/commands/heartbeat.js.map +1 -1
  244. package/dist/commands/plugin.d.ts +4 -0
  245. package/dist/commands/plugin.d.ts.map +1 -0
  246. package/dist/commands/plugin.js +395 -0
  247. package/dist/commands/plugin.js.map +1 -0
  248. package/dist/commands/send.d.ts +8 -0
  249. package/dist/commands/send.d.ts.map +1 -1
  250. package/dist/commands/send.js +8 -0
  251. package/dist/commands/send.js.map +1 -1
  252. package/dist/commands/up.d.ts.map +1 -1
  253. package/dist/commands/up.js +13 -1
  254. package/dist/commands/up.js.map +1 -1
  255. package/dist/config-store.d.ts +18 -1
  256. package/dist/config-store.d.ts.map +1 -1
  257. package/dist/config-store.js +167 -4
  258. package/dist/config-store.js.map +1 -1
  259. package/dist/daemon-lifecycle.d.ts +20 -1
  260. package/dist/daemon-lifecycle.d.ts.map +1 -1
  261. package/dist/daemon-lifecycle.js +57 -7
  262. package/dist/daemon-lifecycle.js.map +1 -1
  263. package/dist/host-registry.d.ts +1 -1
  264. package/dist/host-registry.js +1 -1
  265. package/dist/index.d.ts +1 -0
  266. package/dist/index.d.ts.map +1 -1
  267. package/dist/index.js +2 -0
  268. package/dist/index.js.map +1 -1
  269. package/package.json +1 -1
  270. package/ui/dist/assets/index-C_Q5FczU.css +1 -0
  271. package/ui/dist/assets/index-Rl3ZBrUg.js +547 -0
  272. package/ui/dist/index.html +2 -2
  273. package/daemon/specs/agents/shared/skills/claude-compact-in-place/SKILL.md +0 -100
  274. package/daemon/specs/agents/shared/skills/process/containerized-e2e/SKILL.md +0 -256
  275. package/daemon/specs/agents/shared/skills/process/containerized-e2e/scripts/Dockerfile +0 -39
  276. package/daemon/specs/agents/shared/skills/process/containerized-e2e/scripts/build-e2e-image.sh +0 -37
  277. package/daemon/specs/agents/shared/skills/process/containerized-e2e/templates/control-plane-test.yaml +0 -40
  278. package/daemon/specs/agents/shared/skills/process/containerized-e2e/templates/e2e-report-template.md +0 -94
  279. package/daemon/specs/agents/shared/skills/process/containerized-e2e/templates/expansion-collision-fragment.yaml +0 -13
  280. package/daemon/specs/agents/shared/skills/process/containerized-e2e/templates/expansion-pod-fragment.yaml +0 -14
  281. package/ui/dist/assets/index-BDHU1JUK.js +0 -412
  282. package/ui/dist/assets/index-DXTyJSqu.css +0 -1
@@ -0,0 +1,184 @@
1
+ // Slice 24 — CmuxLayoutService.
2
+ //
3
+ // Algorithmic core of the "Launch in CMUX" feature. Three pure helpers
4
+ // (computeLayout / chunkAgents / orderAgentsFromRigSpec) + one
5
+ // coordinated method (buildWorkspace) that drives the CmuxAdapter
6
+ // through workspace.create + N-1 surface.split + N surface.sendText
7
+ // calls to populate a freshly-created cmux workspace with one tmux-
8
+ // attach panel per agent.
9
+ //
10
+ // Timing strategy (per slice 24 README §Daemon-side + cmux-rig-layout
11
+ // skill §5 gotchas):
12
+ // - After every splitSurface, wait OP_DELAY_MS so the freshly-created
13
+ // surface's shell reaches its prompt before the next operation
14
+ // (skill §5 gotcha 3 — surface-not-ready-for-input window).
15
+ // - After the LAST sendText, wait FINAL_SETTLE_MS to defeat the
16
+ // last-send-key race (skill §5 gotcha 2).
17
+ // - listSurfaces immediately after createWorkspace retries with
18
+ // small backoff to absorb the workspace-default-surface attach
19
+ // latency. The default surface is created by cmux daemon at
20
+ // workspace.create time but the listing may not reflect it for
21
+ // a beat.
22
+ // Sleep is injected via constructor so tests stub it to no-op.
23
+ //
24
+ // Constants live at the top of the file per slice 24 README §Layout
25
+ // algorithm §"Configurability posture". v0 ships them as hardcoded
26
+ // constants; v0.3.2 follow-on graduates to settings keys.
27
+ //
28
+ // TODO(0.3.2): graduate MAX_COLS + MAX_PER_WORKSPACE to settings keys
29
+ // cmux.workspace_columns + cmux.workspace_max_panels (slice 08 settings
30
+ // infra is ready; this is a 2-keys-plus-optional-UI-surface follow-on).
31
+ export const MAX_COLS = 2;
32
+ export const MAX_PER_WORKSPACE = 12;
33
+ export const OP_DELAY_MS = 500;
34
+ export const FINAL_SETTLE_MS = 1000;
35
+ export const LIST_SURFACES_RETRY_DELAY_MS = 100;
36
+ export const LIST_SURFACES_MAX_ATTEMPTS = 5;
37
+ const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
38
+ export class CmuxLayoutService {
39
+ cmuxAdapter;
40
+ sleep;
41
+ constructor(cmuxAdapter, opts = {}) {
42
+ this.cmuxAdapter = cmuxAdapter;
43
+ this.sleep = opts.sleep ?? defaultSleep;
44
+ }
45
+ static computeLayout(n) {
46
+ if (!Number.isInteger(n) || n <= 0) {
47
+ throw new Error(`CmuxLayoutService.computeLayout: N must be a positive integer (got ${n})`);
48
+ }
49
+ if (n > MAX_PER_WORKSPACE) {
50
+ throw new Error(`CmuxLayoutService.computeLayout: N=${n} exceeds MAX_PER_WORKSPACE=${MAX_PER_WORKSPACE}; caller should chunk first`);
51
+ }
52
+ if (n === 1) {
53
+ return { rows: 1, cols: 1, blanks: 0 };
54
+ }
55
+ const cols = MAX_COLS;
56
+ const rows = Math.ceil(n / cols);
57
+ const blanks = rows * cols - n;
58
+ return { rows, cols, blanks };
59
+ }
60
+ static chunkAgents(agents) {
61
+ if (agents.length === 0)
62
+ return [];
63
+ const chunks = [];
64
+ for (let i = 0; i < agents.length; i += MAX_PER_WORKSPACE) {
65
+ chunks.push(agents.slice(i, i + MAX_PER_WORKSPACE));
66
+ }
67
+ return chunks;
68
+ }
69
+ static orderAgentsFromRigSpec(rigSpec) {
70
+ const out = [];
71
+ for (const pod of rigSpec.pods ?? []) {
72
+ for (const member of pod.members ?? []) {
73
+ out.push(`${pod.id}.${member.id}`);
74
+ }
75
+ }
76
+ return out;
77
+ }
78
+ async buildWorkspace(workspaceName, cwd, agentSessions) {
79
+ if (agentSessions.length === 0) {
80
+ const ws = await this.cmuxAdapter.createWorkspace(workspaceName, cwd);
81
+ if (!ws.ok)
82
+ return ws;
83
+ return {
84
+ ok: true,
85
+ data: { workspaceId: ws.data, workspaceName, agents: [], blanks: 0 },
86
+ };
87
+ }
88
+ if (agentSessions.length > MAX_PER_WORKSPACE) {
89
+ return {
90
+ ok: false,
91
+ code: "invalid_input",
92
+ message: `buildWorkspace: ${agentSessions.length} agents exceeds MAX_PER_WORKSPACE=${MAX_PER_WORKSPACE}; caller should chunk first`,
93
+ };
94
+ }
95
+ const layout = CmuxLayoutService.computeLayout(agentSessions.length);
96
+ // 1. Create the workspace.
97
+ const wsResult = await this.cmuxAdapter.createWorkspace(workspaceName, cwd);
98
+ if (!wsResult.ok)
99
+ return wsResult;
100
+ const workspaceId = wsResult.data;
101
+ // 2. Discover the workspace's default surface. workspace.create
102
+ // auto-creates one terminal surface but the listing may not
103
+ // reflect it immediately. Retry with small backoff (skill §5
104
+ // gotcha 3 — surface-not-ready-for-input window also applies
105
+ // to surface enumeration).
106
+ const initialSurface = await this.discoverInitialSurface(workspaceId);
107
+ if (!initialSurface.ok)
108
+ return initialSurface;
109
+ // 3. Build the grid. grid[col][row] holds the surface id. Layout
110
+ // shape determines the split sequence:
111
+ // - col 1: 1 initial surface + (rows-1) down splits below it
112
+ // - col 2: 1 right split off initial + (rows-1) down splits
113
+ // Sleep OP_DELAY_MS after every split so the freshly created
114
+ // surface's shell reaches its prompt before the next op.
115
+ const grid = [[initialSurface.data]];
116
+ if (layout.cols === 2) {
117
+ const rightSplit = await this.cmuxAdapter.splitSurface(initialSurface.data, "right", workspaceId);
118
+ if (!rightSplit.ok)
119
+ return rightSplit;
120
+ grid.push([rightSplit.data]);
121
+ await this.sleep(OP_DELAY_MS);
122
+ }
123
+ for (let r = 1; r < layout.rows; r++) {
124
+ for (let c = 0; c < layout.cols; c++) {
125
+ const prevSurfaceInCol = grid[c][r - 1];
126
+ const downSplit = await this.cmuxAdapter.splitSurface(prevSurfaceInCol, "down", workspaceId);
127
+ if (!downSplit.ok)
128
+ return downSplit;
129
+ grid[c].push(downSplit.data);
130
+ await this.sleep(OP_DELAY_MS);
131
+ }
132
+ }
133
+ // 4. Send tmux-attach to each agent's surface in COLUMN-MAJOR
134
+ // order: fill column 0 top-to-bottom first, then column 1
135
+ // top-to-bottom. Matches README §52 "Fill ... (top-to-bottom,
136
+ // left-to-right)" — each column's contents in reading order,
137
+ // moving left-to-right across columns.
138
+ // Any unpopulated surfaces in column 1's last row(s) remain
139
+ // as "blanks" (cmux still shows them as empty terminals).
140
+ let agentIndex = 0;
141
+ for (let c = 0; c < layout.cols && agentIndex < agentSessions.length; c++) {
142
+ for (let r = 0; r < layout.rows && agentIndex < agentSessions.length; r++) {
143
+ const surface = grid[c][r];
144
+ const session = agentSessions[agentIndex];
145
+ const sendResult = await this.cmuxAdapter.sendText(surface, `tmux attach -t ${session}\n`, workspaceId);
146
+ if (!sendResult.ok)
147
+ return sendResult;
148
+ agentIndex += 1;
149
+ }
150
+ }
151
+ // 5. Final settle. Per skill §5 gotcha 2 the very last send-key
152
+ // can drop if the script exits immediately; the sleep
153
+ // guarantees the terminal flushes the Enter character.
154
+ await this.sleep(FINAL_SETTLE_MS);
155
+ return {
156
+ ok: true,
157
+ data: {
158
+ workspaceId,
159
+ workspaceName,
160
+ agents: agentSessions.slice(),
161
+ blanks: layout.blanks,
162
+ },
163
+ };
164
+ }
165
+ async discoverInitialSurface(workspaceId) {
166
+ for (let attempt = 0; attempt < LIST_SURFACES_MAX_ATTEMPTS; attempt++) {
167
+ const result = await this.cmuxAdapter.listSurfaces(workspaceId);
168
+ if (!result.ok)
169
+ return result;
170
+ if (result.data.length > 0) {
171
+ return { ok: true, data: result.data[0].id };
172
+ }
173
+ if (attempt < LIST_SURFACES_MAX_ATTEMPTS - 1) {
174
+ await this.sleep(LIST_SURFACES_RETRY_DELAY_MS);
175
+ }
176
+ }
177
+ return {
178
+ ok: false,
179
+ code: "request_failed",
180
+ message: `buildWorkspace: workspace ${workspaceId} had no default surface after ${LIST_SURFACES_MAX_ATTEMPTS} attempts; cmux daemon may not be ready`,
181
+ };
182
+ }
183
+ }
184
+ //# sourceMappingURL=cmux-layout-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cmux-layout-service.js","sourceRoot":"","sources":["../../src/domain/cmux-layout-service.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type Database from "better-sqlite3";
2
+ import type { ClaudeCompactionEnforcer } from "./claude-compaction-enforcer.js";
2
3
  import type { ContextUsageStore } from "./context-usage-store.js";
3
4
  import { type NodeBinding, type ReadinessResult } from "./runtime-adapter.js";
4
5
  /** Default polling interval: 30 seconds. */
@@ -14,15 +15,28 @@ interface ClaudeContextProvisioner {
14
15
  * Polls known managed runtime context sources and persists the latest
15
16
  * normalized telemetry. Scheduler-only: no queries, no response shaping,
16
17
  * no in-memory truth.
18
+ *
19
+ * Slice 27: optional `compactionEnforcer` participates in each polling
20
+ * tick after persistence so policy-driven /compact triggers fire on the
21
+ * same observation the operator sees in the UI. Without an enforcer
22
+ * provided, polling behavior is unchanged.
17
23
  */
18
24
  export declare class ContextMonitor {
19
25
  private db;
20
26
  private store;
21
27
  private claudeContextProvisioner;
28
+ private compactionEnforcer;
22
29
  private timer;
23
- constructor(db: Database.Database, store: ContextUsageStore, claudeContextProvisioner?: ClaudeContextProvisioner);
30
+ constructor(db: Database.Database, store: ContextUsageStore, claudeContextProvisioner?: ClaudeContextProvisioner, compactionEnforcer?: ClaudeCompactionEnforcer);
24
31
  /** Discover active managed Claude sessions and poll their sidecar files. */
25
32
  pollOnce(): Promise<void>;
33
+ /**
34
+ * Slice 27 — invoke the enforcer with the latest observation. The
35
+ * enforcer owns policy + dedup + send; ContextMonitor only relays
36
+ * data and absorbs enforcer errors so a trigger-path fault never
37
+ * crashes telemetry polling.
38
+ */
39
+ private maybeAutoCompact;
26
40
  /** Start polling at the given interval. Idempotent. */
27
41
  start(intervalMs?: number): void;
28
42
  /** Stop polling. Safe to call before start or multiple times. */
@@ -1 +1 @@
1
- {"version":3,"file":"context-monitor.d.ts","sourceRoot":"","sources":["../../src/domain/context-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAE9B,4CAA4C;AAC5C,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAY/C,UAAU,wBAAwB;IAChC,sBAAsB,CAAC,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5F,UAAU,CAAC,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7D;AAED;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,wBAAwB,CAAkC;IAClE,OAAO,CAAC,KAAK,CAA+C;gBAG1D,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,iBAAiB,EACxB,wBAAwB,CAAC,EAAE,wBAAwB;IAOrD,4EAA4E;IACtE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB/B,uDAAuD;IACvD,KAAK,CAAC,UAAU,GAAE,MAAiC,GAAG,IAAI;IAW1D,iEAAiE;IACjE,IAAI,IAAI,IAAI;IAOZ,wEAAwE;IACxE,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,gBAAgB;YAeV,sBAAsB;CAuCrC"}
1
+ {"version":3,"file":"context-monitor.d.ts","sourceRoot":"","sources":["../../src/domain/context-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAChF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAG9B,4CAA4C;AAC5C,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAY/C,UAAU,wBAAwB;IAChC,sBAAsB,CAAC,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5F,UAAU,CAAC,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7D;AAED;;;;;;;;;GASG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,wBAAwB,CAAkC;IAClE,OAAO,CAAC,kBAAkB,CAAkC;IAC5D,OAAO,CAAC,KAAK,CAA+C;gBAG1D,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,iBAAiB,EACxB,wBAAwB,CAAC,EAAE,wBAAwB,EACnD,kBAAkB,CAAC,EAAE,wBAAwB;IAQ/C,4EAA4E;IACtE,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB/B;;;;;OAKG;YACW,gBAAgB;IAoB9B,uDAAuD;IACvD,KAAK,CAAC,UAAU,GAAE,MAAiC,GAAG,IAAI;IAW1D,iEAAiE;IACjE,IAAI,IAAI,IAAI;IAOZ,wEAAwE;IACxE,OAAO,CAAC,mBAAmB;IAuB3B,OAAO,CAAC,gBAAgB;YAeV,sBAAsB;CAuCrC"}
@@ -5,26 +5,35 @@ export const DEFAULT_POLL_INTERVAL_MS = 30_000;
5
5
  * Polls known managed runtime context sources and persists the latest
6
6
  * normalized telemetry. Scheduler-only: no queries, no response shaping,
7
7
  * no in-memory truth.
8
+ *
9
+ * Slice 27: optional `compactionEnforcer` participates in each polling
10
+ * tick after persistence so policy-driven /compact triggers fire on the
11
+ * same observation the operator sees in the UI. Without an enforcer
12
+ * provided, polling behavior is unchanged.
8
13
  */
9
14
  export class ContextMonitor {
10
15
  db;
11
16
  store;
12
17
  claudeContextProvisioner;
18
+ compactionEnforcer;
13
19
  timer = null;
14
- constructor(db, store, claudeContextProvisioner) {
20
+ constructor(db, store, claudeContextProvisioner, compactionEnforcer) {
15
21
  this.db = db;
16
22
  this.store = store;
17
23
  this.claudeContextProvisioner = claudeContextProvisioner ?? null;
24
+ this.compactionEnforcer = compactionEnforcer ?? null;
18
25
  }
19
26
  /** Discover active managed Claude sessions and poll their sidecar files. */
20
27
  async pollOnce() {
21
28
  const sessions = this.getEligibleSessions();
22
29
  for (const session of sessions) {
30
+ let observed = null;
23
31
  try {
24
- const usage = this.readContextUsage(session);
25
- this.store.persist(session.node_id, usage);
32
+ observed = this.readContextUsage(session);
33
+ this.store.persist(session.node_id, observed);
26
34
  }
27
35
  catch {
36
+ observed = null;
28
37
  // One bad session must not crash polling for others
29
38
  try {
30
39
  this.store.persist(session.node_id, this.store.unknownUsage("parse_error"));
@@ -32,6 +41,32 @@ export class ContextMonitor {
32
41
  catch { /* give up on this session */ }
33
42
  }
34
43
  await this.normalizeStartupStatus(session);
44
+ await this.maybeAutoCompact(session, observed);
45
+ }
46
+ }
47
+ /**
48
+ * Slice 27 — invoke the enforcer with the latest observation. The
49
+ * enforcer owns policy + dedup + send; ContextMonitor only relays
50
+ * data and absorbs enforcer errors so a trigger-path fault never
51
+ * crashes telemetry polling.
52
+ */
53
+ async maybeAutoCompact(session, usage) {
54
+ if (!this.compactionEnforcer)
55
+ return;
56
+ if (!usage || usage.availability !== "known")
57
+ return;
58
+ try {
59
+ await this.compactionEnforcer.maybeAutoCompact({
60
+ sessionName: session.session_name,
61
+ runtime: session.runtime,
62
+ usedPercentage: usage.usedPercentage,
63
+ transcriptPath: usage.transcriptPath,
64
+ sessionId: usage.sessionId,
65
+ });
66
+ }
67
+ catch {
68
+ // Defensive: enforcer should not throw, but absorb here so the
69
+ // polling loop continues to make progress for remaining sessions.
35
70
  }
36
71
  }
37
72
  /** Start polling at the given interval. Idempotent. */
@@ -1 +1 @@
1
- {"version":3,"file":"context-monitor.js","sourceRoot":"","sources":["../../src/domain/context-monitor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context-monitor.js","sourceRoot":"","sources":["../../src/domain/context-monitor.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,gCAAgC,GAGjC,MAAM,sBAAsB,CAAC;AAG9B,4CAA4C;AAC5C,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAiB/C;;;;;;;;;GASG;AACH,MAAM,OAAO,cAAc;IACjB,EAAE,CAAoB;IACtB,KAAK,CAAoB;IACzB,wBAAwB,CAAkC;IAC1D,kBAAkB,CAAkC;IACpD,KAAK,GAA0C,IAAI,CAAC;IAE5D,YACE,EAAqB,EACrB,KAAwB,EACxB,wBAAmD,EACnD,kBAA6C;QAE7C,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,wBAAwB,GAAG,wBAAwB,IAAI,IAAI,CAAC;QACjE,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,IAAI,IAAI,CAAC;IACvD,CAAC;IAED,4EAA4E;IAC5E,KAAK,CAAC,QAAQ;QACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC5C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,QAAQ,GAAwB,IAAI,CAAC;YACzC,IAAI,CAAC;gBACH,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBAC1C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC;gBACP,QAAQ,GAAG,IAAI,CAAC;gBAChB,oDAAoD;gBACpD,IAAI,CAAC;oBACH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC;gBAC9E,CAAC;gBAAC,MAAM,CAAC,CAAC,6BAA6B,CAAC,CAAC;YAC3C,CAAC;YAED,MAAM,IAAI,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;YAC3C,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,gBAAgB,CAC5B,OAAwB,EACxB,KAA0B;QAE1B,IAAI,CAAC,IAAI,CAAC,kBAAkB;YAAE,OAAO;QACrC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,YAAY,KAAK,OAAO;YAAE,OAAO;QACrD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC;gBAC7C,WAAW,EAAE,OAAO,CAAC,YAAY;gBACjC,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,+DAA+D;YAC/D,kEAAkE;QACpE,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,KAAK,CAAC,aAAqB,wBAAwB;QACjD,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,kBAAkB;QAC1C,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;QACvB,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,oDAAoD;QACpD,IAAI,IAAI,CAAC,KAAK,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACzE,IAAI,CAAC,KAAwB,CAAC,KAAK,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IAED,iEAAiE;IACjE,IAAI;QACF,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;IAED,wEAAwE;IAChE,mBAAmB;QACzB,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;KAmBtB,CAAC,CAAC,GAAG,EAAuB,CAAC;IAChC,CAAC;IAEO,gBAAgB,CAAC,OAAwB;QAC/C,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC,KAAK,CAAC,qBAAqB,CAAC;gBACtC,QAAQ,EAAE,OAAO,CAAC,YAAY;gBAC9B,WAAW,EAAE,OAAO,CAAC,YAAY;aAClC,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,wBAAwB,EAAE,sBAAsB,CAAC;YACpD,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,SAAS;YAC7B,WAAW,EAAE,OAAO,CAAC,YAAY;SAClC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3D,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAAC,OAAwB;QAC3D,IAAI,OAAO,CAAC,OAAO,KAAK,aAAa;YAAE,OAAO;QAC9C,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,UAAU;YAAE,OAAO;QACvD,IAAI,OAAO,CAAC,cAAc,KAAK,QAAQ,IAAI,OAAO,CAAC,cAAc,KAAK,oBAAoB;YAAE,OAAO;QAEnG,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,UAAU,CAAC;gBAC/D,EAAE,EAAE,mBAAmB,OAAO,CAAC,UAAU,EAAE;gBAC3C,MAAM,EAAE,OAAO,CAAC,OAAO;gBACvB,cAAc,EAAE,MAAM;gBACtB,WAAW,EAAE,OAAO,CAAC,YAAY;gBACjC,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,IAAI;gBACnB,WAAW,EAAE,IAAI;gBACjB,SAAS,EAAE,EAAE;gBACb,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE;aACvB,CAAC,CAAC;YACH,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;gBACpB,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;SAKf,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;gBACrD,OAAO;YACT,CAAC;YAED,IAAI,gCAAgC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrD,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;SAIf,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;QACtE,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,74 @@
1
+ import type { EventBus } from "./event-bus.js";
2
+ import type { SessionRegistry } from "./session-registry.js";
3
+ import type { RigRepository } from "./rig-repository.js";
4
+ import type { BootstrapResult } from "./bootstrap-orchestrator.js";
5
+ export type KernelState = "skipped" | "auth_blocked" | "spec_missing" | "booting" | "partial_ready" | "ready" | "bootstrap_failed" | "degraded";
6
+ export interface KernelAgentStatus {
7
+ /** Session name (e.g. `advisor-lead@kernel`). */
8
+ sessionName: string;
9
+ /** Runtime declared in the agent profile (claude-code / codex / terminal). */
10
+ runtime: string;
11
+ /** Startup status from the sessions table. Same enum as session-registry. */
12
+ startupStatus: "pending" | "ready" | "attention_required" | "failed";
13
+ }
14
+ export interface KernelBootStatus {
15
+ kernelState: KernelState;
16
+ agents: KernelAgentStatus[];
17
+ /** ISO timestamp of when the kernel first entered booting; null in
18
+ * terminal/skipped states. */
19
+ firstUnreadySince: string | null;
20
+ /** Filename of the picked variant (rig.yaml / rig-claude-only.yaml /
21
+ * rig-codex-only.yaml). null when no variant was selected. */
22
+ variant: string | null;
23
+ /** Human-readable detail for auth_blocked / spec_missing /
24
+ * bootstrap_failed / degraded states. null otherwise. */
25
+ detail: string | null;
26
+ }
27
+ export interface KernelBootTrackerDeps {
28
+ eventBus: EventBus;
29
+ sessionRegistry: SessionRegistry;
30
+ rigRepo: RigRepository;
31
+ /** Milliseconds the tracker waits in `booting` before emitting
32
+ * `kernel.agent.degraded` and transitioning to the `degraded` state.
33
+ * Default 90_000 (90s) per IMPL-PRD §6.3 amendment. Tests pass
34
+ * shorter values; daemon startup honors the OPENRIG_KERNEL_DEGRADED_MS
35
+ * env override resolved by startup.ts. */
36
+ degradedTimeoutMs?: number;
37
+ }
38
+ export declare class KernelBootTracker {
39
+ private readonly deps;
40
+ private state;
41
+ private variant;
42
+ private detail;
43
+ private firstUnreadySince;
44
+ private degradedTimer;
45
+ private degradedEmitted;
46
+ private bootstrapInFlight;
47
+ constructor(deps: KernelBootTrackerDeps);
48
+ /** Mark the tracker as having intentionally not booted (--no-kernel,
49
+ * already-managed short-circuit, VITEST auto-skip). Terminal state;
50
+ * no degraded timer. */
51
+ setSkipped(detail: string): void;
52
+ /** Auth-blocked terminal. Operator sees the 3-part error in detail. */
53
+ setAuthBlocked(message: string): void;
54
+ /** Spec-missing terminal. Path is in detail for ops triage. */
55
+ setSpecMissing(specPath: string): void;
56
+ /** Begin tracking an in-flight bootstrap. The bootstrap promise
57
+ * is awaited internally; the caller does NOT block on it. */
58
+ startBooting(variant: string, bootstrapPromise: Promise<BootstrapResult>): void;
59
+ /** Read current status. Computes agents[] live from the sessions
60
+ * table so the response always reflects the freshest startup_status. */
61
+ getStatus(): KernelBootStatus;
62
+ /** Stop the degraded timer. Safe to call from anywhere (idempotent).
63
+ * Production callers don't need this; tests + graceful daemon
64
+ * shutdown do. */
65
+ stop(): void;
66
+ private onBootstrapComplete;
67
+ private onBootstrapError;
68
+ private aggregateReadinessFromAgents;
69
+ private computeAgents;
70
+ private scheduleDegradedTimer;
71
+ private cancelTimer;
72
+ private checkDegraded;
73
+ }
74
+ //# sourceMappingURL=kernel-boot-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kernel-boot-tracker.d.ts","sourceRoot":"","sources":["../../src/domain/kernel-boot-tracker.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,MAAM,WAAW,GACnB,SAAS,GACT,cAAc,GACd,cAAc,GACd,SAAS,GACT,eAAe,GACf,OAAO,GACP,kBAAkB,GAClB,UAAU,CAAC;AAEf,MAAM,WAAW,iBAAiB;IAChC,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,aAAa,EAAE,SAAS,GAAG,OAAO,GAAG,oBAAoB,GAAG,QAAQ,CAAC;CACtE;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B;mCAC+B;IAC/B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;mEAC+D;IAC/D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;8DAC0D;IAC1D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,QAAQ,CAAC;IACnB,eAAe,EAAE,eAAe,CAAC;IACjC,OAAO,EAAE,aAAa,CAAC;IACvB;;;;+CAI2C;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,qBAAa,iBAAiB;IAShB,OAAO,CAAC,QAAQ,CAAC,IAAI;IARjC,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,iBAAiB,CAAS;gBAEL,IAAI,EAAE,qBAAqB;IAExD;;6BAEyB;IACzB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAOhC,uEAAuE;IACvE,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAOrC,+DAA+D;IAC/D,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAOtC;kEAC8D;IAC9D,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAe/E;6EACyE;IACzE,SAAS,IAAI,gBAAgB;IAoB7B;;uBAEmB;IACnB,IAAI,IAAI,IAAI;IAIZ,OAAO,CAAC,mBAAmB;IAoB3B,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,4BAA4B;IAepC,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,qBAAqB;IAW7B,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,aAAa;CA6BtB"}
@@ -0,0 +1,213 @@
1
+ // V0.3.1 slice 05 kernel-rig-as-default — forward-fix #3 architectural.
2
+ // Decouples daemon health/listen from kernel-agent readiness.
3
+ //
4
+ // Prior behavior: `bootKernelIfNeeded` awaited `bootstrapOrchestrator.bootstrap(...)`
5
+ // inside `createDaemon`, so the daemon process couldn't reach `serve()` until
6
+ // the kernel rig's members had been launched + their startup deliveries
7
+ // completed. A broken kernel agent (e.g., Codex unauthenticated mid-boot)
8
+ // stalled healthz too. The CLI then reported "daemon failed to start" even
9
+ // though the daemon itself was perfectly happy — only the *kernel* was sad.
10
+ //
11
+ // New behavior: `bootKernelIfNeeded` builds a tracker, fires the bootstrap
12
+ // in the background, and returns immediately. The daemon binds healthz as
13
+ // soon as `createDaemon` completes (HTTP server bind happens in server.ts
14
+ // right after). Tracker state is published via GET /api/kernel/status so
15
+ // operators (and CLI flags like `--wait-for-kernel`) can observe progress.
16
+ //
17
+ // A configurable degraded-timer (default 90s) emits a single
18
+ // `kernel.agent.degraded` event if the kernel doesn't reach a ready / partial-
19
+ // ready state in time — telemetry that something is keeping the kernel
20
+ // stuck (auth / spec / tmux / etc.).
21
+ export class KernelBootTracker {
22
+ deps;
23
+ state = "skipped";
24
+ variant = null;
25
+ detail = null;
26
+ firstUnreadySince = null;
27
+ degradedTimer = null;
28
+ degradedEmitted = false;
29
+ bootstrapInFlight = false;
30
+ constructor(deps) {
31
+ this.deps = deps;
32
+ }
33
+ /** Mark the tracker as having intentionally not booted (--no-kernel,
34
+ * already-managed short-circuit, VITEST auto-skip). Terminal state;
35
+ * no degraded timer. */
36
+ setSkipped(detail) {
37
+ this.cancelTimer();
38
+ this.state = "skipped";
39
+ this.detail = detail;
40
+ this.firstUnreadySince = null;
41
+ }
42
+ /** Auth-blocked terminal. Operator sees the 3-part error in detail. */
43
+ setAuthBlocked(message) {
44
+ this.cancelTimer();
45
+ this.state = "auth_blocked";
46
+ this.detail = message;
47
+ this.firstUnreadySince = null;
48
+ }
49
+ /** Spec-missing terminal. Path is in detail for ops triage. */
50
+ setSpecMissing(specPath) {
51
+ this.cancelTimer();
52
+ this.state = "spec_missing";
53
+ this.detail = specPath;
54
+ this.firstUnreadySince = null;
55
+ }
56
+ /** Begin tracking an in-flight bootstrap. The bootstrap promise
57
+ * is awaited internally; the caller does NOT block on it. */
58
+ startBooting(variant, bootstrapPromise) {
59
+ if (this.bootstrapInFlight)
60
+ return;
61
+ this.bootstrapInFlight = true;
62
+ this.state = "booting";
63
+ this.variant = variant;
64
+ this.detail = null;
65
+ this.firstUnreadySince = new Date().toISOString();
66
+ this.degradedEmitted = false;
67
+ this.scheduleDegradedTimer();
68
+ bootstrapPromise
69
+ .then((result) => this.onBootstrapComplete(result))
70
+ .catch((err) => this.onBootstrapError(err));
71
+ }
72
+ /** Read current status. Computes agents[] live from the sessions
73
+ * table so the response always reflects the freshest startup_status. */
74
+ getStatus() {
75
+ const agents = this.computeAgents();
76
+ let kernelState = this.state;
77
+ // Once bootstrap has completed (state == 'booting' before then),
78
+ // promote to ready / partial_ready based on agent startup_status.
79
+ if (this.state === "booting" && !this.bootstrapInFlight) {
80
+ kernelState = this.aggregateReadinessFromAgents(agents);
81
+ }
82
+ return {
83
+ kernelState,
84
+ agents,
85
+ firstUnreadySince: kernelState === "ready" || kernelState === "skipped"
86
+ ? null
87
+ : this.firstUnreadySince,
88
+ variant: this.variant,
89
+ detail: this.detail,
90
+ };
91
+ }
92
+ /** Stop the degraded timer. Safe to call from anywhere (idempotent).
93
+ * Production callers don't need this; tests + graceful daemon
94
+ * shutdown do. */
95
+ stop() {
96
+ this.cancelTimer();
97
+ }
98
+ onBootstrapComplete(result) {
99
+ this.bootstrapInFlight = false;
100
+ if (result.errors && result.errors.length > 0) {
101
+ this.cancelTimer();
102
+ this.state = "bootstrap_failed";
103
+ this.detail = result.errors.join("; ");
104
+ return;
105
+ }
106
+ // Bootstrap returned cleanly. State transitions to ready /
107
+ // partial_ready are computed on read from agents[]. Cancel the
108
+ // degraded timer ONLY when at least one agent is ready — until
109
+ // then, the kernel is still effectively booting and the operator
110
+ // wants the degraded telemetry if no agent ever reaches ready.
111
+ const agents = this.computeAgents();
112
+ const aggregated = this.aggregateReadinessFromAgents(agents);
113
+ if (aggregated === "ready" || aggregated === "partial_ready") {
114
+ this.cancelTimer();
115
+ }
116
+ }
117
+ onBootstrapError(err) {
118
+ this.bootstrapInFlight = false;
119
+ this.cancelTimer();
120
+ this.state = "bootstrap_failed";
121
+ this.detail = err instanceof Error ? err.message : String(err);
122
+ }
123
+ aggregateReadinessFromAgents(agents) {
124
+ if (agents.length === 0) {
125
+ // Bootstrap finished but no agents are registered yet (race
126
+ // window between session insert + status update). Keep state
127
+ // as booting so the operator sees progress, not a false ready.
128
+ return "booting";
129
+ }
130
+ const readyCount = agents.filter((a) => a.startupStatus === "ready").length;
131
+ if (readyCount === agents.length)
132
+ return "ready";
133
+ if (readyCount === 0)
134
+ return "booting";
135
+ return "partial_ready";
136
+ }
137
+ computeAgents() {
138
+ try {
139
+ const kernelRigs = this.deps.rigRepo.findRigsByName("kernel");
140
+ if (kernelRigs.length === 0)
141
+ return [];
142
+ const out = [];
143
+ for (const rig of kernelRigs) {
144
+ const sessions = this.deps.sessionRegistry.getSessionsForRig(rig.id);
145
+ for (const s of sessions) {
146
+ // session-registry's Session shape carries startupStatus +
147
+ // sessionName; runtime comes from the node row. Read minimal
148
+ // fields here so the tracker doesn't pull in node-repository.
149
+ out.push({
150
+ sessionName: s.sessionName,
151
+ runtime: s.runtime ?? "unknown",
152
+ startupStatus: s.startupStatus,
153
+ });
154
+ }
155
+ }
156
+ return out;
157
+ }
158
+ catch {
159
+ // Tracker must NEVER throw — /api/kernel/status returning a
160
+ // valid envelope with empty agents[] is more useful than a 500
161
+ // when the DB has a transient hiccup.
162
+ return [];
163
+ }
164
+ }
165
+ scheduleDegradedTimer() {
166
+ const ms = this.deps.degradedTimeoutMs ?? 90_000;
167
+ if (ms <= 0)
168
+ return;
169
+ this.cancelTimer();
170
+ this.degradedTimer = setTimeout(() => this.checkDegraded(), ms);
171
+ // Allow the daemon to exit cleanly without waiting on the timer.
172
+ if (typeof this.degradedTimer === "object" && "unref" in this.degradedTimer) {
173
+ this.degradedTimer.unref();
174
+ }
175
+ }
176
+ cancelTimer() {
177
+ if (this.degradedTimer !== null) {
178
+ clearTimeout(this.degradedTimer);
179
+ this.degradedTimer = null;
180
+ }
181
+ }
182
+ checkDegraded() {
183
+ const agents = this.computeAgents();
184
+ const aggregated = this.state === "booting"
185
+ ? this.aggregateReadinessFromAgents(agents)
186
+ : this.state;
187
+ if (aggregated === "ready" || aggregated === "partial_ready") {
188
+ // Made it before the deadline; no degraded emission.
189
+ return;
190
+ }
191
+ // Promote to degraded + emit telemetry exactly once.
192
+ if (this.degradedEmitted)
193
+ return;
194
+ this.degradedEmitted = true;
195
+ this.state = "degraded";
196
+ try {
197
+ this.deps.eventBus.emit({
198
+ type: "kernel.agent.degraded",
199
+ agents: agents.map((a) => ({
200
+ sessionName: a.sessionName,
201
+ runtime: a.runtime,
202
+ startupStatus: a.startupStatus,
203
+ })),
204
+ firstUnreadySince: this.firstUnreadySince,
205
+ detail: this.detail,
206
+ });
207
+ }
208
+ catch {
209
+ // Best-effort telemetry; tracker must not throw.
210
+ }
211
+ }
212
+ }
213
+ //# sourceMappingURL=kernel-boot-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kernel-boot-tracker.js","sourceRoot":"","sources":["../../src/domain/kernel-boot-tracker.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,8DAA8D;AAC9D,EAAE;AACF,sFAAsF;AACtF,8EAA8E;AAC9E,wEAAwE;AACxE,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,EAAE;AACF,2EAA2E;AAC3E,0EAA0E;AAC1E,0EAA0E;AAC1E,yEAAyE;AACzE,2EAA2E;AAC3E,EAAE;AACF,6DAA6D;AAC7D,+EAA+E;AAC/E,uEAAuE;AACvE,qCAAqC;AAoDrC,MAAM,OAAO,iBAAiB;IASC;IARrB,KAAK,GAAgB,SAAS,CAAC;IAC/B,OAAO,GAAkB,IAAI,CAAC;IAC9B,MAAM,GAAkB,IAAI,CAAC;IAC7B,iBAAiB,GAAkB,IAAI,CAAC;IACxC,aAAa,GAAyC,IAAI,CAAC;IAC3D,eAAe,GAAG,KAAK,CAAC;IACxB,iBAAiB,GAAG,KAAK,CAAC;IAElC,YAA6B,IAA2B;QAA3B,SAAI,GAAJ,IAAI,CAAuB;IAAG,CAAC;IAE5D;;6BAEyB;IACzB,UAAU,CAAC,MAAc;QACvB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAChC,CAAC;IAED,uEAAuE;IACvE,cAAc,CAAC,OAAe;QAC5B,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC;QACtB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAChC,CAAC;IAED,+DAA+D;IAC/D,cAAc,CAAC,QAAgB;QAC7B,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;QACvB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAChC,CAAC;IAED;kEAC8D;IAC9D,YAAY,CAAC,OAAe,EAAE,gBAA0C;QACtE,IAAI,IAAI,CAAC,iBAAiB;YAAE,OAAO;QACnC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,iBAAiB,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAClD,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;QAC7B,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAE7B,gBAAgB;aACb,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;aAClD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,CAAC;IAED;6EACyE;IACzE,SAAS;QACP,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,IAAI,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;QAC7B,iEAAiE;QACjE,kEAAkE;QAClE,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACxD,WAAW,GAAG,IAAI,CAAC,4BAA4B,CAAC,MAAM,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO;YACL,WAAW;YACX,MAAM;YACN,iBAAiB,EACf,WAAW,KAAK,OAAO,IAAI,WAAW,KAAK,SAAS;gBAClD,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,IAAI,CAAC,iBAAiB;YAC5B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;IACJ,CAAC;IAED;;uBAEmB;IACnB,IAAI;QACF,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAEO,mBAAmB,CAAC,MAAuB;QACjD,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;QAC/B,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC;YAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvC,OAAO;QACT,CAAC;QACD,2DAA2D;QAC3D,+DAA+D;QAC/D,+DAA+D;QAC/D,iEAAiE;QACjE,+DAA+D;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,4BAA4B,CAAC,MAAM,CAAC,CAAC;QAC7D,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,eAAe,EAAE,CAAC;YAC7D,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,GAAY;QACnC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC;QAC/B,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,kBAAkB,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,CAAC;IAEO,4BAA4B,CAClC,MAA2B;QAE3B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,4DAA4D;YAC5D,6DAA6D;YAC7D,+DAA+D;YAC/D,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;QAC5E,IAAI,UAAU,KAAK,MAAM,CAAC,MAAM;YAAE,OAAO,OAAO,CAAC;QACjD,IAAI,UAAU,KAAK,CAAC;YAAE,OAAO,SAAS,CAAC;QACvC,OAAO,eAAe,CAAC;IACzB,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YAC9D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YACvC,MAAM,GAAG,GAAwB,EAAE,CAAC;YACpC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACrE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;oBACzB,2DAA2D;oBAC3D,6DAA6D;oBAC7D,8DAA8D;oBAC9D,GAAG,CAAC,IAAI,CAAC;wBACP,WAAW,EAAE,CAAC,CAAC,WAAW;wBAC1B,OAAO,EAAG,CAA0B,CAAC,OAAO,IAAI,SAAS;wBACzD,aAAa,EAAE,CAAC,CAAC,aAAa;qBAC/B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;QAAC,MAAM,CAAC;YACP,4DAA4D;YAC5D,+DAA+D;YAC/D,sCAAsC;YACtC,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAEO,qBAAqB;QAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,IAAI,MAAM,CAAC;QACjD,IAAI,EAAE,IAAI,CAAC;YAAE,OAAO;QACpB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC;QAChE,iEAAiE;QACjE,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC3E,IAAI,CAAC,aAA8C,CAAC,KAAK,EAAE,CAAC;QAC/D,CAAC;IACH,CAAC;IAEO,WAAW;QACjB,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,EAAE,CAAC;YAChC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACjC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC5B,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,MAAM,UAAU,GACd,IAAI,CAAC,KAAK,KAAK,SAAS;YACtB,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,MAAM,CAAC;YAC3C,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QACjB,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,eAAe,EAAE,CAAC;YAC7D,qDAAqD;YACrD,OAAO;QACT,CAAC;QACD,qDAAqD;QACrD,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO;QACjC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;QACxB,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACtB,IAAI,EAAE,uBAAuB;gBAC7B,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACzB,WAAW,EAAE,CAAC,CAAC,WAAW;oBAC1B,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,aAAa,EAAE,CAAC,CAAC,aAAa;iBAC/B,CAAC,CAAC;gBACH,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;gBACzC,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,iDAAiD;QACnD,CAAC;IACH,CAAC;CACF"}