@wrongstack/webui-server 0.297.0 → 0.298.0

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 (187) hide show
  1. package/dist/index.js +1238 -398
  2. package/dist/server/backend-services.d.ts +2 -0
  3. package/dist/server/codemap-cache.d.ts +1 -0
  4. package/dist/server/connection-lifecycle.d.ts +13 -0
  5. package/dist/server/connections-health-route.d.ts +7 -1
  6. package/dist/server/context-editor.d.ts +1 -2
  7. package/dist/server/entry.js +940 -385
  8. package/dist/server/frontend-static-serve.d.ts +7 -0
  9. package/dist/server/governance-runtime.d.ts +30 -0
  10. package/dist/server/http-server.d.ts +7 -0
  11. package/dist/server/mcp-handlers.d.ts +3 -1
  12. package/dist/server/memory-handlers.d.ts +3 -3
  13. package/dist/server/pending-confirms.d.ts +9 -0
  14. package/dist/server/sdd-board-ws-handler.d.ts +1 -0
  15. package/dist/server/sdd-wizard-ws-handler.d.ts +2 -0
  16. package/dist/server/specs-ws-handler.d.ts +1 -0
  17. package/dist/server/types.d.ts +3 -1
  18. package/dist/server/ws-auth.d.ts +24 -0
  19. package/dist/server/ws-payload-validation.d.ts +18 -0
  20. package/dist/server/ws-utils.d.ts +12 -1
  21. package/package.json +12 -11
  22. package/dist/index.d.ts.map +0 -1
  23. package/dist/index.js.map +0 -7
  24. package/dist/protocol/client-conversation.d.ts.map +0 -1
  25. package/dist/protocol/client-integrations.d.ts.map +0 -1
  26. package/dist/protocol/client-operations.d.ts.map +0 -1
  27. package/dist/protocol/client-workspace.d.ts.map +0 -1
  28. package/dist/protocol/connection-fsm.d.ts.map +0 -1
  29. package/dist/protocol/decoder.d.ts.map +0 -1
  30. package/dist/protocol/index.d.ts.map +0 -1
  31. package/dist/protocol/index.js.map +0 -7
  32. package/dist/protocol/projections.d.ts.map +0 -1
  33. package/dist/protocol/registry.d.ts.map +0 -1
  34. package/dist/protocol/replay-payload.d.ts.map +0 -1
  35. package/dist/protocol/server-conversation.d.ts.map +0 -1
  36. package/dist/protocol/server-integrations.d.ts.map +0 -1
  37. package/dist/protocol/server-operations.d.ts.map +0 -1
  38. package/dist/protocol/server-workspace.d.ts.map +0 -1
  39. package/dist/protocol/types.d.ts.map +0 -1
  40. package/dist/protocol/version.d.ts.map +0 -1
  41. package/dist/server/agent-roster-handlers.d.ts.map +0 -1
  42. package/dist/server/agent-roster-routes.d.ts.map +0 -1
  43. package/dist/server/autonomy-routes.d.ts.map +0 -1
  44. package/dist/server/backend-services.d.ts.map +0 -1
  45. package/dist/server/boot.d.ts.map +0 -1
  46. package/dist/server/brain-handlers.d.ts.map +0 -1
  47. package/dist/server/brain-routes.d.ts.map +0 -1
  48. package/dist/server/chronicle-routes.d.ts.map +0 -1
  49. package/dist/server/client-presence.d.ts.map +0 -1
  50. package/dist/server/client-transport-routes.d.ts.map +0 -1
  51. package/dist/server/codebase-index-server-control.d.ts.map +0 -1
  52. package/dist/server/codebase-indexing.d.ts.map +0 -1
  53. package/dist/server/codemap-cache.d.ts.map +0 -1
  54. package/dist/server/codemap-handlers.d.ts.map +0 -1
  55. package/dist/server/codemap-telemetry.d.ts.map +0 -1
  56. package/dist/server/collaboration-ws-handler.d.ts.map +0 -1
  57. package/dist/server/completion-handlers.d.ts.map +0 -1
  58. package/dist/server/completion-routes.d.ts.map +0 -1
  59. package/dist/server/config-doctor.d.ts.map +0 -1
  60. package/dist/server/connection-handler.d.ts.map +0 -1
  61. package/dist/server/connection-lifecycle.d.ts.map +0 -1
  62. package/dist/server/connections-health-route.d.ts.map +0 -1
  63. package/dist/server/content-routes.d.ts.map +0 -1
  64. package/dist/server/context-editor.d.ts.map +0 -1
  65. package/dist/server/context-meta.d.ts.map +0 -1
  66. package/dist/server/conversation-operations.d.ts.map +0 -1
  67. package/dist/server/conversation-routes.d.ts.map +0 -1
  68. package/dist/server/custom-context-modes.d.ts.map +0 -1
  69. package/dist/server/deadcode-handlers.d.ts.map +0 -1
  70. package/dist/server/design-handlers.d.ts.map +0 -1
  71. package/dist/server/discover-mailbox-bridge.d.ts.map +0 -1
  72. package/dist/server/embedded-host-adapters.d.ts.map +0 -1
  73. package/dist/server/embedded-lifecycle.d.ts.map +0 -1
  74. package/dist/server/embedded-message-router.d.ts.map +0 -1
  75. package/dist/server/entry.d.ts.map +0 -1
  76. package/dist/server/entry.js.map +0 -7
  77. package/dist/server/eternal-iteration-broadcast.d.ts.map +0 -1
  78. package/dist/server/file-handlers.d.ts.map +0 -1
  79. package/dist/server/file-picker.d.ts.map +0 -1
  80. package/dist/server/frontend-static-serve.d.ts.map +0 -1
  81. package/dist/server/git-handlers.d.ts.map +0 -1
  82. package/dist/server/git-process.d.ts.map +0 -1
  83. package/dist/server/goal-handlers.d.ts.map +0 -1
  84. package/dist/server/goal-routes.d.ts.map +0 -1
  85. package/dist/server/goal-snapshot-routes.d.ts.map +0 -1
  86. package/dist/server/goal-ws-handler.d.ts.map +0 -1
  87. package/dist/server/handlers/index.d.ts.map +0 -1
  88. package/dist/server/handlers/worklist-handlers.d.ts.map +0 -1
  89. package/dist/server/handlers.js.map +0 -7
  90. package/dist/server/host-routes.d.ts.map +0 -1
  91. package/dist/server/http-server/analytics-handler.d.ts.map +0 -1
  92. package/dist/server/http-server/api-handlers.d.ts.map +0 -1
  93. package/dist/server/http-server.d.ts.map +0 -1
  94. package/dist/server/index.d.ts.map +0 -1
  95. package/dist/server/instance-registry.d.ts.map +0 -1
  96. package/dist/server/introspection-routes.d.ts.map +0 -1
  97. package/dist/server/kanban-board-watcher.d.ts.map +0 -1
  98. package/dist/server/kanban-daemon-subscriber.d.ts.map +0 -1
  99. package/dist/server/kanban-decomposition-routes.d.ts.map +0 -1
  100. package/dist/server/kanban-dispatch.d.ts.map +0 -1
  101. package/dist/server/kanban-host-routes.d.ts.map +0 -1
  102. package/dist/server/kanban-route-helpers.d.ts.map +0 -1
  103. package/dist/server/kanban-route-pagination.d.ts.map +0 -1
  104. package/dist/server/kanban-route-protocol.d.ts.map +0 -1
  105. package/dist/server/kanban-routes.d.ts.map +0 -1
  106. package/dist/server/kanban-run-mirror.d.ts.map +0 -1
  107. package/dist/server/kanban-supervisor.d.ts.map +0 -1
  108. package/dist/server/kanban-task-routes.d.ts.map +0 -1
  109. package/dist/server/lifecycle.d.ts.map +0 -1
  110. package/dist/server/mailbox-handlers.d.ts.map +0 -1
  111. package/dist/server/mailbox-routes.d.ts.map +0 -1
  112. package/dist/server/mcp-handlers.d.ts.map +0 -1
  113. package/dist/server/mcp-routes.d.ts.map +0 -1
  114. package/dist/server/memory-diagnostics.d.ts.map +0 -1
  115. package/dist/server/memory-handlers.d.ts.map +0 -1
  116. package/dist/server/memory-routes.d.ts.map +0 -1
  117. package/dist/server/message-dispatcher.d.ts.map +0 -1
  118. package/dist/server/mode-handlers.d.ts.map +0 -1
  119. package/dist/server/mode-operations.d.ts.map +0 -1
  120. package/dist/server/mode-routes.d.ts.map +0 -1
  121. package/dist/server/model-auto-discovery.d.ts.map +0 -1
  122. package/dist/server/model-catalog-search.d.ts.map +0 -1
  123. package/dist/server/model-catalog.d.ts.map +0 -1
  124. package/dist/server/model-operations.d.ts.map +0 -1
  125. package/dist/server/network-info.d.ts.map +0 -1
  126. package/dist/server/open-browser.d.ts.map +0 -1
  127. package/dist/server/path-containment.d.ts.map +0 -1
  128. package/dist/server/pending-confirms.d.ts.map +0 -1
  129. package/dist/server/port-utils.d.ts.map +0 -1
  130. package/dist/server/pre-context-services.d.ts.map +0 -1
  131. package/dist/server/pref-helpers.d.ts.map +0 -1
  132. package/dist/server/prefs-handlers.d.ts.map +0 -1
  133. package/dist/server/prefs-routes.d.ts.map +0 -1
  134. package/dist/server/privileged-actions.d.ts.map +0 -1
  135. package/dist/server/process-handlers.d.ts.map +0 -1
  136. package/dist/server/process-routes.d.ts.map +0 -1
  137. package/dist/server/project-handlers.d.ts.map +0 -1
  138. package/dist/server/project-routes.d.ts.map +0 -1
  139. package/dist/server/projects-manifest.d.ts.map +0 -1
  140. package/dist/server/prompts-handlers.d.ts.map +0 -1
  141. package/dist/server/provider-config-io.d.ts.map +0 -1
  142. package/dist/server/provider-config-standalone.d.ts.map +0 -1
  143. package/dist/server/provider-handlers.d.ts.map +0 -1
  144. package/dist/server/provider-keys.d.ts.map +0 -1
  145. package/dist/server/provider-routes.d.ts.map +0 -1
  146. package/dist/server/provider-store.d.ts.map +0 -1
  147. package/dist/server/route-family-dispatcher.d.ts.map +0 -1
  148. package/dist/server/routes.d.ts.map +0 -1
  149. package/dist/server/sdd-board-routes.d.ts.map +0 -1
  150. package/dist/server/sdd-board-ws-handler.d.ts.map +0 -1
  151. package/dist/server/sdd-wizard-routes.d.ts.map +0 -1
  152. package/dist/server/sdd-wizard-wiring.d.ts.map +0 -1
  153. package/dist/server/sdd-wizard-ws-handler.d.ts.map +0 -1
  154. package/dist/server/server-runtime.d.ts.map +0 -1
  155. package/dist/server/session-handlers.d.ts.map +0 -1
  156. package/dist/server/session-history.d.ts.map +0 -1
  157. package/dist/server/session-routes.d.ts.map +0 -1
  158. package/dist/server/setup-event-projection.d.ts.map +0 -1
  159. package/dist/server/setup-events-core-watchers.d.ts.map +0 -1
  160. package/dist/server/setup-events-fleet-broadcaster.d.ts.map +0 -1
  161. package/dist/server/setup-events-provider-handlers.d.ts.map +0 -1
  162. package/dist/server/setup-events-session-helpers.d.ts.map +0 -1
  163. package/dist/server/setup-events-status-watcher.d.ts.map +0 -1
  164. package/dist/server/setup-events-watcher.d.ts.map +0 -1
  165. package/dist/server/setup-events.d.ts.map +0 -1
  166. package/dist/server/setup-screen.d.ts.map +0 -1
  167. package/dist/server/shell-git-routes.d.ts.map +0 -1
  168. package/dist/server/shell-open.d.ts.map +0 -1
  169. package/dist/server/skills-handlers.d.ts.map +0 -1
  170. package/dist/server/specs-routes.d.ts.map +0 -1
  171. package/dist/server/specs-ws-handler.d.ts.map +0 -1
  172. package/dist/server/standalone-session-identity.d.ts.map +0 -1
  173. package/dist/server/start-webui.d.ts.map +0 -1
  174. package/dist/server/stream-coalescer.d.ts.map +0 -1
  175. package/dist/server/techstack-handlers.d.ts.map +0 -1
  176. package/dist/server/terminal-ws-handler.d.ts.map +0 -1
  177. package/dist/server/token-estimator.d.ts.map +0 -1
  178. package/dist/server/types.d.ts.map +0 -1
  179. package/dist/server/usage-cost.d.ts.map +0 -1
  180. package/dist/server/worklist-routes.d.ts.map +0 -1
  181. package/dist/server/worktree-routes.d.ts.map +0 -1
  182. package/dist/server/worktree-ws-handler.d.ts.map +0 -1
  183. package/dist/server/ws-auth.d.ts.map +0 -1
  184. package/dist/server/ws-payload-preferences.d.ts.map +0 -1
  185. package/dist/server/ws-payload-validation.d.ts.map +0 -1
  186. package/dist/server/ws-utils.d.ts.map +0 -1
  187. package/dist/server/zip.d.ts.map +0 -1
package/dist/index.js.map DELETED
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/server/prefs-handlers.ts", "../src/server/pending-confirms.ts", "../src/server/ws-payload-preferences.ts", "../src/server/ws-payload-validation.ts", "../src/server/ws-utils.ts", "../src/server/autonomy-routes.ts", "../src/server/boot.ts", "../src/server/brain-routes.ts", "../src/server/chronicle-routes.ts", "../src/server/client-transport-routes.ts", "../src/server/codebase-indexing.ts", "../src/server/codemap-cache.ts", "../src/server/codemap-telemetry.ts", "../src/server/collaboration-ws-handler.ts", "../src/server/completion-handlers.ts", "../src/server/completion-routes.ts", "../src/server/design-handlers.ts", "../src/server/file-handlers.ts", "../src/server/file-picker.ts", "../src/server/path-containment.ts", "../src/server/prompts-handlers.ts", "../src/server/skills-handlers.ts", "../src/server/zip.ts", "../src/server/content-routes.ts", "../src/server/conversation-routes.ts", "../src/server/conversation-operations.ts", "../src/server/context-editor.ts", "../src/server/token-estimator.ts", "../src/server/connection-lifecycle.ts", "../src/server/connections-health-route.ts", "../src/server/custom-context-modes.ts", "../src/server/eternal-iteration-broadcast.ts", "../src/server/git-handlers.ts", "../src/server/goal-handlers.ts", "../src/server/goal-routes.ts", "../src/server/goal-snapshot-routes.ts", "../src/server/goal-ws-handler.ts", "../src/server/git-process.ts", "../src/server/handlers/worklist-handlers.ts", "../src/server/host-routes.ts", "../src/server/http-server/analytics-handler.ts", "../src/server/http-server.ts", "../src/server/codemap-handlers.ts", "../src/server/deadcode-handlers.ts", "../src/server/http-server/api-handlers.ts", "../src/server/memory-diagnostics.ts", "../src/server/projects-manifest.ts", "../src/server/techstack-handlers.ts", "../src/server/ws-auth.ts", "../src/server/instance-registry.ts", "../src/server/model-catalog.ts", "../src/server/usage-cost.ts", "../src/server/introspection-routes.ts", "../src/server/kanban-dispatch.ts", "../src/server/kanban-host-routes.ts", "../src/server/kanban-routes.ts", "../src/server/kanban-decomposition-routes.ts", "../src/server/kanban-route-helpers.ts", "../src/server/kanban-task-routes.ts", "../src/server/kanban-route-pagination.ts", "../src/server/kanban-route-protocol.ts", "../src/server/kanban-daemon-subscriber.ts", "../src/server/kanban-board-watcher.ts", "../src/server/lifecycle.ts", "../src/server/config-doctor.ts", "../src/server/mailbox-handlers.ts", "../src/server/mailbox-routes.ts", "../src/server/mcp-handlers.ts", "../src/server/mcp-routes.ts", "../src/server/memory-handlers.ts", "../src/server/memory-routes.ts", "../src/server/mode-operations.ts", "../src/server/mode-routes.ts", "../src/server/model-operations.ts", "../src/server/open-browser.ts", "../src/server/port-utils.ts", "../src/server/frontend-static-serve.ts", "../src/server/embedded-lifecycle.ts", "../src/server/network-info.ts", "../src/server/stream-coalescer.ts", "../src/server/client-presence.ts", "../src/server/brain-handlers.ts", "../src/server/kanban-run-mirror.ts", "../src/server/kanban-supervisor.ts", "../src/server/context-meta.ts", "../src/server/pref-helpers.ts", "../src/server/prefs-routes.ts", "../src/server/process-handlers.ts", "../src/server/privileged-actions.ts", "../src/server/process-routes.ts", "../src/server/embedded-host-adapters.ts", "../src/server/project-handlers.ts", "../src/server/provider-handlers.ts", "../src/server/model-catalog-search.ts", "../src/server/provider-config-io.ts", "../src/server/provider-keys.ts", "../src/server/session-handlers.ts", "../src/protocol/connection-fsm.ts", "../src/protocol/client-conversation.ts", "../src/protocol/client-integrations.ts", "../src/protocol/client-operations.ts", "../src/protocol/client-workspace.ts", "../src/protocol/server-conversation.ts", "../src/protocol/server-integrations.ts", "../src/protocol/server-operations.ts", "../src/protocol/server-workspace.ts", "../src/protocol/registry.ts", "../src/protocol/decoder.ts", "../src/protocol/projections.ts", "../src/protocol/replay-payload.ts", "../src/protocol/version.ts", "../src/server/session-history.ts", "../src/server/embedded-message-router.ts", "../src/server/agent-roster-handlers.ts", "../src/server/codebase-index-server-control.ts", "../src/server/agent-roster-routes.ts", "../src/server/project-routes.ts", "../src/server/provider-routes.ts", "../src/server/sdd-board-routes.ts", "../src/server/sdd-wizard-routes.ts", "../src/server/session-routes.ts", "../src/server/shell-git-routes.ts", "../src/server/specs-routes.ts", "../src/server/worklist-routes.ts", "../src/server/worktree-routes.ts", "../src/server/route-family-dispatcher.ts", "../src/server/shell-open.ts", "../src/server/provider-config-standalone.ts", "../src/server/provider-store.ts", "../src/server/sdd-board-ws-handler.ts", "../src/server/sdd-wizard-wiring.ts", "../src/server/sdd-wizard-ws-handler.ts", "../src/server/setup-events.ts", "../src/server/setup-events-fleet-broadcaster.ts", "../src/server/setup-events-provider-handlers.ts", "../src/server/setup-events-session-helpers.ts", "../src/server/setup-events-status-watcher.ts", "../src/server/setup-events-watcher.ts", "../src/server/setup-events-core-watchers.ts", "../src/server/specs-ws-handler.ts", "../src/server/start-webui.ts", "../src/server/backend-services.ts", "../src/server/discover-mailbox-bridge.ts", "../src/server/terminal-ws-handler.ts", "../src/server/worktree-ws-handler.ts", "../src/server/connection-handler.ts", "../src/server/message-dispatcher.ts", "../src/server/pre-context-services.ts", "../src/server/model-auto-discovery.ts", "../src/server/setup-screen.ts", "../src/server/standalone-session-identity.ts", "../src/server/routes.ts", "../src/server/mode-handlers.ts", "../src/server/server-runtime.ts"],
4
- "sourcesContent": ["import type { ConfigStore } from '@wrongstack/core/types';\nimport { getProcessRegistry } from '@wrongstack/tools';\nimport type { WebSocket } from 'ws';\nimport { type PendingConfirm, resolveYoloEligiblePendingConfirms } from './pending-confirms.js';\nimport type { WSServerMessage } from './types.js';\nimport { validatePrefsUpdatePayload } from './ws-payload-validation.js';\n\nexport interface PrefsHandlerContext {\n meta: Record<string, unknown>;\n snapshot: () => Record<string, unknown>;\n persist: (payload: Record<string, unknown>) => Promise<void>;\n pendingConfirms: Map<string, PendingConfirm>;\n configStore?: ConfigStore | undefined;\n setYolo?: ((enabled: boolean) => void) | undefined;\n setAutonomy?: ((mode: string) => void) | undefined;\n applyConfigPrefs?: ((payload: Record<string, unknown>) => void) | undefined;\n setAutoCompact?: ((enabled: boolean) => void) | undefined;\n setLogLevel?: ((level: 'debug' | 'info' | 'warn' | 'error') => void) | undefined;\n send: (ws: WebSocket, message: WSServerMessage) => void;\n broadcast: (message: WSServerMessage) => void;\n}\n\nfunction sendResult(\n ctx: PrefsHandlerContext,\n ws: WebSocket,\n success: boolean,\n message: string,\n): void {\n ctx.send(ws, { type: 'key.operation_result', payload: { success, message } });\n}\n\nfunction routingPatch(payload: Record<string, unknown>): Record<string, unknown> {\n const patch: Record<string, unknown> = {};\n if (Array.isArray(payload['fallbackModels'])) patch['fallbackModels'] = payload['fallbackModels'];\n if (\n payload['fallbackProfiles'] &&\n typeof payload['fallbackProfiles'] === 'object' &&\n !Array.isArray(payload['fallbackProfiles'])\n ) {\n patch['fallbackProfiles'] = payload['fallbackProfiles'];\n }\n if (Array.isArray(payload['favoriteModels'])) patch['favoriteModels'] = payload['favoriteModels'];\n if (typeof payload['favoriteModelsOnly'] === 'boolean') {\n patch['favoriteModelsOnly'] = payload['favoriteModelsOnly'];\n }\n if (Array.isArray(payload['modelAvailabilitySchedule'])) {\n patch['modelAvailabilitySchedule'] = payload['modelAvailabilitySchedule'];\n }\n if (\n payload['modelMatrix'] &&\n typeof payload['modelMatrix'] === 'object' &&\n !Array.isArray(payload['modelMatrix'])\n ) {\n patch['modelMatrix'] = payload['modelMatrix'];\n }\n if (typeof payload['fallbackAuto'] === 'boolean') patch['fallbackAuto'] = payload['fallbackAuto'];\n return patch;\n}\n\nexport function handlePrefsGet(ctx: PrefsHandlerContext, ws: WebSocket): void {\n ctx.send(ws, { type: 'prefs.updated', payload: ctx.snapshot() });\n}\n\nexport function handlePrefsUpdate(\n ctx: PrefsHandlerContext,\n ws: WebSocket,\n input: Record<string, unknown>,\n): void {\n const parsed = validatePrefsUpdatePayload(input);\n if (!parsed.ok) {\n sendResult(ctx, ws, false, parsed.message);\n return;\n }\n const payload = parsed.value.prefs;\n for (const [key, value] of Object.entries(payload)) ctx.meta[key] = value;\n void ctx.persist(payload);\n\n if (typeof payload['yolo'] === 'boolean') {\n ctx.setYolo?.(payload['yolo']);\n if (payload['yolo']) resolveYoloEligiblePendingConfirms(ctx.pendingConfirms);\n }\n\n ctx.applyConfigPrefs?.(payload);\n const patch = routingPatch(payload);\n if (ctx.configStore && Object.keys(patch).length > 0) ctx.configStore.update(patch as never);\n\n if (typeof payload['contextAutoCompact'] === 'boolean') {\n ctx.setAutoCompact?.(payload['contextAutoCompact']);\n }\n if (\n typeof payload['breakerEnabled'] === 'boolean' ||\n typeof payload['breakerAutoKillResetMs'] === 'number'\n ) {\n getProcessRegistry().setBreakerConfig({\n ...(typeof payload['breakerEnabled'] === 'boolean'\n ? { enabled: payload['breakerEnabled'] }\n : {}),\n ...(typeof payload['breakerAutoKillResetMs'] === 'number'\n ? { autoKillResetMs: payload['breakerAutoKillResetMs'] }\n : {}),\n });\n }\n if (typeof payload['debugStream'] === 'boolean') {\n void import('@wrongstack/providers').then(({ setDebugStreamEnabled }) =>\n setDebugStreamEnabled(payload['debugStream'] as boolean),\n );\n }\n if (\n typeof payload['logLevel'] === 'string' &&\n ['debug', 'info', 'warn', 'error'].includes(payload['logLevel'])\n ) {\n ctx.setLogLevel?.(payload['logLevel'] as 'debug' | 'info' | 'warn' | 'error');\n }\n ctx.broadcast({ type: 'prefs.updated', payload: ctx.snapshot() });\n}\n\nexport function handleAutonomySwitch(ctx: PrefsHandlerContext, ws: WebSocket, mode: string): void {\n ctx.meta['autonomy'] = mode;\n ctx.setAutonomy?.(mode);\n sendResult(ctx, ws, true, `Autonomy mode set to \"${mode}\"`);\n ctx.broadcast({ type: 'prefs.updated', payload: { autonomy: mode } });\n void ctx.persist({ autonomy: mode });\n}\n", "export type ConfirmDecision = 'yes' | 'no' | 'always' | 'deny';\n\nexport interface PendingConfirm {\n resolve: (decision: ConfirmDecision) => void;\n decisionSource?: string | undefined;\n riskTier?: 'safe' | 'standard' | 'destructive' | undefined;\n boundaryReason?: string | undefined;\n /** The exact `tool.confirm_needed` broadcast payload, kept so the prompt\n * can be replayed to clients that connect while the confirm is pending\n * (e.g. a browser refresh mid-prompt). */\n payload?: Record<string, unknown> | undefined;\n}\n\nexport function isDestructivePendingConfirm(confirm: PendingConfirm): boolean {\n return confirm.riskTier === 'destructive' || confirm.decisionSource === 'yolo_destructive';\n}\n\nexport function resolveYoloEligiblePendingConfirms(\n pendingConfirms: Map<string, PendingConfirm>,\n): void {\n for (const [id, confirm] of pendingConfirms) {\n if (confirm.boundaryReason) continue;\n pendingConfirms.delete(id);\n confirm.resolve('yes');\n }\n}\n\nexport function resolveAllPendingConfirms(\n pendingConfirms: Map<string, PendingConfirm>,\n decision: ConfirmDecision,\n): void {\n for (const [id, confirm] of pendingConfirms) {\n pendingConfirms.delete(id);\n confirm.resolve(decision);\n }\n}\n", "import { FORBIDDEN_PROTO_KEYS } from '@wrongstack/core/utils';\n\ntype PayloadValidationResult<T> = { ok: true; value: T } | { ok: false; message: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\ninterface PrefsUpdatePayload {\n prefs: Record<string, unknown>;\n}\n\nconst AUTONOMY_VALUES = new Set(['off', 'suggest', 'auto', 'eternal', 'eternal-parallel']);\nconst CONTEXT_STRATEGY_VALUES = new Set(['hybrid', 'intelligent', 'selective']);\nconst CONTEXT_MODE_VALUES = new Set(['balanced', 'frugal', 'deep']);\nconst TOKEN_SAVING_TIER_VALUES = new Set(['off', 'minimal', 'light', 'medium', 'aggressive']);\nconst ENHANCE_LANGUAGE_VALUES = new Set(['original', 'english']);\nconst LOG_LEVEL_VALUES = new Set(['debug', 'info', 'warn', 'error']);\nconst AUDIT_LEVEL_VALUES = new Set(['minimal', 'standard', 'full']);\nconst REASONING_MODE_VALUES = new Set(['auto', 'on', 'off']);\nconst REASONING_EFFORT_VALUES = new Set([\n 'none',\n 'minimal',\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n 'max',\n]);\nconst CACHE_TTL_VALUES = new Set(['default', '5m', '1h']);\n\nconst BOOLEAN_PREF_KEYS = new Set([\n 'yolo',\n 'chime',\n 'confirmExit',\n 'nextPrediction',\n 'titleAnimation',\n 'enhanceEnabled',\n 'featureMcp',\n 'featurePlugins',\n 'featureMemory',\n 'featureSkills',\n 'featureModelsRegistry',\n 'indexOnStart',\n 'contextAutoCompact',\n 'tgSessionEnd',\n 'tgDelegate',\n 'reasoningPreserve',\n 'hqEnabled',\n 'hqRawContent',\n 'fallbackAuto',\n 'favoriteModelsOnly',\n 'breakerEnabled',\n 'debugStream',\n // Chimera + auto-review master toggles\n 'chimeraEnabled',\n 'autoReviewEnabled',\n 'showModelReasoning',\n // Display-only toggles (purely visual, persisted in localStorage via Zustand).\n 'groupToolCalls',\n 'showThinkingLogs',\n]);\n\n/** Keys whose value must be an array of strings (e.g. an ordered model list). */\nconst STRING_ARRAY_PREF_KEYS = new Set([\n 'fallbackModels',\n 'favoriteModels',\n // Auto-review explicit fallback chain (derived when fallbackProfile is unset;\n // surfaced for visibility/override).\n 'autoReviewFallbackModels',\n]);\nconst STRING_ARRAY_RECORD_PREF_KEYS = new Set(['fallbackProfiles']);\n/** Map of array-typed pref keys to their element-level validator. */\nconst ARRAY_PREF_VALIDATORS: Record<\n string,\n (item: Record<string, unknown>, path: string) => string | null\n> = {\n modelAvailabilitySchedule: validateModelBlackoutRule,\n};\nconst MODEL_MATRIX_PREF_KEYS = new Set(['modelMatrix']);\n// Object of booleans, e.g. { 'plugin-name': true }. Parity with the embedded\n// server, which accepts `pluginsEnabled` and persists it to\n// extensions.<name>.enabled \u2014 the standalone server rejected it as unknown.\nconst BOOLEAN_RECORD_PREF_KEYS = new Set(['pluginsEnabled']);\n\nconst NUMBER_PREF_KEYS = new Set([\n 'autonomyDelayMs',\n 'autoProceedMaxIterations',\n 'maxIterations',\n 'maxConcurrent',\n 'enhanceDelayMs',\n 'tgLongToolMs',\n 'breakerAutoKillResetMs',\n // Chimera + auto-review numeric knobs\n 'chimeraMaxFiles',\n 'autoReviewDebounceMs',\n 'autoReviewMaxFilesPerBatch',\n 'autoReviewMaxConcurrentReviews',\n]);\n\nconst STRING_PREF_KEYS = new Set([\n 'hqUrl',\n 'hqToken',\n 'uiLocale',\n 'thinkingWord',\n 'refinerProvider',\n 'refinerModel',\n 'refinerFallbackProfile',\n // Chimera + auto-review override strings\n 'chimeraProvider',\n 'chimeraModel',\n 'autoReviewProvider',\n 'autoReviewModel',\n 'autoReviewFallbackProfile',\n]);\n\nconst ENUM_PREF_KEYS: Record<string, Set<string>> = {\n autonomy: AUTONOMY_VALUES,\n contextStrategy: CONTEXT_STRATEGY_VALUES,\n contextMode: CONTEXT_MODE_VALUES,\n tokenSavingTier: TOKEN_SAVING_TIER_VALUES,\n enhanceLanguage: ENHANCE_LANGUAGE_VALUES,\n logLevel: LOG_LEVEL_VALUES,\n auditLevel: AUDIT_LEVEL_VALUES,\n reasoningMode: REASONING_MODE_VALUES,\n reasoningEffort: REASONING_EFFORT_VALUES,\n cacheTtl: CACHE_TTL_VALUES,\n statuslineMode: new Set(['minimum', 'detailed', 'no-color']),\n animationStyle: new Set(['rainbow', 'wave', 'pulse', 'dots', 'breathe', 'cycle']),\n fsAccess: new Set(['unrestricted', 'project']),\n // Chimera autoFix + auto-review cascade threshold\n chimeraAutoFix: new Set(['off', 'ask', 'auto']),\n autoReviewCascadeOn: new Set(['off', 'critical', 'high']),\n fleetChatVerbosity: new Set(['off', 'full']),\n};\n\nfunction validateModelRuntimeValue(\n modelRuntime: Record<string, unknown>,\n path: string,\n): string | null {\n const reasoning = modelRuntime['reasoning'];\n if (reasoning !== undefined) {\n if (!isRecord(reasoning)) return `${path}.reasoning must be an object when provided`;\n const mode = reasoning['mode'];\n const effort = reasoning['effort'];\n const preserve = reasoning['preserve'];\n if (mode !== undefined && (typeof mode !== 'string' || !REASONING_MODE_VALUES.has(mode))) {\n return `${path}.reasoning.mode must be one of: ${Array.from(REASONING_MODE_VALUES).join(', ')}`;\n }\n if (\n effort !== undefined &&\n (typeof effort !== 'string' || !REASONING_EFFORT_VALUES.has(effort))\n ) {\n return `${path}.reasoning.effort must be one of: ${Array.from(REASONING_EFFORT_VALUES).join(', ')}`;\n }\n if (preserve !== undefined && typeof preserve !== 'boolean') {\n return `${path}.reasoning.preserve must be a boolean when provided`;\n }\n }\n\n const cache = modelRuntime['cache'];\n if (cache !== undefined) {\n if (!isRecord(cache)) return `${path}.cache must be an object when provided`;\n const ttl = cache['ttl'];\n if (\n ttl !== undefined &&\n (typeof ttl !== 'string' || !CACHE_TTL_VALUES.has(ttl) || ttl === 'default')\n ) {\n return `${path}.cache.ttl must be one of: 5m, 1h`;\n }\n }\n\n const parameters = modelRuntime['parameters'];\n if (parameters !== undefined && !isRecord(parameters)) {\n return `${path}.parameters must be an object when provided`;\n }\n\n return null;\n}\n\n/** Validate a single ModelBlackoutRule element. */\nfunction validateModelBlackoutRule(\n rule: Record<string, unknown>,\n path: string,\n): string | null {\n const id = rule['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return `${path}.id must be a non-empty string`;\n }\n const start = rule['start'];\n if (typeof start !== 'string' || !/^([01]\\d|2[0-3]):[0-5]\\d$/.test(start)) {\n return `${path}.start must be a string in HH:mm (00:00-23:59) format`;\n }\n const end = rule['end'];\n if (typeof end !== 'string' || !/^([01]\\d|2[0-3]):[0-5]\\d$/.test(end)) {\n return `${path}.end must be a string in HH:mm (00:00-23:59) format`;\n }\n // start >= end is valid: it means the rule crosses midnight (overnight).\n // e.g., start=22:00, end=06:00 blocks from 10 PM to 6 AM the next day.\n // (if the caller intends same-day scheduling they must ensure start < end).\n if (rule['enabled'] !== undefined && typeof rule['enabled'] !== 'boolean') {\n return `${path}.enabled must be a boolean when provided`;\n }\n if (rule['provider'] !== undefined && typeof rule['provider'] !== 'string') {\n return `${path}.provider must be a string when provided`;\n }\n if (rule['model'] !== undefined && typeof rule['model'] !== 'string') {\n return `${path}.model must be a string when provided`;\n }\n if (rule['days'] !== undefined) {\n if (!Array.isArray(rule['days'])) return `${path}.days must be an array when provided`;\n const seen = new Set<number>();\n for (const d of rule['days']) {\n if (typeof d !== 'number' || !Number.isInteger(d) || d < 0 || d > 6) {\n return `${path}.days elements must be integers 0-6 when provided`;\n }\n if (seen.has(d)) return `${path}.days contains duplicate day: ${d}`;\n seen.add(d);\n }\n }\n if (rule['timezone'] !== undefined) {\n if (typeof rule['timezone'] !== 'string') {\n return `${path}.timezone must be a string when provided`;\n }\n try {\n Intl.DateTimeFormat(undefined, { timeZone: rule['timezone'] as string });\n } catch {\n return `${path}.timezone is not a valid IANA timezone (e.g. \"America/New_York\")`;\n }\n }\n if (rule['label'] !== undefined && typeof rule['label'] !== 'string') {\n return `${path}.label must be a string when provided`;\n }\n if (\n rule['mode'] !== undefined &&\n rule['mode'] !== 'blackout' &&\n rule['mode'] !== 'allow_only'\n ) {\n return `${path}.mode must be 'blackout' or 'allow_only' when provided`;\n }\n return null;\n}\n\nfunction validatePreferenceValue(key: string, value: unknown): string | null {\n if (BOOLEAN_PREF_KEYS.has(key)) {\n return typeof value === 'boolean' ? null : `prefs.update payload.${key} must be a boolean`;\n }\n if (NUMBER_PREF_KEYS.has(key)) {\n return typeof value === 'number' && Number.isFinite(value)\n ? null\n : `prefs.update payload.${key} must be a finite number`;\n }\n if (STRING_PREF_KEYS.has(key)) {\n return typeof value === 'string' ? null : `prefs.update payload.${key} must be a string`;\n }\n if (STRING_ARRAY_PREF_KEYS.has(key)) {\n return Array.isArray(value) && value.every((v) => typeof v === 'string')\n ? null\n : `prefs.update payload.${key} must be an array of strings`;\n }\n const arrayValidator = ARRAY_PREF_VALIDATORS[key];\n if (arrayValidator) {\n if (!Array.isArray(value)) return `prefs.update payload.${key} must be an array`;\n for (let i = 0; i < value.length; i++) {\n const item = value[i];\n if (!isRecord(item))\n return `prefs.update payload.${key}[${i}] must be an object`;\n const error = arrayValidator(\n item,\n `prefs.update payload.${key}[${i}]`,\n );\n if (error) return error;\n }\n return null;\n }\n if (STRING_ARRAY_RECORD_PREF_KEYS.has(key)) {\n return isRecord(value) &&\n Object.values(value).every(\n (v) => Array.isArray(v) && v.every((item) => typeof item === 'string'),\n )\n ? null\n : `prefs.update payload.${key} must be an object of string arrays`;\n }\n if (BOOLEAN_RECORD_PREF_KEYS.has(key)) {\n if (!isRecord(value) || !Object.values(value).every((v) => typeof v === 'boolean')) {\n return `prefs.update payload.${key} must be an object of booleans`;\n }\n // The KEYS here are plugin names that get used as property keys downstream\n // (extensions.<name>.enabled), so they must be checked too \u2014 validating\n // only the values let `{\"__proto__\": true}` through to a write that\n // polluted Object.prototype. The persist layer guards as well; this\n // rejects loudly instead of silently dropping the entry.\n const badKey = Object.keys(value).find((k) => FORBIDDEN_PROTO_KEYS.has(k));\n if (badKey) {\n return `prefs.update payload.${key} contains a forbidden key: ${badKey}`;\n }\n return null;\n }\n if (MODEL_MATRIX_PREF_KEYS.has(key)) {\n if (!isRecord(value)) return `prefs.update payload.${key} must be an object`;\n for (const entry of Object.values(value)) {\n if (!isRecord(entry)) return `prefs.update payload.${key} entries must be objects`;\n const provider = entry['provider'];\n const model = entry['model'];\n const fallbackProfile = entry['fallbackProfile'];\n const modelRuntime = entry['modelRuntime'];\n if (provider !== undefined && typeof provider !== 'string') {\n return `prefs.update payload.${key}.provider must be a string when provided`;\n }\n if (model !== undefined && typeof model !== 'string') {\n return `prefs.update payload.${key}.model must be a string when provided`;\n }\n if (fallbackProfile !== undefined && typeof fallbackProfile !== 'string') {\n return `prefs.update payload.${key}.fallbackProfile must be a string when provided`;\n }\n if (modelRuntime !== undefined && !isRecord(modelRuntime)) {\n return `prefs.update payload.${key}.modelRuntime must be an object when provided`;\n }\n if (isRecord(modelRuntime)) {\n const runtimeError = validateModelRuntimeValue(\n modelRuntime,\n `prefs.update payload.${key}.modelRuntime`,\n );\n if (runtimeError) return runtimeError;\n }\n if (model === undefined && fallbackProfile === undefined && modelRuntime === undefined) {\n return `prefs.update payload.${key} entries require model, fallbackProfile, or modelRuntime`;\n }\n }\n return null;\n }\n const allowed = ENUM_PREF_KEYS[key];\n if (allowed) {\n return typeof value === 'string' && allowed.has(value)\n ? null\n : `prefs.update payload.${key} must be one of: ${Array.from(allowed).join(', ')}`;\n }\n return `prefs.update payload contains unknown preference key: ${key}`;\n}\n\nexport function validatePrefsUpdatePayload(\n payload: unknown,\n): PayloadValidationResult<PrefsUpdatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'prefs.update payload must be an object' };\n }\n for (const [key, value] of Object.entries(payload)) {\n const error = validatePreferenceValue(key, value);\n if (error) return { ok: false, message: error };\n }\n return { ok: true, value: { prefs: payload } };\n}\n", "export { validatePrefsUpdatePayload } from './ws-payload-preferences.js';\n\ntype PayloadValidationResult<T> = { ok: true; value: T } | { ok: false; message: string };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\ninterface ModelSwitchPayload {\n provider: string;\n model: string;\n requestId?: string | undefined;\n}\n\nexport function validateModelSwitchPayload(\n payload: unknown,\n): PayloadValidationResult<ModelSwitchPayload> {\n if (!isRecord(payload)) {\n return {\n ok: false,\n message: 'model.switch payload must be an object with string provider and model',\n };\n }\n const provider = payload['provider'];\n const model = payload['model'];\n const requestId = payload['requestId'];\n if (typeof provider !== 'string' || provider.trim().length === 0) {\n return { ok: false, message: 'model.switch payload.provider must be a non-empty string' };\n }\n if (typeof model !== 'string' || model.trim().length === 0) {\n return { ok: false, message: 'model.switch payload.model must be a non-empty string' };\n }\n if (requestId !== undefined && (typeof requestId !== 'string' || requestId.trim().length === 0)) {\n return { ok: false, message: 'model.switch payload.requestId must be a non-empty string' };\n }\n return {\n ok: true,\n value: {\n provider: provider.trim(),\n model: model.trim(),\n ...(typeof requestId === 'string' ? { requestId: requestId.trim() } : {}),\n },\n };\n}\n\nconst AUTONOMY_VALUES = new Set(['off', 'suggest', 'auto', 'eternal', 'eternal-parallel']);\n\ninterface MailboxMessagesPayload {\n limit?: number;\n agentId?: string;\n unreadOnly?: boolean;\n incompleteOnly?: boolean;\n}\n\nexport function validateMailboxMessagesPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxMessagesPayload | undefined> {\n if (payload === undefined) return { ok: true, value: undefined };\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.messages payload must be an object when provided' };\n }\n const limit = payload['limit'];\n const agentId = payload['agentId'];\n const unreadOnly = payload['unreadOnly'];\n const incompleteOnly = payload['incompleteOnly'];\n if (limit !== undefined && (typeof limit !== 'number' || !Number.isFinite(limit) || limit < 1)) {\n return {\n ok: false,\n message: 'mailbox.messages payload.limit must be a positive number when provided',\n };\n }\n if (agentId !== undefined && typeof agentId !== 'string') {\n return {\n ok: false,\n message: 'mailbox.messages payload.agentId must be a string when provided',\n };\n }\n if (unreadOnly !== undefined && typeof unreadOnly !== 'boolean') {\n return {\n ok: false,\n message: 'mailbox.messages payload.unreadOnly must be a boolean when provided',\n };\n }\n if (incompleteOnly !== undefined && typeof incompleteOnly !== 'boolean') {\n return {\n ok: false,\n message: 'mailbox.messages payload.incompleteOnly must be a boolean when provided',\n };\n }\n return {\n ok: true,\n value: {\n ...(limit !== undefined ? { limit: limit as number } : {}),\n ...(agentId !== undefined ? { agentId: agentId as string } : {}),\n ...(unreadOnly !== undefined ? { unreadOnly: unreadOnly as boolean } : {}),\n ...(incompleteOnly !== undefined ? { incompleteOnly: incompleteOnly as boolean } : {}),\n },\n };\n}\n\ninterface MailboxAgentsPayload {\n onlineOnly?: boolean;\n}\n\nconst MAILBOX_ACTIONS = new Set(['mark-read', 'acknowledge', 'reopen', 'soft-delete']);\n\nexport interface MailboxActionPayload {\n requestId: string;\n mailId: string;\n action: 'mark-read' | 'acknowledge' | 'reopen' | 'soft-delete';\n readerId: string;\n}\n\nexport function validateMailboxActionPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxActionPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.action payload must be an object' };\n }\n const requestId = payload['requestId'];\n const mailId = payload['mailId'];\n const action = payload['action'];\n const readerId = payload['readerId'];\n if (typeof requestId !== 'string' || requestId.trim().length === 0) {\n return { ok: false, message: 'mailbox.action payload.requestId must be a non-empty string' };\n }\n if (typeof mailId !== 'string' || mailId.trim().length === 0) {\n return { ok: false, message: 'mailbox.action payload.mailId must be a non-empty string' };\n }\n if (typeof action !== 'string' || !MAILBOX_ACTIONS.has(action)) {\n return { ok: false, message: 'mailbox.action payload.action must be a supported action' };\n }\n if (typeof readerId !== 'string' || readerId.trim().length === 0) {\n return { ok: false, message: 'mailbox.action payload.readerId must be a non-empty string' };\n }\n return {\n ok: true,\n value: {\n requestId: requestId.trim(),\n mailId: mailId.trim(),\n action: action as MailboxActionPayload['action'],\n readerId: readerId.trim(),\n },\n };\n}\n\nconst MAILBOX_SEND_TYPES = new Set([\n 'note',\n 'ask',\n 'assign',\n 'steer',\n 'btw',\n 'broadcast',\n 'status',\n 'result',\n 'review',\n]);\n\nexport interface MailboxSendPayload {\n requestId: string;\n from?: string | undefined;\n to: string;\n type: 'note' | 'ask' | 'assign' | 'steer' | 'btw' | 'broadcast' | 'status' | 'result' | 'review';\n audience: 'all' | 'leaders';\n subject: string;\n body: string;\n priority: 'low' | 'normal' | 'high';\n replyTo?: string | undefined;\n}\n\nexport function validateMailboxSendPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxSendPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.send payload must be an object' };\n }\n const requestId = payload['requestId'];\n const rawFrom = payload['from'];\n const rawTo = payload['to'];\n const rawType = payload['type'];\n const rawAudience = payload['audience'];\n const rawSubject = payload['subject'];\n const rawBody = payload['body'];\n const rawPriority = payload['priority'];\n const rawReplyTo = payload['replyTo'];\n\n if (typeof requestId !== 'string' || requestId.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.requestId must be a non-empty string' };\n }\n if (rawFrom !== undefined && (typeof rawFrom !== 'string' || rawFrom.trim().length === 0)) {\n return { ok: false, message: 'mailbox.send payload.from must be a non-empty string when provided' };\n }\n if (typeof rawTo !== 'string' || rawTo.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.to must be a non-empty string' };\n }\n if (typeof rawType !== 'string' || !MAILBOX_SEND_TYPES.has(rawType)) {\n return {\n ok: false,\n message: 'mailbox.send payload.type must be a supported non-control message type',\n };\n }\n if (rawAudience !== 'all' && rawAudience !== 'leaders') {\n return { ok: false, message: 'mailbox.send payload.audience must be all or leaders' };\n }\n if (typeof rawSubject !== 'string' || rawSubject.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.subject must be a non-empty string' };\n }\n if (typeof rawBody !== 'string' || rawBody.trim().length === 0) {\n return { ok: false, message: 'mailbox.send payload.body must be a non-empty string' };\n }\n if (rawPriority !== 'low' && rawPriority !== 'normal' && rawPriority !== 'high') {\n return { ok: false, message: 'mailbox.send payload.priority must be low, normal, or high' };\n }\n if (rawReplyTo !== undefined && typeof rawReplyTo !== 'string') {\n return { ok: false, message: 'mailbox.send payload.replyTo must be a string when provided' };\n }\n\n const type = rawType as MailboxSendPayload['type'];\n const to = type === 'broadcast' ? '*' : rawTo.trim();\n if ((type === 'assign' || type === 'steer') && (to === '*' || to.toLowerCase() === 'all')) {\n return {\n ok: false,\n message: `mailbox.send payload.type ${type} requires a specific recipient`,\n };\n }\n\n return {\n ok: true,\n value: {\n requestId: requestId.trim(),\n ...(rawFrom !== undefined ? { from: rawFrom.trim() } : {}),\n to,\n type,\n audience: rawAudience,\n subject: rawSubject.trim(),\n body: rawBody.trim(),\n priority: rawPriority,\n ...(rawReplyTo !== undefined ? { replyTo: rawReplyTo } : {}),\n },\n };\n}\n\nexport function validateMailboxAgentsPayload(\n payload: unknown,\n): PayloadValidationResult<MailboxAgentsPayload | undefined> {\n if (payload === undefined) return { ok: true, value: undefined };\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.agents payload must be an object when provided' };\n }\n const onlineOnly = payload['onlineOnly'];\n if (onlineOnly !== undefined && typeof onlineOnly !== 'boolean') {\n return {\n ok: false,\n message: 'mailbox.agents payload.onlineOnly must be a boolean when provided',\n };\n }\n return {\n ok: true,\n value: { ...(onlineOnly !== undefined ? { onlineOnly: onlineOnly as boolean } : {}) },\n };\n}\n\ninterface MailboxPurgePayload {\n completedMaxAgeMs?: number;\n incompleteMaxAgeMs?: number;\n}\n\nexport function validateMailboxPurgePayload(\n payload: unknown,\n): PayloadValidationResult<MailboxPurgePayload | undefined> {\n if (payload === undefined) return { ok: true, value: undefined };\n if (!isRecord(payload)) {\n return { ok: false, message: 'mailbox.purge payload must be an object when provided' };\n }\n const completedMaxAgeMs = payload['completedMaxAgeMs'];\n const incompleteMaxAgeMs = payload['incompleteMaxAgeMs'];\n if (\n completedMaxAgeMs !== undefined &&\n (typeof completedMaxAgeMs !== 'number' ||\n !Number.isFinite(completedMaxAgeMs) ||\n completedMaxAgeMs < 0)\n ) {\n return {\n ok: false,\n message:\n 'mailbox.purge payload.completedMaxAgeMs must be a non-negative number when provided',\n };\n }\n if (\n incompleteMaxAgeMs !== undefined &&\n (typeof incompleteMaxAgeMs !== 'number' ||\n !Number.isFinite(incompleteMaxAgeMs) ||\n incompleteMaxAgeMs < 0)\n ) {\n return {\n ok: false,\n message:\n 'mailbox.purge payload.incompleteMaxAgeMs must be a non-negative number when provided',\n };\n }\n return {\n ok: true,\n value: {\n ...(completedMaxAgeMs !== undefined\n ? { completedMaxAgeMs: completedMaxAgeMs as number }\n : {}),\n ...(incompleteMaxAgeMs !== undefined\n ? { incompleteMaxAgeMs: incompleteMaxAgeMs as number }\n : {}),\n },\n };\n}\n\ninterface BrainRiskPayload {\n level: string;\n}\n\nconst BRAIN_RISK_VALUES = new Set(['off', 'low', 'medium', 'high', 'all']);\n\nexport function validateBrainRiskPayload(\n payload: unknown,\n): PayloadValidationResult<BrainRiskPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'brain.risk payload must be an object with string level' };\n }\n const level = payload['level'];\n if (typeof level !== 'string' || !BRAIN_RISK_VALUES.has(level)) {\n return {\n ok: false,\n message: 'brain.risk payload.level must be one of off, low, medium, high, all',\n };\n }\n return { ok: true, value: { level } };\n}\n\ninterface BrainAskPayload {\n question: string;\n}\n\nexport function validateBrainAskPayload(\n payload: unknown,\n): PayloadValidationResult<BrainAskPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'brain.ask payload must be an object with string question' };\n }\n const question = payload['question'];\n if (typeof question !== 'string' || question.trim().length === 0) {\n return { ok: false, message: 'brain.ask payload.question must be a non-empty string' };\n }\n return { ok: true, value: { question: question.trim() } };\n}\n\ninterface BrainConfigSetPayload {\n patch: Record<string, unknown>;\n}\n\nexport function validateBrainConfigSetPayload(\n payload: unknown,\n): PayloadValidationResult<BrainConfigSetPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'brain.config.set payload must be an object with a patch object' };\n }\n const patch = payload['patch'];\n if (!isRecord(patch)) {\n // Field-level validation happens in BrainRuntime.apply(), which throws\n // BEFORE any live state changes \u2014 this only guards the envelope shape.\n return { ok: false, message: 'brain.config.set payload.patch must be an object' };\n }\n return { ok: true, value: { patch } };\n}\n\ninterface AutonomySwitchPayload {\n mode: string;\n}\n\nexport function validateAutonomySwitchPayload(\n payload: unknown,\n): PayloadValidationResult<AutonomySwitchPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'autonomy.switch payload must be an object with string mode' };\n }\n const mode = payload['mode'];\n if (typeof mode !== 'string' || !AUTONOMY_VALUES.has(mode)) {\n return { ok: false, message: 'autonomy.switch payload.mode must be a valid autonomy mode' };\n }\n return { ok: true, value: { mode } };\n}\n\ninterface PlanTemplateUsePayload {\n template: string;\n}\n\nexport function validatePlanTemplateUsePayload(\n payload: unknown,\n): PayloadValidationResult<PlanTemplateUsePayload> {\n if (!isRecord(payload)) {\n return {\n ok: false,\n message: 'plan.template_use payload must be an object with string template',\n };\n }\n const template = payload['template'];\n if (typeof template !== 'string' || template.trim().length === 0) {\n return { ok: false, message: 'plan.template_use payload.template must be a non-empty string' };\n }\n return { ok: true, value: { template } };\n}\ninterface SkillsCreatePayload {\n name: string;\n description: string;\n scope: 'project' | 'global';\n}\n\nexport function validateSkillsCreatePayload(\n payload: unknown,\n): PayloadValidationResult<SkillsCreatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'skills.create payload must be an object' };\n }\n const name = payload['name'];\n const description = payload['description'];\n const scope = payload['scope'];\n if (typeof name !== 'string' || name.trim().length === 0) {\n return { ok: false, message: 'Skill name is required' };\n }\n if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(name.trim())) {\n return { ok: false, message: 'Skill name must be kebab-case (e.g. my-new-skill)' };\n }\n if (typeof description !== 'string' || description.trim().length === 0) {\n return { ok: false, message: 'Description/trigger is required' };\n }\n if (scope !== 'project' && scope !== 'global') {\n return { ok: false, message: 'skills.create payload.scope must be project or global' };\n }\n return { ok: true, value: { name, description, scope } };\n}\n\ninterface SkillsEditPayload {\n name: string;\n body: string;\n}\n\nexport function validateSkillsEditPayload(\n payload: unknown,\n): PayloadValidationResult<SkillsEditPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'skills.edit payload must be an object' };\n }\n const name = payload['name'];\n const body = payload['body'];\n if (typeof name !== 'string' || name.trim().length === 0) {\n return { ok: false, message: 'Skill name is required' };\n }\n if (typeof body !== 'string' || body.length === 0) {\n return { ok: false, message: 'Skill body is required' };\n }\n return { ok: true, value: { name, body } };\n}\n\ninterface ProcessKillPayload {\n pid: number;\n}\n\nexport function validateProcessKillPayload(\n payload: unknown,\n): PayloadValidationResult<ProcessKillPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'process.kill payload must be an object with numeric pid' };\n }\n const pid = payload['pid'];\n if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0) {\n return { ok: false, message: 'process.kill payload.pid must be a positive integer' };\n }\n return { ok: true, value: { pid } };\n}\n\ninterface WorkingDirSetPayload {\n path: string;\n}\n\nexport function validateWorkingDirSetPayload(\n payload: unknown,\n): PayloadValidationResult<WorkingDirSetPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'working_dir.set payload must be an object with string path' };\n }\n const newPath = payload['path'];\n if (typeof newPath !== 'string' || newPath.trim().length === 0) {\n return { ok: false, message: 'working_dir.set payload.path must be a non-empty string' };\n }\n return { ok: true, value: { path: newPath } };\n}\n\ninterface ModeSwitchPayload {\n id: string;\n}\n\nexport function validateModeSwitchPayload(\n payload: unknown,\n): PayloadValidationResult<ModeSwitchPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'mode.switch payload must be an object with string id' };\n }\n const id = payload['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: 'mode.switch payload.id must be a non-empty string' };\n }\n return { ok: true, value: { id } };\n}\n\ninterface ContextModeIdPayload {\n id: string;\n}\n\nfunction validateContextModeIdPayload(\n payload: unknown,\n type: 'context.mode.switch' | 'context.mode.delete',\n): PayloadValidationResult<ContextModeIdPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: `${type} payload must be an object with string id` };\n }\n const id = payload['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: `${type} payload.id must be a non-empty string` };\n }\n return { ok: true, value: { id } };\n}\n\nexport function validateContextModeSwitchPayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeIdPayload> {\n return validateContextModeIdPayload(payload, 'context.mode.switch');\n}\n\nexport function validateContextModeDeletePayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeIdPayload> {\n return validateContextModeIdPayload(payload, 'context.mode.delete');\n}\n\ninterface ContextModeCreatePayload {\n id: string;\n name: string;\n description: string;\n thresholds: { warn: number; soft: number; hard: number };\n preserveK: number;\n eliseThreshold: number;\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nexport function validateContextModeCreatePayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeCreatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'context.mode.create payload must be an object' };\n }\n const id = payload['id'];\n const name = payload['name'];\n const description = payload['description'];\n const thresholds = payload['thresholds'];\n const preserveK = payload['preserveK'];\n const eliseThreshold = payload['eliseThreshold'];\n\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: 'context.mode.create payload.id must be a non-empty string' };\n }\n if (typeof name !== 'string' || name.trim().length === 0) {\n return { ok: false, message: 'context.mode.create payload.name must be a non-empty string' };\n }\n if (typeof description !== 'string') {\n return { ok: false, message: 'context.mode.create payload.description must be a string' };\n }\n if (!isRecord(thresholds)) {\n return {\n ok: false,\n message:\n 'context.mode.create payload.thresholds must be an object with warn/soft/hard numbers',\n };\n }\n if (\n !isFiniteNumber(thresholds['warn']) ||\n !isFiniteNumber(thresholds['soft']) ||\n !isFiniteNumber(thresholds['hard'])\n ) {\n return {\n ok: false,\n message: 'context.mode.create payload.thresholds.warn/soft/hard must be finite numbers',\n };\n }\n if (!isFiniteNumber(preserveK)) {\n return { ok: false, message: 'context.mode.create payload.preserveK must be a finite number' };\n }\n if (!isFiniteNumber(eliseThreshold)) {\n return {\n ok: false,\n message: 'context.mode.create payload.eliseThreshold must be a finite number',\n };\n }\n return {\n ok: true,\n value: {\n id,\n name,\n description,\n thresholds: { warn: thresholds['warn'], soft: thresholds['soft'], hard: thresholds['hard'] },\n preserveK,\n eliseThreshold,\n },\n };\n}\n\ninterface ContextModeUpdatePayload {\n id: string;\n name?: string;\n description?: string;\n thresholds?: { warn?: number; soft?: number; hard?: number };\n preserveK?: number;\n eliseThreshold?: number;\n}\n\nexport function validateContextModeUpdatePayload(\n payload: unknown,\n): PayloadValidationResult<ContextModeUpdatePayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'context.mode.update payload must be an object' };\n }\n const id = payload['id'];\n if (typeof id !== 'string' || id.trim().length === 0) {\n return { ok: false, message: 'context.mode.update payload.id must be a non-empty string' };\n }\n\n const name = payload['name'];\n if (name !== undefined && typeof name !== 'string') {\n return {\n ok: false,\n message: 'context.mode.update payload.name must be a string when provided',\n };\n }\n\n const description = payload['description'];\n if (description !== undefined && typeof description !== 'string') {\n return {\n ok: false,\n message: 'context.mode.update payload.description must be a string when provided',\n };\n }\n\n const thresholds = payload['thresholds'];\n let validatedThresholds: ContextModeUpdatePayload['thresholds'];\n if (thresholds !== undefined) {\n if (!isRecord(thresholds)) {\n return {\n ok: false,\n message: 'context.mode.update payload.thresholds must be an object when provided',\n };\n }\n for (const key of ['warn', 'soft', 'hard'] as const) {\n const val = thresholds[key];\n if (val !== undefined && !isFiniteNumber(val)) {\n return {\n ok: false,\n message: `context.mode.update payload.thresholds.${key} must be a finite number when provided`,\n };\n }\n }\n validatedThresholds = {\n ...(typeof thresholds['warn'] === 'number' ? { warn: thresholds['warn'] } : {}),\n ...(typeof thresholds['soft'] === 'number' ? { soft: thresholds['soft'] } : {}),\n ...(typeof thresholds['hard'] === 'number' ? { hard: thresholds['hard'] } : {}),\n };\n }\n\n const preserveK = payload['preserveK'];\n if (preserveK !== undefined && !isFiniteNumber(preserveK)) {\n return {\n ok: false,\n message: 'context.mode.update payload.preserveK must be a finite number when provided',\n };\n }\n\n const eliseThreshold = payload['eliseThreshold'];\n if (eliseThreshold !== undefined && !isFiniteNumber(eliseThreshold)) {\n return {\n ok: false,\n message: 'context.mode.update payload.eliseThreshold must be a finite number when provided',\n };\n }\n\n return {\n ok: true,\n value: {\n id,\n ...(typeof name === 'string' ? { name } : {}),\n ...(typeof description === 'string' ? { description } : {}),\n ...(validatedThresholds !== undefined ? { thresholds: validatedThresholds } : {}),\n ...(typeof preserveK === 'number' ? { preserveK } : {}),\n ...(typeof eliseThreshold === 'number' ? { eliseThreshold } : {}),\n },\n };\n}\n\ninterface ShellOpenPayload {\n path: string;\n target?: 'file' | 'terminal';\n}\n\nexport function validateShellOpenPayload(\n payload: unknown,\n): PayloadValidationResult<ShellOpenPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'shell.open payload must be an object with string path' };\n }\n const path = payload['path'];\n if (typeof path !== 'string' || path.trim().length === 0) {\n return { ok: false, message: 'shell.open payload.path must be a non-empty string' };\n }\n const target = payload['target'];\n if (target !== undefined && target !== 'file' && target !== 'terminal') {\n return {\n ok: false,\n message: 'shell.open payload.target must be \"file\" or \"terminal\" when provided',\n };\n }\n return {\n ok: true,\n value: {\n path,\n ...(target !== undefined ? { target: target as 'file' | 'terminal' } : {}),\n },\n };\n}\n\ninterface GitDiffPayload {\n path: string;\n}\n\nexport function validateGitDiffPayload(payload: unknown): PayloadValidationResult<GitDiffPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'git.diff payload must be an object' };\n }\n const path = payload['path'];\n if (path === undefined || path === null) {\n return { ok: true, value: { path: '' } };\n }\n if (typeof path !== 'string') {\n return { ok: false, message: 'git.diff payload.path must be a string when provided' };\n }\n return { ok: true, value: { path } };\n}\n\ninterface ProjectsAddPayload {\n root: string;\n name?: string;\n}\n\nexport function validateProjectsAddPayload(\n payload: unknown,\n): PayloadValidationResult<ProjectsAddPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'projects.add payload must be an object with string root' };\n }\n const root = payload['root'];\n if (typeof root !== 'string' || root.trim().length === 0) {\n return { ok: false, message: 'projects.add payload.root must be a non-empty string' };\n }\n const name = payload['name'];\n if (name !== undefined && typeof name !== 'string') {\n return { ok: false, message: 'projects.add payload.name must be a string when provided' };\n }\n return {\n ok: true,\n value: { root, ...(typeof name === 'string' ? { name } : {}) },\n };\n}\n\ninterface ProjectsSelectPayload {\n root: string;\n name?: string;\n}\n\nexport function validateProjectsSelectPayload(\n payload: unknown,\n): PayloadValidationResult<ProjectsSelectPayload> {\n if (!isRecord(payload)) {\n return { ok: false, message: 'projects.select payload must be an object with string root' };\n }\n const root = payload['root'];\n if (typeof root !== 'string' || root.trim().length === 0) {\n return { ok: false, message: 'projects.select payload.root must be a non-empty string' };\n }\n const name = payload['name'];\n if (name !== undefined && typeof name !== 'string') {\n return { ok: false, message: 'projects.select payload.name must be a string when provided' };\n }\n return {\n ok: true,\n value: { root, ...(typeof name === 'string' ? { name } : {}) },\n };\n}\n", "/**\n * Shared WebSocket utilities for both the standalone WebUI server and the\n * CLI's `--webui` embedded server. Extracted from the duplicated `send` /\n * `broadcast` / `sendResult` / `generateAuthToken` patterns that were\n * copy-pasted between `packages/webui/src/server/index.ts` and\n * `packages/cli/src/webui-server.ts`.\n */\nimport { randomBytes } from 'node:crypto';\n// Value import (not `import type`): we reference `WebSocket.OPEN` below, which\n// is a runtime value, not just a type.\nimport { WebSocket } from 'ws';\nimport type { ConnectedClient } from './types.js';\n\n/** Maximum unsent data retained by one client before it is disconnected. */\nexport const WEBUI_WS_MAX_BUFFERED_BYTES = 32 * 1024 * 1024;\n\n/**\n * Send an already serialized frame while enforcing per-client backpressure.\n * A socket above the cap cannot be trusted to catch up: keeping it alive would\n * let `ws` retain every subsequent broadcast in memory.\n */\nexport function sendSerialized(ws: WebSocket, data: string): boolean {\n if (ws.readyState !== WebSocket.OPEN) return false;\n const buffered = Number.isFinite(ws.bufferedAmount) ? ws.bufferedAmount : 0;\n const frameBytes = Buffer.byteLength(data, 'utf8');\n if (buffered + frameBytes > WEBUI_WS_MAX_BUFFERED_BYTES) {\n try {\n ws.terminate();\n } catch {\n try {\n ws.close(1013, 'client cannot keep up');\n } catch {\n // Socket is already gone.\n }\n }\n return false;\n }\n try {\n ws.send(data);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Send a JSON message to a single WebSocket client.\n * No-op when the socket is not in OPEN state (disconnected / closing).\n */\nexport function send(ws: WebSocket, msg: object): void {\n sendSerialized(ws, JSON.stringify(msg));\n}\n\n/**\n * Broadcast a JSON message to every connected client.\n * Swallows per-socket send errors \u2014 a client that disconnected between the\n * readyState check and `ws.send()` is cleaned up by its own `close` handler.\n */\nexport function broadcast(\n clients: Map<WebSocket, ConnectedClient>,\n msg: object,\n): void {\n const data = JSON.stringify(msg);\n for (const [ws] of clients) {\n sendSerialized(ws, data);\n }\n}\n\n/**\n * Send a success/failure result message (used by key.* and provider.* handlers).\n * The frontend expects `key.operation_result` with `{ success, message }`.\n */\nexport function sendResult(ws: WebSocket, success: boolean, message: string): void {\n send(ws, { type: 'key.operation_result', payload: { success, message } });\n}\n\n/**\n * Extract a human-readable message from an unknown thrown value.\n */\nexport function errMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Generate a cryptographically random WebSocket auth token (hex string).\n * Shared between standalone and CLI-embedded WebUI servers.\n */\nexport function generateAuthToken(): string {\n return randomBytes(16).toString('hex');\n}\n\nexport function resolveAuthToken(explicit?: string | undefined): string {\n const configured =\n explicit?.trim() ||\n process.env['WEBUI_TOKEN']?.trim() ||\n process.env['WEBUI_AUTH_TOKEN']?.trim();\n return configured || generateAuthToken();\n}\n\nexport function hostForBrowserUrl(bindHost: string): string {\n if (bindHost === '0.0.0.0') return '127.0.0.1';\n if (bindHost === '::' || bindHost === '[::]') return '[::1]';\n if (bindHost.includes(':') && !bindHost.startsWith('[')) return `[${bindHost}]`;\n return bindHost;\n}\n\nexport function buildWebUIAccessUrl(opts: {\n host: string;\n port: number;\n token?: string | undefined;\n protocol?: 'http' | 'https' | undefined;\n publicUrl?: string | undefined;\n}): string {\n const protocol = opts.protocol ?? 'http';\n const base = opts.publicUrl?.trim() || `${protocol}://${hostForBrowserUrl(opts.host)}:${opts.port}`;\n if (!opts.token) return base;\n try {\n const url = new URL(base);\n url.searchParams.set('token', opts.token);\n const rendered = url.toString();\n const afterOrigin = base.slice(url.origin.length);\n if (url.pathname === '/' && !afterOrigin.startsWith('/')) {\n return `${url.origin}${url.search}${url.hash}`;\n }\n return rendered;\n } catch {\n return `${base}${base.includes('?') ? '&' : '?'}token=${encodeURIComponent(opts.token)}`;\n }\n}\n\nexport function envFlag(name: string): boolean {\n const value = process.env[name]?.trim().toLowerCase();\n return value === '1' || value === 'true' || value === 'yes' || value === 'on';\n}\n", "import type { WebSocket } from 'ws';\nimport { handleAutonomySwitch, type PrefsHandlerContext } from './prefs-handlers.js';\nimport type { WSClientMessage } from './types.js';\nimport { validateAutonomySwitchPayload } from './ws-payload-validation.js';\nimport { sendResult } from './ws-utils.js';\n\nexport interface AutonomyRouteHandlers {\n switchMode: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport function createAutonomyRouteHandlers(ctx: PrefsHandlerContext): AutonomyRouteHandlers {\n return {\n switchMode: (ws, message) => {\n const parsed = validateAutonomySwitchPayload(message.payload);\n if (!parsed.ok) {\n sendResult(ws, false, parsed.message);\n return;\n }\n handleAutonomySwitch(ctx, ws, parsed.value.mode);\n },\n };\n}\n\nexport async function handleAutonomyRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: AutonomyRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'autonomy.switch':\n await handlers.switchMode(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import { bootConfig as coreBootConfig, type DefaultLogger } from '@wrongstack/core/infrastructure';\nimport type { DefaultSecretVault } from '@wrongstack/core/security';\nimport type { Config } from '@wrongstack/core/types';\nimport type { WstackPaths } from '@wrongstack/core/utils';\n\nexport interface BootResult {\n config: Config;\n vault: DefaultSecretVault;\n globalConfigPath: string;\n projectRoot: string;\n wpaths: WstackPaths;\n logger: InstanceType<typeof DefaultLogger>;\n}\n\n/**\n * Thin WebUI wrapper over the canonical `bootConfig` in `@wrongstack/core`\n * (mirrors packages/cli/src/boot-config.ts). All real boot behavior \u2014 wstack\n * path resolution, the AES-GCM `DefaultSecretVault`, plaintext-secret\n * migration, and config load/merge \u2014 lives in core so the WebUI server and the\n * CLI can't drift. Only the secret-migration notice label (`WebUI`) differs.\n */\nexport async function bootConfig(): Promise<BootResult> {\n const { config, vault, globalConfigPath, projectRoot, wpaths, logger } = await coreBootConfig({\n appLabel: 'WebUI',\n });\n return { config, vault, globalConfigPath, projectRoot, wpaths, logger };\n}\n\nexport function patchConfig(config: Config, updates: Partial<Config>): Config {\n return Object.freeze({ ...config, ...updates });\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface BrainRouteHandlers {\n status: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n risk: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n ask: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n configGet: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n configSet: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport async function handleBrainRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: BrainRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'brain.status':\n await handlers.status(ws, msg);\n return true;\n case 'brain.risk':\n await handlers.risk(ws, msg);\n return true;\n case 'brain.ask':\n await handlers.ask(ws, msg);\n return true;\n case 'brain.config.get':\n await handlers.configGet(ws, msg);\n return true;\n case 'brain.config.set':\n await handlers.configSet(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import {\n CHRONICLE_FACET_FIELDS,\n type ChronicleFacet,\n type ChronicleProjectAccess,\n type ChronicleQuery,\n createChronicleProjectAccess,\n} from '@wrongstack/core/chronicle';\nimport type { WebSocket } from 'ws';\nimport type { WSClientMessage, WSServerMessage } from './types.js';\n\nexport interface ChronicleRouteContext {\n getProjectRoot: () => string;\n send: (ws: WebSocket, message: WSServerMessage) => void;\n getChronicleAccess?: (() => Pick<ChronicleProjectAccess, 'mode' | 'call'>) | undefined;\n}\n\nconst accessCache = new Map<string, ChronicleProjectAccess>();\nconst ACCESS_CACHE_MAX_PROJECTS = 8;\n\nfunction defaultChronicleAccess(projectRoot: string): ChronicleProjectAccess {\n let access = accessCache.get(projectRoot);\n if (access) {\n accessCache.delete(projectRoot);\n accessCache.set(projectRoot, access);\n return access;\n }\n access = createChronicleProjectAccess({ projectRoot });\n while (accessCache.size >= ACCESS_CACHE_MAX_PROJECTS) {\n const oldestKey = accessCache.keys().next().value;\n if (oldestKey === undefined) break;\n const oldest = accessCache.get(oldestKey);\n accessCache.delete(oldestKey);\n void oldest?.close();\n }\n accessCache.set(projectRoot, access);\n return access;\n}\n\n/** Canonical Chronicle query/facet/graph handler shared by every WebUI host. */\nexport async function handleChronicleRoute(\n ctx: ChronicleRouteContext,\n ws: WebSocket,\n message: WSClientMessage,\n): Promise<boolean> {\n if (!message.type.startsWith('chronicle.')) return false;\n if (message.type === 'chronicle.status') {\n try {\n const access = ctx.getChronicleAccess?.() ?? defaultChronicleAccess(ctx.getProjectRoot());\n const health = await access.call('ping', {});\n ctx.send(ws, {\n type: 'chronicle.status_result',\n payload: {\n mode: access.mode,\n ...health,\n pipeline: {\n collection: 'session-event-adapters',\n processing:\n access.mode === 'server' ? 'project-chronicle-server' : 'inline-chronicle-fallback',\n storage: health.chronicleDirectory,\n serving: 'webui-server',\n },\n },\n });\n } catch (error) {\n ctx.send(ws, {\n type: 'chronicle.error',\n payload: { message: error instanceof Error ? error.message : String(error) },\n });\n }\n return true;\n }\n if (message.type === 'chronicle.metrics') {\n const payload = (message.payload ?? {}) as {\n view?: 'summary' | 'providers' | 'tasks' | 'files';\n from?: string;\n to?: string;\n path?: string;\n taskId?: string;\n boardId?: string;\n sessionId?: string;\n status?: string;\n limit?: number;\n };\n const view = payload.view ?? 'summary';\n try {\n const access = ctx.getChronicleAccess?.() ?? defaultChronicleAccess(ctx.getProjectRoot());\n const result = await access.call('metrics', {\n view,\n ...(view === 'providers'\n ? {\n providers: {\n ...(payload.from ? { from: payload.from } : {}),\n ...(payload.to ? { to: payload.to } : {}),\n },\n }\n : {}),\n ...(view === 'tasks'\n ? {\n tasks: {\n ...(payload.boardId ? { boardId: payload.boardId } : {}),\n ...(payload.sessionId ? { sessionId: payload.sessionId } : {}),\n ...(payload.status ? { status: payload.status } : {}),\n ...(payload.limit !== undefined ? { limit: payload.limit } : {}),\n },\n }\n : {}),\n ...(view === 'files'\n ? {\n files: {\n ...(payload.path ? { path: payload.path } : {}),\n ...(payload.taskId ? { taskId: payload.taskId } : {}),\n ...(payload.boardId ? { boardId: payload.boardId } : {}),\n ...(payload.sessionId ? { sessionId: payload.sessionId } : {}),\n ...(payload.limit !== undefined ? { limit: payload.limit } : {}),\n },\n }\n : {}),\n });\n ctx.send(ws, {\n type: 'chronicle.metrics_result',\n payload: { view, refreshed: result.refreshed, data: result.data },\n });\n } catch (error) {\n // node:sqlite unavailable or a corrupt metrics.db \u2014 surface, don't crash.\n ctx.send(ws, {\n type: 'chronicle.error',\n payload: { message: error instanceof Error ? error.message : String(error) },\n });\n }\n return true;\n }\n if (\n message.type !== 'chronicle.query' &&\n message.type !== 'chronicle.facet' &&\n message.type !== 'chronicle.facets' &&\n message.type !== 'chronicle.graph'\n ) {\n return false;\n }\n try {\n const access = ctx.getChronicleAccess?.() ?? defaultChronicleAccess(ctx.getProjectRoot());\n switch (message.type) {\n case 'chronicle.query': {\n const payload = (message.payload ?? {}) as { query?: ChronicleQuery };\n ctx.send(ws, {\n type: 'chronicle.query_result',\n payload: await access.call('query', { query: payload.query ?? {} }),\n });\n return true;\n }\n case 'chronicle.facet': {\n const payload = (message.payload ?? {}) as {\n field?: ChronicleFacet;\n query?: ChronicleQuery;\n limit?: number;\n };\n if (!payload.field || !CHRONICLE_FACET_FIELDS.has(payload.field)) {\n ctx.send(ws, {\n type: 'chronicle.error',\n payload: { message: 'Invalid Chronicle facet field.' },\n });\n return true;\n }\n ctx.send(ws, {\n type: 'chronicle.facet_result',\n payload: {\n field: payload.field,\n ...(await access.call('facet', {\n field: payload.field,\n query: payload.query ?? {},\n ...(payload.limit !== undefined ? { limit: payload.limit } : {}),\n })),\n },\n });\n return true;\n }\n case 'chronicle.facets': {\n const payload = (message.payload ?? {}) as {\n fields?: ChronicleFacet[];\n query?: ChronicleQuery;\n limit?: number;\n };\n if (\n !Array.isArray(payload.fields) ||\n payload.fields.length === 0 ||\n payload.fields.some((field) => !CHRONICLE_FACET_FIELDS.has(field))\n ) {\n ctx.send(ws, {\n type: 'chronicle.error',\n payload: { message: 'Invalid Chronicle facet fields.' },\n });\n return true;\n }\n ctx.send(ws, {\n type: 'chronicle.facets_result',\n payload: await access.call('facets', {\n fields: payload.fields,\n query: payload.query ?? {},\n ...(payload.limit !== undefined ? { limit: payload.limit } : {}),\n }),\n });\n return true;\n }\n case 'chronicle.graph': {\n const payload = (message.payload ?? {}) as {\n seed?: ChronicleQuery;\n hops?: number;\n maxNodes?: number;\n };\n ctx.send(ws, {\n type: 'chronicle.graph_result',\n payload: await access.call('graph', {\n seed: payload.seed ?? {},\n ...(payload.hops !== undefined ? { hops: payload.hops } : {}),\n ...(payload.maxNodes !== undefined ? { maxNodes: payload.maxNodes } : {}),\n }),\n });\n return true;\n }\n default:\n return false;\n }\n } catch (error) {\n ctx.send(ws, {\n type: 'chronicle.error',\n payload: { message: error instanceof Error ? error.message : String(error) },\n });\n return true;\n }\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface ClientTransportRouteHandlers {\n collaboration: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n terminal: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport async function handleClientTransportRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: ClientTransportRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'collab.join':\n case 'collab.leave':\n case 'collab.annotate':\n case 'collab.resolve':\n case 'collab.request_pause':\n case 'collab.resume':\n case 'collab.grant_control':\n case 'collab.inject_tool':\n await handlers.collaboration(ws, msg);\n return true;\n case 'terminal.create':\n case 'terminal.input':\n case 'terminal.resize':\n case 'terminal.close':\n await handlers.terminal(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { Context } from '@wrongstack/core/agent';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport type { IndexingConfig, Logger } from '@wrongstack/core/types';\nimport {\n DEFAULT_WALK_IGNORE_SET,\n type ProjectWatchSubscription,\n watchProjectTree,\n} from '@wrongstack/core/utils';\nimport {\n cancelPendingReindexes,\n enqueueReindex,\n ensureCodebaseIndexServer,\n isIndexableFile,\n onIndexStateChange,\n runStartupIndex,\n shutdownCodebaseIndexHost,\n} from '@wrongstack/tools';\nimport { clearCodemapGraphCache } from './codemap-cache.js';\n\nconst WATCHER_DEDUP_TTL_MS = 60_000;\nconst WATCHER_DEDUP_MAX_PATHS = 4_096;\n\nexport interface WebUICodebaseIndexingDeps {\n config: { indexing?: IndexingConfig | undefined };\n context: Context;\n projectRoot: string;\n logger: Logger;\n events?: EventBus | undefined;\n}\n\nexport interface WebUICodebaseIndexing {\n onFileWritten(filePath: string): void;\n dispose(): void;\n}\n\nexport function setupWebUICodebaseIndexing(deps: WebUICodebaseIndexingDeps): WebUICodebaseIndexing {\n const idx: IndexingConfig | undefined = deps.config.indexing;\n\n const indexDir =\n typeof deps.context.meta['codebaseIndexDir'] === 'string'\n ? deps.context.meta['codebaseIndexDir']\n : undefined;\n const debounceMs = idx?.debounceMs ?? 400;\n const onError = (err: unknown) => {\n deps.logger.debug(\n `webui codebase auto-index failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n };\n\n if (idx) {\n void ensureCodebaseIndexServer({\n projectRoot: deps.projectRoot,\n indexDir,\n watchExternal: idx.watchExternal ?? false,\n debounceMs,\n }).catch(onError);\n }\n\n if (idx?.onSessionStart) {\n void runStartupIndex({\n projectRoot: deps.projectRoot,\n indexDir,\n signal: deps.context.signal,\n timeoutMs: idx.indexTimeoutMs,\n })\n .then((result) => {\n deps.logger.info(\n `webui codebase index ready: ${result.symbolsIndexed} symbols \u00B7 ${result.filesIndexed} files \u00B7 ${result.durationMs}ms`,\n );\n })\n .catch((err) => {\n deps.logger.warn(\n `webui codebase index (startup) failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n });\n }\n\n let watcher: ProjectWatchSubscription | undefined;\n const lastWatcherEvent = new Map<string, number>();\n if (deps.events) {\n try {\n // Shares the process-wide recursive watcher with any other subscriber\n // on the same root instead of opening a second OS-level tree watch.\n // Emitted async: a rename needs an access() probe to tell delete from edit.\n const emitActivity = async (\n abs: string,\n eventType: 'rename' | 'change',\n now: number,\n ): Promise<void> => {\n let operation: 'delete' | 'edit' = 'edit';\n if (eventType === 'rename') {\n try {\n await fs.promises.access(abs);\n } catch {\n operation = 'delete';\n }\n }\n deps.events?.emit('file.activity', {\n filePath: path.normalize(abs),\n operation,\n phase: 'changed',\n source: 'watcher',\n at: now,\n });\n };\n watcher = watchProjectTree(\n deps.projectRoot,\n ({ eventType, filename }) => {\n if (!filename) return;\n const rel = filename;\n if (isIgnored(rel)) return;\n const abs = path.resolve(deps.projectRoot, rel);\n if (!isInside(deps.projectRoot, abs) || !isIndexableFile(abs)) return;\n const now = Date.now();\n const previousEventAt = lastWatcherEvent.get(abs) ?? 0;\n if (now - previousEventAt > 75) {\n // Treat the map as a small LRU and opportunistically evict expired\n // paths. Generated files can otherwise leave one permanent entry per\n // unique filename in a long-running WebUI process.\n lastWatcherEvent.delete(abs);\n lastWatcherEvent.set(abs, now);\n if (lastWatcherEvent.size > WATCHER_DEDUP_MAX_PATHS) {\n for (const [cachedPath, seenAt] of lastWatcherEvent) {\n if (now - seenAt > WATCHER_DEDUP_TTL_MS) lastWatcherEvent.delete(cachedPath);\n }\n while (lastWatcherEvent.size > WATCHER_DEDUP_MAX_PATHS) {\n const oldest = lastWatcherEvent.keys().next().value;\n if (oldest === undefined) break;\n lastWatcherEvent.delete(oldest);\n }\n }\n void emitActivity(abs, eventType, now).catch((err) =>\n deps.logger.debug(`webui codebase index watcher error: ${err}`),\n );\n }\n // External reindexing is owned by the detached project server. This\n // local shared watcher exists only to publish file.activity telemetry.\n },\n { onError: (err) => deps.logger.debug(`webui codebase index watcher error: ${err}`) },\n );\n } catch (err) {\n deps.logger.debug(\n `webui codebase index watcher unavailable: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n function enqueueFile(filePath: string): void {\n if (!idx || (!idx.onEdit && !idx.watchExternal)) return;\n const abs = path.isAbsolute(filePath)\n ? path.normalize(filePath)\n : path.resolve(deps.projectRoot, filePath);\n if (!isInside(deps.projectRoot, abs) || !isIndexableFile(abs)) return;\n enqueueReindex({\n projectRoot: deps.projectRoot,\n files: [abs],\n indexDir,\n debounceMs,\n timeoutMs: idx.indexTimeoutMs,\n onError,\n });\n }\n\n // Drop CodeMap graph cache + notify clients when an index run finishes so\n // package/file/symbol maps pick up new symbols without a process restart.\n // mtime-versioned cache is the safety net; this is the proactive path.\n let wasIndexing = false;\n const unsubscribeIndexState = onIndexStateChange((state) => {\n if (wasIndexing && !state.indexing) {\n clearCodemapGraphCache();\n deps.events?.emit('codemap.index_updated', {\n at: Date.now(),\n ready: state.ready,\n reason: 'index_complete',\n });\n deps.logger.debug(`webui codemap cache invalidated after index run (ready=${state.ready})`);\n }\n wasIndexing = state.indexing;\n });\n\n return {\n onFileWritten(filePath) {\n const abs = path.isAbsolute(filePath)\n ? path.normalize(filePath)\n : path.resolve(deps.projectRoot, filePath);\n deps.events?.emit('file.activity', {\n filePath: abs,\n operation: 'write',\n phase: 'completed',\n source: 'editor',\n at: Date.now(),\n sessionId: deps.context.session?.id,\n agentId: 'webui-editor',\n agentName: 'WebUI Editor',\n });\n if (idx?.onEdit) enqueueFile(abs);\n },\n dispose() {\n unsubscribeIndexState();\n lastWatcherEvent.clear();\n try {\n watcher?.close();\n } catch {\n /* ignore */\n }\n if (idx) {\n cancelPendingReindexes();\n void shutdownCodebaseIndexHost();\n }\n },\n };\n}\n\nfunction isIgnored(rel: string): boolean {\n return rel.split(/[/\\\\]/).some((seg) => DEFAULT_WALK_IGNORE_SET.has(seg));\n}\n\nfunction isInside(root: string, target: string): boolean {\n const normalizedRoot = path.resolve(root);\n const normalizedTarget = path.resolve(target);\n return (\n normalizedTarget === normalizedRoot || normalizedTarget.startsWith(normalizedRoot + path.sep)\n );\n}\n", "/**\n * In-process CodeMap graph cache.\n *\n * Graph queries hit SQLite and can be expensive on monorepos. Package/file/symbol\n * drill-downs are pure functions of the index DB contents, so we cache the\n * pre-serialized JSON body keyed by scope and invalidate when `index.db`\n * mtime/size changes (indexer writes bump mtime).\n */\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { resolveIndexDir } from '@wrongstack/tools/codebase-index/index';\n\nconst DB_FILE = 'index.db';\n/** Soft cap \u2014 symbol-level scopes can proliferate during live agent sessions. */\nconst MAX_CACHE_ENTRIES = 128;\n\nexport interface CodemapCacheEntry {\n version: string;\n /** Pre-serialized JSON body \u2014 avoids re-stringify on cache hits. */\n body: string;\n}\n\nconst cache = new Map<string, CodemapCacheEntry>();\n\n/** Filesystem fingerprint of the index DB used as the cache generation key. */\nexport function indexDbVersion(projectRoot: string, indexDir?: string): string {\n try {\n const dir = resolveIndexDir(projectRoot, indexDir);\n const st = fs.statSync(path.join(dir, DB_FILE));\n return `${st.mtimeMs}:${st.size}`;\n } catch {\n return 'missing';\n }\n}\n\nexport function codemapCacheKey(\n projectRoot: string,\n indexDir: string | undefined,\n scope: string,\n): string {\n return `${projectRoot}\\0${indexDir ?? ''}\\0${scope}`;\n}\n\nexport function getCachedCodemapBody(\n key: string,\n version: string,\n): string | undefined {\n const entry = cache.get(key);\n if (!entry) return undefined;\n if (entry.version !== version) {\n cache.delete(key);\n return undefined;\n }\n // Refresh LRU order (Map insertion order).\n cache.delete(key);\n cache.set(key, entry);\n return entry.body;\n}\n\nexport function setCachedCodemapBody(\n key: string,\n version: string,\n body: string,\n): void {\n if (cache.has(key)) cache.delete(key);\n cache.set(key, { version, body });\n while (cache.size > MAX_CACHE_ENTRIES) {\n const oldest = cache.keys().next().value;\n if (oldest === undefined) break;\n cache.delete(oldest);\n }\n}\n\n/** Test / process-shutdown helper. */\nexport function clearCodemapGraphCache(): void {\n cache.clear();\n}\n\nexport function codemapGraphCacheSize(): number {\n return cache.size;\n}\n", "import * as path from 'node:path';\n\nexport type CodeMapOperation = 'read' | 'write' | 'edit' | 'delete' | 'search';\n\nexport interface CodeMapFileTarget {\n filePath: string;\n operation: CodeMapOperation;\n line?: number | undefined;\n endLine?: number | undefined;\n}\n\nconst TOOL_OPERATION: Record<string, CodeMapOperation> = {\n read: 'read',\n read_file: 'read',\n view: 'read',\n write: 'write',\n write_file: 'write',\n create_file: 'write',\n edit: 'edit',\n replace: 'edit',\n patch: 'edit',\n apply_patch: 'edit',\n delete: 'delete',\n delete_file: 'delete',\n remove: 'delete',\n unlink: 'delete',\n grep: 'search',\n search: 'search',\n codebase_search: 'search',\n 'codebase-search': 'search',\n};\n\nfunction numberField(input: Record<string, unknown>, names: string[]): number | undefined {\n for (const name of names) {\n const value = input[name];\n if (typeof value === 'number' && Number.isFinite(value) && value > 0) return Math.floor(value);\n }\n return undefined;\n}\n\nfunction normalizeTarget(projectRoot: string, filePath: string): string {\n const root = typeof projectRoot === 'string' && projectRoot.length > 0 ? projectRoot : process.cwd();\n return path.normalize(path.isAbsolute(filePath) ? filePath : path.resolve(root, filePath));\n}\n\nexport function normalizeCodeMapFileTarget(\n projectRoot: string,\n filePath: string,\n operation: 'write' | 'edit' | 'delete' | 'rename' = 'edit',\n line?: number,\n endLine?: number,\n): CodeMapFileTarget {\n return {\n filePath: normalizeTarget(projectRoot, filePath),\n operation: operation === 'rename' ? 'edit' : operation,\n ...(line ? { line } : {}),\n ...(endLine ? { endLine } : {}),\n };\n}\n\nfunction patchTargets(patch: string): string[] {\n const targets: string[] = [];\n for (const line of patch.split(/\\r?\\n/)) {\n const match = /^\\+\\+\\+\\s+(?:b\\/)?(.+?)(?:\\t.*)?$/.exec(line);\n const target = match?.[1]?.trim();\n if (target && target !== '/dev/null') targets.push(target);\n }\n return targets;\n}\n\n/**\n * Convert heterogeneous tool inputs into canonical absolute file targets.\n * This is intentionally deterministic and shared by both standalone and CLI\n * WebUI event bridges so the browser never has to guess path roots.\n */\nexport function extractCodeMapFileTargets(\n projectRoot: string,\n toolName: string,\n rawInput: unknown,\n): CodeMapFileTarget[] {\n const operation = TOOL_OPERATION[toolName.toLowerCase()];\n if (!operation || !rawInput || typeof rawInput !== 'object' || Array.isArray(rawInput)) return [];\n const input = rawInput as Record<string, unknown>;\n const rawPaths: string[] = [];\n for (const key of ['path', 'file', 'filePath', 'target']) {\n const value = input[key];\n if (typeof value === 'string' && value.trim()) rawPaths.push(value.trim());\n }\n const files = input['files'];\n if (Array.isArray(files)) {\n for (const value of files)\n if (typeof value === 'string' && value.trim()) rawPaths.push(value.trim());\n } else if (typeof files === 'string' && files.trim() && !/[?*{}[\\]]/.test(files)) {\n rawPaths.push(files.trim());\n }\n if ((toolName === 'patch' || toolName === 'apply_patch') && typeof input['patch'] === 'string') {\n rawPaths.push(...patchTargets(input['patch']));\n }\n\n const line = numberField(input, ['line', 'offset', 'startLine', 'start_line', 'line_start']);\n const explicitEnd = numberField(input, ['endLine', 'end_line', 'line_end']);\n const limit = numberField(input, ['limit']);\n const endLine = explicitEnd ?? (line && limit ? line + limit - 1 : undefined);\n const seen = new Set<string>();\n const targets: CodeMapFileTarget[] = [];\n for (const rawPath of rawPaths) {\n const filePath = normalizeTarget(projectRoot, rawPath);\n if (seen.has(filePath)) continue;\n seen.add(filePath);\n targets.push({\n filePath,\n operation,\n ...(line ? { line } : {}),\n ...(endLine ? { endLine } : {}),\n });\n }\n return targets;\n}\n", "import { randomUUID } from 'node:crypto';\nimport type { CollaborationBus, ConsumedInjectionInfo } from '@wrongstack/core/coordination';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport type { AnnotationsStore, SessionReader } from '@wrongstack/core/storage';\nimport type { Logger } from '@wrongstack/core/types';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport type { WebSocket } from 'ws';\nimport type { CollabRole, WSCollabState, WSServerMessage } from './types.js';\nimport { sendSerialized } from './ws-utils.js';\n\n/** How many historical events to replay to a late-joining observer. */\nconst REPLAY_LIMIT = 50;\n\n/** How long the middleware waits before auto-resuming (mirrors the middleware default). */\nconst PAUSE_TIMEOUT_MS = 60_000;\n\nexport interface CollaborationHandlerOptions {\n /**\n * Resolve the session currently owned by this WebUI runtime. When supplied,\n * joins and live EventBus mirrors are constrained to that session.\n */\n getActiveSessionId?: (() => string) | undefined;\n /**\n * Host-owned authorization for roles that can mutate collaboration state.\n * Omission is intentionally fail-closed: clients may only join as observers.\n */\n authorizeRole?:\n | ((input: {\n ws: WebSocket;\n sessionId: string;\n requestedRole: Exclude<CollabRole, 'observer'>;\n }) => boolean)\n | undefined;\n}\n\n/**\n * CollaborationWebSocketHandler \u2014 session-scoped collaboration transport.\n * Mirrors `WorktreeWebSocketHandler` and `GoalWebSocketHandler`.\n *\n * Capabilities in this phase:\n * - A second human (or any client) joins an active agent run as an\n * `observer` and receives a live mirror of the kernel's iteration /\n * tool / subagent events.\n * - The observer declares a `sessionId` on join. Hosts provide the live\n * runtime session id so replay and EventBus routing stay session-scoped.\n * - The observer can leave at any time; cleanup runs on WS close/error.\n * - Privileged roles are never accepted from the wire by themselves.\n * The host must explicitly authorize annotator/controller grants.\n *\n * Protocol additions (see `packages/webui/src/types.ts`):\n * client \u2192 server: collab.join { sessionId, role: 'observer' }\n * collab.leave { sessionId }\n * server \u2192 client: collab.state (initial + 2s periodic)\n * collab.participant.joined\n * collab.participant.left\n * collab.event (live kernel event mirror)\n */\nexport class CollaborationWebSocketHandler {\n private readonly clients = new Set<WebSocket>();\n /** sessionId \u2192 participants currently watching it. */\n private readonly bySession = new Map<string, Set<Participant>>();\n private broadcastInterval: ReturnType<typeof setInterval> | null = null;\n private readonly offs: Array<() => void> = [];\n\n constructor(\n private readonly events: EventBus,\n private readonly logger: Logger,\n /**\n * Optional reader over the on-disk session log. When provided, late\n * joiners receive the last `REPLAY_LIMIT` events of the joined\n * session before live mirroring begins. Without a reader, joining\n * is still allowed \u2014 the observer simply starts from \"now\" with no\n * historical context.\n */\n private readonly reader?: SessionReader | undefined,\n /**\n * Optional sidecar store for collaboration annotations. Required\n * for the `annotator` role \u2014 without it, `collab.annotate` messages\n * are rejected with an error.\n */\n private readonly annotations?: AnnotationsStore | undefined,\n /**\n * Optional kernel-level pause/resume bus. Required for the\n * `controller` role \u2014 without it, `collab.request_pause` is rejected\n * with an error. Wired to the agent's `toolCall` pipeline via\n * `collabPauseMiddleware` in the webui server boot.\n */\n private readonly bus?: CollaborationBus | undefined,\n private readonly options: CollaborationHandlerOptions = {},\n ) {\n this.subscribe();\n // Phase 4 feedback loop: when the inject middleware applies a queued\n // injection, broadcast a `consumed` grant so observers see it landed.\n // Store the disposer in this.offs so dispose() removes the callback,\n // preventing the handler closure from keeping this instance alive\n // via the bus reference after teardown.\n const offInjection = this.bus?.onInjectionConsumed((info) =>\n this.broadcastInjectionConsumed(info),\n );\n if (offInjection) this.offs.push(offInjection);\n }\n\n // \u2500\u2500 Public API (called by server/index.ts per WS connection) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n addClient(ws: WebSocket): void {\n this.clients.add(ws);\n this.ensureBroadcast();\n ws.on('close', () => this.handleDisconnect(ws));\n ws.on('error', () => this.handleDisconnect(ws));\n }\n\n dispose(): void {\n for (const off of this.offs) off();\n this.offs.length = 0;\n this.stopBroadcast();\n this.clients.clear();\n }\n\n // \u2500\u2500 Inbound client messages \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Dispatch a parsed client message. Returns true when the message was\n * recognized and handled; false when the caller should ignore / log.\n * Phase 1 only knows `collab.join` and `collab.leave`; unknown types\n * return false so the upstream router can decide.\n */\n handleMessage(ws: WebSocket, msg: { type: string; payload?: unknown | undefined }): boolean {\n if (msg.type === 'collab.join') {\n const payload = msg.payload as\n | { sessionId?: string | undefined; role?: CollabRole | undefined }\n | undefined;\n if (typeof payload?.sessionId !== 'string' || payload.sessionId.trim().length === 0) {\n this.send(ws, this.errorMessage('collab.join requires sessionId'));\n return true;\n }\n const role = payload.role ?? 'observer';\n if (role !== 'observer' && role !== 'annotator' && role !== 'controller') {\n this.send(ws, this.errorMessage(`unknown collaboration role '${String(role)}'`));\n return true;\n }\n this.join(ws, payload.sessionId, role);\n return true;\n }\n if (msg.type === 'collab.leave') {\n this.leave(ws);\n return true;\n }\n if (msg.type === 'collab.annotate') {\n void this.handleAnnotate(ws, msg.payload);\n return true;\n }\n if (msg.type === 'collab.resolve') {\n void this.handleResolve(ws, msg.payload);\n return true;\n }\n if (msg.type === 'collab.request_pause') {\n void this.handleRequestPause(ws, msg.payload);\n return true;\n }\n if (msg.type === 'collab.resume') {\n void this.handleResume(ws, msg.payload);\n return true;\n }\n if (msg.type === 'collab.grant_control') {\n void this.handleGrantControl(ws, msg.payload);\n return true;\n }\n if (msg.type === 'collab.inject_tool') {\n void this.handleInjectTool(ws, msg.payload);\n return true;\n }\n return false;\n }\n\n // \u2500\u2500 Join / leave flow \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private join(ws: WebSocket, sessionId: string, role: CollabRole): void {\n const activeSessionId = this.options.getActiveSessionId?.();\n if (activeSessionId !== undefined && sessionId !== activeSessionId) {\n this.send(\n ws,\n this.errorMessage(`collab.join sessionId mismatch (active: ${activeSessionId})`),\n );\n return;\n }\n if (this.findParticipant(ws)) {\n this.send(ws, this.errorMessage('collab.join requires leaving the current session first'));\n return;\n }\n if (role === 'controller' && !this.bus) {\n this.send(\n ws,\n this.errorMessage(`role 'controller' is not available: server has no CollaborationBus`),\n );\n return;\n }\n if (role === 'annotator' && !this.annotations) {\n this.send(\n ws,\n this.errorMessage(`role 'annotator' is not available: server has no annotations store`),\n );\n return;\n }\n if (\n role !== 'observer' &&\n this.options.authorizeRole?.({ ws, sessionId, requestedRole: role }) !== true\n ) {\n this.send(ws, this.errorMessage(`role '${role}' requires explicit server authorization`));\n return;\n }\n const participant: Participant = {\n participantId: randomUUID(),\n ws,\n sessionId,\n role,\n joinedAt: new Date().toISOString(),\n };\n let bucket = this.bySession.get(sessionId);\n if (!bucket) {\n bucket = new Set();\n this.bySession.set(sessionId, bucket);\n }\n bucket.add(participant);\n\n // Per-participant hello: send the current state snapshot immediately\n // so the new observer knows who else is watching. Then broadcast the\n // join event AND a fresh state to every participant (including the\n // newcomer) so existing observers see the updated count without\n // waiting for the 2s timer.\n this.send(ws, this.stateMessage(sessionId));\n this.broadcast(sessionId, {\n type: 'collab.participant.joined',\n payload: {\n participantId: participant.participantId,\n sessionId,\n role,\n joinedAt: participant.joinedAt,\n },\n });\n this.broadcast(sessionId, this.stateMessage(sessionId));\n\n // Replay last N events to give the late joiner historical context.\n // Best-effort: failures are logged and silently ignored \u2014 the live\n // mirror continues regardless.\n if (this.reader) {\n this.replayHistory(ws, sessionId).catch((err) => {\n this.logger.debug?.(`collab: replay failed for ${sessionId}: ${toErrorMessage(err)}`);\n });\n }\n this.logger.debug?.(`collab: participant ${participant.participantId} joined ${sessionId}`);\n }\n\n private leave(ws: WebSocket): void {\n this.handleDisconnect(ws);\n }\n\n private handleDisconnect(ws: WebSocket): void {\n this.clients.delete(ws);\n // Remove from every session bucket the WS may have joined (a single\n // WS is in at most one bucket in Phase 1, but the loop is cheap and\n // future-proofs multi-session observers).\n //\n // Order matters:\n // 1. Send `participant.left` to the leaving ws so they get a\n // confirmation that their leave registered.\n // 2. Delete from bucket.\n // 3. Broadcast the fresh state to remaining observers so they\n // see the updated count without waiting for the 2s timer.\n for (const [sessionId, bucket] of this.bySession) {\n for (const p of bucket) {\n if (p.ws === ws) {\n const leftEvent = {\n type: 'collab.participant.left' as const,\n payload: { participantId: p.participantId, sessionId },\n };\n // Send directly to the leaving ws first so they get an\n // immediate confirmation, then broadcast to the rest of the\n // bucket (which is still inclusive of the leaving ws here \u2014\n // the per-iteration below strips it out).\n this.send(ws, leftEvent);\n bucket.delete(p);\n if (bucket.size === 0) {\n this.bySession.delete(sessionId);\n } else {\n this.broadcast(sessionId, leftEvent);\n this.broadcast(sessionId, this.stateMessage(sessionId));\n }\n break;\n }\n }\n }\n if (this.bySession.size === 0) this.stopBroadcast();\n }\n\n // \u2500\u2500 Annotation flow (Phase 2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Look up the participant record for a given WS across all sessions.\n * Returns null when the WS hasn't joined (e.g. the client sent a\n * `collab.annotate` before `collab.join`).\n */\n private findParticipant(ws: WebSocket): Participant | null {\n for (const bucket of this.bySession.values()) {\n for (const p of bucket) {\n if (p.ws === ws) return p;\n }\n }\n return null;\n }\n\n private findParticipantById(sessionId: string, participantId: string): Participant | null {\n const bucket = this.bySession.get(sessionId);\n if (!bucket) return null;\n for (const p of bucket) {\n if (p.participantId === participantId) return p;\n }\n return null;\n }\n\n private async handleAnnotate(ws: WebSocket, raw: unknown): Promise<void> {\n if (!this.annotations) {\n this.send(ws, this.errorMessage('annotations store is not configured'));\n return;\n }\n const participant = this.findParticipant(ws);\n if (!participant) {\n this.send(ws, this.errorMessage('annotate requires an active join'));\n return;\n }\n if (participant.role !== 'annotator') {\n this.send(\n ws,\n this.errorMessage(\n `annotate requires the 'annotator' role (current: '${participant.role}')`,\n ),\n );\n return;\n }\n const payload = raw as\n | {\n sessionId?: string | undefined;\n atEventIndex?: number | undefined;\n text?: string | undefined;\n }\n | undefined;\n if (\n !payload?.sessionId ||\n typeof payload.atEventIndex !== 'number' ||\n typeof payload.text !== 'string'\n ) {\n this.send(ws, this.errorMessage('annotate requires { sessionId, atEventIndex, text }'));\n return;\n }\n if (payload.sessionId !== participant.sessionId) {\n this.send(\n ws,\n this.errorMessage(`annotate sessionId mismatch (joined: ${participant.sessionId})`),\n );\n return;\n }\n try {\n const annotation = await this.annotations.add({\n sessionId: payload.sessionId,\n atEventIndex: payload.atEventIndex,\n authorId: participant.participantId,\n text: payload.text,\n });\n this.broadcast(payload.sessionId, {\n type: 'collab.annotation.added',\n payload: {\n sessionId: payload.sessionId,\n annotation: {\n id: annotation.id,\n atEventIndex: annotation.atEventIndex,\n authorId: annotation.authorId,\n authorRole: annotation.authorRole,\n text: annotation.text,\n createdAt: annotation.createdAt,\n resolved: annotation.resolved,\n },\n },\n });\n } catch (err) {\n this.send(ws, this.errorMessage(`annotation rejected: ${toErrorMessage(err)}`));\n }\n }\n\n private async handleResolve(ws: WebSocket, raw: unknown): Promise<void> {\n if (!this.annotations) {\n this.send(ws, this.errorMessage('annotations store is not configured'));\n return;\n }\n const participant = this.findParticipant(ws);\n if (!participant) {\n this.send(ws, this.errorMessage('resolve requires an active join'));\n return;\n }\n if (participant.role !== 'annotator') {\n this.send(\n ws,\n this.errorMessage(`resolve requires the 'annotator' role (current: '${participant.role}')`),\n );\n return;\n }\n const payload = raw as\n | { sessionId?: string | undefined; annotationId?: string | undefined }\n | undefined;\n if (!payload?.sessionId || !payload.annotationId) {\n this.send(ws, this.errorMessage('resolve requires { sessionId, annotationId }'));\n return;\n }\n if (payload.sessionId !== participant.sessionId) {\n this.send(\n ws,\n this.errorMessage(`resolve sessionId mismatch (joined: ${participant.sessionId})`),\n );\n return;\n }\n try {\n const updated = await this.annotations.resolve({\n sessionId: payload.sessionId,\n annotationId: payload.annotationId,\n resolvedBy: participant.participantId,\n });\n if (!updated) {\n this.send(ws, this.errorMessage(`annotation not found: ${payload.annotationId}`));\n return;\n }\n this.broadcast(payload.sessionId, {\n type: 'collab.annotation.resolved',\n payload: {\n sessionId: payload.sessionId,\n annotationId: updated.id,\n resolvedBy: updated.resolvedBy ?? participant.participantId,\n resolvedAt: updated.resolvedAt ?? new Date().toISOString(),\n },\n });\n } catch (err) {\n this.send(ws, this.errorMessage(`resolve failed: ${toErrorMessage(err)}`));\n }\n }\n\n // \u2500\u2500 Event subscription (live mirror) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private subscribe(): void {\n // Same trick as WorktreeWebSocketHandler: bind a single typed-on helper\n // to a string-keyed signature so we can register many handlers.\n const on = this.events.on.bind(this.events) as never as (\n ev: string,\n fn: (p: unknown) => void,\n ) => () => void;\n\n // Mirror every event an observer would care about. Each is forwarded\n // to all joined participants as a generic `collab.event` envelope so\n // the client can render a flowing activity strip. Filtering /\n // denormalization happens on the client.\n const forwarded: Array<[string, string]> = [\n ['iteration.started', 'iteration.started'],\n ['iteration.completed', 'iteration.completed'],\n ['tool.started', 'tool.started'],\n ['tool.progress', 'tool.progress'],\n ['tool.executed', 'tool.executed'],\n ['tool.confirm_needed', 'tool.confirm_needed'],\n ['subagent.spawned', 'subagent.spawned'],\n ['subagent.task_started', 'subagent.task_started'],\n ['subagent.iteration_summary', 'subagent.iteration_summary'],\n ['subagent.task_completed', 'subagent.task_completed'],\n ['subagent.done', 'subagent.done'],\n ];\n for (const [kernelEvent, kind] of forwarded) {\n this.offs.push(\n on(kernelEvent, (raw) => {\n // Bail before the clone when nobody is watching. This list includes\n // `tool.progress` and `subagent.iteration_summary` \u2014 per-delta hot\n // paths \u2014 and the deep clone below used to run on every kernel event\n // even with zero observers connected, because the only no-op guard\n // lived inside broadcastEvent().\n if (this.bySession.size === 0) return;\n // Best-effort payload shape: we don't deeply validate, but we\n // make sure it's serializable. Observers must never receive\n // non-serializable objects (Functions, circular refs).\n let payload: unknown = raw;\n try {\n payload = JSON.parse(JSON.stringify(raw));\n } catch {\n // Skip unserializable payloads \u2014 better to drop than to crash\n // the broadcast loop.\n return;\n }\n this.broadcastEvent(kind, payload);\n }),\n );\n }\n }\n\n private broadcastEvent(kind: string, payload: unknown): void {\n if (this.bySession.size === 0) return; // nobody watching \u2014 no-op\n const msg: WSServerMessage = {\n type: 'collab.event',\n payload: { kind, payload, at: new Date().toISOString() },\n };\n const activeSessionId = this.options.getActiveSessionId?.();\n if (activeSessionId !== undefined) {\n this.broadcast(activeSessionId, msg);\n return;\n }\n for (const sessionId of this.bySession.keys()) {\n this.broadcast(sessionId, msg);\n }\n }\n\n /**\n * Replay the last `REPLAY_LIMIT` events from the on-disk session log\n * to a single observer (the late joiner). Each event is forwarded as\n * a `collab.event` with `replay: true` so the client can distinguish\n * history from the live stream.\n *\n * The session log stores typed `SessionEvent`s (`user_input`,\n * `llm_response`, `tool_result`, etc.) \u2014 different from the kernel's\n * bus events. We translate the most useful subset (`tool.*` and\n * `iteration.*`-shaped ones) into the same `kind` namespace the live\n * mirror uses, so the client can render a single activity strip.\n */\n private async replayHistory(ws: WebSocket, sessionId: string): Promise<void> {\n if (!this.reader) return;\n // Keep only the trailing REPLAY_LIMIT events in a ring instead of\n // materializing the whole session log. `reader.replay` is already an async\n // iterator; buffering all of it just to `slice(-50)` meant a late joiner\n // pulled an entire (unbounded) session history into memory first.\n const ring: unknown[] = new Array(REPLAY_LIMIT);\n let seen = 0;\n try {\n for await (const ev of this.reader.replay(sessionId)) {\n ring[seen % REPLAY_LIMIT] = ev;\n seen++;\n }\n } catch (err) {\n this.logger.debug?.(`collab: session reader rejected ${sessionId}: ${toErrorMessage(err)}`);\n return;\n }\n const tail =\n seen <= REPLAY_LIMIT\n ? ring.slice(0, seen)\n : // Unwrap the ring back into chronological order.\n [...ring.slice(seen % REPLAY_LIMIT), ...ring.slice(0, seen % REPLAY_LIMIT)];\n if (tail.length === 0) return; // nothing to replay\n for (const raw of tail) {\n const ev = raw as {\n type?: string | undefined;\n ts?: string | undefined;\n [k: string]: unknown;\n };\n const kind = this.historyEventToKind(ev);\n if (!kind) continue; // skip events we don't know how to mirror\n this.send(ws, {\n type: 'collab.event',\n payload: {\n kind,\n payload: ev,\n at: ev.ts ?? new Date().toISOString(),\n replay: true,\n },\n });\n }\n }\n\n /**\n * Map a stored `SessionEvent` to a `collab.event.kind` so the live\n * strip and the history strip can share a single rendering path.\n * Returns null for events that don't have a meaningful live analog\n * (e.g. `session_start`, file-snapshot bookkeeping, rewind markers).\n */\n private historyEventToKind(ev: { type?: string | undefined }): string | null {\n switch (ev.type) {\n case 'user_input':\n return 'user_input';\n case 'llm_response':\n return 'llm_response';\n case 'tool_result':\n return 'tool.executed';\n case 'compaction':\n return 'compaction';\n case 'error':\n return 'error';\n default:\n return null;\n }\n }\n\n // \u2500\u2500 State snapshot + periodic broadcast \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private stateMessage(sessionId: string): WSCollabState {\n const bucket = this.bySession.get(sessionId);\n return {\n type: 'collab.state',\n payload: {\n sessionId,\n participants: bucket\n ? [...bucket].map((p) => ({\n participantId: p.participantId,\n role: p.role,\n joinedAt: p.joinedAt,\n }))\n : [],\n },\n };\n }\n\n private ensureBroadcast(): void {\n if (this.broadcastInterval) return;\n this.broadcastInterval = setInterval(() => {\n for (const sessionId of this.bySession.keys()) {\n this.broadcast(sessionId, this.stateMessage(sessionId));\n }\n }, 2000);\n }\n\n private stopBroadcast(): void {\n if (this.broadcastInterval) {\n clearInterval(this.broadcastInterval);\n this.broadcastInterval = null;\n }\n }\n\n private broadcast(sessionId: string, msg: WSServerMessage): void {\n const data = JSON.stringify(msg);\n const bucket = this.bySession.get(sessionId);\n if (!bucket) return;\n for (const p of bucket) {\n try {\n sendSerialized(p.ws, data);\n } catch (err) {\n this.logger.debug?.(`collab broadcast failed: ${toErrorMessage(err)}`);\n }\n }\n }\n\n private send(ws: WebSocket, msg: WSServerMessage): void {\n try {\n sendSerialized(ws, JSON.stringify(msg));\n } catch {\n /* client gone */\n }\n }\n\n private errorMessage(detail: string): WSServerMessage {\n return { type: 'error', payload: { phase: 'collab', message: detail } };\n }\n\n // \u2500\u2500 Controller flow (Phase 3) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async handleRequestPause(ws: WebSocket, raw: unknown): Promise<void> {\n if (!this.bus) {\n this.send(ws, this.errorMessage('pause requires a CollaborationBus'));\n return;\n }\n const participant = this.findParticipant(ws);\n if (!participant) {\n this.send(ws, this.errorMessage('pause requires an active join'));\n return;\n }\n if (participant.role !== 'controller') {\n this.send(\n ws,\n this.errorMessage(`pause requires the 'controller' role (current: '${participant.role}')`),\n );\n return;\n }\n const payload = raw as { sessionId?: string | undefined } | undefined;\n if (!payload?.sessionId || payload.sessionId !== participant.sessionId) {\n this.send(ws, this.errorMessage('pause sessionId mismatch'));\n return;\n }\n const transitioned = this.bus.requestPause(participant.participantId);\n if (!transitioned) {\n // Already paused \u2014 surface the current state to the requester.\n const s = this.bus.getState();\n this.send(ws, {\n type: 'error',\n payload: {\n phase: 'collab',\n message: `bus already paused by ${s.pausedBy ?? '?'} at ${s.pausedAt ?? '?'}`,\n },\n });\n return;\n }\n const s = this.bus.getState();\n this.broadcast(payload.sessionId, {\n type: 'collab.pause.granted',\n payload: {\n sessionId: payload.sessionId,\n pausedBy: s.pausedBy ?? participant.participantId,\n pausedAt: s.pausedAt ?? new Date().toISOString(),\n autoResumeInMs: PAUSE_TIMEOUT_MS,\n },\n });\n }\n\n private async handleResume(ws: WebSocket, raw: unknown): Promise<void> {\n if (!this.bus) {\n this.send(ws, this.errorMessage('resume requires a CollaborationBus'));\n return;\n }\n const participant = this.findParticipant(ws);\n if (!participant) {\n this.send(ws, this.errorMessage('resume requires an active join'));\n return;\n }\n // Permission: controller OR the original pauser. We do a simple\n // \"any controller can release\" check \u2014 fine for Phase 3, can be\n // tightened to \"only the pauser\" later.\n if (participant.role !== 'controller') {\n this.send(\n ws,\n this.errorMessage(`resume requires the 'controller' role (current: '${participant.role}')`),\n );\n return;\n }\n const payload = raw as { sessionId?: string | undefined } | undefined;\n if (!payload?.sessionId || payload.sessionId !== participant.sessionId) {\n this.send(ws, this.errorMessage('resume sessionId mismatch'));\n return;\n }\n const transitioned = this.bus.resume();\n if (!transitioned) {\n this.send(ws, this.errorMessage('bus is not currently paused'));\n return;\n }\n this.broadcast(payload.sessionId, {\n type: 'collab.pause.released',\n payload: {\n sessionId: payload.sessionId,\n reason: 'controller',\n at: new Date().toISOString(),\n },\n });\n }\n\n private async handleGrantControl(ws: WebSocket, raw: unknown): Promise<void> {\n // Promote a target participant to `controller` so the pause/resume and\n // inject_tool checks (which gate on role === 'controller') accept it. Only\n // a current controller may grant; the granter itself already passed the\n // bus requirement when it joined as controller, so no extra bus check is\n // needed here. The new roster is broadcast so every client reflects it.\n const participant = this.findParticipant(ws);\n if (!participant) {\n this.send(ws, this.errorMessage('grant_control requires an active join'));\n return;\n }\n if (participant.role !== 'controller') {\n this.send(\n ws,\n this.errorMessage(\n `grant_control requires the 'controller' role (current: '${participant.role}')`,\n ),\n );\n return;\n }\n const payload = raw as\n | { sessionId?: string | undefined; toParticipant?: string | undefined }\n | undefined;\n if (\n !payload?.sessionId ||\n !payload.toParticipant ||\n payload.sessionId !== participant.sessionId\n ) {\n this.send(ws, this.errorMessage('grant_control requires { sessionId, toParticipant }'));\n return;\n }\n const target = this.findParticipantById(payload.sessionId, payload.toParticipant);\n if (!target) {\n this.send(\n ws,\n this.errorMessage(\n `grant_control: no participant '${payload.toParticipant}' in this session`,\n ),\n );\n return;\n }\n target.role = 'controller';\n this.logger.debug?.(\n `collab: control granted from ${participant.participantId} to ${target.participantId} in ${payload.sessionId}`,\n );\n this.broadcast(payload.sessionId, this.stateMessage(payload.sessionId));\n }\n\n /**\n * Phase 4 \u2014 handle a controller's manual tool-call injection.\n * Validates the payload, queues it on the bus, and broadcasts\n * the grant so observers see what just happened. The actual\n * splice into the agent's pipeline is performed by the\n * `collabInjectMiddleware` on the next tool call.\n */\n private async handleInjectTool(ws: WebSocket, raw: unknown): Promise<void> {\n if (!this.bus) {\n this.send(ws, this.errorMessage('inject_tool requires a CollaborationBus'));\n return;\n }\n const participant = this.findParticipant(ws);\n if (!participant) {\n this.send(ws, this.errorMessage('inject_tool requires an active join'));\n return;\n }\n if (participant.role !== 'controller') {\n this.send(\n ws,\n this.errorMessage(\n `inject_tool requires the 'controller' role (current: '${participant.role}')`,\n ),\n );\n return;\n }\n const payload = raw as\n | {\n sessionId?: string | undefined;\n toolUseId?: string | undefined;\n content?: unknown | undefined;\n isError?: boolean | undefined;\n reason?: string | undefined;\n }\n | undefined;\n if (\n !payload?.sessionId ||\n !payload.toolUseId ||\n typeof payload.isError !== 'boolean' ||\n typeof payload.reason !== 'string' ||\n payload.content === undefined\n ) {\n this.send(\n ws,\n this.errorMessage(\n 'inject_tool requires { sessionId, toolUseId, content, isError, reason }',\n ),\n );\n return;\n }\n if (payload.sessionId !== participant.sessionId) {\n this.send(\n ws,\n this.errorMessage(`inject_tool sessionId mismatch (joined: ${participant.sessionId})`),\n );\n return;\n }\n const queued = this.bus.injectToolResult({\n toolUseId: payload.toolUseId,\n content: payload.content,\n isError: payload.isError,\n reason: payload.reason,\n authorId: participant.participantId,\n });\n if (!queued) {\n this.send(\n ws,\n this.errorMessage(`an injection for toolUseId ${payload.toolUseId} is already queued`),\n );\n return;\n }\n this.broadcast(payload.sessionId, {\n type: 'collab.injection.granted',\n payload: {\n sessionId: payload.sessionId,\n toolUseId: payload.toolUseId,\n // The tool name is unknown here (the injection is queued\n // before the model produces the tool call). We surface a\n // placeholder; the middleware will emit a `consumed` event\n // with the real name on match.\n toolName: '(pending match)',\n authorId: participant.participantId,\n reason: payload.reason,\n isError: payload.isError,\n phase: 'queued',\n at: new Date().toISOString(),\n },\n });\n }\n\n /**\n * Bus callback: a queued injection was spliced into a real tool call. Re-emit\n * `collab.injection.granted` with phase `'consumed'` and the now-known tool\n * name. The injection carries no sessionId, so resolve it from the author's\n * current participant. If the author has left, fail closed rather than leak\n * the payload to unrelated sessions.\n */\n private broadcastInjectionConsumed(info: ConsumedInjectionInfo): void {\n let sessionId: string | null = null;\n for (const [sid, bucket] of this.bySession) {\n for (const p of bucket) {\n if (p.participantId === info.authorId) {\n sessionId = sid;\n break;\n }\n }\n if (sessionId) break;\n }\n const message = (sid: string): WSServerMessage => ({\n type: 'collab.injection.granted',\n payload: {\n sessionId: sid,\n toolUseId: info.toolUseId,\n toolName: info.toolName,\n authorId: info.authorId,\n reason: info.reason,\n isError: info.isError,\n phase: 'consumed',\n at: new Date().toISOString(),\n },\n });\n if (sessionId) {\n this.broadcast(sessionId, message(sessionId));\n } else {\n this.logger.debug?.(\n `collab: consumed injection ${info.toolUseId} has no live author; broadcast suppressed`,\n );\n }\n }\n}\n\ninterface Participant {\n participantId: string;\n ws: WebSocket;\n sessionId: string;\n role: CollabRole;\n joinedAt: string;\n}\n", "/**\n * Context-aware editor completion for the WebUI Monaco surface.\n *\n * The handler combines fast symbol-index hits with a short, JSON-only LLM call.\n * It is intentionally side-effect free: it never writes files and only reads the\n * existing codebase index when available.\n */\n\nimport * as path from 'node:path';\nimport type { WebSocket } from 'ws';\nimport type { Context } from '@wrongstack/core/agent';\nimport type { Provider, Request, Tool } from '@wrongstack/core/types';\nimport { searchCodebaseIndex, type SearchResult } from '@wrongstack/tools/codebase-index/index';\nimport { send, errMessage } from './ws-utils.js';\n\nexport type CompletionItemKind =\n | 'text'\n | 'method'\n | 'function'\n | 'constructor'\n | 'field'\n | 'variable'\n | 'class'\n | 'interface'\n | 'module'\n | 'property'\n | 'unit'\n | 'value'\n | 'enum'\n | 'keyword'\n | 'snippet'\n | 'file'\n | 'reference';\n\nexport interface CompletionSuggestion {\n label: string;\n insertText: string;\n kind?: CompletionItemKind | undefined;\n detail?: string | undefined;\n documentation?: string | undefined;\n sortText?: string | undefined;\n source?: 'llm' | 'index' | 'lsp' | undefined;\n}\n\ninterface CompletionRequestPayload {\n requestId: string;\n filePath: string;\n language: string;\n lineNumber: number;\n column: number;\n content?: string | undefined;\n prefix: string;\n suffix?: string | undefined;\n triggerCharacter?: string | undefined;\n triggerKind?: number | undefined;\n allowLlm?: boolean | undefined;\n}\n\nexport interface CompletionHandlerOptions {\n projectRoot: string;\n provider?: Provider | undefined;\n model?: string | undefined;\n indexDir?: string | undefined;\n lspCompletion?: LspCompletionSource | undefined;\n timeoutMs?: number | undefined;\n}\n\nexport interface LspCompletionSourceRequest {\n filePath: string;\n lineNumber: number;\n column: number;\n content?: string | undefined;\n triggerCharacter?: string | undefined;\n signal: AbortSignal;\n}\n\nexport type LspCompletionSource = (\n request: LspCompletionSourceRequest,\n) => Promise<CompletionSuggestion[]>;\n\nconst MAX_PREFIX_CHARS = 12_000;\nconst MAX_SUFFIX_CHARS = 4_000;\nconst MAX_CONTENT_CHARS = 500_000;\nconst INDEX_LIMIT = 8;\nconst LLM_LIMIT = 8;\nconst DEFAULT_TIMEOUT_MS = 4_500;\n\nconst COMPLETION_SYSTEM_PROMPT = [\n 'You are a code completion engine for an IDE.',\n 'Return only JSON. No markdown, prose, or code fences.',\n 'Suggest context-aware completions that fit the cursor location.',\n 'Prefer project-local names, repository conventions, and type-safe APIs.',\n 'Do not invent large code blocks; keep insertText small and directly insertable.',\n].join('\\n');\n\nconst COMPLETION_JSON_SCHEMA = {\n type: 'object',\n additionalProperties: false,\n properties: {\n items: {\n type: 'array',\n maxItems: LLM_LIMIT,\n items: {\n type: 'object',\n additionalProperties: false,\n properties: {\n label: { type: 'string' },\n insertText: { type: 'string' },\n kind: {\n type: 'string',\n enum: [\n 'text',\n 'method',\n 'function',\n 'constructor',\n 'field',\n 'variable',\n 'class',\n 'interface',\n 'module',\n 'property',\n 'unit',\n 'value',\n 'enum',\n 'keyword',\n 'snippet',\n 'file',\n 'reference',\n ],\n },\n detail: { type: 'string' },\n documentation: { type: 'string' },\n sortText: { type: 'string' },\n },\n required: ['label', 'insertText'],\n },\n },\n },\n required: ['items'],\n};\n\nexport async function handleCompletionRequest(\n ws: WebSocket,\n msg: unknown,\n opts: CompletionHandlerOptions,\n): Promise<void> {\n const parsed = parsePayload(msg);\n if (!parsed.ok) {\n send(ws, {\n type: 'completion.result',\n payload: {\n requestId: parsed.requestId ?? '',\n filePath: parsed.filePath ?? '',\n items: [],\n error: parsed.error,\n },\n });\n return;\n }\n\n const payload = parsed.payload;\n const projectRoot = path.resolve(opts.projectRoot);\n const resolved = path.resolve(projectRoot, payload.filePath);\n if (!isInside(projectRoot, resolved)) {\n send(ws, {\n type: 'completion.result',\n payload: {\n requestId: payload.requestId,\n filePath: payload.filePath,\n items: [],\n error: 'Forbidden',\n },\n });\n return;\n }\n\n const prefix = tail(payload.prefix, MAX_PREFIX_CHARS);\n const suffix = head(payload.suffix ?? '', MAX_SUFFIX_CHARS);\n const linePrefix = currentLinePrefix(prefix);\n const query = buildSearchQuery(linePrefix, payload.filePath);\n\n const [lspItems, indexItems] = await Promise.all([\n loadLspSuggestions(opts.lspCompletion, payload, resolved)\n .catch(() => [] as CompletionSuggestion[]),\n loadIndexSuggestions({\n projectRoot,\n indexDir: opts.indexDir,\n query,\n }).catch(() => [] as CompletionSuggestion[]),\n ]);\n\n const llmResult = shouldUseLlm(payload, linePrefix, query)\n ? await loadLlmSuggestions({\n provider: opts.provider,\n model: opts.model,\n payload,\n prefix,\n suffix,\n linePrefix,\n query,\n relatedSymbols: indexItems,\n timeoutMs: opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n }).catch((err) => ({ error: errMessage(err), items: [] as CompletionSuggestion[] }))\n : ([] as CompletionSuggestion[]);\n\n const llmItems = Array.isArray(llmResult) ? llmResult : llmResult.items;\n const error = Array.isArray(llmResult) ? undefined : llmResult.error;\n const items = mergeSuggestions([...lspItems, ...llmItems, ...indexItems]).slice(\n 0,\n LLM_LIMIT + INDEX_LIMIT,\n );\n\n send(ws, {\n type: 'completion.result',\n payload: {\n requestId: payload.requestId,\n filePath: payload.filePath,\n items,\n error: items.length === 0 ? error : undefined,\n },\n });\n}\n\nexport function createToolLspCompletionSource(\n tool: Tool | undefined,\n ctx: Context,\n): LspCompletionSource | undefined {\n if (!tool) return undefined;\n return async (request) => {\n const output = await tool.execute(\n {\n path: request.filePath,\n line: request.lineNumber,\n character: request.column,\n content: request.content,\n limit: 8,\n trigger_character: request.triggerCharacter,\n format: 'json',\n },\n ctx,\n { signal: request.signal },\n );\n return parseLspToolOutput(String(output));\n };\n}\n\nfunction parsePayload(msg: unknown):\n | { ok: true; payload: CompletionRequestPayload }\n | { ok: false; error: string; requestId?: string | undefined; filePath?: string | undefined } {\n const payload = (msg as { payload?: Partial<CompletionRequestPayload> | undefined }).payload;\n const requestId = typeof payload?.requestId === 'string' ? payload.requestId : undefined;\n const filePath = typeof payload?.filePath === 'string' ? payload.filePath : undefined;\n if (!payload || typeof payload !== 'object') {\n return { ok: false, error: 'Missing payload' };\n }\n if (!requestId) {\n return { ok: false, error: 'Missing requestId', filePath };\n }\n if (!filePath) {\n return { ok: false, error: 'Missing filePath', requestId };\n }\n if (typeof payload.language !== 'string') {\n return { ok: false, error: 'Missing language', requestId, filePath };\n }\n if (typeof payload.prefix !== 'string') {\n return { ok: false, error: 'Missing prefix', requestId, filePath };\n }\n if (!isValidPositionValue(payload.lineNumber) || !isValidPositionValue(payload.column)) {\n return { ok: false, error: 'Invalid cursor position', requestId, filePath };\n }\n const content = typeof payload.content === 'string' && payload.content.length <= MAX_CONTENT_CHARS\n ? payload.content\n : undefined;\n return {\n ok: true,\n payload: {\n requestId,\n filePath,\n language: payload.language,\n lineNumber: payload.lineNumber,\n column: payload.column,\n content,\n prefix: payload.prefix,\n suffix: typeof payload.suffix === 'string' ? payload.suffix : undefined,\n triggerCharacter: typeof payload.triggerCharacter === 'string'\n ? payload.triggerCharacter\n : undefined,\n triggerKind: typeof payload.triggerKind === 'number' ? payload.triggerKind : undefined,\n allowLlm: typeof payload.allowLlm === 'boolean' ? payload.allowLlm : undefined,\n },\n };\n}\n\nfunction shouldUseLlm(\n payload: CompletionRequestPayload,\n linePrefix: string,\n query: string,\n): boolean {\n if (payload.allowLlm !== undefined) return payload.allowLlm;\n if (payload.triggerCharacter === '.') return true;\n if (payload.triggerCharacter) return false;\n const token = linePrefix.match(/([A-Za-z_$][\\w$]*)$/)?.[1] ?? query;\n return /^(findBy|findAllBy|create|update|delete|remove|get[A-Z_]|set[A-Z_]|use[A-Z_])/.test(\n token,\n );\n}\n\nasync function loadIndexSuggestions(opts: {\n projectRoot: string;\n indexDir?: string | undefined;\n query: string;\n}): Promise<CompletionSuggestion[]> {\n const query = opts.query.trim();\n if (query.length < 2) return [];\n const result = await searchCodebaseIndex(\n {\n projectRoot: opts.projectRoot,\n indexDir: opts.indexDir,\n query,\n limit: INDEX_LIMIT,\n },\n { timeoutMs: 1_500 },\n );\n\n return result.results.map(indexResultToSuggestion);\n}\n\nasync function loadLspSuggestions(\n source: LspCompletionSource | undefined,\n payload: CompletionRequestPayload,\n resolvedFilePath: string,\n): Promise<CompletionSuggestion[]> {\n if (!source) return [];\n const timer = new AbortController();\n const to = setTimeout(() => timer.abort(new Error('lsp completion timeout')), 2_000);\n to.unref?.();\n try {\n return await source({\n filePath: resolvedFilePath,\n lineNumber: payload.lineNumber,\n column: payload.column,\n content: payload.content,\n triggerCharacter: payload.triggerCharacter,\n signal: timer.signal,\n });\n } finally {\n timer.abort();\n clearTimeout(to);\n }\n}\n\nasync function loadLlmSuggestions(opts: {\n provider?: Provider | undefined;\n model?: string | undefined;\n payload: CompletionRequestPayload;\n prefix: string;\n suffix: string;\n linePrefix: string;\n query: string;\n relatedSymbols: CompletionSuggestion[];\n timeoutMs: number;\n}): Promise<CompletionSuggestion[]> {\n if (!opts.provider || !opts.model) return [];\n\n const req: Request = {\n model: opts.model,\n system: [{ type: 'text', text: COMPLETION_SYSTEM_PROMPT }],\n messages: [\n {\n role: 'user',\n content: buildCompletionPrompt(opts),\n },\n ],\n maxTokens: 700,\n };\n\n if (opts.provider.capabilities.structuredOutput) {\n req.responseFormat = {\n type: 'json_schema',\n jsonSchema: {\n name: 'code_completion_suggestions',\n strict: false,\n schema: COMPLETION_JSON_SCHEMA,\n },\n };\n } else if (opts.provider.capabilities.jsonMode) {\n req.responseFormat = { type: 'json_object' };\n }\n\n const timer = new AbortController();\n const to = setTimeout(() => timer.abort(new Error('completion timeout')), opts.timeoutMs);\n to.unref?.();\n try {\n const res = await opts.provider.complete(req, { signal: timer.signal });\n const text = res.content\n .filter((block) => block.type === 'text')\n .map((block) => block.text)\n .join('\\n')\n .trim();\n return parseCompletionJson(text).slice(0, LLM_LIMIT);\n } finally {\n timer.abort();\n clearTimeout(to);\n }\n}\n\nfunction buildCompletionPrompt(opts: {\n payload: CompletionRequestPayload;\n prefix: string;\n suffix: string;\n linePrefix: string;\n query: string;\n relatedSymbols: CompletionSuggestion[];\n}): string {\n const related = opts.relatedSymbols.length > 0\n ? opts.relatedSymbols\n .slice(0, INDEX_LIMIT)\n .map((item) => `- ${item.label}: ${item.detail ?? item.documentation ?? item.kind ?? 'symbol'}`)\n .join('\\n')\n : '(none)';\n\n return [\n `File: ${opts.payload.filePath}`,\n `Language: ${opts.payload.language}`,\n `Cursor: line ${opts.payload.lineNumber}, column ${opts.payload.column}`,\n `Trigger: ${opts.payload.triggerCharacter ?? 'manual'}`,\n `Current line prefix: ${opts.linePrefix}`,\n `Search/query hint: ${opts.query}`,\n '',\n 'Relevant project symbols from the codebase index:',\n related,\n '',\n 'Return JSON shaped exactly as:',\n '{\"items\":[{\"label\":\"name\",\"insertText\":\"text\",\"kind\":\"function\",\"detail\":\"short optional detail\",\"documentation\":\"short optional docs\",\"sortText\":\"optional\"}]}',\n '',\n '<prefix>',\n opts.prefix,\n '</prefix>',\n '<suffix>',\n opts.suffix,\n '</suffix>',\n ].join('\\n');\n}\n\nfunction parseCompletionJson(text: string): CompletionSuggestion[] {\n const parsed = JSON.parse(extractJson(text)) as { items?: unknown };\n if (!Array.isArray(parsed.items)) return [];\n return parsed.items\n .map(normalizeSuggestion)\n .filter((item): item is CompletionSuggestion => item !== null);\n}\n\nfunction normalizeSuggestion(value: unknown): CompletionSuggestion | null {\n if (!value || typeof value !== 'object') return null;\n const raw = value as Record<string, unknown>;\n const label = typeof raw.label === 'string' ? raw.label.trim() : '';\n const insertText = typeof raw.insertText === 'string' ? raw.insertText : '';\n if (!label || !insertText) return null;\n return {\n label,\n insertText,\n kind: normalizeKind(raw.kind),\n detail: optionalString(raw.detail),\n documentation: optionalString(raw.documentation),\n sortText: optionalString(raw.sortText),\n source: 'llm',\n };\n}\n\nfunction indexResultToSuggestion(result: SearchResult): CompletionSuggestion {\n return {\n label: result.name,\n insertText: result.name,\n kind: mapIndexKind(result.kind),\n detail: result.signature || `${result.kind} ${relativeDisplayPath(result.file, result.line)}`,\n documentation: result.docComment || result.snippet || undefined,\n sortText: `z-${String(Math.round(10_000 - result.score)).padStart(5, '0')}-${result.name}`,\n source: 'index',\n };\n}\n\nfunction parseLspToolOutput(output: string): CompletionSuggestion[] {\n if (!output || output.startsWith('No completions') || output.startsWith('[LSP_')) return [];\n const jsonItems = parseLspToolJson(output);\n if (jsonItems) return jsonItems;\n return output\n .split(/\\r?\\n/)\n .map((line) => line.match(/^\\d+\\.\\s+(.+?)\\s+\\[([^\\]]+)](?:\\s+\u2014\\s+(.+))?$/))\n .filter((match): match is RegExpMatchArray => match !== null)\n .map((match, index): CompletionSuggestion => {\n const label = match[1]?.trim() ?? '';\n const detail = match[3]?.trim();\n return {\n label,\n insertText: label,\n kind: mapLspKindName(match[2]),\n detail: detail || undefined,\n sortText: `a-${String(index).padStart(3, '0')}-${label}`,\n source: 'lsp',\n };\n })\n .filter((item) => item.label);\n}\n\nfunction parseLspToolJson(output: string): CompletionSuggestion[] | null {\n try {\n const parsed = JSON.parse(output) as { items?: unknown };\n if (!Array.isArray(parsed.items)) return [];\n return parsed.items\n .map((value, index): CompletionSuggestion | null => {\n if (!value || typeof value !== 'object') return null;\n const raw = value as Record<string, unknown>;\n const label = typeof raw.label === 'string' ? raw.label.trim() : '';\n const insertText = typeof raw.insertText === 'string' && raw.insertText\n ? raw.insertText\n : label;\n if (!label || !insertText) return null;\n return {\n label,\n insertText,\n kind: mapLspKindName(typeof raw.kind === 'string' ? raw.kind : undefined),\n detail: optionalString(raw.detail),\n documentation: optionalString(raw.documentation),\n sortText: `a-${String(index).padStart(3, '0')}-${label}`,\n source: 'lsp',\n };\n })\n .filter((item): item is CompletionSuggestion => item !== null);\n } catch {\n return null;\n }\n}\n\nfunction mapLspKindName(kind: string | undefined): CompletionItemKind {\n switch (kind?.toLowerCase()) {\n case 'method':\n return 'method';\n case 'function':\n return 'function';\n case 'constructor':\n return 'constructor';\n case 'field':\n return 'field';\n case 'variable':\n case 'constant':\n return 'variable';\n case 'class':\n case 'struct':\n return 'class';\n case 'interface':\n case 'typeparameter':\n return 'interface';\n case 'module':\n return 'module';\n case 'property':\n return 'property';\n case 'unit':\n return 'unit';\n case 'value':\n case 'enummember':\n return 'value';\n case 'enum':\n return 'enum';\n case 'keyword':\n return 'keyword';\n case 'snippet':\n return 'snippet';\n case 'file':\n return 'file';\n case 'reference':\n return 'reference';\n default:\n return 'text';\n }\n}\n\nfunction mapIndexKind(kind: SearchResult['kind']): CompletionItemKind {\n switch (kind) {\n case 'class':\n case 'struct':\n return 'class';\n case 'interface':\n case 'trait':\n case 'type':\n return 'interface';\n case 'enum':\n return 'enum';\n case 'function':\n return 'function';\n case 'method':\n return 'method';\n case 'property':\n case 'parameter':\n return 'property';\n case 'var':\n case 'let':\n case 'const':\n case 'static':\n return 'variable';\n case 'namespace':\n case 'mod':\n return 'module';\n default:\n return 'reference';\n }\n}\n\nfunction normalizeKind(value: unknown): CompletionItemKind | undefined {\n if (typeof value !== 'string') return undefined;\n const allowed: CompletionItemKind[] = [\n 'text',\n 'method',\n 'function',\n 'constructor',\n 'field',\n 'variable',\n 'class',\n 'interface',\n 'module',\n 'property',\n 'unit',\n 'value',\n 'enum',\n 'keyword',\n 'snippet',\n 'file',\n 'reference',\n ];\n return allowed.includes(value as CompletionItemKind)\n ? value as CompletionItemKind\n : undefined;\n}\n\nfunction mergeSuggestions(items: CompletionSuggestion[]): CompletionSuggestion[] {\n const seen = new Set<string>();\n const merged: CompletionSuggestion[] = [];\n for (const item of items) {\n const key = `${item.label}\\0${item.insertText}`;\n if (seen.has(key)) continue;\n seen.add(key);\n merged.push(item);\n }\n return merged;\n}\n\nfunction buildSearchQuery(linePrefix: string, filePath: string): string {\n const memberMatch = linePrefix.match(/([A-Za-z_$][\\w$]*)\\.\\s*([A-Za-z_$][\\w$]*)?$/);\n if (memberMatch?.[2]) return memberMatch[2];\n if (memberMatch?.[1]) return memberMatch[1];\n const token = linePrefix.match(/([A-Za-z_$][\\w$]*)$/)?.[1];\n if (token && token.length >= 2) return token;\n return path.basename(filePath, path.extname(filePath));\n}\n\nfunction currentLinePrefix(prefix: string): string {\n const idx = Math.max(prefix.lastIndexOf('\\n'), prefix.lastIndexOf('\\r'));\n return idx === -1 ? prefix : prefix.slice(idx + 1);\n}\n\nfunction extractJson(text: string): string {\n const trimmed = text.trim();\n if (trimmed.startsWith('{')) return trimmed;\n const start = trimmed.indexOf('{');\n const end = trimmed.lastIndexOf('}');\n if (start !== -1 && end > start) return trimmed.slice(start, end + 1);\n return trimmed;\n}\n\nfunction optionalString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\nfunction isValidPositionValue(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 1;\n}\n\nfunction relativeDisplayPath(file: string, line: number): string {\n return `${file.replace(/\\\\/g, '/')}:${line}`;\n}\n\nfunction tail(value: string, max: number): string {\n return value.length <= max ? value : value.slice(value.length - max);\n}\n\nfunction head(value: string, max: number): string {\n return value.length <= max ? value : value.slice(0, max);\n}\n\nfunction isInside(root: string, target: string): boolean {\n return target === root || target.startsWith(root + path.sep);\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface CompletionRouteHandlers {\n request: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport async function handleCompletionRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: CompletionRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'completion.request':\n await handlers.request(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "/**\n * Shared Design Studio WebSocket handlers for both the standalone WebUI server\n * (`packages/webui/src/server/index.ts`) and the CLI's `--webui` embedded\n * server (`packages/cli/src/webui-server.ts`). One source of truth keeps the two\n * servers at parity (enforced by ws-handler-parity.test.ts).\n *\n * case 'design.list': return handleDesignList(ws, designCtx);\n * case 'design.use': return handleDesignUse(ws, designCtx, msg);\n * case 'design.state': return handleDesignState(ws, designCtx);\n * case 'design.set': return handleDesignSet(ws, designCtx, msg);\n * case 'design.materialize': return handleDesignMaterialize(ws, designCtx, msg);\n *\n * Browsing + customization of curated UI design kits; `design.use` pins the\n * active kit, `design.set` records color/token overrides, `design.materialize`\n * writes the (override-applied) tokens to a real theme file on disk.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport {\n applyTokenOverrides,\n clearPersistedActiveKit,\n getDesignKitLoader,\n getDesignState,\n isDesignStack,\n loadActiveKit,\n materializeTokens,\n recordKitChoice,\n recordOverrides,\n resolveSemanticTune,\n type SemanticTune,\n runDesignVerify,\n setActiveKit,\n setDesignOverrides,\n type DesignStack,\n} from '@wrongstack/core/design';\nimport type { WebSocket } from 'ws';\nimport { send } from './ws-utils.js';\n\n/** Coerce a loose payload value into a string\u2192string override map. */\nfunction readOverrides(value: unknown): Record<string, string> {\n const out: Record<string, string> = {};\n if (value && typeof value === 'object') {\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n if (typeof v === 'string') out[k] = v;\n }\n }\n return out;\n}\n\nexport interface DesignContext {\n projectRoot: string;\n /** Live agent context whose `meta.designStudio` we read/pin. Optional. */\n agentMeta?: { meta: Record<string, unknown> } | undefined;\n}\n\nconst FOUNDATIONS_ID = '_foundations';\n\nasync function buildListPayload(ctx: DesignContext): Promise<{\n kits: Array<{\n id: string;\n name: string;\n aesthetic: string;\n bestFor: string;\n stacks: string[];\n tags: string[];\n light: Record<string, string>;\n dark: Record<string, string>;\n }>;\n activeKit: string | null;\n stack: string | null;\n overrides: Record<string, string>;\n}> {\n const loader = getDesignKitLoader(ctx.projectRoot);\n const manifests = (await loader.list()).filter((k) => k.id !== FOUNDATIONS_ID);\n const kits = [];\n for (const m of manifests) {\n const tokens = await loader.readTokens(m.id);\n kits.push({\n id: m.id,\n name: m.name,\n aesthetic: m.aesthetic,\n bestFor: m.bestFor,\n stacks: m.stacks,\n tags: m.tags,\n light: tokens?.light ?? {},\n dark: tokens?.dark ?? {},\n });\n }\n const state = ctx.agentMeta ? getDesignState(ctx.agentMeta) : undefined;\n const persisted = await loadActiveKit(ctx.projectRoot).catch(() => undefined);\n return {\n kits,\n activeKit: state?.activeKit ?? persisted?.kit ?? null,\n stack: state?.stack ?? persisted?.stack ?? null,\n overrides: state?.overrides ?? persisted?.overrides ?? {},\n };\n}\n\nexport async function handleDesignList(ws: WebSocket, ctx: DesignContext): Promise<void> {\n try {\n send(ws, { type: 'design.list', payload: await buildListPayload(ctx) });\n } catch (err) {\n send(ws, {\n type: 'design.list',\n payload: { kits: [], activeKit: null, stack: null, error: String(err) },\n });\n }\n}\n\nexport async function handleDesignState(ws: WebSocket, ctx: DesignContext): Promise<void> {\n const state = ctx.agentMeta ? getDesignState(ctx.agentMeta) : undefined;\n send(ws, {\n type: 'design.state',\n payload: {\n activeKit: state?.activeKit ?? null,\n stack: state?.stack ?? null,\n overrides: state?.overrides ?? {},\n },\n });\n}\n\nexport async function handleDesignUse(\n ws: WebSocket,\n ctx: DesignContext,\n msg: { payload?: unknown },\n): Promise<void> {\n const payload = (msg.payload ?? {}) as { kit?: unknown; stack?: unknown };\n const kitId = typeof payload.kit === 'string' ? payload.kit.trim() : '';\n if (!kitId) {\n send(ws, { type: 'design.use', payload: { ok: false, error: 'No kit id provided' } });\n return;\n }\n try {\n const loader = getDesignKitLoader(ctx.projectRoot);\n const kit = await loader.find(kitId);\n if (!kit) {\n send(ws, { type: 'design.use', payload: { ok: false, kit: kitId, error: 'Kit not found' } });\n return;\n }\n const stackArg = typeof payload.stack === 'string' ? payload.stack : undefined;\n const stack: DesignStack =\n stackArg && isDesignStack(stackArg) ? stackArg : (kit.stacks[0] ?? 'web');\n // Preserve persisted overrides for this kit; merge any passed with `use`.\n const persisted = await loadActiveKit(ctx.projectRoot).catch(() => undefined);\n const keep = persisted?.kit === kit.id ? (persisted.overrides ?? {}) : {};\n const overrides = { ...keep, ...readOverrides((payload as { overrides?: unknown }).overrides) };\n if (ctx.agentMeta) setActiveKit(ctx.agentMeta, kit.id, stack, overrides);\n await recordKitChoice(\n ctx.projectRoot,\n kit.id,\n stack,\n 'webui',\n new Date().toISOString(),\n Object.keys(overrides).length ? overrides : undefined,\n );\n const body = await loader.readBody(kit.id, stack);\n const rawTokens = await loader.readTokens(kit.id);\n const tokens = rawTokens ? applyTokenOverrides(rawTokens, overrides) : rawTokens;\n send(ws, {\n type: 'design.use',\n payload: {\n ok: true,\n kit: kit.id,\n name: kit.name,\n aesthetic: kit.aesthetic,\n stack,\n body,\n overrides,\n light: tokens?.light ?? {},\n dark: tokens?.dark ?? {},\n },\n });\n } catch (err) {\n send(ws, { type: 'design.use', payload: { ok: false, kit: kitId, error: String(err) } });\n }\n}\n\n/** Record structured color/token overrides without changing the pinned kit. */\nexport async function handleDesignSet(\n ws: WebSocket,\n ctx: DesignContext,\n msg: { payload?: unknown },\n): Promise<void> {\n const patch = readOverrides((msg.payload as { overrides?: unknown })?.overrides);\n if (Object.keys(patch).length === 0) {\n send(ws, { type: 'design.set', payload: { ok: false, error: 'No overrides provided' } });\n return;\n }\n try {\n const merged = await recordOverrides(ctx.projectRoot, patch, new Date().toISOString());\n if (!merged) {\n send(ws, { type: 'design.set', payload: { ok: false, error: 'No active kit' } });\n return;\n }\n if (ctx.agentMeta) setDesignOverrides(ctx.agentMeta, merged);\n send(ws, { type: 'design.set', payload: { ok: true, overrides: merged } });\n } catch (err) {\n send(ws, { type: 'design.set', payload: { ok: false, error: String(err) } });\n }\n}\n\n/** Resolve high-level knobs (radius/density/font/motion) into token overrides. */\nexport async function handleDesignTune(\n ws: WebSocket,\n ctx: DesignContext,\n msg: { payload?: unknown },\n): Promise<void> {\n const raw = (msg.payload as { tune?: unknown })?.tune;\n const tune = (raw && typeof raw === 'object' ? raw : {}) as SemanticTune;\n const patch = resolveSemanticTune(tune);\n if (Object.keys(patch).length === 0) {\n send(ws, { type: 'design.tune', payload: { ok: false, error: 'No recognized knobs' } });\n return;\n }\n try {\n const merged = await recordOverrides(ctx.projectRoot, patch, new Date().toISOString());\n if (!merged) {\n send(ws, { type: 'design.tune', payload: { ok: false, error: 'No active kit' } });\n return;\n }\n if (ctx.agentMeta) setDesignOverrides(ctx.agentMeta, merged);\n send(ws, { type: 'design.tune', payload: { ok: true, resolved: patch, overrides: merged } });\n } catch (err) {\n send(ws, { type: 'design.tune', payload: { ok: false, error: String(err) } });\n }\n}\n\n/** Switch to a different kit, dropping the prior kit's overrides. */\nexport async function handleDesignSwap(\n ws: WebSocket,\n ctx: DesignContext,\n msg: { payload?: unknown },\n): Promise<void> {\n const payload = (msg.payload ?? {}) as { kit?: unknown; stack?: unknown };\n const kitId = typeof payload.kit === 'string' ? payload.kit.trim() : '';\n if (!kitId) {\n send(ws, { type: 'design.swap', payload: { ok: false, error: 'No kit id provided' } });\n return;\n }\n try {\n const loader = getDesignKitLoader(ctx.projectRoot);\n const kit = await loader.find(kitId);\n if (!kit) {\n send(ws, { type: 'design.swap', payload: { ok: false, kit: kitId, error: 'Kit not found' } });\n return;\n }\n const stackArg = typeof payload.stack === 'string' ? payload.stack : undefined;\n const stack: DesignStack =\n stackArg && isDesignStack(stackArg) ? stackArg : (kit.stacks[0] ?? 'web');\n // Fresh switch: drop old overrides before pinning.\n await clearPersistedActiveKit(ctx.projectRoot);\n if (ctx.agentMeta) setActiveKit(ctx.agentMeta, kit.id, stack, {});\n await recordKitChoice(ctx.projectRoot, kit.id, stack, 'webui-swap', new Date().toISOString());\n const body = await loader.readBody(kit.id, stack);\n const tokens = await loader.readTokens(kit.id);\n send(ws, {\n type: 'design.swap',\n payload: {\n ok: true,\n kit: kit.id,\n name: kit.name,\n aesthetic: kit.aesthetic,\n stack,\n body,\n overrides: {},\n light: tokens?.light ?? {},\n dark: tokens?.dark ?? {},\n },\n });\n } catch (err) {\n send(ws, { type: 'design.swap', payload: { ok: false, kit: kitId, error: String(err) } });\n }\n}\n\n/** Write the active kit's (override-applied) tokens to a real theme file. */\nexport async function handleDesignMaterialize(\n ws: WebSocket,\n ctx: DesignContext,\n msg: { payload?: unknown },\n): Promise<void> {\n const payload = (msg.payload ?? {}) as { stack?: unknown; out?: unknown };\n try {\n const active = await loadActiveKit(ctx.projectRoot);\n if (!active) {\n send(ws, { type: 'design.materialize', payload: { ok: false, error: 'No active kit' } });\n return;\n }\n const loader = getDesignKitLoader(ctx.projectRoot);\n const stackArg = typeof payload.stack === 'string' ? payload.stack : undefined;\n const stack: DesignStack =\n stackArg && isDesignStack(stackArg)\n ? stackArg\n : active.stack && isDesignStack(active.stack)\n ? active.stack\n : 'web';\n const raw = await loader.readTokens(active.kit);\n if (!raw) {\n send(ws, { type: 'design.materialize', payload: { ok: false, error: 'Kit has no tokens' } });\n return;\n }\n const tokens = applyTokenOverrides(raw, active.overrides);\n const result = materializeTokens({\n tokens,\n stack,\n kitId: active.kit,\n outPath: typeof payload.out === 'string' ? payload.out : undefined,\n });\n const abs = path.join(ctx.projectRoot, result.path);\n await fs.mkdir(path.dirname(abs), { recursive: true });\n await fs.writeFile(abs, result.content);\n send(ws, {\n type: 'design.materialize',\n payload: { ok: true, path: result.path, format: result.format, stack },\n });\n } catch (err) {\n send(ws, { type: 'design.materialize', payload: { ok: false, error: String(err) } });\n }\n}\n\n/** Scan project UI files for off-palette colors against the active kit. */\nexport async function handleDesignVerify(ws: WebSocket, ctx: DesignContext): Promise<void> {\n try {\n const active = await loadActiveKit(ctx.projectRoot);\n if (!active) {\n send(ws, { type: 'design.verify', payload: { ok: false, error: 'No active kit' } });\n return;\n }\n const loader = getDesignKitLoader(ctx.projectRoot);\n const raw = await loader.readTokens(active.kit);\n if (!raw) {\n send(ws, { type: 'design.verify', payload: { ok: false, error: 'Kit has no tokens' } });\n return;\n }\n const tokens = applyTokenOverrides(raw, active.overrides);\n const report = await runDesignVerify(ctx.projectRoot, tokens);\n send(ws, {\n type: 'design.verify',\n payload: {\n ok: true,\n kit: active.kit,\n filesScanned: report.filesScanned,\n score: report.score,\n violations: report.violations.slice(0, 50),\n violationCount: report.violations.length,\n },\n });\n } catch (err) {\n send(ws, { type: 'design.verify', payload: { ok: false, error: String(err) } });\n }\n}\n", "/**\n * Shared file-operation WebSocket handlers for both the standalone WebUI\n * server and the CLI's `--webui` embedded server. Extracted from the\n * duplicated switch cases in `index.ts` and `cli/src/webui-server.ts`.\n *\n * Each function handles the full request\u2192response cycle for one message\n * type. Callers drop them into their switch statement:\n *\n * case 'files.tree': return handleFilesTree(ws, msg, projectRoot);\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { WebSocket } from 'ws';\nimport { ToolValidationError } from '@wrongstack/core/types';\nimport { atomicWrite } from '@wrongstack/core/utils';\nimport { SKIP_DIRS, isHiddenEntry, rankFiles } from './file-picker.js';\nimport { isPathInside, resolveWorkingDirInsideProject } from './path-containment.js';\nimport { send, errMessage } from './ws-utils.js';\n\n/**\n * Resolve a user-supplied file path against `projectRoot` and verify the\n * canonical (real) path stays inside the canonical project root. This\n * rejects:\n * - lexical escapes (`../../etc/passwd`)\n * - in-project symlinks that point outside the project root\n * - absolute paths outside the project root\n *\n * The target file does not need to exist; we `realpath` the parent\n * directory and re-attach the basename. This matches the behavior of\n * `realpath(3)` once the file is later created.\n */\nasync function resolveFileInsideProject(\n projectRoot: string,\n filePath: string,\n): Promise<string> {\n // Lexical containment check first \u2014 cheap, and avoids calling realpath\n // on a path we already know is bogus. This also blocks `..` segments.\n const resolved = path.resolve(projectRoot, filePath);\n if (!isPathInside(projectRoot, resolved)) {\n throw new ToolValidationError({ message: 'Path outside project root', field: 'path' });\n }\n\n // Canonical containment: walk the parent directory's real path and\n // re-attach the basename. If the parent doesn't exist yet, walk up\n // until we find an existing ancestor and verify the rest of the path\n // is still inside the real project root.\n const { parent, base } = splitParentAndBase(resolved);\n const realProjectRoot = await fs.realpath(projectRoot);\n const realParent = await realpathAllowMissing(parent);\n const realFull = path.join(realParent, base);\n if (!isPathInside(realProjectRoot, realFull)) {\n throw new ToolValidationError({ message: 'Path outside project root', field: 'path' });\n }\n return realFull;\n}\n\nfunction splitParentAndBase(p: string): { parent: string; base: string } {\n const base = path.basename(p);\n const parent = path.dirname(p);\n return { parent, base };\n}\n\n/**\n * `realpath` that does not throw when the path doesn't exist. Walks up\n * until an existing ancestor is found, realpaths that ancestor, then\n * re-attaches the missing tail. This is what we need for write targets\n * that don't exist yet, and for read targets whose parent may have\n * been deleted between check and use.\n */\nasync function realpathAllowMissing(p: string): Promise<string> {\n // Existing path \u2014 normal realpath, canonicalizing any symlinks.\n try {\n return await fs.realpath(p);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n }\n // Walk up to the first existing ancestor, realpath that, and reattach.\n const segments: string[] = [];\n let cursor = p;\n while (true) {\n const parent = path.dirname(cursor);\n if (parent === cursor) {\n // Hit a filesystem root and still nothing exists. The lexical\n // check above already kept us inside projectRoot, so this should\n // be unreachable; bail out conservatively.\n throw new ToolValidationError({ message: 'Path outside project root', field: 'path' });\n }\n segments.unshift(path.basename(cursor));\n try {\n const realParent = await fs.realpath(parent);\n return path.join(realParent, ...segments);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') throw err;\n cursor = parent;\n }\n }\n}\n\n// \u2500\u2500 Type helpers (inlined, no dependence on types.ts) \u2500\u2500\n\ninterface FilesListPayload {\n query?: string | undefined;\n limit?: number | undefined;\n /** Optional directory root for the file list (relative to projectRoot).\n * When set, only files under this directory are returned. */\n path?: string | undefined;\n}\n\ninterface FilesReadPayload {\n filePath: string;\n}\n\ninterface FilesWritePayload {\n filePath: string;\n content: string;\n}\n\n/** Guard: ensure msg is an object with a payload of the expected shape.\n * Throws TypeError if the shape is wrong so callers catch it explicitly. */\nfunction validatedPayload<T>(msg: unknown, label: string): T {\n if (msg == null || typeof msg !== 'object') {\n throw new TypeError(`Expected object for ${label}, got ${msg}`);\n }\n const payload = (msg as { payload?: unknown }).payload;\n if (payload == null || typeof payload !== 'object') {\n throw new TypeError(`Expected payload object for ${label}, got ${payload}`);\n }\n return payload as T;\n}\n\nexport interface FilesWriteOptions {\n onWritten?: ((filePath: string) => void | Promise<void>) | undefined;\n}\n\n// \u2500\u2500 Shared handlers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Build and send a nested directory tree for the File Explorer.\n *\n * Walks `projectRoot` to depth 10 max, skipping heavyweight dirs\n * (node_modules, .git, dist, \u2026) and dot-entries. Responds with\n * `{ type: 'files.tree', payload: { root, tree } }`.\n */\nexport async function handleFilesTree(\n ws: WebSocket,\n msg: unknown,\n projectRoot: string,\n): Promise<void> {\n interface TreeNode {\n name: string;\n path: string;\n type: 'file' | 'directory';\n children?: TreeNode[];\n }\n\n // Use the optional `path` from the message payload as the tree root.\n // When absent, empty, or \".\", fall back to projectRoot (backward compatible).\n const payload = (msg as { payload?: { path?: string | undefined } }).payload;\n const rawPath = payload?.path?.trim();\n\n // Guard: the requested tree root must be both lexically AND via\n // realpath() inside the project root. A symlinked subdirectory that\n // points outside the project would otherwise expose arbitrary\n // directory structure to a connected client.\n let treeRoot: string;\n let realProjectRoot: string;\n try {\n if (rawPath && rawPath !== '.') {\n treeRoot = await resolveWorkingDirInsideProject(projectRoot, rawPath);\n } else {\n treeRoot = projectRoot;\n }\n realProjectRoot = await fs.realpath(projectRoot);\n } catch {\n send(ws, {\n type: 'files.tree',\n payload: { root: projectRoot, tree: [], error: 'Path outside project root' },\n });\n return;\n }\n\n // Compute the path prefix so tree paths are always relative to\n // projectRoot (not treeRoot). This ensures double-clicking a file in\n // the explorer sends the correct path to files.read/files.write.\n const pathPrefix = treeRoot === projectRoot\n ? ''\n : (path.relative(projectRoot, treeRoot) + '/').replace(/\\\\/g, '/');\n\n async function buildTree(dir: string, rel: string, depth: number): Promise<TreeNode[]> {\n if (depth > 10) return [];\n let entries: import('node:fs').Dirent[] = [];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return [];\n }\n entries.sort((a, b) => {\n if (a.isDirectory() !== b.isDirectory()) return a.isDirectory() ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n const nodes: TreeNode[] = [];\n for (const e of entries) {\n if (isHiddenEntry(e.name)) continue;\n const childRel = rel ? `${rel}/${e.name}` : e.name;\n const childAbs = path.join(dir, e.name);\n // Prepend the workingDir prefix so the path is projectRoot-relative\n const childPath = pathPrefix + childRel;\n if (e.isDirectory()) {\n if (SKIP_DIRS.has(e.name)) continue;\n // Reject symlinked directories whose real path escapes the\n // real project root. A symlink to an in-project directory is\n // fine and recursed into normally.\n let realChild: string;\n try {\n realChild = await fs.realpath(childAbs);\n } catch {\n continue;\n }\n if (!isPathInside(realProjectRoot, realChild)) {\n continue;\n }\n const children = await buildTree(realChild, childRel, depth + 1);\n nodes.push({ name: e.name, path: childPath, type: 'directory', children });\n } else if (e.isFile()) {\n nodes.push({ name: e.name, path: childPath, type: 'file' });\n }\n }\n return nodes;\n }\n\n try {\n const tree = await buildTree(treeRoot, '', 0);\n const rootLabel = treeRoot === projectRoot\n ? projectRoot\n : path.relative(projectRoot, treeRoot) || '.';\n send(ws, { type: 'files.tree', payload: { root: rootLabel, tree } });\n } catch (err) {\n const rootLabel = treeRoot === projectRoot\n ? projectRoot\n : path.relative(projectRoot, treeRoot) || '.';\n send(ws, {\n type: 'files.tree',\n payload: { root: rootLabel, tree: [], error: errMessage(err) },\n });\n }\n}\n\n/**\n * Read a file's content for the Monaco editor.\n *\n * Guards against path traversal (`../` escapes). Responds with\n * `{ type: 'files.read', payload: { filePath, content } }`.\n */\nexport async function handleFilesRead(\n ws: WebSocket,\n msg: unknown,\n projectRoot: string,\n): Promise<void> {\n let filePath: string;\n try {\n ({ filePath } = validatedPayload<FilesReadPayload>(msg, 'files.read'));\n } catch {\n send(ws, { type: 'files.read', payload: { filePath: '', content: '', error: 'Malformed request' } });\n return;\n }\n\n // Path traversal guard: resolve and verify both lexically AND via\n // realpath() that the file stays inside the canonical project root.\n // A string-prefix check is not enough \u2014 an in-project symlink to\n // an external file would otherwise escape the project root.\n let realResolved: string;\n try {\n realResolved = await resolveFileInsideProject(projectRoot, filePath);\n } catch {\n send(ws, { type: 'files.read', payload: { filePath, content: '', error: 'Forbidden' } });\n return;\n }\n\n try {\n const content = await fs.readFile(realResolved, 'utf8');\n send(ws, { type: 'files.read', payload: { filePath, content } });\n } catch (err) {\n send(ws, {\n type: 'files.read',\n payload: { filePath, content: '', error: errMessage(err) },\n });\n }\n}\n\n/**\n * Write file content back to disk (atomic write via tmp + rename).\n *\n * Guards against path traversal. Responds with\n * `{ type: 'files.written', payload: { filePath, success } }`.\n */\nexport async function handleFilesWrite(\n ws: WebSocket,\n msg: unknown,\n projectRoot: string,\n opts: FilesWriteOptions = {},\n): Promise<void> {\n let filePath: string;\n let content: string;\n try {\n ({ filePath, content } = validatedPayload<FilesWritePayload>(msg, 'files.write'));\n } catch {\n send(ws, { type: 'files.written', payload: { filePath: '', success: false, error: 'Malformed request' } });\n return;\n }\n\n // Path traversal guard: resolve and verify both lexically AND via\n // realpath() that the parent directory stays inside the canonical\n // project root. A string-prefix check is not enough \u2014 an in-project\n // symlink to an external directory would let a write escape the\n // project root and clobber files elsewhere on disk.\n let realResolved: string;\n try {\n realResolved = await resolveFileInsideProject(projectRoot, filePath);\n } catch {\n send(ws, { type: 'files.written', payload: { filePath, success: false, error: 'Forbidden' } });\n return;\n }\n\n try {\n await atomicWrite(realResolved, content);\n send(ws, { type: 'files.written', payload: { filePath, success: true } });\n if (opts.onWritten) {\n void Promise.resolve(opts.onWritten(realResolved)).catch(() => undefined);\n }\n } catch (err) {\n send(ws, {\n type: 'files.written',\n payload: { filePath, success: false, error: errMessage(err) },\n });\n }\n}\n\n/**\n * Lightweight project file picker for the chat `@` mention popup.\n *\n * Walks `projectRoot` (max depth 8), skipping hidden and heavyweight\n * dirs, then fuzzy-ranks results against `query`. Responds with\n * `{ type: 'files.list', payload: { files } }`.\n */\nexport async function handleFilesList(\n ws: WebSocket,\n msg: unknown,\n projectRoot: string,\n): Promise<void> {\n const payload = (msg as { payload?: FilesListPayload }).payload ?? {};\n const limit = payload.limit ?? 50;\n\n // Guard: the requested list root must be both lexically AND via\n // realpath() inside the project root. A symlinked subdirectory that\n // points outside the project would otherwise expose arbitrary\n // filenames to a connected client.\n let listRoot: string;\n let realProjectRoot: string;\n try {\n if (payload.path) {\n listRoot = await resolveWorkingDirInsideProject(projectRoot, payload.path);\n } else {\n listRoot = projectRoot;\n }\n realProjectRoot = await fs.realpath(projectRoot);\n } catch {\n send(ws, { type: 'files.list', payload: { files: [] } });\n return;\n }\n\n const results: string[] = [];\n\n async function walk(dir: string, rel: string, depth: number): Promise<void> {\n if (depth > 8 || results.length >= 600) return;\n let entries: import('node:fs').Dirent[] = [];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch {\n return;\n }\n for (const e of entries) {\n if (results.length >= 600) return;\n if (isHiddenEntry(e.name)) continue;\n const childRel = rel ? `${rel}/${e.name}` : e.name;\n if (e.isDirectory()) {\n if (SKIP_DIRS.has(e.name)) continue;\n // Reject symlinked directories whose real path escapes the\n // real project root. A symlink to an in-project directory is\n // fine and recursed into normally.\n let realChild: string;\n try {\n realChild = await fs.realpath(path.join(dir, e.name));\n } catch {\n continue;\n }\n if (!isPathInside(realProjectRoot, realChild)) {\n continue;\n }\n await walk(realChild, childRel, depth + 1);\n } else if (e.isFile()) {\n results.push(childRel);\n }\n }\n }\n\n await walk(listRoot, '', 0);\n send(ws, {\n type: 'files.list',\n payload: { files: rankFiles(results, payload.query ?? '', limit) },\n });\n}\n", "/**\n * Pure filtering + ranking for the `files.list` project file picker (the chat\n * `@`-mention popup). The directory *walk* stays in index.ts (it's I/O), but\n * the two decisions that shape the result \u2014 which entries to hide and how to\n * rank matches \u2014 are pure and live here so the scoring weights, depth penalty,\n * and tie-break order can be unit tested. A silently-flipped weight would make\n * the picker feel subtly wrong with nothing to catch it.\n */\n/** Heavyweight build/vcs/dependency dirs the picker never descends into. */\nexport const SKIP_DIRS: ReadonlySet<string> = new Set([\n '.git',\n 'node_modules',\n 'dist',\n 'build',\n '.next',\n '.turbo',\n '.cache',\n 'target',\n 'coverage',\n '.nyc_output',\n 'out',\n '.pnpm-store',\n '.parcel-cache',\n]);\n\n/** Dotfiles/dirs kept despite the hide-dotfiles-by-default rule. */\nconst KEEP_DOTFILES: ReadonlySet<string> = new Set([\n '.wrongstack',\n '.env.example',\n '.gitignore',\n '.eslintrc',\n '.prettierrc',\n]);\n\n/**\n * Whether a directory entry should be hidden from the picker by its name.\n * Dotfiles are hidden by default, except a few commonly-wanted ones.\n */\nexport function isHiddenEntry(name: string): boolean {\n return name.startsWith('.') && !KEEP_DOTFILES.has(name);\n}\n\n/**\n * Rank `paths` against `query` and return up to `limit` paths, best first.\n *\n * Scoring (cheap heuristic, good enough for a picker): exact basename match\n * (100) > basename prefix (60) > path substring (20); non-matches are dropped.\n * Each match is penalized by its path depth so root files sort first. Ties\n * break by lexicographic path. An empty query keeps every path (score 0), so\n * the result is the paths sorted lexicographically, capped to `limit`.\n */\nexport function rankFiles(paths: readonly string[], query: string, limit: number): string[] {\n const q = query.toLowerCase();\n const scored: Array<{ path: string; score: number }> = [];\n for (const p of paths) {\n if (!q) {\n scored.push({ path: p, score: 0 });\n continue;\n }\n const lower = p.toLowerCase();\n const base = lower.split('/').pop() ?? lower;\n let score = 0;\n if (base === q) score = 100;\n else if (base.startsWith(q)) score = 60;\n else if (lower.includes(q)) score = 20;\n else continue;\n // Penalise depth so root files come first.\n score -= p.split('/').length;\n scored.push({ path: p, score });\n }\n scored.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path));\n return scored.slice(0, limit).map((s) => s.path);\n}\n", "import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { ToolValidationError } from '@wrongstack/core/types';\n\nexport function isPathInside(root: string, target: string): boolean {\n const relative = path.relative(root, target);\n return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));\n}\n\nexport async function resolveWorkingDirInsideProject(\n projectRoot: string,\n inputPath: string,\n): Promise<string> {\n const resolved = path.resolve(projectRoot, inputPath);\n\n // Reject lexical escapes before touching the target so callers receive a\n // containment error even when the escaped path does not exist.\n if (!isPathInside(path.resolve(projectRoot), resolved)) {\n throw new ToolValidationError({\n message: `Path must stay inside the project root: ${projectRoot}`,\n field: 'path',\n });\n }\n\n let stat;\n try {\n stat = await fs.stat(resolved);\n } catch {\n throw new ToolValidationError({\n message: `Directory not found or not accessible: ${resolved}`,\n field: 'path',\n });\n }\n if (!stat.isDirectory()) {\n throw new ToolValidationError({\n message: `Directory not found or not accessible: ${resolved}`,\n field: 'path',\n });\n }\n\n const [realProjectRoot, realResolved] = await Promise.all([\n fs.realpath(projectRoot),\n fs.realpath(resolved),\n ]);\n\n if (!isPathInside(realProjectRoot, realResolved)) {\n throw new ToolValidationError({\n message: `Path must stay inside the project root: ${projectRoot}`,\n field: 'path',\n });\n }\n\n return resolved;\n}\n", "/**\n * Shared prompt-library WebSocket handlers for BOTH the standalone WebUI server\n * (`packages/webui/src/server/index.ts`) and the CLI's `--webui` embedded server\n * (`packages/cli/src/webui-server.ts`). One source of truth so the two servers\n * never drift (the lesson from skills-handlers).\n *\n * Each function handles one request\u2192response cycle; callers drop them into their\n * switch:\n *\n * case 'prompts.search': return handlePromptsSearch(ws, promptsCtx, msg);\n *\n * The prompt library is read across three layers (builtin + user + project) by\n * the injected `PromptLoader`; writes (create/favorite) go to the user layer\n * with copy-on-write for builtins. Treat synced/builtin content as DATA \u2014 these\n * handlers never execute it; the client inserts a chosen prompt into the chat\n * input as an ordinary user turn.\n */\n\nimport type { PromptUsageStore } from '@wrongstack/core/storage';\nimport type { PromptEntry, PromptLoader, PromptVariable } from '@wrongstack/core/types';\nimport { errMessage, send } from './ws-utils.js';\n\n/**\n * Normalize a client-supplied `variables` array into clean PromptVariable[].\n * Drops entries without a string `name`; carries description/required/multiline\n * and a string-only `enum`. Returns undefined when nothing valid is present so\n * the entry omits the field entirely.\n */\nfunction parseVariablesPayload(raw: unknown): PromptVariable[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const out: PromptVariable[] = [];\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue;\n const o = item as Record<string, unknown>;\n if (typeof o['name'] !== 'string' || !o['name'].trim()) continue;\n const enumVals =\n Array.isArray(o['enum']) && o['enum'].every((x) => typeof x === 'string')\n ? (o['enum'] as string[]).map((s) => s.trim()).filter(Boolean)\n : undefined;\n const v: PromptVariable = { name: o['name'].trim() };\n if (typeof o['description'] === 'string' && o['description'].trim()) {\n v.description = o['description'].trim();\n }\n if (o['required'] === true) v.required = true;\n if (o['multiline'] === true) v.multiline = true;\n if (enumVals && enumVals.length > 0) v.enum = enumVals;\n out.push(v);\n }\n return out.length > 0 ? out : undefined;\n}\n\nexport interface PromptsContext {\n /** Backs all prompt ops. Absent \u21D2 feature unavailable. */\n promptLoader: PromptLoader | undefined;\n /** Records per-slug insert counts (shared with CLI `/prompt recent`). */\n promptUsage?: PromptUsageStore | undefined;\n}\n\n/** Project-relative, content-free metadata for list/search results. */\nfunction toMeta(e: PromptEntry) {\n return {\n id: e.id,\n slug: e.slug,\n title: e.title,\n description: e.description,\n category: e.category,\n tags: e.tags,\n source: e.source,\n favorite: e.favorite,\n variables: e.variables ?? [],\n };\n}\n\nexport async function handlePromptsList(ws: WSLike, ctx: PromptsContext): Promise<void> {\n if (!ctx.promptLoader) {\n send(ws, { type: 'prompts.list', payload: { enabled: false, prompts: [], categories: [] } });\n return;\n }\n try {\n const [all, categories] = await Promise.all([\n ctx.promptLoader.list(),\n ctx.promptLoader.categories(),\n ]);\n send(ws, {\n type: 'prompts.list',\n payload: { enabled: true, prompts: all.map(toMeta), categories },\n });\n } catch (err) {\n send(ws, {\n type: 'prompts.list',\n payload: { enabled: true, prompts: [], categories: [], error: errMessage(err) },\n });\n }\n}\n\nexport async function handlePromptsSearch(\n ws: WSLike,\n ctx: PromptsContext,\n msg: unknown,\n): Promise<void> {\n if (!ctx.promptLoader) {\n send(ws, { type: 'prompts.search', payload: { enabled: false, prompts: [] } });\n return;\n }\n const payload = (msg as { payload?: { query?: string; category?: string } }).payload ?? {};\n try {\n const results = await ctx.promptLoader.search(payload.query ?? '', {\n ...(payload.category ? { category: payload.category } : {}),\n limit: 50,\n });\n send(ws, { type: 'prompts.search', payload: { enabled: true, prompts: results.map(toMeta) } });\n } catch (err) {\n send(ws, {\n type: 'prompts.search',\n payload: { enabled: true, prompts: [], error: errMessage(err) },\n });\n }\n}\n\nexport async function handlePromptsContent(\n ws: WSLike,\n ctx: PromptsContext,\n msg: unknown,\n): Promise<void> {\n const slug = (msg as { payload?: { slug?: string } }).payload?.slug;\n if (!ctx.promptLoader || !slug) {\n send(ws, {\n type: 'prompts.content',\n payload: { slug: slug ?? '', found: false, content: '', variables: [] },\n });\n return;\n }\n try {\n const entry = await ctx.promptLoader.find(slug);\n if (!entry) {\n send(ws, {\n type: 'prompts.content',\n payload: { slug, found: false, content: '', variables: [] },\n });\n return;\n }\n send(ws, {\n type: 'prompts.content',\n payload: {\n slug: entry.slug,\n found: true,\n title: entry.title,\n content: entry.content,\n variables: entry.variables ?? [],\n category: entry.category,\n source: entry.source,\n },\n });\n } catch (err) {\n send(ws, {\n type: 'prompts.content',\n payload: { slug, found: false, content: '', variables: [], error: errMessage(err) },\n });\n }\n}\n\nexport async function handlePromptsFavorite(\n ws: WSLike,\n ctx: PromptsContext,\n msg: unknown,\n): Promise<void> {\n const payload = (msg as { payload?: { slug?: string; favorite?: boolean } }).payload;\n if (!ctx.promptLoader || !payload?.slug) {\n send(ws, {\n type: 'prompts.favorite',\n payload: { success: false, error: 'Prompt library unavailable' },\n });\n return;\n }\n try {\n const updated = await ctx.promptLoader.setFavorite(payload.slug, payload.favorite !== false);\n if (!updated) {\n send(ws, {\n type: 'prompts.favorite',\n payload: { success: false, error: 'Prompt not found' },\n });\n return;\n }\n send(ws, {\n type: 'prompts.favorite',\n payload: { success: true, slug: updated.slug, favorite: updated.favorite },\n });\n } catch (err) {\n send(ws, { type: 'prompts.favorite', payload: { success: false, error: errMessage(err) } });\n }\n}\n\nexport async function handlePromptsCreate(\n ws: WSLike,\n ctx: PromptsContext,\n msg: unknown,\n): Promise<void> {\n const p = (msg as { payload?: Record<string, unknown> }).payload;\n if (!ctx.promptLoader || !p) {\n send(ws, {\n type: 'prompts.created',\n payload: { success: false, error: 'Prompt library unavailable' },\n });\n return;\n }\n const title = typeof p['title'] === 'string' ? p['title'].trim() : '';\n const content = typeof p['content'] === 'string' ? p['content'] : '';\n if (!title || !content) {\n send(ws, {\n type: 'prompts.created',\n payload: { success: false, error: 'Title and content are required' },\n });\n return;\n }\n try {\n const now = new Date().toISOString();\n const tags = Array.isArray(p['tags'])\n ? (p['tags'].filter((t) => typeof t === 'string') as string[])\n : [];\n const slug =\n title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 64) || 'prompt';\n const variables = parseVariablesPayload(p['variables']);\n const entry: PromptEntry = {\n id: slug,\n slug,\n title,\n description: typeof p['description'] === 'string' ? p['description'] : '',\n content,\n category:\n typeof p['category'] === 'string' && p['category']\n ? (p['category'] as string)\n : 'uncategorized',\n tags,\n source: 'user',\n favorite: false,\n ...(variables ? { variables } : {}),\n createdAt: now,\n updatedAt: now,\n };\n await ctx.promptLoader.save(entry);\n send(ws, { type: 'prompts.created', payload: { success: true, slug } });\n } catch (err) {\n send(ws, { type: 'prompts.created', payload: { success: false, error: errMessage(err) } });\n }\n}\n\n/** Record that a prompt was inserted (best-effort; feeds CLI `/prompt recent`). */\nexport async function handlePromptsUsed(ws: WSLike, ctx: PromptsContext, msg: unknown): Promise<void> {\n const slug = (msg as { payload?: { slug?: string } }).payload?.slug;\n if (!ctx.promptUsage || !slug) {\n send(ws, { type: 'prompts.used', payload: { success: false } });\n return;\n }\n try {\n await ctx.promptUsage.record(slug);\n send(ws, { type: 'prompts.used', payload: { success: true, slug } });\n } catch {\n send(ws, { type: 'prompts.used', payload: { success: false } });\n }\n}\n\n/** Return recently-inserted prompt slugs (most-recent first) for the modal's Recent view. */\nexport async function handlePromptsRecent(ws: WSLike, ctx: PromptsContext): Promise<void> {\n if (!ctx.promptUsage) {\n send(ws, { type: 'prompts.recent', payload: { slugs: [] } });\n return;\n }\n try {\n const recent = await ctx.promptUsage.recent(50);\n send(ws, { type: 'prompts.recent', payload: { slugs: recent.map((r) => r.slug) } });\n } catch (err) {\n send(ws, { type: 'prompts.recent', payload: { slugs: [], error: errMessage(err) } });\n }\n}\n\n/** Minimal structural type for the ws.send sink (matches `ws` WebSocket). */\ntype WSLike = Parameters<typeof send>[0];\n", "/**\n * Shared skills WebSocket handlers for both the standalone WebUI server\n * (`packages/webui/src/server/index.ts`) and the CLI's `--webui` embedded\n * server (`packages/cli/src/webui-server.ts`).\n *\n * These were previously inlined in BOTH servers, and the CLI copy had\n * drifted \u2014 it only wired `skills.list`, so `skills.content` /\n * `skills.export` / `skills.update` (and install/uninstall/create/edit)\n * fell through to the \"Unhandled message type\" warning even though the\n * SkillsPanel sends them. Extracting the full set here gives both servers\n * one source of truth. Each function handles the full request\u2192response\n * cycle for one message type; callers drop them into their switch:\n *\n * case 'skills.content': return handleSkillsContent(ws, skillsCtx, msg);\n *\n * The logic is a verbatim lift of the standalone's inline cases \u2014 only the\n * dependency references changed (`skillLoader`/`skillInstaller`/\n * `projectRoot` \u2192 `ctx.*`, local `send`/`errMessage` \u2192 imported helpers).\n */\n\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport type { WebSocket } from 'ws';\nimport type { SkillLoader } from '@wrongstack/core/types';\nimport { atomicWrite, resolveWstackPaths } from '@wrongstack/core/utils';\nimport type { SkillInstaller } from '@wrongstack/core/skills';\nimport { send, errMessage } from './ws-utils.js';\nimport { validateSkillsCreatePayload, validateSkillsEditPayload } from './ws-payload-validation.js';\nimport { createZipBuffer, type ZipEntryInput } from './zip.js';\n\nexport interface SkillsContext {\n /** Backs skills.list/content/edit/export. Absent \u21D2 feature disabled. */\n skillLoader: SkillLoader | undefined;\n /** Backs skills.install/uninstall/update. Absent \u21D2 those ops disabled. */\n skillInstaller: SkillInstaller | undefined;\n /** Project root \u2014 used by skills.create to write `.wrongstack/skills/\u2026`. */\n projectRoot: string;\n /** Project skills directory, normally `<project>/.wrongstack/skills`. */\n projectSkillsDir?: string | undefined;\n /** Profile skills directory, normally `~/.wrongstack/profiles/<name>/skills`. */\n globalSkillsDir?: string | undefined;\n}\n\n// \u2500\u2500 Shared handlers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * List installed skills. Enriches each manifest with the source URL + git\n * ref recorded by the installer (when present), so the panel can show\n * provenance and offer update/uninstall.\n */\nexport async function handleSkillsList(ws: WebSocket, ctx: SkillsContext): Promise<void> {\n if (!ctx.skillLoader) {\n send(ws, { type: 'skills.list', payload: { skills: [], enabled: false } });\n return;\n }\n try {\n const manifests = await ctx.skillLoader.list();\n const entries = await ctx.skillLoader.listEntries();\n const byName = new Map(entries.map((e) => [e.name, e]));\n\n // Fetch source URLs and commit refs from the manifest (installed-skills.json)\n const sourceUrlsByName = new Map<string, string>();\n const refsByName = new Map<string, string>();\n if (ctx.skillInstaller) {\n try {\n const installed = await ctx.skillInstaller.listInstalled();\n for (const entry of installed) {\n sourceUrlsByName.set(entry.name, entry.source);\n refsByName.set(entry.name, entry.ref);\n }\n } catch {\n // Non-fatal \u2014 source URLs just won't be shown\n }\n }\n\n send(ws, {\n type: 'skills.list',\n payload: {\n enabled: true,\n skills: manifests.map((m) => ({\n name: m.name,\n description: m.description,\n version: m.version ?? '',\n source: m.source,\n sourceUrl: sourceUrlsByName.get(m.name) ?? '',\n ref: refsByName.get(m.name) ?? '',\n path: m.path,\n trigger: byName.get(m.name)?.trigger ?? '',\n scope: byName.get(m.name)?.scope ?? [],\n })),\n },\n });\n } catch (err) {\n send(ws, {\n type: 'skills.list',\n payload: {\n skills: [],\n enabled: true,\n error: errMessage(err),\n },\n });\n }\n}\n\n/**\n * Read a single skill's body + its directory's related files + which other\n * skills reference it by name. Powers the skill detail/preview view.\n */\nexport async function handleSkillsContent(\n ws: WebSocket,\n ctx: SkillsContext,\n msg: unknown,\n): Promise<void> {\n if (!ctx.skillLoader) {\n send(ws, { type: 'skills.content', payload: { name: '', body: '', path: '', source: '', relatedFiles: [], references: [], error: 'Skills not enabled' } });\n return;\n }\n const contentPayload = (msg as { payload: { name: string; source: string } }).payload;\n if (!contentPayload?.name) {\n send(ws, { type: 'skills.content', payload: { name: '', body: '', path: '', source: '', relatedFiles: [], references: [], error: 'Skill name is required' } });\n return;\n }\n try {\n const { name, source } = contentPayload;\n const entries = await ctx.skillLoader.listEntries();\n const entry = entries.find((e) => e.name.toLowerCase() === name.toLowerCase());\n if (!entry) {\n send(ws, { type: 'skills.content', payload: { name, body: '', path: '', source, relatedFiles: [], references: [], error: `Skill \"${name}\" not found` } });\n return;\n }\n // Read body directly from path \u2014 avoids re-running find() which re-reads all SKILL.md files\n const body = await fs.readFile(entry.path, 'utf8');\n const skillDir = path.dirname(entry.path);\n\n // Related files \u2014 other files in the same skill directory\n let relatedFiles: string[] = [];\n try {\n const files = await fs.readdir(skillDir);\n relatedFiles = files\n .filter((f) => f !== path.basename(entry.path))\n .map((f) => path.join(skillDir, f));\n } catch {\n // Non-fatal\n }\n\n // References \u2014 which other skills reference this one (by name)\n // Read all other skill bodies in parallel, keyed by name for O(1) lookup\n const nameLower = name.toLowerCase();\n const refResults = await Promise.all(\n entries\n .filter((e) => e.name.toLowerCase() !== nameLower)\n .map(async (e): Promise<[string, boolean]> => {\n try {\n // Use entry.path directly to skip find() overhead\n const content = await fs.readFile(e.path, 'utf8');\n return [e.name, content.toLowerCase().includes(nameLower)];\n } catch {\n return [e.name, false];\n }\n }),\n );\n const refs = refResults.filter(([, hasRef]) => hasRef).map(([n]) => n);\n\n send(ws, { type: 'skills.content', payload: { name, body, path: entry.path, source, relatedFiles, references: refs } });\n } catch (err) {\n send(ws, { type: 'skills.content', payload: { name: contentPayload.name, body: '', path: '', source: contentPayload.source, relatedFiles: [], references: [], error: errMessage(err) } });\n }\n}\n\n/**\n * Install a skill from a git ref (`owner/repo` or URL). Optional `global`\n * installs into the user-wide skills dir instead of the project's.\n */\nexport async function handleSkillsInstall(\n ws: WebSocket,\n ctx: SkillsContext,\n msg: unknown,\n): Promise<void> {\n if (!ctx.skillInstaller) {\n send(ws, { type: 'skills.installed', payload: { success: false, error: 'Skills not enabled' } });\n return;\n }\n const installPayload = (msg as { payload: { ref: string; global?: boolean } }).payload;\n if (!installPayload?.ref?.trim()) {\n send(ws, { type: 'skills.installed', payload: { success: false, error: 'Skill reference is required (e.g. owner/repo or https://github.com/owner/repo)' } });\n return;\n }\n try {\n const results = await ctx.skillInstaller.install(installPayload.ref.trim(), { global: installPayload.global });\n send(ws, {\n type: 'skills.installed',\n payload: {\n success: true,\n results,\n error: null,\n },\n });\n } catch (err) {\n send(ws, {\n type: 'skills.installed',\n payload: {\n success: false,\n error: errMessage(err),\n },\n });\n }\n}\n\n/**\n * Uninstall a skill by name. Optional `global` restricts/Targets the\n * user-wide install.\n */\nexport async function handleSkillsUninstall(\n ws: WebSocket,\n ctx: SkillsContext,\n msg: unknown,\n): Promise<void> {\n if (!ctx.skillInstaller) {\n send(ws, { type: 'skills.uninstalled', payload: { success: false, error: 'Skills not enabled' } });\n return;\n }\n const uninstallPayload = (msg as { payload: { name: string; global?: boolean } }).payload;\n if (!uninstallPayload?.name?.trim()) {\n send(ws, { type: 'skills.uninstalled', payload: { success: false, error: 'Skill name is required' } });\n return;\n }\n try {\n await ctx.skillInstaller.uninstall(uninstallPayload.name.trim(), { global: uninstallPayload.global });\n send(ws, { type: 'skills.uninstalled', payload: { success: true, error: null } });\n } catch (err) {\n send(ws, { type: 'skills.uninstalled', payload: { success: false, error: errMessage(err) } });\n }\n}\n\n/**\n * Update one skill (`name`) or all installed skills (when `name` is\n * omitted). Reports per-skill updated/unchanged/error tallies.\n */\nexport async function handleSkillsUpdate(\n ws: WebSocket,\n ctx: SkillsContext,\n msg: unknown,\n): Promise<void> {\n if (!ctx.skillInstaller) {\n send(ws, { type: 'skills.updated', payload: { success: false, error: 'Skills not enabled' } });\n return;\n }\n const updatePayload = (msg as { payload?: { name?: string; global?: boolean } | undefined }).payload;\n try {\n const result = await ctx.skillInstaller.update(updatePayload?.name, { global: updatePayload?.global });\n send(ws, {\n type: 'skills.updated',\n payload: {\n success: true,\n error: null,\n updated: result.updated,\n unchanged: result.unchanged,\n errors: result.errors,\n },\n });\n } catch (err) {\n send(ws, { type: 'skills.updated', payload: { success: false, error: errMessage(err) } });\n }\n}\n\n/**\n * Scaffold a new project- or global-scoped skill from a name + description.\n * Writes a templated `SKILL.md` under `.wrongstack/skills/<name>/` (project)\n * or the user-wide skills dir (global).\n */\nexport async function handleSkillsCreate(\n ws: WebSocket,\n ctx: SkillsContext,\n msg: unknown,\n): Promise<void> {\n const parsed = validateSkillsCreatePayload((msg as { payload?: unknown }).payload);\n if (!parsed.ok) {\n send(ws, { type: 'skills.created', payload: { success: false, error: parsed.message } });\n return;\n }\n const createPayload = parsed.value;\n try {\n const targetDir =\n createPayload.scope === 'global'\n ? path.join(\n ctx.globalSkillsDir ?? resolveWstackPaths({ projectRoot: ctx.projectRoot }).globalSkills,\n createPayload.name.trim(),\n )\n : path.join(\n ctx.projectSkillsDir ?? path.join(ctx.projectRoot, '.wrongstack', 'skills'),\n createPayload.name.trim(),\n );\n\n // Check if directory already exists\n try {\n await fs.access(targetDir);\n send(ws, { type: 'skills.created', payload: { success: false, error: `Skill \"${createPayload.name}\" already exists` } });\n return;\n } catch {\n // Directory does not exist \u2014 good\n }\n\n await fs.mkdir(targetDir, { recursive: true });\n\n // Parse description lines to build the skill content\n const lines = createPayload.description.trim().split('\\n');\n const firstLine = (lines[0] ?? '').trim();\n const bodyLines = lines.slice(1).map((l) => l.trim()).filter(Boolean);\n const descriptionText = firstLine + (bodyLines.length > 0 ? `\\n${bodyLines.join('\\n')}` : '');\n const trigger = bodyLines.find((l) => l.toLowerCase().startsWith('triggers:')) ?? '';\n\n const skillContent = [\n '---',\n `name: ${createPayload.name.trim()}`,\n 'description: |',\n ` ${descriptionText.replace(/\\n/g, '\\n ')}`,\n `version: 1.0.0`,\n '---',\n '',\n `# ${createPayload.name.trim().split('-').map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' ')}`,\n '',\n '## Overview',\n '',\n firstLine,\n '',\n ...(bodyLines.length > 0 ? bodyLines.filter((l) => !l.toLowerCase().startsWith('triggers:')) : []),\n '',\n '## Rules',\n '- TODO: add your first rule',\n '',\n '## Patterns',\n '### Do',\n '```ts',\n '// TODO: add a good example',\n '```',\n '',\n '### Don\\'t',\n '```ts',\n '// TODO: add a bad example',\n '```',\n '',\n '## Workflow',\n '1. TODO: describe step one',\n '2. TODO: describe step two',\n '',\n trigger ? `\\n${trigger}\\n` : '',\n '## Skills in scope',\n '- `bug-hunter` \u2014 for systematic bug detection patterns',\n '- `output-standards` \u2014 for standardized `<nextsteps>` formatting',\n ].join('\\n');\n\n await atomicWrite(path.join(targetDir, 'SKILL.md'), skillContent);\n\n // Invalidate the SkillLoader cache so the new skill appears immediately\n // in skills.list and the system prompt builder. Without this, the\n // DefaultSkillLoader caches its results and the skill would stay invisible\n // until the next process restart.\n ctx.skillLoader?.invalidateCache();\n\n send(ws, {\n type: 'skills.created',\n payload: {\n success: true,\n error: null,\n skill: { name: createPayload.name.trim(), path: path.join(targetDir, 'SKILL.md'), scope: createPayload.scope },\n },\n });\n } catch (err) {\n send(ws, { type: 'skills.created', payload: { success: false, error: errMessage(err) } });\n }\n}\n\n/**\n * Overwrite a skill's body. Refuses bundled skills (read-only) and unknown\n * names.\n */\nexport async function handleSkillsEdit(\n ws: WebSocket,\n ctx: SkillsContext,\n msg: unknown,\n): Promise<void> {\n if (!ctx.skillLoader) {\n send(ws, { type: 'skills.edited', payload: { success: false, error: 'Skills not enabled' } });\n return;\n }\n const parsed = validateSkillsEditPayload((msg as { payload?: unknown }).payload);\n if (!parsed.ok) {\n send(ws, { type: 'skills.edited', payload: { success: false, error: parsed.message } });\n return;\n }\n const editPayload = parsed.value;\n try {\n const entries = await ctx.skillLoader.listEntries();\n const entry = entries.find((e) => e.name.toLowerCase() === editPayload.name.toLowerCase());\n if (!entry) {\n send(ws, { type: 'skills.edited', payload: { success: false, error: `Skill \"${editPayload.name}\" not found` } });\n return;\n }\n // Only allow editing WrongStack-managed skills (project/user). Bundled and\n // foreign (.claude/*, extra) sources are read-only \u2014 editing them would\n // write into another tool's directory.\n if (entry.source !== 'project' && entry.source !== 'user') {\n const label = entry.source === 'bundled' ? 'Bundled' : 'Foreign (read-only)';\n send(ws, { type: 'skills.edited', payload: { success: false, error: `${label} skills cannot be edited` } });\n return;\n }\n await atomicWrite(entry.path, editPayload.body);\n // Invalidate the SkillLoader cache so the edited body is picked up\n // immediately by readBody and the system prompt builder.\n ctx.skillLoader?.invalidateCache();\n send(ws, { type: 'skills.edited', payload: { success: true, error: null } });\n } catch (err) {\n send(ws, { type: 'skills.edited', payload: { success: false, error: errMessage(err) } });\n }\n}\n\n/**\n * Export every readable skill as a base64-encoded zip (one folder per skill,\n * each with its `SKILL.md`). Powers the panel's \"Export all\" button.\n */\nexport async function handleSkillsExport(ws: WebSocket, ctx: SkillsContext): Promise<void> {\n if (!ctx.skillLoader) {\n send(ws, { type: 'skills.exported', payload: { zipBase64: '', skillCount: 0, error: 'Skills not enabled' } });\n return;\n }\n try {\n const entries = await ctx.skillLoader.listEntries();\n const zipEntries: ZipEntryInput[] = [];\n for (const entry of entries) {\n try {\n const body = await ctx.skillLoader!.readBody(entry.name);\n const safeName = entry.name.replace(/\\//g, '_');\n zipEntries.push({ name: `${safeName}/SKILL.md`, data: body });\n } catch {\n // Skip skills we can't read\n }\n }\n const zipBuffer = createZipBuffer(zipEntries);\n const zipBase64 = zipBuffer.toString('base64');\n send(ws, { type: 'skills.exported', payload: { zipBase64, skillCount: entries.length, error: undefined } });\n } catch (err) {\n send(ws, { type: 'skills.exported', payload: { zipBase64: '', skillCount: 0, error: errMessage(err) } });\n }\n}\n", "import { deflateRawSync, inflateRawSync } from 'node:zlib';\n\nexport interface ZipEntryInput {\n name: string;\n data: string | Uint8Array;\n}\n\n/** Create a standards-compliant ZIP archive using only Node built-ins. */\nexport function createZipBuffer(entries: ZipEntryInput[]): Buffer {\n const localParts: Buffer[] = [];\n const centralParts: Buffer[] = [];\n let offset = 0;\n const { date, time } = dosDateTime(new Date());\n\n for (const entry of entries) {\n const name = Buffer.from(normalizeZipPath(entry.name), 'utf8');\n const data = typeof entry.data === 'string' ? Buffer.from(entry.data, 'utf8') : Buffer.from(entry.data);\n const compressed = deflateRawSync(data);\n const crc = crc32(data);\n const local = Buffer.alloc(30);\n local.writeUInt32LE(0x04034b50, 0);\n local.writeUInt16LE(20, 4);\n local.writeUInt16LE(0x0800, 6);\n local.writeUInt16LE(8, 8);\n local.writeUInt16LE(time, 10);\n local.writeUInt16LE(date, 12);\n local.writeUInt32LE(crc, 14);\n local.writeUInt32LE(compressed.length, 18);\n local.writeUInt32LE(data.length, 22);\n local.writeUInt16LE(name.length, 26);\n localParts.push(local, name, compressed);\n\n const central = Buffer.alloc(46);\n central.writeUInt32LE(0x02014b50, 0);\n central.writeUInt16LE(0x031e, 4);\n central.writeUInt16LE(20, 6);\n central.writeUInt16LE(0x0800, 8);\n central.writeUInt16LE(8, 10);\n central.writeUInt16LE(time, 12);\n central.writeUInt16LE(date, 14);\n central.writeUInt32LE(crc, 16);\n central.writeUInt32LE(compressed.length, 20);\n central.writeUInt32LE(data.length, 24);\n central.writeUInt16LE(name.length, 28);\n central.writeUInt32LE(offset, 42);\n centralParts.push(central, name);\n offset += local.length + name.length + compressed.length;\n }\n\n const centralDirectory = Buffer.concat(centralParts);\n const end = Buffer.alloc(22);\n end.writeUInt32LE(0x06054b50, 0);\n end.writeUInt16LE(entries.length, 8);\n end.writeUInt16LE(entries.length, 10);\n end.writeUInt32LE(centralDirectory.length, 12);\n end.writeUInt32LE(offset, 16);\n return Buffer.concat([...localParts, centralDirectory, end]);\n}\n\n/** Minimal reader for validation/import paths; rejects encrypted or unsafe entries. */\nexport function readZipEntries(archive: Uint8Array): Map<string, Buffer> {\n const maxEntries = 1_000;\n const maxEntryBytes = 64 * 1024 * 1024;\n const maxTotalBytes = 128 * 1024 * 1024;\n const buffer = Buffer.from(archive);\n const result = new Map<string, Buffer>();\n let totalBytes = 0;\n let offset = 0;\n while (offset + 4 <= buffer.length && buffer.readUInt32LE(offset) === 0x04034b50) {\n if (offset + 30 > buffer.length) throw new Error('Truncated ZIP local header.');\n const flags = buffer.readUInt16LE(offset + 6);\n const method = buffer.readUInt16LE(offset + 8);\n if ((flags & 1) !== 0) throw new Error('Encrypted ZIP entries are not supported.');\n if ((flags & 8) !== 0) throw new Error('ZIP data descriptors are not supported.');\n const compressedSize = buffer.readUInt32LE(offset + 18);\n const expectedSize = buffer.readUInt32LE(offset + 22);\n if (result.size >= maxEntries) throw new Error('ZIP contains too many entries.');\n if (expectedSize > maxEntryBytes || totalBytes + expectedSize > maxTotalBytes) {\n throw new Error('ZIP expands beyond the configured size limit.');\n }\n if (compressedSize > 0 && expectedSize / compressedSize > 1_000) {\n throw new Error('ZIP entry has a suspicious compression ratio.');\n }\n const nameLength = buffer.readUInt16LE(offset + 26);\n const extraLength = buffer.readUInt16LE(offset + 28);\n const nameStart = offset + 30;\n const dataStart = nameStart + nameLength + extraLength;\n const dataEnd = dataStart + compressedSize;\n if (dataEnd > buffer.length) throw new Error('Truncated ZIP entry.');\n const name = buffer.subarray(nameStart, nameStart + nameLength).toString('utf8');\n if (!isSafeZipPath(name)) throw new Error(`Unsafe ZIP entry path: ${name}`);\n const compressed = buffer.subarray(dataStart, dataEnd);\n const data = method === 0 ? Buffer.from(compressed) : method === 8 ? inflateRawSync(compressed) : undefined;\n if (!data) throw new Error(`Unsupported ZIP compression method: ${method}`);\n if (data.length !== expectedSize) throw new Error(`ZIP size mismatch for ${name}`);\n if (crc32(data) !== buffer.readUInt32LE(offset + 14)) throw new Error(`ZIP CRC mismatch for ${name}`);\n result.set(name, data);\n totalBytes += data.length;\n offset = dataEnd;\n }\n return result;\n}\n\nfunction normalizeZipPath(value: string): string {\n const normalized = value.replace(/\\\\/g, '/').replace(/^\\/+/, '');\n if (!isSafeZipPath(normalized)) throw new Error(`Unsafe ZIP entry path: ${value}`);\n return normalized;\n}\n\nfunction isSafeZipPath(value: string): boolean {\n return value.length > 0 && !value.includes('\\0') && !value.startsWith('/')\n && !/^[a-z]:/i.test(value) && !value.split('/').includes('..');\n}\n\nfunction dosDateTime(value: Date): { date: number; time: number } {\n const year = Math.max(1980, Math.min(2107, value.getFullYear()));\n return {\n date: ((year - 1980) << 9) | ((value.getMonth() + 1) << 5) | value.getDate(),\n time: (value.getHours() << 11) | (value.getMinutes() << 5) | Math.floor(value.getSeconds() / 2),\n };\n}\n\nconst CRC_TABLE = Array.from({ length: 256 }, (_, index) => {\n let crc = index;\n for (let bit = 0; bit < 8; bit++) crc = (crc & 1) !== 0 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1;\n return crc >>> 0;\n});\n\nfunction crc32(data: Uint8Array): number {\n let crc = 0xffffffff;\n for (const byte of data) crc = (crc >>> 8) ^ (CRC_TABLE[(crc ^ byte) & 0xff] ?? 0);\n return (crc ^ 0xffffffff) >>> 0;\n}\n", "import type { WebSocket } from 'ws';\nimport {\n type DesignContext,\n handleDesignList,\n handleDesignMaterialize,\n handleDesignSet,\n handleDesignState,\n handleDesignSwap,\n handleDesignTune,\n handleDesignUse,\n handleDesignVerify,\n} from './design-handlers.js';\nimport {\n handleFilesList,\n handleFilesRead,\n handleFilesTree,\n handleFilesWrite,\n} from './file-handlers.js';\nimport {\n handlePromptsContent,\n handlePromptsCreate,\n handlePromptsFavorite,\n handlePromptsList,\n handlePromptsRecent,\n handlePromptsSearch,\n handlePromptsUsed,\n type PromptsContext,\n} from './prompts-handlers.js';\nimport {\n handleSkillsContent,\n handleSkillsCreate,\n handleSkillsEdit,\n handleSkillsExport,\n handleSkillsInstall,\n handleSkillsList,\n handleSkillsUninstall,\n handleSkillsUpdate,\n type SkillsContext,\n} from './skills-handlers.js';\nimport type { WSClientMessage } from './types.js';\n\nexport interface ContentRouteContext {\n getProjectRoot: () => string;\n getSkillsContext: () => SkillsContext;\n getPromptsContext: () => PromptsContext;\n getDesignContext: () => DesignContext;\n onFileWritten?: ((filePath: string) => void) | undefined;\n}\n\n/** Canonical file/skill/prompt/design routing shared by every WebUI host. */\nexport async function handleContentRoute(\n ctx: ContentRouteContext,\n ws: WebSocket,\n message: WSClientMessage,\n): Promise<boolean> {\n switch (message.type) {\n case 'files.list':\n await handleFilesList(ws, message, ctx.getProjectRoot());\n return true;\n case 'files.tree':\n await handleFilesTree(ws, message, ctx.getProjectRoot());\n return true;\n case 'files.read':\n await handleFilesRead(ws, message, ctx.getProjectRoot());\n return true;\n case 'files.write':\n await handleFilesWrite(ws, message, ctx.getProjectRoot(), {\n onWritten: ctx.onFileWritten,\n });\n return true;\n case 'skills.list':\n await handleSkillsList(ws, ctx.getSkillsContext());\n return true;\n case 'skills.content':\n await handleSkillsContent(ws, ctx.getSkillsContext(), message);\n return true;\n case 'skills.install':\n await handleSkillsInstall(ws, ctx.getSkillsContext(), message);\n return true;\n case 'skills.uninstall':\n await handleSkillsUninstall(ws, ctx.getSkillsContext(), message);\n return true;\n case 'skills.update':\n await handleSkillsUpdate(ws, ctx.getSkillsContext(), message);\n return true;\n case 'skills.create':\n await handleSkillsCreate(ws, ctx.getSkillsContext(), message);\n return true;\n case 'skills.edit':\n await handleSkillsEdit(ws, ctx.getSkillsContext(), message);\n return true;\n case 'skills.export':\n await handleSkillsExport(ws, ctx.getSkillsContext());\n return true;\n case 'prompts.list':\n await handlePromptsList(ws, ctx.getPromptsContext());\n return true;\n case 'prompts.search':\n await handlePromptsSearch(ws, ctx.getPromptsContext(), message);\n return true;\n case 'prompts.content':\n await handlePromptsContent(ws, ctx.getPromptsContext(), message);\n return true;\n case 'prompts.favorite':\n await handlePromptsFavorite(ws, ctx.getPromptsContext(), message);\n return true;\n case 'prompts.create':\n await handlePromptsCreate(ws, ctx.getPromptsContext(), message);\n return true;\n case 'prompts.used':\n await handlePromptsUsed(ws, ctx.getPromptsContext(), message);\n return true;\n case 'prompts.recent':\n await handlePromptsRecent(ws, ctx.getPromptsContext());\n return true;\n case 'design.list':\n await handleDesignList(ws, ctx.getDesignContext());\n return true;\n case 'design.use':\n await handleDesignUse(ws, ctx.getDesignContext(), message);\n return true;\n case 'design.state':\n await handleDesignState(ws, ctx.getDesignContext());\n return true;\n case 'design.set':\n await handleDesignSet(ws, ctx.getDesignContext(), message);\n return true;\n case 'design.tune':\n await handleDesignTune(ws, ctx.getDesignContext(), message);\n return true;\n case 'design.swap':\n await handleDesignSwap(ws, ctx.getDesignContext(), message);\n return true;\n case 'design.materialize':\n await handleDesignMaterialize(ws, ctx.getDesignContext(), message);\n return true;\n case 'design.verify':\n await handleDesignVerify(ws, ctx.getDesignContext());\n return true;\n default:\n return false;\n }\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface ConversationRouteHandlers {\n userMessage: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n abort: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n ping: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n confirmTool: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport async function handleConversationRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: ConversationRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'user_message':\n await handlers.userMessage(ws, msg);\n return true;\n case 'abort':\n await handlers.abort(ws, msg);\n return true;\n case 'ping':\n await handlers.ping(ws, msg);\n return true;\n case 'tool.confirm_result':\n await handlers.confirmTool(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import type { Agent } from '@wrongstack/core/agent';\nimport type { ContentBlock } from '@wrongstack/core/types';\nimport {\n buildUserContentBlocks,\n IncomingImageError,\n type IncomingImagePayload,\n parseIncomingImages,\n} from '@wrongstack/core/utils';\nimport {\n createToolVisionAdapters,\n ImageInputUnsupportedError,\n routeImagesForModel,\n VisionUrlBlockedError,\n} from '@wrongstack/runtime/vision';\nimport type { WebSocket } from 'ws';\nimport type { ConversationRouteHandlers } from './conversation-routes.js';\nimport type { ConfirmDecision, PendingConfirm } from './pending-confirms.js';\nimport type { WSClientMessage } from './types.js';\nimport { errMessage } from './ws-utils.js';\n\ntype OutboundMessage = { type: string; payload: unknown };\n\nexport interface ConversationRunControl {\n /** Return a controller when acquired, or undefined when this host is busy. */\n begin(ws: WebSocket): AbortController | undefined;\n end(ws: WebSocket, controller: AbortController): void;\n abort(ws: WebSocket): void;\n}\n\nexport interface ConversationOperationsContext {\n getAgent: () => Agent;\n getSessionId: () => string;\n runControl: ConversationRunControl;\n pendingConfirms: Map<string, PendingConfirm>;\n send: (ws: WebSocket, message: OutboundMessage) => void;\n notifyAbort: (ws: WebSocket, message: OutboundMessage) => void;\n getMaxIterations?: () => number | undefined;\n busyPhase?: string;\n busyMessage?: string;\n}\n\nfunction requestedSessionId(msg: WSClientMessage): string | undefined {\n const payload = msg.payload;\n return payload &&\n typeof payload === 'object' &&\n typeof (payload as { sessionId?: unknown }).sessionId === 'string'\n ? (payload as { sessionId: string }).sessionId\n : undefined;\n}\n\nexport function createConversationOperations(\n ctx: ConversationOperationsContext,\n): ConversationRouteHandlers {\n const sessionPayload = (payload: Record<string, unknown>): Record<string, unknown> => {\n const provided = payload['sessionId'];\n const sessionId =\n typeof provided === 'string' && provided.length > 0 ? provided : ctx.getSessionId();\n return sessionId ? { ...payload, sessionId } : payload;\n };\n const ensureCurrentSession = (ws: WebSocket, msg: WSClientMessage, phase: string): boolean => {\n const requested = requestedSessionId(msg);\n const current = ctx.getSessionId();\n if (!requested || !current || requested === current) return true;\n ctx.send(ws, {\n type: 'error',\n payload: sessionPayload({\n phase,\n message: `Request targeted session ${requested}, but this WebUI runtime is currently on ${current}.`,\n requestedSessionId: requested,\n }),\n });\n return false;\n };\n\n return {\n userMessage: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'user_message')) return;\n const payload = (msg.payload ?? {}) as {\n content?: unknown;\n images?: IncomingImagePayload[] | undefined;\n imageBase64?: string | undefined;\n };\n const controller = ctx.runControl.begin(ws);\n if (!controller) {\n ctx.send(ws, {\n type: 'error',\n payload: sessionPayload({\n phase: ctx.busyPhase ?? 'user_message',\n message:\n ctx.busyMessage ??\n 'Agent is already processing a request. Wait for the current run to finish.',\n }),\n });\n return;\n }\n\n // Pin the session this run was started in. The host can swap the\n // active session (session.new/resume) while a slow provider stream\n // is still in flight; stamping run.result with the live session id\n // at completion time would leak the previous request's final text\n // into the freshly-opened session's chat. Declared before the try so\n // the catch branches can stamp it too.\n const originSessionId = ctx.getSessionId();\n try {\n const agent = ctx.getAgent();\n const content = typeof payload.content === 'string' ? payload.content : '';\n let input: string | ContentBlock[] = content;\n const imageBlocks = parseIncomingImages(payload.images, payload.imageBase64);\n if (imageBlocks.length > 0) {\n const routed = await routeImagesForModel(buildUserContentBlocks(content, imageBlocks), {\n supportsVision: agent.ctx.provider.capabilities.vision,\n adapters: () => createToolVisionAdapters(agent.tools),\n ctx: agent.ctx,\n signal: controller.signal,\n providerId: agent.ctx.provider.id,\n model: agent.ctx.model,\n });\n input = routed.blocks;\n }\n const maxIterations = ctx.getMaxIterations?.();\n const runResult = await agent.run(input, {\n signal: controller.signal,\n ...(maxIterations !== undefined ? { maxIterations } : {}),\n });\n ctx.send(ws, {\n type: 'run.result',\n payload: sessionPayload({\n sessionId: originSessionId,\n status: runResult.status,\n iterations: runResult.iterations,\n finalText: runResult.finalText,\n error: runResult.error\n ? {\n code: runResult.error.code,\n message: runResult.error.message,\n recoverable: runResult.error.recoverable,\n }\n : undefined,\n }),\n });\n } catch (error) {\n if (\n error instanceof IncomingImageError ||\n error instanceof ImageInputUnsupportedError ||\n error instanceof VisionUrlBlockedError\n ) {\n ctx.send(ws, {\n type: 'error',\n payload: sessionPayload({\n sessionId: originSessionId,\n phase: 'user_message',\n ...(error instanceof ImageInputUnsupportedError\n ? { code: 'vision_unsupported' }\n : {}),\n message: error.message,\n }),\n });\n } else {\n ctx.send(ws, {\n type: 'error',\n payload: sessionPayload({\n sessionId: originSessionId,\n phase: 'agent.run',\n message: errMessage(error),\n }),\n });\n }\n } finally {\n ctx.runControl.end(ws, controller);\n }\n },\n abort: (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'abort')) return;\n ctx.runControl.abort(ws);\n ctx.notifyAbort(ws, {\n type: 'error',\n payload: sessionPayload({ phase: 'abort', message: 'User aborted' }),\n });\n },\n ping: (ws) => ctx.send(ws, { type: 'pong', payload: {} }),\n confirmTool: (_ws, msg) => {\n const requested = requestedSessionId(msg);\n const current = ctx.getSessionId();\n if (requested && current && requested !== current) return;\n const { id, decision } = (msg.payload ?? {}) as {\n id?: unknown;\n decision?: unknown;\n };\n if (typeof id !== 'string') return;\n const confirm = ctx.pendingConfirms.get(id);\n if (!confirm) return;\n ctx.pendingConfirms.delete(id);\n confirm.resolve(decision as ConfirmDecision);\n },\n };\n}\n", "import { createHash } from 'node:crypto';\nimport type { Context } from '@wrongstack/core/agent';\nimport type { ContentBlock } from '@wrongstack/core/types';\nimport type { Message } from '@wrongstack/core/types';\nimport { repairToolUseAdjacency } from '@wrongstack/core/utils';\nimport type { ToolRegistry } from '@wrongstack/core/registry';\nimport { estimateContextBreakdown, messageTokens } from './token-estimator.js';\n\nexport type ContextEditorBlock = ContentBlock;\n\nexport interface ContextEditorMessage {\n role: Message['role'];\n content: string | ContextEditorBlock[];\n ts?: string | undefined;\n}\n\nexport interface ContextEditorMetrics {\n messages: number;\n blocks: number;\n messageTokens: number;\n fullRequestTokens: number;\n}\n\nexport interface ContextEditorDiagnostics {\n hasToolAdjacencyIssues: boolean;\n orphanToolUses: string[];\n orphanToolResults: string[];\n emptyMessages: number;\n thinkingBlocks: number;\n signedThinkingBlocks: number;\n}\n\nexport interface ContextEditorRepairPreview {\n changed: boolean;\n removedToolUses: string[];\n removedToolResults: string[];\n removedMessages: number;\n}\n\nexport interface ContextEditorValidationError {\n path: string;\n code: string;\n message: string;\n}\n\nexport interface ContextEditorWarning {\n path?: string | undefined;\n code: string;\n severity: 'info' | 'warning' | 'danger';\n message: string;\n}\n\nexport interface ContextEditorConflict {\n code: 'CONTEXT_REVISION_CONFLICT' | 'RUN_ACTIVE';\n message: string;\n}\n\nexport interface ContextEditorValidationResult {\n ok: boolean;\n baseRevision: string;\n currentRevision: string;\n before: ContextEditorMetrics;\n after?: ContextEditorMetrics | undefined;\n validationErrors: ContextEditorValidationError[];\n warnings: ContextEditorWarning[];\n repair: ContextEditorRepairPreview;\n conflict?: ContextEditorConflict | undefined;\n messages?: Message[] | undefined;\n}\n\nexport interface ContextEditorAppliedResult {\n previousRevision: string;\n revision: string;\n before: ContextEditorMetrics;\n after: ContextEditorMetrics;\n removed: {\n messages: number;\n blocks: number;\n toolUses: string[];\n toolResults: string[];\n emptyMessages: number;\n };\n warnings: ContextEditorWarning[];\n}\n\nexport interface ContextEditorSnapshot {\n revision: string;\n messages: ContextEditorMessage[];\n readonlyContext: {\n systemPromptTokens: number;\n toolSchemaTokens: number;\n toolCount: number;\n totalTokens: number;\n messageTokens: number;\n };\n messageBreakdown: Array<{\n index: number;\n role: Message['role'];\n tokens: number;\n preview: string;\n blockCount: number | null;\n warnings: ContextEditorWarning[];\n }>;\n diagnostics: ContextEditorDiagnostics;\n}\n\nconst REVISION_PREFIX = 'wrongstack-context-editor-v1\\0';\nconst MAX_MESSAGE_COUNT_GROWTH = 10;\nconst MAX_PAYLOAD_BYTES = 16 * 1024 * 1024;\nconst MAX_STRING_LENGTH = 8 * 1024 * 1024;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\nfunction canonicalize(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalize);\n if (isRecord(value)) {\n const sorted: Record<string, unknown> = {};\n for (const key of Object.keys(value).sort()) {\n if (key === '_estTokens') continue;\n const item = value[key];\n if (item === undefined) continue;\n sorted[key] = canonicalize(item);\n }\n return sorted;\n }\n return value;\n}\n\nexport function contextEditorRevision(messages: readonly Message[]): string {\n const hash = createHash('sha256');\n hash.update(REVISION_PREFIX);\n hash.update(JSON.stringify(canonicalize(messages)));\n return hash.digest('hex');\n}\n\nfunction jsonByteLength(value: unknown): number {\n try {\n return Buffer.byteLength(JSON.stringify(value), 'utf8');\n } catch {\n return MAX_PAYLOAD_BYTES + 1;\n }\n}\n\nfunction error(\n errors: ContextEditorValidationError[],\n path: string,\n code: string,\n message: string,\n): void {\n errors.push({ path, code, message });\n}\n\nfunction isMessageRole(value: unknown): value is Message['role'] {\n return value === 'user' || value === 'assistant' || value === 'system';\n}\n\nfunction isPlainJsonObject(value: unknown): value is Record<string, unknown> {\n return isRecord(value);\n}\n\nfunction validateCacheControl(\n value: unknown,\n path: string,\n errors: ContextEditorValidationError[],\n): { type: 'ephemeral' } | undefined {\n if (value === undefined) return undefined;\n if (!isRecord(value) || value['type'] !== 'ephemeral') {\n error(errors, path, 'INVALID_CACHE_CONTROL', 'cache_control must be { type: \"ephemeral\" }.');\n return undefined;\n }\n return { type: 'ephemeral' };\n}\n\nfunction validateProviderMeta(\n value: unknown,\n path: string,\n errors: ContextEditorValidationError[],\n): Record<string, unknown> | undefined {\n if (value === undefined) return undefined;\n if (!isPlainJsonObject(value)) {\n error(errors, path, 'INVALID_PROVIDER_META', 'providerMeta must be a JSON object.');\n return undefined;\n }\n return value;\n}\n\nfunction validateBlock(\n value: unknown,\n path: string,\n errors: ContextEditorValidationError[],\n): ContentBlock | undefined {\n if (!isRecord(value)) {\n error(errors, path, 'INVALID_BLOCK', 'Content block must be an object.');\n return undefined;\n }\n const type = value['type'];\n switch (type) {\n case 'text': {\n const text = value['text'];\n if (typeof text !== 'string') {\n error(errors, `${path}/text`, 'INVALID_TEXT', 'Text block text must be a string.');\n return undefined;\n }\n if (text.length > MAX_STRING_LENGTH) {\n error(errors, `${path}/text`, 'TEXT_TOO_LARGE', 'Text block is too large.');\n return undefined;\n }\n const cacheControl = validateCacheControl(value['cache_control'], `${path}/cache_control`, errors);\n return cacheControl ? { type: 'text', text, cache_control: cacheControl } : { type: 'text', text };\n }\n case 'tool_use': {\n const id = value['id'];\n const name = value['name'];\n const input = value['input'];\n if (typeof id !== 'string' || id.length === 0) {\n error(errors, `${path}/id`, 'INVALID_TOOL_USE_ID', 'tool_use.id must be a non-empty string.');\n }\n if (typeof name !== 'string' || name.length === 0) {\n error(errors, `${path}/name`, 'INVALID_TOOL_NAME', 'tool_use.name must be a non-empty string.');\n }\n if (!isPlainJsonObject(input)) {\n error(errors, `${path}/input`, 'INVALID_TOOL_INPUT', 'tool_use.input must be an object.');\n }\n const providerMeta = validateProviderMeta(value['providerMeta'], `${path}/providerMeta`, errors);\n if (typeof id !== 'string' || id.length === 0 || typeof name !== 'string' || name.length === 0 || !isPlainJsonObject(input)) {\n return undefined;\n }\n return providerMeta === undefined\n ? { type: 'tool_use', id, name, input }\n : { type: 'tool_use', id, name, input, providerMeta };\n }\n case 'tool_result': {\n const toolUseId = value['tool_use_id'];\n const name = value['name'];\n const content = value['content'];\n const isError = value['is_error'];\n if (typeof toolUseId !== 'string' || toolUseId.length === 0) {\n error(errors, `${path}/tool_use_id`, 'INVALID_TOOL_RESULT_ID', 'tool_result.tool_use_id must be a non-empty string.');\n }\n if (name !== undefined && typeof name !== 'string') {\n error(errors, `${path}/name`, 'INVALID_TOOL_RESULT_NAME', 'tool_result.name must be a string.');\n }\n if (typeof content !== 'string') {\n error(errors, `${path}/content`, 'INVALID_TOOL_RESULT_CONTENT', 'tool_result.content must be a string.');\n } else if (content.length > MAX_STRING_LENGTH) {\n error(errors, `${path}/content`, 'TOOL_RESULT_TOO_LARGE', 'tool_result.content is too large.');\n }\n if (isError !== undefined && typeof isError !== 'boolean') {\n error(errors, `${path}/is_error`, 'INVALID_TOOL_RESULT_ERROR', 'tool_result.is_error must be boolean.');\n }\n if (typeof toolUseId !== 'string' || toolUseId.length === 0 || typeof content !== 'string') return undefined;\n return {\n type: 'tool_result',\n tool_use_id: toolUseId,\n content,\n ...(typeof name === 'string' ? { name } : {}),\n ...(typeof isError === 'boolean' ? { is_error: isError } : {}),\n };\n }\n case 'image': {\n const source = value['source'];\n if (!isRecord(source)) {\n error(errors, `${path}/source`, 'INVALID_IMAGE_SOURCE', 'image.source must be an object.');\n return undefined;\n }\n const sourceType = source['type'];\n if (sourceType !== 'base64' && sourceType !== 'url') {\n error(errors, `${path}/source/type`, 'INVALID_IMAGE_SOURCE_TYPE', 'image.source.type must be base64 or url.');\n return undefined;\n }\n const mediaType = source['media_type'];\n const data = source['data'];\n const url = source['url'];\n if (mediaType !== undefined && typeof mediaType !== 'string') {\n error(errors, `${path}/source/media_type`, 'INVALID_IMAGE_MEDIA_TYPE', 'image.source.media_type must be a string.');\n }\n if (data !== undefined && typeof data !== 'string') {\n error(errors, `${path}/source/data`, 'INVALID_IMAGE_DATA', 'image.source.data must be a string.');\n }\n if (url !== undefined && typeof url !== 'string') {\n error(errors, `${path}/source/url`, 'INVALID_IMAGE_URL', 'image.source.url must be a string.');\n }\n return {\n type: 'image',\n source: {\n type: sourceType,\n ...(typeof mediaType === 'string' ? { media_type: mediaType } : {}),\n ...(typeof data === 'string' ? { data } : {}),\n ...(typeof url === 'string' ? { url } : {}),\n },\n };\n }\n case 'thinking': {\n const thinking = value['thinking'];\n const signature = value['signature'];\n if (typeof thinking !== 'string') {\n error(errors, `${path}/thinking`, 'INVALID_THINKING', 'thinking.thinking must be a string.');\n return undefined;\n }\n if (signature !== undefined && typeof signature !== 'string') {\n error(errors, `${path}/signature`, 'INVALID_THINKING_SIGNATURE', 'thinking.signature must be a string.');\n }\n const providerMeta = validateProviderMeta(value['providerMeta'], `${path}/providerMeta`, errors);\n return {\n type: 'thinking',\n thinking,\n ...(typeof signature === 'string' ? { signature } : {}),\n ...(providerMeta === undefined ? {} : { providerMeta }),\n };\n }\n default:\n error(errors, `${path}/type`, 'UNKNOWN_BLOCK_TYPE', `Unknown content block type: ${String(type)}`);\n return undefined;\n }\n}\n\nexport function validateContextEditorMessages(\n value: unknown,\n currentMessageCount = 0,\n): { messages: Message[]; errors: ContextEditorValidationError[] } {\n const errors: ContextEditorValidationError[] = [];\n const messages: Message[] = [];\n if (!Array.isArray(value)) {\n error(errors, '/messages', 'INVALID_MESSAGES', 'messages must be an array.');\n return { messages, errors };\n }\n if (value.length > currentMessageCount + MAX_MESSAGE_COUNT_GROWTH) {\n error(errors, '/messages', 'TOO_MANY_MESSAGES', 'Context editor is deletion-oriented; proposed message count grew too much.');\n }\n if (jsonByteLength(value) > MAX_PAYLOAD_BYTES) {\n error(errors, '/messages', 'PAYLOAD_TOO_LARGE', 'Context editor payload is too large.');\n }\n value.forEach((item, index) => {\n const path = `/messages/${index}`;\n if (!isRecord(item)) {\n error(errors, path, 'INVALID_MESSAGE', 'Message must be an object.');\n return;\n }\n const role = item['role'];\n if (!isMessageRole(role)) {\n error(errors, `${path}/role`, 'INVALID_ROLE', 'Message role must be user, assistant, or system.');\n return;\n }\n const rawContent = item['content'];\n let content: Message['content'] | undefined;\n if (typeof rawContent === 'string') {\n if (rawContent.length > MAX_STRING_LENGTH) {\n error(errors, `${path}/content`, 'CONTENT_TOO_LARGE', 'Message content is too large.');\n return;\n }\n content = rawContent;\n } else if (Array.isArray(rawContent)) {\n const blocks: ContentBlock[] = [];\n rawContent.forEach((block, blockIndex) => {\n const parsed = validateBlock(block, `${path}/content/${blockIndex}`, errors);\n if (parsed) blocks.push(parsed);\n });\n content = blocks;\n } else {\n error(errors, `${path}/content`, 'INVALID_CONTENT', 'Message content must be a string or content block array.');\n return;\n }\n const ts = item['ts'];\n if (ts !== undefined) {\n if (typeof ts !== 'string' || Number.isNaN(Date.parse(ts))) {\n error(errors, `${path}/ts`, 'INVALID_TIMESTAMP', 'Message ts must be an ISO-like timestamp string.');\n return;\n }\n }\n messages.push({ role, content, ...(typeof ts === 'string' ? { ts } : {}) });\n });\n return { messages, errors };\n}\n\nfunction countBlocks(messages: readonly Message[]): number {\n let total = 0;\n for (const message of messages) total += Array.isArray(message.content) ? message.content.length : 1;\n return total;\n}\n\nfunction toolDiagnostics(messages: readonly Message[]): ContextEditorDiagnostics {\n const repair = repairToolUseAdjacency([...messages]);\n let thinkingBlocks = 0;\n let signedThinkingBlocks = 0;\n for (const message of messages) {\n if (!Array.isArray(message.content)) continue;\n for (const block of message.content) {\n if (block.type !== 'thinking') continue;\n thinkingBlocks++;\n if (block.signature) signedThinkingBlocks++;\n }\n }\n return {\n hasToolAdjacencyIssues: repair.report.changed,\n orphanToolUses: repair.report.removedToolUses,\n orphanToolResults: repair.report.removedToolResults,\n emptyMessages: repair.report.removedMessages,\n thinkingBlocks,\n signedThinkingBlocks,\n };\n}\n\nfunction warningsForMessage(message: Message, index: number): ContextEditorWarning[] {\n const warnings: ContextEditorWarning[] = [];\n if (!Array.isArray(message.content)) return warnings;\n message.content.forEach((block, blockIndex) => {\n if (block.type === 'thinking' && block.signature) {\n warnings.push({\n path: `/messages/${index}/content/${blockIndex}`,\n code: 'SIGNED_THINKING_PRESENT',\n severity: 'warning',\n message: 'This block contains provider replay metadata and should only be removed with the whole turn if no longer needed.',\n });\n }\n if (block.type === 'tool_result' && block.content.length > 20_000) {\n warnings.push({\n path: `/messages/${index}/content/${blockIndex}`,\n code: 'LARGE_TOOL_RESULT',\n severity: 'info',\n message: 'Large tool result; inspect before removing.',\n });\n }\n });\n return warnings;\n}\n\nfunction collectWarnings(messages: readonly Message[]): ContextEditorWarning[] {\n return messages.flatMap((message, index) => warningsForMessage(message, index));\n}\n\nfunction metricFor(ctx: Context, messages: readonly Message[], tools: ReturnType<ToolRegistry['list']> | undefined): ContextEditorMetrics {\n const breakdown = estimateContextBreakdown({\n systemPrompt: ctx.systemPrompt,\n tools: tools ?? ctx.tools ?? [],\n messages,\n });\n return {\n messages: messages.length,\n blocks: countBlocks(messages),\n messageTokens: breakdown.messages.total,\n fullRequestTokens: breakdown.total,\n };\n}\n\nexport function buildContextEditorSnapshot(ctx: Context, tools: ReturnType<ToolRegistry['list']> | undefined): ContextEditorSnapshot {\n const messages = ctx.messages.map((message): ContextEditorMessage => ({\n role: message.role,\n content: message.content,\n ...(message.ts ? { ts: message.ts } : {}),\n }));\n const breakdown = estimateContextBreakdown({\n systemPrompt: ctx.systemPrompt,\n tools: tools ?? ctx.tools ?? [],\n messages: ctx.messages,\n });\n return {\n revision: contextEditorRevision(ctx.messages),\n messages,\n readonlyContext: {\n systemPromptTokens: breakdown.systemPrompt,\n toolSchemaTokens: breakdown.tools.total,\n toolCount: breakdown.tools.count,\n totalTokens: breakdown.total,\n messageTokens: breakdown.messages.total,\n },\n messageBreakdown: ctx.messages.map((message, index) => ({\n index,\n role: message.role,\n tokens: messageTokens(message.content),\n preview: breakdown.messages.breakdown[index]?.preview ?? '',\n blockCount: Array.isArray(message.content) ? message.content.length : null,\n warnings: warningsForMessage(message, index),\n })),\n diagnostics: toolDiagnostics(ctx.messages),\n };\n}\n\nexport function validateContextEditorProposal(input: {\n ctx: Context;\n tools?: ReturnType<ToolRegistry['list']> | undefined;\n baseRevision: string;\n messages: unknown;\n allowRepair: boolean;\n runActive?: boolean | undefined;\n}): ContextEditorValidationResult {\n const currentRevision = contextEditorRevision(input.ctx.messages);\n const before = metricFor(input.ctx, input.ctx.messages, input.tools);\n const emptyRepair: ContextEditorRepairPreview = {\n changed: false,\n removedToolUses: [],\n removedToolResults: [],\n removedMessages: 0,\n };\n if (input.runActive) {\n return {\n ok: false,\n baseRevision: input.baseRevision,\n currentRevision,\n before,\n validationErrors: [],\n warnings: [],\n repair: emptyRepair,\n conflict: { code: 'RUN_ACTIVE', message: 'The agent is currently running. Abort or wait before applying context edits.' },\n };\n }\n if (input.baseRevision !== currentRevision) {\n return {\n ok: false,\n baseRevision: input.baseRevision,\n currentRevision,\n before,\n validationErrors: [],\n warnings: [],\n repair: emptyRepair,\n conflict: { code: 'CONTEXT_REVISION_CONFLICT', message: 'Context changed while the editor was open. Reload before applying.' },\n };\n }\n const parsed = validateContextEditorMessages(input.messages, input.ctx.messages.length);\n if (parsed.errors.length > 0) {\n return {\n ok: false,\n baseRevision: input.baseRevision,\n currentRevision,\n before,\n validationErrors: parsed.errors,\n warnings: [],\n repair: emptyRepair,\n };\n }\n const repaired = repairToolUseAdjacency(parsed.messages);\n const repair: ContextEditorRepairPreview = {\n changed: repaired.report.changed,\n removedToolUses: repaired.report.removedToolUses,\n removedToolResults: repaired.report.removedToolResults,\n removedMessages: repaired.report.removedMessages,\n };\n const finalMessages = repaired.messages;\n const warnings = collectWarnings(finalMessages);\n const after = metricFor(input.ctx, finalMessages, input.tools);\n if (repaired.report.changed && !input.allowRepair) {\n return {\n ok: false,\n baseRevision: input.baseRevision,\n currentRevision,\n before,\n after,\n validationErrors: [],\n warnings,\n repair,\n };\n }\n return {\n ok: true,\n baseRevision: input.baseRevision,\n currentRevision,\n before,\n after,\n validationErrors: [],\n warnings,\n repair,\n messages: finalMessages,\n };\n}\n\nexport async function applyContextEditorProposal(input: {\n ctx: Context;\n tools?: ReturnType<ToolRegistry['list']> | undefined;\n baseRevision: string;\n messages: unknown;\n allowRepair: boolean;\n runActive?: boolean | undefined;\n}): Promise<ContextEditorValidationResult | ContextEditorAppliedResult> {\n const validation = validateContextEditorProposal(input);\n if (!validation.ok || !validation.messages || !validation.after) return validation;\n const previousRevision = validation.currentRevision;\n const beforeMessages = input.ctx.messages.length;\n const beforeBlocks = countBlocks(input.ctx.messages);\n input.ctx.state.replaceMessages(validation.messages);\n await input.ctx.flushConversationJournal?.();\n input.ctx.lastRequestTokens = undefined;\n input.ctx.lastRealInputTokens = undefined;\n input.ctx.state.deleteMeta?.('lastRequestTokensAt');\n input.ctx.state.deleteMeta?.('realAnchorMsgCount');\n input.ctx.readFiles.clear();\n input.ctx.fileMtimes.clear();\n const revision = contextEditorRevision(input.ctx.messages);\n const after = metricFor(input.ctx, input.ctx.messages, input.tools);\n const afterBlocks = countBlocks(input.ctx.messages);\n return {\n previousRevision,\n revision,\n before: validation.before,\n after,\n removed: {\n messages: Math.max(0, beforeMessages - input.ctx.messages.length),\n blocks: Math.max(0, beforeBlocks - afterBlocks),\n toolUses: validation.repair.removedToolUses,\n toolResults: validation.repair.removedToolResults,\n emptyMessages: validation.repair.removedMessages,\n },\n warnings: validation.warnings,\n };\n}\n", "/**\n * Per-section context-window token estimate for the `context.debug` command.\n *\n * Uses the simple 4-chars-per-token heuristic \u2014 not exact, but close enough to\n * spot which section (system prompt, tool schemas, or message history) is\n * eating the context window. Tool schemas in particular are easy to overlook:\n * each tool ships its full JSON schema to the model every turn, so 20+ builtins\n * can cost 10-20k tokens on their own.\n *\n * Extracted from `index.ts` as a pure function so the breakdown maths can be\n * unit tested without standing up a Context/ToolRegistry.\n */\n\n/** 4-chars-per-token heuristic estimate for a string. */\nexport function estimateTokens(s: string): number {\n return Math.ceil(s.length / 4);\n}\n\n/** Stringify arbitrary content for length estimation (JSON, with fallbacks). */\nexport function stringifyContent(c: unknown): string {\n if (typeof c === 'string') return c;\n try {\n return JSON.stringify(c);\n } catch {\n return String(c);\n }\n}\n\ninterface PromptBlock {\n text?: string | undefined;\n}\ninterface ToolLike {\n name: string;\n inputSchema?: unknown | undefined;\n description?: string | undefined;\n}\ninterface ContentBlock {\n type?: string | undefined;\n text?: string | undefined;\n input?: unknown | undefined;\n content?: unknown | undefined;\n name?: string | undefined;\n}\ninterface MessageLike {\n role: string;\n content: unknown;\n}\n\nexport interface ToolTokenEntry {\n name: string;\n tokens: number;\n}\nexport interface MessageTokenEntry {\n index: number;\n role: string;\n tokens: number;\n preview: string;\n}\n\nexport interface ContextBreakdown {\n total: number;\n systemPrompt: number;\n tools: { total: number; count: number; breakdown: ToolTokenEntry[] };\n messages: { total: number; count: number; breakdown: MessageTokenEntry[] };\n}\n\nexport function messageTokens(content: unknown): number {\n if (typeof content === 'string') return estimateTokens(content);\n if (!Array.isArray(content)) return 0;\n let tk = 0;\n for (const b of content as ContentBlock[]) {\n if (b.type === 'text') tk += estimateTokens(b.text ?? '');\n else if (b.type === 'tool_use') tk += estimateTokens(stringifyContent(b.input));\n else if (b.type === 'tool_result') tk += estimateTokens(stringifyContent(b.content));\n else tk += estimateTokens(stringifyContent(b));\n }\n return tk;\n}\n\nexport function messagePreview(content: unknown): string {\n if (typeof content === 'string') return content.slice(0, 60);\n if (!Array.isArray(content)) return '';\n return (content as ContentBlock[])\n .map((b) =>\n b.type === 'text'\n ? (b.text ?? '').slice(0, 40)\n : b.type === 'tool_use'\n ? `[tool_use: ${b.name}]`\n : b.type === 'tool_result'\n ? '[tool_result]'\n : `[${b.type}]`,\n )\n .join(' ')\n .slice(0, 60);\n}\n\n/**\n * Compute the per-section token breakdown for the active context. Mirrors the\n * shape the `context.debug` WS reply expects (minus the `mode`/`policy` fields,\n * which the caller layers on from `context.meta`).\n */\nexport function estimateContextBreakdown(input: {\n systemPrompt: ReadonlyArray<PromptBlock>;\n tools: ReadonlyArray<ToolLike>;\n messages: ReadonlyArray<MessageLike>;\n}): ContextBreakdown {\n const sysTokens = input.systemPrompt.reduce((acc, b) => acc + estimateTokens(b.text ?? ''), 0);\n\n const toolBreakdown: ToolTokenEntry[] = input.tools.map((t) => {\n const schema = t.inputSchema ?? {};\n const desc = t.description ?? '';\n return {\n name: t.name,\n tokens:\n estimateTokens(t.name) + estimateTokens(desc) + estimateTokens(stringifyContent(schema)),\n };\n });\n const toolTokens = toolBreakdown.reduce((a, b) => a + b.tokens, 0);\n\n const messageBreakdown: MessageTokenEntry[] = input.messages.map((m, i) => ({\n index: i,\n role: m.role,\n tokens: messageTokens(m.content),\n preview: messagePreview(m.content),\n }));\n const msgTokens = messageBreakdown.reduce((a, b) => a + b.tokens, 0);\n\n return {\n total: sysTokens + toolTokens + msgTokens,\n systemPrompt: sysTokens,\n tools: { total: toolTokens, count: input.tools.length, breakdown: toolBreakdown },\n messages: { total: msgTokens, count: input.messages.length, breakdown: messageBreakdown },\n };\n}\n", "import type { WebSocket } from 'ws';\nimport type { PendingConfirm } from './pending-confirms.js';\nimport { resolveAllPendingConfirms } from './pending-confirms.js';\n\ntype OutboundMessage = { type: string; payload: unknown };\ntype ProtocolIssue = { code: string; message: string };\ntype DecodeResult<Message> = { ok: true; message: Message } | { ok: false; issue: ProtocolIssue };\n\n/**\n * Payload delivered to the `onSecurityRejection` callback when the decoder\n * trips a security-relevant issue code (`unsafe_key` or `too_deep`).\n */\nexport interface SecurityRejectionEvent {\n /** Decoder issue code that triggered the alert. */\n issueCode: string;\n /** Human-readable issue message from the decoder. */\n issueMessage: string;\n /** Event name logged alongside this rejection. */\n eventName: string;\n /** Per-connection id \u2014 `undefined` when the client lacks this field. */\n connectionId?: string;\n /** Session id bound to this connection \u2014 `null` when the client has none. */\n sessionId?: string | null;\n /** Agent id from the server-wide client context. */\n agentId?: string;\n /** Project root from the server-wide client context. */\n projectRoot?: string;\n}\n\n/**\n * Minimum shape a client must expose for verbose logging to attach\n * per-connection identity to rejection logs. The connection lifecycle\n * reads these fields defensively (`?.connId`, `?.sessionId`), so any\n * subset is fine \u2014 but consumers should declare the shape on their\n * `Client` type to make the contract explicit and avoid silent drops\n * when fields are renamed.\n */\nexport interface ClientWithConnectionInfo {\n /** Unique per-connection id \u2014 defaults to `undefined` when absent. */\n connId?: string;\n /** Session id bound to this connection \u2014 may be `null` when not yet known. */\n sessionId?: string | null;\n /** Remote socket address captured when the connection is accepted. */\n remoteAddress?: string;\n}\n\nexport interface ConnectionLifecycleOptions<Client, Request, Message> {\n clients: Map<WebSocket, Client>;\n pendingConfirms: Map<string, PendingConfirm>;\n authenticate?: (ws: WebSocket, request: Request) => boolean | Promise<boolean>;\n createClient: (ws: WebSocket, connectionId: string) => Client;\n registerClient: (ws: WebSocket) => void;\n unregisterClient?: (ws: WebSocket) => void;\n onClose?: (ws: WebSocket, client: Client | undefined) => void;\n decode: (raw: string) => DecodeResult<Message>;\n dispatch: (ws: WebSocket, client: Client, message: Message) => Promise<void>;\n send: (ws: WebSocket, message: OutboundMessage) => void;\n sessionPayload: (payload: Record<string, unknown>) => Record<string, unknown>;\n buildInitialPayload: () => Promise<Record<string, unknown>>;\n rateLimitMax?: number;\n rateLimitWindowMs?: number;\n confirmDrainGraceMs?: number;\n rateLimitMessage?: string;\n /**\n * Enrich rejection/parse-failure logs with per-connection context so the\n * server can identify the sender of unknown client message types. When\n * false (default), the original `{ level, event, message }` shape is\n * preserved for back-compat with downstream log consumers.\n */\n verboseWsLogging?: boolean;\n /**\n * Connection-level context attached to verbose rejection logs. Note that\n * per-connection identity (`connectionId`, `sessionId`) is sourced from the\n * `client` argument of `logRejection` directly, so it does not need to be\n * duplicated here.\n */\n clientContext?: {\n agentId?: string;\n projectRoot?: string;\n };\n /**\n * Optional consumer-supplied log sink. Honored by every error-emitting\n * branch (`webui_server.client_socket_error`, `message_handler_failed`,\n * `session_start_payload_failed`, and the verbose rejection path under\n * `verboseWsLogging`). The `error` argument is typed `unknown` and is the\n * standard Error / string for the three standard branches, while the\n * verbose rejection branch passes the enriched structured payload object\n * (with `connectionId`, `sessionId`, `agentId`, `code`, `type`, etc.) so\n * downstream sinks can index/filter on the extra fields.\n */\n log?: (level: 'warn' | 'error', event: string, error: unknown) => void;\n /**\n * Called when the decoder reports a security-tripwire issue code\n * (`unsafe_key` or `too_deep`). The caller (typically `start-webui.ts`\n * via the connection handler) can use this to send a `to:'*' audience:'leaders'`\n * mailbox message so the running agent-loop is notified immediately of\n * possible exploit attempts or runaway payloads.\n *\n * The callback is fire-and-forget from the lifecycle's perspective: it is\n * invoked with bare `void` (no await) so a slow or throwing consumer never\n * delays the message handler. Wrap any async work in a promise that is\n * intentionally not awaited.\n */\n onSecurityRejection?: ((event: SecurityRejectionEvent) => void) | undefined;\n}\n\n/**\n * Canonical WebSocket lifecycle: protection, auth, registration, protocol\n * decode, rate limiting, initial replay, and disconnect cleanup.\n */\nexport function createConnectionLifecycle<Client, Request, Message>(\n options: ConnectionLifecycleOptions<Client, Request, Message>,\n): (ws: WebSocket, request: Request) => Promise<void> {\n const rateLimitMax = options.rateLimitMax ?? 0;\n const rateLimitWindowMs = options.rateLimitWindowMs ?? 60_000;\n const confirmDrainGraceMs = options.confirmDrainGraceMs ?? 30_000;\n let connectionSequence = 0;\n let confirmDrainTimer: ReturnType<typeof setTimeout> | null = null;\n\n const log = (level: 'warn' | 'error', event: string, error: unknown): void => {\n if (options.log) {\n options.log(level, event, error);\n return;\n }\n const output = JSON.stringify({\n level,\n event,\n message: error instanceof Error ? error.message : String(error),\n timestamp: new Date().toISOString(),\n });\n if (level === 'warn') console.warn(output);\n else console.error(output);\n };\n\n /**\n * Verbose variant of `log` used for the rejection/parse-failure path only.\n * Adds per-connection context and the decoder issue's code/type when\n * available. Falls back to the standard `log` shape when `verboseWsLogging`\n * is off or no client context has been bound yet.\n */\n const logRejection = (\n level: 'warn' | 'error',\n event: string,\n issueMessage: string,\n issueCode: string | undefined,\n issuePath: string | undefined,\n client: ClientWithConnectionInfo | undefined,\n ): void => {\n if (!options.verboseWsLogging) {\n log(level, event, issueMessage);\n return;\n }\n // The decoder's `unknown_type` issue message has the shape\n // `Unknown <direction> message: <type>`; re-parse the type suffix so\n // log consumers can filter on `type` without parsing the human string.\n let rejectedType: string | undefined;\n if (issueCode === 'unknown_type') {\n const match = /Unknown\\s+\\S+\\s+message:\\s+(\\S+)/.exec(issueMessage);\n if (match?.[1]) rejectedType = match[1];\n }\n const payload: Record<string, unknown> = {\n level,\n event,\n message: issueMessage,\n timestamp: new Date().toISOString(),\n };\n if (client?.connId) payload['connectionId'] = client.connId;\n if (client?.sessionId) payload['sessionId'] = client.sessionId;\n if (options.clientContext?.agentId) payload['agentId'] = options.clientContext.agentId;\n if (options.clientContext?.projectRoot)\n payload['projectRoot'] = options.clientContext.projectRoot;\n if (client?.remoteAddress) payload['remoteAddress'] = client.remoteAddress;\n if (issueCode) payload['code'] = issueCode;\n if (issuePath) payload['path'] = issuePath;\n if (rejectedType) payload['type'] = rejectedType;\n if (options.log) {\n // Route the enriched structured payload through the consumer-supplied\n // logger so callers that wire a custom sink (e.g. a log aggregator) do\n // not lose verbose rejection entries. The `error` argument is already\n // typed `unknown` on the option contract \u2014 this is the one site where\n // we pass an object instead of an Error/string, which is the whole\n // reason verbose mode exists.\n options.log(level, event, payload);\n return;\n }\n const line = JSON.stringify(payload);\n if (level === 'warn') console.warn(line);\n else console.error(line);\n };\n\n return async (ws, request) => {\n ws.on('error', (error) => log('warn', 'webui_server.client_socket_error', error));\n if (options.authenticate && !(await options.authenticate(ws, request))) return;\n\n const client = options.createClient(ws, `c${++connectionSequence}`);\n options.clients.set(ws, client);\n options.registerClient(ws);\n\n if (confirmDrainTimer) {\n clearTimeout(confirmDrainTimer);\n confirmDrainTimer = null;\n }\n for (const confirm of options.pendingConfirms.values()) {\n if (confirm.payload) {\n options.send(ws, { type: 'tool.confirm_needed', payload: confirm.payload });\n }\n }\n\n let messageCount = 0;\n let rateWindowResetAt = Date.now() + rateLimitWindowMs;\n ws.on('message', async (data) => {\n if (rateLimitMax > 0) {\n const now = Date.now();\n if (now > rateWindowResetAt) {\n messageCount = 0;\n rateWindowResetAt = now + rateLimitWindowMs;\n }\n if (++messageCount > rateLimitMax) {\n options.send(ws, {\n type: 'error',\n payload: options.sessionPayload({\n phase: 'rate_limit',\n message: options.rateLimitMessage ?? 'Too many messages. Please wait.',\n }),\n });\n return;\n }\n }\n\n const decoded = options.decode(data.toString());\n if (!decoded.ok) {\n const eventName =\n decoded.issue.message === 'Protocol frame is not valid JSON'\n ? 'webui_server.message_parse_failed'\n : 'webui_server.message_rejected';\n // Severity policy for rejected frames:\n // - `unknown_type` / `invalid_envelope` / `invalid_type` \u2192 warn.\n // The frame parsed; the server is healthy. The client is sending\n // a type the server does not know (stale bundle, deprecated type,\n // extra payload). Not actionable on the server side without a\n // client deploy \u2014 flooding the error channel with this kind of\n // noise crowds out real server faults.\n // - `unsafe_key` / `too_deep` \u2192 error. The decoder's prototype-\n // pollution guard (`unsafe_key`) and the depth-limit guard\n // (`too_deep`) are tripwires for hostile or runaway payloads.\n // Either an exploit attempt or a buggy client must surface so an\n // operator can investigate.\n // The parse-failed branch (`message_parse_failed`) follows the same\n // policy via `code` because the decoder tags it `invalid_envelope`.\n const level: 'warn' | 'error' =\n decoded.issue.code === 'unsafe_key' || decoded.issue.code === 'too_deep'\n ? 'error'\n : 'warn';\n // Fire the optional security-rejection callback. This is intentionally\n // fire-and-forget (bare `void`, no `await`) so a slow or throwing\n // consumer never delays the message handler.\n if (\n level === 'error' &&\n options.onSecurityRejection &&\n (decoded.issue.code === 'unsafe_key' || decoded.issue.code === 'too_deep')\n ) {\n const c = client as unknown as ClientWithConnectionInfo | undefined;\n void options.onSecurityRejection({\n issueCode: decoded.issue.code,\n issueMessage: decoded.issue.message,\n eventName,\n ...(c?.connId ? { connectionId: c.connId } : {}),\n ...(c?.sessionId != null ? { sessionId: c.sessionId } : {}),\n ...(options.clientContext?.agentId ? { agentId: options.clientContext.agentId } : {}),\n ...(options.clientContext?.projectRoot\n ? { projectRoot: options.clientContext.projectRoot }\n : {}),\n } as SecurityRejectionEvent);\n }\n logRejection(\n level,\n eventName,\n decoded.issue.message,\n decoded.issue.code,\n (decoded.issue as { path?: string }).path,\n // `client` is typed as the generic `Client`; widen to the\n // connection-info shape defensively. Consumers that declare\n // `Client extends ClientWithConnectionInfo` skip the cast entirely\n // because the structural assignability is already satisfied.\n client as unknown as ClientWithConnectionInfo,\n );\n options.send(ws, {\n type: 'error',\n payload: options.sessionPayload({\n phase: 'parse',\n code: decoded.issue.code,\n message: decoded.issue.message,\n }),\n });\n return;\n }\n try {\n await options.dispatch(ws, client, decoded.message);\n } catch (error) {\n log('error', 'webui_server.message_handler_failed', error);\n }\n });\n\n ws.on('close', () => {\n const closing = options.clients.get(ws);\n options.clients.delete(ws);\n options.unregisterClient?.(ws);\n options.onClose?.(ws, closing);\n if (options.clients.size === 0 && options.pendingConfirms.size > 0 && !confirmDrainTimer) {\n confirmDrainTimer = setTimeout(() => {\n confirmDrainTimer = null;\n if (options.clients.size === 0) {\n resolveAllPendingConfirms(options.pendingConfirms, 'no');\n }\n }, confirmDrainGraceMs);\n confirmDrainTimer.unref?.();\n }\n });\n\n try {\n options.send(ws, { type: 'session.start', payload: await options.buildInitialPayload() });\n } catch (error) {\n log('warn', 'webui.session_start_payload_failed', error);\n }\n };\n}\n", "import {\n ChronicleProjectServerClient,\n createChronicleProjectAccess,\n resolveChronicleProjectServerOptions,\n} from '@wrongstack/core/chronicle';\nimport {\n isMailboxProjectServerAvailable,\n MailboxProjectServerConnection,\n} from '@wrongstack/core/coordination';\nimport { resolveWstackPaths } from '@wrongstack/core/utils';\nimport { getKanbanServerConnection } from '@wrongstack/kanban';\nimport { isSageProjectServerAvailable, SageProjectServerConnection } from '@wrongstack/sage';\nimport {\n checkCodebaseIndexServerHealth,\n getIndexState,\n resolveProjectIndexDaemonAvailability,\n shutdownCodebaseIndexServer,\n} from '@wrongstack/tools';\nimport type { WebSocket } from 'ws';\nimport type { WSClientMessage, WSServerMessage } from './types.js';\n\nexport type ConnectionHealthStatus = 'healthy' | 'degraded' | 'offline' | 'unavailable' | 'error';\n\nexport interface ConnectionHealthService {\n id: 'webui' | 'chronicle' | 'codebase-index' | 'sage' | 'kanban' | 'mailbox';\n label: string;\n status: ConnectionHealthStatus;\n required: boolean;\n mode: string;\n detail: string;\n ownerPid?: number | undefined;\n endpoint?: string | undefined;\n storage?: string | undefined;\n uptimeMs?: number | undefined;\n latencyMs?: number | undefined;\n clients?: number | undefined;\n activeRequests?: number | undefined;\n queuedWork?: number | undefined;\n watcher?: { active: boolean; watchedFiles?: number | undefined } | undefined;\n lastError?: string | undefined;\n}\n\nexport interface ConnectionsHealthReport {\n checkedAt: number;\n overall: 'healthy' | 'degraded' | 'error';\n backend: 'standalone' | 'cli-embedded';\n projectRoot: string;\n services: ConnectionHealthService[];\n}\n\nexport interface ConnectionsHealthContext {\n getProjectRoot(): string;\n getIndexDir(): string | undefined;\n send(ws: WebSocket, message: WSServerMessage): void;\n backend: ConnectionsHealthReport['backend'];\n collect?: (() => Promise<ConnectionsHealthReport>) | undefined;\n}\n\n/** One read-only health report for every per-project backend connection. */\nexport async function handleConnectionsHealthRoute(\n context: ConnectionsHealthContext,\n ws: WebSocket,\n message: WSClientMessage,\n): Promise<boolean> {\n if (message.type !== 'connections.health') return false;\n try {\n const report =\n (await context.collect?.()) ??\n (await collectConnectionsHealth({\n projectRoot: context.getProjectRoot(),\n indexDir: context.getIndexDir(),\n backend: context.backend,\n }));\n context.send(ws, { type: 'connections.health_result', payload: report });\n } catch (error) {\n context.send(ws, {\n type: 'connections.health_error',\n payload: { message: error instanceof Error ? error.message : String(error) },\n });\n }\n return true;\n}\n\nexport async function collectConnectionsHealth(options: {\n projectRoot: string;\n indexDir?: string | undefined;\n backend: ConnectionsHealthReport['backend'];\n}): Promise<ConnectionsHealthReport> {\n const services = await Promise.all([\n Promise.resolve(webuiHealth(options.backend)),\n chronicleHealth(options.projectRoot),\n codebaseIndexHealth(options.projectRoot, options.indexDir),\n sageHealth(options.projectRoot),\n kanbanHealth(options.projectRoot),\n mailboxHealth(options.projectRoot),\n ]);\n const required = services.filter((service) => service.required);\n const overall = required.some((service) => service.status === 'error')\n ? 'error'\n : required.some((service) => service.status !== 'healthy')\n ? 'degraded'\n : 'healthy';\n return {\n checkedAt: Date.now(),\n overall,\n backend: options.backend,\n projectRoot: options.projectRoot,\n services,\n };\n}\n\nfunction webuiHealth(backend: ConnectionsHealthReport['backend']): ConnectionHealthService {\n return {\n id: 'webui',\n label: 'WebUI transport',\n status: 'healthy',\n required: true,\n mode: backend,\n detail: 'This browser is connected to the WebUI WebSocket backend.',\n ownerPid: process.pid,\n };\n}\n\nasync function chronicleHealth(projectRoot: string): Promise<ConnectionHealthService> {\n const startedAt = Date.now();\n let access: ReturnType<typeof createChronicleProjectAccess> | undefined;\n try {\n access = createChronicleProjectAccess({ projectRoot });\n const health = await access.call('ping', {}, { timeoutMs: 5_000 });\n const quarantined = health.quarantinedFamilies ?? [];\n return {\n id: 'chronicle',\n label: 'Chronicle telemetry',\n status:\n quarantined.length > 0 ? 'degraded' : access.mode === 'server' ? 'healthy' : 'degraded',\n required: true,\n mode: access.mode,\n detail:\n quarantined.length > 0\n ? `Serving, but ${quarantined.length} day(s) were quarantined for a broken chain: ${quarantined\n .map((family) => family.day)\n .join(', ')}.`\n : access.mode === 'server'\n ? 'One project owner collects, processes, stores, and serves telemetry.'\n : 'Inline fallback is active; ownership is not shared across clients.',\n ownerPid: health.pid,\n endpoint: health.endpoint,\n storage: health.chronicleDirectory,\n uptimeMs: health.uptimeMs,\n latencyMs: Date.now() - startedAt,\n clients: health.clients,\n activeRequests: health.activeRequests,\n queuedWork: health.journal.pendingEvents,\n watcher: {\n active: health.watcher.active,\n watchedFiles: health.watcher.watchedFiles,\n },\n ...(quarantined[0]\n ? { lastError: quarantined[0].reason }\n : health.watcher.lastError\n ? { lastError: health.watcher.lastError }\n : {}),\n };\n } catch (error) {\n return failureService(\n 'chronicle',\n 'Chronicle telemetry',\n true,\n access?.mode ?? 'unavailable',\n error,\n Date.now() - startedAt,\n );\n } finally {\n await access?.close();\n }\n}\n\nasync function codebaseIndexHealth(\n projectRoot: string,\n indexDir?: string,\n): Promise<ConnectionHealthService> {\n const startedAt = Date.now();\n const availability = resolveProjectIndexDaemonAvailability(projectRoot, indexDir);\n if (availability.kind === 'endpoint-invalid') {\n return {\n id: 'codebase-index',\n label: 'Codebase index',\n status: 'unavailable',\n required: false,\n mode: 'endpoint-invalid',\n detail:\n `Socket path is ${availability.byteLength} bytes \u2014 over this platform's ` +\n `${availability.maxBytes}-byte sun_path limit. Queries fall back to a process-local ` +\n `index. Set a shorter TMPDIR to restore the shared daemon.`,\n endpoint: availability.endpoint,\n latencyMs: Date.now() - startedAt,\n };\n }\n try {\n const health = await checkCodebaseIndexServerHealth(projectRoot, indexDir, {\n timeoutMs: 2_000,\n });\n const connection = getIndexState().server;\n return {\n id: 'codebase-index',\n label: 'Codebase index',\n status: health.status === 'unresponsive' ? 'error' : health.status,\n required: false,\n mode: 'project-server',\n detail: health.server?.activity.indexing\n ? `Indexing ${health.server.activity.currentFile}/${health.server.activity.totalFiles}.`\n : 'Shared symbol index is ready for project queries.',\n ownerPid: connection.pid,\n endpoint: connection.endpoint,\n storage:\n connection.indexDir ?? indexDir ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex,\n uptimeMs: health.server?.uptimeMs,\n latencyMs: health.latencyMs ?? Date.now() - startedAt,\n clients: health.server?.clients,\n activeRequests: health.server?.activeRequests,\n queuedWork: health.server?.queuedWrites,\n watcher: health.server\n ? { active: health.server.watchingExternal, watchedFiles: health.server.watchingClients }\n : undefined,\n };\n } catch (error) {\n if (!isOfflineConnectionError(error)) {\n return failureService(\n 'codebase-index',\n 'Codebase index',\n false,\n 'project-server',\n error,\n Date.now() - startedAt,\n );\n }\n return {\n ...failureService(\n 'codebase-index',\n 'Codebase index',\n false,\n 'on-demand project-server',\n error,\n Date.now() - startedAt,\n ),\n status: 'offline',\n detail: 'Not running for this project; it starts on demand when indexing is used.',\n };\n }\n}\n\nasync function sageHealth(projectRoot: string): Promise<ConnectionHealthService> {\n const startedAt = Date.now();\n if (!isSageProjectServerAvailable()) {\n return {\n id: 'sage',\n label: 'SAGE memory',\n status: 'unavailable',\n required: false,\n mode: 'unavailable',\n detail: 'The packaged SAGE project server is unavailable in this runtime.',\n };\n }\n const connection = new SageProjectServerConnection(projectRoot);\n try {\n const status = await connection.status();\n if (!status) {\n return {\n id: 'sage',\n label: 'SAGE memory',\n status: 'offline',\n required: false,\n mode: 'on-demand project-server',\n detail: 'Not running for this project; it starts on demand when memory is used.',\n endpoint: connection.getState().endpoint,\n latencyMs: Date.now() - startedAt,\n };\n }\n const healthStatus =\n status.health.status === 'ready'\n ? 'healthy'\n : status.health.status === 'degraded'\n ? 'degraded'\n : 'error';\n return {\n id: 'sage',\n label: 'SAGE memory',\n status: healthStatus,\n required: false,\n mode: 'project-server',\n detail: `Persistent project memory backend: ${status.health.backend}.`,\n ownerPid: status.pid,\n endpoint: status.endpoint,\n storage: status.storageRoot,\n latencyMs: Date.now() - startedAt,\n clients: status.clients,\n activeRequests: status.pendingRequests,\n };\n } catch (error) {\n return failureService(\n 'sage',\n 'SAGE memory',\n false,\n 'project-server',\n error,\n Date.now() - startedAt,\n );\n } finally {\n connection.close();\n }\n}\n\nasync function kanbanHealth(projectRoot: string): Promise<ConnectionHealthService> {\n const startedAt = Date.now();\n if (process.env['WRONGSTACK_KANBAN_SERVER'] === '0') {\n return {\n id: 'kanban',\n label: 'Kanban IPC',\n status: 'unavailable',\n required: false,\n mode: 'disabled',\n detail: 'Kanban IPC daemon is disabled via WRONGSTACK_KANBAN_SERVER=0.',\n };\n }\n let connection;\n try {\n connection = await getKanbanServerConnection(projectRoot);\n } catch (error) {\n return failureService(\n 'kanban',\n 'Kanban IPC',\n false,\n 'project-server',\n error,\n Date.now() - startedAt,\n );\n }\n if (!connection) {\n return {\n id: 'kanban',\n label: 'Kanban IPC',\n status: 'unavailable',\n required: false,\n mode: 'disabled',\n detail: 'Kanban IPC daemon is disabled in this runtime.',\n };\n }\n try {\n const status = await connection.request('ping', {}, { timeoutMs: 5_000 });\n return {\n id: 'kanban',\n label: 'Kanban IPC',\n status: 'healthy',\n required: true,\n mode: 'project-server',\n detail: `Single shared project-server owns kanban state for this project (v${status.protocolVersion}).`,\n ownerPid: status.pid,\n endpoint: status.endpoint,\n storage: status.databasePath,\n latencyMs: Date.now() - startedAt,\n clients: status.clients,\n activeRequests: status.pendingRequests,\n uptimeMs: Date.now() - new Date(status.startedAt).getTime(),\n };\n } catch (error) {\n return failureService(\n 'kanban',\n 'Kanban IPC',\n true,\n 'project-server',\n error,\n Date.now() - startedAt,\n );\n }\n}\n\nfunction isOfflineConnectionError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n return /(?:ENOENT|ECONNREFUSED|not found|not running|unavailable|connect failed)/iu.test(message);\n}\n\nasync function mailboxHealth(projectRoot: string): Promise<ConnectionHealthService> {\n const startedAt = Date.now();\n if (!isMailboxProjectServerAvailable()) {\n return {\n id: 'mailbox',\n label: 'Mailbox IPC',\n status: 'unavailable',\n required: false,\n mode: 'unavailable',\n detail: 'The packaged mailbox project server is unavailable in this runtime.',\n };\n }\n // The mailbox owner keys its pipe on the *data* directory, not the repo root\n // \u2014 unlike SAGE and kanban, which take the root. Passing the root here\n // derived a different pipe name than the running daemon, so a healthy owner\n // with live clients was reported as \"sleeping\" on every refresh.\n const connection = new MailboxProjectServerConnection(\n resolveWstackPaths({ projectRoot }).projectDir,\n );\n try {\n const status = await connection.probeStatus();\n if (!status) {\n return {\n id: 'mailbox',\n label: 'Mailbox IPC',\n status: 'offline',\n required: false,\n mode: 'on-demand project-server',\n detail: 'Not running for this project; it starts on demand when mailbox is used.',\n endpoint: connection.getState().endpoint,\n latencyMs: Date.now() - startedAt,\n };\n }\n return {\n id: 'mailbox',\n label: 'Mailbox IPC',\n status: 'healthy',\n required: true,\n mode: 'project-server',\n detail: `Single shared project-server owns inter-agent mailbox state for this project (v${status.protocolVersion}).`,\n ownerPid: status.pid,\n endpoint: status.endpoint,\n storage: status.databasePath,\n latencyMs: Date.now() - startedAt,\n clients: status.clients,\n activeRequests: status.pendingRequests,\n uptimeMs: Date.now() - new Date(status.startedAt).getTime(),\n };\n } catch (error) {\n return failureService(\n 'mailbox',\n 'Mailbox IPC',\n true,\n 'project-server',\n error,\n Date.now() - startedAt,\n );\n } finally {\n connection.close();\n }\n}\n\n// \u2500\u2500 Service action (reset/kill) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface ServiceActionResult {\n serviceId: ConnectionHealthService['id'] | null;\n action: 'shutdown' | 'restart';\n success: boolean;\n message: string;\n}\n\n/** Handle WS message type `connections.service_action` \u2014 reset or kill a service. */\nexport async function handleConnectionsServiceAction(\n ws: WebSocket,\n message: WSClientMessage,\n context: ConnectionsHealthContext,\n): Promise<boolean> {\n if (message.type !== 'connections.service_action') return false;\n\n const payload = message.payload as { serviceId?: string; action?: string } | undefined;\n const serviceId = payload?.serviceId;\n const rawAction = payload?.action ?? 'shutdown';\n\n if (!serviceId) {\n context.send(ws, {\n type: 'connections.service_action_result',\n payload: {\n serviceId: null,\n action: rawAction as 'shutdown' | 'restart',\n success: false,\n message: 'Missing serviceId in payload',\n } satisfies ServiceActionResult,\n });\n return true;\n }\n\n if (rawAction !== 'shutdown') {\n context.send(ws, {\n type: 'connections.service_action_result',\n payload: {\n serviceId: serviceId as ConnectionHealthService['id'],\n action: rawAction as 'shutdown' | 'restart',\n success: false,\n message: `Unsupported action \"${rawAction}\" \u2014 only \"shutdown\" is currently supported`,\n } satisfies ServiceActionResult,\n });\n return true;\n }\n\n const action: 'shutdown' = rawAction;\n\n // 'webui' cannot kill itself\n if (serviceId === 'webui') {\n context.send(ws, {\n type: 'connections.service_action_result',\n payload: {\n serviceId: 'webui',\n action: action as 'shutdown' | 'restart',\n success: false,\n message: 'Cannot shut down the WebUI transport itself',\n } satisfies ServiceActionResult,\n });\n return true;\n }\n\n try {\n const result = await executeServiceAction(\n serviceId as ConnectionHealthService['id'],\n action as 'shutdown' | 'restart',\n context.getProjectRoot(),\n context.getIndexDir(),\n );\n context.send(ws, {\n type: 'connections.service_action_result',\n payload: result satisfies ServiceActionResult,\n });\n } catch (error) {\n context.send(ws, {\n type: 'connections.service_action_result',\n payload: {\n serviceId: serviceId as ConnectionHealthService['id'],\n action: action as 'shutdown' | 'restart',\n success: false,\n message: error instanceof Error ? error.message : String(error),\n } satisfies ServiceActionResult,\n });\n }\n return true;\n}\n\nasync function executeServiceAction(\n serviceId: ConnectionHealthService['id'],\n action: 'shutdown' | 'restart',\n projectRoot: string,\n indexDir: string | undefined,\n): Promise<ServiceActionResult> {\n switch (serviceId) {\n case 'kanban':\n return killKanbanServer(projectRoot, action);\n case 'sage':\n return killSageServer(projectRoot, action);\n case 'chronicle':\n return killChronicleServer(projectRoot, action);\n case 'codebase-index':\n return killCodebaseIndexServer(projectRoot, indexDir, action);\n case 'mailbox':\n return killMailboxServer(projectRoot, action);\n default:\n return {\n serviceId: serviceId as ConnectionHealthService['id'],\n action,\n success: false,\n message: `Unknown service: ${serviceId}`,\n };\n }\n}\n\nasync function killKanbanServer(\n projectRoot: string,\n action: 'shutdown' | 'restart',\n): Promise<ServiceActionResult> {\n if (process.env['WRONGSTACK_KANBAN_SERVER'] === '0') {\n return {\n serviceId: 'kanban',\n action,\n success: false,\n message: 'Kanban IPC daemon is disabled via WRONGSTACK_KANBAN_SERVER=0',\n };\n }\n let connection;\n try {\n connection = await getKanbanServerConnection(projectRoot);\n } catch (error) {\n return {\n serviceId: 'kanban',\n action,\n success: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n if (!connection) {\n return {\n serviceId: 'kanban',\n action,\n success: false,\n message: 'Kanban IPC daemon is not running',\n };\n }\n try {\n const result = await connection.request('shutdown', {\n reason: `WebUI request: ${action}`,\n });\n return {\n serviceId: 'kanban',\n action,\n success: result.stopping,\n message: result.stopping\n ? `Kanban IPC daemon ${action} requested`\n : `Kanban IPC daemon ${action} failed (shutdown not confirmed)`,\n };\n } catch (error) {\n return {\n serviceId: 'kanban',\n action,\n success: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nasync function killSageServer(\n projectRoot: string,\n action: 'shutdown' | 'restart',\n): Promise<ServiceActionResult> {\n if (!isSageProjectServerAvailable()) {\n return {\n serviceId: 'sage',\n action,\n success: false,\n message: 'SAGE project server is unavailable in this runtime',\n };\n }\n const connection = new SageProjectServerConnection(projectRoot);\n try {\n const result = await connection.shutdown(`WebUI request: ${action}`);\n return {\n serviceId: 'sage',\n action,\n success: result.stopped,\n message: result.stopped\n ? `SAGE memory server ${action} requested`\n : `SAGE memory server ${action} failed: ${result.reason ?? 'unknown'}`,\n };\n } catch (error) {\n return {\n serviceId: 'sage',\n action,\n success: false,\n message: error instanceof Error ? error.message : String(error),\n };\n } finally {\n connection.close();\n }\n}\n\nasync function killChronicleServer(\n projectRoot: string,\n action: 'shutdown' | 'restart',\n): Promise<ServiceActionResult> {\n const options = resolveChronicleProjectServerOptions({ projectRoot });\n const client = new ChronicleProjectServerClient(options);\n try {\n const result = await client.shutdown(`WebUI request: ${action}`);\n return {\n serviceId: 'chronicle',\n action,\n success: result.stopped,\n message: result.stopped\n ? `Chronicle telemetry server ${action} requested`\n : `Chronicle telemetry server ${action} failed: ${result.reason ?? 'unknown'}`,\n };\n } catch (error) {\n return {\n serviceId: 'chronicle',\n action,\n success: false,\n message: error instanceof Error ? error.message : String(error),\n };\n } finally {\n client.close();\n }\n}\n\nasync function killCodebaseIndexServer(\n projectRoot: string,\n indexDir: string | undefined,\n action: 'shutdown' | 'restart',\n): Promise<ServiceActionResult> {\n try {\n const result = await shutdownCodebaseIndexServer(\n projectRoot,\n indexDir,\n `websocket-request:${action}`,\n );\n return {\n serviceId: 'codebase-index',\n action,\n success: result.stopped,\n message: result.stopped\n ? `Codebase index server ${action} requested`\n : `Codebase index server ${action} failed: ${result.reason ?? 'unknown'}`,\n };\n } catch (error) {\n return {\n serviceId: 'codebase-index',\n action,\n success: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nasync function killMailboxServer(\n projectRoot: string,\n action: 'shutdown' | 'restart',\n): Promise<ServiceActionResult> {\n if (!isMailboxProjectServerAvailable()) {\n return {\n serviceId: 'mailbox',\n action,\n success: false,\n message: 'Mailbox project server is unavailable in this runtime',\n };\n }\n const connection = new MailboxProjectServerConnection(\n resolveWstackPaths({ projectRoot }).projectDir,\n );\n try {\n const result = await connection.shutdown(`WebUI request: ${action}`);\n return {\n serviceId: 'mailbox',\n action,\n success: result.stopped,\n message: result.stopped\n ? `Mailbox IPC server ${action} requested`\n : `Mailbox IPC server ${action} failed: ${result.reason ?? 'unknown'}`,\n };\n } catch (error) {\n return {\n serviceId: 'mailbox',\n action,\n success: false,\n message: error instanceof Error ? error.message : String(error),\n };\n } finally {\n connection.close();\n }\n}\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction failureService(\n id: ConnectionHealthService['id'],\n label: string,\n required: boolean,\n mode: string,\n error: unknown,\n latencyMs?: number,\n): ConnectionHealthService {\n const message = error instanceof Error ? error.message : String(error);\n return {\n id,\n label,\n status: 'error',\n required,\n mode,\n detail: message,\n lastError: message,\n ...(latencyMs === undefined ? {} : { latencyMs }),\n };\n}\n", "import { listContextWindowModes } from '@wrongstack/core/types';\nimport { atomicWrite } from '@wrongstack/core/utils';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\n/**\n * Custom context modes \u2014 user-defined presets that are loaded from disk,\n * merged with the built-in modes, and managed via WebSocket CRUD handlers.\n *\n * Stored in: ~/.wrongstack/profiles/<name>/custom-context-modes.json\n * Format: { \"modes\": ContextWindowMode[] }\n */\n\nexport interface CustomContextMode {\n id: string;\n name: string;\n description: string;\n thresholds: { warn: number; soft: number; hard: number };\n aggressiveOn: string;\n preserveK: number;\n eliseThreshold: number;\n targetLoad: number;\n /** Whether this is a user-defined (custom) or built-in mode. */\n custom: boolean;\n}\n\nexport interface CustomModeStore {\n modes: Map<string, CustomContextMode>;\n load: () => Promise<void>;\n save: () => Promise<void>;\n create: (mode: CustomContextMode) => { ok: boolean; error?: string | undefined };\n update: (id: string, patch: Partial<CustomContextMode>) => { ok: boolean; error?: string | undefined };\n remove: (id: string) => { ok: boolean; error?: string | undefined };\n list: () => CustomContextMode[];\n}\n\nconst STORE_FILENAME = 'custom-context-modes.json';\n\nfunction storePath(wrongstackDir: string): string {\n return path.join(wrongstackDir, STORE_FILENAME);\n}\n\nconst BUILTIN_IDS = new Set(['balanced', 'frugal', 'deep', 'archival']); // archival is reserved as a deprecated built-in alias.\n\nexport function createCustomModeStore(wrongstackDir: string): CustomModeStore {\n const modes = new Map<string, CustomContextMode>();\n\n const load = async (): Promise<void> => {\n modes.clear();\n try {\n const raw = await fs.readFile(storePath(wrongstackDir), 'utf8');\n const parsed = JSON.parse(raw) as { modes?: CustomContextMode[] };\n if (Array.isArray(parsed.modes)) {\n for (const m of parsed.modes) {\n if (m.id && !BUILTIN_IDS.has(m.id)) {\n modes.set(m.id, { ...m, custom: true });\n }\n }\n }\n } catch {\n // File missing or corrupt \u2014 start with empty custom modes.\n }\n };\n\n const save = async (): Promise<void> => {\n const arr = [...modes.values()];\n const json = JSON.stringify({ modes: arr }, null, 2);\n await atomicWrite(storePath(wrongstackDir), json);\n };\n\n const create = (\n mode: CustomContextMode,\n ): { ok: boolean; error?: string | undefined } => {\n if (!mode.id || typeof mode.id !== 'string') {\n return { ok: false, error: 'id is required' };\n }\n if (BUILTIN_IDS.has(mode.id)) {\n return { ok: false, error: `Cannot override built-in mode \"${mode.id}\"` };\n }\n if (modes.has(mode.id)) {\n return { ok: false, error: `Mode \"${mode.id}\" already exists` };\n }\n if (!mode.name) {\n return { ok: false, error: 'name is required' };\n }\n const entry: CustomContextMode = {\n id: mode.id,\n name: mode.name,\n description: mode.description || '',\n thresholds: {\n warn: mode.thresholds?.warn ?? 0.6,\n soft: mode.thresholds?.soft ?? 0.75,\n hard: mode.thresholds?.hard ?? 0.9,\n },\n aggressiveOn: mode.aggressiveOn || 'soft',\n preserveK: mode.preserveK ?? 10,\n eliseThreshold: mode.eliseThreshold ?? 2000,\n targetLoad: mode.targetLoad ?? 0.65,\n custom: true,\n };\n modes.set(mode.id, entry);\n void save().catch(() => {});\n return { ok: true };\n };\n\n const update = (\n id: string,\n patch: Partial<CustomContextMode>,\n ): { ok: boolean; error?: string | undefined } => {\n if (BUILTIN_IDS.has(id)) {\n return { ok: false, error: `Cannot modify built-in mode \"${id}\"` };\n }\n const existing = modes.get(id);\n if (!existing) {\n return { ok: false, error: `Mode \"${id}\" not found` };\n }\n const next: CustomContextMode = { ...existing };\n if (patch.name !== undefined) next.name = patch.name;\n if (patch.description !== undefined) next.description = patch.description;\n if (patch.thresholds) {\n next.thresholds = {\n warn: patch.thresholds.warn ?? existing.thresholds.warn,\n soft: patch.thresholds.soft ?? existing.thresholds.soft,\n hard: patch.thresholds.hard ?? existing.thresholds.hard,\n };\n }\n if (patch.preserveK !== undefined) next.preserveK = patch.preserveK;\n if (patch.eliseThreshold !== undefined) next.eliseThreshold = patch.eliseThreshold;\n if (patch.targetLoad !== undefined) next.targetLoad = patch.targetLoad;\n if (patch.aggressiveOn !== undefined) next.aggressiveOn = patch.aggressiveOn;\n modes.set(id, next);\n void save().catch(() => {});\n return { ok: true };\n };\n\n const remove = (\n id: string,\n ): { ok: boolean; error?: string | undefined } => {\n if (BUILTIN_IDS.has(id)) {\n return { ok: false, error: `Cannot delete built-in mode \"${id}\"` };\n }\n if (!modes.delete(id)) {\n return { ok: false, error: `Mode \"${id}\" not found` };\n }\n void save().catch(() => {});\n return { ok: true };\n };\n\n const list = (): CustomContextMode[] => {\n const builtins = listContextWindowModes().map((m) => ({\n id: m.id as string,\n name: m.name,\n description: m.description,\n thresholds: { ...m.thresholds },\n aggressiveOn: m.aggressiveOn as string,\n preserveK: m.preserveK,\n eliseThreshold: m.eliseThreshold,\n targetLoad: m.targetLoad,\n custom: false as const,\n }));\n const custom = [...modes.values()];\n return [...builtins, ...custom];\n };\n\n return { modes, load, save, create, update, remove, list };\n}\n", "// Eternal-autonomy iteration broadcast wiring.\n//\n// The CLI's `runWebUI` owns the eternal-autonomy engine and exposes a\n// `subscribeEternalIteration` callback that lets the webui hook into\n// the journal-entry stream. This module extracts the wiring in\n// isolation so it can be unit-tested without spinning up the full\n// server (clients, WS, HTTP bring-up).\n//\n// `createEternalSubscription` is the helper that:\n// 1. Calls the caller-supplied `subscribe` function with a broadcast\n// closure bound to the current `clients` Map.\n// 2. Captures the returned disposer so `tearDown` can invoke it on\n// server shutdown.\n//\n// Both the disposer and the `JournalEntry` are projected by the caller\n// \u2014 this module intentionally knows nothing about the engine itself.\n\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from './types.js';\nimport type { JournalEntry } from '@wrongstack/core/storage';\n\nexport type EternalSubscribe = (\n fn: (entry: JournalEntry) => void,\n) => () => void;\n\n// `clients` is generic so callers that use a structurally-similar\n// `ConnectedClient` (the CLI's own Map<WebSocket, { ws; sessionId }>,\n// for example) don't have to alias their type to webui's\n// `ConnectedClient`. The helper doesn't read the value at all \u2014\n// `broadcast` gets to decide whether to use the map or not \u2014 so we\n// only need the key type (WebSocket) to be present, which is\n// enforced by the constraint.\nexport type EternalBroadcast<C> = (clients: Map<WebSocket, C>, msg: WSServerMessage) => void;\n\nexport interface EternalSubscription {\n /** Tear down the underlying engine subscription. Idempotent. */\n dispose: () => void;\n}\n\nexport function createEternalSubscription<C>(\n subscribe: EternalSubscribe,\n broadcast: EternalBroadcast<C>,\n clientsRef: () => Map<WebSocket, C>,\n): EternalSubscription {\n let disposed = false;\n const dispose = subscribe((entry) => {\n if (disposed) return;\n broadcast(clientsRef(), {\n type: 'eternal.iteration',\n payload: { entry },\n });\n });\n return {\n dispose() {\n if (disposed) return;\n disposed = true;\n dispose();\n },\n };\n}\n", "/**\n * Shared `git.info` WebSocket handler for both the standalone WebUI server and\n * the CLI's `--webui` embedded server. Extracted from the duplicated switch\n * cases in `index.ts` and `cli/src/webui-server.ts`, which had drifted (the\n * standalone copy transposed ahead/behind and never matched deletions). One\n * implementation here keeps both surfaces in lockstep.\n *\n * case 'git.info': return handleGitInfo(ws, projectRoot);\n */\n\nimport type { WebSocket } from 'ws';\nimport nodePath from 'node:path';\nimport { send } from './ws-utils.js';\n\n/**\n * Read git branch, change stats, and upstream sync status from `projectRoot`\n * and broadcast a `git.info` message. Never throws \u2014 a non-repo / missing-git\n * directory yields an empty-but-valid payload.\n */\nexport async function handleGitInfo(ws: WebSocket, projectRoot: string): Promise<void> {\n const cwd = projectRoot || undefined;\n try {\n const { execFile: ef } = await import('node:child_process');\n const git = (args: string[]): Promise<string> =>\n new Promise((resolve) => {\n ef('git', args, { cwd, timeout: 3000 }, (err: Error | null, stdout: string) => {\n resolve(err ? '' : stdout.trim());\n });\n });\n\n const [branchRaw, diffRaw, statusRaw, upstreamRaw] = await Promise.all([\n git(['branch', '--show-current']),\n git(['diff', '--stat']),\n git(['status', '--porcelain']),\n git(['rev-list', '--left-right', '--count', '@{upstream}...HEAD']),\n ]);\n\n const branch = branchRaw || '(detached)';\n\n // `git diff --stat` summary line: \"N files changed, X insertions(+), Y deletions(-)\".\n // Deletions are formatted \"Y deletions(-)\" \u2014 the `+` only ever precedes\n // INSERTIONS, so a `\\+`-anchored deletion regex never matches.\n const addMatch = /(\\d+)\\s+insertion/i.exec(diffRaw);\n const delMatch = /(\\d+)\\s+deletion/i.exec(diffRaw);\n const added = addMatch ? Number(addMatch[1]) : 0;\n const deleted = delMatch ? Number(delMatch[1]) : 0;\n\n // Untracked files from `git status --porcelain` (lines starting with \"??\").\n const untracked = statusRaw.split('\\n').filter((l) => l.startsWith('??')).length;\n\n // `git rev-list --left-right --count @{upstream}...HEAD` prints \"<behind>\\t<ahead>\":\n // left = commits in upstream not in HEAD (BEHIND), right = HEAD-only (AHEAD).\n const [behindRaw, aheadRaw] = (upstreamRaw || '0\\t0').split('\\t');\n const behind = Number(behindRaw) || 0;\n const ahead = Number(aheadRaw) || 0;\n\n send(ws, { type: 'git.info', payload: { branch, added, deleted, untracked, ahead, behind } });\n } catch {\n // Git not available or not a repo \u2014 send empty info silently.\n send(ws, { type: 'git.info', payload: { branch: '', added: 0, deleted: 0, untracked: 0, ahead: 0, behind: 0 } });\n }\n}\n\n/** One changed file in the working tree (vs HEAD). */\nexport interface GitChangedFile {\n /** Repo-relative path (POSIX separators, as git reports). */\n path: string;\n /**\n * Single-letter change kind for the badge:\n * `M` modified, `A` added/staged-new, `D` deleted, `R` renamed,\n * `?` untracked, `C` copied, `U` unmerged/conflict.\n */\n status: string;\n /** Lines added (best-effort; 0 for untracked-binary / unknown). */\n added: number;\n /** Lines removed (best-effort). */\n deleted: number;\n /** True when the change is at least partly staged. */\n staged: boolean;\n}\n\n/** Spawn `git` in `cwd` and resolve its trimmed stdout ('' on any error). */\nfunction makeGit(cwd: string | undefined) {\n return async (args: string[]): Promise<string> => {\n const { execFile: ef } = await import('node:child_process');\n return new Promise((resolve) => {\n ef(\n 'git',\n args,\n { cwd, timeout: 5000, maxBuffer: 1024 * 1024 * 16 },\n (err: Error | null, stdout: string) => resolve(err ? '' : stdout),\n );\n });\n };\n}\n\n/**\n * Read the working-tree change set (everything that differs from HEAD:\n * staged, unstaged, and untracked) and broadcast a `git.changes` message.\n *\n * The file list comes from `git status --porcelain -z` (NUL-delimited so\n * paths with spaces/unicode survive intact, and renames are unambiguous).\n * Per-file line counts come from `--numstat` of both the unstaged and the\n * staged diff, summed. Untracked files intentionally report 0/0 here so the\n * list view does not read every untracked file; `git.diff` loads a selected\n * file lazily on demand.\n * Never throws \u2014 a non-repo yields an empty list.\n */\nexport async function handleGitChanges(ws: WebSocket, projectRoot: string): Promise<void> {\n const cwd = projectRoot || undefined;\n try {\n const git = makeGit(cwd);\n const [statusRaw, unstagedNumstat, stagedNumstat] = await Promise.all([\n git(['status', '--porcelain', '-z']),\n git(['diff', '--numstat', '-z']),\n git(['diff', '--cached', '--numstat', '-z']),\n ]);\n\n // numstat -z format: \"<added>\\t<deleted>\\t<path>\\0\" per entry. For a rename\n // git emits \"<added>\\t<deleted>\\0<oldpath>\\0<newpath>\\0\" (path field empty,\n // two extra NUL records). Parse defensively, keying counts by final path.\n const counts = new Map<string, { added: number; deleted: number }>();\n const parseNumstat = (raw: string): void => {\n const parts = raw.split('\\0');\n for (let i = 0; i < parts.length; i++) {\n const entry = parts[i];\n if (!entry) continue;\n const m = /^(\\d+|-)\\t(\\d+|-)\\t(.*)$/.exec(entry);\n if (!m) continue;\n const added = m[1] === '-' ? 0 : Number(m[1]);\n const deleted = m[2] === '-' ? 0 : Number(m[2]);\n let path = m[3] ?? '';\n if (path === '') {\n // Rename: next two records are old, then new path.\n i += 1;\n path = parts[i + 1] ?? parts[i] ?? '';\n i += 1;\n }\n if (!path) continue;\n const prev = counts.get(path) ?? { added: 0, deleted: 0 };\n counts.set(path, { added: prev.added + added, deleted: prev.deleted + deleted });\n }\n };\n parseNumstat(unstagedNumstat);\n parseNumstat(stagedNumstat);\n\n // `git status --porcelain -z`: each record is \"XY <path>\" (no separator\n // after the 2-char code beyond the single space). Rename/copy records are\n // followed by a separate NUL record carrying the original path.\n const records = statusRaw.split('\\0').filter((r) => r.length > 0);\n const files: GitChangedFile[] = [];\n for (let i = 0; i < records.length; i++) {\n const rec = records[i];\n if (!rec || rec.length < 3) continue;\n const x = rec[0] ?? ' ';\n const y = rec[1] ?? ' ';\n const path = rec.slice(3);\n const isRename = x === 'R' || x === 'C' || y === 'R' || y === 'C';\n if (isRename) i += 1; // consume the original-path record that follows\n\n let status: string;\n if (x === '?' && y === '?') status = '?';\n else if (x === 'U' || y === 'U' || (x === 'A' && y === 'A') || (x === 'D' && y === 'D')) status = 'U';\n else if (x === 'R' || y === 'R') status = 'R';\n else if (x === 'C' || y === 'C') status = 'C';\n else if (x === 'A' || y === 'A') status = 'A';\n else if (x === 'D' || y === 'D') status = 'D';\n else status = 'M';\n\n const staged = x !== ' ' && x !== '?';\n\n let added = counts.get(path)?.added ?? 0;\n let deleted = counts.get(path)?.deleted ?? 0;\n if (status === '?') {\n // Untracked files are not present in numstat. Do not read every file\n // here: large generated/untracked trees made git.changes an N+1 file\n // scan. The diff endpoint loads a selected file on demand.\n added = 0;\n deleted = 0;\n }\n files.push({ path, status, added, deleted, staged });\n }\n\n send(ws, { type: 'git.changes', payload: { files } });\n } catch (err) {\n send(ws, {\n type: 'git.changes',\n payload: { files: [], error: err instanceof Error ? err.message : String(err) },\n });\n }\n}\n\nconst MAX_DIFF_BYTES = 2 * 1024 * 1024; // 2 MB per side \u2014 guard the renderer\n\n/**\n * Resolve the before/after text for a single file and broadcast a `git.diff`\n * message. `oldText` is the file at HEAD (`git show HEAD:<path>`), `newText`\n * is the current working-tree content. New/untracked files have empty\n * `oldText`; deleted files have empty `newText`. Binary or oversized files\n * are reported with a flag instead of content so the client can show a notice.\n */\nexport async function handleGitDiff(\n ws: WebSocket,\n projectRoot: string,\n path: string,\n): Promise<void> {\n const cwd = projectRoot || undefined;\n const reply = (extra: Record<string, unknown>): void =>\n send(ws, { type: 'git.diff', payload: { path, ...extra } });\n\n if (!path || path.includes('\\0') || path.includes('..') || nodePath.isAbsolute(path)) {\n reply({ oldText: '', newText: '', error: 'invalid path' });\n return;\n }\n\n try {\n const git = makeGit(cwd);\n const { readFile } = await import('node:fs/promises');\n const { join } = await import('node:path');\n\n // HEAD version. `git show` writes nothing for a path absent at HEAD.\n const oldText = await git(['show', `HEAD:${path}`]);\n\n // Working-tree version (absent \u2192 deleted file \u2192 empty).\n let newText = '';\n try {\n const abs = cwd ? join(cwd, path) : path;\n const buf = await readFile(abs);\n if (buf.includes(0)) {\n reply({ oldText: '', newText: '', binary: true });\n return;\n }\n if (buf.length > MAX_DIFF_BYTES) {\n reply({ oldText: '', newText: '', tooLarge: true });\n return;\n }\n newText = buf.toString('utf8');\n } catch {\n newText = '';\n }\n\n if ((oldText.length || 0) > MAX_DIFF_BYTES) {\n reply({ oldText: '', newText: '', tooLarge: true });\n return;\n }\n if (oldText.includes('\\0')) {\n reply({ oldText: '', newText: '', binary: true });\n return;\n }\n\n reply({ oldText, newText });\n } catch (err) {\n reply({ oldText: '', newText: '', error: err instanceof Error ? err.message : String(err) });\n }\n}\n", "/**\n * Goal-state WebSocket handler for the WebUI server, extracted from the\n * `handleMessage` switch in `index.ts` as part of splitting that file (#31).\n *\n * case 'goal.get': return handleGoalGet(projectRoot, (m) => broadcast(clients, m));\n *\n * Reads the canonical goal.json and broadcasts it to every connected client so\n * all browser tabs share one goal snapshot. Never throws \u2014 a missing or\n * unparseable file broadcasts `null` so clients clear stale goal state.\n */\n\nimport { resolveWstackPaths } from '@wrongstack/core/utils';\n\n/**\n * Read `goal.json` for `projectRoot` and broadcast a `goal-state.updated` message.\n * The path must match /goal, the autonomy engines, and TUI F9, which all\n * resolve via `resolveWstackPaths().projectGoal`\n * (`~/.wrongstack/projects/<slug>/goal.json`) \u2014 NOT the repo-local\n * `.wrongstack/goal.json`.\n */\nexport async function handleGoalGet(\n projectRoot: string,\n broadcast: (msg: object) => void,\n): Promise<void> {\n try {\n const goalPath = resolveWstackPaths({ projectRoot }).projectGoal;\n const { readFile } = await import('node:fs/promises');\n const raw = await readFile(goalPath, 'utf8');\n const goal = JSON.parse(raw);\n broadcast({ type: 'goal-state.updated', payload: goal });\n } catch {\n broadcast({ type: 'goal-state.updated', payload: null });\n }\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface GoalRouteHandlers {\n handleMessage: (ws: WebSocket, msg: { type: string; payload?: Record<string, unknown> }) => Promise<void>;\n}\n\nexport async function handleGoalRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: GoalRouteHandlers,\n): Promise<boolean> {\n if (!msg.type.startsWith('goal.')) return false;\n await handlers.handleMessage(ws, msg as { type: string; payload?: Record<string, unknown> });\n return true;\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface GoalSnapshotRouteHandlers {\n getSnapshot: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport async function handleGoalSnapshotRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: GoalSnapshotRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'goal.get':\n case 'goal-state.get':\n await handlers.getSnapshot(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import type { Agent, Context } from '@wrongstack/core/agent';\nimport { assignNickname } from '@wrongstack/core/coordination';\nimport {\n GoalAssessor,\n type GoalAssessResult,\n GoalPlanner,\n type PhaseExecutionContext,\n type PhaseGraph,\n PhaseGraphBuilder,\n type PhaseNode,\n PhaseOrchestrator,\n PhaseStore,\n type PhaseTemplate,\n} from '@wrongstack/core/goal';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport type { Logger } from '@wrongstack/core/types';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport { WorktreeManager } from '@wrongstack/core/worktree';\nimport type { WebSocket } from 'ws';\nimport { gitStdout, isGitWorkTree } from './git-process.js';\nimport { sendSerialized } from './ws-utils.js';\n\n/**\n * Derive a short, single-line heading from a (possibly multi-paragraph) goal\n * prompt. Takes the first non-empty line, trims to its first sentence, and caps\n * the length so Goal headers stay readable. The full prompt is preserved\n * separately as the graph description.\n */\nfunction deriveTitle(goal: string): string {\n const firstLine = goal\n .split('\\n')\n .map((l) => l.trim())\n .find(Boolean);\n if (!firstLine) return 'Goal';\n const sentence = firstLine.split(/(?<=[.!?])\\s/)[0] ?? firstLine;\n const trimmed = sentence.length <= 64 ? sentence : `${sentence.slice(0, 63).trimEnd()}\u2026`;\n return trimmed || 'Goal';\n}\n\n/**\n * List the commits on `branch` since `baseSha` (oldest \u2192 newest, the order they\n * landed). Used by `goal.revert` to feed WorktreeManager.revertCommits,\n * which reverses them. Returns [] on any git error.\n */\nasync function commitsSince(cwd: string, baseSha: string, branch: string): Promise<string[]> {\n const output = await gitStdout(cwd, ['log', '--reverse', '--format=%H', `${baseSha}..${branch}`]);\n if (output === null) return [];\n return output\n .split('\\n')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n\ninterface WSClient {\n ws: WebSocket;\n id: string;\n}\n\ninterface GoalWSMessage {\n type: string;\n payload?: Record<string, unknown>;\n}\n\n/**\n * GoalWebSocketHandler \u2014 WebSocket-based goal-driven phase execution.\n *\n * Message types:\n * goal.start \u2192 { title, phases?, autonomous? }\n * goal.pause \u2192 {}\n * goal.resume \u2192 {}\n * goal.stop \u2192 {}\n * goal.status \u2192 {}\n * goal.selectPhase \u2192 { phaseId }\n * goal.taskStatus \u2192 { taskId, status }\n */\nexport class GoalWebSocketHandler {\n private orchestrator: PhaseOrchestrator | null = null;\n private graph: PhaseGraph | null = null;\n private store: PhaseStore;\n private clients = new Set<WSClient>();\n private broadcastInterval: ReturnType<typeof setInterval> | null = null;\n /** Aborts in-flight task agents AND the planning turn when the run is stopped. */\n private abort: AbortController | null = null;\n /** Per-assessment AbortController so a newer assessment can abort the prior\n * LLM call instead of waiting for it to finish (frees the Agent's single-flight\n * guard sooner). */\n private assessAbort: AbortController | null = null;\n /** Monotonically increasing seq for stale-assessment detection. */\n private assessSeq = 0;\n /** Set the instant a stop/clear/revert is requested, so a planning turn that\n * resolves afterwards never launches the orchestrator (the abort alone can't\n * cover the window between the LLM call resolving and the orchestrator start). */\n private stopping = false;\n /** Optional per-phase git-worktree isolation (lazily created at start). */\n private worktrees: WorktreeManager | null = null;\n /** Base branch + tip SHA captured at run start so a revert can git-revert the\n * run's squash commits (history-preserving) instead of a destructive reset. */\n private runBase: { branch: string; sha: string } | null = null;\n /** Per-run worker identities so the board can show \"who is on what\". */\n private usedNicknames = new Set<string>();\n\n constructor(\n private agent: Agent,\n private context: Context,\n private logger: Logger,\n storeDir: string,\n private events?: EventBus | undefined,\n private projectRoot?: string | undefined,\n /**\n * Optional tap invoked on every board-state broadcast with the live\n * `buildState()` projection. Lets a KanbanRunMirror project the Goal\n * run into a kanban board without this handler knowing about kanban. The\n * WebUI orchestrator does NOT emit PhaseEventMap on the shared bus, so this\n * callback is the mirror's only live signal for Goal.\n */\n private onBoardState?: ((graphId: string, state: Record<string, unknown>) => void) | undefined,\n ) {\n this.store = new PhaseStore({ baseDir: storeDir });\n }\n\n addClient(ws: WebSocket): void {\n const client: WSClient = { ws, id: crypto.randomUUID() };\n this.clients.add(client);\n\n ws.on('close', () => this.clients.delete(client));\n ws.on('error', () => this.clients.delete(client));\n\n // Send current state\n this.sendState(client);\n }\n\n /** Release timers, in-flight work, and socket references owned by this host. */\n dispose(): void {\n this.stopping = true;\n this.abort?.abort();\n this.abort = null;\n this.assessAbort?.abort();\n this.assessAbort = null;\n this.orchestrator?.stop();\n this.stopBroadcast();\n this.clients.clear();\n }\n\n async handleMessage(ws: WebSocket, msg: GoalWSMessage): Promise<void> {\n switch (msg.type) {\n case 'goal.assess':\n await this.handleAssess(ws, msg.payload);\n break;\n case 'goal.start':\n await this.handleStart(msg.payload);\n break;\n case 'goal.pause':\n this.orchestrator?.pause();\n this.broadcast({ type: 'goal.paused', payload: {} });\n break;\n case 'goal.resume':\n this.orchestrator?.resume();\n this.broadcast({ type: 'goal.resumed', payload: {} });\n break;\n case 'goal.stop':\n await this.handleStop();\n break;\n case 'goal.clear':\n await this.handleClear();\n break;\n case 'goal.revert':\n await this.handleRevert();\n break;\n case 'goal.status':\n this.broadcastState();\n break;\n case 'goal.selectPhase': {\n const phaseId = msg.payload?.phaseId as string;\n if (phaseId && this.graph) {\n this.broadcastState(phaseId);\n }\n break;\n }\n case 'goal.taskStatus': {\n const { taskId, status } = msg.payload as { taskId: string; status: string };\n await this.handleTaskStatusChange(taskId, status);\n break;\n }\n case 'goal.moveTask': {\n const { taskId, toPhaseId } = msg.payload as { taskId: string; toPhaseId: string };\n if (this.orchestrator?.moveTask(taskId, toPhaseId)) this.afterBoardMutation();\n break;\n }\n case 'goal.assignTask': {\n const { taskId, agentId, agentName } = msg.payload as {\n taskId: string;\n agentId?: string;\n agentName?: string;\n };\n if (this.orchestrator?.setTaskAssignee(taskId, agentId, agentName))\n this.afterBoardMutation();\n break;\n }\n case 'goal.addTask': {\n const { phaseId, title, description, type, priority } = msg.payload as {\n phaseId: string;\n title: string;\n description?: string;\n type?: import('@wrongstack/core/types').TaskNode['type'];\n priority?: import('@wrongstack/core/types').TaskNode['priority'];\n };\n if (\n title?.trim() &&\n this.orchestrator?.addTask(phaseId, { title: title.trim(), description, type, priority })\n ) {\n this.afterBoardMutation();\n }\n break;\n }\n case 'goal.retryTask':\n case 'goal.runTask': {\n const { taskId } = msg.payload as { taskId: string };\n if (this.orchestrator?.requeueTask(taskId)) this.afterBoardMutation();\n break;\n }\n case 'goal.toggleAutonomous': {\n const autonomous = (msg.payload?.autonomous as boolean) ?? !this.graph?.autonomous;\n if (this.graph) {\n this.graph.autonomous = autonomous;\n await this.store.save(this.graph);\n this.broadcast({ type: 'goal.state', payload: this.buildState() });\n }\n break;\n }\n case 'goal.save': {\n if (this.graph) {\n await this.store.save(this.graph);\n this.broadcast({ type: 'goal.saved', payload: { graphId: this.graph.id } });\n }\n break;\n }\n case 'goal.list': {\n const graphs = await this.store.list();\n this.broadcast({ type: 'goal.list', payload: { graphs } });\n break;\n }\n case 'goal.load': {\n const graphId = msg.payload?.graphId as string | undefined;\n if (graphId) {\n const graph = await this.store.load(graphId);\n if (graph) {\n this.graph = graph;\n this.broadcast({ type: 'goal.state', payload: this.buildState() });\n } else {\n this.broadcast({\n type: 'goal.error',\n payload: { message: `Graph not found: ${graphId}` },\n });\n }\n }\n break;\n }\n }\n }\n\n /**\n * Assess a goal prompt for duration realism. Runs a lightweight LLM call\n * (faster than planPhases) and returns the structured assessment to the\n * requesting client so the UI can warn about unrealistic durations before\n * the user submits the goal for planning. Sends only to the originating\n * client (unicast) and echoes the client's `seq` for response correlation.\n */\n private async handleAssess(ws: WebSocket, payload?: Record<string, unknown>): Promise<void> {\n const goal = (payload?.goal as string) || '';\n const seq = (payload?.seq as number) ?? 0;\n\n // Abort any prior assessment so its LLM call stops and frees the Agent's\n // single-flight guard (_runInProgress), allowing this new assessment to\n // start without waiting. The stale-seq guard below still catches any\n // race between abort and the new seq being set.\n this.assessAbort?.abort();\n this.assessAbort = new AbortController();\n const signal = this.assessAbort.signal;\n\n const mySeq = ++this.assessSeq;\n\n const sendResult = (result: GoalAssessResult) => {\n // Stale guard: if a newer assessment arrived while this one was running,\n // discard the response. The client also has its own reqSeq guard.\n if (mySeq !== this.assessSeq) return;\n sendSerialized(\n ws,\n JSON.stringify({\n type: 'goal.assess.result',\n payload: { ...result, reqSeq: seq },\n }),\n );\n };\n\n if (!goal.trim()) {\n sendResult({\n realistic: true,\n durationClaimed: null,\n explanation: '',\n recommendedDuration: null,\n concerns: [],\n raw: '',\n parseFailed: false,\n });\n return;\n }\n\n try {\n const assessor = new GoalAssessor({\n goal,\n runOnce: async (prompt: string) => {\n const result = (await this.agent.run(prompt, { signal })) as {\n status: string;\n finalText?: string | undefined;\n };\n return result.status === 'done' ? (result.finalText ?? '') : '';\n },\n });\n const result = await assessor.assess();\n sendResult(result);\n } catch (err: unknown) {\n // Stale guard: skip logging+response if superseded.\n if (mySeq !== this.assessSeq) return;\n this.logger.error(`[Goal] Assessment failed: ${toErrorMessage(err)}`);\n sendResult({\n realistic: true,\n durationClaimed: null,\n explanation: '',\n recommendedDuration: null,\n concerns: [],\n raw: '',\n parseFailed: true,\n parseError: `Assessment error: ${toErrorMessage(err)}`,\n });\n }\n }\n\n private async handleStart(payload?: Record<string, unknown>): Promise<void> {\n // The caller sends the operator's full prompt as the goal. We keep it intact\n // as the graph `description` and derive a short, human-readable `title` for\n // headers / the board switcher \u2014 pasting the whole prompt as the title made\n // the Goal header unreadable.\n const goal = (payload?.goal as string) || (payload?.title as string) || 'Untitled Project';\n const title = deriveTitle(goal);\n const autonomous = (payload?.autonomous as boolean) ?? true;\n const multiBoard = (payload?.multiBoard as boolean) ?? false;\n const verifyTasks = (payload?.verifyTasks as boolean) ?? false;\n const chimeraReview = (payload?.chimeraReview as boolean) ?? false;\n\n // Fresh abort for THIS run, created BEFORE planning so a stop pressed during\n // the (long) planning turn actually cancels it. Previously the controller was\n // created only after planning, so a stop while \"starting\" was a no-op and the\n // run launched anyway.\n const runAbort = new AbortController();\n this.abort = runAbort;\n this.stopping = false;\n\n // Phase plan resolution:\n // 1. explicit phases in the payload win (caller override);\n // 2. otherwise the LLM plans phases+todos for the goal;\n // 3. failing that, fall back to the generic default phases.\n const phases = Array.isArray(payload?.phases)\n ? (payload.phases as PhaseTemplate[])\n : await this.planPhases(goal, runAbort.signal);\n\n // Stop requested during planning \u2192 never launch the orchestrator. The abort\n // may not have interrupted the in-flight LLM call promptly, so the `stopping`\n // flag is the authoritative guard for the resolve-after-stop window.\n if (this.stopping || runAbort.signal.aborted) {\n this.broadcast({ type: 'goal.stopped', payload: { title } });\n return;\n }\n\n this.logger.info(`[Goal] Starting: ${title}`);\n\n // Build the graph up-front so we have a reference for live broadcasts and\n // persistence *before* the (long-running) build begins.\n const graph = await new PhaseGraphBuilder({\n title,\n description: goal,\n phases,\n autonomous,\n multiBoard,\n verifyTasks,\n chimeraReview,\n }).build();\n this.graph = graph;\n await this.store.save(graph);\n\n // Per-phase git-worktree isolation, when enabled and inside a git repo.\n // The shared agent/context means we can't run phases in parallel here\n // (we swap a single context.cwd per task), so phases stay sequential \u2014\n // but each phase still commits + squash-merges back through its own\n // worktree, and the lifecycle events drive the live swim-lane/DAG view.\n // Per-run worktree-isolation override from the UI wins; omitted \u2192 env default\n // (disable with WRONGSTACK_GOAL_WORKTREES=0). false \u2192 run on the current branch.\n const useWorktrees =\n (payload?.worktrees as boolean | undefined) ??\n process.env['WRONGSTACK_GOAL_WORKTREES'] !== '0';\n if (\n !this.worktrees &&\n this.events &&\n this.projectRoot &&\n useWorktrees &&\n (await isGitWorkTree(this.projectRoot))\n ) {\n this.worktrees = new WorktreeManager({\n projectRoot: this.projectRoot,\n events: this.events,\n sessionId: () => this.context.session?.id,\n });\n }\n // Capture the pre-run base tip so `goal.revert` can git-revert exactly\n // the commits this run lands on the base branch.\n if (this.worktrees) {\n this.runBase = await this.worktrees.currentBase();\n }\n\n // Verification hooks \u2014 conditionally wired when verifyTasks is enabled.\n // When active, the orchestrator runs typecheck after each task and triggers\n // a repair subagent on failure, closing the verify\u2192repair\u2192verify loop.\n const maybeVerify: {\n verifyPhase?: PhaseExecutionContext['verifyPhase'];\n repairPhase?: PhaseExecutionContext['repairPhase'];\n } = {};\n if (verifyTasks && this.projectRoot) {\n maybeVerify.verifyPhase = (async (\n phase: PhaseNode,\n env?: { cwd?: string | undefined; branch?: string | undefined },\n ) => {\n const cwd = env?.cwd ?? this.projectRoot!;\n try {\n // Run typecheck in the phase worktree (or project root).\n const { execFile } = await import('node:child_process');\n const result = await new Promise<string>((resolve) => {\n const npxCommand = process.platform === 'win32' ? 'npx.cmd' : 'npx';\n execFile(npxCommand, ['tsc', '--noEmit'], { cwd, timeout: 60_000 }, (err, stdout, stderr) => {\n if (err && (err as NodeJS.ErrnoException).code === 'ENOENT') {\n resolve('[verify] tsc not found \u2014 skipping');\n return;\n }\n resolve(stdout + stderr);\n });\n });\n if (result.includes('[verify]') || result.trim().length === 0) {\n return { ok: true as const };\n }\n this.logger.warn(`[Goal] Verify failed for phase \"${phase.name}\":\\n${result}`);\n return { ok: false as const, output: result };\n } catch {\n return { ok: true as const };\n }\n }) as PhaseExecutionContext['verifyPhase'];\n maybeVerify.repairPhase = (async (phase: PhaseNode, failure: string, attempt: number) => {\n this.logger.info(`[Goal] Repair attempt ${attempt} for phase \"${phase.name}\"`);\n const repairPrompt = `Fix all type errors in the project at ${this.projectRoot ?? '(unknown)'}. Typecheck output:\\n\\n${failure.slice(0, 4000)}\\n\\nRun npx tsc --noEmit to verify the fix. Output the fixed file paths.`;\n const repairResult = (await this.agent.run(repairPrompt)) as {\n status: string;\n finalText?: string | undefined;\n };\n if (repairResult.status !== 'done') {\n this.logger.warn(`[Goal] Repair attempt ${attempt} did not complete`);\n }\n }) as PhaseExecutionContext['repairPhase'];\n }\n\n this.orchestrator = new PhaseOrchestrator({\n graph,\n ctx: {\n executeTask: async (task, phaseId, env) => {\n this.logger.info(`[Goal] [${phaseId}] Executing: ${task.title}`);\n const result = await this.executeTaskWithAgent(task, phaseId, env);\n this.logger.info(`[Goal] [${phaseId}] Completed: ${task.title}`);\n\n // Chimera auto-review: when enabled, run a lightweight review\n // of the task output in the background (fire-and-forget).\n if (chimeraReview) {\n void this.runChimeraReview(task, phaseId, result, env?.cwd);\n }\n\n return result;\n },\n ...maybeVerify,\n onPhaseComplete: (phase) => {\n this.logger.info(`[Goal] Phase completed: ${phase.name}`);\n void this.store.save(graph);\n this.broadcastState();\n },\n onPhaseFail: (phase, error) => {\n this.logger.error(`[Goal] Phase failed: ${phase.name} \u2014 ${error.message}`);\n void this.store.save(graph);\n this.broadcastState();\n },\n },\n worktrees: this.worktrees ?? undefined,\n autonomous,\n // Must stay 1: phase tasks run on the single shared context whose cwd we\n // swap per phase, so parallel phases would race on context.cwd.\n maxConcurrentPhases: 1,\n // Sequential within a phase: each todo is a full-tool agent editing the\n // phase worktree, so running two at once risks concurrent writes.\n maxConcurrentTasks: 1,\n });\n\n // Start the live broadcast immediately, then run the orchestrator in the\n // background. Awaiting start() would block until the *entire* build\n // finishes \u2014 the periodic broadcast (below) reads the mutating graph, so\n // clients see live progress while it runs.\n this.startBroadcast();\n this.broadcastState();\n\n void this.orchestrator\n .start()\n .then(() => {\n this.orchestrator?.stop(); // clear the autonomous tick interval\n void this.store.save(graph);\n this.stopBroadcast();\n const failed = graph.failedPhaseIds.length > 0;\n this.broadcast(\n failed\n ? { type: 'goal.failed', payload: { title } }\n : { type: 'goal.completed', payload: { title } },\n );\n this.broadcastState();\n })\n .catch((err: unknown) => {\n this.logger.error(`[Goal] Aborted: ${toErrorMessage(err)}`);\n this.stopBroadcast();\n this.broadcast({ type: 'goal.failed', payload: { title, error: String(err) } });\n });\n }\n\n /**\n * Halt the run NOW \u2014 at any phase. Sets `stopping` (so a planning turn that\n * resolves afterwards bails), aborts in-flight agents, stops the orchestrator\n * tick, and ends the live broadcast. The board is kept for review; use\n * `goal.clear` to reset or `goal.revert` to undo the changes.\n */\n private async handleStop(): Promise<void> {\n this.stopping = true;\n this.abort?.abort();\n this.assessAbort?.abort();\n this.assessAbort = null;\n this.orchestrator?.stop();\n this.stopBroadcast();\n if (this.graph) await this.store.save(this.graph).catch(() => undefined);\n this.broadcast({ type: 'goal.stopped', payload: { title: this.graph?.title } });\n }\n\n /**\n * Stop + wipe: tear down phase worktrees and reset to an empty board so the UI\n * returns to the start screen (\"new one\"). Does NOT touch already-merged commits\n * on the base branch \u2014 that is `goal.revert`.\n */\n private async handleClear(): Promise<void> {\n await this.handleStop();\n if (this.worktrees) await this.worktrees.cleanupAllManaged().catch(() => undefined);\n this.orchestrator = null;\n this.graph = null;\n this.runBase = null;\n this.usedNicknames.clear();\n this.broadcast({ type: 'goal.cleared', payload: {} });\n // Empty state \u2192 board/wizard falls back to the goal-entry screen.\n this.broadcast({ type: 'goal.state', payload: this.buildState() });\n }\n\n /**\n * Stop + undo: remove phase worktrees, then history-preservingly `git revert`\n * every commit this run landed on the base branch (captured `runBase`..HEAD),\n * then reset to an empty board. Refuses (reports a reason) on a dirty tree or a\n * conflicting revert rather than leaving the tree half-reverted.\n */\n private async handleRevert(): Promise<void> {\n await this.handleStop();\n if (!this.worktrees || !this.runBase || !this.projectRoot) {\n this.broadcast({\n type: 'goal.reverted',\n payload: { ok: false, reverted: 0, reason: 'no git baseline was captured for this run' },\n });\n return;\n }\n await this.worktrees.cleanupAllManaged().catch(() => undefined);\n const shas = await commitsSince(this.projectRoot, this.runBase.sha, this.runBase.branch);\n const res = await this.worktrees.revertCommits(this.runBase.branch, shas);\n this.broadcast({ type: 'goal.reverted', payload: res });\n if (res.ok) {\n this.orchestrator = null;\n this.graph = null;\n this.runBase = null;\n this.broadcast({ type: 'goal.cleared', payload: {} });\n this.broadcast({ type: 'goal.state', payload: this.buildState() });\n }\n }\n\n /** Generic fallback phases when the LLM planner produces nothing usable. */\n private defaultPhases(): PhaseTemplate[] {\n return [\n {\n name: 'Discovery',\n description: 'Requirements gathering',\n priority: 'high',\n estimateHours: 2,\n parallelizable: false,\n },\n {\n name: 'Design',\n description: 'Architecture and design',\n priority: 'critical',\n estimateHours: 4,\n parallelizable: false,\n },\n {\n name: 'Implementation',\n description: 'Core development',\n priority: 'critical',\n estimateHours: 12,\n parallelizable: false,\n },\n {\n name: 'Testing',\n description: 'Unit and integration tests',\n priority: 'high',\n estimateHours: 6,\n parallelizable: true,\n },\n {\n name: 'Deployment',\n description: 'Deploy to production',\n priority: 'medium',\n estimateHours: 2,\n parallelizable: false,\n },\n ];\n }\n\n /** Plan phases+todos for the goal via the LLM; fall back to defaults on failure.\n * The caller passes the run's abort signal so a stop during planning cancels\n * the LLM turn (the previous fresh, never-aborted controller made planning\n * uninterruptible). */\n private async planPhases(goal: string, signal?: AbortSignal): Promise<PhaseTemplate[]> {\n try {\n const planner = new GoalPlanner({\n goal,\n runOnce: async (prompt) => {\n const result = (await this.agent.run(prompt, {\n signal: signal ?? new AbortController().signal,\n })) as {\n status: string;\n finalText?: string | undefined;\n };\n return result.status === 'done' ? (result.finalText ?? '') : '';\n },\n });\n const { phases, parseFailed } = await planner.plan();\n if (!parseFailed && phases.length > 0) {\n const todos = phases.reduce((n, p) => n + (p.taskTemplates?.length ?? 0), 0);\n this.logger.info(`[Goal] Planned ${phases.length} phases / ${todos} todos for: ${goal}`);\n return phases;\n }\n this.logger.info(`[Goal] Planner produced no phases; using defaults for: ${goal}`);\n } catch (err) {\n this.logger.error(`[Goal] Planning failed, using defaults: ${toErrorMessage(err)}`);\n }\n return this.defaultPhases();\n }\n\n private async executeTaskWithAgent(\n task: import('@wrongstack/core/types').TaskNode,\n phaseId: string,\n env?: { cwd?: string | undefined; branch?: string | undefined },\n ): Promise<unknown> {\n // Give the task a human worker identity (reuse a manual assignment if one\n // exists) so the board shows who is running it; reflect it on the node and\n // push a live state update before the (long) run begins.\n if (!task.assignee) {\n const nick = assignNickname('executor', this.usedNicknames);\n this.usedNicknames.add(nick.key);\n task.assignee = nick.display.replace(/\\s*\\([^)]*\\)\\s*$/, '');\n task.updatedAt = Date.now();\n this.broadcastState();\n }\n\n // Execute task with agent\n const prompt = `Execute task: ${task.title}\\n\\nDescription: ${task.description}\\nPhase: ${phaseId}\\nPriority: ${task.priority}\\nType: ${task.type}`;\n const signal = this.abort?.signal ?? new AbortController().signal;\n // Redirect the shared context's cwd at the phase worktree for the duration\n // of this task. Safe because phases/tasks run strictly sequentially here;\n // tools read `ctx.cwd` live, so the agent operates inside the worktree.\n const prevCwd = this.context.cwd;\n if (env?.cwd) this.context.cwd = env.cwd;\n try {\n return await this.agent.run(prompt, { signal });\n } finally {\n this.context.cwd = prevCwd;\n }\n }\n\n /**\n * Run a lightweight chimera-style review of a completed task's output.\n * Fire-and-forget: runs in the background and logs the review summary.\n */\n private async runChimeraReview(\n task: import('@wrongstack/core/types').TaskNode,\n phaseId: string,\n result: unknown,\n cwd?: string | undefined,\n ): Promise<void> {\n const output = typeof result === 'string' ? result : JSON.stringify(result, null, 2);\n void cwd; // reserved for future worktree-scoped review\n const reviewPrompt = [\n 'You are a code review agent. Review the following completed task and its output.',\n '',\n `Task: ${task.title}`,\n task.description ? `Description: ${task.description}` : '',\n `Phase: ${phaseId}`,\n `Priority: ${task.priority}`,\n '',\n '--- Task Output ---',\n output.slice(0, 8000),\n '',\n '---',\n '',\n 'Provide a brief review (2-5 sentences) covering:',\n '1. Does the output satisfy the task requirements? (yes/no/partial)',\n '2. Any correctness, security, or quality concerns.',\n '3. A confidence score (low/medium/high).',\n ]\n .filter(Boolean)\n .join('\\n');\n\n try {\n const result_ = (await this.agent.run(reviewPrompt)) as {\n status: string;\n finalText?: string | undefined;\n };\n if (result_.status === 'done' && result_.finalText) {\n this.logger.info(\n `[Goal] Chimera review for \"${task.title}\":\\n${result_.finalText.slice(0, 2000)}`,\n );\n }\n } catch (err: unknown) {\n this.logger.warn(`[Goal] Chimera review failed for \"${task.title}\": ${toErrorMessage(err)}`);\n }\n }\n\n /** Persist + broadcast after an interactive board mutation. */\n private afterBoardMutation(): void {\n if (this.graph) void this.store.save(this.graph);\n this.broadcastState();\n }\n\n private async handleTaskStatusChange(taskId: string, status: string): Promise<void> {\n if (!this.graph) return;\n\n for (const phase of this.graph.phases.values()) {\n const task = phase.taskGraph.nodes.get(taskId);\n if (task) {\n task.status = status as import('@wrongstack/core/types').TaskStatus;\n task.updatedAt = Date.now();\n this.broadcastState();\n return;\n }\n }\n }\n\n private startBroadcast(): void {\n if (this.broadcastInterval) return;\n this.broadcastInterval = setInterval(() => {\n const progress = this.orchestrator?.getProgress();\n if (progress) this.broadcast({ type: 'goal.progress', payload: progress });\n this.broadcastState();\n }, 2000);\n }\n\n private stopBroadcast(): void {\n if (this.broadcastInterval) {\n clearInterval(this.broadcastInterval);\n this.broadcastInterval = null;\n }\n }\n\n private broadcastState(activePhaseId?: string): void {\n if (!this.graph) return;\n\n const state = this.buildState(activePhaseId);\n this.broadcast({ type: 'goal.state', payload: state });\n // Feed the run mirror (if any) the same projection so it can sync a kanban\n // board. Best-effort \u2014 a mirror error must never break the live broadcast.\n if (this.onBoardState) {\n try {\n this.onBoardState(this.graph.id, state);\n } catch (err) {\n this.logger.error(\n `[Goal] board-state tap failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n }\n\n private buildState(activePhaseId?: string): Record<string, unknown> {\n if (!this.graph) {\n return {\n phases: [],\n tasks: [],\n overallPercent: 0,\n autonomous: true,\n title: '',\n multiBoard: false,\n verifyTasks: false,\n chimeraReview: false,\n };\n }\n\n const phases = Array.from(this.graph.phases.values());\n const currentActiveId =\n activePhaseId || phases.find((p) => p.status === 'running')?.id || phases[0]?.id || '';\n const activePhase = this.graph.phases.get(currentActiveId);\n\n const totalTasks = phases.reduce((sum, p) => sum + p.taskGraph.nodes.size, 0);\n const completedTasks = phases.reduce(\n (sum, p) =>\n sum + Array.from(p.taskGraph.nodes.values()).filter((t) => t.status === 'completed').length,\n 0,\n );\n\n // Shared task \u2192 board-card mapper. Carries assignee/timestamps so the kanban\n // can show who is on each card and how long it has been running.\n const mapTask = (t: import('@wrongstack/core/types').TaskNode) => ({\n id: t.id,\n title: t.title,\n description: t.description,\n status: t.status,\n priority: t.priority,\n type: t.type,\n estimateHours: t.estimateHours,\n actualHours: t.actualHours,\n assignee: t.assignee,\n tags: t.tags || [],\n startedAt: t.startedAt,\n completedAt: t.completedAt,\n });\n\n const phaseItems = phases.map((p) => {\n const nodes = Array.from(p.taskGraph.nodes.values());\n const done = nodes.filter((t) => t.status === 'completed').length;\n return {\n id: p.id,\n name: p.name,\n description: p.description,\n status: p.status,\n priority: p.priority,\n estimateHours: p.estimateHours,\n actualDurationMs: p.actualDurationMs,\n startedAt: p.startedAt,\n completedAt: p.completedAt,\n progressPercent: nodes.length > 0 ? Math.round((done / nodes.length) * 100) : 0,\n taskCount: nodes.length,\n completedTasks: done,\n assignedAgents: p.assignedAgents,\n isActive: p.id === currentActiveId,\n // Every phase carries its full task list so the board can render each\n // phase as a column (not just the selected one).\n tasks: nodes.map(mapTask),\n };\n });\n\n // Back-compat: the chat-area TaskBoard still reads the flat active-phase list.\n const taskItems = activePhase\n ? Array.from(activePhase.taskGraph.nodes.values()).map(mapTask)\n : [];\n\n const completedPhases = phases.filter((p) => p.status === 'completed').length;\n const failedPhases = phases.filter((p) => p.status === 'failed').length;\n const failedTasks = phases.reduce(\n (sum, p) =>\n sum + Array.from(p.taskGraph.nodes.values()).filter((t) => t.status === 'failed').length,\n 0,\n );\n\n // Surface the most recent failure so the board can show it (the store keeps a\n // `lastError` field the UI renders). Prefer the worktree integration error,\n // else a generic phase-failure note.\n const lastFailed = phases\n .filter((p) => p.status === 'failed')\n .sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0))[0];\n const lastError = lastFailed\n ? `${lastFailed.name}: ${(lastFailed.metadata?.integrationError as string | undefined) ?? 'phase failed'}`\n : null;\n\n return {\n title: this.graph.title,\n // Full operator prompt, shown verbatim in a dedicated goal block (the\n // title is only a short derived heading). Fall back to the title for\n // legacy boards saved before the title/goal split.\n goal: this.graph.description || this.graph.title,\n phases: phaseItems,\n tasks: taskItems,\n activePhaseId: currentActiveId,\n overallPercent: phases.length > 0 ? Math.round((completedPhases / phases.length) * 100) : 0,\n autonomous: this.graph.autonomous,\n totalTasks,\n completedTasks,\n // Structured progress + lastError consumed by the goal store (were\n // defined client-side but never sent, so they stayed null on the board).\n progress: {\n totalPhases: phases.length,\n completed: completedPhases,\n failed: failedPhases,\n totalTasks,\n completedTasks,\n failedTasks,\n },\n lastError,\n multiBoard: this.graph.multiBoard ?? false,\n verifyTasks: this.graph.verifyTasks ?? false,\n chimeraReview: this.graph.chimeraReview ?? false,\n };\n }\n\n private sendState(client: WSClient): void {\n if (!this.graph) return;\n const state = this.buildState();\n this.send(client, { type: 'goal.state', payload: state });\n }\n\n private broadcast(msg: { type: string; payload: unknown }): void {\n const data = JSON.stringify(msg);\n for (const client of this.clients) {\n sendSerialized(client.ws, data);\n }\n }\n\n private send(client: WSClient, msg: { type: string; payload: unknown }): void {\n sendSerialized(client.ws, JSON.stringify(msg));\n }\n}\n", "import { execFile } from 'node:child_process';\n\nconst GIT_TIMEOUT_MS = 10_000;\nconst GIT_MAX_OUTPUT_BYTES = 1024 * 1024;\n\n/** Run a small read-only git query without blocking the WebUI event loop. */\nexport function gitStdout(cwd: string, args: readonly string[]): Promise<string | null> {\n return new Promise((resolve) => {\n execFile(\n 'git',\n [...args],\n {\n cwd,\n encoding: 'utf8',\n windowsHide: true,\n timeout: GIT_TIMEOUT_MS,\n maxBuffer: GIT_MAX_OUTPUT_BYTES,\n },\n (error, stdout) => resolve(error ? null : stdout),\n );\n });\n}\n\nexport async function isGitWorkTree(cwd: string): Promise<boolean> {\n const output = await gitStdout(cwd, ['rev-parse', '--is-inside-work-tree']);\n return output?.trim() === 'true';\n}\n", "import {\n addPlanItem,\n emptyPlan,\n getPlanTemplate,\n loadPlan,\n loadTasks,\n mutatePlan,\n mutateTasks,\n savePlan,\n setPlanItemStatus,\n} from '@wrongstack/core/storage';\nimport type { TodoItem } from '@wrongstack/core/agent';\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from '../types.js';\nimport { validatePlanTemplateUsePayload } from '../ws-payload-validation.js';\n\nexport interface WorklistContext {\n context: {\n todos: TodoItem[];\n meta: Record<string, unknown>;\n session: { id: string } | null;\n };\n send: (ws: WebSocket, msg: WSServerMessage) => void;\n broadcast: (msg: WSServerMessage) => void;\n replaceTodos?: ((todos: TodoItem[]) => void) | undefined;\n}\n\nexport interface WorklistMessage {\n type: string;\n payload?: unknown;\n}\n\nfunction sendResult(ctx: WorklistContext, ws: WebSocket, success: boolean, message: string): void {\n ctx.send(ws, { type: 'key.operation_result', payload: { success, message } });\n}\n\nfunction currentSessionId(ctx: WorklistContext): string {\n return ctx.context.session?.id ?? '';\n}\n\nfunction sessionPayload<T extends Record<string, unknown>>(\n ctx: WorklistContext,\n payload: T,\n): T & { sessionId: string } {\n const provided = payload['sessionId'];\n const sessionId =\n typeof provided === 'string' && provided.length > 0 ? provided : currentSessionId(ctx);\n return { ...payload, sessionId };\n}\n\nfunction planPathOf(ctx: WorklistContext): string | undefined {\n const value = ctx.context.meta['plan.path'];\n return typeof value === 'string' && value ? value : undefined;\n}\n\nfunction taskPathOf(ctx: WorklistContext): string | undefined {\n const value = ctx.context.meta['task.path'];\n return typeof value === 'string' && value ? value : undefined;\n}\n\nexport function handleTodosGet(ctx: WorklistContext, ws: WebSocket): void {\n ctx.send(ws, {\n type: 'todos.updated',\n payload: sessionPayload(ctx, { todos: [...ctx.context.todos] }),\n });\n}\n\nexport function handleTodosClear(ctx: WorklistContext, ws: WebSocket): void {\n ctx.replaceTodos?.([]);\n sendResult(ctx, ws, true, 'Todos cleared');\n ctx.broadcast({ type: 'todos.updated', payload: sessionPayload(ctx, { todos: [] }) });\n}\n\nexport function handleTodosRemove(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: { id?: string | undefined; index?: number | undefined } | undefined,\n): void {\n if (!payload) {\n sendResult(ctx, ws, false, 'Missing id or index');\n return;\n }\n const todos = ctx.context.todos;\n let targetIndex = -1;\n if (typeof payload.id === 'string') {\n targetIndex = todos.findIndex((todo) => todo.id === payload.id);\n } else if (typeof payload.index === 'number' && payload.index > 0) {\n targetIndex = payload.index - 1;\n }\n const removed = todos[targetIndex];\n if (targetIndex < 0 || !removed) {\n sendResult(ctx, ws, false, 'Todo not found');\n return;\n }\n const next = [...todos.slice(0, targetIndex), ...todos.slice(targetIndex + 1)];\n ctx.replaceTodos?.(next);\n sendResult(ctx, ws, true, `Removed: ${removed.content}`);\n ctx.broadcast({ type: 'todos.updated', payload: sessionPayload(ctx, { todos: next }) });\n}\n\nexport function handleTodoUpdate(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: { id: string; status?: TodoItem['status'] | undefined; activeForm?: string | undefined },\n): void {\n const index = ctx.context.todos.findIndex((todo) => todo.id === payload.id);\n const existing = ctx.context.todos[index];\n if (index === -1 || !existing) {\n sendResult(ctx, ws, false, 'Todo not found');\n return;\n }\n const next = [...ctx.context.todos];\n next[index] = {\n ...existing,\n status: payload.status ?? existing.status,\n activeForm: payload.activeForm !== undefined ? payload.activeForm : existing.activeForm,\n };\n ctx.replaceTodos?.(next);\n sendResult(ctx, ws, true, `Todo \"${existing.content}\" updated`);\n ctx.broadcast({ type: 'todos.updated', payload: sessionPayload(ctx, { todos: next }) });\n}\n\nexport async function handleTasksGet(ctx: WorklistContext, ws: WebSocket): Promise<void> {\n const taskPath = taskPathOf(ctx);\n if (!taskPath) {\n ctx.send(ws, {\n type: 'tasks.updated',\n payload: sessionPayload(ctx, { tasks: [], error: 'Task storage not configured.' }),\n });\n return;\n }\n try {\n const file = await loadTasks(taskPath);\n ctx.send(ws, {\n type: 'tasks.updated',\n payload: sessionPayload(ctx, { tasks: file?.tasks ?? [] }),\n });\n } catch {\n ctx.send(ws, { type: 'tasks.updated', payload: sessionPayload(ctx, { tasks: [] }) });\n }\n}\n\nexport async function handleTaskUpdate(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: {\n id: string;\n status: 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed';\n },\n): Promise<void> {\n const taskPath = taskPathOf(ctx);\n if (!taskPath) {\n sendResult(ctx, ws, false, 'Task storage not configured.');\n return;\n }\n try {\n const file = await mutateTasks(taskPath, currentSessionId(ctx), async (tasks) => {\n const task = tasks.tasks.find((candidate) => candidate.id === payload.id);\n if (!task) return tasks;\n task.status = payload.status;\n task.updatedAt = new Date().toISOString();\n return tasks;\n });\n sendResult(ctx, ws, true, `Task status updated to \"${payload.status}\".`);\n ctx.broadcast({\n type: 'tasks.updated',\n payload: sessionPayload(ctx, { tasks: file.tasks }),\n });\n } catch (error) {\n sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));\n }\n}\n\nexport async function handlePlanGet(ctx: WorklistContext, ws: WebSocket): Promise<void> {\n const planPath = planPathOf(ctx);\n const emptySnapshot = () => ({\n version: 1,\n sessionId: currentSessionId(ctx),\n updatedAt: new Date().toISOString(),\n items: [],\n });\n if (!planPath) {\n ctx.send(ws, {\n type: 'plan.updated',\n payload: sessionPayload(ctx, {\n plan: null,\n error: 'Plan storage is not configured for this session.',\n }),\n });\n return;\n }\n try {\n const plan = await loadPlan(planPath);\n ctx.send(ws, {\n type: 'plan.updated',\n payload: sessionPayload(ctx, { plan: plan ?? emptySnapshot() }),\n });\n } catch {\n ctx.send(ws, {\n type: 'plan.updated',\n payload: sessionPayload(ctx, { plan: emptySnapshot() }),\n });\n }\n}\n\nexport async function handlePlanTemplateUse(\n ctx: WorklistContext,\n ws: WebSocket,\n template: string,\n): Promise<void> {\n const planPath = planPathOf(ctx);\n if (!planPath) {\n sendResult(ctx, ws, false, 'Plan storage is not configured for this session.');\n return;\n }\n try {\n const templateDefinition = getPlanTemplate(template);\n if (!templateDefinition) {\n sendResult(ctx, ws, false, `Unknown template \"${template}\".`);\n return;\n }\n let plan = (await loadPlan(planPath)) ?? emptyPlan(currentSessionId(ctx));\n for (const item of templateDefinition.items) {\n ({ plan } = addPlanItem(plan, item.title, item.details));\n }\n await savePlan(planPath, plan);\n sendResult(\n ctx,\n ws,\n true,\n `Applied template \"${templateDefinition.name}\" \u2014 ${templateDefinition.items.length} items added.`,\n );\n ctx.broadcast({ type: 'plan.updated', payload: sessionPayload(ctx, { plan }) });\n } catch (error) {\n sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));\n }\n}\n\nexport async function handlePlanItemUpdate(\n ctx: WorklistContext,\n ws: WebSocket,\n payload: { target: string; status: 'open' | 'in_progress' | 'done' },\n): Promise<void> {\n const planPath = planPathOf(ctx);\n if (!planPath) {\n sendResult(ctx, ws, false, 'Plan storage is not configured for this session.');\n return;\n }\n try {\n let changed = false;\n const plan = await mutatePlan(planPath, currentSessionId(ctx), async (currentPlan) => {\n const before = currentPlan.updatedAt;\n const next = setPlanItemStatus(currentPlan, payload.target, payload.status);\n changed = next.updatedAt !== before;\n return next;\n });\n if (!changed) {\n sendResult(ctx, ws, false, `No plan item matched \"${payload.target}\".`);\n return;\n }\n sendResult(ctx, ws, true, `Plan item status updated to \"${payload.status}\".`);\n ctx.broadcast({ type: 'plan.updated', payload: sessionPayload(ctx, { plan }) });\n } catch (error) {\n sendResult(ctx, ws, false, error instanceof Error ? error.message : String(error));\n }\n}\n\nexport async function handleWorklistMessage(\n ctx: WorklistContext,\n ws: WebSocket,\n message: WorklistMessage,\n): Promise<void> {\n switch (message.type) {\n case 'todos.get':\n handleTodosGet(ctx, ws);\n return;\n case 'todos.clear':\n handleTodosClear(ctx, ws);\n return;\n case 'todos.remove':\n handleTodosRemove(ctx, ws, message.payload as { id?: string; index?: number } | undefined);\n return;\n case 'todo.update':\n handleTodoUpdate(\n ctx,\n ws,\n message.payload as {\n id: string;\n status?: TodoItem['status'];\n activeForm?: string;\n },\n );\n return;\n case 'tasks.get':\n await handleTasksGet(ctx, ws);\n return;\n case 'task.update':\n await handleTaskUpdate(\n ctx,\n ws,\n message.payload as {\n id: string;\n status: 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed';\n },\n );\n return;\n case 'plan.get':\n await handlePlanGet(ctx, ws);\n return;\n case 'plan.template_use': {\n const parsed = validatePlanTemplateUsePayload(message.payload);\n if (!parsed.ok) {\n sendResult(ctx, ws, false, parsed.message);\n return;\n }\n await handlePlanTemplateUse(ctx, ws, parsed.value.template);\n return;\n }\n case 'plan.item.update':\n await handlePlanItemUpdate(\n ctx,\n ws,\n message.payload as { target: string; status: 'open' | 'in_progress' | 'done' },\n );\n }\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface HostRouteHandlers {\n shutdown: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport async function handleHostRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: HostRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'webui.shutdown':\n await handlers.shutdown(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "/**\n * HTTP /api/analytics handler for the WebUI server.\n *\n * Accepts a batch of analytics events from the frontend, validates them,\n * and stores them for later aggregation. Events are kept in a small\n * in-memory ring buffer (last 1000) and can be retrieved via GET for\n * debugging or exported to an external system.\n *\n * The endpoint is intentionally simple: no persistent storage, no external\n * dependencies. If you need durable analytics, poll the GET endpoint\n * and ship the events to your own aggregation pipeline (PostHog,\n * Segment, etc.).\n */\nimport type * as http from 'node:http';\n\nexport interface AnalyticsEvent {\n event: string;\n category: string;\n label?: string | undefined;\n value?: number | undefined;\n metadata?: Record<string, unknown> | undefined;\n timestamp: string;\n sessionId?: string | undefined;\n userAgent?: string | undefined;\n}\n\nconst EVENT_BUFFER: AnalyticsEvent[] = [];\nconst MAX_BUFFER_SIZE = 1000;\nexport const ANALYTICS_MAX_BODY_BYTES = 256 * 1024;\nexport const ANALYTICS_MAX_EVENT_BYTES = 32 * 1024;\nconst ANALYTICS_MAX_NAME_CHARS = 256;\nconst ANALYTICS_MAX_LABEL_CHARS = 2_048;\nconst ANALYTICS_MAX_USER_AGENT_CHARS = 512;\n\nclass AnalyticsBodyTooLargeError extends Error {}\n\n// Running counters so /summary is O(1) instead of O(n). Maintained alongside\n// the ring buffer; reset together with the buffer (see clearAnalyticsBuffer).\nconst EVENT_COUNTS = new Map<string, number>();\nconst CATEGORY_COUNTS = new Map<string, number>();\n\nfunction incCount(map: Map<string, number>, key: string): void {\n map.set(key, (map.get(key) ?? 0) + 1);\n}\n\nfunction decCount(map: Map<string, number>, key: string): void {\n const next = (map.get(key) ?? 0) - 1;\n if (next <= 0) {\n map.delete(key);\n } else {\n map.set(key, next);\n }\n}\n\nfunction pushEvent(event: AnalyticsEvent): void {\n EVENT_BUFFER.push(event);\n incCount(EVENT_COUNTS, event.event);\n incCount(CATEGORY_COUNTS, event.category);\n // Cap the ring buffer; decrement the counter for the evicted event.\n if (EVENT_BUFFER.length > MAX_BUFFER_SIZE) {\n const evicted = EVENT_BUFFER.shift();\n if (evicted) {\n decCount(EVENT_COUNTS, evicted.event);\n decCount(CATEGORY_COUNTS, evicted.category);\n }\n }\n}\n\nfunction parseBody(req: http.IncomingMessage): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let body = '';\n let bodyBytes = 0;\n let tooLarge = false;\n req.on('data', (chunk: Buffer) => {\n bodyBytes += chunk.length;\n if (bodyBytes > ANALYTICS_MAX_BODY_BYTES) {\n tooLarge = true;\n body = '';\n return;\n }\n if (tooLarge) return;\n body += chunk.toString('utf-8');\n });\n req.on('end', () => {\n if (tooLarge) {\n reject(new AnalyticsBodyTooLargeError('Analytics request body too large'));\n return;\n }\n try {\n resolve(JSON.parse(body));\n } catch {\n reject(new Error('Invalid JSON'));\n }\n });\n req.on('error', reject);\n });\n}\n\nfunction isValidEvent(obj: unknown): obj is AnalyticsEvent {\n if (typeof obj !== 'object' || obj === null) return false;\n const e = obj as Record<string, unknown>;\n const shapeValid =\n typeof e.event === 'string' &&\n e.event.length > 0 &&\n e.event.length <= ANALYTICS_MAX_NAME_CHARS &&\n typeof e.category === 'string' &&\n e.category.length > 0 &&\n e.category.length <= ANALYTICS_MAX_NAME_CHARS &&\n typeof e.timestamp === 'string' &&\n e.timestamp.length <= 128 &&\n (e.label === undefined ||\n (typeof e.label === 'string' && e.label.length <= ANALYTICS_MAX_LABEL_CHARS)) &&\n (e.sessionId === undefined ||\n (typeof e.sessionId === 'string' && e.sessionId.length <= ANALYTICS_MAX_NAME_CHARS)) &&\n (e.value === undefined || (typeof e.value === 'number' && Number.isFinite(e.value))) &&\n (e.metadata === undefined ||\n (typeof e.metadata === 'object' && e.metadata !== null && !Array.isArray(e.metadata)));\n if (!shapeValid) return false;\n try {\n return Buffer.byteLength(JSON.stringify(obj), 'utf8') <= ANALYTICS_MAX_EVENT_BYTES;\n } catch {\n return false;\n }\n}\n\n/** POST /api/analytics \u2014 ingest a batch of events from the frontend. */\nexport async function handleApiAnalyticsPost(\n res: http.ServerResponse,\n req: http.IncomingMessage,\n): Promise<void> {\n try {\n const body = await parseBody(req);\n const events = Array.isArray(body) ? body : [body];\n const validEvents: AnalyticsEvent[] = [];\n const rejected: number[] = [];\n\n for (let i = 0; i < events.length; i++) {\n const evt = events[i];\n if (isValidEvent(evt)) {\n // Enrich with server-side metadata\n const enriched: AnalyticsEvent = {\n ...evt,\n userAgent: req.headers['user-agent']?.slice(0, ANALYTICS_MAX_USER_AGENT_CHARS),\n };\n pushEvent(enriched);\n validEvents.push(enriched);\n } else {\n rejected.push(i);\n }\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n accepted: validEvents.length,\n rejected: rejected.length,\n rejectedIndices: rejected,\n }),\n );\n } catch (error) {\n const tooLarge = error instanceof AnalyticsBodyTooLargeError;\n res.writeHead(tooLarge ? 413 : 400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: tooLarge ? 'Request body too large' : 'Invalid JSON body' }));\n }\n}\n\n/** GET /api/analytics \u2014 retrieve the last N events (debug/export). */\nexport async function handleApiAnalyticsGet(res: http.ServerResponse, url: URL): Promise<void> {\n const rawLimit = Number.parseInt(url.searchParams.get('limit') ?? '100', 10);\n const limit = Math.min(1000, Math.max(1, Number.isFinite(rawLimit) ? rawLimit : 100));\n const events = EVENT_BUFFER.slice(-limit);\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ events, total: EVENT_BUFFER.length }));\n}\n\n/** GET /api/analytics/summary \u2014 aggregated stats for quick inspection. */\nexport async function handleApiAnalyticsSummary(res: http.ServerResponse): Promise<void> {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n totalEvents: EVENT_BUFFER.length,\n uniqueEvents: EVENT_COUNTS.size,\n uniqueCategories: CATEGORY_COUNTS.size,\n eventBreakdown: Object.fromEntries(EVENT_COUNTS),\n categoryBreakdown: Object.fromEntries(CATEGORY_COUNTS),\n oldestTimestamp: EVENT_BUFFER[0]?.timestamp ?? null,\n newestTimestamp: EVENT_BUFFER[EVENT_BUFFER.length - 1]?.timestamp ?? null,\n }),\n );\n}\n\n/** Clear the in-memory buffer (useful for testing). */\nexport function clearAnalyticsBuffer(): void {\n EVENT_BUFFER.length = 0;\n EVENT_COUNTS.clear();\n CATEGORY_COUNTS.clear();\n}\n\n/** Get a snapshot of the buffer (useful for testing). */\nexport function getAnalyticsBuffer(): readonly AnalyticsEvent[] {\n return [...EVENT_BUFFER];\n}\n", "/**\n * Static-file HTTP server for the WebUI / SimpleUI React frontends.\n *\n * Design:\n * - **Single port \u2014 shared HTTP + WebSocket.** A single port serves both the\n * static frontend and the WebSocket protocol. See the port-utils module.\n * - **CSP**: `connect-src 'self'` covers the core same-origin case. For loopback\n * binds (127.0.0.1 / localhost) we also add explicit `ws://`/`wss://` entries\n * so browsers that strictly separate `ws:` from `http:` in CSP `connect-src`\n * matching still allow WS upgrades. These loopback entries are safe because\n * they only open connections to the local machine. Tunnel/proxy setups use\n * `publicWsUrl` for the single external origin.\n * - **Path-traversal guard**: `path.join` alone does NOT prevent\n * `%2e%2e%2f` escapes (the `URL` constructor decodes percent-encoding\n * before we see the path). We re-`resolve` the candidate and verify it\n * stays under `distDir`.\n * - **Access auth**: on non-loopback binds, all HTTP routes require the same\n * shared token as the WS upgrade, accepted via `?token=...`, `X-WS-Token`,\n * or the `ws_token` HttpOnly cookie. This protects the React UI and the\n * `/api/*` control/read endpoints when `WS_HOST=0.0.0.0`.\n *\n * Extracted from `index.ts` so the static-serve concern can be tested\n * with a tiny fake `distDir` and asserted on path-traversal, MIME\n * matching, and CSP header presence.\n */\nimport * as fs from 'node:fs/promises';\nimport * as http from 'node:http';\nimport * as path from 'node:path';\nimport * as v8 from 'node:v8';\nimport { getIndexState } from '@wrongstack/tools';\nimport {\n handleCodemapFiles,\n handleCodemapPackages,\n handleCodemapSymbols,\n} from './codemap-handlers.js';\nimport {\n type DeadCodeHandlerDeps,\n handleDeadCodeActionPlan,\n handleDeadCodeScan,\n} from './deadcode-handlers.js';\nimport {\n handleApiAnalyticsGet,\n handleApiAnalyticsPost,\n handleApiAnalyticsSummary,\n} from './http-server/analytics-handler.js';\nimport {\n handleApiFleetBroadcast,\n handleApiSessionAgents,\n handleApiSessionEvents,\n handleApiSessionInterrupt,\n handleApiSessionMailbox,\n handleApiSessionMessage,\n handleApiSessions,\n} from './http-server/api-handlers.js';\nimport { readRecentProcessMemoryDiagnostics } from './memory-diagnostics.js';\nimport { generateProjectSlug } from './projects-manifest.js';\nimport type { FileWatcherMetrics } from './setup-events.js';\nimport {\n handleTechStackAnalyze,\n handleTechStackCancel,\n handleTechStackDependencyResearch,\n handleTechStackInventory,\n handleTechStackJobStatus,\n handleTechStackRemediationApply,\n handleTechStackRemediationPlan,\n handleTechStackReport,\n handleTechStackSnapshot,\n handleTechStackTrends,\n type TechStackEvent,\n} from './techstack-handlers.js';\nimport {\n extractTokenFromCookie,\n isLoopbackBind,\n isLoopbackHostname,\n tokenMatches,\n} from './ws-auth.js';\n\nexport interface CreateHttpServerOptions {\n /** Port to listen on. Defaults to 3456 (or the `PORT` env var). */\n port?: number | undefined;\n /** Host/interface to bind. Typically the loopback for the WebUI. */\n host: string;\n /** Resolved path to the directory containing the built React assets. */\n distDir: string;\n /**\n * Public WebSocket URL injected into the frontend. Use this behind tunnels or\n * reverse proxies where the browser-facing WS URL differs from host:wsPort.\n */\n publicWsUrl?: string | undefined;\n /**\n * Path to the global WrongStack root (~/.wrongstack). Used by the\n * /api/sessions and /api/sessions/:id/agents endpoints to read the\n * cross-process SessionRegistry.\n */\n globalRoot?: string | undefined;\n /**\n * Shared auth token for HTTP and WS access. Required for non-loopback\n * binds (LAN exposure). Loopback binds accept local browser access without\n * a token (the WS path's loopback-bootstrap policy \u2014 see ws-auth.ts).\n */\n apiToken?: string | undefined;\n /** Force HTTP token auth even on loopback binds, useful behind public tunnels. */\n requireToken?: boolean | undefined;\n /**\n * If true, the `/ws-auth` endpoint exchanges a `?token=` query param (or\n * `X-WS-Token` header) for an `HttpOnly` auth cookie. The cookie is then\n * sent automatically on the WS upgrade, closing the C-598 query-string\n * token exposure class. Default: true. Set to false to keep the legacy\n * URL-token-only flow (e.g. in tests that don't want cookie state).\n */\n enableWsCookie?: boolean | undefined;\n /**\n * Optional file watcher metrics object. When provided, the\n * /debug/watcher-metrics endpoint will be enabled to expose these metrics.\n */\n watcherMetrics?: FileWatcherMetrics | undefined;\n /**\n * Push-on-write hook. `POST /api/fleet/ping` (loopback only) invokes this to\n * trigger an immediate fleet re-broadcast, so a TUI/REPL's registry write\n * reaches the map without waiting on the file-watch/poll. Best-effort.\n */\n onFleetPing?: (() => void) | undefined;\n /**\n * Project root path for the codebase index. When provided, the\n * /api/codemap/* endpoints serve the dependency graph.\n */\n projectRoot?: string | undefined;\n /** Optional codebase-index directory override (tests). */\n indexDir?: string | undefined;\n /** Project-wide TechStack events projected onto the WebSocket transport. */\n onTechStackEvent?: ((event: TechStackEvent) => void) | undefined;\n /**\n * Live provider access for TechStack's LLM research stage. Omit it and\n * `analyze` stays deterministic (registry + advisories only).\n *\n * A getter, not a value \u2014 see `TechStackHandlerDeps.getLlm`.\n */\n getLlm?:\n | (() => { provider: import('@wrongstack/core/types').Provider; model: string } | undefined)\n | undefined;\n /** Permission-governed language_package bridge for approved remediation. */\n executePackageOperation?: import('./techstack-handlers.js').TechStackHandlerDeps['executePackageOperation'];\n}\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html',\n '.js': 'application/javascript',\n '.css': 'text/css',\n '.json': 'application/json',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.ico': 'image/x-icon',\n};\n\nfunction escapeHtmlAttr(value: string): string {\n return value\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\nexport function injectWsConfig(html: string, opts: { publicWsUrl?: string | undefined }): string {\n // The WebSocket now shares the HTTP server port, so the frontend derives\n // the WS URL from the page origin. No wrongstack-ws-port meta tag needed.\n const out = html;\n if (!opts.publicWsUrl || out.includes('name=\"wrongstack-ws-url\"')) return out;\n const tag = `<meta name=\"wrongstack-ws-url\" content=\"${escapeHtmlAttr(opts.publicWsUrl)}\" />`;\n if (out.includes('</head>')) {\n return out.replace('</head>', ` ${tag}\\n </head>`);\n }\n return `${tag}\\n${out}`;\n}\n\nfunction firstHeader(value: string | string[] | undefined): string | undefined {\n return Array.isArray(value) ? value[0] : value;\n}\n\nfunction wsTokenCookie(token: string): string {\n return `ws_token=${encodeURIComponent(token)}; HttpOnly; SameSite=Strict; Path=/; Max-Age=3600`;\n}\n\nfunction setAuthCookieHeaders(res: http.ServerResponse, token: string): void {\n res.setHeader('Set-Cookie', wsTokenCookie(token));\n res.setHeader('Cache-Control', 'no-store');\n}\n\nfunction setStaticSecurityHeaders(res: http.ServerResponse): void {\n res.setHeader('X-Content-Type-Options', 'nosniff');\n res.setHeader('X-Frame-Options', 'DENY');\n res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');\n}\n\nfunction requestToken(req: http.IncomingMessage, url: URL): string | undefined {\n return (\n url.searchParams.get('token') ??\n firstHeader(req.headers['x-ws-token']) ??\n extractTokenFromCookie(req.headers.cookie)\n );\n}\n\nfunction formatCspHostname(hostname: string): string {\n return hostname.includes(':') && !hostname.startsWith('[') ? `[${hostname}]` : hostname;\n}\n\nfunction cspSourceFromUrl(rawUrl: string): string | undefined {\n try {\n const url = new URL(rawUrl);\n if (url.protocol !== 'ws:' && url.protocol !== 'wss:') return undefined;\n return `${url.protocol}//${formatCspHostname(url.hostname)}${url.port ? `:${url.port}` : ''}`;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Extra `script-src` sources beyond `'self'`.\n *\n * The WrongStack frontend is a Vite build that ships **zero** inline scripts \u2014\n * every script is an external `.js` file covered by `'self'`. The app itself\n * needs no `'unsafe-inline'`.\n *\n * `'unsafe-inline'` is added only to suppress browser-extension console noise:\n * extensions (password managers, dark-mode readers, dev helpers) page-inject\n * inline bootstrap code, which would otherwise trip per-extension CSP\n * violations (`content.js:\u2026` with a sha256 of the extension's bytes). Adding\n * `'unsafe-inline'` once is simpler than chasing per-extension sha256 hashes\n * that change on every update.\n *\n * `'wasm-unsafe-eval'` is required for `shiki` (used by `rehype-pretty-code`\n * for code-block syntax highlighting in chat messages) \u2014 its oniguruma\n * grammar engine is compiled to WebAssembly. Without this source, every\n * markdown render that encounters a code block throws:\n * `CompileError: call to WebAssembly.instantiate() blocked by CSP`\n * `Error: \\`runSync\\` finished async. Use \\`run\\` instead`\n */\nconst EXTRA_SCRIPT_SOURCES: readonly string[] = [\"'wasm-unsafe-eval'\", \"'unsafe-inline'\"];\n\n/**\n * Build the Content-Security-Policy value for the WebUI.\n *\n * Adds explicit `ws://`/`wss://` entries for loopback addresses (`127.0.0.1`,\n * `localhost`) so `connect-src` covers WebSocket even in strict CSP\n * implementations that distinguish `ws:` from `http:` origins.\n *\n * @param publicWsUrl - Optional public-facing WS URL (tunnel/reverse-proxy).\n * When set, this origin is added to `connect-src` as a `ws://`/`wss://` entry.\n * @param host - The server bind host. When it matches a known loopback address\n * (`127.0.0.1`, `::1`, `[::1]`, or `localhost`), explicit `ws://`/`wss://`\n * entries for all three canonical loopback hosts are added to `connect-src`.\n * @param port - The server listen port. Defaults to `3456`. Unnecessary when\n * only publicWsUrl is used (no loopback branch).\n */\nexport function buildCspHeader(\n publicWsUrl?: string | undefined,\n host?: string,\n port?: number,\n): string {\n const connect = new Set([\"'self'\"]);\n const publicWsSource = publicWsUrl ? cspSourceFromUrl(publicWsUrl) : undefined;\n if (publicWsSource) connect.add(publicWsSource);\n // Explicit WS origins for loopback binds \u2014 some CSP implementations do not\n // equate `ws:`/`wss:` with `http:`/`https:` for the `'self'` keyword in\n // connect-src. Adding the canonical loopback addresses covers access via\n // 127.0.0.1, localhost, and [::1] regardless of which interface the server\n // is actually bound to (prevents drift from the ws-auth.ts policy).\n if (host && isLoopbackHostname(host)) {\n const p = port ?? 3456;\n // Guard against config typos (negative, zero, or impossibly large port).\n // This is NOT about ephemeral-port binds (listen(0)) \u2014 createHttpServer\n // resolves the real port from server.address() and passes it here.\n if (p > 0 && p <= 65535) {\n for (const h of ['127.0.0.1', 'localhost', '[::1]']) {\n connect.add(`ws://${h}:${p}`);\n connect.add(`wss://${h}:${p}`);\n }\n }\n }\n const scriptSrc = [\"'self'\", ...EXTRA_SCRIPT_SOURCES].join(' ');\n return (\n `default-src 'self'; script-src ${scriptSrc}; style-src 'self' 'unsafe-inline'; ` +\n `connect-src ${Array.from(connect).join(' ')}; ` +\n `img-src 'self' data:; font-src 'self' data:; worker-src 'self' blob:; object-src 'none'; ` +\n `base-uri 'self'; frame-ancestors 'none'; form-action 'self'`\n );\n}\n\n/**\n * Returns true when `candidate` (a fully-resolved absolute path) lies\n * strictly inside `distDir` (or equals it). Used to reject path-traversal\n * attempts after `path.resolve` has normalised any `..` segments.\n *\n * Exported so tests can assert the guard's contract without having to\n * also defeat the WHATWG URL normaliser (which strips `..` from the\n * path string *before* the request even reaches the server, making a\n * black-box test via fetch impossible).\n */\nexport function isInsideDist(candidate: string, distDir: string): boolean {\n const root = path.resolve(distDir);\n const resolved = path.resolve(candidate);\n return resolved === root || resolved.startsWith(root + path.sep);\n}\n\n/**\n * Decode a `:id` path segment captured by the `/api/sessions/:id/*` routes.\n *\n * Session ids are `YYYY-MM-DD/sess_<ULID>` \u2014 they contain a literal\n * `/`. The frontend builds the URL with `encodeURIComponent(sessionId)`, so\n * that slash arrives as `%2F`. The route regex `([^/]+)` correctly captures\n * the whole percent-encoded segment (there is no real `/` in `%2F`), but the\n * SessionRegistry is keyed by the *decoded* id \u2014 so the capture must be\n * `decodeURIComponent`d before lookup. Without this, every\n * `/api/sessions/:id/{events,message,agents}` request 404s (the registry has\n * `2026-\u2026/\u2026` but we looked up `2026-\u2026%2F\u2026`), which broke the Fleet HQ\n * watch-stream and the steer-message composer.\n *\n * Malformed percent-encoding (a lone `%`) makes `decodeURIComponent` throw;\n * fall back to the raw segment so the caller still gets a clean 404 rather\n * than a 500.\n */\nexport function decodeSessionId(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\n/**\n * Decode a URI-encoded path segment and return 400 on failure.\n * Use this when the caller should not silently accept malformed input.\n */\nfunction strictDecodeParam(segment: string, res: http.ServerResponse): string | null {\n try {\n return decodeURIComponent(segment);\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid URI encoding in path parameter' }));\n return null;\n }\n}\n\n/**\n * Create the static-file HTTP server. Returns the `http.Server` (not\n * listening yet) so the caller can attach to a `shutdown()` hook and\n * coordinate the listen() with the WebSocket bootstrap.\n */\nexport function createHttpServer(opts: CreateHttpServerOptions): http.Server {\n const port = opts.port ?? Number.parseInt(process.env['PORT'] ?? '3456', 10);\n const distDir = path.resolve(opts.distDir);\n // Loopback bind: no HTTP token required (mirrors WS loopback-bootstrap).\n // LAN bind: caller MUST supply a token; fail closed if it is absent.\n const requireAccessToken = Boolean(opts.requireToken) || !isLoopbackBind(opts.host);\n let techStackRuntime: Promise<{\n store: import('@wrongstack/techstack').TechStackStore;\n engine: import('@wrongstack/techstack').TechStackEngine;\n runningJobs: Map<string, AbortController>;\n }> | null = null;\n const getTechStackRuntime = async () => {\n if (!opts.projectRoot) throw new Error('Project root not configured');\n techStackRuntime ??= import('@wrongstack/techstack').then(\n ({ TechStackEngine, TechStackStore }) => {\n const store = new TechStackStore({ projectSlug: generateProjectSlug(opts.projectRoot!) });\n return { store, engine: new TechStackEngine(store), runningJobs: new Map() };\n },\n );\n return techStackRuntime;\n };\n\n const server = http.createServer(async (req, res) => {\n try {\n const url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);\n const providedAccessToken = requestToken(req, url);\n const accessTokenOk =\n Boolean(opts.apiToken) && tokenMatches(providedAccessToken, opts.apiToken ?? '');\n const shouldSetAuthCookie =\n Boolean(opts.apiToken) &&\n tokenMatches(url.searchParams.get('token') ?? undefined, opts.apiToken ?? '');\n\n // \u2500\u2500 API routes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // /ws-auth \u2014 exchange a one-shot token (header or query) for an\n // HttpOnly cookie. The browser then sends the cookie on the WS\n // upgrade automatically, closing C-598 (token-in-URL). Disabled\n // when `enableWsCookie: false` (tests, or operators who prefer\n // the URL-token flow for explicit dev).\n if (url.pathname === '/ws-auth' && req.method === 'GET' && (opts.enableWsCookie ?? true)) {\n // Accept the token from `?token=` query (browser navigation\n // from the server-printed URL) OR the `X-WS-Token` header\n // (scripted client).\n const provided = requestToken(req, url);\n if (!provided || !opts.apiToken || !tokenMatches(provided, opts.apiToken)) {\n res.writeHead(401, { 'Content-Type': 'text/plain' });\n res.end('Unauthorized');\n return;\n }\n // HttpOnly + SameSite=Strict + Path=/ \u2014 the cookie is immune to\n // XSS exfiltration (no JS access), cross-origin Referer leakage\n // (Strict blocks cross-site), and is scoped to this origin only.\n // No `Secure` flag: the dev server is plain HTTP on loopback,\n // and a Secure cookie over HTTP would not be sent by the browser.\n setAuthCookieHeaders(res, opts.apiToken);\n res.writeHead(200, { 'Content-Type': 'text/plain' });\n res.end('ok');\n return;\n }\n\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, {\n 'Content-Type': 'text/plain',\n 'Cache-Control': 'no-store',\n });\n res.end('Unauthorized');\n return;\n }\n\n if (shouldSetAuthCookie && opts.apiToken) {\n setAuthCookieHeaders(res, opts.apiToken);\n }\n\n // /api/fleet/ping \u2014 push-on-write nudge from a same-project TUI/REPL.\n // Triggers an immediate fleet re-broadcast of data the WS clients already\n // receive (no new disclosure, no persistent mutation). Same auth posture\n // as /api/sessions: open on loopback, token-gated on a LAN bind.\n if (url.pathname === '/api/fleet/ping' && req.method === 'POST') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n try {\n opts.onFleetPing?.();\n } catch {\n /* best-effort */\n }\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (url.pathname === '/api/sessions' && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n await handleApiSessions(res, opts.globalRoot);\n return;\n }\n\n const agentsMatch = url.pathname.match(/^\\/api\\/sessions\\/([^/]+)\\/agents$/);\n if (agentsMatch && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n await handleApiSessionAgents(res, opts.globalRoot, decodeSessionId(agentsMatch[1]!));\n return;\n }\n\n // /api/sessions/:id/events \u2014 replay another session's conversation +\n // tool stream (read-only) so the WebUI can *watch* a TUI/REPL running in\n // the same project. Reads that session's JSONL via the core session\n // reader; the browser re-fetches to tail it live.\n const eventsMatch = url.pathname.match(/^\\/api\\/sessions\\/([^/]+)\\/events$/);\n if (eventsMatch && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n const rawLimit = Number.parseInt(url.searchParams.get('limit') ?? '200', 10);\n const limit = Math.min(500, Math.max(1, Number.isFinite(rawLimit) ? rawLimit : 200));\n await handleApiSessionEvents(res, opts.globalRoot, decodeSessionId(eventsMatch[1]!), limit);\n return;\n }\n\n // /api/sessions/:id/message \u2014 send a steering message into another\n // session's mailbox. Its running agent injects pending mailbox messages\n // before each LLM call, so this is two-way control: the WebUI steers a\n // TUI/REPL working in the same project. Loopback-open, token-gated on LAN.\n const msgMatch = url.pathname.match(/^\\/api\\/sessions\\/([^/]+)\\/message$/);\n if (msgMatch && req.method === 'POST') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n await handleApiSessionMessage(res, req, opts.globalRoot, decodeSessionId(msgMatch[1]!));\n return;\n }\n\n // /api/sessions/:id/mailbox \u2014 the human<->leader thread (read-receipts +\n // replies). Makes the two-way loop visible in Fleet HQ.\n const mailboxMatch = url.pathname.match(/^\\/api\\/sessions\\/([^/]+)\\/mailbox$/);\n if (mailboxMatch && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n await handleApiSessionMailbox(res, opts.globalRoot, decodeSessionId(mailboxMatch[1]!));\n return;\n }\n\n // /api/sessions/:id/interrupt \u2014 cooperative stop (control message).\n const interruptMatch = url.pathname.match(/^\\/api\\/sessions\\/([^/]+)\\/interrupt$/);\n if (interruptMatch && req.method === 'POST') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n await handleApiSessionInterrupt(\n res,\n req,\n opts.globalRoot,\n decodeSessionId(interruptMatch[1]!),\n );\n return;\n }\n\n // /api/fleet/broadcast \u2014 one message to every live session's leader.\n if (url.pathname === '/api/fleet/broadcast' && req.method === 'POST') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n await handleApiFleetBroadcast(res, req, opts.globalRoot);\n return;\n }\n\n // /api/analytics \u2014 ingest frontend analytics events.\n // POST: accept a batch of events. GET: retrieve recent events.\n // GET /api/analytics/summary: aggregated stats.\n if (url.pathname === '/api/analytics' && req.method === 'POST') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n await handleApiAnalyticsPost(res, req);\n return;\n }\n if (url.pathname === '/api/analytics' && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n await handleApiAnalyticsGet(res, url);\n return;\n }\n if (url.pathname === '/api/analytics/summary' && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n await handleApiAnalyticsSummary(res);\n return;\n }\n\n // \u2500\u2500 CodeMap endpoints \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Serve the dependency graph at three drill-down levels. All read-only\n // GET \u2014 the graph is derived from the SQLite codebase index, so these\n // are safe behind the same access-token gate as other /api routes.\n if (url.pathname === '/api/codemap/packages' && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n if (!opts.projectRoot) {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Project root not configured' }));\n return;\n }\n await handleCodemapPackages(res, {\n projectRoot: opts.projectRoot,\n ...(opts.indexDir ? { indexDir: opts.indexDir } : {}),\n });\n return;\n }\n\n if (url.pathname === '/api/codemap/files' && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n if (!opts.projectRoot) {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Project root not configured' }));\n return;\n }\n const pkg = url.searchParams.get('package') ?? '';\n await handleCodemapFiles(\n res,\n {\n projectRoot: opts.projectRoot,\n ...(opts.indexDir ? { indexDir: opts.indexDir } : {}),\n },\n pkg,\n );\n return;\n }\n\n if (url.pathname === '/api/codemap/symbols' && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n if (!opts.projectRoot) {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Project root not configured' }));\n return;\n }\n const file = url.searchParams.get('file') ?? '';\n await handleCodemapSymbols(\n res,\n {\n projectRoot: opts.projectRoot,\n ...(opts.indexDir ? { indexDir: opts.indexDir } : {}),\n },\n file,\n );\n return;\n }\n\n // \u2500\u2500 Dead-Code Scan endpoints \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (url.pathname === '/api/deadcode/scan' && req.method === 'POST') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n if (!opts.projectRoot) {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Project root not configured' }));\n return;\n }\n const deadCodeDeps: DeadCodeHandlerDeps = {\n projectRoot: opts.projectRoot,\n ...(opts.indexDir ? { indexDir: opts.indexDir } : {}),\n };\n await handleDeadCodeScan(res, deadCodeDeps, req);\n return;\n }\n\n if (url.pathname === '/api/deadcode/action-plan' && req.method === 'POST') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n if (!opts.projectRoot) {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Project root not configured' }));\n return;\n }\n const deadCodeDeps: DeadCodeHandlerDeps = {\n projectRoot: opts.projectRoot,\n ...(opts.indexDir ? { indexDir: opts.indexDir } : {}),\n };\n await handleDeadCodeActionPlan(res, deadCodeDeps, req);\n return;\n }\n\n // \u2500\u2500 TechStack endpoints \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n if (url.pathname.startsWith('/api/techstack/')) {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n if (!opts.projectRoot) {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Project root not configured' }));\n return;\n }\n try {\n const runtime = await getTechStackRuntime();\n const deps = {\n projectId: opts.projectRoot,\n projectRoot: opts.projectRoot,\n store: runtime.store,\n engine: runtime.engine,\n runningJobs: runtime.runningJobs,\n emit: opts.onTechStackEvent,\n getLlm: opts.getLlm,\n executePackageOperation: opts.executePackageOperation,\n };\n if (url.pathname === '/api/techstack/snapshot' && req.method === 'GET') {\n handleTechStackSnapshot(res, deps);\n return;\n }\n if (url.pathname === '/api/techstack/inventory' && req.method === 'POST') {\n handleTechStackInventory(res, deps);\n return;\n }\n if (url.pathname === '/api/techstack/analyze' && req.method === 'POST') {\n handleTechStackAnalyze(res, deps);\n return;\n }\n if (url.pathname === '/api/techstack/trends' && req.method === 'GET') {\n await handleTechStackTrends(res, deps);\n return;\n }\n if (url.pathname === '/api/techstack/remediation' && req.method === 'GET') {\n await handleTechStackRemediationPlan(res, deps);\n return;\n }\n if (url.pathname === '/api/techstack/remediation/apply' && req.method === 'POST') {\n await handleTechStackRemediationApply(req, res, deps);\n return;\n }\n const cancelMatch = /^\\/api\\/techstack\\/jobs\\/([^/]+)\\/cancel$/.exec(url.pathname);\n if (cancelMatch && req.method === 'POST') {\n const id = strictDecodeParam(cancelMatch[1]!, res);\n if (id === null) return;\n handleTechStackCancel(res, deps, id);\n return;\n }\n const jobMatch = /^\\/api\\/techstack\\/jobs\\/([^/]+)$/.exec(url.pathname);\n if (jobMatch && req.method === 'GET') {\n const id = strictDecodeParam(jobMatch[1]!, res);\n if (id === null) return;\n handleTechStackJobStatus(res, deps, id);\n return;\n }\n const reportMatch = /^\\/api\\/techstack\\/reports\\/([^/]+)$/.exec(url.pathname);\n if (reportMatch && req.method === 'GET') {\n const id = strictDecodeParam(reportMatch[1]!, res);\n if (id === null) return;\n const fmt = url.searchParams.get('format') === 'json' ? 'json' : 'md';\n handleTechStackReport(res, deps, id, fmt);\n return;\n }\n const researchMatch = /^\\/api\\/techstack\\/deps\\/([^/]+)\\/research$/.exec(url.pathname);\n if (researchMatch && req.method === 'POST') {\n const pkg = strictDecodeParam(researchMatch[1]!, res);\n if (pkg === null) return;\n await handleTechStackDependencyResearch(res, deps, pkg);\n return;\n }\n } catch (error) {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'TechStack store unavailable',\n detail: error instanceof Error ? error.message : String(error),\n }),\n );\n return;\n }\n }\n\n // Debug endpoint: /debug/watcher-metrics\n // Returns file watcher metrics as JSON. Protected by the same HTTP access\n // token when the server is bound beyond loopback.\n if (url.pathname === '/debug/watcher-metrics' && req.method === 'GET') {\n if (requireAccessToken && !accessTokenOk) {\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Unauthorized' }));\n return;\n }\n if (opts.watcherMetrics) {\n // Update computed fields before returning\n const avgDelay =\n opts.watcherMetrics.broadcastsSent > 0\n ? opts.watcherMetrics.totalDebounceDelayMs / opts.watcherMetrics.broadcastsSent\n : 0;\n const response = {\n ...opts.watcherMetrics,\n averageDebounceDelayMs: avgDelay,\n timestamp: Date.now(),\n };\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(response));\n } else {\n res.writeHead(503, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'File watcher metrics not available' }));\n }\n return;\n }\n\n // Current WebUI server process memory. This intentionally reports the\n // Node process behind the page (not the browser tab's JavaScript heap),\n // so operators can spot long-running RSS/heap growth from the UI.\n if (url.pathname === '/debug/system' && req.method === 'GET') {\n const processes = await readRecentProcessMemoryDiagnostics(opts.globalRoot);\n res.writeHead(200, {\n 'Content-Type': 'application/json',\n 'Cache-Control': 'no-store',\n });\n res.end(\n JSON.stringify({\n pid: process.pid,\n memoryUsage: process.memoryUsage(),\n heapLimit: v8.getHeapStatistics().heap_size_limit,\n uptime: process.uptime(),\n cpuUsage: process.cpuUsage(),\n codebaseIndexServer: getIndexState().server,\n processes,\n timestamp: Date.now(),\n }),\n );\n return;\n }\n\n let filePath: string;\n\n if (url.pathname === '/' || url.pathname === '') {\n filePath = path.join(distDir, 'index.html');\n } else {\n filePath = path.join(distDir, url.pathname);\n }\n\n // Path traversal guard: the resolved path must stay inside distDir.\n // WHATWG URL leaves percent-encoding alone in `url.pathname` (it\n // does not decode `%2e%2e` to `..`), so percent-encoded escapes\n // are *not* a concern here \u2014 but unencoded `..` segments are\n // normalised by `path.resolve` and would walk the candidate up\n // out of distDir. `isInsideDist` catches that.\n const resolvedPath = path.resolve(filePath);\n if (!isInsideDist(resolvedPath, distDir)) {\n res.writeHead(403, { 'Content-Type': 'text/plain' });\n res.end('Forbidden');\n return;\n }\n\n const ext = path.extname(resolvedPath);\n const contentType = MIME_TYPES[ext] ?? 'application/octet-stream';\n res.setHeader('Content-Type', contentType);\n setStaticSecurityHeaders(res);\n\n if (ext === '.html') {\n if (!shouldSetAuthCookie) res.setHeader('Cache-Control', 'no-cache');\n res.setHeader('Content-Security-Policy', buildCspHeader(opts.publicWsUrl, opts.host, port));\n // The frontend derives the WebSocket URL from the page origin since\n // WS now shares the HTTP server port. No WS-port injection needed.\n const html = await fs.readFile(resolvedPath, 'utf8');\n res.writeHead(200);\n res.end(injectWsConfig(html, { publicWsUrl: opts.publicWsUrl }));\n return;\n }\n\n if (!shouldSetAuthCookie) {\n res.setHeader(\n 'Cache-Control',\n url.pathname.startsWith('/assets/')\n ? 'public, max-age=31536000, immutable'\n : 'public, max-age=3600',\n );\n }\n const fileContent = await fs.readFile(resolvedPath);\n res.writeHead(200);\n res.end(fileContent);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n // SPA fallback: serve index.html so client-side routing still works.\n try {\n const html = await fs.readFile(path.join(distDir, 'index.html'), 'utf8');\n setStaticSecurityHeaders(res);\n res.writeHead(200, {\n 'Content-Type': 'text/html',\n 'Content-Security-Policy': buildCspHeader(opts.publicWsUrl, opts.host, port),\n });\n res.end(injectWsConfig(html, { publicWsUrl: opts.publicWsUrl }));\n } catch {\n res.writeHead(404);\n res.end('Not found');\n }\n } else {\n console.error({ url: req.url, err });\n res.writeHead(500);\n res.end('Server error');\n }\n }\n });\n\n server.once('close', () => {\n void techStackRuntime\n ?.then(({ store, runningJobs }) => {\n for (const controller of runningJobs.values()) controller.abort();\n runningJobs.clear();\n store.close();\n })\n .catch(() => undefined);\n });\n return server;\n}\n", "/**\n * CodeMap HTTP handlers \u2014 serve the dependency graph at three drill-down\n * levels (package \u2192 file \u2192 symbol) from the codebase index SQLite store.\n *\n * Each handler queries via the graph services and returns JSON. Results are\n * cached in-process and invalidated when `index.db` mtime/size changes.\n *\n * Endpoints:\n * GET /api/codemap/packages \u2014 package-level graph\n * GET /api/codemap/files?package=<name> \u2014 file-level graph for one package\n * GET /api/codemap/symbols?file=<path> \u2014 symbol-level graph for one file\n */\nimport type * as http from 'node:http';\nimport type { CodeMapGraph } from '@wrongstack/tools';\nimport { fileGraphService, packageGraphService, symbolGraphService } from '@wrongstack/tools';\nimport {\n codemapCacheKey,\n getCachedCodemapBody,\n indexDbVersion,\n setCachedCodemapBody,\n} from './codemap-cache.js';\n\nexport interface CodemapHandlerDeps {\n projectRoot: string;\n /** Optional index directory override (tests, custom wiring). */\n indexDir?: string | undefined;\n}\n\nfunction sendJsonBody(\n res: http.ServerResponse,\n status: number,\n body: string,\n cacheStatus: 'HIT' | 'MISS' | 'BYPASS',\n): void {\n res.writeHead(status, {\n 'Content-Type': 'application/json',\n 'X-Codemap-Cache': cacheStatus,\n });\n res.end(body);\n}\n\nfunction sendJson(\n res: http.ServerResponse,\n status: number,\n data: unknown,\n cacheStatus: 'HIT' | 'MISS' | 'BYPASS' = 'BYPASS',\n): void {\n sendJsonBody(res, status, JSON.stringify(data), cacheStatus);\n}\n\nasync function serveCachedGraph(\n res: http.ServerResponse,\n deps: CodemapHandlerDeps,\n scope: string,\n compute: () => Promise<CodeMapGraph>,\n): Promise<void> {\n try {\n const version = indexDbVersion(deps.projectRoot, deps.indexDir);\n const key = codemapCacheKey(deps.projectRoot, deps.indexDir, scope);\n const hit = getCachedCodemapBody(key, version);\n if (hit !== undefined) {\n sendJsonBody(res, 200, hit, 'HIT');\n return;\n }\n const graph = await compute();\n const body = JSON.stringify(graph);\n if (version !== 'missing') {\n setCachedCodemapBody(key, version, body);\n }\n sendJsonBody(res, 200, body, 'MISS');\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // 503 when the index is not yet built (node:sqlite missing or empty DB)\n sendJson(res, 503, { error: 'CodeMap index unavailable', detail: msg }, 'BYPASS');\n }\n}\n\n/** GET /api/codemap/packages \u2014 workspace-level package dependency graph. */\nexport async function handleCodemapPackages(\n res: http.ServerResponse,\n deps: CodemapHandlerDeps,\n): Promise<void> {\n await serveCachedGraph(res, deps, 'packages', () =>\n packageGraphService({\n projectRoot: deps.projectRoot,\n ...(deps.indexDir ? { indexDir: deps.indexDir } : {}),\n }),\n );\n}\n\n/** GET /api/codemap/files?package=<name> \u2014 file-level graph within a package. */\nexport async function handleCodemapFiles(\n res: http.ServerResponse,\n deps: CodemapHandlerDeps,\n pkg: string,\n): Promise<void> {\n if (!pkg) {\n sendJson(res, 400, { error: 'Missing \"package\" query parameter' });\n return;\n }\n await serveCachedGraph(res, deps, `files:${pkg}`, () =>\n fileGraphService({\n projectRoot: deps.projectRoot,\n packageFilter: pkg,\n ...(deps.indexDir ? { indexDir: deps.indexDir } : {}),\n }),\n );\n}\n\n/** GET /api/codemap/symbols?file=<path> \u2014 symbol-level graph within a file. */\nexport async function handleCodemapSymbols(\n res: http.ServerResponse,\n deps: CodemapHandlerDeps,\n file: string,\n): Promise<void> {\n if (!file) {\n sendJson(res, 400, { error: 'Missing \"file\" query parameter' });\n return;\n }\n await serveCachedGraph(res, deps, `symbols:${file}`, () =>\n symbolGraphService({\n projectRoot: deps.projectRoot,\n fileFilter: file,\n ...(deps.indexDir ? { indexDir: deps.indexDir } : {}),\n }),\n );\n}\n", "/**\n * Dead-Code Scan HTTP handlers.\n *\n * POST /api/deadcode/scan \u2014 runs `runDeadCodeScan` from @wrongstack/tools\n * and returns structured results (deadSymbols, deadFiles, deadPackages).\n *\n * POST /api/deadcode/action-plan \u2014 converts scan results into an ordered\n * action plan with priority-sorted file groups for LLM execution.\n */\nimport * as path from 'node:path';\nimport type * as http from 'node:http';\n// Import from the subpath barrel so consuming packages resolve against\n// the already-built dist/codebase-index/index.js without rebuilding @wrongstack/tools.\nimport { runDeadCodeScan } from '@wrongstack/tools/codebase-index';\nimport type { DeadCodeScanOutput } from '@wrongstack/tools/codebase-index';\n\nexport interface DeadCodeHandlerDeps {\n projectRoot: string;\n indexDir?: string | undefined;\n}\n\n// \u2500\u2500\u2500 POST /api/deadcode/scan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface ScanRequestBody {\n indexDir?: string | undefined;\n entryPoints?: string[] | undefined;\n}\n\n/** Max accepted POST body size (10 MiB). Beyond this the connection is destroyed. */\nconst MAX_BODY_BYTES = 10 * 1024 * 1024;\n\nfunction readJsonBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let total = 0;\n req.on('data', (chunk: Buffer) => {\n total += chunk.length;\n if (total > MAX_BODY_BYTES) {\n req.destroy(new Error('Request body too large'));\n reject(new Error('Request body exceeds 10 MiB limit'));\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));\n req.on('error', (err) => reject(err));\n });\n}\n\nexport async function handleDeadCodeScan(\n res: http.ServerResponse,\n deps: DeadCodeHandlerDeps,\n req: http.IncomingMessage,\n): Promise<void> {\n try {\n let body: ScanRequestBody = {};\n const raw = await readJsonBody(req);\n if (raw) {\n try {\n body = JSON.parse(raw) as ScanRequestBody;\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid JSON body' }));\n return;\n }\n }\n\n // Validate client-supplied indexDir resolves inside the project root\n // to prevent path-traversal through the request body.\n const scanIndexDir = body.indexDir ?? deps.indexDir;\n if (scanIndexDir) {\n const resolvedRoot = path.resolve(deps.projectRoot);\n const resolvedIndex = path.resolve(deps.projectRoot, scanIndexDir);\n if (\n resolvedIndex !== resolvedRoot &&\n !resolvedIndex.startsWith(resolvedRoot + path.sep)\n ) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid indexDir: must be within project root' }));\n return;\n }\n }\n\n const result = runDeadCodeScan(deps.projectRoot, {\n indexDir: scanIndexDir,\n userEntryPoints: body.entryPoints,\n });\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(result));\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'Dead-code scan failed',\n detail: err instanceof Error ? err.message : String(err),\n }),\n );\n }\n}\n\n// \u2500\u2500\u2500 POST /api/deadcode/action-plan \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface ActionPlanFile {\n file: string;\n symbolCount: number;\n /** The kind of symbols to remove (for the LLM prompt). */\n symbols: string[];\n /** Suggested priority: 0 = dead package (highest impact), 1 = dead file, 2 = dead symbol. */\n priority: number;\n}\n\ninterface ActionPlan {\n summary: string;\n files: ActionPlanFile[];\n totalDeadSymbols: number;\n totalDeadFiles: number;\n totalDeadPackages: number;\n}\n\nexport function handleDeadCodeActionPlan(\n res: http.ServerResponse,\n _deps: DeadCodeHandlerDeps,\n req: http.IncomingMessage,\n): Promise<void> {\n return readJsonBody(req)\n .then((raw) => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid scan result JSON' }));\n return;\n }\n\n // Runtime shape check: buildActionPlan accesses deadPackages, deadFiles,\n // deadSymbols, and stats.dead \u2014 verify they exist before trusting the cast.\n if (\n !parsed ||\n typeof parsed !== 'object' ||\n !Array.isArray((parsed as Record<string, unknown>).deadPackages) ||\n !Array.isArray((parsed as Record<string, unknown>).deadFiles) ||\n !Array.isArray((parsed as Record<string, unknown>).deadSymbols)\n ) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error:\n 'Invalid scan result: missing or malformed required fields ' +\n '(deadPackages, deadFiles, deadSymbols)',\n }),\n );\n return;\n }\n\n const result = parsed as DeadCodeScanOutput;\n const plan = buildActionPlan(result);\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(plan));\n })\n .catch((err) => {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n error: 'Failed to read request body',\n detail: err instanceof Error ? err.message : String(err),\n }),\n );\n });\n}\n\nfunction buildActionPlan(result: DeadCodeScanOutput): ActionPlan {\n const files = new Map<string, ActionPlanFile>();\n\n // P0: Dead packages \u2014 all files in the package.\n for (const dp of result.deadPackages) {\n // The scan returns deadPackage objects; synthesize file entries.\n const pseudoFile: ActionPlanFile = {\n file: `${dp.package}/ (package)`,\n symbolCount: dp.fileCount,\n symbols: [`remove package ${dp.package} (${dp.fileCount} files, path: ${dp.path})`],\n priority: 0,\n };\n files.set(pseudoFile.file, pseudoFile);\n }\n\n // P1: Dead files \u2014 all symbols are unreferenced.\n for (const df of result.deadFiles) {\n const existing = files.get(df.file);\n if (existing) {\n // Already queued as part of a dead package \u2014 keep the higher priority.\n if (existing.priority > 1) existing.priority = 1;\n existing.symbolCount += df.symbolCount;\n continue;\n }\n files.set(df.file, {\n file: df.file,\n symbolCount: df.symbolCount,\n symbols: [`entire file (${df.symbolCount} symbols) is dead`],\n priority: 1,\n });\n }\n\n // P2: Individual dead symbols in otherwise-alive files.\n const deadInAliveFiles = new Map<string, string[]>();\n const deadFileSet = new Set(result.deadFiles.map((df) => df.file));\n for (const ds of result.deadSymbols) {\n if (deadFileSet.has(ds.file)) continue; // already counted in deadFiles\n const list = deadInAliveFiles.get(ds.file) ?? [];\n list.push(`${ds.kind} ${ds.name} (line ${ds.line})`);\n deadInAliveFiles.set(ds.file, list);\n }\n for (const [file, symbols] of deadInAliveFiles) {\n const existing = files.get(file);\n if (existing) {\n existing.symbols.push(...symbols);\n existing.symbolCount += symbols.length;\n continue;\n }\n files.set(file, {\n file,\n symbolCount: symbols.length,\n symbols,\n priority: 2,\n });\n }\n\n const sorted = [...files.values()].sort((a, b) => a.priority - b.priority || a.file.localeCompare(b.file));\n\n return {\n summary:\n `Dead-code scan found ${result.stats.dead} dead symbols across ` +\n `${result.deadFiles.length} dead files and ${result.deadPackages.length} dead packages. ` +\n `Action plan has ${sorted.length} file group(s) to address.`,\n files: sorted,\n totalDeadSymbols: result.stats.dead,\n totalDeadFiles: result.deadFiles.length,\n totalDeadPackages: result.deadPackages.length,\n };\n}\n", "/**\n * HTTP /api/* request handlers for the WebUI server \u2014 extracted from\n * http-server.ts to keep the static-serve/routing concern separate from the\n * (substantial) Fleet-HQ session/mailbox API. Every handler is a pure,\n * param-based function: it takes the Node req/res plus the globalRoot and reads\n * the cross-process SessionRegistry / project mailbox via dynamic core imports.\n * createHttpServer() in http-server.ts dispatches to these.\n */\nimport type * as http from 'node:http';\n\nexport async function handleApiSessions(\n res: http.ServerResponse,\n globalRoot: string | undefined,\n): Promise<void> {\n if (!globalRoot) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'SessionRegistry not available' }));\n return;\n }\n\n try {\n const { SessionRegistry } = await import('@wrongstack/core/storage');\n const registry = new SessionRegistry(globalRoot);\n const sessions = await registry.list();\n\n const result = sessions.map((s) => ({\n sessionId: s.sessionId,\n projectSlug: s.projectSlug,\n projectName: s.projectName,\n projectRoot: s.projectRoot,\n workingDir: s.workingDir,\n status: s.status,\n pid: s.pid,\n startedAt: s.startedAt,\n lastHeartbeatAt: s.lastHeartbeatAt,\n agentCount: s.agentCount,\n agents: s.agents.map((a) => ({\n id: a.id,\n name: a.name,\n status: a.status,\n currentTool: a.currentTool,\n iterations: a.iterations,\n toolCalls: a.toolCalls,\n lastActivityAt: a.lastActivityAt,\n })),\n }));\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(result));\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: String(err) }));\n }\n}\n\nexport async function handleApiSessionAgents(\n res: http.ServerResponse,\n globalRoot: string | undefined,\n sessionId: string,\n): Promise<void> {\n if (!globalRoot) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'SessionRegistry not available' }));\n return;\n }\n\n try {\n const { SessionRegistry } = await import('@wrongstack/core/storage');\n const registry = new SessionRegistry(globalRoot);\n const entry = await registry.get(sessionId);\n\n if (!entry) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Session not found' }));\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({\n sessionId: entry.sessionId,\n projectName: entry.projectName,\n status: entry.status,\n agents: entry.agents.map((a) => ({\n id: a.id,\n name: a.name,\n status: a.status,\n currentTool: a.currentTool,\n iterations: a.iterations,\n toolCalls: a.toolCalls,\n lastActivityAt: a.lastActivityAt,\n })),\n }));\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: String(err) }));\n }\n}\n\n/** One line in the session \"watch\" stream sent to the browser.\n * Rich enough for the frontend to render full tool call details,\n * markdown, and structured data \u2014 not just pre-clipped text. */\ninterface WatchEntry {\n ts: string;\n role: 'user' | 'assistant' | 'tool' | 'system' | 'error';\n /** Human-readable text summary (may be clipped for tool input/output). */\n text: string;\n /** Tool name (for tool-role entries). */\n tool?: string;\n /** Structured tool input (object or array \u2014 rendered by ToolInputView). */\n input?: unknown;\n /** Structured tool output (rendered as pre-formatted text / markdown). */\n output?: unknown;\n /** Wall-clock duration in ms (tool call / response). */\n durationMs?: number;\n /** Whether the tool/response had an error. */\n isError?: boolean;\n /** Tool use correlation id \u2014 pairs tool_call_start with tool_call_end. */\n toolUseId?: string;\n}\n\n/** Join the text blocks of a message content value into a single string. */\nfunction blocksToText(content: unknown): string {\n if (typeof content === 'string') return content;\n if (Array.isArray(content)) {\n return content\n .filter(\n (b): b is { type: string; text: string } =>\n !!b && typeof b === 'object' && (b as { type?: unknown }).type === 'text' &&\n typeof (b as { text?: unknown }).text === 'string',\n )\n .map((b) => b.text)\n .join('\\n');\n }\n return '';\n}\n\nfunction asString(v: unknown): string {\n if (typeof v === 'string') return v;\n try {\n return JSON.stringify(v, null, 2);\n } catch {\n return String(v);\n }\n}\n\n/** Map a raw session event to a watch entry. Returns rich structured data\n * for tool calls (input + output + duration) so the frontend can render\n * full detail via WatchMessageBubble \u2014 matching the main ChatView. */\nfunction mapWatchEntry(ev: Record<string, unknown>): WatchEntry | null {\n const ts = typeof ev['ts'] === 'string' ? (ev['ts'] as string) : '';\n switch (ev['type']) {\n case 'user_input': {\n const text = blocksToText(ev['content']);\n return text.trim() ? { ts, role: 'user', text } : null;\n }\n case 'llm_response': {\n const text = blocksToText(ev['content']);\n return text.trim() ? { ts, role: 'assistant', text } : null;\n }\n case 'tool_use':\n case 'tool_call_start': {\n const toolName = String(ev['name'] ?? 'tool');\n const input = ev['input'] ?? ev['args'];\n const text = input !== undefined && input !== null ? asString(input) : '';\n const toolUseId = typeof ev['id'] === 'string' ? ev['id'] : undefined;\n return {\n ts,\n role: 'tool',\n tool: toolName,\n text,\n input,\n ...(toolUseId !== undefined ? { toolUseId } : {}),\n };\n }\n case 'tool_call_end':\n case 'tool_result': {\n const isError = ev['isError'] === true;\n const content = ev['output'] ?? ev['content'];\n const outStr = content !== undefined && content !== null ? asString(content) : '';\n const durationMs = typeof ev['durationMs'] === 'number' ? ev['durationMs'] : undefined;\n const toolUseId = typeof ev['id'] === 'string' ? ev['id'] : undefined;\n const toolName = typeof ev['name'] === 'string' ? String(ev['name']) : '\u21B3 result';\n if (!outStr.trim() && !isError) return null;\n return {\n ts,\n role: isError ? 'error' : 'tool',\n tool: toolName,\n text: outStr,\n output: content,\n isError,\n ...(durationMs !== undefined ? { durationMs } : {}),\n ...(toolUseId !== undefined ? { toolUseId } : {}),\n };\n }\n case 'error':\n case 'provider_error':\n return { ts, role: 'error', text: String(ev['message'] ?? 'error') };\n case 'agent_spawned':\n return { ts, role: 'system', text: `spawned ${String(ev['role'] ?? 'agent')}` };\n case 'task_completed':\n return { ts, role: 'system', text: `task done: ${String(ev['title'] ?? '')}` };\n case 'task_failed':\n return { ts, role: 'system', text: `task failed: ${String(ev['title'] ?? '')}` };\n default:\n return null;\n }\n}\n\n/** Correlate tool_call_start + tool_call_end events by id and merge them\n * into unified WatchEntry entries with full input+output+duration.\n * Standalone events (unpaired) pass through as-is. */\nfunction correlateToolEvents(entries: WatchEntry[]): WatchEntry[] {\n const pending = new Map<string, WatchEntry>(); // toolUseId \u2192 start entry\n const result: WatchEntry[] = [];\n for (const e of entries) {\n if (e.role === 'tool' && e.toolUseId && e.output === undefined && e.durationMs === undefined) {\n // This is a tool_call_start with no result yet \u2014 stash it\n pending.set(e.toolUseId, e);\n continue;\n }\n if (e.toolUseId && pending.has(e.toolUseId)) {\n const start = pending.get(e.toolUseId)!;\n pending.delete(e.toolUseId);\n // Merge: keep the start's ts, tool name, and input; add the end's output/duration/error\n result.push({\n ts: start.ts,\n role: e.isError ? 'error' : 'tool',\n text: e.text || start.text,\n ...(e.isError !== undefined ? { isError: e.isError } : {}),\n ...(start.tool !== undefined ? { tool: start.tool } : {}),\n ...(start.input !== undefined ? { input: start.input } : {}),\n ...(e.output !== undefined ? { output: e.output } : {}),\n ...(e.durationMs !== undefined ? { durationMs: e.durationMs } : {}),\n ...(e.toolUseId !== undefined ? { toolUseId: e.toolUseId } : {}),\n });\n continue;\n }\n result.push(e);\n }\n // Unpaired start events: flush at the end\n for (const e of pending.values()) result.push(e);\n return result;\n}\n\nexport async function handleApiSessionEvents(\n res: http.ServerResponse,\n globalRoot: string | undefined,\n sessionId: string,\n limit: number,\n): Promise<void> {\n if (!globalRoot) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'SessionRegistry not available' }));\n return;\n }\n\n try {\n const { SessionRegistry, DefaultSessionStore, DefaultSessionReader } =\n await import('@wrongstack/core/storage');\n const { resolveWstackPaths } = await import('@wrongstack/core/utils');\n const registry = new SessionRegistry(globalRoot);\n const entry = await registry.get(sessionId);\n if (!entry) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Session not found' }));\n return;\n }\n\n const paths = resolveWstackPaths({ projectRoot: entry.projectRoot, globalRoot });\n const store = new DefaultSessionStore({ dir: paths.projectSessions });\n const reader = new DefaultSessionReader({ store });\n\n const rawEntries: WatchEntry[] = [];\n for await (const ev of reader.replay(sessionId)) {\n const mapped = mapWatchEntry(ev as never as Record<string, unknown>);\n if (mapped) rawEntries.push(mapped);\n }\n // Correlate paired tool call start+end events for rich combined rendering\n const all = correlateToolEvents(rawEntries);\n const tail = all.slice(-limit);\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(\n JSON.stringify({\n sessionId,\n status: entry.status,\n clientType: entry.clientType,\n projectName: entry.projectName,\n total: all.length,\n entries: tail,\n }),\n );\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: String(err) }));\n }\n}\n\n/** Read and JSON-parse a request body, capped at 64 KiB. */\nfunction readJsonBody(req: http.IncomingMessage): Promise<Record<string, unknown>> {\n return new Promise((resolve, reject) => {\n let data = '';\n req.on('data', (chunk) => {\n data += chunk;\n if (data.length > 64_000) {\n reject(new Error('Request body too large'));\n req.destroy();\n }\n });\n req.on('end', () => {\n try {\n resolve(data ? (JSON.parse(data) as Record<string, unknown>) : {});\n } catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)));\n }\n });\n req.on('error', reject);\n });\n}\n\nexport async function handleApiSessionMessage(\n res: http.ServerResponse,\n req: http.IncomingMessage,\n globalRoot: string | undefined,\n sessionId: string,\n): Promise<void> {\n if (!globalRoot) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'SessionRegistry not available' }));\n return;\n }\n\n let body: Record<string, unknown>;\n try {\n body = await readJsonBody(req);\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid request body' }));\n return;\n }\n\n const text = typeof body['text'] === 'string' ? (body['text'] as string).trim() : '';\n if (!text) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'text is required' }));\n return;\n }\n const from =\n typeof body['from'] === 'string' && (body['from'] as string).trim()\n ? (body['from'] as string).trim()\n : 'human@webui';\n\n // Message kind from Fleet HQ's composer. The agent-loop injects every type\n // before its next LLM call; 'ask'/'assign' carry a stronger call-to-action\n // in the injected block (see buildMailboxBlock). Default 'steer'.\n const ALLOWED = new Set(['steer', 'ask', 'assign', 'note', 'btw']);\n const rawType = typeof body['type'] === 'string' ? (body['type'] as string) : 'steer';\n const type = (ALLOWED.has(rawType) ? rawType : 'steer') as\n | 'steer'\n | 'ask'\n | 'assign'\n | 'note'\n | 'btw';\n const rawPriority = typeof body['priority'] === 'string' ? (body['priority'] as string) : '';\n const priority = (['low', 'normal', 'high'].includes(rawPriority) ? rawPriority : 'high') as\n | 'low'\n | 'normal'\n | 'high';\n const subject =\n typeof body['subject'] === 'string' && (body['subject'] as string).trim()\n ? (body['subject'] as string).trim()\n : 'Message from Fleet HQ';\n\n try {\n const { SessionRegistry } = await import('@wrongstack/core/storage');\n const { getSharedProjectMailbox, mailboxSessionTag } = await import('@wrongstack/core/coordination');\n const { resolveWstackPaths } = await import('@wrongstack/core/utils');\n const registry = new SessionRegistry(globalRoot);\n const entry = await registry.get(sessionId);\n if (!entry) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Session not found' }));\n return;\n }\n\n const paths = resolveWstackPaths({ projectRoot: entry.projectRoot, globalRoot });\n const mailbox = getSharedProjectMailbox(paths.projectDir);\n // The target session's leader answers to `leader@<sessionTag>` \u2014 its\n // agent-loop checker queries exactly this address before each LLM call.\n const to = `leader@${mailboxSessionTag(sessionId)}`;\n const sent = await mailbox.send({ from, to, type, subject, body: text, priority });\n\n // Return the message id so the caller can poll the thread for read-receipt\n // (readBy) and the agent's reply \u2014 the visible two-way feedback loop.\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ ok: true, id: sent.id, to, type, delivered: entry.status }));\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: String(err) }));\n }\n}\n\n/**\n * GET /api/sessions/:id/mailbox \u2014 the human\u2194leader thread for a session.\n *\n * Returns the messages exchanged between the operator (human@webui) and this\n * session's leader, newest last, with read-receipts (readBy) and completion/\n * outcome. This is what makes the WebUI's two-way loop *visible*: after Fleet\n * HQ sends a steer/ask, the panel shows whether the target read it (\u2713) and any\n * reply the agent posted back.\n */\nexport async function handleApiSessionMailbox(\n res: http.ServerResponse,\n globalRoot: string | undefined,\n sessionId: string,\n): Promise<void> {\n if (!globalRoot) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'SessionRegistry not available' }));\n return;\n }\n try {\n const { SessionRegistry } = await import('@wrongstack/core/storage');\n const { getSharedProjectMailbox, mailboxSessionTag } = await import('@wrongstack/core/coordination');\n const { resolveWstackPaths } = await import('@wrongstack/core/utils');\n const registry = new SessionRegistry(globalRoot);\n const entry = await registry.get(sessionId);\n if (!entry) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Session not found' }));\n return;\n }\n const paths = resolveWstackPaths({ projectRoot: entry.projectRoot, globalRoot });\n const mailbox = getSharedProjectMailbox(paths.projectDir);\n const leaderAddr = `leader@${mailboxSessionTag(sessionId)}`;\n // Messages TO the leader (operator \u2192 agent) and FROM the leader (replies).\n const [inbound, outbound] = await Promise.all([\n mailbox.query({ to: leaderAddr, limit: 50 }),\n mailbox.query({ from: leaderAddr, limit: 50 }),\n ]);\n const seen = new Set<string>();\n const thread = [...inbound, ...outbound]\n .filter((m) => {\n if (seen.has(m.id)) return false;\n seen.add(m.id);\n return true;\n })\n .sort((a, b) => Date.parse(a.timestamp) - Date.parse(b.timestamp))\n .map((m) => ({\n id: m.id,\n from: m.from,\n to: m.to,\n type: m.type,\n subject: m.subject,\n body: m.body,\n priority: m.priority,\n // Whether the leader has read it, and when.\n readByLeader: m.readBy?.[leaderAddr] ?? null,\n readByCount: Object.keys(m.readBy ?? {}).length,\n completed: m.completed,\n outcome: m.outcome ?? null,\n timestamp: m.timestamp,\n replyTo: m.replyTo ?? null,\n fromLeader: m.from === leaderAddr,\n }));\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ sessionId, leader: leaderAddr, status: entry.status, thread }));\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: String(err) }));\n }\n}\n\n/**\n * POST /api/sessions/:id/interrupt \u2014 cooperatively halt a running session.\n *\n * Sends a high-priority `control` mailbox message. The target's agent-loop\n * checks the mailbox before each LLM call; on seeing a fresh control:interrupt\n * it stops gracefully at the next iteration boundary (it does NOT kill the\n * process \u2014 for a hard stop use the process panel's PID kill). Cross-process\n * interrupt is necessarily cooperative: the WebUI server can't reach another\n * process's AbortController, only its mailbox.\n */\nexport async function handleApiSessionInterrupt(\n res: http.ServerResponse,\n req: http.IncomingMessage,\n globalRoot: string | undefined,\n sessionId: string,\n): Promise<void> {\n if (!globalRoot) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'SessionRegistry not available' }));\n return;\n }\n let body: Record<string, unknown> = {};\n try {\n body = await readJsonBody(req);\n } catch {\n /* interrupt needs no body \u2014 ignore parse errors */\n }\n const reason =\n typeof body['reason'] === 'string' && (body['reason'] as string).trim()\n ? (body['reason'] as string).trim()\n : 'Operator requested stop from Fleet HQ';\n const from =\n typeof body['from'] === 'string' && (body['from'] as string).trim()\n ? (body['from'] as string).trim()\n : 'human@webui';\n try {\n const { SessionRegistry } = await import('@wrongstack/core/storage');\n const { getSharedProjectMailbox, mailboxSessionTag } = await import('@wrongstack/core/coordination');\n const { resolveWstackPaths } = await import('@wrongstack/core/utils');\n const registry = new SessionRegistry(globalRoot);\n const entry = await registry.get(sessionId);\n if (!entry) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Session not found' }));\n return;\n }\n const paths = resolveWstackPaths({ projectRoot: entry.projectRoot, globalRoot });\n const mailbox = getSharedProjectMailbox(paths.projectDir);\n const to = `leader@${mailboxSessionTag(sessionId)}`;\n const sent = await mailbox.sendRuntimeControl({\n from,\n to,\n subject: 'interrupt',\n body: reason,\n priority: 'high',\n });\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ ok: true, id: sent.id, to, delivered: entry.status }));\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: String(err) }));\n }\n}\n\n/**\n * POST /api/fleet/broadcast \u2014 send one message to every live session's leader.\n *\n * Resolves all non-stale sessions in the same project as the WebUI host and\n * sends the message to each session's `leader@<tag>` (a true per-leader fan-out\n * rather than the bare '*' broadcast, so every live leader's mailbox loop \u2014\n * which queries its session-bound id \u2014 actually receives it).\n */\nexport async function handleApiFleetBroadcast(\n res: http.ServerResponse,\n req: http.IncomingMessage,\n globalRoot: string | undefined,\n): Promise<void> {\n if (!globalRoot) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'SessionRegistry not available' }));\n return;\n }\n let body: Record<string, unknown>;\n try {\n body = await readJsonBody(req);\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'Invalid request body' }));\n return;\n }\n const text = typeof body['text'] === 'string' ? (body['text'] as string).trim() : '';\n if (!text) {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'text is required' }));\n return;\n }\n const from =\n typeof body['from'] === 'string' && (body['from'] as string).trim()\n ? (body['from'] as string).trim()\n : 'human@webui';\n try {\n const { SessionRegistry } = await import('@wrongstack/core/storage');\n const { getSharedProjectMailbox, mailboxSessionTag } = await import('@wrongstack/core/coordination');\n const { resolveWstackPaths } = await import('@wrongstack/core/utils');\n const registry = new SessionRegistry(globalRoot);\n const all = await registry.list();\n // Scope to the WebUI host's own project (its pid's entry), like the live\n // status poll does. Fall back to every non-stale session if not found.\n const mySlug = all.find((s) => s.pid === process.pid)?.projectSlug;\n const targets = all\n .filter((s) => s.status !== 'stale')\n .filter((s) => (mySlug ? s.projectSlug === mySlug : true));\n if (targets.length === 0) {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ ok: true, delivered: 0 }));\n return;\n }\n // Cache one mailbox per project dir (targets here share a slug).\n const mbByDir = new Map<\n string,\n ReturnType<typeof getSharedProjectMailbox>\n >();\n const mailboxFor = (\n projectRoot: string,\n ): ReturnType<typeof getSharedProjectMailbox> => {\n const dir = resolveWstackPaths({ projectRoot, globalRoot }).projectDir;\n let mb = mbByDir.get(dir);\n if (!mb) {\n mb = getSharedProjectMailbox(dir);\n mbByDir.set(dir, mb);\n }\n return mb;\n };\n let delivered = 0;\n await Promise.all(\n targets.map(async (s) => {\n try {\n const mb = mailboxFor(s.projectRoot);\n await mb.send({\n from,\n to: `leader@${mailboxSessionTag(s.sessionId)}`,\n type: 'steer',\n subject: 'Broadcast from Fleet HQ',\n body: text,\n priority: 'high',\n });\n delivered++;\n } catch {\n /* best-effort per target */\n }\n }),\n );\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ ok: true, delivered, targets: targets.length }));\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: String(err) }));\n }\n}\n", "import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nconst DEFAULT_TAIL_BYTES = 1024 * 1024;\nconst MAX_PROCESSES = 32;\n\nexport interface ProcessMemoryDiagnostic {\n pid: number;\n surface: string;\n sessionId?: string | undefined;\n ts: string;\n memory: {\n rss: number;\n heapUsed: number;\n heapTotal: number;\n retainedHeapUsed?: number | undefined;\n nativeResidual?: number | undefined;\n external?: number | undefined;\n arrayBuffers?: number | undefined;\n };\n signal?: string | undefined;\n heapGrowthBytesPerHour?: number | undefined;\n rssGrowthBytesPerHour?: number | undefined;\n workload: {\n messages?: number | undefined;\n messageEstimatedTokens?: number | undefined;\n historyEntries?: number | undefined;\n historyMountedEntries?: number | undefined;\n historyCachedGroups?: number | undefined;\n appRenders?: number | undefined;\n metricsDroppedObservations?: number | undefined;\n kanbanSyncActive?: boolean | undefined;\n kanbanSyncPendingBoards?: number | undefined;\n kanbanSyncFullRescanPending?: boolean | undefined;\n kanbanSyncRemoteApplyQueued?: boolean | undefined;\n kanbanSyncPendingRemoteBoards?: number | undefined;\n kanbanSyncPublishRuns?: number | undefined;\n kanbanSyncCoalescedRefreshes?: number | undefined;\n kanbanSupervisorSnapshots?: number | undefined;\n kanbanSupervisorScheduledBoards?: number | undefined;\n kanbanSupervisorAgentCooldowns?: number | undefined;\n kanbanSupervisorRunningAgents?: number | undefined;\n };\n resources: {\n active?: number | undefined;\n types?: string | undefined;\n };\n hqQueue?:\n | {\n entries: number;\n bytes: number;\n maxBytes: number;\n droppedFrames: number;\n droppedBytes: number;\n coalescedFrames: number;\n coalescedBytes: number;\n }\n | undefined;\n hqSnapshot?:\n | {\n inFlight: boolean;\n pending: boolean;\n timerScheduled: boolean;\n eventInFlight: boolean;\n pendingEvents: number;\n coalescedEvents: number;\n droppedEvents: number;\n }\n | undefined;\n profileTopStack?: string | undefined;\n profileTopStackBytes?: number | undefined;\n}\n\nfunction finiteNumber(record: Record<string, unknown>, key: string): number | undefined {\n const value = record[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction stringValue(record: Record<string, unknown>, key: string): string | undefined {\n const value = record[key];\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction toProcessDiagnostic(record: Record<string, unknown>): ProcessMemoryDiagnostic | null {\n const pid = finiteNumber(record, 'pid');\n const ts = stringValue(record, 'ts');\n if (pid === undefined || ts === undefined) return null;\n\n const queueEntries = finiteNumber(record, 'hqQueueEntries');\n const queueBytes = finiteNumber(record, 'hqQueueBytes');\n const queueMaxBytes = finiteNumber(record, 'hqQueueMaxBytes');\n const snapshotInFlight = finiteNumber(record, 'hqSnapshotInFlight');\n const snapshotPending = finiteNumber(record, 'hqSnapshotPending');\n const snapshotTimerScheduled = finiteNumber(record, 'hqSnapshotTimerScheduled');\n const eventInFlight = finiteNumber(record, 'hqEventInFlight');\n const eventPending = finiteNumber(record, 'hqEventPending');\n const eventCoalesced = finiteNumber(record, 'hqEventCoalesced');\n const eventDropped = finiteNumber(record, 'hqEventDropped');\n\n return {\n pid,\n surface: stringValue(record, 'surface') ?? 'unknown',\n ...(stringValue(record, 'sessionId') !== undefined\n ? { sessionId: stringValue(record, 'sessionId') }\n : {}),\n ts,\n memory: {\n rss: finiteNumber(record, 'rss') ?? 0,\n heapUsed: finiteNumber(record, 'heapUsed') ?? 0,\n heapTotal: finiteNumber(record, 'heapTotal') ?? 0,\n retainedHeapUsed: finiteNumber(record, 'retainedHeapUsed'),\n nativeResidual: finiteNumber(record, 'nativeResidual'),\n external: finiteNumber(record, 'external'),\n arrayBuffers: finiteNumber(record, 'arrayBuffers'),\n },\n signal: stringValue(record, 'memorySignal'),\n heapGrowthBytesPerHour: finiteNumber(record, 'heapGrowthBytesPerHour'),\n rssGrowthBytesPerHour: finiteNumber(record, 'rssGrowthBytesPerHour'),\n workload: {\n messages: finiteNumber(record, 'messages'),\n messageEstimatedTokens: finiteNumber(record, 'messageEstimatedTokens'),\n historyEntries: finiteNumber(record, 'historyEntries'),\n historyMountedEntries: finiteNumber(record, 'historyMountedEntries'),\n historyCachedGroups: finiteNumber(record, 'historyCachedGroups'),\n appRenders: finiteNumber(record, 'appRenders'),\n metricsDroppedObservations: finiteNumber(record, 'metricsDroppedObservations'),\n kanbanSyncActive: finiteNumber(record, 'kanbanSyncActive') === 1,\n kanbanSyncPendingBoards: finiteNumber(record, 'kanbanSyncPendingBoards'),\n kanbanSyncFullRescanPending: finiteNumber(record, 'kanbanSyncFullRescanPending') === 1,\n kanbanSyncRemoteApplyQueued: finiteNumber(record, 'kanbanSyncRemoteApplyQueued') === 1,\n kanbanSyncPendingRemoteBoards: finiteNumber(record, 'kanbanSyncPendingRemoteBoards'),\n kanbanSyncPublishRuns: finiteNumber(record, 'kanbanSyncPublishRuns'),\n kanbanSyncCoalescedRefreshes: finiteNumber(record, 'kanbanSyncCoalescedRefreshes'),\n kanbanSupervisorSnapshots: finiteNumber(record, 'kanbanSupervisorSnapshots'),\n kanbanSupervisorScheduledBoards: finiteNumber(record, 'kanbanSupervisorScheduledBoards'),\n kanbanSupervisorAgentCooldowns: finiteNumber(record, 'kanbanSupervisorAgentCooldowns'),\n kanbanSupervisorRunningAgents: finiteNumber(record, 'kanbanSupervisorRunningAgents'),\n },\n resources: {\n active: finiteNumber(record, 'activeResources'),\n types: stringValue(record, 'activeResourceTypes'),\n },\n ...(queueEntries !== undefined && queueBytes !== undefined && queueMaxBytes !== undefined\n ? {\n hqQueue: {\n entries: queueEntries,\n bytes: queueBytes,\n maxBytes: queueMaxBytes,\n droppedFrames: finiteNumber(record, 'hqQueueDroppedFrames') ?? 0,\n droppedBytes: finiteNumber(record, 'hqQueueDroppedBytes') ?? 0,\n coalescedFrames: finiteNumber(record, 'hqQueueCoalescedFrames') ?? 0,\n coalescedBytes: finiteNumber(record, 'hqQueueCoalescedBytes') ?? 0,\n },\n }\n : {}),\n ...(snapshotInFlight !== undefined ||\n snapshotPending !== undefined ||\n snapshotTimerScheduled !== undefined\n ? {\n hqSnapshot: {\n inFlight: snapshotInFlight === 1,\n pending: snapshotPending === 1,\n timerScheduled: snapshotTimerScheduled === 1,\n eventInFlight: eventInFlight === 1,\n pendingEvents: eventPending ?? 0,\n coalescedEvents: eventCoalesced ?? 0,\n droppedEvents: eventDropped ?? 0,\n },\n }\n : {}),\n profileTopStack: stringValue(record, 'memoryProfileTopStack'),\n profileTopStackBytes: finiteNumber(record, 'memoryProfileTopStackBytes'),\n };\n}\n\n/**\n * Read only the tail of the process-wide heap JSONL flight recorder and\n * return the newest sample for each PID. This endpoint must stay cheap even\n * after weeks of uptime, so it never loads the full log into the WebUI server.\n */\nexport async function readRecentProcessMemoryDiagnostics(\n globalRoot: string | undefined,\n tailBytes = DEFAULT_TAIL_BYTES,\n): Promise<ProcessMemoryDiagnostic[]> {\n if (!globalRoot) return [];\n const heapLog = path.join(globalRoot, 'logs', 'heap.jsonl');\n let handle: fs.FileHandle | undefined;\n try {\n handle = await fs.open(heapLog, 'r');\n const stat = await handle.stat();\n const length = Math.min(stat.size, Math.max(1, tailBytes));\n if (length === 0) return [];\n const start = stat.size - length;\n const buffer = Buffer.allocUnsafe(length);\n const { bytesRead } = await handle.read(buffer, 0, length, start);\n let text = buffer.subarray(0, bytesRead).toString('utf8');\n if (start > 0) {\n const firstNewline = text.indexOf('\\n');\n if (firstNewline === -1) return [];\n text = text.slice(firstNewline + 1);\n }\n\n const newestByPid = new Map<number, ProcessMemoryDiagnostic>();\n const lines = text.split(/\\r?\\n/u);\n for (let index = lines.length - 1; index >= 0; index -= 1) {\n const line = lines[index]?.trim();\n if (!line) continue;\n try {\n const parsed = JSON.parse(line) as unknown;\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) continue;\n const diagnostic = toProcessDiagnostic(parsed as Record<string, unknown>);\n if (!diagnostic || newestByPid.has(diagnostic.pid)) continue;\n newestByPid.set(diagnostic.pid, diagnostic);\n if (newestByPid.size >= MAX_PROCESSES) break;\n } catch {\n // A concurrent append can leave the final line temporarily partial.\n }\n }\n return [...newestByPid.values()].sort((a, b) => b.ts.localeCompare(a.ts));\n } catch {\n return [];\n } finally {\n await handle?.close().catch(() => undefined);\n }\n}\n", "/**\n * Projects manifest (~/.wrongstack/projects.json) helpers \u2014 extracted from the\n * giant startWebUI closure in index.ts. Pure, param-based file IO: each fn\n * takes the global config path explicitly, so they close over nothing. Mirrors\n * the CLI's project-manifest registration (touchProjectInManifest).\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { ConfigError } from '@wrongstack/core/types';\nimport { projectSlug, withFileLock } from '@wrongstack/core/utils';\n\nexport interface ProjectEntry {\n name: string;\n root: string;\n slug: string;\n /** Repo-committed identity shared by clones, worktrees, and machines. */\n projectId?: string | undefined;\n lastSeen?: string | undefined;\n createdAt?: string | undefined;\n /** Working directory of the most recent session (may differ from root). */\n lastWorkingDir?: string | undefined;\n}\n\nexport interface ProjectsManifest {\n projects: ProjectEntry[];\n}\n\nexport function projectsJsonPath(globalConfigPath: string): string {\n const base = path.dirname(globalConfigPath);\n return path.join(base, 'projects.json');\n}\n\nexport async function loadManifest(globalConfigPath: string): Promise<ProjectsManifest> {\n try {\n const raw = await fs.readFile(projectsJsonPath(globalConfigPath), 'utf8');\n const parsed = JSON.parse(raw) as ProjectsManifest;\n return { projects: parsed.projects ?? [] };\n } catch {\n return { projects: [] };\n }\n}\n\nexport async function saveManifest(\n manifest: ProjectsManifest,\n globalConfigPath: string,\n): Promise<void> {\n const file = projectsJsonPath(globalConfigPath);\n await fs.mkdir(path.dirname(file), { recursive: true });\n await fs.writeFile(file, JSON.stringify(manifest, null, 2), 'utf8');\n}\n\nexport function generateProjectSlug(rootPath: string): string {\n // Canonical derivation \u2014 must match wstack-paths/projectSlug exactly or\n // the WebUI and CLI would key the same project under different dirs.\n return projectSlug(rootPath);\n}\n\nexport async function ensureProjectDataDir(\n slug: string,\n globalConfigPath: string,\n): Promise<string> {\n const base = path.dirname(globalConfigPath);\n const dir = path.join(base, 'projects', slug);\n await fs.mkdir(dir, { recursive: true });\n return dir;\n}\n\n/** Register or refresh a project with a serialized read-modify-write. */\nexport async function touchProjectInManifest(\n options: {\n projectRoot: string;\n workingDir?: string | undefined;\n name?: string | undefined;\n },\n globalConfigPath: string,\n): Promise<ProjectEntry> {\n const root = path.resolve(options.projectRoot);\n const file = projectsJsonPath(globalConfigPath);\n let entry: ProjectEntry | undefined;\n await withFileLock(file, async () => {\n const manifest = await loadManifest(globalConfigPath);\n const now = new Date().toISOString();\n entry = manifest.projects.find((candidate) => path.resolve(candidate.root) === root);\n if (entry) {\n entry.lastSeen = now;\n if (options.workingDir) entry.lastWorkingDir = path.resolve(options.workingDir);\n } else {\n entry = {\n name: options.name ?? path.basename(root),\n root,\n slug: generateProjectSlug(root),\n createdAt: now,\n lastSeen: now,\n lastWorkingDir: options.workingDir ? path.resolve(options.workingDir) : undefined,\n };\n manifest.projects.push(entry);\n }\n await saveManifest(manifest, globalConfigPath);\n });\n if (!entry) {\n throw new ConfigError({\n message: 'touchProjectInManifest: entry not resolved',\n code: 'CONFIG_INVALID',\n context: { phase: 'manifest-resolve' },\n });\n }\n await ensureProjectDataDir(entry.slug, globalConfigPath);\n return entry;\n}\n", "/**\n * TechStack HTTP handlers.\n *\n * Endpoints:\n * GET /api/techstack/snapshot\n * POST /api/techstack/inventory\n * POST /api/techstack/analyze\n * POST /api/techstack/jobs/:id/cancel\n * POST /api/techstack/deps/:id/research\n *\n * Commands arrive over REST; progress goes back over the WebSocket via `emit`.\n *\n * @see docs/specs/techstack-sdd.md \u00A74.2\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type * as http from 'node:http';\nimport type { Provider } from '@wrongstack/core/types';\nimport type {\n PackageOperation,\n Snapshot,\n TechStackEngine,\n TechStackJobKind,\n TechStackResearcher,\n TechStackStore,\n} from '@wrongstack/techstack';\n\n/** Upper bound on a single-package deep dive: one search fan-out + one LLM call. */\nconst DEEP_DIVE_TIMEOUT_MS = 60_000;\n\nfunction sendJson(res: http.ServerResponse, status: number, data: unknown): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n}\n\nexport interface TechStackHandlerDeps {\n /** Project ID used to look up the snapshot. */\n projectId: string;\n /** Server-owned project root. Never sourced from the request body. */\n projectRoot?: string | undefined;\n /** TechStack store instance. */\n store: TechStackStore;\n /** Service engine for inventory/analyze actions. */\n engine?: TechStackEngine | undefined;\n /** Publish WS-compatible events without coupling the HTTP layer to sockets. */\n emit?: ((event: TechStackEvent) => void) | undefined;\n /** Abort controllers keyed by running job id. */\n runningJobs?: Map<string, AbortController> | undefined;\n /**\n * Live provider access for the LLM research stage. Returns `undefined` when\n * no provider is configured, which downgrades `analyze` to a purely\n * deterministic run rather than failing it.\n *\n * A getter, not a captured value: the user can switch model or rotate\n * credentials mid-session (config hot-reload), and a provider snapshotted at\n * server construction would go stale without anyone noticing.\n */\n getLlm?: (() => { provider: Provider; model: string } | undefined) | undefined;\n /** Normal permission-governed bridge to the language_package tool. */\n executePackageOperation?:\n | ((\n operation: PackageOperation,\n workspace?: string,\n ) => Promise<{ readonly detail?: string } | void>)\n | undefined;\n}\n\n/**\n * Build the research stage for a job, or `undefined` when research should not\n * run (offline inventory, or no provider wired).\n */\nasync function buildResearcher(\n deps: TechStackHandlerDeps,\n kind: TechStackJobKind,\n): Promise<TechStackResearcher | undefined> {\n if (kind !== 'analyze' || !deps.getLlm) return undefined;\n const { createProviderLlm, createResearcher, createToolSearch } = await import(\n '@wrongstack/techstack'\n );\n const llm = createProviderLlm(deps.getLlm);\n if (!llm) return undefined;\n return createResearcher({ llm, search: createToolSearch() });\n}\n\nexport type TechStackEvent =\n | { type: 'techstack.job.started'; payload: { jobId: string; kind: 'inventory' | 'analyze' } }\n | {\n type: 'techstack.job.progress';\n payload: { jobId: string; phase: string; completed: number; total: number };\n }\n | { type: 'techstack.snapshot.updated'; payload: { snapshot: Snapshot; stale: false } }\n | { type: 'techstack.job.failed'; payload: { jobId: string; error: string } }\n | { type: 'techstack.job.cancelled'; payload: { jobId: string } };\n\n/** GET /api/techstack/snapshot */\nexport function handleTechStackSnapshot(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n): void {\n try {\n const snapshot = deps.store.getSnapshot(deps.projectId);\n if (!snapshot) {\n sendJson(res, 404, { snapshot: null, stale: false });\n return;\n }\n const ageMs = Date.now() - new Date(snapshot.createdAt).getTime();\n sendJson(res, 200, { snapshot, stale: ageMs > 24 * 60 * 60 * 1000 });\n } catch (error) {\n sendJson(res, 500, {\n error: 'TechStack store unavailable',\n detail: errorMessage(error),\n });\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction requireJobDeps(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n): deps is TechStackHandlerDeps & { projectRoot: string; engine: TechStackEngine } {\n if (!deps.projectRoot || !deps.engine) {\n sendJson(res, 503, { error: 'TechStack engine unavailable' });\n return false;\n }\n return true;\n}\n\nfunction startJob(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n kind: TechStackJobKind,\n): void {\n if (!requireJobDeps(res, deps)) return;\n\n const jobId = randomUUID();\n const controller = new AbortController();\n deps.runningJobs?.set(jobId, controller);\n deps.emit?.({ type: 'techstack.job.started', payload: { jobId, kind } });\n sendJson(res, 202, { jobId, kind, status: 'queued' });\n\n void buildResearcher(deps, kind)\n .catch(() => undefined)\n .then((researcher) =>\n deps.engine.analyze(deps.projectId, {\n targetRoot: deps.projectRoot,\n requestedBy: 'webui',\n online: kind === 'analyze',\n jobId,\n signal: controller.signal,\n researcher,\n onProgress: (phase, completed, total) => {\n deps.emit?.({\n type: 'techstack.job.progress',\n payload: { jobId, phase, completed, total },\n });\n },\n }),\n )\n .then(({ snapshot }) => {\n if (controller.signal.aborted) return;\n deps.emit?.({\n type: 'techstack.snapshot.updated',\n payload: { snapshot, stale: false },\n });\n })\n .catch((error: unknown) => {\n if (controller.signal.aborted) {\n deps.emit?.({ type: 'techstack.job.cancelled', payload: { jobId } });\n return;\n }\n deps.emit?.({\n type: 'techstack.job.failed',\n payload: { jobId, error: errorMessage(error) },\n });\n })\n .finally(() => {\n deps.runningJobs?.delete(jobId);\n });\n}\n\n/** POST /api/techstack/inventory */\nexport function handleTechStackInventory(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n): void {\n startJob(res, deps, 'inventory');\n}\n\n/** POST /api/techstack/analyze */\nexport function handleTechStackAnalyze(res: http.ServerResponse, deps: TechStackHandlerDeps): void {\n startJob(res, deps, 'analyze');\n}\n\n/** POST /api/techstack/jobs/:id/cancel \u2014 idempotent. */\nexport function handleTechStackCancel(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n jobId: string,\n): void {\n const controller = deps.runningJobs?.get(jobId);\n if (controller && !controller.signal.aborted) controller.abort();\n deps.store.updateJobStatus(jobId, 'cancelled');\n deps.emit?.({ type: 'techstack.job.cancelled', payload: { jobId } });\n sendJson(res, 200, { jobId, status: 'cancelled' });\n}\n\n/**\n * POST /api/techstack/deps/:id/research \u2014 deep dive on one dependency.\n *\n * Synchronous: one package is a single cluster and a single LLM call, so the\n * caller gets the findings in the response rather than having to correlate a\n * job id over the socket.\n *\n * Deliberately bypasses triage. Triage answers \"what is worth spending tokens\n * on unprompted\"; an explicit click has already answered that, so a `current`\n * package the user is curious about is fair game.\n */\nexport async function handleTechStackDependencyResearch(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n dependencyId: string,\n): Promise<void> {\n const snapshot = deps.store.getSnapshot(deps.projectId);\n const dependency = snapshot?.dependencies.find((dep) => dep.id === dependencyId);\n if (!dependency) {\n sendJson(res, 404, { error: 'Dependency not found in the current snapshot' });\n return;\n }\n\n let researcher: TechStackResearcher | undefined;\n try {\n researcher = await buildResearcher(deps, 'analyze');\n } catch (error) {\n sendJson(res, 503, { error: 'Research unavailable', detail: errorMessage(error) });\n return;\n }\n if (!researcher) {\n sendJson(res, 503, {\n error: 'No model configured \u2014 connect a provider to run LLM analysis.',\n });\n return;\n }\n\n const controller = new AbortController();\n const timeout = setTimeout(() => {\n controller.abort(new Error('research timeout'));\n }, DEEP_DIVE_TIMEOUT_MS);\n timeout.unref?.();\n\n try {\n const { triageCandidates } = await import('@wrongstack/techstack');\n // Reuse triage purely to derive the right cluster for this status; fall\n // back to a breaking-change read when the status is one triage skips.\n const [triaged] = triageCandidates([dependency], { limit: 1 });\n const findings = await researcher.research(\n [triaged ?? { dependency, cluster: 'breaking_change', priority: 0 }],\n { signal: controller.signal },\n );\n sendJson(res, 200, { dependencyId, findings });\n } catch (error) {\n sendJson(res, 500, { error: 'Research failed', detail: errorMessage(error) });\n } finally {\n clearTimeout(timeout);\n controller.abort();\n }\n}\n\n/** GET /api/techstack/jobs/:id */\nexport function handleTechStackJobStatus(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n jobId: string,\n): void {\n const job = deps.store.getJob(jobId);\n if (!job) {\n sendJson(res, 404, { error: 'Job not found' });\n return;\n }\n sendJson(res, 200, { job });\n}\n\n/** GET /api/techstack/reports/:id?format=md|json */\nexport function handleTechStackReport(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n reportId: string,\n format: 'md' | 'json',\n): void {\n const snapshot = deps.store.getSnapshotById(reportId);\n if (!snapshot) {\n sendJson(res, 404, { error: 'Report not found' });\n return;\n }\n if (deps.engine) {\n const report = deps.engine.generateReport(snapshot, format);\n res.writeHead(200, {\n 'Content-Type': format === 'json' ? 'application/json' : 'text/markdown',\n 'Content-Disposition': `attachment; filename=\"techstack-report.${format}\"`,\n });\n res.end(report);\n } else {\n // No engine \u2014 fall back to raw JSON snapshot\n sendJson(res, 200, snapshot);\n }\n}\n\n/** GET /api/techstack/trends */\nexport async function handleTechStackTrends(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n): Promise<void> {\n try {\n const { TrendStore } = await import('@wrongstack/techstack');\n sendJson(res, 200, { trend: new TrendStore(deps.store).analyze(deps.projectId) });\n } catch (error) {\n sendJson(res, 500, { error: 'Trend analysis failed', detail: errorMessage(error) });\n }\n}\n\n/** GET /api/techstack/remediation */\nexport async function handleTechStackRemediationPlan(\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n): Promise<void> {\n const snapshot = deps.store.getSnapshot(deps.projectId);\n if (!snapshot) {\n sendJson(res, 404, { error: 'No TechStack snapshot is available' });\n return;\n }\n const { applyPlan, generateUpgradePlan } = await import('@wrongstack/techstack');\n const plan = generateUpgradePlan(snapshot);\n sendJson(res, 200, { plan, preview: await applyPlan(plan) });\n}\n\n/** POST /api/techstack/remediation/apply */\nexport async function handleTechStackRemediationApply(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n deps: TechStackHandlerDeps,\n): Promise<void> {\n if (!deps.executePackageOperation) {\n sendJson(res, 503, { error: 'Permission-governed package execution is unavailable' });\n return;\n }\n let approvedItems: string[];\n try {\n let raw = '';\n for await (const chunk of req) {\n raw += Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk);\n if (Buffer.byteLength(raw) > 64 * 1024) throw new Error('Request body is too large');\n }\n const body = JSON.parse(raw || '{}') as { approvedItems?: unknown };\n approvedItems = Array.isArray(body.approvedItems)\n ? body.approvedItems.filter((value): value is string => typeof value === 'string')\n : [];\n } catch (error) {\n sendJson(res, 400, { error: 'Invalid request body', detail: errorMessage(error) });\n return;\n }\n if (approvedItems.length === 0) {\n sendJson(res, 400, { error: 'approvedItems must explicitly identify at least one plan item' });\n return;\n }\n const snapshot = deps.store.getSnapshot(deps.projectId);\n if (!snapshot) {\n sendJson(res, 404, { error: 'No TechStack snapshot is available' });\n return;\n }\n const approved = new Set(approvedItems);\n const executePackageOperation = deps.executePackageOperation;\n const { applyPlan, generateUpgradePlan } = await import('@wrongstack/techstack');\n const plan = generateUpgradePlan(snapshot);\n const result = await applyPlan(plan, {\n dryRun: false,\n approve: (item) =>\n approved.has(`${item.workspaceId}:${item.ecosystem}:${item.dependencyName}:${item.action}`),\n execute: (operation) => {\n const workspace = snapshot.workspaces.find((item) => item.id === operation.workspaceId);\n return executePackageOperation(operation, workspace?.relativeRoot);\n },\n });\n sendJson(res, 200, { plan, result });\n}\n", "/**\n * WebSocket connection authentication for the WebUI server.\n *\n * Three layered defenses, all enforced in {@link verifyClient}:\n * 1. **DNS-rebinding guard** ({@link hostHeaderOk}) \u2014 on a loopback bind the\n * `Host` header must itself be a loopback name, so a rebound attacker page\n * (`Host: evil.com`) is rejected even though its TCP peer is 127.0.0.1.\n * 2. **Shared-token auth** ({@link tokenMatches}, constant-time) \u2014 required for\n * any non-loopback origin and for non-browser clients reaching a publicly\n * bound socket. Tokens are accepted via `Cookie: ws_token=\u2026` (preferred;\n * set by the `/ws-auth` HTTP endpoint with HttpOnly+SameSite=Strict) OR\n * `?token=\u2026` URL query param (non-browser fallback).\n * 3. **Loopback bootstrap** \u2014 same-machine browser origins are allowed without\n * a token; the Host-header guard above already blocks cross-site pages.\n *\n * Browser clients (those that send an `Origin` header) authenticate via the\n * HttpOnly cookie by default \u2014 the URL `?token=` path is rejected for them,\n * closing the C-598 (Information Exposure Through Query String) class (token in\n * browser history / referrer / proxy logs). The only browser URL-token exception\n * is an explicit public-WS tunnel URL whose origin is allowlisted by the server;\n * that covers separate HTTP/WS hostnames where cookies cannot cross hosts.\n * Non-browser clients (no `Origin`: curl, scripts, tests) keep the URL-token\n * path for ergonomics \u2014 query-string exposure is a browser-only concern.\n *\n * Extracted from `index.ts` as pure functions so the auth contract can be unit\n * tested without standing up a real `http.Server`/`WebSocketServer`. `index.ts`\n * builds a thin closure that pulls the fields below off the incoming request.\n */\nimport { Buffer } from 'node:buffer';\nimport { timingSafeEqual } from 'node:crypto';\n\n/** A hostname that refers to the local machine. */\nexport function isLoopbackHostname(hostname: string): boolean {\n return (\n hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n hostname === '::1' ||\n hostname === '[::1]'\n );\n}\n\n/**\n * Check if an origin is a trusted loopback browser origin.\n * Defense-in-depth: when wsHost=0.0.0.0, only accept explicit localhost origins,\n * not arbitrary loopback hostnames that could be spoofed by local malware.\n */\nfunction isTrustedLoopbackOrigin(origin: string): boolean {\n try {\n const url = new URL(origin);\n // Only allow explicit loopback http(s) origins.\n // Reject file://, data://, and other schemes even on loopback.\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return false;\n return (\n url.hostname === 'localhost' ||\n url.hostname === '127.0.0.1' ||\n url.hostname === '::1' ||\n url.hostname === '[::1]'\n );\n } catch {\n return false;\n }\n}\n\n/** True when the server is bound to a loopback interface (vs. LAN/0.0.0.0). */\nexport function isLoopbackBind(wsHost: string): boolean {\n return wsHost === '127.0.0.1' || wsHost === '::1' || wsHost === 'localhost';\n}\n\n/**\n * True when the server is bound to a wildcard address that exposes it on every\n * interface \u2014 IPv4 `0.0.0.0` OR IPv6 `::` (and its bracketed form). The\n * \"LAN exposure = deny\" guards below must treat both families identically; a\n * `::` bind is exactly as exposed as `0.0.0.0` and previously slipped past the\n * `wsHost === '0.0.0.0'` string check.\n */\nexport function isWildcardBind(wsHost: string): boolean {\n return wsHost === '0.0.0.0' || wsHost === '::' || wsHost === '[::]';\n}\n\nfunction normalizeHostname(hostname: string): string {\n const h = hostname.trim().toLowerCase();\n return h.startsWith('[') && h.endsWith(']') ? h.slice(1, -1) : h;\n}\n\nfunction allowedHostname(hostname: string, allowedHostnames?: readonly string[]): boolean {\n const normalized = normalizeHostname(hostname);\n return (allowedHostnames ?? []).some((candidate) => normalizeHostname(candidate) === normalized);\n}\n\n/**\n * Constant-time comparison of a provided token against the expected one.\n * A length mismatch short-circuits (lengths aren't secret); equal-length\n * inputs are compared with `timingSafeEqual` so the token can't be recovered\n * byte-by-byte via response timing.\n */\nexport function tokenMatches(provided: string | undefined, expected: string): boolean {\n if (!provided) return false;\n const a = Buffer.from(provided);\n const b = Buffer.from(expected);\n if (a.length !== b.length) return false;\n return timingSafeEqual(a, b);\n}\n\n/** Pull the `token` query param out of a request URL (`/?token=\u2026`). */\nexport function extractToken(url: string): string | undefined {\n const match = url.match(/[?&]token=([^&]+)/);\n return match ? match[1] : undefined;\n}\n\n/**\n * Pull the `ws_token` value out of a Cookie header (`Cookie: ws_token=\u2026`).\n * The WebUI's auth-token cookie is set via `Set-Cookie: ws_token=<token>;\n * HttpOnly; SameSite=Strict; Path=/` from the `/ws-auth` HTTP endpoint. The\n * browser then sends it back automatically on the WS upgrade request \u2014\n * closing the C-598 (Information Exposure Through Query String) class\n * because the token never appears in the URL, browser history, or\n * reverse-proxy access logs.\n *\n * Returns `undefined` if the cookie header is absent or malformed.\n */\nexport function extractTokenFromCookie(cookieHeader: string | string[] | undefined): string | undefined {\n if (!cookieHeader) return undefined;\n const raw = Array.isArray(cookieHeader) ? cookieHeader.join('; ') : cookieHeader;\n for (const part of raw.split(';')) {\n const eq = part.indexOf('=');\n if (eq < 0) continue;\n const name = part.slice(0, eq).trim();\n if (name === 'ws_token') {\n // Cookie values are url-encoded in spec; decode for the constant-time\n // compare downstream. Trim trailing whitespace defensively.\n try {\n return decodeURIComponent(part.slice(eq + 1).trim());\n } catch {\n return part.slice(eq + 1).trim();\n }\n }\n }\n return undefined;\n}\n\n/**\n * DNS-rebinding defense. On a loopback bind, the `Host` header must resolve to\n * a loopback name. When the operator deliberately exposes the socket (wsHost is\n * a LAN/0.0.0.0 address) the Host is legitimately non-loopback, so the guard is\n * skipped and connection auth falls to the token check.\n */\nexport function hostHeaderOk(input: {\n hostHeader: string | undefined;\n wsHost: string;\n allowedHostnames?: readonly string[] | undefined;\n}): boolean {\n if (!isLoopbackBind(input.wsHost)) return true; // operator opted into wider exposure\n const hostHeader = (input.hostHeader ?? '').trim();\n if (!hostHeader) return false;\n // Strip the port (handle bare host, host:port, and [::1]:port).\n let hostname: string;\n try {\n hostname = new URL(`http://${hostHeader}`).hostname;\n } catch {\n return false;\n }\n return isLoopbackHostname(hostname) || allowedHostname(hostname, input.allowedHostnames);\n}\n\nexport interface VerifyClientInput {\n /** Browser `Origin` header, or undefined for non-browser clients. */\n origin?: string | undefined;\n /** Request URL (`req.url`) \u2014 carries the `?token=\u2026` query param. */\n url: string;\n /** `Host` header (`req.headers.host`). */\n hostHeader?: string | undefined;\n /** Peer address (`req.socket.remoteAddress`). */\n remoteAddress?: string | undefined;\n /** `Cookie` header (`req.headers.cookie`). Carries `ws_token=\u2026` when the\n * browser went through `/ws-auth` to set the HttpOnly auth cookie. */\n cookieHeader?: string | string[] | undefined;\n /** Host/interface the WS server is bound to. */\n wsHost: string;\n /** The server's generated auth token. */\n expectedToken: string;\n /** Force token auth even for loopback binds, useful behind public tunnels. */\n requireToken?: boolean | undefined;\n /** Extra Host header names allowed on loopback binds, e.g. a tunnel hostname. */\n allowedHostnames?: readonly string[] | undefined;\n /** Allow browser WS URL tokens for explicit public WS URLs where cookies cannot cross hostnames. */\n allowBrowserUrlToken?: boolean | undefined;\n}\n\n/**\n * Decide whether to accept an incoming WebSocket handshake. Pure mirror of the\n * closure previously inlined in `index.ts`; see the module doc for the layered\n * policy. Returns `true` to accept, `false` to reject.\n *\n * Token sources, in priority order:\n * 1. `Cookie: ws_token=\u2026` (browser clients that went through `/ws-auth`)\n * 2. `?token=\u2026` URL query param (non-browser clients: curl, scripts)\n *\n * Browser clients (with an `Origin` header) are restricted to the cookie path \u2014\n * URL token is rejected for them, closing the C-598 query-string token\n * exposure class. Non-browser clients keep the URL-token fallback so curl\n * and tests continue to work.\n */\nexport function verifyClient(input: VerifyClientInput): boolean {\n const {\n origin,\n url,\n hostHeader,\n remoteAddress,\n cookieHeader,\n wsHost,\n expectedToken,\n requireToken,\n allowedHostnames,\n allowBrowserUrlToken,\n } = input;\n const urlTokenOk = tokenMatches(extractToken(url ?? ''), expectedToken);\n const cookieTokenOk = tokenMatches(extractTokenFromCookie(cookieHeader), expectedToken);\n\n // DNS-rebinding guard runs first on a loopback bind \u2014 independent of token\n // and Origin. Blocks a rebound attacker page (Host = attacker domain) even\n // though the TCP peer is 127.0.0.1.\n if (!hostHeaderOk({ hostHeader, wsHost, allowedHostnames })) return false;\n\n if (!origin) {\n // Non-browser clients (curl, scripts): require token unless on loopback.\n // The URL `?token=` path stays valid here for ergonomics (curl/tests have\n // no cookie jar) \u2014 query-string token exposure (C-598) is a *browser*\n // history/log concern, which non-browser clients don't have.\n // When wsHost=0.0.0.0 the server accepts connections from any network\n // interface. Tokenless connections from non-loopback peers are denied\n // outright, but a valid token (URL or cookie) authenticates non-browser\n // clients from any origin \u2014 enabling curl, scripts, and automation tools\n // on Tailscale/LAN peers to reach the WS API with the operator's token.\n const remoteIp = remoteAddress ?? '';\n const isRemoteLoopback = remoteIp === '127.0.0.1' || remoteIp === '::1';\n if (!isRemoteLoopback && isWildcardBind(wsHost) && !urlTokenOk && !cookieTokenOk) return false;\n return urlTokenOk || cookieTokenOk || (isLoopbackBind(wsHost) && !requireToken);\n }\n try {\n const { hostname: originHostname } = new URL(origin);\n // Loopback browser origins: allow without token only if the origin is\n // explicitly http://localhost or http://127.0.0.1 (defense-in-depth).\n // Reject file://, data://, and other schemes even on loopback.\n if (isLoopbackHostname(originHostname)) {\n if (requireToken || !isLoopbackBind(wsHost)) return cookieTokenOk;\n return isTrustedLoopbackOrigin(origin);\n }\n // Non-loopback browser origins normally authenticate via the HttpOnly cookie\n // set by `/ws-auth`. When an operator supplies a separate public WS URL, the\n // cookie may not cross hostnames, so an explicit opt-in keeps URL-token auth\n // available for that tunnel endpoint.\n return (\n cookieTokenOk ||\n (Boolean(allowBrowserUrlToken) &&\n urlTokenOk &&\n allowedHostname(originHostname, allowedHostnames))\n );\n } catch {\n return false;\n }\n}\n", "/**\n * Running-instance registry for the standalone WebUI server.\n *\n * Every live `wstack --webui` process records itself in a single JSON file under the\n * wstack home dir (`~/.wrongstack/webui-instances.json`) so a user running\n * several instances (one per project, or several per project on different\n * ports) can see at a glance which ports are open for which path.\n *\n * Design notes:\n * - **Self-healing**: every register/unregister/list prunes entries whose PID\n * is no longer alive (`process.kill(pid, 0)`), so a crashed instance that\n * never got to unregister doesn't leave a ghost behind.\n * - **Atomic writes**: the file is rewritten via `atomicWrite` (tmp + rename),\n * so a concurrent reader never sees a half-written file. Two instances\n * starting at the *exact* same millisecond could still race the\n * read-modify-write \u2014 acceptable for a best-effort tracking file, and the\n * next register() heals any dropped entry.\n * - **Best-effort**: a failure to read/write the registry must NEVER take the\n * server down. Callers wrap these in `.catch()`.\n */\n\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { atomicWrite } from '@wrongstack/core/utils';\n\n/** One running WebUI / SimpleUI process. */\nexport interface WebUIInstanceRecord {\n /** OS process id \u2014 also the liveness key. */\n pid: number;\n /** Surface kind \u2014 'webui' or 'simpleui'. */\n surface: 'webui' | 'simpleui';\n /** Port serving both HTTP and WebSocket. */\n httpPort: number;\n /** Bind host (e.g. 127.0.0.1 or 0.0.0.0). */\n host: string;\n /** Absolute project root the instance booted against. */\n projectRoot: string;\n /** Display name (basename of projectRoot). */\n projectName: string;\n /** ISO timestamp when the instance registered. */\n startedAt: string;\n /** Convenience open-in-browser URL. */\n url: string;\n}\n\ninterface RegistryFile {\n version: 1;\n instances: WebUIInstanceRecord[];\n}\n\n/** Default wstack home dir (`~/.wrongstack`). Callers may override the base. */\nexport function defaultBaseDir(): string {\n return path.join(os.homedir(), '.wrongstack');\n}\n\n/** Resolve the registry file path for a given base dir. */\nexport function registryPath(baseDir: string = defaultBaseDir()): string {\n return path.join(baseDir, 'webui-instances.json');\n}\n\n/**\n * Liveness probe. `process.kill(pid, 0)` sends no signal \u2014 it only checks the\n * process exists. ESRCH \u21D2 dead; EPERM \u21D2 alive but owned by another user (still\n * counts as alive). Any other error is treated conservatively as \"alive\" so we\n * never prune an instance we simply failed to probe.\n */\nexport function isPidAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (err) {\n return (err as NodeJS.ErrnoException).code !== 'ESRCH';\n }\n}\n\nasync function load(file: string): Promise<RegistryFile> {\n try {\n const raw = await fs.readFile(file, 'utf8');\n const parsed = JSON.parse(raw) as RegistryFile;\n if (parsed?.version === 1 && Array.isArray(parsed.instances)) {\n return parsed;\n }\n } catch {\n // Missing or corrupt \u2192 start fresh.\n }\n return { version: 1, instances: [] };\n}\n\nasync function save(file: string, instances: WebUIInstanceRecord[]): Promise<void> {\n await atomicWrite(file, `${JSON.stringify({ version: 1, instances }, null, 2)}\\n`, {\n mode: 0o600,\n });\n}\n\n/** Drop dead processes and (optionally) one specific pid. */\nfunction prune(instances: WebUIInstanceRecord[], excludePid?: number): WebUIInstanceRecord[] {\n return instances.filter((i) => i.pid !== excludePid && isPidAlive(i.pid));\n}\n\n/**\n * Register (or refresh) this instance. Prunes dead entries and any stale entry\n * for our own PID before adding the current record. Best-effort \u2014 rejects only\n * on a hard fs error, which callers swallow.\n */\nexport async function registerInstance(\n record: WebUIInstanceRecord,\n baseDir: string = defaultBaseDir(),\n): Promise<void> {\n const file = registryPath(baseDir);\n const data = await load(file);\n const instances = prune(data.instances, record.pid);\n instances.push(record);\n await save(file, instances);\n}\n\n/** Remove this instance (called on graceful shutdown). Also prunes dead pids. */\nexport async function unregisterInstance(\n pid: number,\n baseDir: string = defaultBaseDir(),\n): Promise<void> {\n const file = registryPath(baseDir);\n const data = await load(file);\n const instances = prune(data.instances, pid);\n await save(file, instances);\n}\n\n/** List live instances, pruning any dead entries encountered. */\nexport async function listInstances(\n baseDir: string = defaultBaseDir(),\n): Promise<WebUIInstanceRecord[]> {\n const file = registryPath(baseDir);\n const data = await load(file);\n const live = prune(data.instances);\n // Persist the pruned view so `cat`-ing the file also shows reality, but never\n // fail the list on a write error.\n if (live.length !== data.instances.length) {\n await save(file, live).catch(() => {});\n }\n return live;\n}\n\n/** Human-readable table of running instances for `wstack --webui --list`. */\nexport function formatInstances(instances: WebUIInstanceRecord[]): string {\n if (instances.length === 0) {\n return 'No WebUI instances are currently running.';\n }\n const lines = [`Running WebUI instances (${instances.length}):`, ''];\n for (const i of instances) {\n lines.push(\n ` \u2022 ${i.url} \u00B7 pid ${i.pid}`,\n ` project: ${i.projectName} (${i.projectRoot})`,\n ` since: ${i.startedAt}`,\n );\n }\n return lines.join('\\n');\n}\n", "import type {\n Capabilities,\n ModelsRegistry,\n ProviderConfig,\n ResolvedModel,\n ResolvedProvider,\n} from '@wrongstack/core/types';\nimport { capabilitiesFor } from '@wrongstack/providers';\n\nexport const SIBLING_CATALOG: Record<string, string> = {\n 'anthropic-oauth': 'anthropic',\n 'openai-codex': 'openai',\n 'github-copilot': 'openai',\n};\n\n/**\n * Resolve the catalog entry to use for a saved provider's WebUI model list.\n * Runtime discovery injects provider-specific catalogs under the saved provider\n * id (for example `omniroute`), while older aliases may still need to fall\n * back to their generic wire/catalog `type`.\n */\nexport async function resolveProviderCatalogForModels(\n modelsRegistry: Pick<ModelsRegistry, 'getProvider'>,\n providerId: string,\n cfg: Pick<ProviderConfig, 'type'> | undefined,\n): Promise<ResolvedProvider | undefined> {\n return (\n (await modelsRegistry.getProvider(providerId)) ??\n (cfg?.type && cfg.type !== providerId\n ? await modelsRegistry.getProvider(cfg.type)\n : undefined)\n );\n}\n\n/**\n * Resolve model metadata for a selected config provider. Prefer the saved\n * provider id so provider-specific runtime discovery (for example Omniroute)\n * supplies context/cost/capability metadata; fall back to cfg.type for aliases.\n */\nexport async function resolveProviderModelMetadata(\n modelsRegistry: Pick<ModelsRegistry, 'getModel' | 'getProvider'> & Partial<Pick<ModelsRegistry, 'listProviders'>>,\n providerId: string,\n modelId: string,\n cfg: Pick<ProviderConfig, 'type' | 'family' | 'models' | 'customModels' | 'capabilities'> | undefined,\n): Promise<ResolvedModel | undefined> {\n const direct = await modelsRegistry.getModel(providerId, modelId).catch(() => undefined);\n if (direct) return overlayConfiguredCapabilities(direct, cfg);\n\n if (cfg?.type && cfg.type !== providerId) {\n const typed = await modelsRegistry.getModel(cfg.type, modelId).catch(() => undefined);\n if (typed) return overlayConfiguredCapabilities(typed, cfg);\n }\n\n const sibling = cfg?.family ? SIBLING_CATALOG[cfg.family] : undefined;\n if (sibling) {\n const siblingModel = await modelsRegistry.getModel(sibling, modelId).catch(() => undefined);\n if (siblingModel) return overlayConfiguredCapabilities(siblingModel, cfg);\n const caps = await capabilitiesFor(\n modelsRegistry as ModelsRegistry,\n sibling,\n modelId,\n cfg?.customModels,\n ).catch(() => undefined);\n if (caps && positiveNumber(caps.maxContext)) {\n return syntheticModel(providerId, modelId, cfg, caps);\n }\n }\n\n const catalogId = cfg?.type && cfg.type !== providerId ? cfg.type : providerId;\n const caps = await capabilitiesFor(\n modelsRegistry as ModelsRegistry,\n catalogId,\n modelId,\n cfg?.customModels,\n ).catch(() => undefined);\n if (caps && positiveNumber(caps.maxContext)) {\n return syntheticModel(providerId, modelId, cfg, caps);\n }\n\n const crossCatalog = await findModelAcrossCatalog(modelsRegistry, modelId);\n if (crossCatalog) return overlayConfiguredCapabilities(crossCatalog, cfg);\n\n return syntheticModel(providerId, modelId, cfg);\n}\n\nasync function findModelAcrossCatalog(\n modelsRegistry: Partial<Pick<ModelsRegistry, 'listProviders' | 'getModel'>>,\n modelId: string,\n): Promise<ResolvedModel | undefined> {\n if (typeof modelsRegistry.listProviders !== 'function' || typeof modelsRegistry.getModel !== 'function') {\n return undefined;\n }\n const providers = await modelsRegistry.listProviders().catch(() => []);\n for (const provider of providers) {\n if (!provider.models.some((model) => model.id === modelId)) continue;\n const resolved = await modelsRegistry.getModel(provider.id, modelId).catch(() => undefined);\n if (resolved?.capabilities?.maxContext) return resolved;\n }\n return undefined;\n}\n\nfunction syntheticModel(\n providerId: string,\n modelId: string,\n cfg: Pick<ProviderConfig, 'models' | 'customModels' | 'capabilities'> | undefined,\n capabilities?: Partial<Capabilities> | undefined,\n): ResolvedModel | undefined {\n const custom = cfg?.customModels?.[modelId];\n const configuredMax = positiveNumber(readConfiguredMaxContext(cfg));\n const customCaps = custom?.capabilities;\n const maxContext =\n positiveNumber(customCaps?.maxContext) ??\n positiveNumber(capabilities?.maxContext) ??\n configuredMax ??\n 0;\n const isKnown =\n Boolean(custom) ||\n Boolean(cfg?.models?.includes(modelId)) ||\n maxContext > 0 ||\n Boolean(capabilities);\n if (!isKnown) return undefined;\n return {\n providerId,\n modelId,\n capabilities: {\n tools: readConfiguredBool(cfg, 'tools') ?? capabilities?.tools ?? customCaps?.tools ?? false,\n vision: readConfiguredBool(cfg, 'vision') ?? capabilities?.vision ?? customCaps?.vision ?? false,\n reasoning: readConfiguredBool(cfg, 'reasoning') ?? capabilities?.reasoning ?? customCaps?.reasoning ?? false,\n maxContext,\n maxOutput: custom?.maxOutput ?? customCaps?.maxOutput ?? capabilities?.maxOutput,\n },\n cost: undefined,\n };\n}\n\nfunction overlayConfiguredCapabilities(\n model: ResolvedModel,\n cfg: Pick<ProviderConfig, 'customModels' | 'capabilities'> | undefined,\n): ResolvedModel {\n const custom = cfg?.customModels?.[model.modelId];\n const configuredMax = positiveNumber(readConfiguredMaxContext(cfg));\n const customCaps = custom?.capabilities;\n if (!configuredMax && !customCaps && custom?.maxOutput === undefined) return model;\n return {\n ...model,\n capabilities: {\n ...model.capabilities,\n ...customCaps,\n maxContext: customCaps?.maxContext ?? configuredMax ?? model.capabilities.maxContext,\n maxOutput: custom?.maxOutput ?? customCaps?.maxOutput ?? model.capabilities.maxOutput,\n },\n };\n}\n\nfunction readConfiguredMaxContext(providerConfig: unknown): number | undefined {\n if (!providerConfig || typeof providerConfig !== 'object') return undefined;\n const capabilities = (providerConfig as { capabilities?: unknown | undefined }).capabilities;\n if (!capabilities || typeof capabilities !== 'object') return undefined;\n return (capabilities as Partial<Capabilities>).maxContext;\n}\n\nfunction readConfiguredBool(\n providerConfig: unknown,\n key: 'tools' | 'vision' | 'reasoning',\n): boolean | undefined {\n if (!providerConfig || typeof providerConfig !== 'object') return undefined;\n const capabilities = (providerConfig as { capabilities?: unknown | undefined }).capabilities;\n if (!capabilities || typeof capabilities !== 'object') return undefined;\n const value = (capabilities as Partial<Capabilities>)[key];\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction positiveNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : undefined;\n}\n", "/**\n * Token-usage cost math for the WebUI server.\n *\n * models.dev pricing is expressed in **dollars per 1,000,000 tokens**, and\n * providers omit the field entirely for free/unmetered plans. Both the\n * `session.start` payload (which ships the per-token rates to the client) and\n * `stats.get` (which reports an actual dollar figure) repeated the same\n * \"read `model.cost.*` with a `?? 0` fallback, then divide by 1e6\" logic\n * inline. Pulling it here keeps the rate normalization and the cost formula in\n * one tested place \u2014 a wrong field name or a missing `/ 1e6` silently produces\n * a plausible-but-wrong number, which is exactly what a unit test should pin.\n */\n\n/** Per-1,000,000-token pricing, normalized to numbers (0 when unpriced). */\nexport interface CostRates {\n /** $ per 1M input tokens. */\n input: number;\n /** $ per 1M output tokens. */\n output: number;\n /** $ per 1M cache-read tokens. */\n cacheRead: number;\n}\n\n/** Token counts for a turn/session. `cacheRead` is optional (older counters). */\nexport interface TokenUsage {\n input: number;\n output: number;\n cacheRead?: number | undefined;\n}\n\n/**\n * Normalize a models.dev model object's pricing into {@link CostRates}.\n * Missing model, missing `cost`, or missing individual fields all yield 0 \u2014\n * free/unmetered plans report `$0` rather than crashing.\n */\nexport function getCostRates(model: unknown): CostRates {\n const cost = (\n model as { cost?: { input?: number | undefined; output?: number | undefined; cache_read?: number | undefined } } | null | undefined\n )?.cost;\n return {\n input: cost?.input ?? 0,\n output: cost?.output ?? 0,\n cacheRead: cost?.cache_read ?? 0,\n };\n}\n\n/**\n * Dollar cost of `usage` at the given per-1M-token `rates`. Returns 0 when all\n * rates are 0 (unpriced plan).\n */\nexport function computeUsageCost(usage: TokenUsage, rates: CostRates): number {\n return (\n (usage.input * rates.input +\n usage.output * rates.output +\n (usage.cacheRead ?? 0) * rates.cacheRead) /\n 1_000_000\n );\n}\n", "import type { Agent } from '@wrongstack/core/agent';\nimport type { Config, ConfigStore, ModelsRegistry } from '@wrongstack/core/types';\nimport type { WebSocket } from 'ws';\nimport { resolveProviderModelMetadata } from './model-catalog.js';\nimport type { WSClientMessage, WSServerMessage } from './types.js';\nimport { computeUsageCost, getCostRates } from './usage-cost.js';\n\nexport interface IntrospectionRouteContext {\n agent: Agent;\n modelsRegistry?: ModelsRegistry | undefined;\n configStore?: ConfigStore | undefined;\n getConfig: () => Config;\n getProjectRoot: () => string;\n getSessionId: () => string;\n getSessionStartedAt: () => number;\n getModeId: () => string;\n send: (ws: WebSocket, message: WSServerMessage) => void;\n allowSessionMessage?: ((ws: WebSocket, message: WSClientMessage) => boolean) | undefined;\n}\n\ninterface ToolLike {\n name: string;\n description?: string | undefined;\n inputSchema?: { properties?: Record<string, unknown> } | undefined;\n mutating?: boolean | undefined;\n permission?: string | undefined;\n}\n\ninterface ToolEntryLike {\n tool: ToolLike;\n owner: string;\n}\n\nfunction toolEntries(ctx: IntrospectionRouteContext): ToolEntryLike[] {\n const registry = ctx.agent.tools as unknown as {\n list?: () => ToolLike[];\n listWithOwner?: () => ToolEntryLike[];\n listDisabled?: () => ToolEntryLike[];\n };\n if (typeof registry.listWithOwner === 'function') {\n return [\n ...registry.listWithOwner(),\n ...(typeof registry.listDisabled === 'function' ? registry.listDisabled() : []),\n ];\n }\n return (registry.list?.() ?? []).map((tool) => ({ tool, owner: 'core' }));\n}\n\nfunction persistDisabledTool(\n ctx: IntrospectionRouteContext,\n name: string,\n disabled: boolean,\n): void {\n if (!ctx.configStore) return;\n const currentTools = ctx.configStore.get().tools ?? {};\n const disabledTools = new Set(currentTools.disabledTools ?? []);\n if (disabled) disabledTools.add(name);\n else disabledTools.delete(name);\n ctx.configStore.update({ tools: { ...currentTools, disabledTools: [...disabledTools] } });\n}\n\nfunction toolName(payload: unknown): string | undefined {\n const value = (payload as { name?: unknown } | undefined)?.name;\n return typeof value === 'string' && value.trim() ? value.trim() : undefined;\n}\n\nfunction sessionAllowed(\n ctx: IntrospectionRouteContext,\n ws: WebSocket,\n message: WSClientMessage,\n): boolean {\n return ctx.allowSessionMessage?.(ws, message) ?? true;\n}\n\n/** Canonical diagnostics/tool-registry handler shared by every WebUI host. */\nexport async function handleIntrospectionRoute(\n ctx: IntrospectionRouteContext,\n ws: WebSocket,\n message: WSClientMessage,\n): Promise<boolean> {\n const actx = ctx.agent.ctx;\n const config = ctx.getConfig();\n switch (message.type) {\n case 'diag.get': {\n if (!sessionAllowed(ctx, ws, message)) return true;\n const tools = ctx.agent.tools.list();\n ctx.send(ws, {\n type: 'diag.get',\n payload: {\n provider: actx.provider.id,\n model: actx.model,\n cwd: ctx.getProjectRoot(),\n sessionId: ctx.getSessionId(),\n tools: { count: tools.length, names: tools.map((tool) => tool.name) },\n features: {\n memory: !!config.features?.memory,\n skills: !!config.features?.skills,\n modelsRegistry: !!config.features?.modelsRegistry,\n },\n mode: ctx.getModeId() || 'default',\n usage: actx.tokenCounter.total(),\n messages: actx.messages.length,\n todos: actx.todos.length,\n },\n });\n return true;\n }\n case 'stats.get': {\n if (!sessionAllowed(ctx, ws, message)) return true;\n const usage = actx.tokenCounter.total();\n const cache = actx.tokenCounter.cacheStats();\n const metadata = ctx.modelsRegistry\n ? await resolveProviderModelMetadata(\n ctx.modelsRegistry,\n actx.provider.id,\n actx.model,\n config.providers?.[actx.provider.id],\n ).catch(() => null)\n : null;\n ctx.send(ws, {\n type: 'stats.get',\n payload: {\n sessionId: ctx.getSessionId(),\n provider: actx.provider.id,\n model: actx.model,\n usage,\n cache,\n cost: metadata ? computeUsageCost(usage, getCostRates(metadata)) : null,\n messages: actx.messages.length,\n readFiles: actx.readFiles.size,\n tools: ctx.agent.tools.list().length,\n sideEffectCount: actx.sideEffects?.length ?? 0,\n elapsedMs: Date.now() - ctx.getSessionStartedAt(),\n },\n });\n return true;\n }\n case 'side_effects.list': {\n if (!sessionAllowed(ctx, ws, message)) return true;\n ctx.send(ws, {\n type: 'side_effects',\n payload: {\n sessionId: ctx.getSessionId(),\n sideEffects: (actx.sideEffects ?? []).slice(-50).map((effect) => ({\n toolUseId: effect.toolUseId,\n toolName: effect.toolName,\n ts: effect.ts,\n input: effect.input,\n outcome: effect.outcome,\n risk: effect.risk,\n })),\n },\n });\n return true;\n }\n case 'tools.list': {\n const registry = ctx.agent.tools as unknown as { isDisabled?: (name: string) => boolean };\n const tools = toolEntries(ctx).map(({ tool, owner }) => {\n const schema = tool.inputSchema ?? {};\n return {\n name: tool.name,\n owner,\n description: tool.description ?? '',\n params: schema.properties ? Object.keys(schema.properties) : [],\n disabled: registry.isDisabled?.(tool.name) ?? false,\n mutating: !!tool.mutating,\n permission: tool.permission ?? 'auto',\n };\n });\n ctx.send(ws, { type: 'tools.list', payload: { tools } });\n return true;\n }\n case 'tool.disable':\n case 'tool.enable': {\n const name = toolName(message.payload);\n if (!name) {\n ctx.send(ws, {\n type: 'error',\n payload: { message: `${message.type} requires a name` },\n });\n return true;\n }\n const disabled = message.type === 'tool.disable';\n const ok = disabled ? ctx.agent.tools.disable(name) : ctx.agent.tools.enable(name);\n if (ok) persistDisabledTool(ctx, name, disabled);\n ctx.send(ws, {\n type: disabled ? 'tool.disabled' : 'tool.enabled',\n payload: { name, ok },\n });\n return true;\n }\n default:\n return false;\n }\n}\n", "import { randomUUID } from 'node:crypto';\nimport type { Context } from '@wrongstack/core/agent';\nimport {\n areDependenciesMet,\n getServerKanbanStore,\n type KanbanBoard,\n type KanbanEventContext,\n type KanbanTask,\n} from '@wrongstack/kanban';\nimport { recordKanbanVerificationEvidence } from '@wrongstack/tools';\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from './types.js';\nimport { send } from './ws-utils.js';\n\nexport interface KanbanDispatchResult {\n status: 'completed' | 'failed';\n result?: string | undefined;\n error?: string | undefined;\n}\n\nexport type KanbanTaskDispatcher = (\n description: string,\n opts?: {\n provider?: string | undefined;\n model?: string | undefined;\n fallbackModels?: string[] | undefined;\n fallbackProfile?: string | undefined;\n skills?: string[] | undefined;\n tools?: string[] | undefined;\n name?: string | undefined;\n allowedCapabilities?: readonly string[] | undefined;\n context?:\n | {\n kanban?: { boardId?: string; taskId?: string; projectRoot?: string; leaseId?: string };\n }\n | undefined;\n onDone?: ((result: KanbanDispatchResult) => void | Promise<void>) | undefined;\n },\n) => Promise<string>;\n\nexport interface KanbanDispatchContext {\n projectRoot: string;\n context?: Context | undefined;\n broadcast?: ((message: WSServerMessage) => void) | undefined;\n dispatchTask?: KanbanTaskDispatcher | undefined;\n}\n\nexport interface ResolvedDispatchRoute {\n provider?: string | undefined;\n model?: string | undefined;\n fallbackProfile?: string | undefined;\n fallbackModels?: string[] | undefined;\n}\n\nexport function parseResolvedDispatchRoute(summary: string): ResolvedDispatchRoute {\n const tags = summary.match(/Spawned subagent\\s+\\S+\\s+\\((.*?)\\)\\s+for task/i)?.[1];\n if (!tags) return {};\n const parts = tags.split(/\\s+\\/\\s+/).map((part) => part.trim());\n const positional = parts.filter((part) => !part.includes('=') && !part.startsWith('\"'));\n const fallbackProfile = parts.find((part) => part.startsWith('profile='))?.slice(8);\n const fallback = parts.find((part) => part.startsWith('fallback='))?.slice(9);\n return {\n ...(positional[0] ? { provider: positional[0] } : {}),\n ...(positional[1] ? { model: positional[1] } : {}),\n ...(fallbackProfile ? { fallbackProfile } : {}),\n ...(fallback ? { fallbackModels: fallback.split(',').filter(Boolean) } : {}),\n };\n}\n\nfunction reply(ws: WebSocket, type: string, success: boolean, value: unknown): void {\n send(ws, {\n type,\n payload: success ? { success: true, data: value } : { success: false, error: String(value) },\n });\n}\n\nfunction activityContext(\n ctx: KanbanDispatchContext,\n note?: string,\n expectedLeaseId?: string,\n): KanbanEventContext {\n const sessionId = ctx.context?.session?.id;\n return {\n ...(sessionId ? { sessionId } : {}),\n ...(note?.trim() ? { note: note.trim() } : {}),\n ...(expectedLeaseId ? { expectedLeaseId } : {}),\n };\n}\n\nexport async function handleKanbanTaskDispatch(\n ws: WebSocket,\n payload: Record<string, unknown> | undefined,\n ctx: KanbanDispatchContext,\n): Promise<void> {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n if (!boardId || !taskId) {\n reply(ws, 'kanban.task.dispatch', false, 'boardId and taskId required');\n return;\n }\n if (!ctx.dispatchTask) {\n reply(\n ws,\n 'kanban.task.dispatch',\n false,\n 'Kanban agent dispatch is not available in this runtime',\n );\n return;\n }\n const store = getServerKanbanStore(ctx.projectRoot);\n const board = await store.getBoard(boardId);\n const task = board ? findTask(board.tasks, taskId) : undefined;\n if (!board || !task) {\n reply(ws, 'kanban.task.dispatch', false, 'Board or task not found');\n return;\n }\n\n // Check task readiness \u2014 don't dispatch if dependencies are unmet.\n if (task.dependsOn && task.dependsOn.length > 0 && !areDependenciesMet(board, task.id)) {\n reply(ws, 'kanban.task.dispatch', false, `Task \"${task.title}\" has unmet dependencies and cannot be dispatched yet.`);\n return;\n }\n\n // Enforced atomicity: a childless leaf judged too large must be decomposed\n // before dispatch. Distinct error text so the WebUI can render a\n // \"decompose\" call-to-action instead of a generic failure.\n if (\n board.atomicity?.mode === 'enforce' &&\n !task.childTaskIds?.length &&\n task.atomicityAssessment?.verdict === 'needs_decomposition'\n ) {\n reply(\n ws,\n 'kanban.task.dispatch',\n false,\n `Task \"${task.title}\" needs decomposition before dispatch (board enforces atomicity). Split it into smaller subtasks first.`,\n );\n return;\n }\n\n const modelRouting =\n (payload?.modelRouting as 'session' | 'fixed' | 'fallback_profile' | undefined) ??\n task.assignment?.modelRouting ??\n (payload?.provider || payload?.model || task.assignment?.provider || task.assignment?.model\n ? 'fixed'\n : 'session');\n const useSessionModel = modelRouting === 'session';\n // Generate a leaseId for fencing writes to the kanban board. This lease is\n // passed to the worker via the kanban context and expectedLeaseId in the\n // prompt instructions. Every subsequent updateTaskAssignment call fences\n // with expectedLeaseId so a recovered-and-reassigned task cannot be\n // overwritten by this worker's terminal writes.\n const leaseId = randomUUID();\n const now = new Date().toISOString();\n // Use a generous lease (30 min) so long-running workers do not silently\n // drop their completion result. The WebUI dispatch path has no host-side\n // heartbeat renewal (unlike kanban_queue's detached supervisor), so the\n // lease must outlive typical AI task durations. Workers that need more\n // time should call heartbeat_assignment with their expectedLeaseId.\n const leaseTtlMs = 30 * 60 * 1000;\n const leaseExpiresAt = new Date(Date.now() + leaseTtlMs).toISOString();\n const assignment = {\n agentId:\n (payload?.agentId as string | undefined) ?? task.assignment?.agentId ?? task.assignedAgent,\n name: (payload?.name as string | undefined) ?? task.assignment?.name ?? task.assignedAgent,\n role: (payload?.role as string | undefined) ?? task.assignment?.role,\n modelRouting,\n provider: useSessionModel\n ? ctx.context?.provider.id\n : ((payload?.provider as string | undefined) ?? task.assignment?.provider),\n model: useSessionModel\n ? ctx.context?.model\n : ((payload?.model as string | undefined) ?? task.assignment?.model),\n fallbackProfile:\n modelRouting === 'fallback_profile'\n ? ((payload?.fallbackProfile as string | undefined) ?? task.assignment?.fallbackProfile)\n : undefined,\n fallbackModels:\n (payload?.fallbackModels as string[] | undefined) ?? task.assignment?.fallbackModels,\n skills: (payload?.skills as string[] | undefined) ?? task.assignment?.skills,\n tools: (payload?.tools as string[] | undefined) ?? task.assignment?.tools,\n allowedCapabilities:\n (payload?.allowedCapabilities as string[] | undefined) ??\n task.assignment?.allowedCapabilities,\n maxAttempts: (payload?.maxAttempts as number | undefined) ?? task.assignment?.maxAttempts,\n costCeilingUsd:\n (payload?.costCeilingUsd as number | undefined) ??\n task.assignment?.costCeilingUsd ??\n task.costCeilingUsd,\n retryPolicy:\n (payload?.retryPolicy as KanbanTask['retryPolicy'] | undefined) ??\n task.assignment?.retryPolicy ??\n task.retryPolicy,\n attempt: (task.assignment?.attempt ?? 0) + 1,\n status: 'queued' as const,\n dispatchedAt: now,\n leaseId,\n claimedAt: now,\n heartbeatAt: now,\n leaseExpiresAt,\n };\n const assignedBoard = await store.assignTask(\n boardId,\n task.id,\n assignment,\n activityContext(ctx, payload?.activityNote as string | undefined),\n );\n if (!assignedBoard) {\n reply(ws, 'kanban.task.dispatch', false, `Failed to assign task \"${task.title}\". The task may have been removed or the board does not allow external assignment.`);\n return;\n }\n\n try {\n const summary = await ctx.dispatchTask(buildKanbanAgentPrompt(board, task, assignment, leaseId), {\n ...(assignment.provider ? { provider: assignment.provider } : {}),\n ...(assignment.model ? { model: assignment.model } : {}),\n ...(assignment.fallbackModels ? { fallbackModels: assignment.fallbackModels } : {}),\n ...(assignment.fallbackProfile ? { fallbackProfile: assignment.fallbackProfile } : {}),\n ...(assignment.skills ? { skills: assignment.skills } : {}),\n ...(assignment.tools ? { tools: assignment.tools } : {}),\n ...(assignment.name ? { name: assignment.name } : {}),\n ...(assignment.allowedCapabilities\n ? { allowedCapabilities: assignment.allowedCapabilities }\n : {}),\n context: { kanban: { boardId, taskId: task.id, projectRoot: ctx.projectRoot, leaseId } },\n onDone: async (result) => {\n const terminalWrite = await store.updateTaskAssignment(\n boardId,\n task.id,\n {\n ...assignment,\n status: result.status,\n ...(result.result !== undefined ? { lastResult: result.result } : {}),\n ...(result.error !== undefined ? { error: result.error } : {}),\n },\n activityContext(ctx, undefined, leaseId),\n );\n // Universal completion gate: updateTaskAssignment parks a completed\n // worker in review on gated boards; finalize verifies and applies the\n // final status before the board is reconciled + broadcast.\n if (result.status === 'completed' && terminalWrite) {\n try {\n const finalized = await store.finalizeTaskCompletion(boardId, task.id, {\n eventContext: activityContext(ctx, undefined, leaseId),\n });\n // Evidence bridge: link the verification report into the session's\n // completed-work ledger when this server runs inside a session.\n if (finalized?.gate.report && ctx.context) {\n recordKanbanVerificationEvidence(ctx.context, finalized.gate.report);\n }\n } catch (error) {\n console.warn(\n `[kanban-dispatch] completion gate failed for task ${task.id}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n // Managed lifecycle: finalizeTaskCompletion is intentionally a\n // no-op above; the worker's completed assignment represents the\n // Running \u2192 Review transition. Advance the card so a reviewer\n // can verify and accept it.\n if (terminalWrite.lifecycle?.mode === 'managed') {\n const managedTask = terminalWrite.tasks.find(\n (candidate: KanbanTask) => candidate.id === task.id,\n );\n if (managedTask && managedTask.lifecycle?.currentStage === 'running') {\n const actor = ctx.context?.agentId ?? 'kanban-agent';\n const comment =\n typeof result.result === 'string' && result.result.trim().length > 0\n ? result.result.trim().slice(0, 1000)\n : 'Work completed.';\n try {\n await store.transitionTask(boardId, task.id, {\n to: 'review',\n actor,\n comment,\n attachment: {\n url: `kanban://task/${task.id}/result`,\n title: 'Worker completion result',\n type: 'file',\n },\n });\n } catch (transitionError) {\n console.warn(\n `[kanban-dispatch] auto-transition to review failed for task ${task.id}: ${\n transitionError instanceof Error ? transitionError.message : String(transitionError)\n }`,\n );\n }\n }\n }\n }\n const reconciled = await store.reconcileBoard(boardId);\n const completed = reconciled?.board ?? (await store.getBoard(boardId));\n const completedTask =\n completed?.tasks.find((candidate: KanbanTask) => candidate.id === task.id) ?? task;\n ctx.broadcast?.({\n type: 'kanban.task.update',\n payload: { success: true, data: { boardId: board.id, task: completedTask } },\n });\n if (completed) {\n ctx.broadcast?.({\n type: 'kanban.get',\n payload: { success: true, data: { board: completed } },\n });\n }\n ctx.broadcast?.({\n type: 'kanban.list',\n payload: { success: true, data: await store.listBoards() },\n });\n },\n });\n const subagentId = summary.match(/Spawned subagent\\s+([^\\s]+)/)?.[1];\n const runTaskId = summary.match(/\\bfor task\\s+([^\\s.]+)/i)?.[1];\n const resolvedRoute = parseResolvedDispatchRoute(summary);\n const updated = await store.updateTaskAssignment(\n boardId,\n task.id,\n {\n ...assignment,\n ...resolvedRoute,\n status: 'running',\n ...(subagentId ? { subagentId } : {}),\n ...(runTaskId ? { runTaskId } : {}),\n lastResult: summary,\n },\n activityContext(ctx, undefined, leaseId),\n );\n // Managed lifecycle: auto-advance Todo \u2192 Running so the worker starts\n // in the correct stage. The assignment telemetry was already persisted\n // by updateTaskAssignment; a separate transition carries the lifecycle.\n // Capture post-transition board so runningTask below uses fresh state.\n let transitionBoard = updated;\n if (updated?.lifecycle?.mode === 'managed') {\n const managedTask = updated.tasks.find((candidate: KanbanTask) => candidate.id === task.id);\n if (managedTask && managedTask.lifecycle?.currentStage === 'todo') {\n try {\n const tr = await store.transitionTask(boardId, task.id, {\n to: 'running',\n actor: ctx.context?.agentId ?? 'kanban-agent',\n comment: 'Work started.',\n });\n if (tr) transitionBoard = tr.board;\n } catch (transitionErr) {\n console.warn(\n `[kanban-dispatch] auto-transition to Running failed for task ${task.id}: ${transitionErr instanceof Error ? transitionErr.message : String(transitionErr)}`,\n );\n }\n }\n }\n const runningTask =\n transitionBoard?.tasks.find((candidate: KanbanTask) => candidate.id === task.id) ?? task;\n ctx.broadcast?.({\n type: 'kanban.task.update',\n payload: { success: true, data: { boardId: board.id, task: runningTask } },\n });\n if (updated) {\n ctx.broadcast?.({ type: 'kanban.get', payload: { success: true, data: { board: updated } } });\n }\n reply(ws, 'kanban.task.dispatch', true, { boardId: board.id, task: runningTask, summary });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await store.updateTaskAssignment(\n boardId,\n task.id,\n { ...assignment, status: 'failed', error: message },\n activityContext(ctx, undefined, leaseId),\n );\n reply(ws, 'kanban.task.dispatch', false, message);\n }\n}\n\nfunction buildKanbanAgentPrompt(\n board: Pick<KanbanBoard, 'id' | 'title' | 'tasks'>,\n task: KanbanTask,\n assignment: KanbanTask['assignment'],\n leaseId: string | undefined,\n): string {\n const dependencies = (task.dependsOn ?? [])\n .map((dependencyId) => board.tasks.find((candidate) => candidate.id === dependencyId))\n .filter((dependency): dependency is KanbanTask => Boolean(dependency))\n .map((dependency) => `- ${dependency.title} [${dependency.status}] (${dependency.id})`);\n const checks = task.successCriteria?.map((check) => `- ${check.description}`).join('\\n');\n const metrics = task.goalMetrics\n ?.map(\n (metric) =>\n `- ${metric.name}: ${metric.current ?? 'n/a'}${metric.target !== undefined ? ` / ${metric.target}` : ''}${metric.unit ? ` ${metric.unit}` : ''} [${metric.status}]`,\n )\n .join('\\n');\n const chain = task.chain\n ? [\n `chainId: ${task.chain.chainId}`,\n `order: ${task.chain.order}`,\n task.chain.previousTaskId ? `previous: ${task.chain.previousTaskId}` : '',\n task.chain.nextTaskId ? `next: ${task.chain.nextTaskId}` : '',\n ]\n .filter(Boolean)\n .join('\\n')\n : '';\n const routing = [\n assignment?.role ? `role: ${assignment.role}` : '',\n assignment?.modelRouting ? `modelRouting: ${assignment.modelRouting}` : '',\n assignment?.provider ? `provider: ${assignment.provider}` : '',\n assignment?.model ? `model: ${assignment.model}` : '',\n assignment?.fallbackProfile ? `fallbackProfile: ${assignment.fallbackProfile}` : '',\n assignment?.fallbackModels?.length\n ? `fallbackModels: ${assignment.fallbackModels.join(', ')}`\n : '',\n assignment?.skills?.length ? `skills: ${assignment.skills.join(', ')}` : '',\n ].filter(Boolean);\n return [\n 'You are processing a WrongStack kanban task.',\n '',\n `Board: ${board.title} (${board.id})`,\n `Task: ${task.title} (${task.id})`,\n `Status: ${task.status}`,\n `Priority: ${task.priority}`,\n task.description ? `Description:\\n${task.description}` : '',\n routing.length ? `Routing hints:\\n${routing.join('\\n')}` : '',\n chain ? `Task chain:\\n${chain}` : '',\n dependencies.length ? `Dependencies:\\n${dependencies.join('\\n')}` : '',\n checks ? `Success criteria:\\n${checks}` : '',\n metrics ? `Goal metrics:\\n${metrics}` : '',\n task.labels?.length ? `Labels: ${task.labels.join(', ')}` : '',\n '',\n 'Work the task end-to-end. Use the kanban tool, not direct file edits, to update this task.',\n ...(leaseId ? [\n 'LEASE CONTRACT:',\n `- Your leaseId is \"${leaseId}\". Include expectedLeaseId \"${leaseId}\" in every mark_assignment and heartbeat_assignment call.`,\n '- The expectedLeaseId fence makes your write a safe no-op if recover_stale already reassigned the task because your lease expired (e.g. if you take too long).',\n '- If your lease expires, call heartbeat_assignment with expectedLeaseId to extend it, or release_task so another worker can claim.',\n 'On failure the host may call recover_stale; respect its decisions and do not duplicate work.',\n ] : []),\n `When you start or finish, call kanban with action \"mark_assignment\", boardId \"${board.id}\", taskId \"${task.id}\", and assignmentStatus \"running\", \"completed\", or \"failed\"${leaseId ? `, and expectedLeaseId \"${leaseId}\"` : ''}. Include lastResult or error when you finish. On managed lifecycle boards, mark_assignment(completed) will automatically advance your card from Running to Review \u2014 a separate verification step is required before the card reaches Done.`,\n 'When finished, report what changed, what you verified, and any remaining blockers.',\n ]\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction findTask(tasks: KanbanTask[], taskId: string): KanbanTask | undefined {\n return tasks.find((task) => task.id === taskId || task.id.startsWith(taskId));\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface KanbanHostRouteHandlers {\n meta: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n supervisorStatus: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n supervisorAudit: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n runStart: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport async function handleKanbanHostRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: KanbanHostRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'kanban.meta':\n await handlers.meta(ws, msg);\n return true;\n case 'kanban.supervisor.status':\n await handlers.supervisorStatus(ws, msg);\n return true;\n case 'kanban.supervisor.audit':\n await handlers.supervisorAudit(ws, msg);\n return true;\n case 'kanban.run.start':\n await handlers.runStart(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import type { Context } from '@wrongstack/core/agent';\nimport { deserializeTaskGraph, serializeTaskGraph } from '@wrongstack/core/tasking';\nimport type { SerializableTaskGraph } from '@wrongstack/core/types';\nimport {\n addCheckToTask,\n addColumn,\n addGoalMetricToTask,\n addNoteToTask,\n addTask,\n assignTask,\n claimReadyTask,\n copyTaskToBoard,\n createBoard,\n duplicateBoard,\n exportBoardToTaskGraph,\n createBoardFromText,\n getBoard,\n getKanbanOrchestrationSnapshot,\n getKanbanQueueHealth,\n getTaskChain,\n type KanbanBoard,\n type KanbanColumn,\n type KanbanLifecycleStage,\n type KanbanLink,\n type KanbanTask,\n type KanbanTaskPriority,\n type KanbanTaskStatus,\n type KanbanTaskTransitionInput,\n listBoards,\n listReadyTasks,\n mergeTasks,\n moveTask,\n parseLinesIntoTasks,\n reconcileKanbanBoard,\n recoverStaleTaskAssignments,\n releaseTaskClaim,\n removeBoard,\n removeColumn,\n setTaskChain,\n splitTask,\n syncBoardFromTaskGraph,\n transferTaskToBoard,\n transitionTask,\n updateBoard,\n updateCheckOnTask,\n updateGoalMetricOnTask,\n updateTask,\n} from '@wrongstack/kanban';\nimport type { WebSocket } from 'ws';\nimport type { WSClientMessage, WSServerMessage } from './types.js';\nimport { handleKanbanTaskDispatch, type KanbanTaskDispatcher } from './kanban-dispatch.js';\nimport { handleKanbanDecompositionRoute } from './kanban-decomposition-routes.js';\nimport { handleKanbanTaskRoute } from './kanban-task-routes.js';\nimport {\n activityContext,\n fail,\n findTask,\n has,\n ok,\n syncSessionSource,\n} from './kanban-route-helpers.js';\nimport { paginateKanbanBoards } from './kanban-route-pagination.js';\nexport { KANBAN_CLIENT_MESSAGE_TYPES } from './kanban-route-protocol.js';\nexport { paginateKanbanBoards, type KanbanBoardPage } from './kanban-route-pagination.js';\n\nexport interface KanbanRouteContext {\n projectRoot: string;\n context?: Context | undefined;\n broadcast?: ((msg: WSServerMessage) => void) | undefined;\n dispatchTask?: KanbanTaskDispatcher | undefined;\n}\n\nexport async function handleKanbanRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n ctx: KanbanRouteContext,\n): Promise<boolean> {\n if (!msg.type.startsWith('kanban.')) return false;\n const payload = msg.payload as Record<string, unknown> | undefined;\n const type = msg.type;\n\n try {\n if (await handleKanbanDecompositionRoute(ws, type, payload, ctx)) return true;\n if (await handleKanbanTaskRoute(ws, type, payload, ctx)) return true;\n switch (type) {\n case 'kanban.list': {\n const boards = await listBoards(ctx.projectRoot);\n const requestedPage = Number(payload?.page);\n const requestedPageSize = Number(payload?.pageSize);\n if (!Number.isFinite(requestedPage) || !Number.isFinite(requestedPageSize)) {\n // Keep the legacy array response for older clients.\n ok(ws, type, boards);\n return true;\n }\n const activeSessionIds = Array.isArray(payload?.activeSessionIds)\n ? payload.activeSessionIds.filter((id): id is string => typeof id === 'string')\n : [];\n ok(\n ws,\n type,\n paginateKanbanBoards(boards, {\n page: requestedPage,\n pageSize: requestedPageSize,\n activeSessionIds,\n }),\n );\n return true;\n }\n case 'kanban.get': {\n const boardId = payload?.boardId as string | undefined;\n if (!boardId) {\n fail(ws, type, 'boardId required');\n return true;\n }\n const board = await getBoard(ctx.projectRoot, boardId);\n board ? ok(ws, type, board) : fail(ws, type, `Board not found: ${boardId}`);\n return true;\n }\n case 'kanban.health': {\n const hBoardId = payload?.boardId as string | undefined;\n if (!hBoardId) {\n fail(ws, type, 'boardId required');\n return true;\n }\n ok(ws, type, await getKanbanQueueHealth(ctx.projectRoot, { boardId: hBoardId }));\n return true;\n }\n case 'kanban.supervisor.status':\n case 'kanban.supervisor.audit': {\n const boardId = payload?.boardId as string | undefined;\n if (!boardId) {\n fail(ws, type, 'boardId required');\n return true;\n }\n const board = await getBoard(ctx.projectRoot, boardId);\n if (!board) {\n fail(ws, type, `Board not found: ${boardId}`);\n return true;\n }\n const reconciled = await reconcileKanbanBoard(ctx.projectRoot, boardId);\n let health = await getKanbanQueueHealth(ctx.projectRoot, { boardId });\n const recovered = health.staleAssignments.count\n ? await recoverStaleTaskAssignments(ctx.projectRoot, boardId, {\n mode: board.supervisor?.recoveryMode ?? 'auto',\n reason: 'On-demand standalone Kanban supervisor audit.',\n })\n : null;\n if (recovered) health = await getKanbanQueueHealth(ctx.projectRoot, { boardId });\n const anomalyCount =\n health.staleAssignments.count +\n health.dependencyBlocked.count +\n health.failedRetryable.count +\n health.counts.failed +\n health.counts.blocked;\n ok(ws, type, {\n boardId,\n status:\n board.supervisor?.enabled === false\n ? 'disabled'\n : anomalyCount\n ? 'attention'\n : 'healthy',\n mode: board.supervisor?.mode ?? 'deterministic',\n lastAuditAt: new Date().toISOString(),\n reconciledTaskIds: reconciled?.tasks.map((task) => task.id) ?? [],\n staleRecoveredTaskIds: recovered?.tasks.map((task) => task.id) ?? [],\n anomalyCount,\n summary: `${health.counts.running} running \u00B7 ${health.counts.ready} ready \u00B7 ${health.counts.review} review \u00B7 ${health.counts.blocked} blocked \u00B7 ${health.counts.failed} failed`,\n });\n return true;\n }\n case 'kanban.create': {\n const title = payload?.title as string | undefined;\n if (!title) {\n fail(ws, type, 'title required');\n return true;\n }\n ok(\n ws,\n type,\n await createBoard(ctx.projectRoot, {\n title,\n ...(payload?.description ? { description: payload.description as string } : {}),\n ...(payload?.tags ? { tags: payload.tags as string[] } : {}),\n ...(payload?.columns ? { columns: payload.columns as KanbanColumn[] } : {}),\n ...(has(payload, 'lifecycle')\n ? { lifecycle: payload?.lifecycle as NonNullable<KanbanBoard['lifecycle']> }\n : {}),\n ...(has(payload, 'boundary')\n ? { boundary: payload?.boundary as NonNullable<KanbanBoard['boundary']> }\n : {}),\n }),\n );\n return true;\n }\n case 'kanban.update': {\n const boardId = payload?.boardId as string | undefined;\n if (!boardId) {\n fail(ws, type, 'boardId required');\n return true;\n }\n const board = await updateBoard(ctx.projectRoot, boardId, {\n ...(payload?.title ? { title: payload.title as string } : {}),\n ...(payload?.description ? { description: payload.description as string } : {}),\n ...(payload?.tags ? { tags: payload.tags as string[] } : {}),\n ...(payload?.columns ? { columns: payload.columns as KanbanColumn[] } : {}),\n ...(has(payload, 'lifecycle')\n ? {\n lifecycle:\n (payload?.lifecycle as KanbanBoard['lifecycle'] | null | undefined) ?? null,\n }\n : {}),\n ...(has(payload, 'supervisor')\n ? {\n supervisor:\n (payload?.supervisor as KanbanBoard['supervisor'] | null | undefined) ?? null,\n }\n : {}),\n ...(has(payload, 'boundary')\n ? {\n boundary: (payload?.boundary as KanbanBoard['boundary'] | null | undefined) ?? null,\n }\n : {}),\n });\n board ? ok(ws, type, board) : fail(ws, type, `Board not found: ${boardId}`);\n return true;\n }\n case 'kanban.duplicate': {\n const boardId = payload?.boardId as string | undefined;\n if (!boardId) {\n fail(ws, type, 'boardId required');\n return true;\n }\n const board = await duplicateBoard(ctx.projectRoot, boardId, {\n ...(payload?.title ? { title: payload.title as string } : {}),\n ...(typeof payload?.includeTasks === 'boolean'\n ? { includeTasks: payload.includeTasks }\n : {}),\n ...(typeof payload?.includeCompletedTasks === 'boolean'\n ? { includeCompletedTasks: payload.includeCompletedTasks }\n : {}),\n ...(typeof payload?.preserveAssignment === 'boolean'\n ? { preserveAssignment: payload.preserveAssignment }\n : {}),\n });\n board ? ok(ws, type, board) : fail(ws, type, `Board not found: ${boardId}`);\n return true;\n }\n case 'kanban.delete': {\n const boardId = payload?.boardId as string | undefined;\n if (!boardId) {\n fail(ws, type, 'boardId required');\n return true;\n }\n const board = await getBoard(ctx.projectRoot, boardId);\n const activeSessionId = ctx.context?.session?.id;\n if (activeSessionId && board?.tags?.includes(`session:${activeSessionId}`)) {\n fail(ws, type, 'The active session Kanban board cannot be deleted.');\n return true;\n }\n ok(ws, type, {\n removed: board ? await removeBoard(ctx.projectRoot, board.id) : false,\n boardId: board?.id ?? boardId,\n });\n return true;\n }\n case 'kanban.generate': {\n const description = payload?.description as string | undefined;\n if (!description) {\n fail(ws, type, 'description required');\n return true;\n }\n const board = await createBoard(\n ctx.projectRoot,\n createBoardFromText({\n description,\n ...(payload?.title ? { title: payload.title as string } : {}),\n ...(payload?.context ? { context: payload.context as string } : {}),\n }),\n );\n for (const taskInput of parseLinesIntoTasks(\n description,\n board.columns[0]?.id ?? 'backlog',\n )) {\n await addTask(ctx.projectRoot, board.id, taskInput);\n }\n ok(ws, type, (await getBoard(ctx.projectRoot, board.id)) ?? board);\n return true;\n }\n case 'kanban.task.ready': {\n ok(\n ws,\n type,\n await listReadyTasks(ctx.projectRoot, {\n ...(payload?.boardId ? { boardId: payload.boardId as string } : {}),\n ...(payload?.query ? { query: payload.query as string } : {}),\n ...(payload?.assignedAgent ? { assignedAgent: payload.assignedAgent as string } : {}),\n ...(payload?.priority ? { priority: payload.priority as KanbanTaskPriority } : {}),\n ...(payload?.label ? { label: payload.label as string } : {}),\n ...(payload?.chainId ? { chainId: payload.chainId as string } : {}),\n ...(typeof payload?.limit === 'number' ? { limit: payload.limit } : {}),\n }),\n );\n return true;\n }\n case 'kanban.snapshot': {\n ok(\n ws,\n type,\n await getKanbanOrchestrationSnapshot(ctx.projectRoot, {\n ...(payload?.boardId ? { boardId: payload.boardId as string } : {}),\n ...(payload?.query ? { query: payload.query as string } : {}),\n ...(payload?.assignedAgent ? { assignedAgent: payload.assignedAgent as string } : {}),\n ...(payload?.priority ? { priority: payload.priority as KanbanTaskPriority } : {}),\n ...(payload?.status ? { status: payload.status as KanbanTaskStatus } : {}),\n ...(payload?.label ? { label: payload.label as string } : {}),\n ...(payload?.chainId ? { chainId: payload.chainId as string } : {}),\n }),\n );\n return true;\n }\n case 'kanban.taskgraph.export': {\n const boardId = payload?.boardId as string | undefined;\n if (!boardId) {\n fail(ws, type, 'boardId required');\n return true;\n }\n const exported = await exportBoardToTaskGraph(ctx.projectRoot, boardId, {\n ...(payload?.graphId ? { graphId: payload.graphId as string } : {}),\n ...(payload?.specId ? { specId: payload.specId as string } : {}),\n ...(payload?.title ? { title: payload.title as string } : {}),\n ...(typeof payload?.preserveOriginTaskIds === 'boolean'\n ? { preserveOriginTaskIds: payload.preserveOriginTaskIds }\n : {}),\n ...(typeof payload?.includeArchived === 'boolean'\n ? { includeArchived: payload.includeArchived }\n : {}),\n });\n exported\n ? ok(ws, type, { board: exported.board, taskGraph: serializeTaskGraph(exported.graph) })\n : fail(ws, type, `Board not found: ${boardId}`);\n return true;\n }\n case 'kanban.taskgraph.sync': {\n const boardId = payload?.boardId as string | undefined;\n const taskGraph = payload?.taskGraph as SerializableTaskGraph | undefined;\n if (!boardId || !taskGraph) {\n fail(ws, type, 'boardId and taskGraph required');\n return true;\n }\n const result = await syncBoardFromTaskGraph(\n ctx.projectRoot,\n boardId,\n deserializeTaskGraph(taskGraph),\n {\n ...(payload?.title ? { title: payload.title as string } : {}),\n ...(payload?.description ? { description: payload.description as string } : {}),\n ...(payload?.tags ? { tags: payload.tags as string[] } : {}),\n ...(payload?.generatedBy ? { generatedBy: payload.generatedBy as string } : {}),\n ...(payload?.sourceSystem ? { sourceSystem: payload.sourceSystem as string } : {}),\n ...(payload?.phaseId ? { phaseId: payload.phaseId as string } : {}),\n ...(typeof payload?.includeCompletedTasks === 'boolean'\n ? { includeCompletedTasks: payload.includeCompletedTasks }\n : {}),\n ...(typeof payload?.archiveMissingTasks === 'boolean'\n ? { archiveMissingTasks: payload.archiveMissingTasks }\n : {}),\n ...(typeof payload?.preserveManualDependencies === 'boolean'\n ? { preserveManualDependencies: payload.preserveManualDependencies }\n : {}),\n },\n );\n result\n ? ok(ws, type, {\n board: result.board,\n taskIdMap: Object.fromEntries(result.taskIdMap),\n createdTaskIds: result.createdTaskIds,\n updatedTaskIds: result.updatedTaskIds,\n archivedTaskIds: result.archivedTaskIds,\n })\n : fail(ws, type, `Board not found: ${boardId}`);\n return true;\n }\n case 'kanban.task.add': {\n const boardId = payload?.boardId as string | undefined;\n const title = payload?.title as string | undefined;\n if (!boardId || !title) {\n fail(ws, type, 'boardId and title required');\n return true;\n }\n const result = await addTask(\n ctx.projectRoot,\n boardId,\n {\n title,\n columnId: (payload?.columnId as string | undefined) ?? 'backlog',\n ...(payload?.description ? { description: payload.description as string } : {}),\n ...(payload?.dueDate ? { dueDate: payload.dueDate as string } : {}),\n ...(payload?.priority ? { priority: payload.priority as KanbanTaskPriority } : {}),\n ...(payload?.assignedAgent ? { assignedAgent: payload.assignedAgent as string } : {}),\n ...(payload?.labels ? { labels: payload.labels as string[] } : {}),\n ...(has(payload, 'boundary')\n ? { boundary: payload?.boundary as NonNullable<KanbanTask['boundary']> }\n : {}),\n },\n activityContext(ctx, 'webui', payload?.activityNote as string | undefined),\n );\n result ? ok(ws, type, result.task) : fail(ws, type, `Board not found: ${boardId}`);\n return true;\n }\n case 'kanban.task.split': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const childTitles = payload?.childTitles as string[] | undefined;\n if (!boardId || !taskId || !childTitles?.length) {\n fail(ws, type, 'boardId, taskId, and childTitles required');\n return true;\n }\n const result = await splitTask(ctx.projectRoot, boardId, taskId, {\n titles: childTitles,\n ...(payload?.targetColumnId ? { columnId: payload.targetColumnId as string } : {}),\n ...(typeof payload?.inheritAssignment === 'boolean'\n ? { inheritAssignment: payload.inheritAssignment }\n : {}),\n ...(typeof payload?.inheritLabels === 'boolean'\n ? { inheritLabels: payload.inheritLabels }\n : {}),\n ...(typeof payload?.inheritSuccessCriteria === 'boolean'\n ? { inheritSuccessCriteria: payload.inheritSuccessCriteria }\n : {}),\n ...(typeof payload?.inheritGoalMetrics === 'boolean'\n ? { inheritGoalMetrics: payload.inheritGoalMetrics }\n : {}),\n ...(typeof payload?.inheritDependencies === 'boolean'\n ? { inheritDependencies: payload.inheritDependencies }\n : {}),\n ...(typeof payload?.chainChildren === 'boolean'\n ? { chainChildren: payload.chainChildren }\n : {}),\n ...(typeof payload?.rewireDependents === 'boolean'\n ? { rewireDependents: payload.rewireDependents }\n : {}),\n });\n result\n ? ok(ws, type, { board: result.board, parent: result.parent, children: result.children })\n : fail(ws, type, 'Board or task not found');\n return true;\n }\n case 'kanban.task.merge': {\n const boardId = payload?.boardId as string | undefined;\n const taskIds = payload?.taskIds as string[] | undefined;\n const title = payload?.title as string | undefined;\n if (!boardId || !taskIds?.length || !title) {\n fail(ws, type, 'boardId, taskIds, and title required');\n return true;\n }\n const result = await mergeTasks(ctx.projectRoot, boardId, {\n taskIds,\n title,\n ...(payload?.description ? { description: payload.description as string } : {}),\n ...(payload?.targetColumnId ? { targetColumnId: payload.targetColumnId as string } : {}),\n ...(typeof payload?.preserveAssignment === 'boolean'\n ? { preserveAssignment: payload.preserveAssignment }\n : {}),\n ...(typeof payload?.closeSourceTasks === 'boolean'\n ? { closeSourceTasks: payload.closeSourceTasks }\n : {}),\n });\n result\n ? ok(ws, type, {\n board: result.board,\n task: result.task,\n sourceTasks: result.sourceTasks,\n })\n : fail(ws, type, 'Board or task not found');\n return true;\n }\n case 'kanban.task.update': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n if (!boardId || !taskId) {\n fail(ws, type, 'boardId and taskId required');\n return true;\n }\n const board = await updateTask(\n ctx.projectRoot,\n boardId,\n taskId,\n {\n ...(has(payload, 'title') ? { title: payload?.title as string } : {}),\n ...(has(payload, 'description')\n ? { description: (payload?.description as string | undefined) ?? '' }\n : {}),\n ...(has(payload, 'dueDate')\n ? { dueDate: (payload?.dueDate as string | null | undefined) ?? null }\n : {}),\n ...(has(payload, 'columnId') ? { columnId: payload?.columnId as string } : {}),\n ...(has(payload, 'priority')\n ? { priority: payload?.priority as KanbanTaskPriority }\n : {}),\n ...(has(payload, 'type')\n ? { type: payload?.type as NonNullable<KanbanTask['type']> }\n : {}),\n ...(has(payload, 'status') ? { status: payload?.status as KanbanTaskStatus } : {}),\n ...(has(payload, 'dependsOn')\n ? { dependsOn: (payload?.dependsOn as string[] | undefined) ?? [] }\n : {}),\n ...(has(payload, 'chain')\n ? { chain: (payload?.chain as KanbanTask['chain'] | null | undefined) ?? null }\n : {}),\n ...(has(payload, 'labels')\n ? { labels: (payload?.labels as string[] | undefined) ?? [] }\n : {}),\n ...(has(payload, 'estimatedHours')\n ? { estimatedHours: Number(payload?.estimatedHours ?? 0) }\n : {}),\n ...(has(payload, 'actualHours')\n ? { actualHours: Number(payload?.actualHours ?? 0) }\n : {}),\n ...(has(payload, 'retryPolicy')\n ? {\n retryPolicy:\n (payload?.retryPolicy as KanbanTask['retryPolicy'] | null | undefined) ?? null,\n }\n : {}),\n ...(has(payload, 'costCeilingUsd')\n ? {\n costCeilingUsd:\n payload?.costCeilingUsd === null || payload?.costCeilingUsd === ''\n ? null\n : Number(payload?.costCeilingUsd),\n }\n : {}),\n ...(has(payload, 'boundary')\n ? {\n boundary:\n (payload?.boundary as KanbanTask['boundary'] | null | undefined) ?? null,\n }\n : {}),\n },\n activityContext(ctx, 'webui', payload?.activityNote as string | undefined),\n );\n if (!board) {\n fail(ws, type, 'Board or task not found');\n return true;\n }\n const task = findTask(board.tasks, taskId);\n if (task) await syncSessionSource(ctx, task);\n ok(ws, type, task);\n return true;\n }\n case 'kanban.task.transition': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const to = payload?.to as KanbanLifecycleStage | undefined;\n const actor = payload?.actor as string | undefined;\n const comment = payload?.comment as string | undefined;\n if (!boardId || !taskId || !to || !actor || !comment) {\n fail(ws, type, 'boardId, taskId, to, actor, and comment required');\n return true;\n }\n const result = await transitionTask(ctx.projectRoot, boardId, taskId, {\n to,\n actor,\n comment,\n ...(payload?.action ? { action: payload.action as string } : {}),\n ...(payload?.attachment ? { attachment: payload.attachment as KanbanLink } : {}),\n ...(payload?.patch\n ? { patch: payload.patch as NonNullable<KanbanTaskTransitionInput['patch']> }\n : {}),\n });\n if (!result) {\n fail(ws, type, 'Board or task not found');\n return true;\n }\n await syncSessionSource(ctx, result.task);\n ok(ws, type, result);\n return true;\n }\n case 'kanban.task.move': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const columnId = payload?.columnId as string | undefined;\n if (!boardId || !taskId || !columnId) {\n fail(ws, type, 'boardId, taskId, columnId required');\n return true;\n }\n const board = await moveTask(\n ctx.projectRoot,\n boardId,\n taskId,\n columnId,\n payload?.order as number | undefined,\n activityContext(ctx, 'webui', payload?.activityNote as string | undefined),\n );\n if (!board) {\n fail(ws, type, 'Move failed');\n return true;\n }\n const task = findTask(board.tasks, taskId);\n if (task) await syncSessionSource(ctx, task);\n ok(ws, type, task);\n return true;\n }\n case 'kanban.task.copy':\n case 'kanban.task.transfer': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const targetBoardId = payload?.targetBoardId as string | undefined;\n if (!boardId || !taskId || !targetBoardId) {\n fail(ws, type, 'boardId, taskId, targetBoardId required');\n return true;\n }\n const result =\n type === 'kanban.task.copy'\n ? await copyTaskToBoard(ctx.projectRoot, boardId, taskId, targetBoardId, {\n ...(payload?.targetColumnId\n ? { targetColumnId: payload.targetColumnId as string }\n : {}),\n ...(typeof payload?.preserveAssignment === 'boolean'\n ? { preserveAssignment: payload.preserveAssignment }\n : {}),\n ...(typeof payload?.preserveDependencies === 'boolean'\n ? { preserveDependencies: payload.preserveDependencies }\n : {}),\n })\n : await transferTaskToBoard(ctx.projectRoot, boardId, taskId, targetBoardId, {\n ...(payload?.targetColumnId\n ? { targetColumnId: payload.targetColumnId as string }\n : {}),\n ...(typeof payload?.preserveAssignment === 'boolean'\n ? { preserveAssignment: payload.preserveAssignment }\n : {}),\n ...(typeof payload?.preserveDependencies === 'boolean'\n ? { preserveDependencies: payload.preserveDependencies }\n : {}),\n });\n result ? ok(ws, type, result.targetBoard) : fail(ws, type, 'Board or task not found');\n return true;\n }\n case 'kanban.task.chain': {\n const boardId = payload?.boardId as string | undefined;\n const taskIds = payload?.taskIds as string[] | undefined;\n if (!boardId || !taskIds?.length) {\n fail(ws, type, 'boardId and taskIds required');\n return true;\n }\n const result = await setTaskChain(ctx.projectRoot, boardId, {\n taskIds,\n ...(payload?.chainId ? { chainId: payload.chainId as string } : {}),\n ...(typeof payload?.enforceDependencies === 'boolean'\n ? { enforceDependencies: payload.enforceDependencies }\n : {}),\n });\n result\n ? ok(ws, type, { board: result.board, chainId: result.chainId, tasks: result.tasks })\n : fail(ws, type, 'Board or task not found');\n return true;\n }\n case 'kanban.task.chain.get': {\n const boardId = payload?.boardId as string | undefined;\n const taskOrChainId =\n (payload?.taskId as string | undefined) ?? (payload?.chainId as string | undefined);\n if (!boardId || !taskOrChainId) {\n fail(ws, type, 'boardId and taskId or chainId required');\n return true;\n }\n const result = await getTaskChain(ctx.projectRoot, boardId, taskOrChainId);\n result\n ? ok(ws, type, { board: result.board, chainId: result.chainId, tasks: result.tasks })\n : fail(ws, type, 'Chain not found');\n return true;\n }\n case 'kanban.task.claim': {\n const result = await claimReadyTask(ctx.projectRoot, {\n ...(payload?.boardId ? { boardId: payload.boardId as string } : {}),\n ...(payload?.taskId ? { taskId: payload.taskId as string } : {}),\n ...(payload?.agentId ? { agentId: payload.agentId as string } : {}),\n ...(payload?.name ? { name: payload.name as string } : {}),\n ...(payload?.role ? { role: payload.role as string } : {}),\n ...(payload?.provider ? { provider: payload.provider as string } : {}),\n ...(payload?.model ? { model: payload.model as string } : {}),\n ...(payload?.modelRouting\n ? { modelRouting: payload.modelRouting as 'session' | 'fixed' | 'fallback_profile' }\n : {}),\n ...(payload?.fallbackProfile\n ? { fallbackProfile: payload.fallbackProfile as string }\n : {}),\n ...(payload?.fallbackModels\n ? { fallbackModels: payload.fallbackModels as string[] }\n : {}),\n ...(payload?.skills ? { skills: payload.skills as string[] } : {}),\n ...(payload?.tools ? { tools: payload.tools as string[] } : {}),\n ...(payload?.allowedCapabilities\n ? { allowedCapabilities: payload.allowedCapabilities as string[] }\n : {}),\n ...(payload?.assignee ? { assignee: payload.assignee as string } : {}),\n status:\n (payload?.assignmentStatus as 'assigned' | 'queued' | 'running' | undefined) ??\n 'queued',\n });\n result\n ? ok(ws, type, { board: result.board, task: result.task })\n : fail(ws, type, 'No ready kanban task matched the claim');\n return true;\n }\n case 'kanban.task.release': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n if (!boardId || !taskId) {\n fail(ws, type, 'boardId and taskId required');\n return true;\n }\n const board = await releaseTaskClaim(ctx.projectRoot, boardId, taskId, {\n ...(payload?.status ? { status: payload.status as 'pending' | 'ready' | 'blocked' } : {}),\n ...(payload?.reason ? { reason: payload.reason as string } : {}),\n ...(typeof payload?.clearAssignee === 'boolean'\n ? { clearAssignee: payload.clearAssignee }\n : {}),\n ...(typeof payload?.maxAttempts === 'number' ? { maxAttempts: payload.maxAttempts } : {}),\n ...(typeof payload?.costCeilingUsd === 'number'\n ? { costCeilingUsd: payload.costCeilingUsd }\n : {}),\n ...(payload?.retryPolicy\n ? { retryPolicy: payload.retryPolicy as NonNullable<KanbanTask['retryPolicy']> }\n : {}),\n });\n board ? ok(ws, type, board) : fail(ws, type, 'Board or task not found');\n return true;\n }\n case 'kanban.task.metric.add': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const name = payload?.name as string | undefined;\n if (!boardId || !taskId || !name) {\n fail(ws, type, 'boardId, taskId, and name required');\n return true;\n }\n const board = await addGoalMetricToTask(\n ctx.projectRoot,\n boardId,\n taskId,\n {\n name,\n ...(payload?.status\n ? { status: payload.status as 'pending' | 'met' | 'missed' | 'waived' }\n : {}),\n ...(payload?.target !== undefined ? { target: payload.target as string | number } : {}),\n ...(payload?.current !== undefined\n ? { current: payload.current as string | number }\n : {}),\n ...(payload?.unit ? { unit: payload.unit as string } : {}),\n ...(payload?.notes ? { notes: payload.notes as string } : {}),\n },\n activityContext(\n ctx,\n 'webui',\n (payload?.activityNote as string | undefined) ?? `Goal metric added: ${name}.`,\n ),\n );\n board ? ok(ws, type, board) : fail(ws, type, 'Board or task not found');\n return true;\n }\n case 'kanban.task.metric.update': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const metricId = payload?.metricId as string | undefined;\n if (!boardId || !taskId || !metricId) {\n fail(ws, type, 'boardId, taskId, and metricId required');\n return true;\n }\n const board = await updateGoalMetricOnTask(\n ctx.projectRoot,\n boardId,\n taskId,\n metricId,\n {\n ...(payload?.name ? { name: payload.name as string } : {}),\n ...(payload?.status\n ? { status: payload.status as 'pending' | 'met' | 'missed' | 'waived' }\n : {}),\n ...(payload?.target !== undefined ? { target: payload.target as string | number } : {}),\n ...(payload?.current !== undefined\n ? { current: payload.current as string | number }\n : {}),\n ...(payload?.unit ? { unit: payload.unit as string } : {}),\n ...(payload?.notes ? { notes: payload.notes as string } : {}),\n },\n activityContext(\n ctx,\n 'webui',\n (payload?.activityNote as string | undefined) ?? 'Goal metric updated in WebUI.',\n ),\n );\n board ? ok(ws, type, board) : fail(ws, type, 'Metric not found');\n return true;\n }\n case 'kanban.task.assign': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n if (!boardId || !taskId) {\n fail(ws, type, 'boardId and taskId required');\n return true;\n }\n const board = await assignTask(\n ctx.projectRoot,\n boardId,\n taskId,\n {\n ...(payload?.agentId ? { agentId: payload.agentId as string } : {}),\n ...(payload?.name ? { name: payload.name as string } : {}),\n ...(payload?.role ? { role: payload.role as string } : {}),\n ...(payload?.provider ? { provider: payload.provider as string } : {}),\n ...(payload?.model ? { model: payload.model as string } : {}),\n ...(payload?.modelRouting\n ? { modelRouting: payload.modelRouting as 'session' | 'fixed' | 'fallback_profile' }\n : {}),\n ...(payload?.fallbackProfile\n ? { fallbackProfile: payload.fallbackProfile as string }\n : {}),\n ...(payload?.fallbackModels\n ? { fallbackModels: payload.fallbackModels as string[] }\n : {}),\n ...(payload?.skills ? { skills: payload.skills as string[] } : {}),\n ...(payload?.tools ? { tools: payload.tools as string[] } : {}),\n ...(payload?.allowedCapabilities\n ? { allowedCapabilities: payload.allowedCapabilities as string[] }\n : {}),\n ...(payload?.assignee ? { assignee: payload.assignee as string } : {}),\n ...(payload?.maxAttempts !== undefined\n ? { maxAttempts: Number(payload.maxAttempts) }\n : {}),\n ...(payload?.costCeilingUsd !== undefined\n ? { costCeilingUsd: Number(payload.costCeilingUsd) }\n : {}),\n ...(payload?.retryPolicy\n ? { retryPolicy: payload.retryPolicy as NonNullable<KanbanTask['retryPolicy']> }\n : {}),\n },\n activityContext(ctx, undefined, payload?.activityNote as string | undefined),\n );\n board\n ? ok(ws, type, findTask(board.tasks, taskId))\n : fail(ws, type, 'Board or task not found');\n return true;\n }\n case 'kanban.task.check.add': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const description = payload?.description as string | undefined;\n if (!boardId || !taskId || !description) {\n fail(ws, type, 'boardId, taskId, and description required');\n return true;\n }\n const board = await addCheckToTask(\n ctx.projectRoot,\n boardId,\n taskId,\n {\n description,\n type:\n (payload?.checkType as 'manual' | 'auto' | 'agent' | 'test' | 'review') ?? 'manual',\n status: (payload?.status as 'pending' | 'passed' | 'failed' | 'skipped') ?? 'pending',\n },\n activityContext(\n ctx,\n 'webui',\n (payload?.activityNote as string | undefined) ??\n `Acceptance check added: ${description}.`,\n ),\n );\n board ? ok(ws, type, board) : fail(ws, type, 'Board or task not found');\n return true;\n }\n case 'kanban.task.check.update': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const checkId = payload?.checkId as string | undefined;\n if (!boardId || !taskId || !checkId) {\n fail(ws, type, 'boardId, taskId, and checkId required');\n return true;\n }\n const board = await updateCheckOnTask(\n ctx.projectRoot,\n boardId,\n taskId,\n checkId,\n {\n ...(has(payload, 'status')\n ? { status: payload?.status as 'pending' | 'passed' | 'failed' | 'skipped' }\n : {}),\n },\n activityContext(\n ctx,\n 'webui',\n (payload?.activityNote as string | undefined) ??\n `Acceptance check updated${payload?.status ? ` to ${String(payload.status)}` : ''}.`,\n ),\n );\n if (!board) fail(ws, type, 'Check not found');\n else ok(ws, type, (await reconcileKanbanBoard(ctx.projectRoot, boardId))?.board ?? board);\n return true;\n }\n case 'kanban.task.note.add': {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const content = payload?.content as string | undefined;\n if (!boardId || !taskId || !content) {\n fail(ws, type, 'boardId, taskId, and content required');\n return true;\n }\n const author = (payload?.author as string | undefined) ?? 'webui';\n const board = await addNoteToTask(\n ctx.projectRoot,\n boardId,\n taskId,\n {\n author,\n content,\n },\n activityContext(ctx, author),\n );\n board ? ok(ws, type, board) : fail(ws, type, 'Board or task not found');\n return true;\n }\n case 'kanban.task.dispatch':\n await handleKanbanTaskDispatch(ws, payload, ctx);\n return true;\n case 'kanban.capabilities':\n ok(ws, type, { dispatchSupported: Boolean(ctx.dispatchTask) });\n return true;\n case 'kanban.column.add': {\n const boardId = payload?.boardId as string | undefined;\n const title = payload?.title as string | undefined;\n if (!boardId || !title) {\n fail(ws, type, 'boardId and title required');\n return true;\n }\n const result = await addColumn(ctx.projectRoot, boardId, { title });\n result ? ok(ws, type, result.board.columns) : fail(ws, type, `Board not found: ${boardId}`);\n return true;\n }\n case 'kanban.column.remove': {\n const boardId = payload?.boardId as string | undefined;\n const columnId = payload?.columnId as string | undefined;\n if (!boardId || !columnId) {\n fail(ws, type, 'boardId and columnId required');\n return true;\n }\n const board = await removeColumn(ctx.projectRoot, boardId, columnId, {\n moveTasksToColumnId: payload?.moveTasksToColumnId as string | undefined,\n });\n board\n ? ok(ws, type, { removed: true, boardId: board.id, columnId, board })\n : fail(ws, type, `Column not found: ${columnId}`);\n return true;\n }\n default:\n fail(ws, type, `Unknown kanban message type: ${type}`);\n return true;\n }\n } catch (err) {\n fail(ws, type, err instanceof Error ? err.message : String(err));\n return true;\n }\n}\n", "import type { Context } from '@wrongstack/core/agent';\nimport {\n listBoards,\n resolveDecompositionProposal,\n updateTask,\n verifyTaskCompletion,\n type KanbanDecompositionSubtask,\n} from '@wrongstack/kanban';\nimport { recordKanbanVerificationEvidence } from '@wrongstack/tools';\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from './types.js';\nimport { fail, ok } from './kanban-route-helpers.js';\n\nexport interface KanbanDecompositionRouteContext {\n projectRoot: string;\n context?: Context | undefined;\n broadcast?: ((msg: WSServerMessage) => void) | undefined;\n}\n\nexport async function handleKanbanDecompositionRoute(\n ws: WebSocket,\n type: string,\n payload: Record<string, unknown> | undefined,\n ctx: KanbanDecompositionRouteContext,\n): Promise<boolean> {\n switch (type) {\n case 'kanban.decomposition.approve':\n case 'kanban.decomposition.reject':\n await handleDecompositionResolution(ws, type, payload, ctx);\n return true;\n case 'kanban.task.verify':\n await handleTaskVerification(ws, type, payload, ctx);\n return true;\n default:\n return false;\n }\n}\n\nasync function handleDecompositionResolution(\n ws: WebSocket,\n type: string,\n payload: Record<string, unknown> | undefined,\n ctx: KanbanDecompositionRouteContext,\n): Promise<void> {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const proposalId = payload?.proposalId as string | undefined;\n if (!boardId || !taskId || !proposalId) {\n fail(ws, type, 'boardId, taskId, and proposalId required');\n return;\n }\n const action = type === 'kanban.decomposition.approve' ? 'approve' : 'reject';\n let edits: KanbanDecompositionSubtask[] | undefined;\n if (Array.isArray(payload?.edits)) {\n const rawEdits = payload.edits as unknown[];\n const valid = rawEdits.every(\n (e): e is KanbanDecompositionSubtask =>\n e !== null &&\n typeof e === 'object' &&\n typeof (e as Record<string, unknown>).title === 'string',\n );\n if (!valid) {\n fail(ws, type, 'Each edit must be an object with a string \"title\"');\n return;\n }\n edits = rawEdits;\n }\n const resolved = await resolveDecompositionProposal(ctx.projectRoot, boardId, taskId, proposalId, {\n action,\n ...(typeof payload?.reason === 'string' ? { reason: payload.reason } : {}),\n ...(edits ? { editedSubtasks: edits } : {}),\n resolvedBy: 'webui',\n });\n if (!resolved) {\n fail(ws, type, `Proposal not found or already resolved: ${proposalId}`);\n return;\n }\n ok(ws, type, { boardId, task: resolved.task });\n if (action === 'approve') {\n ctx.broadcast?.({\n type: 'kanban.decomposition.applied',\n payload: { success: true, data: { board: resolved.board } },\n });\n ctx.broadcast?.({\n type: 'kanban.get',\n payload: { success: true, data: { board: resolved.board } },\n });\n ctx.broadcast?.({\n type: 'kanban.list',\n payload: { success: true, data: await listBoards(ctx.projectRoot) },\n });\n } else {\n ctx.broadcast?.({\n type: 'kanban.decomposition.resolved',\n payload: { success: true, data: { boardId, task: resolved.task } },\n });\n }\n}\n\nasync function handleTaskVerification(\n ws: WebSocket,\n type: string,\n payload: Record<string, unknown> | undefined,\n ctx: KanbanDecompositionRouteContext,\n): Promise<void> {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n if (!boardId || !taskId) {\n fail(ws, type, 'boardId and taskId required');\n return;\n }\n ctx.broadcast?.({\n type: 'kanban.task.verification_started',\n payload: { success: true, data: { boardId, taskId } },\n });\n try {\n const verResult = await verifyTaskCompletion(ctx.projectRoot, boardId, taskId);\n const persisted = await updateTask(ctx.projectRoot, boardId, taskId, {\n verificationReport: verResult.report,\n successCriteria: verResult.task.successCriteria,\n });\n const freshTask =\n persisted?.tasks.find((candidate) => candidate.id === verResult.task.id) ?? verResult.task;\n if (ctx.context) recordKanbanVerificationEvidence(ctx.context, verResult.report);\n ok(ws, type, { boardId, task: freshTask });\n ctx.broadcast?.({\n type: 'kanban.task.verification_completed',\n payload: { success: true, data: { boardId, task: freshTask } },\n });\n if (persisted) {\n ctx.broadcast?.({\n type: 'kanban.get',\n payload: { success: true, data: { board: persisted } },\n });\n }\n } catch (err) {\n ctx.broadcast?.({\n type: 'kanban.task.verification_completed',\n payload: {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n data: { boardId, taskId },\n },\n });\n fail(ws, type, err instanceof Error ? err.message : String(err));\n }\n}\n", "import type { Context } from '@wrongstack/core/agent';\nimport type {\n KanbanBoard,\n KanbanEventContext,\n KanbanTask,\n} from '@wrongstack/kanban';\nimport { touchKanbanPresence } from '@wrongstack/kanban';\nimport { applySessionKanbanTaskToSource } from '@wrongstack/tools/session-kanban';\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from './types.js';\nimport { send } from './ws-utils.js';\n\nexport interface KanbanRouteHelperContext {\n projectRoot: string;\n context?: Context | undefined;\n broadcast?: ((msg: WSServerMessage) => void) | undefined;\n}\n\nexport async function syncSessionSource(\n ctx: KanbanRouteHelperContext,\n task: KanbanTask,\n remove = false,\n): Promise<void> {\n if (!ctx.context) return;\n const update = await applySessionKanbanTaskToSource(ctx.context, task, { remove });\n const sessionId = ctx.context.session?.id ?? '';\n if (update.todos)\n ctx.broadcast?.({ type: 'todos.updated', payload: { sessionId, todos: update.todos } });\n if (update.tasks)\n ctx.broadcast?.({ type: 'tasks.updated', payload: { sessionId, tasks: update.tasks.tasks } });\n if (update.plan)\n ctx.broadcast?.({ type: 'plan.updated', payload: { sessionId, plan: update.plan } });\n}\n\nexport function ok(ws: WebSocket, type: string, data?: unknown): void {\n send(ws, { type, payload: { success: true, data: data ?? null } });\n}\n\nexport function fail(ws: WebSocket, type: string, message: string): void {\n send(ws, { type, payload: { success: false, error: message } });\n}\n\nexport function has(payload: Record<string, unknown> | undefined, key: string): boolean {\n return payload !== undefined && Object.hasOwn(payload, key);\n}\n\nexport function activityContext(\n ctx: KanbanRouteHelperContext,\n actor?: string,\n note?: string,\n): KanbanEventContext {\n const sessionId = ctx.context?.session?.id;\n return {\n ...(sessionId ? { sessionId } : {}),\n ...(actor ? { actor } : {}),\n ...(note?.trim() ? { note: note.trim() } : {}),\n };\n}\n\nexport async function touchTaskPresence(\n ctx: KanbanRouteHelperContext,\n boardId: string,\n taskId: string,\n): Promise<KanbanBoard | null> {\n const context = ctx.context;\n const sessionId = context?.session?.id;\n if (!context || !sessionId) return null;\n try {\n return await touchKanbanPresence(ctx.projectRoot, boardId, {\n sessionId,\n agentId: context.agentId || 'webui',\n agentName: context.agentName || context.agentId || 'WebUI',\n taskId,\n });\n } catch {\n return null;\n }\n}\n\nexport function findTask(tasks: KanbanTask[], taskId: string): KanbanTask | undefined {\n return tasks.find((task) => task.id === taskId || task.id.startsWith(taskId));\n}\n", "import type { Context } from '@wrongstack/core/agent';\nimport {\n getTask,\n listTaskActivity,\n recordTaskActivity,\n removeTask,\n} from '@wrongstack/kanban';\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from './types.js';\nimport {\n activityContext,\n fail,\n ok,\n syncSessionSource,\n touchTaskPresence,\n} from './kanban-route-helpers.js';\n\nexport interface KanbanTaskRouteContext {\n projectRoot: string;\n context?: Context | undefined;\n broadcast?: ((msg: WSServerMessage) => void) | undefined;\n}\n\nexport async function handleKanbanTaskRoute(\n ws: WebSocket,\n type: string,\n payload: Record<string, unknown> | undefined,\n ctx: KanbanTaskRouteContext,\n): Promise<boolean> {\n switch (type) {\n case 'kanban.task.remove':\n await handleTaskRemove(ws, type, payload, ctx);\n return true;\n case 'kanban.task.get':\n await handleTaskGet(ws, type, payload, ctx);\n return true;\n case 'kanban.task.activity':\n await handleTaskActivity(ws, type, payload, ctx);\n return true;\n case 'kanban.task.activity.add':\n await handleTaskActivityAdd(ws, type, payload, ctx);\n return true;\n default:\n return false;\n }\n}\n\nasync function handleTaskRemove(\n ws: WebSocket,\n type: string,\n payload: Record<string, unknown> | undefined,\n ctx: KanbanTaskRouteContext,\n): Promise<void> {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n if (!boardId || !taskId) {\n fail(ws, type, 'boardId and taskId required');\n return;\n }\n const task = await getTask(ctx.projectRoot, boardId, taskId);\n if (!task) {\n fail(ws, type, 'Board or task not found');\n return;\n }\n const board = await removeTask(ctx.projectRoot, boardId, taskId);\n if (!board) {\n fail(ws, type, 'Board or task not found');\n return;\n }\n await syncSessionSource(ctx, task, true);\n ok(ws, type, { removed: true, boardId: board.id, taskId: task.id, board });\n}\n\nasync function handleTaskGet(\n ws: WebSocket,\n type: string,\n payload: Record<string, unknown> | undefined,\n ctx: KanbanTaskRouteContext,\n): Promise<void> {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n if (!boardId || !taskId) {\n fail(ws, type, 'boardId and taskId required');\n return;\n }\n const task = await getTask(ctx.projectRoot, boardId, taskId);\n if (task) {\n await touchTaskPresence(ctx, boardId, task.id);\n ok(ws, type, task);\n } else {\n fail(ws, type, 'Task not found');\n }\n}\n\nasync function handleTaskActivity(\n ws: WebSocket,\n type: string,\n payload: Record<string, unknown> | undefined,\n ctx: KanbanTaskRouteContext,\n): Promise<void> {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n if (!boardId || !taskId) {\n fail(ws, type, 'boardId and taskId required');\n return;\n }\n const presenceBoard = await touchTaskPresence(ctx, boardId, taskId);\n const events = await listTaskActivity(ctx.projectRoot, boardId, taskId, {\n ...(typeof payload?.limit === 'number' ? { limit: payload.limit } : {}),\n });\n ok(ws, type, {\n boardId,\n taskId,\n events,\n presence: presenceBoard?.presence?.filter((entry) => entry.taskId === taskId) ?? [],\n });\n}\n\nasync function handleTaskActivityAdd(\n ws: WebSocket,\n type: string,\n payload: Record<string, unknown> | undefined,\n ctx: KanbanTaskRouteContext,\n): Promise<void> {\n const boardId = payload?.boardId as string | undefined;\n const taskId = payload?.taskId as string | undefined;\n const kind = payload?.kind as string | undefined;\n const summary = payload?.summary as string | undefined;\n const allowedKinds = ['decision', 'attempt', 'result', 'blocker', 'observation'] as const;\n const allowedOutcomes = ['succeeded', 'failed', 'partial', 'skipped', 'unknown'] as const;\n if (!boardId || !taskId || !summary?.trim() || !allowedKinds.includes(kind as never)) {\n fail(ws, type, 'boardId, taskId, summary, and a valid activity kind required');\n return;\n }\n const requestedOutcome = payload?.outcome as string | undefined;\n const outcome = allowedOutcomes.includes(requestedOutcome as never)\n ? (requestedOutcome as (typeof allowedOutcomes)[number])\n : 'unknown';\n const board = await recordTaskActivity(\n ctx.projectRoot,\n boardId,\n taskId,\n {\n kind: kind as (typeof allowedKinds)[number],\n summary: summary.trim(),\n outcome,\n ...(typeof payload?.details === 'string' && payload.details.trim()\n ? { details: payload.details.trim() }\n : {}),\n },\n activityContext(\n ctx,\n (payload?.actor as string | undefined) ?? ctx.context?.agentId ?? 'webui',\n ),\n );\n board ? ok(ws, type, board) : fail(ws, type, 'Board or task not found');\n}\n", "import type { KanbanBoardSummary } from '@wrongstack/kanban';\n\nexport interface KanbanBoardPage {\n items: KanbanBoardSummary[];\n total: number;\n page: number;\n pageSize: number;\n totalPages: number;\n activeTotal: number;\n orphanedTotal: number;\n}\n\nexport function paginateKanbanBoards(\n boards: KanbanBoardSummary[],\n input: { page: number; pageSize: number; activeSessionIds?: readonly string[] | undefined },\n): KanbanBoardPage {\n const pageSize = Math.min(100, Math.max(1, Math.floor(input.pageSize)));\n const activeSessionIds = new Set(input.activeSessionIds ?? []);\n const isActive = (board: KanbanBoardSummary) =>\n board.presence?.some((entry) => entry.active) === true ||\n board.tags?.some((tag) => tag.startsWith('session:') && activeSessionIds.has(tag.slice(8))) ===\n true;\n const sorted = [...boards].sort((left, right) => {\n const activityOrder = Number(isActive(right)) - Number(isActive(left));\n return activityOrder || right.updatedAt.localeCompare(left.updatedAt);\n });\n const activeTotal = sorted.filter(isActive).length;\n const total = sorted.length;\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n const requestedPage = Number.isFinite(input.page) ? Math.floor(input.page) : 1;\n const page = Math.min(totalPages, Math.max(1, requestedPage));\n const start = (page - 1) * pageSize;\n return {\n items: sorted.slice(start, start + pageSize),\n total,\n page,\n pageSize,\n totalPages,\n activeTotal,\n orphanedTotal: total - activeTotal,\n };\n}\n", "export const KANBAN_CLIENT_MESSAGE_TYPES = [\n 'kanban.capabilities',\n 'kanban.column.add',\n 'kanban.column.remove',\n 'kanban.create',\n 'kanban.decomposition.approve',\n 'kanban.decomposition.reject',\n 'kanban.delete',\n 'kanban.duplicate',\n 'kanban.generate',\n 'kanban.get',\n 'kanban.health',\n 'kanban.list',\n 'kanban.snapshot',\n 'kanban.supervisor.audit',\n 'kanban.supervisor.status',\n 'kanban.task.activity',\n 'kanban.task.activity.add',\n 'kanban.task.add',\n 'kanban.task.assign',\n 'kanban.task.chain',\n 'kanban.task.chain.get',\n 'kanban.task.check.add',\n 'kanban.task.check.update',\n 'kanban.task.claim',\n 'kanban.task.copy',\n 'kanban.task.dispatch',\n 'kanban.task.get',\n 'kanban.task.merge',\n 'kanban.task.metric.add',\n 'kanban.task.metric.update',\n 'kanban.task.move',\n 'kanban.task.note.add',\n 'kanban.task.ready',\n 'kanban.task.release',\n 'kanban.task.remove',\n 'kanban.task.split',\n 'kanban.task.transfer',\n 'kanban.task.transition',\n 'kanban.task.update',\n 'kanban.task.verify',\n 'kanban.taskgraph.export',\n 'kanban.taskgraph.sync',\n 'kanban.update',\n] as const;\n", "/**\n * Kanban daemon event subscriber \u2014 replaces `kanban-board-watcher.ts`.\n *\n * Instead of polling the old board-file directory with `fs.watch`,\n * this subscribes to push events from the Kanban IPC daemon via\n * `bridgeKanbanSupervisor`. When a mutation event arrives (board created,\n * task added, column moved, etc.), the affected board is re-read through\n * `ServerKanbanStore` and broadcast to all WebSocket clients.\n *\n * Benefits over the file watcher:\n * - No filesystem polling (lower latency, no inotify/FSEvents overhead)\n * - No `fs.watch` platform quirks (Windows EPERM, macOS FSEvents latency)\n * - Works through the daemon's SQLite revision serialization\n * - Auto-reconnects when the daemon restarts\n */\nimport { bridgeKanbanSupervisor, getServerKanbanStore } from '@wrongstack/kanban';\nimport type { WSServerMessage } from './types.js';\n\nexport function subscribeKanbanDaemonEvents(\n projectRoot: string,\n broadcastMessage: (message: WSServerMessage) => void,\n): () => void {\n const store = getServerKanbanStore(projectRoot);\n const knownRevisions = new Map<string, string>();\n let connectionCount = 0;\n\n const broadcastDeleted = (boardId: string): void => {\n knownRevisions.delete(boardId);\n broadcastMessage({\n type: 'kanban.delete',\n payload: { success: true, data: { removed: true, boardId } },\n });\n };\n\n const broadcastBoard = async (boardId: string): Promise<void> => {\n const board = await store.getBoard(boardId);\n if (!board) {\n broadcastDeleted(boardId);\n return;\n }\n knownRevisions.set(boardId, board.updatedAt);\n broadcastMessage({\n type: 'kanban.get',\n payload: { success: true, data: { board } },\n } as WSServerMessage);\n };\n\n const reconcileAfterConnect = async (): Promise<void> => {\n const summaries = await store.listBoards();\n connectionCount++;\n if (connectionCount === 1) {\n for (const summary of summaries) knownRevisions.set(summary.id, summary.updatedAt);\n return;\n }\n const present = new Set(summaries.map((summary) => summary.id));\n for (const boardId of [...knownRevisions.keys()]) {\n if (!present.has(boardId)) broadcastDeleted(boardId);\n }\n for (const summary of summaries) {\n if (knownRevisions.get(summary.id) !== summary.updatedAt) {\n await broadcastBoard(summary.id);\n }\n }\n };\n\n return bridgeKanbanSupervisor(\n projectRoot,\n async (event) => {\n // Extract boardId from the mutation event data.\n // The daemon sends { type: 'event', event: '<name>', data: { boardId, ... } }\n // for every board mutation (board.created, task.added, column.updated, etc.).\n const evData = event.data as { boardId?: string } | undefined;\n const boardId = evData?.boardId;\n if (!boardId) return;\n\n try {\n if (event.event === 'board.deleted') {\n broadcastDeleted(boardId);\n return;\n }\n await broadcastBoard(boardId);\n } catch {\n // Best-effort: the next explicit refresh or next daemon event\n // will catch transient errors (e.g. board deleted mid-read).\n }\n },\n {\n autoReconnect: true,\n reconnectDelayMs: 1_000,\n onConnected: reconcileAfterConnect,\n },\n );\n}\n", "/**\n * Compatibility alias for the old file-watcher entry point.\n *\n * Kanban is now server-owned SQLite, so liveness comes from daemon events and\n * board reloads travel through IPC. Keep this export for downstream callers\n * without allowing a filesystem watcher to reintroduce a second data path.\n */\nimport type { WSServerMessage } from './types.js';\nimport { subscribeKanbanDaemonEvents } from './kanban-daemon-subscriber.js';\n\nexport function watchKanbanBoards(\n projectRoot: string,\n broadcastMessage: (message: WSServerMessage) => void,\n): () => void {\n return subscribeKanbanDaemonEvents(projectRoot, broadcastMessage);\n}\n", "/**\n * Process lifecycle for the WebUI server: graceful shutdown and the\n * SIGINT/SIGTERM wiring that triggers it.\n *\n * On a termination signal we (best-effort) flush + close the active session,\n * close every connected WebSocket, stop the HTTP and WS servers, then exit.\n * A re-entrancy guard makes a second signal during shutdown a no-op (rapid\n * double Ctrl+C no longer runs the teardown twice).\n *\n * Extracted from `index.ts` as a parameterized factory so the teardown\n * sequence can be unit tested without a real process signal, server, or\n * `process.exit` \u2014 `log` and `exit` are injectable seams.\n */\n\nexport interface LifecycleResources {\n /** Persist + close the active session (best-effort; errors are logged). */\n flushSession: () => Promise<void>;\n /**\n * Returns the currently-connected client sockets to close. A thunk (not a\n * snapshot) so shutdown closes whoever is connected *at signal time*, not\n * whoever was connected when the handler was registered.\n */\n clients: () => Iterable<{ close: () => void }>;\n /** Servers to stop (HTTP + WS). `null`/`undefined` entries are skipped. */\n servers: Array<{ close: () => void } | null | undefined>;\n /**\n * Optional best-effort cleanup run after the session flush and before exit\n * (e.g. removing this process from the running-instance registry). Errors are\n * logged, never thrown \u2014 cleanup must not block a clean shutdown.\n */\n onShutdown?: (() => Promise<void> | void) | undefined;\n /** Output sink. Defaults to `console.log`. */\n log?: ((msg: string) => void) | undefined;\n /** Process exit. Defaults to `process.exit`. Injectable for tests. */\n exit?: ((code: number) => void) | undefined;\n}\n\n/**\n * Build the graceful-shutdown handler. Returns an idempotent async function:\n * the first call runs the teardown, subsequent calls (e.g. a second SIGINT)\n * return immediately.\n */\nexport function createShutdown(res: LifecycleResources): () => Promise<void> {\n const log = res.log ?? ((m: string) => console.log(m));\n const exit = res.exit ?? ((code: number) => process.exit(code));\n let shuttingDown = false;\n\n return async () => {\n if (shuttingDown) return; // a second signal during teardown is a no-op\n shuttingDown = true;\n\n log('[WebUI] Shutting down...');\n try {\n await res.flushSession();\n } catch (e) {\n log(`[WebUI] Error closing session: ${e instanceof Error ? e.message : String(e)}`);\n }\n for (const ws of res.clients()) ws.close();\n for (const server of res.servers) server?.close();\n if (res.onShutdown) {\n try {\n await res.onShutdown();\n } catch (e) {\n log(`[WebUI] Error during shutdown cleanup: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n exit(0);\n };\n}\n\n/**\n * Register the shutdown handler on SIGINT and SIGTERM. Returns an unregister\n * function that detaches both listeners (useful for tests and clean restarts).\n */\nexport function registerShutdownHandlers(res: LifecycleResources): () => void {\n const shutdown = createShutdown(res);\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n return () => {\n process.off('SIGINT', shutdown);\n process.off('SIGTERM', shutdown);\n };\n}\n", "import * as fs from 'node:fs/promises';\nimport {\n type ConfigDefaultRepairReport,\n repairConfigDefaults,\n} from '@wrongstack/core/storage';\nimport type { Config, SecretVault } from '@wrongstack/core/types';\nimport { atomicWrite } from '@wrongstack/core/utils';\nimport { decryptConfigSecrets } from '@wrongstack/core/security';\nimport type { WebSocket } from 'ws';\nimport { send } from './ws-utils.js';\n\nexport interface ConfigDoctorDeps {\n profileConfigPath: string;\n vault: SecretVault;\n updateConfig: (\n mutate: (config: Record<string, unknown>) => void,\n errorLabel: string,\n ) => Promise<void>;\n applyRuntimeConfig: (config: Config) => void;\n}\n\nasync function readConfig(\n file: string,\n vault: SecretVault,\n): Promise<{ raw: string; decrypted: Record<string, unknown> }> {\n const raw = await fs.readFile(file, 'utf8');\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('Active profile config must contain a JSON object.');\n }\n return {\n raw,\n decrypted: decryptConfigSecrets(parsed as Record<string, unknown>, vault) as Record<\n string,\n unknown\n >,\n };\n}\n\n/** Preview or apply canonical defaults to the active profile config. */\nexport async function handleConfigDoctor(\n ws: WebSocket,\n apply: boolean,\n deps: ConfigDoctorDeps,\n): Promise<void> {\n try {\n const current = await readConfig(deps.profileConfigPath, deps.vault);\n const report: ConfigDefaultRepairReport = repairConfigDefaults(current.decrypted);\n\n if (apply && report.changed) {\n // Keep the exact encrypted source as a recoverable sibling before the\n // shared config writer decrypts, mutates, re-encrypts, and atomically saves.\n // Use a timestamped suffix so consecutive `/doctor fix` runs don't\n // overwrite prior snapshots (the UI surfaces this path to the user).\n const backupSuffix = `.last-${Date.now()}`;\n const backupPath = `${deps.profileConfigPath}${backupSuffix}`;\n await atomicWrite(backupPath, current.raw, { mode: 0o600 });\n await deps.updateConfig((config) => {\n for (const key of Object.keys(config)) delete config[key];\n Object.assign(config, report.fixed);\n }, 'config.doctor');\n deps.applyRuntimeConfig(report.fixed as unknown as Config);\n\n send(ws, {\n type: 'config.doctor.result',\n payload: {\n success: true,\n applied: true,\n changed: true,\n changes: report.changes,\n configPath: deps.profileConfigPath,\n backupPath,\n },\n });\n } else {\n send(ws, {\n type: 'config.doctor.result',\n payload: {\n success: true,\n applied: false,\n changed: report.changed,\n changes: report.changes,\n configPath: deps.profileConfigPath,\n backupPath: undefined,\n },\n });\n }\n } catch (err) {\n send(ws, {\n type: 'config.doctor.result',\n payload: {\n success: false,\n applied: false,\n changed: false,\n changes: [],\n configPath: deps.profileConfigPath,\n error: err instanceof Error ? err.message : String(err),\n },\n });\n }\n}\n", "/**\n * Mailbox WebSocket handlers for the WebUI.\n *\n * Handles `mailbox.messages` and `mailbox.agents` message types.\n * The frontend sends these to populate the mailbox panel; the server\n * reads from the server-backed project mailbox and responds.\n */\n\nimport {\n actionToAckInput,\n getSharedProjectMailbox,\n isMailboxMessageVisibleTo,\n MAILBOX_TYPE_PROPERTIES,\n mailboxIdentityBase,\n type RemoteMailbox,\n resolveProjectDir,\n} from '@wrongstack/core/coordination';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport type { WebSocket } from 'ws';\nimport type { MailboxActionPayload, MailboxSendPayload } from './ws-payload-validation.js';\nimport { errMessage, send } from './ws-utils.js';\n\nexport interface MailboxHandlerDeps {\n /** Absolute project root or a live getter for hosts that can switch projects. */\n projectRoot: string | (() => string);\n /** Global WrongStack root (~/.wrongstack), or a live getter. */\n globalRoot: string | (() => string);\n /** Host event bus used by mailbox mutation/activity notifications. */\n events?: EventBus | undefined;\n}\n\nfunction current(value: string | (() => string)): string {\n return typeof value === 'function' ? value() : value;\n}\n\nexport function getMailboxForDeps(deps: MailboxHandlerDeps): RemoteMailbox | null {\n const projectRoot = current(deps.projectRoot);\n const globalRoot = current(deps.globalRoot);\n if (!projectRoot || !globalRoot) return null;\n const dir = resolveProjectDir(projectRoot, globalRoot);\n return getSharedProjectMailbox(dir, deps.events);\n}\n\n// \u2500\u2500 Handlers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport async function handleMailboxAction(\n ws: WebSocket,\n deps: MailboxHandlerDeps,\n payload: MailboxActionPayload,\n): Promise<void> {\n const mb = getMailboxForDeps(deps);\n if (!mb) {\n send(ws, {\n type: 'mailbox.action_result',\n payload: {\n requestId: payload.requestId,\n success: false,\n error: 'No project root available',\n },\n });\n return;\n }\n try {\n const message =\n payload.action === 'soft-delete'\n ? await mb.softDelete(payload.mailId, payload.readerId)\n : await mb.ack(actionToAckInput(payload.action, payload));\n send(ws, {\n type: 'mailbox.action_result',\n payload: {\n requestId: payload.requestId,\n success: message !== null,\n action: payload.action,\n mailId: payload.mailId,\n },\n });\n } catch (err) {\n send(ws, {\n type: 'mailbox.action_result',\n payload: {\n requestId: payload.requestId,\n success: false,\n action: payload.action,\n mailId: payload.mailId,\n error: errMessage(err),\n },\n });\n }\n}\n\n/** Persist a human-authored WebUI message in the shared project mailbox. */\nexport async function handleMailboxSend(\n ws: WebSocket,\n deps: MailboxHandlerDeps,\n payload: MailboxSendPayload,\n): Promise<void> {\n const mb = getMailboxForDeps(deps);\n if (!mb) {\n send(ws, {\n type: 'mailbox.sent',\n payload: {\n requestId: payload.requestId,\n success: false,\n error: 'No project root available',\n },\n });\n return;\n }\n try {\n const message = await mb.send({\n from: payload.from ?? 'webui',\n to: payload.to,\n type: payload.type,\n audience: payload.audience,\n subject: payload.subject,\n body: payload.body,\n priority: payload.priority,\n replyTo: payload.replyTo,\n });\n send(ws, {\n type: 'mailbox.sent',\n payload: {\n requestId: payload.requestId,\n success: true,\n messageId: message.id,\n from: message.from,\n to: message.to,\n audience: message.audience ?? 'all',\n },\n });\n } catch (err) {\n send(ws, {\n type: 'mailbox.sent',\n payload: {\n requestId: payload.requestId,\n success: false,\n error: errMessage(err),\n },\n });\n }\n}\n\n/**\n * List recent mailbox messages. Frontend sends:\n * { type: 'mailbox.messages', limit?: number, incompleteOnly?: boolean }\n *\n * Uses `incompleteOnly` so the server filters to active/unread messages,\n * making readByCount === 0 a reliable \"unread to all agents\" signal for\n * the ActivityBar badge count.\n */\nexport async function handleMailboxMessages(\n ws: WebSocket,\n deps: MailboxHandlerDeps,\n payload:\n | { limit?: number; agentId?: string; unreadOnly?: boolean; incompleteOnly?: boolean }\n | undefined,\n): Promise<void> {\n const mb = getMailboxForDeps(deps);\n if (!mb) {\n send(ws, {\n type: 'mailbox.messages',\n payload: { messages: [], error: 'No project root available' },\n });\n return;\n }\n try {\n const limit = payload?.limit ?? 30;\n const unreadForAgent = payload?.unreadOnly === true && payload.agentId !== undefined;\n const readerRole =\n payload?.agentId !== undefined\n ? (await mb.getAgentStatuses()).find(\n (agent) =>\n agent.agentId === payload.agentId ||\n mailboxIdentityBase(agent.agentId) === mailboxIdentityBase(payload.agentId as string),\n )?.role\n : undefined;\n const messages = await mb.query({\n limit:\n payload?.unreadOnly === true && payload.agentId === undefined\n ? Math.max(limit * 5, 100)\n : limit,\n to: payload?.agentId,\n unreadBy: unreadForAgent ? payload.agentId : undefined,\n readerRole,\n incompleteOnly: payload?.incompleteOnly ?? false,\n });\n const audienceVisible =\n payload?.agentId !== undefined\n ? messages.filter((message) =>\n isMailboxMessageVisibleTo(message, payload.agentId as string, readerRole),\n )\n : messages;\n const visibleMessages =\n payload?.unreadOnly === true && payload.agentId === undefined\n ? audienceVisible.filter((m) => Object.keys(m.readBy).length === 0).slice(0, limit)\n : audienceVisible;\n send(ws, {\n type: 'mailbox.messages',\n payload: {\n ...(payload?.unreadOnly === true ? { unreadOnly: true } : {}),\n messages: visibleMessages.map((m) => {\n const readByMe = payload?.agentId !== undefined ? (payload.agentId as string) in m.readBy : false;\n const completedByMe = payload?.agentId !== undefined ? m.completedBy === payload.agentId : false;\n const actionRequiredForMe =\n payload?.agentId !== undefined\n ? MAILBOX_TYPE_PROPERTIES[m.type]?.requiresAction === true &&\n !completedByMe &&\n m.deletedAt === undefined\n : false;\n return {\n id: m.id,\n from: m.from,\n to: m.to,\n type: m.type,\n audience: m.audience ?? 'all',\n subject: m.subject,\n body: m.body,\n priority: m.priority,\n readBy: m.readBy,\n readByCount: Object.keys(m.readBy).length,\n completed: m.completed,\n completedBy: m.completedBy,\n completedAt: m.completedAt,\n outcome: m.outcome,\n timestamp: m.timestamp,\n replyTo: m.replyTo,\n senderSessionId: m.senderSessionId,\n taskContext: m.taskContext,\n ...(payload?.agentId !== undefined ? { readByMe, completedByMe, actionRequiredForMe } : {}),\n };}),\n },\n });\n } catch (err) {\n send(ws, { type: 'mailbox.messages', payload: { messages: [], error: errMessage(err) } });\n }\n}\n\n/**\n * List registered agents. Frontend sends:\n * { type: 'mailbox.agents', onlineOnly?: boolean }\n */\nexport async function handleMailboxAgents(\n ws: WebSocket,\n deps: MailboxHandlerDeps,\n payload: { onlineOnly?: boolean } | undefined,\n): Promise<void> {\n const mb = getMailboxForDeps(deps);\n if (!mb) {\n send(ws, {\n type: 'mailbox.agents',\n payload: { agents: [], error: 'No project root available' },\n });\n return;\n }\n try {\n const agents = payload?.onlineOnly ? await mb.getOnlineAgents() : await mb.getAgentStatuses();\n send(ws, {\n type: 'mailbox.agents',\n payload: {\n agents: agents.map((a) => ({\n agentId: a.agentId,\n name: a.name,\n role: a.role,\n sessionId: a.sessionId,\n status: a.status,\n currentTool: a.currentTool,\n currentTask: a.currentTask,\n iterations: a.iterations,\n toolCalls: a.toolCalls,\n lastSeenAt: a.lastSeenAt,\n online: a.online,\n pid: a.pid,\n source: a.source,\n })),\n },\n });\n } catch (err) {\n send(ws, { type: 'mailbox.agents', payload: { agents: [], error: errMessage(err) } });\n }\n}\n\n/**\n * Delete all messages from the mailbox. Frontend sends:\n * { type: 'mailbox.clear' }\n * Server responds with 'mailbox.cleared'.\n */\nexport async function handleMailboxClear(ws: WebSocket, deps: MailboxHandlerDeps): Promise<void> {\n const mb = getMailboxForDeps(deps);\n if (!mb) {\n send(ws, { type: 'mailbox.cleared', payload: { error: 'No project root available' } });\n return;\n }\n try {\n await mb.clearAll();\n send(ws, { type: 'mailbox.cleared', payload: {} });\n } catch (err) {\n send(ws, { type: 'mailbox.cleared', payload: { error: errMessage(err) } });\n }\n}\n\n/**\n * Purge stale/orphaned messages from the mailbox. Frontend sends:\n * { type: 'mailbox.purge', payload?: { completedMaxAgeMs?: number; incompleteMaxAgeMs?: number } }\n * Server responds with 'mailbox.purged'.\n */\nexport async function handleMailboxPurge(\n ws: WebSocket,\n deps: MailboxHandlerDeps,\n opts?: { completedMaxAgeMs?: number; incompleteMaxAgeMs?: number },\n): Promise<void> {\n const mb = getMailboxForDeps(deps);\n if (!mb) {\n send(ws, { type: 'mailbox.purged', payload: { error: 'No project root available' } });\n return;\n }\n try {\n const result = await mb.purgeStale(opts);\n send(ws, { type: 'mailbox.purged', payload: result });\n } catch (err) {\n send(ws, { type: 'mailbox.purged', payload: { error: errMessage(err) } });\n }\n}\n\n/**\n * Auto-compact the mailbox: removes expired (TTL) messages, messages read\n * by all online agents, and stale messages \u2014 all in one pass. Frontend sends:\n * { type: 'mailbox.compact', payload?: { readMaxAgeMs?, defaultTtlMs?, ... } }\n * Server responds with 'mailbox.compacted' containing the result.\n */\nexport async function handleMailboxCompact(\n ws: WebSocket,\n deps: MailboxHandlerDeps,\n opts?: {\n readMaxAgeMs?: number;\n defaultTtlMs?: number;\n completedMaxAgeMs?: number;\n incompleteMaxAgeMs?: number;\n },\n): Promise<void> {\n const mb = getMailboxForDeps(deps);\n if (!mb) {\n send(ws, { type: 'mailbox.compacted', payload: { error: 'No project root available' } });\n return;\n }\n try {\n const result = await mb.autoCompact(opts);\n send(ws, { type: 'mailbox.compacted', payload: result });\n } catch (err) {\n send(ws, { type: 'mailbox.compacted', payload: { error: errMessage(err) } });\n }\n}\n", "import type { EventBus } from '@wrongstack/core/kernel';\nimport type { WebSocket } from 'ws';\nimport {\n handleMailboxAction,\n handleMailboxAgents,\n handleMailboxClear,\n handleMailboxCompact,\n handleMailboxMessages,\n handleMailboxPurge,\n handleMailboxSend,\n type MailboxHandlerDeps,\n} from './mailbox-handlers.js';\nimport type { WSClientMessage } from './types.js';\nimport {\n validateMailboxActionPayload,\n validateMailboxAgentsPayload,\n validateMailboxMessagesPayload,\n validateMailboxPurgePayload,\n validateMailboxSendPayload,\n} from './ws-payload-validation.js';\nimport { send, sendResult } from './ws-utils.js';\n\nexport interface MailboxRouteHandlers {\n action: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n send: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n messages: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n agents: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n clear: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n purge: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n compact: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport interface MailboxRouteContext {\n getProjectRoot: () => string;\n getGlobalRoot: () => string;\n events?: EventBus | undefined;\n}\n\nexport function createMailboxRouteHandlers(ctx: MailboxRouteContext): MailboxRouteHandlers {\n const deps: MailboxHandlerDeps = {\n projectRoot: ctx.getProjectRoot,\n globalRoot: ctx.getGlobalRoot,\n ...(ctx.events ? { events: ctx.events } : {}),\n };\n return {\n action: (ws, msg) => {\n const parsed = validateMailboxActionPayload(msg.payload);\n if (!parsed.ok) {\n sendResult(ws, false, parsed.message);\n return;\n }\n return handleMailboxAction(ws, deps, parsed.value);\n },\n send: (ws, msg) => {\n const parsed = validateMailboxSendPayload(msg.payload);\n if (!parsed.ok) {\n const requestId =\n typeof msg.payload === 'object' &&\n msg.payload !== null &&\n typeof (msg.payload as { requestId?: unknown }).requestId === 'string'\n ? (msg.payload as { requestId: string }).requestId\n : undefined;\n if (requestId !== undefined) {\n send(ws, {\n type: 'mailbox.sent',\n payload: { requestId, success: false, error: parsed.message },\n });\n return;\n }\n sendResult(ws, false, parsed.message);\n return;\n }\n return handleMailboxSend(ws, deps, parsed.value);\n },\n messages: (ws, msg) => {\n const parsed = validateMailboxMessagesPayload(msg.payload);\n if (!parsed.ok) {\n sendResult(ws, false, parsed.message);\n return;\n }\n return handleMailboxMessages(ws, deps, parsed.value);\n },\n agents: (ws, msg) => {\n const parsed = validateMailboxAgentsPayload(msg.payload);\n if (!parsed.ok) {\n sendResult(ws, false, parsed.message);\n return;\n }\n return handleMailboxAgents(ws, deps, parsed.value);\n },\n clear: (ws) => handleMailboxClear(ws, deps),\n purge: (ws, msg) => {\n const parsed = validateMailboxPurgePayload(msg.payload);\n if (!parsed.ok) {\n sendResult(ws, false, parsed.message);\n return;\n }\n return handleMailboxPurge(ws, deps, parsed.value);\n },\n compact: (ws, msg) =>\n handleMailboxCompact(\n ws,\n deps,\n (msg.payload as {\n readMaxAgeMs?: number;\n defaultTtlMs?: number;\n completedMaxAgeMs?: number;\n incompleteMaxAgeMs?: number;\n }) ?? {},\n ),\n };\n}\n\nexport async function handleMailboxRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: MailboxRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'mailbox.action':\n await handlers.action(ws, msg);\n return true;\n case 'mailbox.send':\n await handlers.send(ws, msg);\n return true;\n case 'mailbox.messages':\n await handlers.messages(ws, msg);\n return true;\n case 'mailbox.agents':\n await handlers.agents(ws, msg);\n return true;\n case 'mailbox.clear':\n await handlers.clear(ws, msg);\n return true;\n case 'mailbox.purge':\n await handlers.purge(ws, msg);\n return true;\n case 'mailbox.compact':\n await handlers.compact(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "/**\n * MCP management handlers for the WebUI server (both the standalone\n * standalone server and the CLI's embedded `--webui` server).\n *\n * These are thin WebSocket translators over the shared, surface-agnostic\n * management core in `@wrongstack/mcp` (`manage.ts`) \u2014 the SAME core the REPL\n * `/mcp` command writes against (same config.json, same MCPRegistry). All the\n * config IO, url/header persistence, and live registry start/stop logic lives\n * there; here we only map structured results to WS events the browser expects.\n */\n\nimport { allServers } from '@wrongstack/core/infrastructure';\nimport {\n addMcp,\n disableMcp,\n discoverMcp,\n enableMcp,\n listMcp,\n type MCPRegistry,\n type MCPServerOperationalHealth,\n type McpManageDeps,\n type McpServerInfo,\n type McpServerInput,\n removeMcp,\n restartMcp,\n updateMcp,\n} from '@wrongstack/mcp';\nimport type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\nimport { send } from './ws-utils.js';\n\n/** Wire view of a server as the browser MCP panel consumes it. */\nexport interface MCPServerView {\n name: string;\n transport: string;\n status: 'stopped' | 'connecting' | 'connected' | 'sleeping' | 'discovering' | 'error';\n enabled: boolean;\n description?: string;\n tools?: string[];\n error?: string;\n pid?: number;\n lazy?: boolean;\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n url?: string;\n health?: MCPServerOperationalHealth;\n}\n\n/** Map a raw registry state to the UI status union. */\nfunction mapStatus(raw: string): MCPServerView['status'] {\n switch (raw) {\n case 'connected':\n return 'connected';\n case 'connecting':\n case 'reconnecting':\n return 'connecting';\n case 'failed':\n return 'error';\n case 'dormant':\n // Lazy server registered from cache, process not spawned \u2014 show as sleeping.\n return 'sleeping';\n default:\n // idle / disconnected / stopped\n return 'stopped';\n }\n}\n\n/** Project the shared {@link McpServerInfo} into the browser wire shape. */\nfunction toView(info: McpServerInfo, health?: MCPServerOperationalHealth | undefined): MCPServerView {\n const view: MCPServerView = {\n name: info.name,\n transport: info.transport,\n // A dormant lazy server is \"asleep\", not stopped \u2014 preserve that even when\n // it's enabled in config.\n status:\n info.status === 'dormant'\n ? 'sleeping'\n : info.enabled === false\n ? 'stopped'\n : mapStatus(info.status),\n enabled: info.enabled,\n tools: info.tools,\n };\n if (info.description !== undefined) view.description = info.description;\n if (info.lazy !== undefined) view.lazy = info.lazy;\n if (info.command !== undefined) view.command = info.command;\n if (info.args !== undefined) view.args = info.args;\n if (info.env !== undefined) view.env = info.env;\n if (info.url !== undefined) view.url = info.url;\n if (health !== undefined) view.health = health;\n return view;\n}\n\n/**\n * Build the shared management deps. Returns null (and sends a failure result)\n * when the live registry isn't wired \u2014 both WebUI servers now pass one, so this\n * is a defensive guard rather than the normal path.\n */\nfunction deps(\n ws: WebSocket,\n globalConfigPath: string | undefined,\n registry: MCPRegistry | undefined,\n): McpManageDeps | null {\n if (!registry || !globalConfigPath) {\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: false, message: 'MCP registry is not available in this session.' },\n });\n return null;\n }\n return { configPath: globalConfigPath, registry, presets: allServers() };\n}\n\nfunction name(msg: WSClientMessage): string {\n return (msg.payload as { name?: string } | undefined)?.name ?? '';\n}\n\n/** mcp.list \u2014 configured servers merged with live registry status + tools. */\nexport async function handleMcpList(\n ws: WebSocket,\n _msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n if (!mcpRegistry || !globalConfigPath) {\n send(ws, { type: 'mcp.list', payload: { servers: [] } });\n return;\n }\n const servers = await listMcp({\n configPath: globalConfigPath,\n registry: mcpRegistry,\n presets: allServers(),\n });\n const health = new Map(\n (\n typeof mcpRegistry.operationalHealth === 'function' ? mcpRegistry.operationalHealth() : []\n ).map((item) => [item.name, item]),\n );\n send(ws, {\n type: 'mcp.list',\n payload: { servers: servers.map((server) => toView(server, health.get(server.name))) },\n });\n}\n\n/** mcp.add \u2014 persist a new server (incl. url/headers) and start it if enabled. */\nexport async function handleMcpAdd(\n ws: WebSocket,\n msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n const d = deps(ws, globalConfigPath, mcpRegistry);\n if (!d) return;\n const result = await addMcp(msg.payload as McpServerInput, d);\n if (result.ok && result.server) {\n send(ws, { type: 'mcp.server.added', payload: { server: toView(result.server) } });\n if (result.registryError) {\n send(ws, {\n type: 'mcp.server.error',\n payload: { name: result.server.name, error: result.registryError },\n });\n } else if (result.server.enabled) {\n send(ws, { type: 'mcp.server.connected', payload: { name: result.server.name } });\n }\n }\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: result.ok, message: result.message },\n });\n}\n\n/** mcp.update \u2014 re-persist config (incl. url/headers) and re-apply to registry. */\nexport async function handleMcpUpdate(\n ws: WebSocket,\n msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n const d = deps(ws, globalConfigPath, mcpRegistry);\n if (!d) return;\n const result = await updateMcp(msg.payload as McpServerInput, d);\n if (result.ok && result.server) {\n send(ws, { type: 'mcp.server.updated', payload: { server: toView(result.server) } });\n }\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: result.ok, message: result.message },\n });\n}\n\n/** mcp.remove \u2014 stop the server and delete it from config. */\nexport async function handleMcpRemove(\n ws: WebSocket,\n msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n const d = deps(ws, globalConfigPath, mcpRegistry);\n if (!d) return;\n const result = await removeMcp(name(msg), d);\n if (result.ok) {\n send(ws, { type: 'mcp.server.removed', payload: { name: name(msg) } });\n }\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: result.ok, message: result.message },\n });\n}\n\n/** mcp.enable \u2014 flip enabled:true in config and start the server. */\nexport async function handleMcpEnable(\n ws: WebSocket,\n msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n const d = deps(ws, globalConfigPath, mcpRegistry);\n if (!d) return;\n const result = await enableMcp(name(msg), d);\n if (result.ok && result.server) {\n send(ws, { type: 'mcp.server.updated', payload: { server: toView(result.server) } });\n if (result.registryError) {\n send(ws, {\n type: 'mcp.server.error',\n payload: { name: name(msg), error: result.registryError },\n });\n } else {\n send(ws, { type: 'mcp.server.connected', payload: { name: name(msg) } });\n }\n }\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: result.ok, message: result.message },\n });\n}\n\n/** mcp.disable \u2014 stop the server and flip enabled:false in config. */\nexport async function handleMcpDisable(\n ws: WebSocket,\n msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n const d = deps(ws, globalConfigPath, mcpRegistry);\n if (!d) return;\n const result = await disableMcp(name(msg), d);\n if (result.ok) {\n send(ws, { type: 'mcp.server.sleeping', payload: { name: name(msg) } });\n if (result.server) {\n send(ws, { type: 'mcp.server.updated', payload: { server: toView(result.server) } });\n }\n }\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: result.ok, message: result.message },\n });\n}\n\n/** mcp.sleep \u2014 stop a running server (config stays enabled). */\nexport async function handleMcpSleep(\n ws: WebSocket,\n msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n const d = deps(ws, globalConfigPath, mcpRegistry);\n if (!d) return;\n // Sleep == disable the live process but keep config enabled \u2014 use the\n // registry directly so the persisted `enabled` flag is untouched.\n try {\n await d.registry.stop(name(msg));\n send(ws, { type: 'mcp.server.sleeping', payload: { name: name(msg) } });\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: true, message: `Server \"${name(msg)}\" stopped` },\n });\n } catch (err) {\n const error = err instanceof Error ? err.message : String(err);\n send(ws, { type: 'mcp.server.error', payload: { name: name(msg), error } });\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: false, message: `Failed to stop \"${name(msg)}\": ${error}` },\n });\n }\n}\n\n/** mcp.wake \u2014 restart a sleeping/stopped server from config. */\nexport async function handleMcpWake(\n ws: WebSocket,\n msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n const d = deps(ws, globalConfigPath, mcpRegistry);\n if (!d) return;\n send(ws, { type: 'mcp.server.waking', payload: { name: name(msg) } });\n const result = await restartMcp(name(msg), d);\n if (result.ok && !result.registryError) {\n send(ws, { type: 'mcp.server.connected', payload: { name: name(msg) } });\n } else if (result.registryError) {\n send(ws, {\n type: 'mcp.server.error',\n payload: { name: name(msg), error: result.registryError },\n });\n }\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: result.ok, message: result.message },\n });\n}\n\n/** mcp.restart \u2014 stop + start a server. */\nexport async function handleMcpRestart(\n ws: WebSocket,\n msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n const d = deps(ws, globalConfigPath, mcpRegistry);\n if (!d) return;\n const result = await restartMcp(name(msg), d);\n if (result.ok && !result.registryError) {\n send(ws, { type: 'mcp.server.connected', payload: { name: name(msg) } });\n } else if (result.registryError) {\n send(ws, {\n type: 'mcp.server.error',\n payload: { name: name(msg), error: result.registryError },\n });\n }\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: result.ok, message: result.message },\n });\n}\n\n/** mcp.discover \u2014 ensure the server is running and report its live tools. */\nexport async function handleMcpDiscover(\n ws: WebSocket,\n msg: WSClientMessage,\n globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n const d = deps(ws, globalConfigPath, mcpRegistry);\n if (!d) return;\n const result = await discoverMcp(name(msg), d);\n if (result.ok) {\n send(ws, {\n type: 'mcp.server.discovered',\n payload: { name: name(msg), tools: result.tools ?? [] },\n });\n }\n send(ws, {\n type: 'mcp.operation_result',\n payload: { success: result.ok, message: result.message },\n });\n}\n\n/** mcp.resources \u2014 list cached resources/templates, refreshing only when explicitly requested. */\nexport async function handleMcpResources(\n ws: WebSocket,\n msg: WSClientMessage,\n _globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n if (!mcpRegistry) return sendContentError(ws, 'resources', '', 'MCP registry is not available.');\n const payload = payloadRecord(msg);\n let serverName = '';\n try {\n serverName = requiredPayloadString(payload, 'name');\n const refresh = payload['refresh'] === true;\n const [resources, resourceTemplates] = await Promise.all([\n mcpRegistry.listResources(serverName, { refresh }),\n mcpRegistry.listResourceTemplates(serverName, { refresh }),\n ]);\n send(ws, {\n type: 'mcp.resources',\n payload: { name: serverName, resources, resourceTemplates },\n });\n } catch (err) {\n sendContentError(ws, 'resources', serverName, errorMessage(err));\n }\n}\n\n/** mcp.prompts \u2014 list cached prompts, refreshing only when explicitly requested. */\nexport async function handleMcpPrompts(\n ws: WebSocket,\n msg: WSClientMessage,\n _globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n if (!mcpRegistry) return sendContentError(ws, 'prompts', '', 'MCP registry is not available.');\n const payload = payloadRecord(msg);\n let serverName = '';\n try {\n serverName = requiredPayloadString(payload, 'name');\n const prompts = await mcpRegistry.listPrompts(serverName, {\n refresh: payload['refresh'] === true,\n });\n send(ws, { type: 'mcp.prompts', payload: { name: serverName, prompts } });\n } catch (err) {\n sendContentError(ws, 'prompts', serverName, errorMessage(err));\n }\n}\n\n/** mcp.resource.read \u2014 explicit user selection; returns an untrusted provenance envelope. */\nexport async function handleMcpResourceRead(\n ws: WebSocket,\n msg: WSClientMessage,\n _globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n if (!mcpRegistry)\n return sendContentError(ws, 'resource.read', '', 'MCP registry is not available.');\n const payload = payloadRecord(msg);\n let serverName = '';\n try {\n serverName = requiredPayloadString(payload, 'name');\n const insertion = await mcpRegistry.selectResourceForInsertion(\n serverName,\n requiredPayloadString(payload, 'uri'),\n );\n send(ws, { type: 'mcp.content.selected', payload: insertion });\n } catch (err) {\n sendContentError(ws, 'resource.read', serverName, errorMessage(err));\n }\n}\n\n/** mcp.prompt.get \u2014 explicit user selection; prompt argument values stay out of provenance. */\nexport async function handleMcpPromptGet(\n ws: WebSocket,\n msg: WSClientMessage,\n _globalConfigPath: string,\n mcpRegistry?: MCPRegistry,\n): Promise<void> {\n if (!mcpRegistry) return sendContentError(ws, 'prompt.get', '', 'MCP registry is not available.');\n const payload = payloadRecord(msg);\n let serverName = '';\n try {\n serverName = requiredPayloadString(payload, 'name');\n const insertion = await mcpRegistry.selectPromptForInsertion(\n serverName,\n requiredPayloadString(payload, 'prompt'),\n promptArguments(payload['arguments']),\n );\n send(ws, { type: 'mcp.content.selected', payload: insertion });\n } catch (err) {\n sendContentError(ws, 'prompt.get', serverName, errorMessage(err));\n }\n}\n\nfunction payloadRecord(msg: WSClientMessage): Record<string, unknown> {\n return msg.payload && typeof msg.payload === 'object' && !Array.isArray(msg.payload)\n ? (msg.payload as Record<string, unknown>)\n : {};\n}\n\nfunction requiredPayloadString(payload: Record<string, unknown>, field: string): string {\n const value = payload[field];\n if (typeof value !== 'string' || value.length === 0) {\n throw new Error(`MCP payload field \"${field}\" must be a non-empty string`);\n }\n return value;\n}\n\nfunction promptArguments(value: unknown): Record<string, string> | undefined {\n if (value === undefined) return undefined;\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('MCP prompt arguments must be an object');\n }\n const args: Record<string, string> = {};\n for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n if (typeof item !== 'string') throw new Error(`MCP prompt argument \"${key}\" must be a string`);\n args[key] = item;\n }\n return args;\n}\n\nfunction sendContentError(ws: WebSocket, action: string, name: string, error: string): void {\n send(ws, { type: 'mcp.content.error', payload: { action, name, error } });\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n", "// MCP WS-message routing \u2014 extracted from packages/webui/src/server/index.ts\n// (issue #31, follow-on to PRs #94\u2013#110, #118, #119). The handler logic was\n// already in mcp-handlers.ts; this module is the chain-of-responsibility\n// dispatcher that mirrors the shape of the other 12 sibling route handlers\n// already wired through `handleMessage`.\n//\n// Why a thin dispatcher instead of importing handleMcpXxx directly into\n// index.ts: every other sibling uses the handleXxxRoute(ws, msg, handlers)\n// callback-injection pattern, which lets the test surface stub individual\n// callbacks (dispatcher-routing.test.ts covers 13 of these now). Bypassing\n// the pattern for MCP would mean the dispatcher-routing test for mcp.*\n// would have to spin up a real MCPRegistry \u2014 high cost for low value.\n//\n// Why 10 callbacks (one per case) instead of a McpContext interface: each\n// handleMcpXxx already takes the same (ws, msg, globalConfigPath,\n// mcpRegistry) signature. Bundling those 4 params into a single\n// McpContext object would be churn for no behavior change. The two-callback\n// (prefs) vs ten-callback (mcp) asymmetry is fine \u2014 the contract is\n// \"one callback per owned message type\", not \"smallest possible surface\".\n\nimport type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface McpRouteHandlers {\n list: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n add: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n update: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n remove: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n enable: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n disable: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n sleep: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n wake: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n restart: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n discover: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n resources: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n prompts: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n resourceRead: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n promptGet: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n}\n\n/**\n * Chain-of-responsibility dispatcher for the `mcp.*` WS message family.\n * Returns `true` if the message was handled by this layer (so the caller's\n * chain short-circuits), `false` if it should fall through to the next layer\n * or the residual switch.\n *\n * Owned prefixes (10 message types \u2014 full coverage of the MCP management\n * surface; the WebUI MCP panel only ever talks to the server through these):\n * - mcp.list\n * - mcp.add\n * - mcp.update\n * - mcp.remove\n * - mcp.enable\n * - mcp.disable\n * - mcp.sleep\n * - mcp.wake\n * - mcp.restart\n * - mcp.discover\n *\n * Regression-tested by packages/webui/tests/server/dispatcher-routing.test.ts.\n */\nexport async function handleMcpRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: McpRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'mcp.list':\n await handlers.list(ws, msg);\n return true;\n case 'mcp.add':\n await handlers.add(ws, msg);\n return true;\n case 'mcp.update':\n await handlers.update(ws, msg);\n return true;\n case 'mcp.remove':\n await handlers.remove(ws, msg);\n return true;\n case 'mcp.enable':\n await handlers.enable(ws, msg);\n return true;\n case 'mcp.disable':\n await handlers.disable(ws, msg);\n return true;\n case 'mcp.sleep':\n await handlers.sleep(ws, msg);\n return true;\n case 'mcp.wake':\n await handlers.wake(ws, msg);\n return true;\n case 'mcp.restart':\n await handlers.restart(ws, msg);\n return true;\n case 'mcp.discover':\n await handlers.discover(ws, msg);\n return true;\n case 'mcp.resources':\n await handlers.resources(ws, msg);\n return true;\n case 'mcp.prompts':\n await handlers.prompts(ws, msg);\n return true;\n case 'mcp.resource.read':\n await handlers.resourceRead(ws, msg);\n return true;\n case 'mcp.prompt.get':\n await handlers.promptGet(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "/**\n * Shared memory-operation WebSocket handlers for both the standalone WebUI\n * server and the CLI's `--webui` embedded server.\n *\n * Each function handles the full request\u2192response cycle for one message\n * type. Callers drop them into their switch statement:\n *\n * case 'memory.list': return handleMemoryList(ws, memoryStore);\n *\n * Sage handlers request the typed surface capability:\n *\n * case 'memory.sage.list': return handleSageList(ws, memoryStore);\n */\n\nimport type { MemoryPort } from '@wrongstack/core/types';\nimport { getSageSurface } from '@wrongstack/sage';\nimport type { WebSocket } from 'ws';\nimport { errMessage, send } from './ws-utils.js';\n\n// \u2500\u2500 Sage response projection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface SageLike {\n id: string;\n kind: string;\n status: string;\n text: string;\n tags: string[];\n}\n\ninterface SageStatsLike {\n total: number;\n byStatus: Record<string, number>;\n byKind: Partial<Record<string, number>>;\n edges: number;\n}\n\nfunction requiresSage(command: string): string {\n return `\\`${command}\\` requires the SAGE backend (Sage.enabled).`;\n}\n\n// \u2500\u2500 Memory list (chat `/memory`) \u2014 renders the single SAGE store \u2500\u2500\n\n/**\n * List memory for the chat `/memory` command. When the backend is SAGE\n * (always, in practice) this renders the rich structured view \u2014 the same one\n * surface as the MemoryManager panel and the CLI/TUI `/memory show`. Falls back\n * to `readAll()` text only for a non-SAGE store.\n * Responds with `{ type: 'memory.list', payload: { text } }`.\n */\nexport async function handleMemoryList(ws: WebSocket, memoryStore: MemoryPort): Promise<void> {\n try {\n const Sage = getSageSurface(memoryStore);\n if (Sage) {\n const [stats, memories] = await Promise.all([Sage.stats(), Sage.listSage()]);\n const text =\n memories.length === 0\n ? '\uD83E\uDDE0 SAGE is empty.'\n : formatSageText(stats, memories);\n send(ws, { type: 'memory.list', payload: { text } });\n return;\n }\n const text = await memoryStore.readAll();\n send(ws, { type: 'memory.list', payload: { text } });\n } catch (err) {\n send(ws, {\n type: 'memory.list',\n payload: { text: '', error: errMessage(err) },\n });\n }\n}\n\n/** Render the SAGE list as markdown for the chat `/memory` view. */\nfunction formatSageText(stats: SageStatsLike, memories: SageLike[]): string {\n const active = stats.byStatus['active'] ?? 0;\n const stale = stats.byStatus['stale'] ?? 0;\n const archived = stats.byStatus['archived'] ?? 0;\n const lines: string[] = [\n '## \uD83E\uDDE0 SAGE',\n '',\n `**Total:** ${stats.total} \u00B7 \uD83D\uDFE2 ${active} active \u00B7 \uD83D\uDFE1 ${stale} stale \u00B7 \uD83D\uDD35 ${archived} archived \u00B7 **edges:** ${stats.edges}`,\n '',\n ];\n for (const m of memories) {\n const tags = m.tags.length > 0 ? ` \\`${m.tags.slice(0, 3).join('` `')}\\`` : '';\n const icon =\n m.status === 'active'\n ? '\uD83D\uDFE2'\n : m.status === 'stale'\n ? '\uD83D\uDFE1'\n : m.status === 'archived'\n ? '\uD83D\uDD35'\n : '\u26AA';\n const preview = m.text.replace(/\\s+/g, ' ').trim().slice(0, 140);\n lines.push(`- ${icon} \\`${m.id.slice(0, 12)}\u2026\\` [${m.kind}] ${preview}${tags}`);\n }\n return lines.join('\\n');\n}\n\n// \u2500\u2500 Sage handlers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * List all Sage entries with stats.\n * Request: { type: 'memory.sage.list' }\n * Response: { type: 'memory.sage.list', payload: { memories, stats } }\n */\nexport async function handleSageList(ws: WebSocket, memoryStore: MemoryPort): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage) {\n send(ws, {\n type: 'memory.sage.list',\n payload: { error: requiresSage('memory.sage.list') },\n });\n return;\n }\n try {\n const [stats, memories] = await Promise.all([Sage.stats(), Sage.listSage()]);\n send(ws, { type: 'memory.sage.list', payload: { memories, stats } });\n } catch (err) {\n send(ws, { type: 'memory.sage.list', payload: { error: errMessage(err) } });\n }\n}\n\n/**\n * Paginated, status-filtered Sage listing. Preferred over\n * `memory.sage.list` for the MemoryManager: it returns a bounded page plus a\n * cursor so the WebUI never loads thousands of soft-deleted records at once.\n *\n * Request: { type: 'memory.sage.listPage', payload: { statuses?, kind?, query?, limit?, cursor? } }\n * Response: { type: 'memory.sage.listPage', payload: { memories, nextCursor, total, statusCounts } }\n *\n * `statuses` defaults (backend-side) to every status EXCEPT `deleted`. Pass\n * `statuses: ['deleted']` for the WebUI \"Deleted\" tab. Falls back gracefully to\n * a full `listSage()` for stores that predate `listSagePage`.\n */\nexport async function handleSageListPage(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage) {\n send(ws, {\n type: 'memory.sage.listPage',\n payload: { error: requiresSage('memory.sage.listPage') },\n });\n return;\n }\n try {\n const payload = (msg as { payload?: Record<string, unknown> }).payload ?? {};\n const options = {\n statuses: Array.isArray(payload['statuses'])\n ? (payload['statuses'] as unknown[]).filter((s): s is string => typeof s === 'string')\n : undefined,\n kind: typeof payload['kind'] === 'string' ? (payload['kind'] as string) : undefined,\n query: typeof payload['query'] === 'string' ? (payload['query'] as string) : undefined,\n limit: typeof payload['limit'] === 'number' ? (payload['limit'] as number) : undefined,\n cursor: typeof payload['cursor'] === 'string' ? (payload['cursor'] as string) : undefined,\n };\n\n if (typeof Sage.listSagePage === 'function') {\n const [page, stats] = await Promise.all([\n Sage.listSagePage(options as never),\n Sage.stats(),\n ]);\n send(ws, { type: 'memory.sage.listPage', payload: { ...page, stats } });\n return;\n }\n\n // Backend without native pagination: emulate by loading + slicing in-memory.\n const allowed =\n options.statuses && options.statuses.length > 0 ? new Set(options.statuses) : undefined; // undefined => every status; deleted filtered below\n const everything = await Sage.listSage();\n const statusCounts: Record<string, number> = {};\n for (const m of everything) statusCounts[m.status] = (statusCounts[m.status] ?? 0) + 1;\n const kind = options.kind && options.kind !== 'all' ? options.kind : undefined;\n const q = options.query?.trim().toLowerCase();\n const filtered = everything\n .filter((m) => {\n if (allowed) return allowed.has(m.status);\n return m.status !== 'deleted';\n })\n .filter((m) => !kind || m.kind === kind)\n .filter((m) => !q || m.text.toLowerCase().includes(q));\n const limit = Math.max(1, Math.min(500, Math.floor(options.limit ?? 50)));\n send(ws, {\n type: 'memory.sage.listPage',\n payload: {\n memories: filtered.slice(0, limit),\n nextCursor: null,\n total: filtered.length,\n statusCounts,\n stats: await Sage.stats(),\n },\n });\n } catch (err) {\n send(ws, { type: 'memory.sage.listPage', payload: { error: errMessage(err) } });\n }\n}\n\n/**\n * Get a single Sage entry by ID.\n * Request: { type: 'memory.sage.get', payload: { id } }\n * Response: { type: 'memory.sage.get', payload: { memory } }\n */\nexport async function handleSageGet(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage) {\n send(ws, {\n type: 'memory.sage.get',\n payload: { error: requiresSage('memory.sage.get') },\n });\n return;\n }\n const { id } = (msg as { payload: { id: string } }).payload;\n if (!id) {\n send(ws, { type: 'memory.sage.get', payload: { error: 'id is required' } });\n return;\n }\n try {\n const memory = await Sage.getSage(id);\n if (!memory) {\n send(ws, { type: 'memory.sage.get', payload: { error: `Memory \"${id}\" not found.` } });\n return;\n }\n send(ws, { type: 'memory.sage.get', payload: { memory } });\n } catch (err) {\n send(ws, { type: 'memory.sage.get', payload: { error: errMessage(err) } });\n }\n}\n\n/** Return the real persisted graph plus memory records for directly referenced nodes. */\nexport async function handleSageGraph(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage?.graphFor) {\n send(ws, {\n type: 'memory.sage.graph',\n payload: { query: '', error: requiresSage('memory.sage.graph') },\n });\n return;\n }\n const payload = (msg as { payload?: Record<string, unknown> }).payload ?? {};\n const query = typeof payload['query'] === 'string' ? payload['query'].trim() : '';\n if (!query) {\n send(ws, { type: 'memory.sage.graph', payload: { query, error: 'query is required' } });\n return;\n }\n const maxDepth =\n typeof payload['maxDepth'] === 'number'\n ? Math.max(1, Math.min(3, Math.floor(payload['maxDepth'])))\n : 1;\n const limit =\n typeof payload['limit'] === 'number'\n ? Math.max(1, Math.min(250, Math.floor(payload['limit'])))\n : 100;\n try {\n const edges = await Sage.graphFor(query, maxDepth, limit);\n const memoryIds = new Set<string>();\n for (const edge of edges) {\n for (const node of [edge.from, edge.to]) {\n if (node.startsWith('mem:')) memoryIds.add(node.slice(4));\n }\n }\n const memories = (\n await Promise.all([...memoryIds].map((id) => Sage.getSage(id)))\n ).filter((memory) => memory !== null);\n send(ws, { type: 'memory.sage.graph', payload: { query, edges, memories } });\n } catch (err) {\n send(ws, {\n type: 'memory.sage.graph',\n payload: { query, error: errMessage(err) },\n });\n }\n}\n\n/**\n * Update a Sage entry.\n * Request: { type: 'memory.sage.update', payload: { id, ...patch } }\n * Response: { type: 'memory.sage.update', payload: { memory } }\n * On error: { type: 'memory.sage.update', payload: { error } }\n */\nexport async function handleSageUpdate(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage) {\n send(ws, {\n type: 'memory.sage.update',\n payload: { error: requiresSage('memory.sage.update') },\n });\n return;\n }\n const payload = (msg as { payload: Record<string, unknown> }).payload;\n const id = payload['id'] as string | undefined;\n if (!id) {\n send(ws, { type: 'memory.sage.update', payload: { error: 'id is required' } });\n return;\n }\n\n // Extract patch fields (everything except id)\n const patch: Record<string, unknown> = { ...payload };\n delete patch['id'];\n\n if (Object.keys(patch).length === 0) {\n send(ws, { type: 'memory.sage.update', payload: { error: 'No fields to update.' } });\n return;\n }\n\n try {\n const memory = await Sage.updateSage(id, patch as never);\n send(ws, { type: 'memory.sage.update', payload: { memory } });\n } catch (err) {\n send(ws, { type: 'memory.sage.update', payload: { error: errMessage(err) } });\n }\n}\n\n/**\n * Create a new Sage entry with full metadata.\n * Request: { type: 'memory.sage.remember', payload: { text, kind?, scope?, tags?, anchors?, importance?, confidence?, freshness?, supersedes?, contradicts? } }\n * Response: { type: 'memory.sage.remember', payload: { memory } }\n * On error: { type: 'memory.sage.remember', payload: { error } }\n */\nexport async function handleSageRemember(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage) {\n send(ws, {\n type: 'memory.sage.remember',\n payload: { error: requiresSage('memory.sage.remember') },\n });\n return;\n }\n const payload = (msg as { payload: Record<string, unknown> }).payload;\n const text = payload['text'] as string | undefined;\n if (!text?.trim()) {\n send(ws, { type: 'memory.sage.remember', payload: { error: 'text is required' } });\n return;\n }\n try {\n const memory = await Sage.rememberSage({\n text: text.trim(),\n kind: payload['kind'] as string | undefined,\n scope: payload['scope'] as string | undefined,\n tags: payload['tags'] as string[] | undefined,\n anchors: payload['anchors'] as\n | Array<{ type: string; path?: string; symbol?: string; command?: string }>\n | undefined,\n importance: payload['importance'] as number | undefined,\n confidence: payload['confidence'] as number | undefined,\n freshness: payload['freshness'] as number | undefined,\n audience: payload['audience'] as\n | { roles?: string[]; taskTypes?: string[]; modes?: string[] }\n | undefined,\n supersedes: payload['supersedes'] as string[] | undefined,\n contradicts: payload['contradicts'] as string[] | undefined,\n } as never);\n send(ws, { type: 'memory.sage.remember', payload: { memory } });\n } catch (err) {\n send(ws, { type: 'memory.sage.remember', payload: { error: errMessage(err) } });\n }\n}\n\n/**\n * Delete a Sage entry (soft-delete with cascade cleanup).\n * Request: { type: 'memory.sage.delete', payload: { id, reason?, force?, neverInject? } }\n * Response: { type: 'memory.sage.delete', payload: { success, message } }\n *\n * `force` defaults to `true` (backward-compatible). When `false`, the\n * permanent-memory guard in `deleteSage` is respected and\n * `persistence: 'permanent'` entries cannot be deleted.\n *\n * `neverInject` (default false) marks the memory so context injection\n * never loads it \u2014 used when a memory is factually wrong, not just\n * superseded.\n *\n * Uses an operation-specific response type (not the generic\n * `key.operation_result`) so the client can correlate the response\n * to this specific action without matching unrelated broadcast events.\n */\nexport async function handleSageDelete(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage) {\n send(ws, {\n type: 'memory.sage.delete',\n payload: { success: false, message: requiresSage('memory.sage.delete') },\n });\n return;\n }\n const { id, reason, neverInject, force } = (\n msg as {\n payload: {\n id: string;\n reason?: string | undefined;\n neverInject?: boolean | undefined;\n force?: boolean | undefined;\n };\n }\n ).payload;\n if (!id) {\n send(ws, {\n type: 'memory.sage.delete',\n payload: { success: false, message: 'id is required' },\n });\n return;\n }\n try {\n // Default force: true for backward compatibility \u2014 existing WebUI\n // clients always force-delete. Newer clients may pass force: false\n // to respect the permanent-memory guard (soft-delete path).\n await Sage.deleteSage(id, reason, {\n force: force ?? true,\n neverInject: neverInject === true,\n });\n send(ws, {\n type: 'memory.sage.delete',\n payload: { success: true, message: `Deleted memory \"${id}\".` },\n });\n } catch (err) {\n send(ws, {\n type: 'memory.sage.delete',\n payload: { success: false, message: errMessage(err) },\n });\n }\n}\n\n/**\n * Restore a deleted SAGE entry to active status (PR #1).\n * Request: { type: 'memory.sage.recover', payload: { id, reason? } }\n * Response: { type: 'memory.sage.recover', payload: { memory?, noop?, activeId? } }\n *\n * - `noop: true` when the id was already active (no write happened)\n * - `activeId: <id>` when the id was superseded \u2014 returns the head of the chain\n * - otherwise returns the freshly-restored memory\n */\nexport async function handleSageRecover(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage?.recoverSage) {\n send(ws, {\n type: 'memory.sage.recover',\n payload: { error: requiresSage('memory.sage.recover') },\n });\n return;\n }\n const payload = (msg as { payload: Record<string, unknown> }).payload;\n const id = payload['id'] as string | undefined;\n if (!id) {\n send(ws, { type: 'memory.sage.recover', payload: { error: 'id is required' } });\n return;\n }\n const reason = payload['reason'] as string | undefined;\n try {\n const preExisting = await Sage.getSage(id);\n if (!preExisting) {\n send(ws, {\n type: 'memory.sage.recover',\n payload: { error: `SAGE \"${id}\" not found.` },\n });\n return;\n }\n // Already active: no-op \u2014 return the existing record without calling recover.\n if (preExisting.status === 'active') {\n send(ws, {\n type: 'memory.sage.recover',\n payload: { recovered: true, memory: preExisting, noop: true },\n });\n return;\n }\n // Deleted or superseded: call recover to get the actual result.\n const memory = await Sage.recoverSage(id, reason);\n // Superseded: the store returns the chain head (different id).\n const noop = memory.id !== id;\n const response: Record<string, unknown> = { recovered: true, memory };\n if (noop) {\n response['activeId'] = memory.id;\n response['noop'] = true;\n }\n send(ws, { type: 'memory.sage.recover', payload: response });\n } catch (err) {\n send(ws, { type: 'memory.sage.recover', payload: { error: errMessage(err) } });\n }\n}\n\n/**\n * Resolve a pending hygiene review candidate (PR #1).\n * Request: { type: 'memory.sage.candidateResolve', payload: { candidateId, action: 'accept'|'reject', reason? } }\n * Response: { type: 'memory.sage.candidateResolve', payload: { candidate, resolvedAction } }\n *\n * The store handles audit + status mutation; the handler just relays the\n * payload. If the candidate id is unknown, the store returns null and we\n * surface a structured error.\n */\nexport async function handleSageCandidateResolve(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage) {\n send(ws, {\n type: 'memory.sage.candidateResolve',\n payload: { error: requiresSage('memory.sage.candidateResolve') },\n });\n return;\n }\n const payload = (msg as { payload: Record<string, unknown> }).payload;\n const candidateId = payload['candidateId'] as string | undefined;\n const action = payload['action'] as 'accept' | 'reject' | undefined;\n if (!candidateId) {\n send(ws, {\n type: 'memory.sage.candidateResolve',\n payload: { error: 'candidateId is required' },\n });\n return;\n }\n if (action !== 'accept' && action !== 'reject') {\n send(ws, {\n type: 'memory.sage.candidateResolve',\n payload: { error: 'action must be \"accept\" or \"reject\"' },\n });\n return;\n }\n const reason = payload['reason'] as string | undefined;\n try {\n let candidate: { id: string; status: string } | undefined;\n if (action === 'accept') {\n const accepted = await Sage.acceptCandidate(candidateId);\n candidate = accepted ? { id: accepted.id, status: accepted.status ?? 'active' } : undefined;\n } else {\n const rejected = await Sage.rejectCandidate(\n candidateId,\n reason ?? 'Rejected via WebUI',\n );\n candidate = rejected ? { id: candidateId, status: 'rejected' } : undefined;\n }\n if (!candidate) {\n send(ws, {\n type: 'memory.sage.candidateResolve',\n payload: { error: `Candidate \"${candidateId}\" not found` },\n });\n return;\n }\n send(ws, {\n type: 'memory.sage.candidateResolve',\n payload: { candidate, resolvedAction: action },\n });\n } catch (err) {\n send(ws, {\n type: 'memory.sage.candidateResolve',\n payload: { error: errMessage(err) },\n });\n }\n}\n\n/**\n * Scan deleted records and either preview (dry-run) or apply a backfill\n * that creates fresh active versions for recoverable entries (PR #3).\n *\n * Request: { type: 'memory.sage.backfillRecoverable', payload: { apply, filter? } }\n * Response: { type: 'memory.sage.backfillRecoverable', payload: { examined, recovered, recoverable, dryRun } }\n *\n * `apply` defaults to false (dry-run preview). When true, the store writes\n * new active versions and links them to the original `deleted` records via\n * `supersedes`. The report count fields are forwarded for dashboard / UI use.\n */\nexport async function handleSageBackfillRecoverable(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage?.backfillRecoverable) {\n send(ws, {\n type: 'memory.sage.backfillRecoverable',\n payload: { error: requiresSage('memory.sage.backfillRecoverable') },\n });\n return;\n }\n const payload = (msg as { payload: Record<string, unknown> }).payload ?? {};\n const apply = payload['apply'] === true;\n // Filter passthrough is permissive: the store validates per-field. We\n // only pass fields that are present so absent fields stay absent (the\n // store defaults its own omission to \"no filter\").\n const rawFilter = (payload['filter'] ?? {}) as Record<string, unknown>;\n const filter: {\n kinds?: string[];\n scopes?: string[];\n updatedAfter?: string;\n updatedBefore?: string;\n } = {};\n if (Array.isArray(rawFilter['kinds'])) filter.kinds = rawFilter['kinds'] as string[];\n if (Array.isArray(rawFilter['scopes'])) filter.scopes = rawFilter['scopes'] as string[];\n if (typeof rawFilter['updatedAfter'] === 'string')\n filter.updatedAfter = rawFilter['updatedAfter'];\n if (typeof rawFilter['updatedBefore'] === 'string')\n filter.updatedBefore = rawFilter['updatedBefore'];\n try {\n const report = await Sage.backfillRecoverable({\n dryRun: !apply,\n ...(Object.keys(filter).length > 0 ? { filter } : {}),\n } as never);\n send(ws, {\n type: 'memory.sage.backfillRecoverable',\n payload: {\n examined: report.examined,\n recovered: report.recovered,\n recoverable: report.recoverable,\n dryRun: !apply,\n },\n });\n } catch (err) {\n send(ws, {\n type: 'memory.sage.backfillRecoverable',\n payload: { error: errMessage(err) },\n });\n }\n}\n\n/**\n * Rich file-drawer query \u2014 returns 3 buckets (primary/symbol/related)\n * with matchedVia, matchStrength, supersededByActiveId, pendingReview (PR #4).\n */\nexport async function handleSageForFile(\n ws: WebSocket,\n msg: unknown,\n memoryStore: MemoryPort,\n): Promise<void> {\n const Sage = getSageSurface(memoryStore);\n if (!Sage?.findMemoriesForFile) {\n send(ws, {\n type: 'memory.sage.forFile',\n payload: { error: requiresSage('memory.sage.forFile') },\n });\n return;\n }\n const payload = (msg as { payload: Record<string, unknown> }).payload ?? {};\n const filePath = payload['filePath'] as string | undefined;\n if (!filePath) {\n send(ws, { type: 'memory.sage.forFile', payload: { error: 'filePath is required' } });\n return;\n }\n try {\n const response = await Sage.findMemoriesForFile(filePath, {\n ...(typeof payload['lineStart'] === 'number'\n ? { lineStart: payload['lineStart'] as number }\n : {}),\n ...(typeof payload['lineEnd'] === 'number' ? { lineEnd: payload['lineEnd'] as number } : {}),\n ...(typeof payload['limit'] === 'number' ? { limit: payload['limit'] as number } : {}),\n ...(payload['includeDeleted'] === true ? { includeDeleted: true } : {}),\n });\n send(ws, { type: 'memory.sage.forFile', payload: response });\n } catch (err) {\n send(ws, { type: 'memory.sage.forFile', payload: { error: errMessage(err) } });\n }\n}\n", "import type { MemoryPort } from '@wrongstack/core/types';\nimport type { WebSocket } from 'ws';\nimport {\n handleMemoryList,\n handleSageBackfillRecoverable,\n handleSageCandidateResolve,\n handleSageDelete,\n handleSageForFile,\n handleSageGet,\n handleSageGraph,\n handleSageList,\n handleSageListPage,\n handleSageRecover,\n handleSageRemember,\n handleSageUpdate,\n} from './memory-handlers.js';\nimport type { WSClientMessage, WSServerMessage } from './types.js';\n\nexport interface MemoryRouteContext {\n getMemoryStore: () => MemoryPort | undefined;\n send: (ws: WebSocket, message: WSServerMessage) => void;\n sendResult: (ws: WebSocket, success: boolean, message: string) => void;\n}\n\nfunction unavailable(ctx: MemoryRouteContext, ws: WebSocket, type: string): void {\n if (type === 'memory.sage.delete') {\n ctx.sendResult(ws, false, 'Memory store not available');\n return;\n }\n ctx.send(ws, {\n type,\n payload: {\n ...(type === 'memory.list' ? { text: '' } : {}),\n ...(type === 'memory.sage.graph' ? { query: '' } : {}),\n error: 'Memory store not available',\n },\n });\n}\n\n/** Canonical Memory/Sage routing and unavailable-store behavior. */\nexport async function handleMemoryRoute(\n ctx: MemoryRouteContext,\n ws: WebSocket,\n message: WSClientMessage,\n): Promise<boolean> {\n if (message.type !== 'memory.list' && !message.type.startsWith('memory.sage.')) return false;\n const store = ctx.getMemoryStore();\n if (!store) {\n unavailable(ctx, ws, message.type);\n return true;\n }\n switch (message.type) {\n case 'memory.list':\n await handleMemoryList(ws, store);\n return true;\n case 'memory.sage.list':\n await handleSageList(ws, store);\n return true;\n case 'memory.sage.listPage':\n await handleSageListPage(ws, message, store);\n return true;\n case 'memory.sage.get':\n await handleSageGet(ws, message, store);\n return true;\n case 'memory.sage.graph':\n await handleSageGraph(ws, message, store);\n return true;\n case 'memory.sage.update':\n await handleSageUpdate(ws, message, store);\n return true;\n case 'memory.sage.delete':\n await handleSageDelete(ws, message, store);\n return true;\n case 'memory.sage.remember':\n await handleSageRemember(ws, message, store);\n return true;\n case 'memory.sage.recover':\n await handleSageRecover(ws, message, store);\n return true;\n case 'memory.sage.candidateResolve':\n await handleSageCandidateResolve(ws, message, store);\n return true;\n case 'memory.sage.backfillRecoverable':\n await handleSageBackfillRecoverable(ws, message, store);\n return true;\n case 'memory.sage.forFile':\n await handleSageForFile(ws, message, store);\n return true;\n default:\n return false;\n }\n}\n", "import type { ModeStore } from '@wrongstack/core/types';\nimport { ToolValidationError } from '@wrongstack/core/types';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from './types.js';\n\ninterface ModeSession {\n append(event: { type: 'mode_changed'; ts: string; from: string; to: string }): Promise<unknown>;\n}\n\nexport interface ModeOperationsContext {\n modeStore?: ModeStore | undefined;\n getSession?: (() => ModeSession | null | undefined) | undefined;\n applyModeId: (id: string) => void;\n afterSwitch?: ((id: string) => void | Promise<void>) | undefined;\n send: (ws: WebSocket, message: WSServerMessage) => void;\n}\n\nfunction sendResult(\n context: ModeOperationsContext,\n ws: WebSocket,\n success: boolean,\n message: string,\n): void {\n context.send(ws, { type: 'key.operation_result', payload: { success, message } });\n}\n\nexport function createModeOperations(context: ModeOperationsContext) {\n return {\n async listModes(ws: WebSocket): Promise<void> {\n if (!context.modeStore) {\n context.send(ws, {\n type: 'modes.list',\n payload: { modes: [], activeId: 'default', error: 'Mode store not available' },\n });\n return;\n }\n try {\n const modes = await context.modeStore.listModes();\n const active = await context.modeStore.getActiveMode();\n context.send(ws, {\n type: 'modes.list',\n payload: {\n modes: modes.map((mode) => ({\n id: mode.id,\n name: mode.name,\n description: mode.description,\n isActive: mode.id === (active?.id ?? 'default'),\n })),\n activeId: active?.id ?? 'default',\n },\n });\n } catch (error) {\n context.send(ws, {\n type: 'modes.list',\n payload: { modes: [], activeId: 'default', error: toErrorMessage(error) },\n });\n }\n },\n\n async switchMode(ws: WebSocket, id: string): Promise<void> {\n if (!context.modeStore) {\n sendResult(context, ws, false, 'Mode store not available');\n return;\n }\n try {\n const previous = await context.modeStore.getActiveMode();\n if (id === 'default') await context.modeStore.setActiveMode(null);\n else {\n const found = await context.modeStore.getMode(id);\n if (!found) {\n throw new ToolValidationError({\n message: `Unknown mode \"${id}\"`,\n field: 'modeId',\n context: { requestedMode: id, kind: 'mode.switch' },\n });\n }\n await context.modeStore.setActiveMode(id);\n }\n context.applyModeId(id);\n const from = previous?.id ?? 'default';\n const session = context.getSession?.();\n if (session && from !== id) {\n void session\n .append({ type: 'mode_changed', ts: new Date().toISOString(), from, to: id })\n .catch(() => undefined);\n }\n await context.afterSwitch?.(id);\n sendResult(context, ws, true, `Switched to mode \"${id}\"`);\n } catch (error) {\n sendResult(context, ws, false, toErrorMessage(error));\n }\n },\n };\n}\n", "import type { WebSocket } from 'ws';\nimport { createModeOperations, type ModeOperationsContext } from './mode-operations.js';\nimport type { WSClientMessage } from './types.js';\nimport { validateModeSwitchPayload } from './ws-payload-validation.js';\n\nexport interface ModeRouteHandlers {\n listModes: (ws: WebSocket) => Promise<void>;\n switchMode: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n}\n\nexport function createModeRouteHandlers(context: ModeOperationsContext): ModeRouteHandlers {\n const operations = createModeOperations(context);\n return {\n listModes: operations.listModes,\n switchMode: async (ws, message) => {\n const parsed = validateModeSwitchPayload(message.payload);\n if (!parsed.ok) {\n context.send(ws, {\n type: 'key.operation_result',\n payload: { success: false, message: parsed.message },\n });\n return;\n }\n await operations.switchMode(ws, parsed.value.id);\n },\n };\n}\n\nexport async function handleModeRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: ModeRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'modes.list':\n await handlers.listModes(ws);\n return true;\n case 'mode.switch':\n await handlers.switchMode(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import type { Context } from '@wrongstack/core/agent';\nimport type { EnhanceFailureKind } from '@wrongstack/core/execution';\nimport type {\n Config,\n MemoryPort,\n ModelsRegistry,\n Provider,\n ProviderConfig,\n} from '@wrongstack/core/types';\nimport {\n buildRefinerContextSections,\n enhanceUserPrompt,\n gatedEnhancerReasoning,\n nextEnhanceTimeout,\n recentTextTurns,\n resolveConfiguredRefinerRef,\n resolveEnhanceFallbackRef,\n} from '@wrongstack/core/execution';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport type { WebSocket } from 'ws';\nimport { resolveProviderModelMetadata } from './model-catalog.js';\nimport type { WSServerMessage } from './types.js';\nimport { validateModelSwitchPayload } from './ws-payload-validation.js';\n\nexport interface ModelRefinePayload {\n text: string;\n timeoutMs?: number | undefined;\n provider?: string | undefined;\n model?: string | undefined;\n previousRefined?: string | undefined;\n previousEnglish?: string | undefined;\n retryFeedback?: string | undefined;\n}\n\nexport interface ModelOperationsContext {\n context: Context;\n memoryStore?: MemoryPort | undefined;\n modelsRegistry?: ModelsRegistry | undefined;\n getConfig: () => Config | undefined;\n getLiveProviderId: () => string;\n buildProvider: (providerId: string, config: ProviderConfig) => Provider | Promise<Provider>;\n applyModelSwitch: (providerId: string, modelId: string) => Promise<void>;\n isRunActive?: (() => boolean) | undefined;\n send: (ws: WebSocket, message: WSServerMessage) => void;\n broadcast?: ((message: WSServerMessage) => void) | undefined;\n log?: ((message: string) => void) | undefined;\n}\n\nfunction sendResult(\n context: ModelOperationsContext,\n ws: WebSocket,\n payload: {\n requestId?: string | undefined;\n success: boolean;\n message: string;\n provider?: string | undefined;\n model?: string | undefined;\n previousProvider?: string | undefined;\n previousModel?: string | undefined;\n runActive: boolean;\n },\n legacyResult = false,\n): void {\n const message = { type: 'model.switch_result', payload };\n if (payload.success && context.broadcast) context.broadcast(message);\n else context.send(ws, message);\n // SimpleUI and older clients do not attach requestId yet. Keep their status\n // notice alive without reintroducing the ambiguous generic result for modern\n // WebUI requests.\n if (legacyResult) {\n context.send(ws, {\n type: 'key.operation_result',\n payload: { success: payload.success, message: payload.message },\n });\n }\n}\n\nexport function createModelOperations(context: ModelOperationsContext) {\n // A model switch rebuilds and persists shared live session state. Serialize\n // requests from multiple tabs so a slower provider build cannot overwrite a\n // newer selection after it completes.\n let switchQueue: Promise<void> = Promise.resolve();\n\n async function switchModel(ws: WebSocket, input: unknown): Promise<void> {\n const parsed = validateModelSwitchPayload(input);\n if (!parsed.ok) {\n sendResult(\n context,\n ws,\n {\n success: false,\n message: parsed.message,\n runActive: context.isRunActive?.() ?? false,\n },\n true,\n );\n return;\n }\n const { provider, model, requestId } = parsed.value;\n const queued = switchQueue.then(async () => {\n const previousProvider = context.getLiveProviderId();\n const previousModel = context.context.model;\n const runActive = context.isRunActive?.() ?? false;\n try {\n await context.applyModelSwitch(provider, model);\n sendResult(\n context,\n ws,\n {\n ...(requestId ? { requestId } : {}),\n success: true,\n message: `Switched to ${provider} / ${model}`,\n provider,\n model,\n previousProvider,\n previousModel,\n runActive,\n },\n requestId === undefined,\n );\n } catch (error) {\n sendResult(\n context,\n ws,\n {\n ...(requestId ? { requestId } : {}),\n success: false,\n message: `Switch failed: ${toErrorMessage(error)}`,\n provider,\n model,\n previousProvider,\n previousModel,\n runActive,\n },\n requestId === undefined,\n );\n }\n });\n switchQueue = queued.catch(() => undefined);\n await queued;\n }\n\n async function buildTargetProvider(\n providerId: string,\n config: Config | undefined,\n ): Promise<Provider> {\n return context.buildProvider(\n providerId,\n config?.providers?.[providerId] ?? { type: providerId },\n );\n }\n\n async function refineModel(ws: WebSocket, payload: ModelRefinePayload): Promise<void> {\n const text = payload.text;\n if (!text?.trim()) {\n context.send(ws, {\n type: 'model.refine_result',\n payload: { refined: '', english: '', error: 'Empty text', errorKind: 'provider_error' },\n });\n return;\n }\n\n const config = context.getConfig();\n const liveProviderId = context.getLiveProviderId();\n const liveModel = context.context.model;\n const fallbackRef = config\n ? resolveEnhanceFallbackRef({ ...config, provider: liveProviderId, model: liveModel })\n : undefined;\n let provider = context.context.provider;\n let providerId = liveProviderId;\n let model = liveModel;\n\n if (payload.provider && payload.model) {\n try {\n provider = await buildTargetProvider(payload.provider, config);\n providerId = payload.provider;\n model = payload.model;\n } catch (error) {\n context.send(ws, {\n type: 'model.refine_result',\n payload: {\n refined: text,\n english: text,\n error: `Cannot use ${payload.provider}/${payload.model}: ${toErrorMessage(error)}`,\n errorKind: 'provider_error',\n ...(fallbackRef ? { fallbackRef } : {}),\n },\n });\n return;\n }\n } else if (config) {\n const configuredRef = resolveConfiguredRefinerRef({\n ...config,\n provider: liveProviderId,\n model: liveModel,\n });\n if (configuredRef) {\n const slash = configuredRef.indexOf('/');\n const configuredProvider = slash > 0 ? configuredRef.slice(0, slash) : liveProviderId;\n const configuredModel = slash > 0 ? configuredRef.slice(slash + 1) : configuredRef;\n try {\n provider = await buildTargetProvider(configuredProvider, config);\n providerId = configuredProvider;\n model = configuredModel;\n } catch {\n // An unavailable dedicated refiner must not block the live model.\n }\n }\n }\n\n const timeoutMs =\n typeof payload.timeoutMs === 'number' && payload.timeoutMs > 0 ? payload.timeoutMs : 90_000;\n try {\n const history = recentTextTurns(context.context.messages);\n const contextSections = await buildRefinerContextSections({\n text,\n memoryStore: context.memoryStore,\n context: context.context,\n });\n const resolved = context.modelsRegistry\n ? await resolveProviderModelMetadata(\n context.modelsRegistry,\n providerId,\n model,\n config?.providers?.[providerId],\n ).catch(() => undefined)\n : undefined;\n const reasoning = gatedEnhancerReasoning(resolved?.capabilities.reasoningConfig as never);\n let failureKind: EnhanceFailureKind | undefined;\n const result = await enhanceUserPrompt({\n provider,\n model,\n text,\n history,\n contextSections,\n ...(payload.previousRefined\n ? {\n previousRefinement: {\n refined: payload.previousRefined,\n english: payload.previousEnglish || payload.previousRefined,\n },\n }\n : {}),\n ...(payload.retryFeedback ? { retryFeedback: payload.retryFeedback } : {}),\n timeoutMs,\n ...(reasoning ? { reasoning } : {}),\n onError: (reason, kind) => {\n failureKind = kind;\n context.log?.(\n JSON.stringify({\n level: 'warn',\n event: 'model.refine_failed',\n reason,\n kind,\n provider: providerId,\n model,\n timestamp: new Date().toISOString(),\n }),\n );\n },\n });\n if (result) {\n context.send(ws, {\n type: 'model.refine_result',\n payload: {\n refined: result.refined,\n english: result.english,\n refinedWith: { provider: providerId, model },\n },\n });\n return;\n }\n context.send(ws, {\n type: 'model.refine_result',\n payload: {\n refined: text,\n english: text,\n error: 'Refinement returned no result',\n errorKind: failureKind ?? 'empty',\n ...(failureKind === 'timeout'\n ? { retryTimeoutMs: nextEnhanceTimeout(timeoutMs, config?.autonomy) }\n : {}),\n ...(fallbackRef ? { fallbackRef } : {}),\n },\n });\n } catch (error) {\n context.log?.(\n JSON.stringify({\n level: 'error',\n event: 'model.refine.error',\n error: toErrorMessage(error),\n timestamp: new Date().toISOString(),\n }),\n );\n context.send(ws, {\n type: 'model.refine_result',\n payload: {\n refined: text,\n english: text,\n error: toErrorMessage(error),\n errorKind: 'provider_error',\n ...(fallbackRef ? { fallbackRef } : {}),\n },\n });\n }\n }\n\n return { switchModel, refineModel };\n}\n", "/**\n * Best-effort \"open this URL in the default browser\" for `--webui --open`.\n *\n * Cross-platform via the OS opener (`start` / `open` / `xdg-open`). Fully\n * fire-and-forget: a missing opener, a headless box, or a spawn failure must\n * NEVER take the server down \u2014 the URL is always also printed to the console.\n */\n\nimport { spawn } from 'node:child_process';\n\n/** Resolve the platform's URL-opener command + args. */\nexport function browserOpenCommand(\n url: string,\n platform: NodeJS.Platform = process.platform,\n): { command: string; args: string[] } {\n if (platform === 'win32') {\n // `start` is a cmd builtin; the empty \"\" is the window title slot so URLs\n // containing `&` / spaces are passed through intact.\n return { command: 'cmd', args: ['/c', 'start', '', url] };\n }\n if (platform === 'darwin') {\n return { command: 'open', args: [url] };\n }\n return { command: 'xdg-open', args: [url] };\n}\n\n/** Spawn the OS browser-opener for `url` and register it as a protected\n * process so it survives kill/killAll. Never throws. */\nexport function openBrowser(url: string, platform: NodeJS.Platform = process.platform): void {\n try {\n const { command, args } = browserOpenCommand(url, platform);\n const child = spawn(command, args, { stdio: 'ignore', detached: true, windowsHide: true });\n // A missing opener (e.g. xdg-open absent on a headless box) surfaces as an\n // async 'error' event \u2014 swallow it so it doesn't crash the process.\n child.on('error', () => {});\n child.unref();\n\n // Register the browser process as protected so process.kill / killAll\n // never accidentally terminates it \u2014 that would crash the webui session.\n // The registry is imported lazily to avoid a circular dependency with\n // @wrongstack/tools (which the webui server does not directly depend on).\n if (child.pid) {\n try {\n // Dynamic import to avoid hard dependency on @wrongstack/tools from\n // this module (the webui server may not have tools installed).\n import('@wrongstack/tools').then(({ getProcessRegistry }) => {\n const pid = child.pid;\n if (pid === undefined) return;\n getProcessRegistry().register({\n pid,\n name: 'browser',\n command: `${command} ${args.join(' ')}`,\n startedAt: Date.now(),\n child,\n protected: true,\n });\n // Auto-unregister on exit so the process list stays accurate.\n child.on('exit', () => {\n getProcessRegistry().unregister(pid);\n });\n }).catch(() => {\n // @wrongstack/tools may not be available \u2014 silently skip registration.\n });\n } catch {\n // Module resolution failure \u2014 silently skip.\n }\n }\n } catch {\n // Synchronous spawn failure \u2014 best-effort, ignore.\n }\n}\n", "/**\n * Port constants for the WebUI / SimpleUI servers.\n *\n * Design:\n * - **Single port \u2014 shared HTTP + WebSocket.** The WebSocket server attaches\n * to the HTTP server (`new WebSocketServer({ server: httpServer })`), so\n * both protocols share one port. No separate WS port is needed.\n * - **Auto-advance.** When a port is taken the server probes upward \u2014 WebUI\n * starts at 3456, SimpleUI at 3466. Set `WEBUI_STRICT_PORT=1` to disable.\n * - **TOCTOU window.** The probe in `findFreePort` binds a throwaway\n * `net.Server` then closes it, so there is a tiny race between \"found free\"\n * and \"real server binds\". For local multi-instance use that race is\n * negligible; if it ever loses, the real bind fails loudly with EADDRINUSE\n * exactly as before.\n * - **Instance registry.** Every live process records itself in\n * `~/.wrongstack/webui-instances.json` with its PID, surface, port, and\n * project root. A crashed instance is pruned on the next registry read\n * (`process.kill(pid, 0)` probe), so ghosts don't accumulate.\n */\n\nimport * as net from 'node:net';\nimport { ToolValidationError } from '@wrongstack/core/types';\n\n/**\n * Surface-specific default single port.\n *\n * WebSocket shares the HTTP port (single-port design), so only one port\n * number is specified per surface:\n *\n * WebUI: 3456\n * SimpleUI: 3466\n */\nexport const SURFACE_DEFAULT_PORTS = {\n webui: { http: 3456 },\n simpleui: { http: 3466 },\n} as const satisfies Record<string, { http: number }>;\n\nexport type SurfaceKind = keyof typeof SURFACE_DEFAULT_PORTS;\n\n/** Human-readable label for surfaces. */\nexport function surfaceLabel(surface: SurfaceKind): string {\n return surface === 'webui' ? 'WebUI' : 'SimpleUI';\n}\n\n/**\n * Return the surface-specific default HTTP port.\n */\nexport function getSurfaceDefaultPorts(surface: SurfaceKind): {\n http: number;\n} {\n return { http: SURFACE_DEFAULT_PORTS[surface].http };\n}\n\n/** Resolve true when `port` can be bound on `host`, false on EADDRINUSE/EACCES. */\nexport function isPortFree(host: string, port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const srv = net.createServer();\n srv.once('error', () => resolve(false));\n srv.once('listening', () => {\n srv.close(() => resolve(true));\n });\n try {\n srv.listen(port, host);\n } catch {\n resolve(false);\n }\n });\n}\n\nexport interface FindFreePortOptions {\n /** Ports to skip even if free (e.g. one already chosen for the sibling server). */\n exclude?: Set<number> | undefined;\n /** How many consecutive ports to try before giving up. Default 200. */\n maxTries?: number | undefined;\n}\n\n/**\n * Find the first free port at or above `startPort` on `host`, skipping any in\n * `exclude`. Throws if nothing is free within `maxTries` steps.\n */\nexport async function findFreePort(\n host: string,\n startPort: number,\n opts: FindFreePortOptions = {},\n): Promise<number> {\n const exclude = opts.exclude ?? new Set<number>();\n const maxTries = opts.maxTries ?? 200;\n let port = startPort;\n for (let i = 0; i < maxTries; i++) {\n // Stay inside the valid TCP range; wrap into the high ephemeral band if a\n // pathological startPort pushes us past the ceiling.\n if (port > 65535) port = 1024 + (port % 50000);\n if (!exclude.has(port) && (await isPortFree(host, port))) {\n return port;\n }\n port++;\n }\n throw new ToolValidationError({\n message: `No free port found near ${startPort} on ${host} after ${maxTries} attempts.`,\n field: 'port',\n });\n}\n", "import { spawn } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { findPackageJSON } from 'node:module';\nimport * as path from 'node:path';\nimport type { Server } from 'node:http';\nimport { type CreateHttpServerOptions, createHttpServer } from './http-server.js';\n\n/**\n * PR 6 of Issue #30 (webui-server 8-PR refactor):\n * dist discovery + HTTP server bring-up.\n *\n * Before this PR, the `runWebUI` body inlined five lines\n * that resolved the webui package's `dist` directory via\n * `createRequire(import.meta.url)` and handed the path to\n * `createHttpServer`. If the webui package wasn't built,\n * the inline try/catch silently degraded to WS-only.\n *\n * After this PR, the dist-resolution lives in\n * `webui-server/static-serve.ts` and the only thing\n * `runWebUI` does is call `startStaticServe({ host,\n * httpPort, globalRoot })`. The function returns\n * the listening `Server` and its real `port` (the OS\n * may reassign if the requested port was in use), or\n * `null` when the webui package is unbuilt.\n *\n * The try/catch around the require resolution stays\n * inside this module so the runWebUI body does not have\n * to think about webui's build state at all.\n */\n\nexport interface StaticServeHandle {\n server: Server;\n port: number;\n}\n\nexport interface StaticServeOptions {\n host: string;\n httpPort: number;\n globalRoot: string;\n /** Explicit frontend build. Omitted for the regular @wrongstack/webui app. */\n distDir?: string | undefined;\n /** Push-on-write hook for `POST /api/fleet/ping` (immediate fleet re-broadcast). */\n onFleetPing?: (() => void) | undefined;\n /** TechStack HTTP job events projected to the embedded WebSocket server. */\n onTechStackEvent?:\n | ((event: import('@wrongstack/webui-server').WSServerMessage) => void)\n | undefined;\n /**\n * Live provider access for TechStack's LLM research stage. Omitting it\n * leaves `analyze` deterministic \u2014 so this must be threaded here as well as\n * in the standalone `start-webui` server, or the CLI-hosted WebUI silently\n * loses LLM analysis while the standalone one has it.\n */\n getLlm?:\n | (() => { provider: import('@wrongstack/core/types').Provider; model: string } | undefined)\n | undefined;\n /** Active target project root for TechStack and CodeMap APIs. */\n projectRoot?: string | undefined;\n /** Public browser-facing WS URL injected into the React app. */\n publicWsUrl?: string | undefined;\n /**\n * Shared auth token for `/ws-auth` and `/api/*` endpoints. Required for\n * the cookie-based auth flow: the frontend extracts this from the URL,\n * calls `/ws-auth?token=...` to get an HttpOnly cookie, then uses the\n * cookie for subsequent WS upgrades (closing C-598 query-string exposure).\n */\n apiToken?: string | undefined;\n /** Force token auth even when the server binds to loopback. */\n requireToken?: boolean | undefined;\n /**\n * When true, skip `server.listen()` \u2014 the caller is responsible for\n * calling listen after attaching the WebSocketServer. This prevents\n * a race where a WS upgrade request arrives between the server\n * listening and the WebSocketServer being attached.\n */\n deferListen?: boolean | undefined;\n /** Package-resolution/build seams supplied by the owning host. */\n ensureDistDeps?: EnsureDistDeps | undefined;\n}\n\n/**\n * Resolve the webui package's built `dist` directory.\n *\n * Returns the absolute path, or `null` if the package or its built\n * `index.html` cannot be found. This is the one piece of\n * `startStaticServe` that touches the module tree, so it lives behind\n * its own function: tests can exercise the resolution (and stub it)\n * without binding a socket.\n */\nexport interface ResolveDistOptions {\n /** Explicit frontend build directory. */\n explicitDistDir?: string | undefined;\n /** Package resolver seam used by tests. */\n resolvePackageJson?: ((id: string) => string) | undefined;\n /** Filesystem seam used by tests. */\n exists?: ((file: string) => boolean) | undefined;\n}\n\n/**\n * Resolve the WebUI dist directory without building it.\n *\n * The string form is retained for callers that provide an explicit frontend\n * directory. The options form exposes package/filesystem seams for the\n * cold-start resolver and its unit tests.\n */\nexport function resolveDistDir(input?: string | ResolveDistOptions): string | null {\n const options: ResolveDistOptions =\n typeof input === 'string' ? { explicitDistDir: input } : (input ?? {});\n if (options.explicitDistDir) return path.resolve(options.explicitDistDir);\n\n const exists = options.exists ?? existsSync;\n\n let packageTarget: string | undefined;\n try {\n packageTarget = options.resolvePackageJson\n ? options.resolvePackageJson('@wrongstack/webui/package.json')\n : findPackageJSON('@wrongstack/webui', import.meta.url);\n } catch {\n if (!options.resolvePackageJson) return null;\n throw new Error(\n '@wrongstack/webui package could not be resolved. Install workspace dependencies and rebuild the CLI.',\n );\n }\n if (!packageTarget) return null;\n\n // Older seams resolved the package's built server entry, while the new seam\n // resolves package.json so discovery still works before the first build.\n const distDir =\n path.basename(packageTarget) === 'package.json'\n ? path.join(path.dirname(packageTarget), 'dist')\n : path.dirname(packageTarget);\n if (options.exists === undefined && options.resolvePackageJson) return distDir;\n return exists(path.join(distDir, 'index.html')) ? distDir : null;\n}\n\n/**\n * Injectable seams for `ensureDistDir`. Both default to the real\n * implementations; tests override them to assert the auto-build path\n * without spawning `pnpm` or walking the real filesystem.\n */\nexport interface EnsureDistDeps extends Omit<ResolveDistOptions, 'explicitDistDir'> {\n /** Build command runner (tests override to no-op or assert cwd). */\n runBuild?: (cwd: string) => void | Promise<void>;\n /** Workspace-root finder (tests return a fake monorepo root). */\n findWorkspaceRoot?: (packageDir: string) => string | null;\n}\n\n/**\n * Resolve the WebUI dist, auto-building it when missing.\n *\n * Mirrors the SimpleUI cold-start recovery in `simpleui-dist.ts`:\n * after a fresh clone, `git clean`, or dependency update the `dist/`\n * directory (gitignored) may not exist. Instead of silently degrading\n * to WS-only, this function runs the Vite build automatically and\n * retries resolution. Explicit missing directories return `null` so\n * callers can intentionally run WS-only; package and build failures\n * throw descriptive errors instead of silently hiding a broken install.\n */\nexport async function ensureDistDir(\n explicitDistDir?: string,\n deps: EnsureDistDeps = {},\n): Promise<string | null> {\n const exists = deps.exists ?? existsSync;\n if (explicitDistDir) {\n const resolved = path.resolve(explicitDistDir);\n return exists(path.join(resolved, 'index.html')) ? resolved : null;\n }\n\n const resolveOptions: ResolveDistOptions = {\n resolvePackageJson: deps.resolvePackageJson,\n exists,\n };\n const resolved = resolveDistDir(resolveOptions);\n if (resolved !== null) return resolved;\n\n // Locate the workspace root to run the pnpm build command.\n let packageDir: string;\n try {\n const packageJson = deps.resolvePackageJson\n ? deps.resolvePackageJson('@wrongstack/webui/package.json')\n : findPackageJSON('@wrongstack/webui', import.meta.url);\n if (!packageJson) throw new Error('not found');\n packageDir = path.dirname(packageJson);\n } catch {\n throw new Error(\n '@wrongstack/webui package could not be resolved. Install workspace dependencies and rebuild the CLI.',\n );\n }\n\n const findRoot =\n deps.findWorkspaceRoot ??\n ((pkgDir: string): string | null => {\n let dir = pkgDir;\n for (let i = 0; i < 10; i++) {\n if (existsSync(path.join(dir, 'pnpm-workspace.yaml'))) return dir;\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n return null; // not in a pnpm workspace \u2014 can't auto-build\n });\n\n const workspaceRoot = findRoot(packageDir);\n if (workspaceRoot === null) {\n throw new Error(`@wrongstack/webui is not inside a pnpm workspace (started at ${packageDir}).`);\n }\n\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'webui.auto_build',\n message: 'Frontend not built \u2014 building now',\n timestamp: new Date().toISOString(),\n }),\n );\n\n const runBuild =\n deps.runBuild ?? ((cwd: string) => runPnpmBuild(cwd, '@wrongstack/webui', 180_000));\n\n try {\n await runBuild(workspaceRoot);\n } catch (error) {\n throw new Error(\n `webui.auto_build.failed: ${error instanceof Error ? error.message : String(error)}. ` +\n 'Run `pnpm --filter @wrongstack/webui build` manually.',\n );\n }\n\n const afterBuild = resolveDistDir(resolveOptions);\n if (afterBuild === null) {\n throw new Error(\n '@wrongstack/webui frontend is not built. Run `pnpm --filter @wrongstack/webui build`.',\n );\n }\n return afterBuild;\n}\n\n/**\n * Injectable seams for `startStaticServe`. Both default to\n * the real implementations; tests override them to assert\n * the wiring without resolving the webui package or binding\n * a real port.\n */\nexport interface StaticServeDeps {\n resolveDist?: (explicitDistDir?: string) => string | null;\n ensureDist?: (\n explicitDistDir?: string,\n deps?: EnsureDistDeps,\n ) => string | null | Promise<string | null>;\n ensureDistDeps?: EnsureDistDeps;\n createServer?: (opts: CreateHttpServerOptions) => Server;\n}\n\nexport async function startStaticServe(\n opts: StaticServeOptions,\n deps: StaticServeDeps = {},\n): Promise<StaticServeHandle | null> {\n const ensureDistDeps = deps.ensureDistDeps ?? opts.ensureDistDeps;\n const ensureDist = (explicit: string | undefined) =>\n deps.ensureDist\n ? deps.ensureDist(explicit, ensureDistDeps)\n : ensureDistDir(explicit, ensureDistDeps);\n const create = deps.createServer ?? createHttpServer;\n\n const distDir = deps.resolveDist\n ? deps.resolveDist(opts.distDir)\n : await ensureDist(opts.distDir);\n if (distDir === null) return null;\n\n const server = create({\n host: opts.host,\n port: opts.httpPort,\n distDir,\n globalRoot: opts.globalRoot,\n onFleetPing: opts.onFleetPing,\n onTechStackEvent: opts.onTechStackEvent,\n getLlm: opts.getLlm,\n projectRoot: opts.projectRoot,\n publicWsUrl: opts.publicWsUrl,\n apiToken: opts.apiToken,\n requireToken: opts.requireToken,\n });\n\n if (!opts.deferListen) {\n server.listen(opts.httpPort, opts.host);\n }\n // `createHttpServer` returns the bound port via\n // `server.address()` after `listen` resolves. We return\n // the requested port instead because the existing\n // call sites pass the requested port straight into\n // the open-browser URL \u2014 the runWebUI body has no\n // use for the bound-port value today. If a future\n // caller needs the actual bound port, this function\n // is the place to expose it (e.g. via a `listening`\n // event).\n return { server, port: opts.httpPort };\n}\n\nfunction runPnpmBuild(cwd: string, workspace: string, timeoutMs: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn('pnpm', ['--filter', workspace, 'build'], {\n cwd,\n shell: process.platform === 'win32',\n stdio: 'inherit',\n windowsHide: true,\n });\n const timer = setTimeout(() => {\n child.kill('SIGKILL');\n reject(new Error(`build timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n timer.unref?.();\n child.once('error', (error) => {\n clearTimeout(timer);\n reject(error);\n });\n child.once('close', (code) => {\n clearTimeout(timer);\n if (code === 0) resolve();\n else reject(new Error(`pnpm build exited with code ${String(code)}`));\n });\n });\n}\n", "import * as path from 'node:path';\nimport {\n registerInstance,\n unregisterInstance,\n type WebUIInstanceRecord,\n} from './instance-registry.js';\nimport { formatExternalAccessUrls } from './network-info.js';\nimport { openBrowser } from './open-browser.js';\nimport type { SurfaceKind } from './port-utils.js';\nimport { buildWebUIAccessUrl } from './ws-utils.js';\n\n/**\n * PR 7 of Issue #30 (webui-server 8-PR refactor): process lifecycle.\n *\n * Three concerns pulled out of the ~3000-line `runWebUI` body:\n *\n * - `registerWebuiInstance` \u2014 record this embedded WebUI in the shared\n * running-instance registry (so `wstack --webui --list` sees it).\n * - `announceWebuiReady` \u2014 log the ready banner and pop the browser\n * once the HTTP server is listening.\n * - `createWebuiShutdown` + `registerWebuiSignalHandlers` \u2014 the\n * SIGINT/SIGTERM teardown sequence.\n *\n * Each external dependency (registry IO, browser launch) is an\n * injectable seam so the orchestration can be unit-tested without\n * touching disk or spawning a browser. Run-loop state (abort\n * controllers, client map, the run promise's `resolve`) stays in\n * `webui-server.ts` and is threaded in as callbacks \u2014 the module never\n * captures it.\n */\n\n// \u2500\u2500 Instance registry \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface RegisterWebuiInstanceParams {\n pid: number;\n /** Surface kind \u2014 'webui' or 'simpleui'. */\n surface: SurfaceKind;\n host: string;\n /** Port serving both HTTP and WebSocket (single-port design). */\n httpPort: number;\n /** Browser-facing public URL when served through a tunnel/proxy. */\n publicUrl?: string | undefined;\n projectRoot: string;\n /** ISO timestamp when the instance registered. */\n startedAt: string;\n /** Registry base dir (dirname of globalConfigPath); undefined \u21D2 registry default. */\n registryBaseDir: string | undefined;\n}\n\nexport interface RegisterWebuiInstanceDeps {\n registerFn?: (record: WebUIInstanceRecord, baseDir?: string) => Promise<void>;\n}\n\n/**\n * Fire-and-forget registration of this WebUI in the running-instance\n * registry. Best-effort: a registry write error never blocks startup and\n * is swallowed (the registry is a convenience index, not a source of\n * truth). Caller guards on `projectRoot` being known.\n */\nexport function registerWebuiInstance(\n p: RegisterWebuiInstanceParams,\n deps: RegisterWebuiInstanceDeps = {},\n): void {\n const register = deps.registerFn ?? registerInstance;\n void register(\n {\n pid: p.pid,\n surface: p.surface,\n httpPort: p.httpPort,\n host: p.host,\n projectRoot: p.projectRoot,\n projectName: path.basename(p.projectRoot) || p.projectRoot,\n startedAt: p.startedAt,\n url: buildWebUIAccessUrl({\n host: p.host,\n port: p.httpPort,\n publicUrl: p.publicUrl,\n }),\n },\n p.registryBaseDir,\n ).catch(() => {});\n}\n\n// \u2500\u2500 Ready banner + open browser \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface AnnounceWebuiReadyParams {\n /** Surface kind \u2014 'webui' or 'simpleui'. */\n surface: SurfaceKind;\n /** The HTTP server (StaticServeHandle.server). */\n server: { on: (event: 'listening', cb: () => void) => void };\n host: string;\n /** Port serving both HTTP and WebSocket. */\n httpPort: number;\n open: boolean;\n /** Auth token for WS connections. Included in the URL so the frontend can exchange it for an HttpOnly cookie via /ws-auth. */\n wsToken?: string;\n /** Browser-facing public URL when served through a tunnel/proxy. */\n publicUrl?: string | undefined;\n log?: (msg: string) => void;\n openBrowserFn?: (url: string) => void;\n}\n\n/**\n * Once the HTTP server is listening, print the ready banner and (if\n * `open`) launch the browser at the served URL.\n */\nexport function announceWebuiReady(p: AnnounceWebuiReadyParams): void {\n const log = p.log ?? ((m: string) => console.log(m));\n const launch = p.openBrowserFn ?? openBrowser;\n // Include the auth token in the URL so the frontend can exchange it for an\n // HttpOnly cookie. Wildcard binds are printed as a local browser URL because\n // http://0.0.0.0 is not navigable.\n const openUrl = buildWebUIAccessUrl({\n host: p.host,\n port: p.httpPort,\n token: p.wsToken,\n publicUrl: p.publicUrl,\n });\n p.server.on('listening', () => {\n const extraUrls = formatExternalAccessUrls({\n bindHost: p.host,\n port: p.httpPort,\n token: p.wsToken,\n publicUrl: p.publicUrl,\n });\n const extraBlock =\n extraUrls.length > 0\n ? `\\n Also reachable on external interfaces:\\n${extraUrls.join('\\n')}\\n`\n : '';\n log(\n `\\n \u25B8 ${p.surface === 'webui' ? 'WebUI' : 'SimpleUI'} ready \u2014 open \\x1b[1m${openUrl}\\x1b[0m in your browser` +\n ` (same agent as this terminal)\\n${extraBlock}`,\n );\n if (p.open) launch(openUrl);\n });\n}\n\n// \u2500\u2500 Graceful shutdown (SIGINT/SIGTERM) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface WebuiShutdownResources {\n /** Abort every in-flight run (legacy single slot + per-socket controllers) and clear them. */\n abortInFlight: () => void;\n /** Run and drop every event-bus unsubscriber. */\n unsubscribeEvents: () => void;\n /** Dispose long-lived handlers, timers, watchers, and project services owned by the host. */\n disposeResources?: (() => void) | undefined;\n /** Close every connected socket and clear the client map. */\n closeClients: () => void;\n /** Close the static HTTP server (no-op when WS-only). */\n closeHttpServer: () => void;\n /** The WebSocket server to stop (its close callback resolves the run promise). */\n wss: { close: (cb?: () => void) => void };\n /** This process's pid \u2014 the registry liveness key. */\n pid: number;\n /** Registry base dir (undefined \u21D2 registry default). */\n registryBaseDir: string | undefined;\n /** Called once teardown settles \u2014 wired to the run promise's `resolve`. */\n onStopped: () => void;\n log?: (msg: string) => void;\n debug?: (msg: string) => void;\n /** Injectable for tests; defaults to the real registry unregister. */\n unregisterFn?: (pid: number, baseDir?: string) => Promise<void>;\n}\n\n/**\n * Build the SIGINT/SIGTERM teardown handler. The returned function is\n * idempotent: the first call runs the teardown, later calls (e.g. a\n * second Ctrl+C, or a signal after another server in the same process\n * already stopped) return immediately.\n *\n * Order matches the original inline handler: abort runs \u2192 unsubscribe\n * events \u2192 close clients \u2192 unregister from the instance registry (async,\n * awaited inside the wss.close callback) \u2192 close HTTP \u2192 close WS \u2192 on\n * close, once the unregister settles, `onStopped()`.\n */\nexport function createWebuiShutdown(res: WebuiShutdownResources): () => void {\n const log = res.log ?? ((m: string) => console.log(m));\n const debug = res.debug ?? ((m: string) => console.debug(m));\n const unregister = res.unregisterFn ?? unregisterInstance;\n let started = false;\n\n return () => {\n if (started) return;\n started = true;\n log('[WebUI] Shutting down...');\n res.abortInFlight();\n res.unsubscribeEvents();\n res.disposeResources?.();\n res.closeClients();\n // Drop ourselves from the running-instance registry; the run promise\n // resolves only after the write settles so callers can safely remove\n // the registry directory once runWebUI's promise resolves.\n const unregistered = unregister(res.pid, res.registryBaseDir).catch((err: unknown) =>\n debug(`[webui-server] unregister failed: ${err}`),\n );\n res.closeHttpServer();\n res.wss.close(() => {\n void unregistered.then(() => {\n log('[WebUI] Server stopped');\n res.onStopped();\n });\n });\n };\n}\n\n/**\n * Register `shutdown` on SIGINT and SIGTERM. The wrapper self-detaches\n * both listeners on first fire (so a server that has already shut down\n * can't re-trigger teardown). Returns an unregister function for tests\n * and clean restarts.\n */\nexport function registerWebuiSignalHandlers(shutdown: () => void): () => void {\n const handler = (): void => {\n process.off('SIGINT', handler);\n process.off('SIGTERM', handler);\n shutdown();\n };\n process.on('SIGINT', handler);\n process.on('SIGTERM', handler);\n return () => {\n process.off('SIGINT', handler);\n process.off('SIGTERM', handler);\n };\n}\n", "/**\n * Network interface discovery for the startup banner.\n *\n * When the server binds to a wildcard address (`0.0.0.0` / `::`), the\n * operator needs to know which external IPs are reachable so they can\n * construct browser URLs for Tailscale/LAN peers without manually\n * running `ip addr` or `ipconfig`.\n *\n * Extracted as a pure function (with an injectable `os.networkInterfaces`\n * seam) so it can be unit-tested without mocking the OS.\n */\nimport * as os from 'node:os';\nimport { isWildcardBind } from './ws-auth.js';\n\nexport interface NetworkAddress {\n /** IPv4 or IPv6 address (no brackets). */\n address: string;\n /** Interface name (e.g. `eth0`, `tailscale0`). */\n interface: string;\n /** Address family \u2014 `'IPv4'` or `'IPv6'`. */\n family: 'IPv4' | 'IPv6';\n /** True when this address belongs to the Tailscale CGNAT / ULA range. */\n tailscale: boolean;\n}\n\n/** Tailscale IPv4 CGNAT prefix: 100.64.0.0/10 (100.64.0.0 \u2013 100.127.255.255). */\nfunction isTailscaleIPv4(addr: string): boolean {\n const parts = addr.split('.');\n if (parts.length !== 4) return false;\n const octet = Number.parseInt(parts[0] ?? '', 10);\n const second = Number.parseInt(parts[1] ?? '', 10);\n return octet === 100 && second >= 64 && second <= 127;\n}\n\n/** Tailscale IPv6 ULA prefix: fd7a:115c:a1e0::/48. */\nfunction isTailscaleIPv6(addr: string): boolean {\n return addr.toLowerCase().startsWith('fd7a:115c:a1e0:');\n}\n\n/**\n * Enumerate all external (non-internal) network addresses on this machine.\n *\n * Returns addresses grouped and sorted:\n * 1. Tailscale addresses first (IPv4 then IPv6)\n * 2. Other external addresses (IPv4 then IPv6)\n *\n * Loopback, link-local, and internal addresses are filtered out.\n *\n * @param getInterfaces \u2014 Injectable seam for testing; defaults to\n * `os.networkInterfaces()`.\n */\nexport function getExternalAddresses(\n getInterfaces: () => NodeJS.Dict<os.NetworkInterfaceInfo[]> = os.networkInterfaces,\n): NetworkAddress[] {\n const interfaces = getInterfaces();\n const result: NetworkAddress[] = [];\n\n for (const [ifName, addrs] of Object.entries(interfaces)) {\n if (!addrs) continue;\n for (const addr of addrs) {\n if (addr.internal) continue;\n const family = addr.family === 'IPv6' ? 'IPv6' : 'IPv4';\n // Skip link-local IPv6 (fe80::) and IPv4 APIPA (169.254.x.x).\n if (family === 'IPv6' && addr.address.toLowerCase().startsWith('fe80:')) continue;\n if (family === 'IPv4' && addr.address.startsWith('169.254.')) continue;\n const tailscale =\n family === 'IPv4' ? isTailscaleIPv4(addr.address) : isTailscaleIPv6(addr.address);\n result.push({ address: addr.address, interface: ifName, family, tailscale });\n }\n }\n\n // Sort: Tailscale first, then other external. Within each group, IPv4 before IPv6.\n result.sort((a, b) => {\n if (a.tailscale !== b.tailscale) return a.tailscale ? -1 : 1;\n if (a.family !== b.family) return a.family === 'IPv4' ? -1 : 1;\n return 0;\n });\n\n return result;\n}\n\n/**\n * Format the extra access-URL lines for a wildcard bind.\n *\n * Returns a list of indented, ready-to-print lines showing the external\n * IPs and their full access URLs (including token). Returns an empty\n * array for non-wildcard binds or when no external addresses are found.\n */\nexport function formatExternalAccessUrls(opts: {\n bindHost: string;\n port: number;\n token?: string | undefined;\n publicUrl?: string | undefined;\n getInterfaces?: () => NodeJS.Dict<os.NetworkInterfaceInfo[]>;\n}): string[] {\n if (!isWildcardBind(opts.bindHost)) return [];\n const addresses = getExternalAddresses(opts.getInterfaces);\n if (addresses.length === 0) return [];\n\n const lines: string[] = [];\n const seen = new Set<string>();\n for (const addr of addresses) {\n const host = addr.family === 'IPv6' ? `[${addr.address}]` : addr.address;\n if (seen.has(host)) continue;\n seen.add(host);\n const label = addr.tailscale ? 'Tailscale' : addr.interface;\n const proto = 'http';\n let url = `${proto}://${host}:${opts.port}`;\n if (opts.token) {\n url += `/?token=${encodeURIComponent(opts.token)}`;\n }\n lines.push(` \u25B8 ${label}: ${url}`);\n }\n return lines;\n}\n", "/**\n * Server-side stream coalescing for WebUI hosts.\n *\n * Coalesces high-volume live events (provider text/thinking deltas, tool\n * progress) before they hit every connected browser tab. The frontend also\n * coalesces per animation frame, but without this layer long streams still\n * create one WebSocket message per provider token/tool progress event.\n *\n * PR 9 of Issue #30: extracted from `webui-server.ts`.\n */\n\nconst STREAM_COALESCE_MS = 16;\nconst STREAM_COALESCE_MAX_CHARS = 8 * 1024;\n\nexport interface StreamCoalescerDeps {\n /** Send a message to every connected client (webui-server's `broadcast`). */\n broadcast: (msg: { type: string; payload: unknown }) => void;\n /** Stamp a payload with the live session id (webui-server's `sessionPayload`). */\n sessionPayload: <T extends Record<string, unknown>>(payload: T) => T & { sessionId: string };\n}\n\nexport interface ToolProgressPayload {\n sessionId?: string | undefined;\n traceId?: string | undefined;\n agentId?: string | undefined;\n agentName?: string | undefined;\n id: string;\n name: string;\n event: {\n type?: string | undefined;\n text?: string | undefined;\n data?: Record<string, unknown> | undefined;\n path?: string | undefined;\n operation?: 'write' | 'edit' | 'delete' | 'rename' | undefined;\n line?: number | undefined;\n endLine?: number | undefined;\n };\n}\n\nexport interface StreamCoalescer {\n queueTextDelta(text: string, sessionId?: string | undefined): void;\n queueThinkingDelta(text: string, sessionId?: string | undefined): void;\n queueToolProgress(payload: ToolProgressPayload): void;\n /** Flush a pending thinking buffer (text deltas interleave with thinking). */\n flushThinkingDelta(): void;\n /** Flush every pending buffer \u2014 call at iteration boundaries and shutdown. */\n flushAllStreamBuffers(): void;\n}\n\nexport function createStreamCoalescer(deps: StreamCoalescerDeps): StreamCoalescer {\n const { broadcast, sessionPayload } = deps;\n\n let textDeltaBuffer = '';\n let textDeltaSessionId: string | undefined;\n let textDeltaTimer: ReturnType<typeof setTimeout> | null = null;\n let thinkingDeltaBuffer = '';\n let thinkingDeltaSessionId: string | undefined;\n let thinkingDeltaTimer: ReturnType<typeof setTimeout> | null = null;\n const toolProgressBuffers = new Map<\n string,\n {\n sessionId?: string | undefined;\n id: string;\n name: string;\n eventType: string;\n text: string;\n timer: ReturnType<typeof setTimeout> | null;\n }\n >();\n\n const flushTextDelta = (): void => {\n if (textDeltaTimer) {\n clearTimeout(textDeltaTimer);\n textDeltaTimer = null;\n }\n if (!textDeltaBuffer) return;\n const text = textDeltaBuffer;\n const sessionId = textDeltaSessionId;\n textDeltaBuffer = '';\n textDeltaSessionId = undefined;\n broadcast({\n type: 'provider.text_delta',\n payload: sessionPayload({ sessionId, text, messageId: 'current' }),\n });\n };\n\n const flushThinkingDelta = (): void => {\n if (thinkingDeltaTimer) {\n clearTimeout(thinkingDeltaTimer);\n thinkingDeltaTimer = null;\n }\n if (!thinkingDeltaBuffer) return;\n const text = thinkingDeltaBuffer;\n const sessionId = thinkingDeltaSessionId;\n thinkingDeltaBuffer = '';\n thinkingDeltaSessionId = undefined;\n broadcast({\n type: 'provider.thinking_delta',\n payload: sessionPayload({ sessionId, text }),\n });\n };\n\n const queueTextDelta = (text: string, sessionId?: string | undefined): void => {\n if (!text) return;\n if (textDeltaBuffer && textDeltaSessionId !== sessionId) {\n flushTextDelta();\n }\n textDeltaSessionId = sessionId;\n textDeltaBuffer += text;\n if (textDeltaBuffer.length >= STREAM_COALESCE_MAX_CHARS) {\n flushTextDelta();\n return;\n }\n if (!textDeltaTimer) {\n textDeltaTimer = setTimeout(flushTextDelta, STREAM_COALESCE_MS);\n textDeltaTimer.unref?.();\n }\n };\n\n const queueThinkingDelta = (text: string, sessionId?: string | undefined): void => {\n if (!text) return;\n if (thinkingDeltaBuffer && thinkingDeltaSessionId !== sessionId) {\n flushThinkingDelta();\n }\n thinkingDeltaSessionId = sessionId;\n thinkingDeltaBuffer += text;\n if (thinkingDeltaBuffer.length >= STREAM_COALESCE_MAX_CHARS) {\n flushThinkingDelta();\n return;\n }\n if (!thinkingDeltaTimer) {\n thinkingDeltaTimer = setTimeout(flushThinkingDelta, STREAM_COALESCE_MS);\n thinkingDeltaTimer.unref?.();\n }\n };\n\n const flushToolProgress = (id: string): void => {\n const buffered = toolProgressBuffers.get(id);\n if (!buffered) return;\n if (buffered.timer) clearTimeout(buffered.timer);\n toolProgressBuffers.delete(id);\n if (!buffered.text) return;\n broadcast({\n type: 'tool.progress',\n payload: sessionPayload({\n sessionId: buffered.sessionId,\n name: buffered.name,\n id: buffered.id,\n event: { type: buffered.eventType, text: buffered.text },\n }),\n });\n };\n\n const flushAllStreamBuffers = (): void => {\n flushTextDelta();\n flushThinkingDelta();\n for (const id of [...toolProgressBuffers.keys()]) flushToolProgress(id);\n };\n\n const queueToolProgress = (payload: ToolProgressPayload): void => {\n const text = payload.event.text;\n if (!text) {\n flushToolProgress(payload.id);\n broadcast({\n type: 'tool.progress',\n payload: sessionPayload(payload as unknown as Record<string, unknown>),\n });\n return;\n }\n\n const eventType = payload.event.type ?? 'progress';\n const existing = toolProgressBuffers.get(payload.id);\n if (existing && existing.sessionId !== payload.sessionId) flushToolProgress(payload.id);\n if (existing && existing.eventType !== eventType) flushToolProgress(payload.id);\n const buffered = toolProgressBuffers.get(payload.id) ?? {\n sessionId: payload.sessionId,\n id: payload.id,\n name: payload.name,\n eventType,\n text: '',\n timer: null,\n };\n buffered.sessionId = payload.sessionId;\n buffered.name = payload.name;\n buffered.text += buffered.text ? `\\n${text}` : text;\n toolProgressBuffers.set(payload.id, buffered);\n\n if (buffered.text.length >= STREAM_COALESCE_MAX_CHARS) {\n flushToolProgress(payload.id);\n return;\n }\n if (!buffered.timer) {\n buffered.timer = setTimeout(() => flushToolProgress(payload.id), STREAM_COALESCE_MS);\n buffered.timer.unref?.();\n }\n };\n\n return {\n queueTextDelta,\n queueThinkingDelta,\n queueToolProgress,\n flushThinkingDelta,\n flushAllStreamBuffers,\n };\n}\n", "import * as crypto from 'node:crypto';\nimport * as path from 'node:path';\nimport {\n getSharedProjectMailbox,\n type RemoteMailbox,\n resolveProjectDir,\n} from '@wrongstack/core/coordination';\nimport { startSessionTelemetryBridge } from '@wrongstack/core/hq';\nimport { wstackGlobalRoot } from '@wrongstack/core/utils';\nimport type { Config } from '@wrongstack/core/types';\nimport type {\n CreateHqPublisherOptions,\n HqClientCapability,\n HqPublisher,\n} from '@wrongstack/core/hq';\nimport type { EventBus } from '@wrongstack/core/kernel';\n\nconst CLIENT_HEARTBEAT_MS = 15_000;\n\nexport interface WebuiHqConnection {\n getPublisher(): HqPublisher | undefined;\n stop(): void;\n}\n\nexport type WebuiHqConnectionOptions = Omit<CreateHqPublisherOptions, 'socketFactory'> & {\n onConnect?: ((publisher: HqPublisher) => void) | undefined;\n};\n\nexport interface WebuiClientPresenceDeps {\n projectRoot: string | undefined;\n appConfig: Config | undefined;\n events: EventBus;\n hqSessionId: string;\n getSessionId: () => string;\n startHqConnection: (options: WebuiHqConnectionOptions) => WebuiHqConnection;\n createCommandHandler?:\n | ((mailbox: RemoteMailbox) => NonNullable<CreateHqPublisherOptions['onCommand']>)\n | undefined;\n}\n\nexport interface WebuiClientPresence {\n register(): Promise<string | null>;\n unregister(): void;\n}\n\nexport function createWebuiClientPresence(deps: WebuiClientPresenceDeps): WebuiClientPresence {\n let clientId: string | null = null;\n let mailbox: RemoteMailbox | undefined;\n let heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n let stopTelemetry: (() => void) | undefined;\n let hqConnection: WebuiHqConnection | undefined;\n\n const register = async (): Promise<string | null> => {\n if (!deps.projectRoot) return null;\n try {\n const projectRoot = deps.projectRoot;\n const projectName = path.basename(projectRoot);\n const nextMailbox = getSharedProjectMailbox(\n resolveProjectDir(projectRoot, wstackGlobalRoot()),\n deps.events,\n () => hqConnection?.getPublisher(),\n );\n mailbox = nextMailbox;\n\n const onCommand = deps.createCommandHandler?.(nextMailbox);\n const capabilities: HqClientCapability[] = [\n 'telemetry.publish',\n 'mailbox.summary',\n 'fleet.summary',\n 'session.summary',\n ];\n if (onCommand) capabilities.push('control.receive');\n\n hqConnection = deps.startHqConnection({\n clientKind: 'webui',\n projectRoot,\n projectName,\n appConfig: deps.appConfig,\n capabilities,\n ...(onCommand ? { onCommand } : {}),\n onConnect: (publisher) => {\n stopTelemetry?.();\n stopTelemetry = startSessionTelemetryBridge({\n publisher,\n events: deps.events,\n sessionId: deps.hqSessionId,\n projectRoot,\n projectName,\n startedAt: new Date().toISOString(),\n });\n },\n });\n\n clientId = `webui@${crypto.randomUUID().slice(0, 8)}`;\n await nextMailbox.registerClient({\n clientId,\n sessionId: deps.getSessionId(),\n name: `WebUI [${projectName}]`,\n source: 'webui',\n pid: process.pid,\n });\n\n heartbeatTimer = setInterval(() => {\n nextMailbox\n .clientHeartbeat({ clientId: clientId!, sessionId: deps.getSessionId() })\n .catch(() => undefined);\n }, CLIENT_HEARTBEAT_MS);\n heartbeatTimer.unref();\n return clientId;\n } catch {\n return null;\n }\n };\n\n const unregister = (): void => {\n if (heartbeatTimer) clearInterval(heartbeatTimer);\n heartbeatTimer = null;\n stopTelemetry?.();\n stopTelemetry = undefined;\n hqConnection?.stop();\n hqConnection = undefined;\n const previousClientId = clientId;\n const previousMailbox = mailbox;\n clientId = null;\n mailbox = undefined;\n if (previousMailbox && previousClientId) {\n void previousMailbox.deregisterClient(previousClientId).catch(() => undefined);\n }\n };\n\n return { register, unregister };\n}\n", "import type { BrainArbiter } from '@wrongstack/core/coordination';\nimport type { BrainAutoRisk, BrainConfigPatch, BrainRuntime } from '@wrongstack/core/execution';\nimport type { WebSocket } from 'ws';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport type { WSServerMessage } from './types.js';\n\n/**\n * PR 5b of Issue #30: Brain WebSocket handlers (`brain.status` /\n * `brain.risk` / `brain.ask`).\n *\n * Extracted from the `runWebUI` switch. The former closure captures \u2014\n * `opts.brainSettings`, `opts.getBrainLog`, and the\n * `opts.brain ?? container.resolve(TOKENS.BrainArbiter)` lookup \u2014 are now\n * fields on `BrainHandlerContext`. The arbiter resolution is passed as a\n * thunk so this module needn't know about the agent container or tokens.\n */\n\n/** A single Brain decision-log entry (newest last). */\nexport interface BrainLogEntry {\n at: number;\n kind: string;\n question: string;\n outcome: string;\n}\n\nexport interface BrainTransportContext {\n send: (ws: WebSocket, message: WSServerMessage) => void;\n}\n\nexport interface BrainHandlerContext extends BrainTransportContext {\n /** Shared autonomy ceiling \u2014 the SAME object `/brain` mutates. */\n brainSettings: { maxAutoRisk: BrainAutoRisk } | undefined;\n /**\n * Live-editable Brain config owner. Powers `brain.config.get/set` and\n * enriches `brain.status`; risk-only hosts may leave it undefined.\n */\n brainRuntime?: BrainRuntime | undefined;\n /** Read the host's rolling Brain decision log, or undefined when not wired. */\n getBrainLog: (() => BrainLogEntry[]) | undefined;\n /** Resolve the active Brain arbiter (host instance, else container-bound), or undefined. */\n resolveArbiter: () => BrainArbiter | undefined;\n /** Read the active session id for brain.ask requests. */\n getSessionId?: (() => string | undefined) | undefined;\n}\n\nfunction sendResult(\n ctx: BrainTransportContext,\n ws: WebSocket,\n success: boolean,\n message: string,\n): void {\n ctx.send(ws, { type: 'key.operation_result', payload: { success, message } });\n}\n\nexport function handleBrainStatus(ctx: BrainHandlerContext, ws: WebSocket): void {\n const snapshot = ctx.brainRuntime?.getSnapshot();\n ctx.send(ws, {\n type: 'brain.status',\n payload: {\n maxAutoRisk: ctx.brainSettings?.maxAutoRisk ?? snapshot?.maxAutoRisk ?? 'medium',\n log: ctx.getBrainLog?.() ?? [],\n // Additive enrichment \u2014 only present when a BrainRuntime is wired.\n ...(snapshot\n ? {\n mode: snapshot.mode,\n poolLabels: snapshot.poolLabels,\n councilLabels: snapshot.councilLabels,\n // Status already lists the seats; without the judge it does not\n // say who breaks their ties \u2014 and the derived judge is exactly\n // the one that can silently be one of those seats.\n judgeLabel: snapshot.judgeLabel,\n // Naming the judge without saying whether it also voted would just\n // move the blind spot one level down.\n judgeIsVoter: snapshot.judgeIsVoter,\n ledgerPath: snapshot.ledger.path,\n }\n : {}),\n },\n });\n}\n\nexport function handleBrainConfigGet(ctx: BrainHandlerContext, ws: WebSocket): void {\n if (!ctx.brainRuntime) {\n sendResult(\n ctx,\n ws,\n false,\n 'Brain config is not editable on this server (no BrainRuntime wired).',\n );\n return;\n }\n ctx.send(ws, {\n type: 'brain.config',\n payload: { config: ctx.brainRuntime.getSnapshot(), persisted: true },\n });\n}\n\nexport async function handleBrainConfigSet(\n ctx: BrainHandlerContext,\n ws: WebSocket,\n payload: unknown,\n): Promise<void> {\n if (!ctx.brainRuntime) {\n sendResult(\n ctx,\n ws,\n false,\n 'Brain config is not editable on this server (no BrainRuntime wired).',\n );\n return;\n }\n const patch = (payload as { patch?: unknown } | undefined)?.patch;\n if (!patch || typeof patch !== 'object' || Array.isArray(patch)) {\n sendResult(ctx, ws, false, 'brain.config.set requires a { patch: {...} } payload.');\n return;\n }\n try {\n // The runtime is the validator: unknown fields / bad values throw\n // BEFORE any live state changes.\n const { persisted } = ctx.brainRuntime.apply(patch as BrainConfigPatch);\n const result = await persisted;\n ctx.send(ws, {\n type: 'brain.config',\n payload: {\n config: ctx.brainRuntime.getSnapshot(),\n persisted: result.ok,\n ...(result.ok ? {} : { error: result.error ?? 'Persist failed.' }),\n },\n });\n // Keep risk-only surfaces (status views, TUI mirrors) in sync.\n handleBrainStatus(ctx, ws);\n } catch (err) {\n ctx.send(ws, {\n type: 'brain.config',\n payload: {\n config: ctx.brainRuntime.getSnapshot(),\n persisted: false,\n error: `Invalid Brain setting: ${toErrorMessage(err)}`,\n },\n });\n }\n}\n\nexport function handleBrainRisk(ctx: BrainHandlerContext, ws: WebSocket, level: string): void {\n const valid = ['off', 'low', 'medium', 'high', 'all'];\n if (!valid.includes(level)) {\n sendResult(ctx, ws, false, `Unknown risk level \"${level}\". Use: ${valid.join(', ')}.`);\n return;\n }\n if (!ctx.brainSettings) {\n sendResult(ctx, ws, false, 'Brain settings are not wired into this server.');\n return;\n }\n ctx.brainSettings.maxAutoRisk = level as BrainAutoRisk;\n ctx.send(ws, {\n type: 'brain.status',\n payload: { maxAutoRisk: ctx.brainSettings.maxAutoRisk, log: ctx.getBrainLog?.() ?? [] },\n });\n}\n\nexport async function handleBrainAsk(\n ctx: BrainHandlerContext,\n ws: WebSocket,\n question: string | undefined,\n): Promise<void> {\n const q = question?.trim();\n if (!q) {\n sendResult(ctx, ws, false, 'Usage: /brain ask <question>');\n return;\n }\n const arbiter = ctx.resolveArbiter();\n if (!arbiter) {\n sendResult(ctx, ws, false, 'No Brain is wired into this server.');\n return;\n }\n try {\n const decision = await arbiter.decide({\n id: `brain-ask-${Date.now().toString(36)}`,\n sessionId: ctx.getSessionId?.(),\n source: 'user',\n question: q,\n risk: 'medium',\n fallback: 'ask_human',\n });\n ctx.send(ws, {\n type: 'brain.answer',\n payload: { sessionId: ctx.getSessionId?.(), question: q, decision },\n });\n } catch (err) {\n sendResult(ctx, ws, false, `Brain consultation failed: ${toErrorMessage(err)}`);\n }\n}\n", "/**\n * KanbanRunMirror \u2014 projects live Goal / SDD runs into `@wrongstack/kanban`\n * boards so the kanban view becomes the unified LIVE surface for both engines.\n *\n * It is fed two ways by any host with the shared EventBus and live handlers:\n * - SDD: subscribe to `sdd.board.snapshot` on the shared bus.\n * - Goal: a callback tap on `GoalWebSocketHandler` (that orchestrator\n * does NOT emit PhaseEventMap on the bus), delivering its `buildState()`.\n *\n * Each run maps to ONE kanban board. Linkage lives in board TAGS (not\n * generatedBy, which `syncBoardFromTaskGraph` overwrites):\n * ['sdd', 'run:<runId>', 'graph:<graphId>'] or ['goal', 'graph:<graphId>']\n *\n * Reconcile per tick is a two-pass, both idempotent:\n * 1. `syncBoardFromTaskGraph` \u2014 structure + status\u2192column + deps + origin-keyed\n * create/update/archive.\n * 2. targeted, diff-guarded `updateTaskAssignment` overlay for the LIVE subset\n * only (running/completed/failed/cancelled/assigned tasks) so the inspector's\n * AgentRunPanel lights up with the real worker + model \u2014 without fabricating\n * phantom assignments or a per-tick event storm.\n */\n\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport { deserializeTaskGraph } from '@wrongstack/core/tasking';\nimport type { SerializedTaskGraph, TaskEdge, TaskNode } from '@wrongstack/core/types';\nimport {\n attachVerificationReport,\n buildVerificationReport,\n createBoard,\n getBoard,\n type KanbanAgentRunStatus,\n type KanbanBoard,\n type KanbanTask,\n listBoards,\n syncBoardFromTaskGraph,\n updateTaskAssignment,\n} from '@wrongstack/kanban';\nimport type { SddBoardSnapshot, SddBoardTask } from '@wrongstack/sdd';\n\ntype Engine = 'sdd' | 'goal';\n\ninterface WSServerMessage {\n type: string;\n payload: unknown;\n}\n\nexport interface KanbanRunMirrorDeps {\n projectRoot: string;\n events?: EventBus | undefined;\n broadcast: (msg: WSServerMessage) => void;\n log?: ((msg: string) => void) | undefined;\n}\n\n/** Loose shape of the Goal `buildState()` projection we consume. */\ninterface GoalState {\n title?: string;\n goal?: string;\n phases?: Array<{\n id: string;\n name?: string;\n tasks?: Array<{\n id: string;\n title: string;\n description?: string;\n status: TaskNode['status'];\n priority: TaskNode['priority'];\n type: TaskNode['type'];\n assignee?: string;\n startedAt?: number;\n completedAt?: number;\n }>;\n }>;\n}\n\nexport interface KanbanRunMirror {\n /** Goal tap \u2014 the handler's `onBoardState(graphId, state)` callback. */\n onGoalState(graphId: string, state: Record<string, unknown>): void;\n /** Bind a runId to a specific board (used by launch-from-board, phase 4). */\n bind(engine: Engine, key: string, boardId: string): void;\n /**\n * One-shot: the NEXT Goal run whose graphId we haven't seen binds to this\n * board instead of creating a new one. Used by launch-from-board \u2014 the graphId\n * is only known after the async build, so we can't `bind()` up front.\n */\n bindGoalNext(boardId: string): void;\n dispose(): void;\n}\n\nconst DEBOUNCE_MS = 300;\n\nexport function createKanbanRunMirror(deps: KanbanRunMirrorDeps): KanbanRunMirror {\n const { projectRoot, events, broadcast } = deps;\n const log = deps.log ?? (() => {});\n\n // engine:key \u2192 boardId (key = runId for sdd, graphId for goal).\n const boards = new Map<string, string>();\n // One-shot board id for the next launched Goal run (graphId unknown yet).\n let pendingGoalBoardId: string | undefined;\n // engine:key \u2192 content stamp of the last projected state (skip-if-unchanged).\n const stamps = new Map<string, string>();\n const pending = new Map<string, () => Promise<void>>();\n const timers = new Map<string, ReturnType<typeof setTimeout>>();\n\n const mapKey = (engine: Engine, key: string) => `${engine}:${key}`;\n\n // Trailing debounce keyed by engine:key \u2014 latest projection wins.\n function schedule(engine: Engine, key: string, run: () => Promise<void>): void {\n const k = mapKey(engine, key);\n pending.set(k, run);\n if (timers.has(k)) return;\n timers.set(\n k,\n setTimeout(() => {\n timers.delete(k);\n const fn = pending.get(k);\n pending.delete(k);\n if (fn) void fn().catch((err) => log(`[KanbanRunMirror] ${k}: ${errMsg(err)}`));\n }, DEBOUNCE_MS),\n );\n }\n\n async function resolveBoardId(\n engine: Engine,\n key: string,\n title: string,\n tags: string[],\n matchTags?: string[],\n ): Promise<string> {\n const k = mapKey(engine, key);\n const existing = boards.get(k);\n if (existing) return existing;\n // Reclaim a board written on a previous mirror lifetime (restart-during-run):\n // scan disk for one carrying every distinguishing tag before minting a new\n // one. Matters more now that Goal fans out to one board PER PHASE \u2014 a\n // restart would otherwise duplicate every phase board.\n if (matchTags?.length) {\n const found = (await listBoards(projectRoot)).find((b) =>\n matchTags.every((t) => b.tags?.includes(t)),\n );\n if (found) {\n boards.set(k, found.id);\n return found.id;\n }\n }\n // Mirror boards reflect an external run whose engine already verifies\n // completions (SDD verify-before-merge / goal gates) \u2014 the kanban\n // completion gate must not re-park mirrored terminal writes in review.\n const board = await createBoard(projectRoot, {\n title,\n tags,\n completionGate: { enforcement: 'off' },\n });\n boards.set(k, board.id);\n return board.id;\n }\n\n // Reconcile one graph (a whole SDD run, or one Goal phase) into the board.\n async function syncGraph(\n boardId: string,\n graph: SerializedTaskGraph,\n engine: Engine,\n tags: string[],\n phaseId?: string,\n ): Promise<KanbanBoard | null> {\n const result = await syncBoardFromTaskGraph(projectRoot, boardId, deserializeTaskGraph(graph), {\n sourceSystem: engine,\n archiveMissingTasks: true,\n includeCompletedTasks: true,\n tags,\n ...(phaseId ? { phaseId } : {}),\n });\n return result?.board ?? null;\n }\n\n // Diff-guarded assignment overlay for the live subset. Returns the final board.\n async function overlayAssignments(\n boardId: string,\n live: Array<{ taskId: string; phaseId?: string; assignment: DesiredAssignment }>,\n fallbackBoard: KanbanBoard | null,\n ): Promise<KanbanBoard | null> {\n if (live.length === 0) return fallbackBoard;\n let board = fallbackBoard ?? (await getBoard(projectRoot, boardId));\n if (!board) return null;\n const byOrigin = new Map<string, KanbanTask>();\n for (const t of board.tasks) {\n if (t.origin?.taskId) byOrigin.set(originKey(t.origin.taskId, t.origin.phaseId), t);\n }\n for (const item of live) {\n const task = byOrigin.get(originKey(item.taskId, item.phaseId));\n if (!task) continue;\n if (assignmentUnchanged(task.assignment, item.assignment)) continue;\n const updated = await updateTaskAssignment(projectRoot, boardId, task.id, item.assignment);\n if (updated) board = updated;\n }\n return board;\n }\n\n async function publish(board: KanbanBoard | null): Promise<void> {\n if (board) {\n broadcast({ type: 'kanban.get', payload: { success: true, data: { board } } });\n }\n broadcast({\n type: 'kanban.list',\n payload: { success: true, data: await listBoards(projectRoot) },\n });\n }\n\n // \u2500\u2500 SDD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Topological dependency columns (waves) map to ONE kanban board PER column\n // when there is more than one \u2014 same multi-board pattern as Goal phases.\n // A single-column / flat graph keeps one board (backward compatible).\n // All boards share `run:<runId>` so the UI groups them; control is run-level.\n async function projectSdd(runId: string, snapshot: SddBoardSnapshot): Promise<void> {\n const k = mapKey('sdd', runId);\n const stamp = sddStamp(snapshot);\n if (stamps.get(k) === stamp) return;\n stamps.set(k, stamp);\n\n const runTitle = snapshot.title || `SDD ${runId}`;\n const columns = snapshot.columns ?? [];\n\n if (columns.length > 1) {\n const shortToTask = new Map(snapshot.tasks.map((t) => [t.shortId, t]));\n for (let i = 0; i < columns.length; i++) {\n const col = columns[i];\n if (!col) continue;\n const phaseId = `wave-${i}`;\n const colTasks = col.taskIds\n .map((sid) => shortToTask.get(sid))\n .filter((t): t is SddBoardTask => Boolean(t));\n if (colTasks.length === 0) continue;\n const tags = [\n 'sdd',\n `run:${runId}`,\n `graph:${snapshot.graphId}`,\n `phase:${phaseId}`,\n `wave:${i}`,\n ];\n const title = `${runTitle} \u2014 ${col.label || `Wave ${i + 1}`}`;\n const boardId = await resolveBoardId('sdd', `${runId}:${phaseId}`, title, tags, [\n `run:${runId}`,\n `phase:${phaseId}`,\n ]);\n const slice: SddBoardSnapshot = {\n ...snapshot,\n title,\n tasks: colTasks,\n // Keep a single column so buildTaskGraphFromSddSnapshot stays faithful\n // without inventing cross-wave edges that live on other boards.\n columns: [col],\n };\n await projectSddSlice(boardId, runId, slice, tags);\n }\n return;\n }\n\n // Flat / single-wave: one board for the whole run.\n const tags = ['sdd', `run:${runId}`, `graph:${snapshot.graphId}`];\n const boardId = await resolveBoardId('sdd', runId, runTitle, tags, [`run:${runId}`]);\n await projectSddSlice(boardId, runId, snapshot, tags);\n }\n\n /** Sync structure + live assignment + verification for one SDD board slice. */\n async function projectSddSlice(\n boardId: string,\n runId: string,\n snapshot: SddBoardSnapshot,\n tags: string[],\n ): Promise<void> {\n const graph = buildTaskGraphFromSddSnapshot(snapshot);\n const board = await syncGraph(boardId, graph, 'sdd', tags);\n\n const live: Array<{ taskId: string; assignment: DesiredAssignment }> = [];\n for (const t of snapshot.tasks) {\n const a = desiredAssignmentFromSdd(t);\n if (a) live.push({ taskId: t.id, assignment: a });\n }\n let final = await overlayAssignments(boardId, live, board);\n\n // Verification flows into the mirrored board: translate the run engine's\n // completion-gate outcome into a minimal KanbanVerificationReport so the\n // WebUI's verification surfaces light up for SDD-mirrored tasks instead of\n // showing \"unverified\". attachVerificationReport is idempotent and never\n // touches task status (sync owns it). Kanban-local fields on mirrored\n // tasks are otherwise NEVER written by sync ticks.\n const withReports = final ?? (await getBoard(projectRoot, boardId));\n if (withReports) {\n const byOrigin = new Map<string, KanbanTask>();\n for (const kt of withReports.tasks) {\n if (kt.origin?.taskId) byOrigin.set(kt.origin.taskId, kt);\n }\n for (const t of snapshot.tasks) {\n if (!t.verificationState) continue;\n const kt = byOrigin.get(t.id);\n if (!kt) continue;\n const verdict = t.verificationState === 'passed' ? 'passed' : 'failed';\n if (kt.verificationReport?.verdict === verdict) continue;\n const attached = await attachVerificationReport(\n projectRoot,\n boardId,\n kt.id,\n buildVerificationReport({\n taskId: kt.id,\n taskTitle: kt.title,\n boardId,\n checks: [\n {\n checkId: `sdd-gate-${t.id}`,\n description: t.verificationCommand\n ? `SDD completion gate: ${t.verificationCommand}`\n : 'SDD completion gate (command / acceptance-criteria verification)',\n type: 'command',\n status: verdict,\n evidence: {\n source: 'sdd-run',\n runId,\n ...(t.verificationDetail ? { detail: t.verificationDetail } : {}),\n },\n ...(verdict === 'failed' && t.verificationDetail\n ? { error: t.verificationDetail }\n : {}),\n },\n ],\n }),\n );\n if (attached) final = attached;\n }\n }\n await publish(final);\n }\n\n // \u2500\u2500 Goal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Phased work spreads across ONE board PER PHASE \u2014 never a single crowded\n // board. All phase boards share a `run:<graphId>` tag (so the frontend groups\n // them under one run) and each carries its own `phase:<phaseId>` tag + a\n // \"<run> \u2014 <phase>\" title. Control (pause/resume/stop, per-task retry/reassign)\n // is run-level, so it works identically from any phase board.\n async function projectGoal(graphId: string, state: GoalState): Promise<void> {\n const k = mapKey('goal', graphId);\n const stamp = goalStamp(state);\n if (stamps.get(k) === stamp) return;\n stamps.set(k, stamp);\n\n const runTitle = state.title || `Goal ${graphId}`;\n const phases = state.phases ?? [];\n\n for (let i = 0; i < phases.length; i++) {\n const phase = phases[i];\n if (!phase) continue;\n const phaseKey = `${graphId}:${phase.id}`;\n const phaseName = phase.name || `Phase ${i + 1}`;\n const tags = ['goal', `run:${graphId}`, `graph:${graphId}`, `phase:${phase.id}`];\n const title = `${runTitle} \u2014 ${phaseName}`;\n // A board-launched run's one-shot binding attaches to the FIRST phase.\n if (i === 0 && !boards.has(mapKey('goal', phaseKey)) && pendingGoalBoardId) {\n boards.set(mapKey('goal', phaseKey), pendingGoalBoardId);\n pendingGoalBoardId = undefined;\n }\n const boardId = await resolveBoardId('goal', phaseKey, title, tags, [\n `graph:${graphId}`,\n `phase:${phase.id}`,\n ]);\n const graph = buildTaskGraphFromGoalPhase(graphId, title, phase);\n const board = await syncGraph(boardId, graph, 'goal', tags, phase.id);\n\n const live: Array<{ taskId: string; phaseId: string; assignment: DesiredAssignment }> = [];\n for (const t of phase.tasks ?? []) {\n const a = desiredAssignmentFromGoal(t);\n if (a) live.push({ taskId: t.id, phaseId: phase.id, assignment: a });\n }\n const final = await overlayAssignments(boardId, live, board);\n await publish(final);\n }\n }\n\n // \u2500\u2500 Wiring \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n let unsub: (() => void) | undefined;\n if (events) {\n const handler = (e: { runId: string; snapshot: SddBoardSnapshot }) => {\n if (!e?.runId || !e.snapshot) return;\n schedule('sdd', e.runId, () => projectSdd(e.runId, e.snapshot));\n };\n unsub = events.on('sdd.board.snapshot', handler as (p: unknown) => void);\n }\n\n return {\n onGoalState(graphId, state) {\n if (!graphId) return;\n schedule('goal', graphId, () => projectGoal(graphId, state as GoalState));\n },\n bind(engine, key, boardId) {\n boards.set(mapKey(engine, key), boardId);\n },\n bindGoalNext(boardId) {\n pendingGoalBoardId = boardId;\n },\n dispose() {\n unsub?.();\n for (const t of timers.values()) clearTimeout(t);\n timers.clear();\n pending.clear();\n },\n };\n}\n\n// \u2500\u2500 Pure normalizers (exported for unit tests) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/** Build a serialized TaskGraph from an SDD board snapshot (faithful; runtime in metadata). */\nexport function buildTaskGraphFromSddSnapshot(snapshot: SddBoardSnapshot): SerializedTaskGraph {\n const shortToId = new Map(snapshot.tasks.map((t) => [t.shortId, t.id]));\n const nodes: TaskNode[] = snapshot.tasks.map((t, i) => ({\n id: t.id,\n title: t.title,\n description: t.description ?? '',\n type: t.type,\n priority: t.priority,\n status: t.status,\n ...(t.agentName ? { assignee: t.agentName } : {}),\n createdAt: i,\n updatedAt: i,\n ...(t.startedAt !== undefined ? { startedAt: t.startedAt } : {}),\n ...(t.completedAt !== undefined ? { completedAt: t.completedAt } : {}),\n metadata: {\n model: t.model,\n provider: t.provider,\n fallbackModels: t.fallbackModels,\n worktreeBranch: t.worktreeBranch,\n retries: t.retries,\n cancelled: t.displayStatus === 'cancelled',\n verificationCommand: t.verificationCommand,\n verificationState: t.verificationState,\n verificationDetail: t.verificationDetail,\n },\n }));\n const edges: TaskEdge[] = [];\n for (const t of snapshot.tasks) {\n for (const dep of t.deps) {\n const from = shortToId.get(dep);\n if (from) edges.push({ id: `${from}->${t.id}`, from, to: t.id, type: 'depends_on' });\n }\n }\n return wrapGraph(\n snapshot.graphId,\n snapshot.specId ?? snapshot.graphId,\n snapshot.title,\n nodes,\n edges,\n );\n}\n\ntype GoalPhase = NonNullable<GoalState['phases']>[number];\n\n/** Build a serialized TaskGraph for one Goal phase (graph.id = RUN graphId; phase scoped via sync phaseId). */\nexport function buildTaskGraphFromGoalPhase(\n graphId: string,\n title: string,\n phase: GoalPhase,\n): SerializedTaskGraph {\n const tasks = phase.tasks ?? [];\n const nodes: TaskNode[] = tasks.map((t, i) => ({\n id: t.id,\n title: t.title,\n description: t.description ?? '',\n type: t.type,\n priority: t.priority,\n status: t.status,\n ...(t.assignee ? { assignee: t.assignee } : {}),\n createdAt: i,\n updatedAt: i,\n ...(t.startedAt !== undefined ? { startedAt: t.startedAt } : {}),\n ...(t.completedAt !== undefined ? { completedAt: t.completedAt } : {}),\n tags: phase.name ? [phase.name] : [],\n }));\n return wrapGraph(graphId, graphId, title, nodes, []);\n}\n\nfunction wrapGraph(\n id: string,\n specId: string,\n title: string,\n nodes: TaskNode[],\n edges: TaskEdge[],\n): SerializedTaskGraph {\n const hasIncoming = new Set(edges.map((e) => e.to));\n const rootNodes = nodes.filter((n) => !hasIncoming.has(n.id)).map((n) => n.id);\n return {\n id,\n specId,\n title,\n nodes,\n edges,\n rootNodes: rootNodes.length ? rootNodes : nodes[0] ? [nodes[0].id] : [],\n createdAt: 0,\n updatedAt: 0,\n };\n}\n\n// \u2500\u2500 Assignment overlay helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ntype DesiredAssignment = Partial<KanbanTask['assignment']> & { status: KanbanAgentRunStatus };\n\nfunction desiredAssignmentFromSdd(t: SddBoardTask): DesiredAssignment | null {\n const status = runStatusFromDisplay(t.displayStatus);\n const isLive = Boolean(t.agentName) || status !== null;\n if (!isLive) return null;\n return {\n ...(t.agentName ? { name: t.agentName } : {}),\n ...(t.provider ? { provider: t.provider } : {}),\n ...(t.model ? { model: t.model } : {}),\n ...(t.fallbackModels?.length ? { fallbackModels: t.fallbackModels } : {}),\n ...(t.retries ? { attempt: t.retries } : {}),\n ...(t.startedAt !== undefined ? { dispatchedAt: new Date(t.startedAt).toISOString() } : {}),\n ...(t.completedAt !== undefined ? { completedAt: new Date(t.completedAt).toISOString() } : {}),\n // Surface the run engine's completion-gate outcome on the assignment.\n ...(t.verificationState === 'failed' && t.verificationDetail\n ? { error: t.verificationDetail }\n : {}),\n ...(t.verificationState === 'passed' ? { lastResult: 'verification passed' } : {}),\n status: status ?? 'assigned',\n };\n}\n\nfunction desiredAssignmentFromGoal(t: {\n status: TaskNode['status'];\n assignee?: string;\n startedAt?: number;\n completedAt?: number;\n}): DesiredAssignment | null {\n const status = runStatusFromCore(t.status);\n const isLive = Boolean(t.assignee) || status !== null;\n if (!isLive) return null;\n return {\n ...(t.assignee ? { name: t.assignee } : {}),\n ...(t.startedAt !== undefined ? { dispatchedAt: new Date(t.startedAt).toISOString() } : {}),\n ...(t.completedAt !== undefined ? { completedAt: new Date(t.completedAt).toISOString() } : {}),\n status: status ?? 'assigned',\n };\n}\n\nfunction runStatusFromDisplay(d: SddBoardTask['displayStatus']): KanbanAgentRunStatus | null {\n if (d === 'in_progress') return 'running';\n if (d === 'completed') return 'completed';\n if (d === 'failed') return 'failed';\n if (d === 'cancelled') return 'cancelled';\n return null;\n}\n\nfunction runStatusFromCore(s: TaskNode['status']): KanbanAgentRunStatus | null {\n if (s === 'in_progress') return 'running';\n if (s === 'completed') return 'completed';\n if (s === 'failed') return 'failed';\n return null;\n}\n\n/** Compare only the scalar fields the mirror sets \u2014 skip a no-op updateTaskAssignment call. */\nfunction assignmentUnchanged(\n current: KanbanTask['assignment'] | undefined,\n desired: DesiredAssignment,\n): boolean {\n if (!current) return false;\n const cur = current as unknown as Record<string, unknown>;\n const des = desired as unknown as Record<string, unknown>;\n for (const k of [\n 'name',\n 'provider',\n 'model',\n 'status',\n 'attempt',\n 'dispatchedAt',\n 'completedAt',\n 'error',\n 'lastResult',\n ]) {\n if (cur[k] !== des[k]) return false;\n }\n const cf = current.fallbackModels ?? [];\n const df = desired.fallbackModels ?? [];\n return cf.length === df.length && cf.every((v, i) => v === df[i]);\n}\n\n// \u2500\u2500 stamps / misc \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction sddStamp(s: SddBoardSnapshot): string {\n return s.tasks\n .map(\n (t) =>\n `${t.id}:${t.displayStatus}:${t.agentName ?? ''}:${t.retries}:${t.model ?? ''}:${t.verificationState ?? ''}:${t.verificationDetail ?? ''}:${t.verificationCommand ?? ''}`,\n )\n .join('|');\n}\n\nfunction goalStamp(state: GoalState): string {\n return (state.phases ?? [])\n .flatMap((p) => (p.tasks ?? []).map((t) => `${t.id}:${t.status}:${t.assignee ?? ''}`))\n .join('|');\n}\n\nfunction originKey(taskId: string, phaseId?: string): string {\n return phaseId ? `${phaseId}:${taskId}` : taskId;\n}\n\nfunction errMsg(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n", "import {\n finalizeTaskCompletion,\n getBoard,\n getKanbanQueueHealth,\n type KanbanBoard,\n type KanbanExecutionRouting,\n type KanbanQueueHealth,\n type KanbanSupervisorConfig,\n type KanbanSupervisorSnapshot,\n listBoards,\n reconcileKanbanBoard,\n recoverStaleTaskAssignments,\n resolveGateEnforcement,\n} from '@wrongstack/kanban';\n\nexport interface KanbanSupervisorDispatchOptions {\n provider?: string | undefined;\n model?: string | undefined;\n fallbackProfile?: string | undefined;\n fallbackModels?: string[] | undefined;\n skills?: string[] | undefined;\n name?: string | undefined;\n /**\n * Free-form task context propagated into the spawned `TaskSpec.context`.\n * The supervisor forwards kanban identity from the board/task snapshot so\n * the tool-runtime boundary gate can resolve the live policy.\n */\n context?:\n | {\n kanban?: { boardId?: string; taskId?: string; projectRoot?: string };\n }\n | undefined;\n onDone?:\n | ((result: {\n status: 'completed' | 'failed';\n result?: string | undefined;\n error?: string | undefined;\n }) => void | Promise<void>)\n | undefined;\n}\n\nexport interface KanbanSupervisorDeps {\n projectRoot: string;\n broadcast: (message: { type: string; payload: unknown }) => void;\n dispatchTask?:\n | ((description: string, opts?: KanbanSupervisorDispatchOptions) => Promise<string>)\n | undefined;\n log?: ((message: string) => void) | undefined;\n}\n\nexport interface KanbanSupervisor {\n getSnapshot(boardId: string): KanbanSupervisorSnapshot | undefined;\n auditNow(boardId?: string): Promise<KanbanSupervisorSnapshot[]>;\n getStats(): {\n snapshots: number;\n scheduledBoards: number;\n agentCooldowns: number;\n runningAgents: number;\n };\n dispose(): void;\n}\n\nconst DEFAULT_INTERVAL_MS = 10_000;\nconst MIN_INTERVAL_MS = 2_000;\nconst DEFAULT_AGENT_COOLDOWN_MS = 5 * 60_000;\n\nconst DEFAULT_CONFIG: KanbanSupervisorConfig = {\n enabled: true,\n mode: 'deterministic',\n intervalMs: DEFAULT_INTERVAL_MS,\n recoveryMode: 'auto',\n};\n\n/**\n * Quiet, project-local board custodian. The frequent pass is deterministic and\n * free; an LLM is spawned only when the board explicitly opts into agentic mode\n * and the health snapshot contains an anomaly.\n */\nexport function createKanbanSupervisor(deps: KanbanSupervisorDeps): KanbanSupervisor {\n const snapshots = new Map<string, KanbanSupervisorSnapshot>();\n const nextDue = new Map<string, number>();\n const agentLastRun = new Map<string, number>();\n const agentRunning = new Set<string>();\n let disposed = false;\n let nextTimer: ReturnType<typeof setTimeout> | undefined;\n\n const forgetBoard = (boardId: string): void => {\n snapshots.delete(boardId);\n nextDue.delete(boardId);\n agentLastRun.delete(boardId);\n agentRunning.delete(boardId);\n };\n\n const pruneAbsentBoards = (presentBoardIds: ReadonlySet<string>): void => {\n for (const boardId of snapshots.keys()) {\n if (!presentBoardIds.has(boardId)) forgetBoard(boardId);\n }\n for (const boardId of nextDue.keys()) {\n if (!presentBoardIds.has(boardId)) forgetBoard(boardId);\n }\n for (const boardId of agentLastRun.keys()) {\n if (!presentBoardIds.has(boardId)) forgetBoard(boardId);\n }\n for (const boardId of agentRunning) {\n if (!presentBoardIds.has(boardId)) forgetBoard(boardId);\n }\n };\n\n const publish = (snapshot: KanbanSupervisorSnapshot) => {\n snapshots.set(snapshot.boardId, snapshot);\n deps.broadcast({\n type: 'kanban.supervisor.status',\n payload: { success: true, data: snapshot },\n });\n };\n\n const auditBoard = async (board: KanbanBoard): Promise<KanbanSupervisorSnapshot> => {\n const config = effectiveConfig(board);\n const auditedAt = new Date().toISOString();\n const intervalMs = Math.max(MIN_INTERVAL_MS, config.intervalMs ?? DEFAULT_INTERVAL_MS);\n const nextAuditAt = new Date(Date.now() + intervalMs).toISOString();\n nextDue.set(board.id, Date.now() + intervalMs);\n\n if (!config.enabled) {\n const snapshot: KanbanSupervisorSnapshot = {\n boardId: board.id,\n status: 'disabled',\n mode: config.mode,\n lastAuditAt: auditedAt,\n nextAuditAt,\n reconciledTaskIds: [],\n staleRecoveredTaskIds: [],\n anomalyCount: 0,\n summary: 'Supervision is disabled for this board.',\n };\n publish(snapshot);\n return snapshot;\n }\n\n const reconciled = await reconcileKanbanBoard(deps.projectRoot, board.id);\n // Completion-gate sweep: catch tasks whose worker marked its assignment\n // completed through a path that never called finalizeTaskCompletion\n // (third-party board writers). They are parked in review by\n // updateTaskAssignment; run the gate so they reach a final state.\n const gateSwept = await sweepGateParkedTasks(deps, reconciled?.board ?? board);\n let health = await getKanbanQueueHealth(deps.projectRoot, { boardId: board.id });\n const recovered = health.staleAssignments.count\n ? await recoverStaleTaskAssignments(deps.projectRoot, board.id, {\n mode: config.recoveryMode ?? 'auto',\n reason: 'Kanban supervisor found an expired worker lease.',\n })\n : null;\n if (recovered) health = await getKanbanQueueHealth(deps.projectRoot, { boardId: board.id });\n\n const anomalyCount = countAnomalies(health);\n const snapshot: KanbanSupervisorSnapshot = {\n boardId: board.id,\n status: anomalyCount > 0 ? 'attention' : 'healthy',\n mode: config.mode,\n lastAuditAt: auditedAt,\n nextAuditAt,\n reconciledTaskIds: reconciled?.tasks.map((task) => task.id) ?? [],\n staleRecoveredTaskIds: recovered?.tasks.map((task) => task.id) ?? [],\n anomalyCount,\n summary: healthSummary(health),\n };\n publish(snapshot);\n\n const changedBoard = recovered?.board ?? gateSwept ?? reconciled?.board;\n if (changedBoard) {\n deps.broadcast({\n type: 'kanban.get',\n payload: { success: true, data: { board: changedBoard } },\n });\n deps.broadcast({\n type: 'kanban.list',\n payload: { success: true, data: await listBoards(deps.projectRoot) },\n });\n }\n\n if (config.mode === 'agentic' && anomalyCount > 0) {\n await maybeRunAgent(board, config, health, snapshot);\n }\n return snapshots.get(board.id) ?? snapshot;\n };\n\n const maybeRunAgent = async (\n board: KanbanBoard,\n config: KanbanSupervisorConfig,\n health: KanbanQueueHealth,\n snapshot: KanbanSupervisorSnapshot,\n ): Promise<void> => {\n if (!deps.dispatchTask || agentRunning.has(board.id)) return;\n const cooldownMs = Math.max(\n MIN_INTERVAL_MS,\n config.agentCooldownMs ?? DEFAULT_AGENT_COOLDOWN_MS,\n );\n if (Date.now() - (agentLastRun.get(board.id) ?? 0) < cooldownMs) return;\n agentRunning.add(board.id);\n agentLastRun.set(board.id, Date.now());\n // Watchdog: if the spawned task crashes or is killed without invoking\n // onDone, clear the lock after a bounded duration so the board isn't\n // permanently blocked from future agentic runs.\n const watchdog = setTimeout(\n () => agentRunning.delete(board.id),\n Math.max(cooldownMs * 2, DEFAULT_AGENT_COOLDOWN_MS * 2),\n );\n watchdog.unref?.();\n publish({\n ...snapshot,\n status: 'running',\n lastAgentRunAt: new Date().toISOString(),\n summary: `Agentic anomaly review started. ${snapshot.summary ?? ''}`.trim(),\n });\n const routing = config.routing ?? { mode: 'session' as const };\n try {\n const spawnSummary = await deps.dispatchTask(buildAuditPrompt(board, health), {\n ...dispatchRoute(routing),\n ...(config.skills?.length ? { skills: config.skills } : {}),\n name: `kanban-supervisor-${board.id.slice(0, 6)}`,\n // Carry the board identity into the spawned TaskSpec.context so the\n // tool-runtime boundary gate (`evaluateToolKanbanBoundary`) can resolve\n // the live board policy instead of failing open. Whole-board agentic\n // runs have no taskId, so only boardId is propagated.\n context: { kanban: { boardId: board.id, projectRoot: deps.projectRoot } },\n onDone: async (result) => {\n clearTimeout(watchdog);\n agentRunning.delete(board.id);\n // A long-running supervisor agent can finish after its board was\n // deleted. Do not resurrect the removed board's snapshot entry.\n if ((await getBoard(deps.projectRoot, board.id)) === null) return;\n const current = snapshots.get(board.id) ?? snapshot;\n publish({\n ...current,\n status:\n result.status === 'failed' ? 'error' : current.anomalyCount ? 'attention' : 'healthy',\n lastAgentRunAt: new Date().toISOString(),\n summary: result.result ?? current.summary,\n ...(result.error ? { error: result.error } : {}),\n });\n },\n });\n const current = snapshots.get(board.id) ?? snapshot;\n publish({ ...current, status: 'running', summary: spawnSummary });\n } catch (error) {\n clearTimeout(watchdog);\n agentRunning.delete(board.id);\n const message = error instanceof Error ? error.message : String(error);\n deps.log?.(`[KanbanSupervisor] ${board.id}: ${message}`);\n publish({ ...snapshot, status: 'error', error: message });\n }\n };\n\n const auditNow = async (boardId?: string): Promise<KanbanSupervisorSnapshot[]> => {\n let boards: KanbanBoard[];\n if (boardId) {\n const board = await getBoard(deps.projectRoot, boardId);\n if (board === null) {\n forgetBoard(boardId);\n boards = [];\n } else {\n boards = [board];\n }\n } else {\n const summaries = await listBoards(deps.projectRoot);\n pruneAbsentBoards(new Set(summaries.map((summary) => summary.id)));\n boards = (\n await Promise.all(summaries.map((summary) => getBoard(deps.projectRoot, summary.id)))\n ).filter((board): board is KanbanBoard => Boolean(board));\n }\n const results: KanbanSupervisorSnapshot[] = [];\n for (const board of boards) results.push(await auditBoard(board));\n scheduleNext();\n return results;\n };\n\n /** Compute the soonest `nextDue` across all boards and schedule the next tick. */\n const scheduleNext = () => {\n if (disposed) return;\n // Clear any timer already armed before overwriting `nextTimer`. Without\n // this, an `auditNow()` call (or a status request that reschedules) that\n // races the background tick chain would orphan the previously-armed timer,\n // which keeps firing as an independent, self-perpetuating chain that\n // `dispose` can no longer see \u2014 one duplicate chain per such call.\n if (nextTimer !== undefined) {\n clearTimeout(nextTimer);\n nextTimer = undefined;\n }\n const now = Date.now();\n let minDue = Infinity;\n for (const due of nextDue.values()) {\n if (due < minDue) minDue = due;\n }\n if (!Number.isFinite(minDue) || minDue <= now) {\n // Either no boards have been seen yet, or a board is already due.\n // Fall back to MIN_INTERVAL_MS to avoid busy-waiting.\n nextTimer = setTimeout(() => void tick(), MIN_INTERVAL_MS);\n nextTimer.unref?.();\n return;\n }\n const delay = Math.min(minDue - now, DEFAULT_INTERVAL_MS);\n if (delay <= 0) {\n nextTimer = setTimeout(() => void tick(), MIN_INTERVAL_MS);\n } else {\n nextTimer = setTimeout(() => void tick(), delay);\n }\n nextTimer.unref?.();\n };\n\n const tick = async () => {\n if (disposed) return;\n try {\n const now = Date.now();\n const summaries = await listBoards(deps.projectRoot);\n pruneAbsentBoards(new Set(summaries.map((summary) => summary.id)));\n for (const summary of summaries) {\n if ((nextDue.get(summary.id) ?? 0) > now) continue;\n const board = await getBoard(deps.projectRoot, summary.id);\n if (board) await auditBoard(board);\n }\n } catch (error) {\n deps.log?.(`[KanbanSupervisor] ${error instanceof Error ? error.message : String(error)}`);\n } finally {\n scheduleNext();\n }\n };\n\n // Initial run \u2014 kick off the first audit cycle.\n void scheduleNext();\n\n return {\n getSnapshot: (boardId) => snapshots.get(boardId),\n auditNow,\n getStats: () => ({\n snapshots: snapshots.size,\n scheduledBoards: nextDue.size,\n agentCooldowns: agentLastRun.size,\n runningAgents: agentRunning.size,\n }),\n dispose() {\n disposed = true;\n if (nextTimer !== undefined) {\n clearTimeout(nextTimer);\n nextTimer = undefined;\n }\n snapshots.clear();\n nextDue.clear();\n agentLastRun.clear();\n agentRunning.clear();\n },\n };\n}\n\nfunction effectiveConfig(board: KanbanBoard): KanbanSupervisorConfig {\n return { ...DEFAULT_CONFIG, ...(board.supervisor ?? {}) };\n}\n\n/**\n * Finalize tasks that a third-party writer completed without calling the gate:\n * assignment says completed, the card is parked in review, and no verification\n * report has been produced yet. Returns the last mutated board, or undefined.\n */\nasync function sweepGateParkedTasks(\n deps: KanbanSupervisorDeps,\n board: KanbanBoard,\n): Promise<KanbanBoard | undefined> {\n if (resolveGateEnforcement(board) === 'off') return undefined;\n const parked = board.tasks.filter(\n (task) =>\n task.status === 'review' &&\n task.assignment?.status === 'completed' &&\n !task.verificationReport,\n );\n let lastBoard: KanbanBoard | undefined;\n for (const task of parked) {\n try {\n const finalized = await finalizeTaskCompletion(deps.projectRoot, board.id, task.id, {\n eventContext: { actor: 'kanban-supervisor' },\n });\n if (finalized) lastBoard = finalized.board;\n } catch (error) {\n deps.log?.(\n `[KanbanSupervisor] completion gate sweep failed for ${task.id}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n return lastBoard;\n}\n\nfunction dispatchRoute(routing: KanbanExecutionRouting): KanbanSupervisorDispatchOptions {\n if (routing.mode === 'session') return {};\n return {\n ...(routing.provider ? { provider: routing.provider } : {}),\n ...(routing.model ? { model: routing.model } : {}),\n ...(routing.fallbackProfile ? { fallbackProfile: routing.fallbackProfile } : {}),\n ...(routing.fallbackModels?.length ? { fallbackModels: routing.fallbackModels } : {}),\n };\n}\n\nfunction countAnomalies(health: KanbanQueueHealth): number {\n return (\n health.staleAssignments.count +\n health.heartbeatDue.count +\n health.counts.failed +\n health.counts.blocked\n );\n}\n\nfunction healthSummary(health: KanbanQueueHealth): string {\n return [\n `${health.counts.running} running`,\n `${health.counts.ready} ready`,\n `${health.counts.review} review`,\n `${health.counts.blocked} blocked`,\n `${health.counts.failed} failed`,\n `${health.staleAssignments.count} stale`,\n `${health.dependencyBlocked.count} dependency-blocked`,\n ].join(' \u00B7 ');\n}\n\nfunction buildAuditPrompt(board: KanbanBoard, health: KanbanQueueHealth): string {\n const taskLines = board.tasks.map(\n (task) =>\n `- ${task.id}: ${task.title} [task=${task.status}; assignment=${task.assignment?.status ?? 'none'}; column=${task.columnId}]`,\n );\n return [\n 'You are the explicitly configured WrongStack Kanban supervisor.',\n 'Audit only this board. Do not implement product tasks.',\n `Board: ${board.title} (${board.id})`,\n `Health: ${healthSummary(health)}`,\n '',\n 'Tasks:',\n ...taskLines,\n '',\n 'Use the kanban tool for corrections. Preserve manual blockers and dependencies.',\n 'Fix only demonstrable status/assignment/column drift, then report every action and remaining anomaly.',\n ].join('\\n');\n}\n", "/**\n * Context-meta seeding for the standalone WebUI server.\n *\n * Phase 1c of the god-module split (issue: God-modules >1500 lines).\n * `startWebUI` in `./index.ts` previously inlined a ~70-line block that\n * mirrored the CLI's `getSettings()` mapping: it reads the persisted\n * `config.json` shape and projects the relevant fields onto `context.meta`\n * so the settings panel, autonomy engine, fallback chain, feature toggles,\n * and Telegram extension state all reflect the persisted config on first\n * connect \u2014 before any `prefs.update` arrives.\n *\n * Pure config \u2192 meta projection. No behaviour change.\n */\n\nimport { FallbackProfileManager } from '@wrongstack/core/agent';\nimport type { Config } from '@wrongstack/core/types';\n\n/**\n * Seed `context.meta` from the loaded config. Mirrors the CLI's\n * `getSettings()` mapping so TUI and WebUI agree. Without this the snapshot\n * is empty and every browser shows localStorage defaults (autonomy \"off\",\n * etc.) regardless of what config.json says.\n *\n * The `context` is typed structurally so this module does not take a\n * dependency on the higher `Context` class \u2014 anything with a writable\n * `meta: Record<string, unknown>` works.\n */\nexport function seedContextMeta(config: Config, context: { meta: Record<string, unknown> }): void {\n const meta = context.meta;\n const autonomyCfg = (config.autonomy ?? {}) as Record<string, unknown>;\n const rawMode = autonomyCfg['defaultMode'];\n meta['autonomy'] = rawMode === 'suggest' || rawMode === 'auto' ? rawMode : 'off';\n meta['autonomyDelayMs'] = (autonomyCfg['autoProceedDelayMs'] as number) ?? 45_000;\n meta['autoProceedMaxIterations'] = (autonomyCfg['autoProceedMaxIterations'] as number) ?? 50;\n meta['yolo'] = (autonomyCfg['yolo'] as boolean) ?? config.yolo ?? false;\n meta['chime'] = (autonomyCfg['chime'] as boolean) ?? false;\n meta['confirmExit'] = autonomyCfg['confirmExit'] !== false;\n meta['fleetChatVerbosity'] = (autonomyCfg['fleetChatVerbosity'] as string) ?? 'off';\n meta['enhanceEnabled'] = (autonomyCfg['enhance'] as boolean) ?? true;\n meta['enhanceDelayMs'] = (autonomyCfg['enhanceDelayMs'] as number) ?? 60_000;\n meta['enhanceLanguage'] = (autonomyCfg['enhanceLanguage'] as string) ?? 'original';\n meta['nextPrediction'] = config.nextPrediction ?? false;\n meta['fallbackModels'] = config.fallbackModels ?? [];\n meta['fallbackProfiles'] = config.fallbackProfiles ?? {};\n meta['favoriteModels'] = config.favoriteModels ?? [];\n meta['favoriteModelsOnly'] = config.favoriteModelsOnly === true;\n meta['modelAvailabilitySchedule'] = config.modelAvailabilitySchedule ?? [];\n meta['modelMatrix'] = config.modelMatrix ?? {};\n meta['fallbackAuto'] = config.fallbackAuto !== false;\n // Display language \u2014 only seeded when the shared config pins one, so an\n // unset config leaves the client's browser-detected/local default intact.\n if (typeof config.uiLocale === 'string' && config.uiLocale) meta['uiLocale'] = config.uiLocale;\n meta['featureMcp'] = config.features?.mcp !== false;\n meta['featurePlugins'] = config.features?.plugins !== false;\n meta['featureMemory'] = config.features?.memory !== false;\n meta['featureSkills'] = config.features?.skills !== false;\n meta['featureModelsRegistry'] = config.features?.modelsRegistry !== false;\n meta['indexOnStart'] = config.indexing?.onSessionStart !== false;\n meta['contextAutoCompact'] = config.context?.autoCompact !== false;\n meta['contextStrategy'] = config.context?.strategy ?? 'hybrid';\n meta['logLevel'] = config.log?.level ?? 'info';\n meta['auditLevel'] = config.session?.auditLevel ?? 'standard';\n meta['maxIterations'] = config.tools?.maxIterations ?? 500;\n meta['contextMode'] = config.context?.mode ?? 'balanced';\n {\n const tsm = config.features?.tokenSavingMode;\n meta['tokenSavingTier'] = typeof tsm === 'string' ? tsm : tsm ? 'medium' : 'off';\n }\n meta['maxConcurrent'] = typeof config.maxConcurrent === 'number' ? config.maxConcurrent : 10;\n meta['titleAnimation'] = autonomyCfg['terminalTitleAnimation'] !== false;\n {\n const mr = (config.modelRuntime ?? {}) as {\n reasoning?: { mode?: string; effort?: string; preserve?: boolean };\n cache?: { ttl?: string };\n };\n meta['reasoningMode'] = mr.reasoning?.mode ?? 'auto';\n meta['reasoningEffort'] = mr.reasoning?.effort ?? 'high';\n meta['reasoningPreserve'] = mr.reasoning?.preserve === true;\n meta['cacheTtl'] = mr.cache?.ttl ?? 'default';\n }\n // Refiner + TUI visual prefs \u2014 parity with the CLI server's seeding so the\n // SettingsPanel shows persisted values on the standalone server too.\n meta['refinerProvider'] = (autonomyCfg['refinerProvider'] as string) ?? '';\n meta['refinerModel'] = (autonomyCfg['refinerModel'] as string) ?? '';\n meta['refinerFallbackProfile'] = (autonomyCfg['refinerFallbackProfile'] as string) ?? '';\n meta['thinkingWord'] = (autonomyCfg['thinkingWord'] as string) ?? 'thinking';\n meta['statuslineMode'] = (autonomyCfg['statuslineMode'] as string) ?? 'detailed';\n meta['animationStyle'] = (autonomyCfg['animationStyle'] as string) ?? 'rainbow';\n meta['showModelReasoning'] = autonomyCfg['showModelReasoning'] !== false;\n // Safety / system prefs\n meta['breakerEnabled'] = config.circuitBreaker?.enabled === true;\n meta['breakerAutoKillResetMs'] = config.circuitBreaker?.autoKillResetMs ?? 60_000;\n {\n // Same precedence as the CLI's deriveFsAccessPair: the canonical\n // features.allowOutsideProjectRoot wins when set, else the legacy\n // tools.restrictToProjectRoot, else unrestricted.\n const featuresAllow = config.features?.allowOutsideProjectRoot;\n const toolsRestrict = config.tools?.restrictToProjectRoot;\n const allow =\n featuresAllow !== undefined\n ? featuresAllow\n : toolsRestrict !== undefined\n ? !toolsRestrict\n : true;\n meta['fsAccess'] = allow ? 'unrestricted' : 'project';\n }\n meta['debugStream'] = config.debugStream === true;\n const hqConfig = (\n config as { hq?: { enabled?: boolean; url?: string; token?: string; rawContent?: boolean } }\n ).hq;\n meta['hqEnabled'] = hqConfig?.enabled === true;\n meta['hqUrl'] = hqConfig?.url ?? '';\n meta['hqToken'] = hqConfig?.token ?? '';\n meta['hqRawContent'] = hqConfig?.rawContent === true;\n\n // Telegram plugin notification settings live under extensions.telegram \u2014\n // same path the CLI's /telegram-settings writes. Seed the meta so the\n // SettingsPanel reflects the persisted config on first connect, before\n // any prefs.update arrives.\n const tgExt = (config.extensions as Record<string, Record<string, unknown>> | undefined)?.[\n 'telegram'\n ];\n meta['tgConfigured'] = typeof tgExt?.['botToken'] === 'string' && tgExt['botToken'].length > 0;\n meta['tgSessionEnd'] = tgExt?.['notifyOnSessionEnd'] === true;\n meta['tgDelegate'] = tgExt?.['notifyOnDelegate'] !== false; // default true\n const tgMs = tgExt?.['longToolThresholdMs'];\n meta['tgLongToolMs'] = typeof tgMs === 'number' ? tgMs : 30_000;\n\n // Chimera (post-session review) \u2014 seed from extensions['wstack-chimera']\n // so the dedicated panel reflects the persisted config on first connect,\n // before any prefs.update arrives. The chimera plugin registers itself with\n // defaultState: 'inactive' \u2014 when there is no extensions.wstack-chimera\n // entry at all the plugin is NOT loaded, so the WebUI must default to\n // disabled to match. Contrast with the chimera-plugin.ts internal default\n // (enabled !== false) which only applies AFTER the plugin is explicitly\n // opted into. See also plugin-manager.ts defaultState.\n const chimeraExt = (config.extensions as Record<string, Record<string, unknown>> | undefined)?.[\n 'wstack-chimera'\n ];\n meta['chimeraEnabled'] = chimeraExt?.['enabled'] === true; // default false (matches defaultState: 'inactive')\n meta['chimeraProvider'] = (chimeraExt?.['provider'] as string) ?? '';\n meta['chimeraModel'] = (chimeraExt?.['model'] as string) ?? '';\n meta['chimeraMaxFiles'] =\n typeof chimeraExt?.['maxFiles'] === 'number' && (chimeraExt['maxFiles'] as number) >= 1\n ? (chimeraExt['maxFiles'] as number)\n : 15;\n const autoFix = chimeraExt?.['autoFix'];\n meta['chimeraAutoFix'] =\n autoFix === 'off' || autoFix === 'ask' || autoFix === 'auto' ? autoFix : 'off';\n\n // Auto-review (mid-session continuous) \u2014 seed from extensions['wstack-auto-review'].\n // Defaults match ResolvedAutoReviewConfig in auto-review-plugin.ts:42\n // (enabled=false; provider/model resolve via fallbackProfile/effective chain).\n const autoReviewExt = (\n config.extensions as Record<string, Record<string, unknown>> | undefined\n )?.['wstack-auto-review'];\n meta['autoReviewEnabled'] = autoReviewExt?.['enabled'] === true; // default false (strict opt-in)\n meta['autoReviewProvider'] = (autoReviewExt?.['provider'] as string) ?? '';\n meta['autoReviewModel'] = (autoReviewExt?.['model'] as string) ?? '';\n meta['autoReviewFallbackProfile'] = (autoReviewExt?.['fallbackProfile'] as string) ?? '';\n meta['autoReviewFallbackModels'] = Array.isArray(autoReviewExt?.['fallbackModels'])\n ? (autoReviewExt?.['fallbackModels'] as string[])\n : [];\n meta['autoReviewDebounceMs'] =\n typeof autoReviewExt?.['debounceMs'] === 'number' &&\n (autoReviewExt['debounceMs'] as number) >= 0\n ? (autoReviewExt['debounceMs'] as number)\n : 15_000;\n meta['autoReviewMaxFilesPerBatch'] =\n typeof autoReviewExt?.['maxFilesPerBatch'] === 'number' &&\n (autoReviewExt['maxFilesPerBatch'] as number) >= 1\n ? (autoReviewExt['maxFilesPerBatch'] as number)\n : 15;\n meta['autoReviewMaxConcurrentReviews'] =\n typeof autoReviewExt?.['maxConcurrentReviews'] === 'number' &&\n (autoReviewExt['maxConcurrentReviews'] as number) >= 1\n ? (autoReviewExt['maxConcurrentReviews'] as number)\n : 2;\n const cascade = autoReviewExt?.['cascadeOn'];\n meta['autoReviewCascadeOn'] = cascade === 'critical' || cascade === 'high' ? cascade : 'off';\n\n // Resolve the effective fallback chain for auto-review via the same\n // FallbackProfileManager the plugin uses (auto-review-plugin.ts:62-69), so\n // the SettingsPanel displays the chain the plugin will actually run with.\n // Inputs: autoReviewExt.fallbackProfile (named profile) OR the session's\n // effective chain via config.fallbackModels + config.fallbackProfiles.\n {\n let resolvedChain: ReadonlyArray<{ providerId: string; model: string }> = [];\n try {\n const mgr = new FallbackProfileManager(config);\n const named = autoReviewExt?.['fallbackProfile'];\n resolvedChain =\n typeof named === 'string' && named.length > 0\n ? mgr.resolve(named)\n : mgr.resolveEffective({ fallbackAuto: true });\n } catch {\n resolvedChain = [];\n }\n meta['autoReviewFallbackModels'] = resolvedChain.map((e) => `${e.providerId}/${e.model}`);\n }\n}\n", "/**\n * Pref-persistence helpers for the standalone WebUI server.\n *\n * Phase 1c of the god-module split (issue: God-modules >1500 lines).\n * `startWebUI` previously inlined four interlocking closures:\n * - `PREF_KEYS` + `prefSnapshot()` \u2014 read the live context.meta subset\n * the settings panel exposes\n * - `updateGlobalConfig()` \u2014 unified read\u2192decrypt\u2192mutate\u2192encrypt\u2192write\n * against config.json, serialized behind a non-poisoning lock\n * - `persistPrefsToConfig()` \u2014 project a prefs.update payload back into\n * config.json so a toggle made in the browser survives restarts\n *\n * All four move here. `updateGlobalConfig` returns the new lock so\n * `startWebUI` can keep its mutable `configWriteLock` reference; the other\n * two take explicit args. No behaviour change \u2014 the mutation ladder,\n * the FEATURE_MAP, and the touch-flags are preserved verbatim.\n */\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { SecretVault } from '@wrongstack/core/types';\nimport { decryptConfigSecrets, encryptConfigSecrets } from '@wrongstack/core/security';\nimport { atomicWrite, backupConfigFile, FORBIDDEN_PROTO_KEYS } from '@wrongstack/core/utils';\n\n/** Pref keys exposed to the settings panel via prefs.get / prefs.updated. */\nexport const PREF_KEYS = [\n 'autonomy',\n 'autonomyDelayMs',\n 'autoProceedMaxIterations',\n 'yolo',\n 'maxIterations',\n 'chime',\n 'confirmExit',\n 'nextPrediction',\n 'enhanceEnabled',\n 'enhanceDelayMs',\n 'enhanceLanguage',\n 'featureMcp',\n 'featurePlugins',\n 'featureMemory',\n 'featureSkills',\n 'featureModelsRegistry',\n 'indexOnStart',\n 'contextAutoCompact',\n 'contextStrategy',\n 'contextMode',\n 'tokenSavingTier',\n 'maxConcurrent',\n 'titleAnimation',\n 'uiLocale',\n 'logLevel',\n 'auditLevel',\n 'hqEnabled',\n 'hqUrl',\n 'hqToken',\n 'hqRawContent',\n 'tgConfigured',\n 'tgSessionEnd',\n 'tgDelegate',\n 'tgLongToolMs',\n 'reasoningMode',\n 'reasoningEffort',\n 'reasoningPreserve',\n 'cacheTtl',\n 'fallbackModels',\n 'fallbackProfiles',\n 'favoriteModels',\n 'favoriteModelsOnly',\n 'modelAvailabilitySchedule',\n 'modelMatrix',\n 'fallbackAuto',\n // Refiner + TUI visual prefs (parity with the CLI's embedded server \u2014\n // these were browser-editable there but rejected as unknown keys here).\n 'refinerProvider',\n 'refinerModel',\n 'refinerFallbackProfile',\n 'thinkingWord',\n 'statuslineMode',\n 'animationStyle',\n 'showModelReasoning',\n // Safety / system prefs (parity with /settings breaker, fs-access, debug-stream).\n 'breakerEnabled',\n 'breakerAutoKillResetMs',\n 'fsAccess',\n 'debugStream',\n // Chimera (post-session) + auto-review (mid-session) settings.\n // Persisted to config.extensions['wstack-chimera'] / ['wstack-auto-review']\n // so the running plugins pick up changes after a session restart.\n 'chimeraEnabled',\n 'chimeraProvider',\n 'chimeraModel',\n 'chimeraMaxFiles',\n 'chimeraAutoFix',\n 'autoReviewEnabled',\n 'autoReviewProvider',\n 'autoReviewModel',\n 'autoReviewFallbackProfile',\n 'autoReviewFallbackModels',\n 'autoReviewDebounceMs',\n 'autoReviewMaxFilesPerBatch',\n 'autoReviewMaxConcurrentReviews',\n 'autoReviewCascadeOn',\n // Display-only toggles (purely visual WebUI prefs, not persisted to config).\n 'groupToolCalls',\n 'showThinkingLogs',\n // Per-plugin enable/disable map (parity with the embedded server).\n 'pluginsEnabled',\n // Fleet chat verbosity: off | full (migrated from streamFleet boolean).\n 'fleetChatVerbosity',\n] as const;\n\nexport interface PrefHelperDeps {\n /** Path to the active profile config; the sole settings mutation target. */\n profileConfigPath: string;\n vault: SecretVault;\n logger: { warn(msg: string): void };\n}\n\n/**\n * Snapshot the pref keys currently present on `contextMeta`. Structural\n * typing on the meta keeps this decoupled from the `Context` class.\n */\nexport function prefSnapshot(contextMeta: Record<string, unknown>): Record<string, unknown> {\n const snapshot: Record<string, unknown> = {};\n for (const k of PREF_KEYS) {\n if (k in contextMeta) snapshot[k] = contextMeta[k];\n }\n return snapshot;\n}\n\n/** Mutable holder for the serialized-config-write lock. The helpers update\n * `lock` in place so callers keep a stable reference across writes (the\n * lock is non-poisoning: a failed write resolves the chain but logs).\n *\n * We use a holder object rather than returning the new lock because\n * TypeScript flattens `Promise<Promise<void>>` into `Promise<void>`,\n * which would make `await helper(...)` yield `void` instead of the new\n * lock value. */\nexport interface ConfigWriteLockHolder {\n lock: Promise<void>;\n}\n\n/**\n * Write the mutated config to a single file path. Handles read/decrypt/mutate/encrypt/write.\n */\nasync function writeGlobalConfigFile(\n filePath: string,\n vault: SecretVault,\n mutate: (config: Record<string, unknown>) => void,\n logger: { warn(msg: string): void },\n errorLabel: string,\n): Promise<void> {\n // Back up the current file before overwriting\n const globalRoot = path.dirname(filePath);\n await backupConfigFile(filePath, { globalRoot });\n let raw: string;\n try {\n raw = await fs.readFile(filePath, 'utf8');\n } catch {\n raw = '{}';\n }\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n logger.warn(`${errorLabel}: refusing to overwrite corrupt config at ${filePath}`);\n return;\n }\n const decrypted = decryptConfigSecrets(parsed, vault) as Record<string, unknown>;\n mutate(decrypted);\n const encrypted = encryptConfigSecrets(decrypted, vault);\n await atomicWrite(filePath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\n}\n\n/**\n * Unified global config mutation: read \u2192 decrypt \u2192 mutate \u2192 encrypt \u2192 write.\n * All config writes MUST go through this helper so encryption is always\n * preserved and writes are serialized behind the holder's `lock`.\n *\n * Mutates `holder.lock` in place to the new (non-poisoning) chain value.\n */\nexport async function updateGlobalConfig(\n deps: PrefHelperDeps,\n holder: ConfigWriteLockHolder,\n mutate: (config: Record<string, unknown>) => void,\n errorLabel: string,\n): Promise<void> {\n const { profileConfigPath, vault, logger } = deps;\n const write = async (): Promise<void> => {\n await writeGlobalConfigFile(profileConfigPath, vault, mutate, logger, errorLabel);\n };\n const next = holder.lock.then(write);\n holder.lock = next.then(\n () => undefined,\n () => undefined,\n );\n try {\n await next;\n } catch (err) {\n logger.warn(\n `${errorLabel}: failed to persist to config: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n\n/**\n * Persist pref changes into the active profile config \u2014 the SAME keys the TUI\n * settings picker writes \u2014 so a toggle made in the browser survives restarts\n * and is visible to the CLI/TUI (and vice versa on next boot). Best-effort\n * and serialized behind the holder's `lock`; failures log but never break\n * the WS reply.\n */\n/** Display-only keys listed in PREF_KEYS for snapshot/get but never persisted. */\nconst DISPLAY_ONLY_KEYS = new Set(['groupToolCalls', 'showThinkingLogs', 'autoReviewFallbackModels']);\n\nexport async function persistPrefsToConfig(\n deps: PrefHelperDeps,\n holder: ConfigWriteLockHolder,\n payload: Record<string, unknown>,\n): Promise<void> {\n // Clone to avoid mutating the caller's payload object.\n payload = { ...payload };\n // Strip display-only keys to avoid a no-op config rewrite cycle.\n for (const k of DISPLAY_ONLY_KEYS) delete payload[k];\n if (Object.keys(payload).length === 0) return;\n\n return updateGlobalConfig(\n deps,\n holder,\n (decrypted) => {\n const autonomyCfg = (decrypted.autonomy as Record<string, unknown>) ?? {};\n let autonomyTouched = false;\n const setAutonomy = (key: string, val: unknown): void => {\n autonomyCfg[key] = val;\n autonomyTouched = true;\n };\n if (\n typeof payload['autonomy'] === 'string' &&\n ['off', 'suggest', 'auto'].includes(payload['autonomy'])\n ) {\n setAutonomy('defaultMode', payload['autonomy']);\n }\n if (typeof payload['autonomyDelayMs'] === 'number')\n setAutonomy('autoProceedDelayMs', payload['autonomyDelayMs']);\n if (typeof payload['autoProceedMaxIterations'] === 'number')\n setAutonomy('autoProceedMaxIterations', payload['autoProceedMaxIterations']);\n if (typeof payload['yolo'] === 'boolean') {\n setAutonomy('yolo', payload['yolo']);\n decrypted.yolo = payload['yolo'];\n }\n if (typeof payload['chime'] === 'boolean') setAutonomy('chime', payload['chime']);\n if (typeof payload['confirmExit'] === 'boolean')\n setAutonomy('confirmExit', payload['confirmExit']);\n if (typeof payload['fleetChatVerbosity'] === 'string')\n setAutonomy('fleetChatVerbosity', payload['fleetChatVerbosity']);\n if (typeof payload['enhanceEnabled'] === 'boolean')\n setAutonomy('enhance', payload['enhanceEnabled']);\n if (typeof payload['enhanceDelayMs'] === 'number')\n setAutonomy('enhanceDelayMs', payload['enhanceDelayMs']);\n if (typeof payload['enhanceLanguage'] === 'string')\n setAutonomy('enhanceLanguage', payload['enhanceLanguage']);\n if (typeof payload['refinerProvider'] === 'string')\n setAutonomy('refinerProvider', payload['refinerProvider']);\n if (typeof payload['refinerModel'] === 'string')\n setAutonomy('refinerModel', payload['refinerModel']);\n if (typeof payload['refinerFallbackProfile'] === 'string')\n setAutonomy('refinerFallbackProfile', payload['refinerFallbackProfile']);\n if (typeof payload['thinkingWord'] === 'string')\n setAutonomy('thinkingWord', payload['thinkingWord']);\n if (typeof payload['statuslineMode'] === 'string')\n setAutonomy('statuslineMode', payload['statuslineMode']);\n if (typeof payload['animationStyle'] === 'string')\n setAutonomy('animationStyle', payload['animationStyle']);\n if (typeof payload['showModelReasoning'] === 'boolean')\n setAutonomy('showModelReasoning', payload['showModelReasoning']);\n if (autonomyTouched) decrypted.autonomy = autonomyCfg;\n\n if (typeof payload['nextPrediction'] === 'boolean')\n decrypted.nextPrediction = payload['nextPrediction'];\n\n // Model switching uses the same serialized/encrypted config boundary.\n if (typeof payload['provider'] === 'string') decrypted.provider = payload['provider'];\n if (typeof payload['model'] === 'string') decrypted.model = payload['model'];\n\n // Display language \u2014 top-level Config.uiLocale (shared across surfaces).\n if (typeof payload['uiLocale'] === 'string') decrypted.uiLocale = payload['uiLocale'];\n\n // Global fallback model chain (top-level config). Read live by the leader's\n // fallback extension each turn (effectiveFallbackChain), so it takes effect\n // without a restart.\n if (Array.isArray(payload['fallbackModels']))\n decrypted.fallbackModels = payload['fallbackModels'];\n if (\n payload['fallbackProfiles'] &&\n typeof payload['fallbackProfiles'] === 'object' &&\n !Array.isArray(payload['fallbackProfiles'])\n ) {\n decrypted.fallbackProfiles = payload['fallbackProfiles'] as Record<string, string[]>;\n }\n if (Array.isArray(payload['favoriteModels']))\n decrypted.favoriteModels = payload['favoriteModels'];\n if (typeof payload['favoriteModelsOnly'] === 'boolean')\n decrypted.favoriteModelsOnly = payload['favoriteModelsOnly'];\n if (Array.isArray(payload['modelAvailabilitySchedule']))\n decrypted.modelAvailabilitySchedule = payload['modelAvailabilitySchedule'];\n if (\n payload['modelMatrix'] &&\n typeof payload['modelMatrix'] === 'object' &&\n !Array.isArray(payload['modelMatrix'])\n ) {\n decrypted.modelMatrix = payload['modelMatrix'] as typeof decrypted.modelMatrix;\n }\n if (typeof payload['fallbackAuto'] === 'boolean')\n decrypted.fallbackAuto = payload['fallbackAuto'];\n\n const FEATURE_MAP: Record<string, string> = {\n featureMcp: 'mcp',\n featurePlugins: 'plugins',\n featureMemory: 'memory',\n featureSkills: 'skills',\n featureModelsRegistry: 'modelsRegistry',\n };\n for (const [prefKey, cfgKey] of Object.entries(FEATURE_MAP)) {\n if (typeof payload[prefKey] === 'boolean') {\n const feats = (decrypted.features as Record<string, unknown>) ?? {};\n feats[cfgKey] = payload[prefKey];\n decrypted.features = feats;\n }\n }\n\n if (\n typeof payload['contextAutoCompact'] === 'boolean' ||\n typeof payload['contextStrategy'] === 'string' ||\n typeof payload['contextMode'] === 'string'\n ) {\n const ctxCfg = (decrypted.context as Record<string, unknown>) ?? {};\n if (typeof payload['contextAutoCompact'] === 'boolean')\n ctxCfg.autoCompact = payload['contextAutoCompact'];\n if (typeof payload['contextStrategy'] === 'string')\n ctxCfg.strategy = payload['contextStrategy'];\n if (typeof payload['contextMode'] === 'string') ctxCfg.mode = payload['contextMode'];\n decrypted.context = ctxCfg;\n }\n if (typeof payload['tokenSavingTier'] === 'string') {\n const featsCfg = (decrypted.features as Record<string, unknown>) ?? {};\n featsCfg.tokenSavingMode = payload['tokenSavingTier'];\n decrypted.features = featsCfg;\n }\n if (typeof payload['maxConcurrent'] === 'number') {\n decrypted.maxConcurrent = payload['maxConcurrent'];\n }\n if (typeof payload['titleAnimation'] === 'boolean') {\n const autoCfg = (decrypted.autonomy as Record<string, unknown>) ?? {};\n autoCfg.terminalTitleAnimation = payload['titleAnimation'];\n decrypted.autonomy = autoCfg;\n }\n if (typeof payload['logLevel'] === 'string') {\n const logCfg = (decrypted.log as Record<string, unknown>) ?? {};\n logCfg.level = payload['logLevel'];\n decrypted.log = logCfg;\n }\n if (typeof payload['auditLevel'] === 'string') {\n const sessionCfg = (decrypted.session as Record<string, unknown>) ?? {};\n sessionCfg.auditLevel = payload['auditLevel'];\n decrypted.session = sessionCfg;\n }\n if (typeof payload['indexOnStart'] === 'boolean') {\n const indexingCfg = (decrypted.indexing as Record<string, unknown>) ?? {};\n indexingCfg.onSessionStart = payload['indexOnStart'];\n decrypted.indexing = indexingCfg;\n }\n if (typeof payload['maxIterations'] === 'number') {\n const toolsCfg = (decrypted.tools as Record<string, unknown>) ?? {};\n toolsCfg.maxIterations = payload['maxIterations'];\n decrypted.tools = toolsCfg;\n }\n\n const hqTouched =\n typeof payload['hqEnabled'] === 'boolean' ||\n typeof payload['hqUrl'] === 'string' ||\n typeof payload['hqToken'] === 'string' ||\n typeof payload['hqRawContent'] === 'boolean';\n if (hqTouched) {\n const hqCfg = (decrypted.hq as Record<string, unknown>) ?? {};\n if (typeof payload['hqEnabled'] === 'boolean') hqCfg.enabled = payload['hqEnabled'];\n if (typeof payload['hqUrl'] === 'string') hqCfg.url = payload['hqUrl'];\n if (typeof payload['hqToken'] === 'string') hqCfg.token = payload['hqToken'];\n if (typeof payload['hqRawContent'] === 'boolean')\n hqCfg.rawContent = payload['hqRawContent'];\n decrypted.hq = hqCfg;\n }\n\n const tgTouched =\n typeof payload['tgSessionEnd'] === 'boolean' ||\n typeof payload['tgDelegate'] === 'boolean' ||\n typeof payload['tgLongToolMs'] === 'number';\n if (tgTouched) {\n const ext = (decrypted.extensions as Record<string, Record<string, unknown>>) ?? {};\n const tg = ext['telegram'] ?? {};\n if (typeof payload['tgSessionEnd'] === 'boolean') {\n tg['notifyOnSessionEnd'] = payload['tgSessionEnd'];\n }\n if (typeof payload['tgDelegate'] === 'boolean') {\n tg['notifyOnDelegate'] = payload['tgDelegate'];\n }\n if (typeof payload['tgLongToolMs'] === 'number') {\n tg['longToolThresholdMs'] = payload['tgLongToolMs'];\n }\n ext['telegram'] = tg;\n decrypted.extensions = ext;\n }\n\n // Reasoning / cache runtime controls \u2192 Config.modelRuntime\n const modelRuntimeTouched =\n typeof payload['reasoningMode'] === 'string' ||\n typeof payload['reasoningEffort'] === 'string' ||\n typeof payload['reasoningPreserve'] === 'boolean' ||\n typeof payload['cacheTtl'] === 'string';\n if (modelRuntimeTouched) {\n const mr = (decrypted.modelRuntime as Record<string, unknown>) ?? {};\n const reasoning = (mr.reasoning as Record<string, unknown>) ?? {};\n if (typeof payload['reasoningMode'] === 'string') reasoning.mode = payload['reasoningMode'];\n if (typeof payload['reasoningEffort'] === 'string')\n reasoning.effort = payload['reasoningEffort'];\n if (typeof payload['reasoningPreserve'] === 'boolean')\n reasoning.preserve = payload['reasoningPreserve'];\n mr.reasoning = reasoning;\n if (typeof payload['cacheTtl'] === 'string' && payload['cacheTtl'] !== 'default') {\n mr.cache = { ttl: payload['cacheTtl'] };\n } else if (payload['cacheTtl'] === 'default') {\n delete mr.cache;\n }\n decrypted.modelRuntime = mr;\n }\n\n // Process circuit breaker \u2192 Config.circuitBreaker\n if (\n typeof payload['breakerEnabled'] === 'boolean' ||\n typeof payload['breakerAutoKillResetMs'] === 'number'\n ) {\n const cb = (decrypted.circuitBreaker as Record<string, unknown>) ?? {};\n if (typeof payload['breakerEnabled'] === 'boolean') cb.enabled = payload['breakerEnabled'];\n if (typeof payload['breakerAutoKillResetMs'] === 'number')\n cb.autoKillResetMs = payload['breakerAutoKillResetMs'];\n decrypted.circuitBreaker = cb;\n }\n\n // Filesystem access scope \u2014 dual-write the inverse pair, same as the\n // CLI's deriveFsAccessPair (tools.restrictToProjectRoot is legacy,\n // features.allowOutsideProjectRoot is canonical; they must stay inverses).\n if (payload['fsAccess'] === 'unrestricted' || payload['fsAccess'] === 'project') {\n const restrict = payload['fsAccess'] === 'project';\n const toolsCfg = (decrypted.tools as Record<string, unknown>) ?? {};\n toolsCfg.restrictToProjectRoot = restrict;\n decrypted.tools = toolsCfg;\n const featsCfg = (decrypted.features as Record<string, unknown>) ?? {};\n featsCfg.allowOutsideProjectRoot = !restrict;\n decrypted.features = featsCfg;\n }\n\n // Raw SSE debug dump \u2192 top-level Config.debugStream\n if (typeof payload['debugStream'] === 'boolean')\n decrypted.debugStream = payload['debugStream'];\n\n // Note: `autoReviewFallbackModels` is intentionally NOT a persisted\n // user-configurable input. It's a *resolved output* computed by the\n // auto-review plugin via FallbackProfileManager (auto-review-plugin.ts:67-69).\n // It's exposed on LocalPrefs for read-only display in the panel; the\n // panel writes the source inputs (`autoReviewFallbackProfile`,\n // `autoReviewProvider`, `autoReviewModel`) and the server seeds the\n // resolved chain from config on next boot.\n\n // Per-plugin enable/disable \u2192 extensions.<name>.enabled. Parity with the\n // embedded server (prefs-seeding.ts) so a browser toggling plugins against\n // the standalone server persists instead of erroring.\n if (typeof payload['pluginsEnabled'] === 'object' && payload['pluginsEnabled'] !== null) {\n const ext = (decrypted.extensions as Record<string, Record<string, unknown>>) ?? {};\n for (const [pluginName, enabled] of Object.entries(\n payload['pluginsEnabled'] as Record<string, boolean>,\n )) {\n // Plugin names are the only attacker-controlled KEYS in this whole\n // ladder (every other ext[...] site is a hardcoded literal). Without\n // this guard, `{\"pluginsEnabled\":{\"__proto__\":true}}` makes\n // `ext['__proto__']` read back Object.prototype, and the next line\n // writes `Object.prototype.enabled = true` \u2014 every object in the\n // process then inherits `.enabled`, silently defeating the\n // `?? true`-style plugin gates. JSON.parse yields `__proto__` as an\n // own enumerable key, so Object.entries hands it to us.\n if (FORBIDDEN_PROTO_KEYS.has(pluginName)) continue;\n const pExt = ext[pluginName] ?? {};\n pExt['enabled'] = enabled;\n ext[pluginName] = pExt;\n }\n decrypted.extensions = ext;\n }\n\n // Chimera (post-session review) \u2192 extensions['wstack-chimera']\n // Matches the ResolvedChimeraConfig shape from chimera-plugin.ts:34.\n const chimeraTouched =\n typeof payload['chimeraEnabled'] === 'boolean' ||\n typeof payload['chimeraProvider'] === 'string' ||\n typeof payload['chimeraModel'] === 'string' ||\n typeof payload['chimeraMaxFiles'] === 'number' ||\n typeof payload['chimeraAutoFix'] === 'string';\n if (chimeraTouched) {\n const ext = (decrypted.extensions as Record<string, Record<string, unknown>>) ?? {};\n const chimera = ext['wstack-chimera'] ?? {};\n if (typeof payload['chimeraEnabled'] === 'boolean')\n chimera['enabled'] = payload['chimeraEnabled'];\n if (typeof payload['chimeraProvider'] === 'string')\n chimera['provider'] = payload['chimeraProvider'];\n if (typeof payload['chimeraModel'] === 'string') chimera['model'] = payload['chimeraModel'];\n if (typeof payload['chimeraMaxFiles'] === 'number' && payload['chimeraMaxFiles'] >= 1) {\n chimera['maxFiles'] = payload['chimeraMaxFiles'];\n }\n if (typeof payload['chimeraAutoFix'] === 'string') {\n if (\n payload['chimeraAutoFix'] === 'off' ||\n payload['chimeraAutoFix'] === 'ask' ||\n payload['chimeraAutoFix'] === 'auto'\n ) {\n chimera['autoFix'] = payload['chimeraAutoFix'];\n }\n }\n ext['wstack-chimera'] = chimera;\n decrypted.extensions = ext;\n }\n\n // Auto-review (mid-session continuous) \u2192 extensions['wstack-auto-review']\n // Matches the ResolvedAutoReviewConfig shape from auto-review-plugin.ts:42.\n const autoReviewTouched =\n typeof payload['autoReviewEnabled'] === 'boolean' ||\n typeof payload['autoReviewProvider'] === 'string' ||\n typeof payload['autoReviewModel'] === 'string' ||\n typeof payload['autoReviewFallbackProfile'] === 'string' ||\n Array.isArray(payload['autoReviewFallbackModels']) ||\n typeof payload['autoReviewDebounceMs'] === 'number' ||\n typeof payload['autoReviewMaxFilesPerBatch'] === 'number' ||\n typeof payload['autoReviewMaxConcurrentReviews'] === 'number' ||\n typeof payload['autoReviewCascadeOn'] === 'string';\n if (autoReviewTouched) {\n const ext = (decrypted.extensions as Record<string, Record<string, unknown>>) ?? {};\n const ar = ext['wstack-auto-review'] ?? {};\n if (typeof payload['autoReviewEnabled'] === 'boolean')\n ar['enabled'] = payload['autoReviewEnabled'];\n if (typeof payload['autoReviewProvider'] === 'string')\n ar['provider'] = payload['autoReviewProvider'];\n if (typeof payload['autoReviewModel'] === 'string')\n ar['model'] = payload['autoReviewModel'];\n if (typeof payload['autoReviewFallbackProfile'] === 'string') {\n // Empty string = clear the named profile (plugin falls back to\n // resolveEffective({ fallbackAuto: true })).\n if (payload['autoReviewFallbackProfile'] === '') {\n delete ar['fallbackProfile'];\n } else {\n ar['fallbackProfile'] = payload['autoReviewFallbackProfile'];\n }\n }\n // Note: `autoReviewFallbackModels` is not a config input \u2014 it's\n // derived from `fallbackProfile` + `config.fallbackModels` by the\n // plugin's resolver. Ignore incoming writes to avoid silently\n // persisting a value that the plugin discards on every load.\n if (\n typeof payload['autoReviewDebounceMs'] === 'number' &&\n payload['autoReviewDebounceMs'] >= 0\n ) {\n ar['debounceMs'] = payload['autoReviewDebounceMs'];\n }\n if (\n typeof payload['autoReviewMaxFilesPerBatch'] === 'number' &&\n payload['autoReviewMaxFilesPerBatch'] >= 1\n ) {\n ar['maxFilesPerBatch'] = payload['autoReviewMaxFilesPerBatch'];\n }\n if (\n typeof payload['autoReviewMaxConcurrentReviews'] === 'number' &&\n payload['autoReviewMaxConcurrentReviews'] >= 1\n ) {\n ar['maxConcurrentReviews'] = payload['autoReviewMaxConcurrentReviews'];\n }\n if (typeof payload['autoReviewCascadeOn'] === 'string') {\n if (\n payload['autoReviewCascadeOn'] === 'off' ||\n payload['autoReviewCascadeOn'] === 'critical' ||\n payload['autoReviewCascadeOn'] === 'high'\n ) {\n ar['cascadeOn'] = payload['autoReviewCascadeOn'];\n }\n }\n ext['wstack-auto-review'] = ar;\n decrypted.extensions = ext;\n }\n },\n 'prefs',\n );\n}\n", "// Prefs WS-message routing \u2014 extracted from packages/webui/src/server/index.ts\n// (issue #31, follow-on to PRs #94\u2013#110). The standalone server owns a richer\n// pref surface than the CLI's embedded ws-handlers/prefs.ts (which only knows\n// about YOLO/autonomy), so this module is a thin dispatch layer \u2014 the actual\n// logic stays in the index.ts closures (getPrefs/updatePrefs) that close over\n// the live boot context (config, context.meta, permissionPolicy, pipelines,\n// autoCompactor, logger). Mirrors the shape of the 11 sibling route handlers\n// already wired through `handleMessage`.\n//\n// Why callback injection (not the CLI's context-object style): the standalone\n// server has ~10 closure-captured dependencies the prefs handler reads (config\n// for feature-flag mutation, pipelines for AutoCompaction add/remove, logger\n// for runtime level, etc.) \u2014 bundling them into a PrefsContext interface\n// would duplicate state already living on index.ts. Two callbacks (one per\n// message type) keeps the contract minimal and avoids drift if any new\n// closure dependency is added.\n\nimport type { WebSocket } from 'ws';\nimport { handlePrefsGet, handlePrefsUpdate, type PrefsHandlerContext } from './prefs-handlers.js';\nimport type { WSClientMessage } from './types.js';\nimport { send } from './ws-utils.js';\n\nexport interface PrefsRouteHandlers {\n /** Respond to the WS client with the current pref snapshot. */\n getPrefs: (ws: WebSocket) => Promise<void>;\n /**\n * Merge the supplied pref payload into context.meta, persist the durable\n * keys to config.json, apply any runtime effects (YOLO toggle, feature-flag\n * mutation, fallback chain update, AutoCompaction pipeline add/remove,\n * logger.level), then broadcast the full current snapshot to all clients.\n */\n updatePrefs: (ws: WebSocket, payload: Record<string, unknown>) => Promise<void>;\n /** Preview/apply canonical defaults in the active profile config. */\n doctorConfig?: ((ws: WebSocket, apply: boolean) => Promise<void>) | undefined;\n}\n\nexport function createPrefsRouteHandlers(\n ctx: PrefsHandlerContext,\n doctorConfig?: PrefsRouteHandlers['doctorConfig'],\n): PrefsRouteHandlers {\n return {\n getPrefs: async (ws) => handlePrefsGet(ctx, ws),\n updatePrefs: async (ws, payload) => handlePrefsUpdate(ctx, ws, payload),\n ...(doctorConfig !== undefined ? { doctorConfig } : {}),\n };\n}\n\n/**\n * Chain-of-responsibility dispatcher for the `prefs.*` WS message family.\n * Returns `true` if the message was handled by this layer (so the caller's\n * chain short-circuits), `false` if it should fall through to the next layer\n * or the residual switch.\n *\n * Owned prefixes:\n * - `prefs.get`\n * - `prefs.update`\n * - `config.doctor`\n *\n * Regression-tested by packages/webui/tests/server/dispatcher-routing.test.ts.\n */\nexport async function handlePrefsRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: PrefsRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'prefs.get': {\n await handlers.getPrefs(ws);\n return true;\n }\n case 'prefs.update': {\n await handlers.updatePrefs(ws, (msg.payload ?? {}) as Record<string, unknown>);\n return true;\n }\n case 'config.doctor': {\n if (!handlers.doctorConfig) {\n send(ws, {\n type: 'config.doctor.result',\n payload: {\n success: false,\n applied: false,\n changed: false,\n changes: [],\n configPath: '',\n backupPath: undefined,\n error: 'config doctor unavailable on this server',\n },\n });\n return true;\n }\n await handlers.doctorConfig(\n ws,\n (msg.payload as { apply?: unknown } | undefined)?.apply === true,\n );\n return true;\n }\n default:\n return false;\n }\n}\n", "/**\n * Process-registry WebSocket handlers for the WebUI server, extracted from the\n * `handleMessage` switch in `index.ts` as part of splitting that file (#31).\n *\n * case 'process.list': return handleProcessList(ws);\n * case 'process.kill': return handleProcessKill(ws, msg.payload);\n * case 'process.killAll': return handleProcessKillAll(ws);\n *\n * Registry failures never escape the handler; they are reported over the\n * socket using the existing protocol envelopes.\n */\n\nimport type { Logger } from '@wrongstack/core/types';\nimport { createCompatibilityTrustBoundary, type TrustBoundary } from '@wrongstack/core/security';\nimport { getProcessRegistry } from '@wrongstack/tools';\nimport type { WebSocket } from 'ws';\nimport { authorizeWebUIAction, type WebUIPrivilegedAction } from './privileged-actions.js';\nimport { validateProcessKillPayload } from './ws-payload-validation.js';\nimport { errMessage, send, sendResult } from './ws-utils.js';\n\n/** Broadcast the tracked-process list; an empty list on any registry failure. */\nexport function handleProcessList(ws: WebSocket): void {\n try {\n const procs = getProcessRegistry().list();\n send(ws, {\n type: 'process.list',\n payload: {\n processes: procs.map((p) => ({\n pid: p.pid,\n command: p.command,\n tool: p.name,\n startedAt: p.startedAt,\n status: p.killed ? ('killed' as const) : ('running' as const),\n protected: p.protected,\n background: p.background,\n })),\n },\n });\n } catch {\n send(ws, { type: 'process.list', payload: { processes: [] } });\n }\n}\n\n/** Kill one tracked PID. Rejects invalid payloads and protected processes. */\nexport async function handleProcessKill(\n ws: WebSocket,\n payload: unknown,\n trustBoundary: TrustBoundary = createCompatibilityTrustBoundary({\n policyId: 'webui-process-compat-v1',\n }),\n logger?: Logger | undefined,\n metadata?: WebUIPrivilegedAction['metadata'] | undefined,\n): Promise<void> {\n const parsed = validateProcessKillPayload(payload);\n if (!parsed.ok) {\n sendResult(ws, false, parsed.message);\n return;\n }\n const { pid } = parsed.value;\n const authorization = await authorizeWebUIAction(\n trustBoundary,\n {\n capability: 'process.terminate',\n subject: { kind: 'process', id: String(pid), attributes: { operation: 'kill' } },\n risk: 'high',\n metadata: { transport: 'websocket', ...(metadata ?? {}) },\n },\n logger,\n );\n if (!authorization.allowed) {\n sendResult(ws, false, `Process termination denied: ${authorization.reason}`);\n return;\n }\n try {\n const proc = getProcessRegistry().get(pid);\n if (proc?.protected) {\n sendResult(ws, false, `Cannot kill protected process (PID ${pid})`);\n return;\n }\n getProcessRegistry().kill(pid);\n sendResult(ws, true, `Killed PID ${pid}`);\n } catch (err) {\n sendResult(ws, false, errMessage(err));\n }\n}\n\n/** Kill every tracked process. */\nexport async function handleProcessKillAll(\n ws: WebSocket,\n trustBoundary: TrustBoundary = createCompatibilityTrustBoundary({\n policyId: 'webui-process-compat-v1',\n }),\n logger?: Logger | undefined,\n metadata?: WebUIPrivilegedAction['metadata'] | undefined,\n): Promise<void> {\n const authorization = await authorizeWebUIAction(\n trustBoundary,\n {\n capability: 'process.terminate-all',\n subject: { kind: 'resource', id: 'tracked-process-registry' },\n risk: 'critical',\n metadata: { transport: 'websocket', ...(metadata ?? {}) },\n },\n logger,\n );\n if (!authorization.allowed) {\n sendResult(ws, false, `Process termination denied: ${authorization.reason}`);\n return;\n }\n try {\n getProcessRegistry().killAll();\n sendResult(ws, true, 'All processes killed');\n } catch (err) {\n sendResult(ws, false, errMessage(err));\n }\n}\n", "import { randomUUID } from 'node:crypto';\nimport type { Logger } from '@wrongstack/core/types';\nimport {\n isTrustDecisionAllowed,\n type TrustBoundary,\n type TrustBoundaryRequest,\n type TrustRisk,\n type TrustSubject,\n} from '@wrongstack/core/security';\n\nexport interface WebUIPrivilegedAction {\n capability: string;\n subject: TrustSubject;\n risk: TrustRisk;\n cwd?: string | undefined;\n sessionId?: string | undefined;\n metadata?: TrustBoundaryRequest['metadata'] | undefined;\n}\n\nexport async function authorizeWebUIAction(\n boundary: TrustBoundary,\n action: WebUIPrivilegedAction,\n logger?: Logger | undefined,\n): Promise<{ allowed: boolean; reason: string; request: TrustBoundaryRequest }> {\n const request: TrustBoundaryRequest = {\n version: 1,\n requestId: randomUUID(),\n actor: {\n kind: 'remote-client',\n ...(action.sessionId ? { sessionId: action.sessionId } : {}),\n },\n surface: 'webui',\n capability: action.capability,\n subject: action.subject,\n risk: action.risk,\n scope: {\n ...(action.cwd ? { cwd: action.cwd } : {}),\n ...(action.sessionId ? { sessionId: action.sessionId } : {}),\n },\n authContext: { method: 'session' },\n ...(action.metadata ? { metadata: action.metadata } : {}),\n };\n const decision = await boundary.evaluate(request);\n logger?.debug?.(\n `[trust-boundary] ${request.capability} ${decision.kind} request=${request.requestId}`,\n );\n return { allowed: isTrustDecisionAllowed(decision), reason: decision.reason, request };\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface ProcessRouteHandlers {\n list: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n kill: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n killAll: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport async function handleProcessRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: ProcessRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'process.list':\n await handlers.list(ws, msg);\n return true;\n case 'process.kill':\n await handlers.kill(ws, msg);\n return true;\n case 'process.killAll':\n await handlers.killAll(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Agent } from '@wrongstack/core/agent';\nimport { TOKENS, type EventBus } from '@wrongstack/core/kernel';\nimport { DefaultSessionStore } from '@wrongstack/core/storage';\nimport type {\n Config,\n MemoryPort,\n ModelsRegistry,\n ModeStore,\n ProviderConfig,\n SessionStore,\n SessionWriter,\n} from '@wrongstack/core/types';\nimport { toErrorMessage, wstackGlobalRoot } from '@wrongstack/core/utils';\nimport { makeProviderFromConfig } from '@wrongstack/providers';\nimport type { WebSocket } from 'ws';\nimport { createConversationOperations } from './conversation-operations.js';\nimport type { ConversationRouteHandlers } from './conversation-routes.js';\nimport type { CustomModeStore } from './custom-context-modes.js';\nimport type { PendingConfirm } from './pending-confirms.js';\nimport { createProjectHandlers } from './project-handlers.js';\nimport type { ProjectRouteHandlers } from './project-routes.js';\nimport { createProviderOperations } from './provider-handlers.js';\nimport { createSessionHandlers } from './session-handlers.js';\nimport type { SessionRouteHandlers } from './session-routes.js';\nimport type { SessionIdentityTarget } from './standalone-session-identity.js';\nimport type { WSServerMessage } from './types.js';\n\nexport interface EmbeddedHostTransport {\n send: (ws: WebSocket, message: WSServerMessage) => void;\n broadcast: (message: WSServerMessage) => void;\n log: (message: string) => void;\n}\n\nexport interface EmbeddedProviderStore {\n load(): Promise<Record<string, ProviderConfig>>;\n save(providers: Record<string, ProviderConfig>): Promise<void>;\n}\n\nexport interface EmbeddedProviderContext extends EmbeddedHostTransport {\n providerStore: EmbeddedProviderStore;\n modelsRegistry: ModelsRegistry | undefined;\n}\n\nexport interface EmbeddedAgentConfigContext extends EmbeddedHostTransport {\n agent: Agent;\n modeStore: ModeStore | undefined;\n buildSessionStart: (overrides?: Record<string, unknown>) => Promise<unknown>;\n loadSavedProviders: () => Promise<Record<string, ProviderConfig>>;\n modelsRegistry?: ModelsRegistry | undefined;\n memoryStore?: MemoryPort | undefined;\n getConfig?: (() => Config | undefined) | undefined;\n onMaxContextResolved?:\n | ((providerId: string, modelId: string, maxContext: number) => void)\n | undefined;\n persistPrefs?: ((payload: Record<string, unknown>) => Promise<void>) | undefined;\n}\n\nexport async function applyEmbeddedModelSwitch(\n ctx: EmbeddedAgentConfigContext,\n providerId: string,\n modelId: string,\n): Promise<void> {\n const agentContext = ctx.agent.ctx;\n await agentContext.runModelTransition(async () => {\n const saved = await ctx.loadSavedProviders();\n const providerConfig = saved[providerId] ?? { type: providerId };\n const nextProvider = makeProviderFromConfig(providerId, providerConfig);\n await ctx.modelsRegistry?.refresh().catch((error) => {\n ctx.log(\n JSON.stringify({\n level: 'warn',\n event: 'models.refresh_failed',\n provider: providerId,\n model: modelId,\n message: toErrorMessage(error),\n timestamp: new Date().toISOString(),\n }),\n );\n });\n const catalogId =\n providerConfig.type && providerConfig.type !== providerId ? providerConfig.type : providerId;\n const resolved = await ctx.modelsRegistry?.getModel(catalogId, modelId).catch(() => undefined);\n const maxContext = resolved?.capabilities.maxContext ?? nextProvider.capabilities.maxContext;\n nextProvider.capabilities.maxContext = maxContext;\n await ctx.persistPrefs?.({ provider: providerId, model: modelId });\n\n agentContext.provider = nextProvider;\n agentContext.model = modelId;\n if (ctx.onMaxContextResolved) ctx.onMaxContextResolved(providerId, modelId, maxContext);\n else {\n if (maxContext > 0) agentContext.meta['effectiveMaxContext'] = maxContext;\n else delete agentContext.meta['effectiveMaxContext'];\n ctx.broadcast({\n type: 'ctx.max_context',\n payload: {\n sessionId: agentContext.session.id,\n providerId,\n modelId,\n maxContext,\n },\n });\n }\n ctx.broadcast({ type: 'session.start', payload: await ctx.buildSessionStart() });\n });\n}\n\nexport function createEmbeddedProviderOperations(ctx: EmbeddedProviderContext) {\n return createProviderOperations({\n providerStore: ctx.providerStore,\n broadcast: ctx.broadcast,\n send: ctx.send,\n modelsRegistry: ctx.modelsRegistry,\n log: ctx.log,\n });\n}\n\nexport interface EmbeddedConversationContext extends EmbeddedHostTransport {\n agent: Agent;\n abortControllers: Map<WebSocket, AbortController>;\n pendingConfirms: Map<string, PendingConfirm>;\n}\n\nexport function createEmbeddedConversationRoutes(\n ctx: EmbeddedConversationContext,\n): ConversationRouteHandlers {\n return createConversationOperations({\n getAgent: () => ctx.agent,\n getSessionId: () => ctx.agent.ctx.session?.id ?? '',\n runControl: {\n begin: (ws) => {\n if (ctx.abortControllers.has(ws)) return undefined;\n const controller = new AbortController();\n ctx.abortControllers.set(ws, controller);\n return controller;\n },\n end: (ws, controller) => {\n if (ctx.abortControllers.get(ws) === controller) ctx.abortControllers.delete(ws);\n },\n abort: (ws) => ctx.abortControllers.get(ws)?.abort(),\n },\n pendingConfirms: ctx.pendingConfirms,\n send: ctx.send,\n notifyAbort: (ws, message) => ctx.send(ws, message),\n busyPhase: 'agent.run',\n busyMessage: 'A run is already in progress. Abort it first.',\n });\n}\n\nexport interface EmbeddedSessionOptions {\n projectRoot?: string | undefined;\n agent: Agent;\n events?: EventBus | undefined;\n session: SessionWriter;\n sessionStore?: SessionStore | undefined;\n sessionsDir?: string | undefined;\n claimSession?:\n | ((sessionId: string, target?: SessionIdentityTarget) => Promise<() => Promise<void>>)\n | undefined;\n onBeforeSessionTodosReplaced?:\n | ((sessionId: string, sessionsDir: string) => void | Promise<void>)\n | undefined;\n onSessionSwapped?:\n | ((sessionId: string, target?: SessionIdentityTarget) => void | Promise<void>)\n | undefined;\n}\n\nexport interface EmbeddedSessionContext extends EmbeddedHostTransport {\n opts: EmbeddedSessionOptions;\n buildSessionStart: (overrides?: Record<string, unknown>) => Promise<unknown>;\n getCustomModeStore: () => Promise<CustomModeStore>;\n /** Abort the in-flight agent run before session.new/resume swaps the session. */\n abortActiveRun?: (() => void) | undefined;\n /** True while an embedded agent run is active. */\n isRunActive?: (() => boolean) | undefined;\n}\n\nfunction sessionStoreFor(opts: EmbeddedSessionOptions): SessionStore {\n const projectRoot = opts.projectRoot ?? opts.agent.ctx.projectRoot;\n return (\n opts.sessionStore ??\n new DefaultSessionStore({ dir: path.join(projectRoot, '.wrongstack', 'sessions'), projectRoot })\n );\n}\n\nexport function createEmbeddedSessionRoutes(ctx: EmbeddedSessionContext): SessionRouteHandlers {\n const { opts } = ctx;\n const actx = opts.agent.ctx;\n const getProjectRoot = () => opts.projectRoot ?? actx.projectRoot;\n return createSessionHandlers({\n config: { model: actx.model ?? '', provider: actx.provider?.id ?? '' },\n getConfig: () => ({ model: actx.model ?? '', provider: actx.provider?.id ?? '' }),\n context: actx,\n events: opts.events,\n listTools: () => opts.agent.tools.list(),\n getCompactor: () => opts.agent.container.resolve(TOKENS.Compactor),\n getCustomModeStore: ctx.getCustomModeStore,\n tokenCounter: actx.tokenCounter,\n getProjectRoot,\n getSession: () => actx.session ?? opts.session,\n getSessionStore: () => sessionStoreFor(opts),\n canSwapSessions: () => opts.sessionStore !== undefined,\n getSessionsDir: () =>\n opts.sessionsDir ?? path.join(getProjectRoot(), '.wrongstack', 'sessions'),\n setSession: (next) => {\n actx.session = next;\n },\n claimSession: opts.claimSession,\n onBeforeSessionTodosReplaced: async (sessionId, sessionsDir) =>\n opts.onBeforeSessionTodosReplaced?.(sessionId, sessionsDir),\n onSessionSwapped: async (sessionId, target) => opts.onSessionSwapped?.(sessionId, target),\n abortActiveRun: ctx.abortActiveRun,\n isRunActive: ctx.isRunActive,\n sessionStartPayload: async (overrides) => (await ctx.buildSessionStart(overrides)) as never,\n sendMessage: ctx.send,\n broadcastMessage: ctx.broadcast,\n });\n}\n\nexport async function broadcastEmbeddedGoalSnapshot(ctx: EmbeddedSessionContext): Promise<void> {\n const projectRoot = ctx.opts.projectRoot ?? ctx.opts.agent.ctx.projectRoot;\n try {\n const raw = await fs.readFile(path.join(projectRoot, '.wrongstack', 'goal.json'), 'utf8');\n ctx.broadcast({ type: 'goal-state.updated', payload: JSON.parse(raw) });\n } catch {\n ctx.broadcast({ type: 'goal-state.updated', payload: null });\n }\n}\n\nexport interface EmbeddedProjectContext extends EmbeddedHostTransport {\n opts: EmbeddedSessionOptions & { globalConfigPath?: string | undefined };\n abortControllers: Map<WebSocket, AbortController>;\n abortLegacyRun: () => void;\n buildSessionStart: (overrides?: Record<string, unknown>) => Promise<unknown>;\n}\n\nexport function createEmbeddedProjectRoutes(ctx: EmbeddedProjectContext): ProjectRouteHandlers {\n const { opts } = ctx;\n const actx = opts.agent.ctx;\n const globalConfigPath = opts.globalConfigPath ?? path.join(wstackGlobalRoot(), 'config.json');\n return createProjectHandlers({\n globalConfigPath,\n wpaths: { globalRoot: path.dirname(globalConfigPath) },\n context: actx,\n tokenCounter: actx.tokenCounter,\n config: { model: actx.model, provider: actx.provider.id },\n getConfig: () => ({ model: actx.model, provider: actx.provider.id }),\n getProjectRoot: () => opts.projectRoot ?? actx.projectRoot,\n getSession: () => actx.session ?? opts.session,\n setProjectRoot: (projectRoot) => {\n opts.projectRoot = projectRoot;\n },\n setWorkingDir: (workingDir) => {\n actx.cwd = workingDir;\n },\n setSession: (session) => {\n opts.session = session;\n actx.session = session;\n },\n setSessionStore: (store) => {\n opts.sessionStore = store;\n },\n abortRunLock: ctx.abortLegacyRun,\n abortAllRuns: () => {\n for (const controller of ctx.abortControllers.values()) controller.abort();\n ctx.abortControllers.clear();\n },\n onBeforeSessionTodosReplaced: async (sessionId, sessionsDir) =>\n opts.onBeforeSessionTodosReplaced?.(sessionId, sessionsDir),\n onSessionSwapped: async (sessionId, target) => opts.onSessionSwapped?.(sessionId, target),\n allowProjectMutations: true,\n sessionStartPayload: ctx.buildSessionStart,\n sendMessage: ctx.send,\n broadcastMessage: ctx.broadcast,\n });\n}\n", "import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Context } from '@wrongstack/core/agent';\nimport { DefaultSessionStore } from '@wrongstack/core/storage';\nimport type { SessionStore, TokenCounter } from '@wrongstack/core/types';\nimport { resolveWstackPaths } from '@wrongstack/core/utils';\nimport type { WebSocket } from 'ws';\nimport { resolveWorkingDirInsideProject } from './path-containment.js';\nimport type { ProjectRouteHandlers } from './project-routes.js';\nimport { loadManifest, touchProjectInManifest } from './projects-manifest.js';\nimport type { SessionIdentityTarget } from './standalone-session-identity.js';\nimport type { ConnectedClient } from './types.js';\nimport {\n validateProjectsAddPayload,\n validateProjectsSelectPayload,\n validateWorkingDirSetPayload,\n} from './ws-payload-validation.js';\nimport { broadcast, errMessage, send, sendResult } from './ws-utils.js';\n\ntype Session = Awaited<ReturnType<SessionStore['create']>>;\ntype OutboundMessage = { type: string; payload: unknown };\n\nexport interface ProjectHandlersContext {\n globalConfigPath: string;\n wpaths: { globalRoot: string };\n clients?: Map<WebSocket, ConnectedClient>;\n sendMessage?: (ws: WebSocket, message: OutboundMessage) => void;\n broadcastMessage?: (message: OutboundMessage) => void;\n context: Context;\n tokenCounter: TokenCounter;\n config: { provider: string; model: string };\n getConfig?: () => { provider: string; model: string };\n getProjectRoot: () => string;\n getSession: () => Session;\n setProjectRoot: (projectRoot: string) => void;\n setWorkingDir: (workingDir: string) => void;\n setSession: (session: Session) => void;\n setSessionStore: (store: DefaultSessionStore) => void;\n setSessionStartedAt?: (startedAt: number) => void;\n abortRunLock: () => void;\n abortAllRuns?: () => void;\n onBeforeSessionTodosReplaced?:\n | ((sessionId: string, sessionsDir: string) => void | Promise<void>)\n | undefined;\n onSessionSwapped?: (sessionId: string, target?: SessionIdentityTarget) => void | Promise<void>;\n allowProjectMutations?: boolean;\n sessionStartPayload: (overrides?: Record<string, unknown>) => Promise<unknown>;\n}\n\nexport function createProjectHandlers(ctx: ProjectHandlersContext): ProjectRouteHandlers {\n const sendTo = (ws: WebSocket, message: OutboundMessage): void => {\n if (ctx.sendMessage) ctx.sendMessage(ws, message);\n else send(ws, message);\n };\n const broadcastToAll = (message: OutboundMessage): void => {\n if (ctx.broadcastMessage) ctx.broadcastMessage(message);\n else broadcast(ctx.clients ?? new Map(), message);\n };\n const result = (ws: WebSocket, success: boolean, message: string): void => {\n if (ctx.sendMessage) {\n sendTo(ws, { type: 'key.operation_result', payload: { success, message } });\n } else {\n sendResult(ws, success, message);\n }\n };\n\n return {\n listProjects: async (ws) => {\n try {\n const manifest = await loadManifest(ctx.globalConfigPath);\n sendTo(ws, { type: 'projects.list', payload: { projects: manifest.projects } });\n } catch (error) {\n sendTo(ws, {\n type: 'projects.list',\n payload: { projects: [], error: errMessage(error) },\n });\n }\n },\n addProject: async (ws, msg) => {\n const parsed = validateProjectsAddPayload(msg.payload);\n if (!parsed.ok) {\n sendTo(ws, {\n type: 'projects.added',\n payload: { name: '', root: '', slug: '', message: parsed.message },\n });\n return;\n }\n if (!ctx.allowProjectMutations) {\n sendTo(ws, {\n type: 'projects.added',\n payload: {\n name: parsed.value.name ?? '',\n root: parsed.value.root,\n slug: '',\n message:\n 'Project registration is disabled in WebUI. Open/register projects from the launcher or desktop shell.',\n },\n });\n return;\n }\n const resolved = path.resolve(parsed.value.root);\n const name = parsed.value.name?.trim() || path.basename(resolved);\n try {\n const stat = await fs.stat(resolved).catch(() => null);\n if (!stat?.isDirectory()) {\n sendTo(ws, {\n type: 'projects.added',\n payload: { name, root: resolved, slug: '', message: `Not a directory: ${resolved}` },\n });\n return;\n }\n const before = await loadManifest(ctx.globalConfigPath);\n const already = before.projects.some((project) => path.resolve(project.root) === resolved);\n const entry = await touchProjectInManifest(\n { projectRoot: resolved, workingDir: resolved, name },\n ctx.globalConfigPath,\n );\n sendTo(ws, {\n type: 'projects.added',\n payload: {\n name: entry.name,\n root: entry.root,\n slug: entry.slug,\n message: already\n ? `Already registered project \"${entry.name}\"`\n : `Registered project \"${entry.name}\"`,\n },\n });\n } catch (error) {\n sendTo(ws, {\n type: 'projects.added',\n payload: { name, root: resolved, slug: '', message: errMessage(error) },\n });\n }\n },\n selectProject: async (ws, msg) => {\n const parsed = validateProjectsSelectPayload(msg.payload);\n if (!parsed.ok) {\n sendTo(ws, {\n type: 'projects.selected',\n payload: { root: '', name: '', message: parsed.message },\n });\n return;\n }\n const resolved = path.resolve(parsed.value.root);\n const name = parsed.value.name?.trim() || path.basename(resolved);\n if (!ctx.allowProjectMutations) {\n sendTo(ws, {\n type: 'projects.selected',\n payload: {\n root: resolved,\n name,\n message:\n 'Project switching is disabled in WebUI. Open a project from the launcher or desktop shell instead.',\n },\n });\n return;\n }\n try {\n const stat = await fs.stat(resolved).catch(() => null);\n if (!stat?.isDirectory()) {\n sendTo(ws, {\n type: 'projects.selected',\n payload: {\n root: resolved,\n name,\n message: `Cannot switch: not a directory: ${resolved}`,\n },\n });\n return;\n }\n const paths = resolveWstackPaths({\n projectRoot: resolved,\n globalRoot: ctx.wpaths.globalRoot,\n });\n const store = new DefaultSessionStore({\n dir: paths.projectSessions,\n projectRoot: resolved,\n });\n const previous = ctx.getSession();\n const previousId = previous.id;\n const previousProjectRoot = ctx.getProjectRoot();\n const previousPaths = resolveWstackPaths({\n projectRoot: previousProjectRoot,\n globalRoot: ctx.wpaths.globalRoot,\n });\n const previousIdentityTarget: SessionIdentityTarget = {\n projectSlug: previousPaths.projectSlug,\n projectRoot: previousProjectRoot,\n projectName: path.basename(previousProjectRoot),\n workingDir: ctx.context.workingDir,\n };\n const previousUsage = ctx.tokenCounter.total();\n const config = ctx.getConfig?.() ?? ctx.config;\n const next = await store.create({\n id: '',\n title: '',\n model: config.model,\n provider: config.provider,\n });\n\n try {\n ctx.abortRunLock();\n ctx.abortAllRuns?.();\n } catch {\n // Best-effort cancellation must not strand the fresh writer.\n }\n await touchProjectInManifest(\n { projectRoot: resolved, workingDir: resolved, name },\n ctx.globalConfigPath,\n );\n const identityTarget: SessionIdentityTarget = {\n projectSlug: paths.projectSlug,\n projectRoot: resolved,\n projectName: name,\n workingDir: resolved,\n };\n try {\n await ctx.onSessionSwapped?.(next.id, identityTarget);\n await ctx.onBeforeSessionTodosReplaced?.(next.id, paths.projectSessions);\n } catch (err) {\n try {\n await ctx.onBeforeSessionTodosReplaced?.(previous.id, previousPaths.projectSessions);\n } catch {\n // Best-effort rollback must continue restoring identity and disposing the fresh writer.\n }\n try {\n await ctx.onSessionSwapped?.(previous.id, previousIdentityTarget);\n } catch {\n // Best-effort rollback must still dispose the fresh writer.\n }\n await next.close().catch(() => undefined);\n await store.delete(next.id).catch(() => undefined);\n throw err;\n }\n ctx.setProjectRoot(resolved);\n ctx.setWorkingDir(resolved);\n ctx.setSessionStore(store);\n ctx.setSession(next);\n ctx.context.projectRoot = resolved;\n ctx.context.cwd = resolved;\n ctx.context.workingDir = resolved;\n ctx.context.session = next;\n ctx.context.state.replaceMessages([]);\n ctx.context.state.replaceTodos([]);\n ctx.context.readFiles.clear();\n ctx.context.fileMtimes.clear();\n ctx.tokenCounter.reset();\n\n if (previous !== next) {\n await previous\n .append({ type: 'session_end', ts: new Date().toISOString(), usage: previousUsage })\n .catch(() => undefined);\n await previous.close().catch(() => undefined);\n }\n ctx.setSessionStartedAt?.(Date.now());\n sendTo(ws, {\n type: 'projects.selected',\n payload: { root: resolved, name, message: `Switched to ${name}` },\n });\n broadcastToAll({\n type: 'session.start',\n payload: await ctx.sessionStartPayload({ reset: true, clearedSessionId: previousId }),\n });\n } catch (error) {\n sendTo(ws, {\n type: 'projects.selected',\n payload: { root: resolved, name, message: `Cannot switch: ${errMessage(error)}` },\n });\n }\n },\n setWorkingDir: async (ws, msg) => {\n const parsed = validateWorkingDirSetPayload(msg.payload);\n if (!parsed.ok) {\n result(ws, false, parsed.message);\n return;\n }\n try {\n const projectRoot = ctx.getProjectRoot();\n const resolved = await resolveWorkingDirInsideProject(projectRoot, parsed.value.path);\n ctx.setWorkingDir(resolved);\n ctx.context.cwd = resolved;\n broadcastToAll({ type: 'working_dir.changed', payload: { cwd: resolved, projectRoot } });\n result(ws, true, `Working directory set to ${resolved}`);\n } catch (error) {\n result(ws, false, errMessage(error));\n }\n },\n };\n}\n", "import { resolveProviderModelList } from '@wrongstack/core/models';\nimport { DefaultSecretScrubber } from '@wrongstack/core/security';\nimport type { ModelsRegistry, ProviderConfig } from '@wrongstack/core/types';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport {\n beginOAuthLogin,\n type OAuthKind,\n type OAuthLoginOutcome,\n type OAuthSession,\n} from '@wrongstack/providers/oauth';\nimport { probeLocalLlm } from '@wrongstack/runtime/probe';\nimport type { WebSocket } from 'ws';\nimport {\n resolveProviderCatalogForModels,\n resolveProviderModelMetadata,\n SIBLING_CATALOG,\n} from './model-catalog.js';\nimport { searchCatalogModels } from './model-catalog-search.js';\nimport { loadSavedProviders, saveProviders } from './provider-config-io.js';\nimport {\n addProvider as addProviderRecord,\n deleteKey as deleteKeyRecord,\n maskedKey,\n normalizeKeys,\n removeProvider as removeProviderRecord,\n setActiveKey as setActiveKeyRecord,\n upsertKey as upsertKeyRecord,\n writeKeysBack,\n} from './provider-keys.js';\nimport type { ConnectedClient, WSServerMessage } from './types.js';\nimport { errMessage, send as sendToSocket } from './ws-utils.js';\n\n/**\n * Wire shape of one saved provider as broadcast over `providers.saved`.\n * The WebUI's `<ProviderModelsPanel>` consumes this \u2014 when\n * `pickedModelId` / `models` is missing, the panel renders the empty\n * state.\n */\nexport interface SavedProviderView {\n id: string;\n family?: string | undefined;\n baseUrl?: string | undefined;\n /** Saved model allowlist, verbatim (undefined / [] both possible). */\n models?: string[] | undefined;\n /** Per-model metadata (display name, output limits, capability overrides). */\n customModels?: ProviderConfig['customModels'] | undefined;\n /** First entry of `models`, or undefined when the list is empty/unset. */\n pickedModelId?: string | undefined;\n apiKeys: Array<{\n label: string;\n maskedKey: string;\n isActive: boolean;\n createdAt: string;\n }>;\n}\n\n/**\n * Canonical projection from in-memory `ProviderConfig` to the\n * `providers.saved` wire shape. Pure (no I/O) so it's unit-tested in\n * isolation \u2014 see `tests/server/provider-handlers-projection.test.ts`.\n *\n * Secrets never leave: every key is run through `maskedKey` before it\n * reaches the wire.\n */\nexport function projectSavedProviders(\n providers: Record<string, ProviderConfig>,\n): SavedProviderView[] {\n return Object.entries(providers).map(([id, cfg]) => {\n const keys = normalizeKeys(cfg);\n const models = cfg.models;\n const view: SavedProviderView = {\n id,\n family: cfg.family ?? id,\n baseUrl: cfg.baseUrl,\n models,\n customModels: cfg.customModels,\n apiKeys: keys.map((k) => ({\n label: k.label,\n maskedKey: maskedKey(k.apiKey),\n isActive: k.label === cfg.activeKey,\n createdAt: k.createdAt,\n })),\n };\n const picked = models && models.length > 0 ? models[0] : undefined;\n if (picked !== undefined) view.pickedModelId = picked;\n return view;\n });\n}\n\n/** Shared scrubber for probe error/body redaction. */\nconst probeScrubber = new DefaultSecretScrubber();\n\n/**\n * Probe a saved provider's OpenAI-compatible `/v1/models` and map the\n * discovered ids into the minimal model-descriptor shape the WebUI dropdown\n * needs. Used as a fallback when a config-only custom provider (no saved\n * `models` allowlist, absent from models.dev) would otherwise resolve to an\n * empty list. Returns `[]` on any failure \u2014 the caller treats that as \"no\n * models\" (unchanged behaviour).\n */\nexport async function probeModelDescriptors(\n cfg: ProviderConfig,\n): Promise<Array<{ id: string; name: string; capabilities: [] }>> {\n if (!cfg.baseUrl) return [];\n try {\n const keys = normalizeKeys(cfg);\n const active = keys.find((k) => k.label === cfg.activeKey) ?? keys[0];\n const result = await probeLocalLlm({\n baseUrl: cfg.baseUrl,\n apiKey: active?.apiKey,\n noAuth: false,\n scrubber: probeScrubber,\n });\n if (!result.ok || !result.modelIds) return [];\n return result.modelIds.map((id) => ({ id, name: id, capabilities: [] as [] }));\n } catch {\n return [];\n }\n}\n\nexport interface ProviderHandlerDeps {\n /** Path to the active profile config; the only provider mutation target. */\n profileConfigPath: string;\n vault: import('@wrongstack/core/types').SecretVault;\n /** Shared config write lock \u2014 serialized via chained promises */\n setConfigWriteLock: (lock: Promise<void>) => void;\n getConfigWriteLock: () => Promise<void>;\n /** Broadcast a message to all connected WebUI clients */\n broadcast: (clients: Map<WebSocket, ConnectedClient>, msg: WSServerMessage) => void;\n /** Connected WebUI clients map */\n clients: Map<WebSocket, ConnectedClient>;\n /** Used by the ChatGPT OAuth flow's tier-2 model lookup (best-effort). */\n modelsRegistry?: ModelsRegistry | undefined;\n hasActiveModel?: (() => boolean) | undefined;\n onProvidersLoaded?:\n | ((providers: Record<string, ProviderConfig>) => void | Promise<void>)\n | undefined;\n applyModelSwitch?: ((providerId: string, modelId: string) => Promise<void>) | undefined;\n}\n\nexport interface ProviderPersistence {\n load(): Promise<Record<string, ProviderConfig>>;\n save(providers: Record<string, ProviderConfig>): Promise<void>;\n}\n\nexport interface ProviderOperationsDeps {\n providerStore: ProviderPersistence;\n broadcast: (message: WSServerMessage) => void;\n send?: ((ws: WebSocket, message: WSServerMessage) => void) | undefined;\n modelsRegistry?: ModelsRegistry | undefined;\n log?: ((message: string) => void) | undefined;\n hasActiveModel?: (() => boolean) | undefined;\n onProvidersLoaded?:\n | ((providers: Record<string, ProviderConfig>) => void | Promise<void>)\n | undefined;\n applyModelSwitch?: ((providerId: string, modelId: string) => Promise<void>) | undefined;\n}\n\nexport function createProviderOperations(deps: ProviderOperationsDeps) {\n const sendMessage = deps.send ?? sendToSocket;\n const sendOperationResult = (ws: WebSocket, success: boolean, message: string): void =>\n sendMessage(ws, { type: 'key.operation_result', payload: { success, message } });\n\n async function loadConfigProviders(): Promise<Record<string, ProviderConfig>> {\n return deps.providerStore.load();\n }\n\n async function saveConfigProviders(providers: Record<string, ProviderConfig>): Promise<void> {\n await deps.providerStore.save(providers);\n }\n\n async function handleProvidersList(ws: WebSocket): Promise<void> {\n if (!deps.modelsRegistry) {\n sendOperationResult(ws, false, 'Models registry not available');\n return;\n }\n try {\n const providers = await deps.modelsRegistry.listProviders();\n const savedIds = new Set(Object.keys(await loadConfigProviders()));\n sendMessage(ws, {\n type: 'provider.catalog',\n payload: {\n providers: providers.map((provider) => ({\n id: provider.id,\n name: provider.name,\n family: provider.family,\n apiBase: provider.apiBase,\n envVars: provider.envVars,\n modelCount: provider.models.length,\n hasApiKey:\n savedIds.has(provider.id) || provider.envVars.some((name) => !!process.env[name]),\n })),\n },\n });\n } catch (error) {\n sendOperationResult(ws, false, errMessage(error));\n }\n }\n\n async function handleProvidersSaved(ws: WebSocket): Promise<void> {\n try {\n sendMessage(ws, {\n type: 'providers.saved',\n payload: { providers: projectSavedProviders(await loadConfigProviders()) },\n });\n } catch (error) {\n sendOperationResult(ws, false, errMessage(error));\n }\n }\n\n async function handleProviderModelsSearch(\n ws: WebSocket,\n query: string,\n limit?: number | undefined,\n ): Promise<void> {\n if (!deps.modelsRegistry) {\n sendOperationResult(ws, false, 'Models registry not available');\n return;\n }\n try {\n const matches = await searchCatalogModels(deps.modelsRegistry, query, limit);\n sendMessage(ws, {\n type: 'provider.models.search_result',\n payload: { query, matches },\n });\n } catch (error) {\n sendOperationResult(ws, false, errMessage(error));\n }\n }\n\n async function handleProviderModels(ws: WebSocket, providerId: string): Promise<void> {\n if (!deps.modelsRegistry) {\n sendOperationResult(ws, false, 'Models registry not available');\n return;\n }\n try {\n const saved = await loadConfigProviders();\n const config = saved[providerId];\n const provider = await resolveProviderCatalogForModels(\n deps.modelsRegistry,\n providerId,\n config,\n );\n const siblingId = SIBLING_CATALOG[providerId];\n const sibling =\n siblingId && siblingId !== providerId\n ? await deps.modelsRegistry.getProvider(siblingId).catch(() => undefined)\n : undefined;\n let models = resolveProviderModelList(\n config?.models,\n provider,\n config?.type ?? providerId,\n sibling,\n );\n if (models.length === 0 && config?.baseUrl) models = await probeModelDescriptors(config);\n const enriched = await Promise.all(\n models.map(async (model) => {\n if (model.contextWindow && model.capabilities.length > 0) return model;\n const resolved = await resolveProviderModelMetadata(\n deps.modelsRegistry as ModelsRegistry,\n providerId,\n model.id,\n config,\n ).catch(() => undefined);\n if (!resolved) return model;\n const capabilities = new Set(model.capabilities);\n if (resolved.capabilities.tools) capabilities.add('tools');\n if (resolved.capabilities.reasoning) capabilities.add('reasoning');\n if (resolved.capabilities.vision) capabilities.add('vision');\n return {\n ...model,\n contextWindow: model.contextWindow ?? resolved.capabilities.maxContext ?? undefined,\n inputCost: model.inputCost ?? resolved.cost?.input,\n outputCost: model.outputCost ?? resolved.cost?.output,\n capabilities: [...capabilities],\n };\n }),\n );\n sendMessage(ws, {\n type: 'provider.models',\n payload: { provider: providerId, models: enriched },\n });\n } catch (error) {\n sendOperationResult(ws, false, errMessage(error));\n }\n }\n\n async function adoptDefaultProviderIfUnset(providerId: string): Promise<void> {\n if (!deps.applyModelSwitch || deps.hasActiveModel?.()) return;\n const saved = await loadConfigProviders();\n await deps.onProvidersLoaded?.(saved);\n const config = saved[providerId];\n if (!config) return;\n let model = config.models?.[0];\n if (!model && deps.modelsRegistry) {\n const catalogId = config.type && config.type !== providerId ? config.type : providerId;\n const catalog = await deps.modelsRegistry.getProvider(catalogId).catch(() => undefined);\n model = catalog?.models?.[0]?.id;\n }\n if (!model) model = (await probeModelDescriptors(config))[0]?.id;\n if (!model) return;\n try {\n await deps.applyModelSwitch(providerId, model);\n } catch {\n // Best effort: the persisted provider becomes the default next session.\n }\n }\n\n async function handleKeyUpsert(\n ws: WebSocket,\n providerId: string,\n label: string,\n apiKey: string,\n ): Promise<void> {\n try {\n const providers = await loadConfigProviders();\n const result = upsertKeyRecord(\n providers,\n providerId,\n label,\n apiKey,\n new Date().toISOString(),\n );\n if (result.ok) {\n await saveConfigProviders(providers);\n broadcastSaved(providers);\n }\n sendOperationResult(ws, result.ok, result.message);\n } catch (err) {\n sendOperationResult(ws, false, errMessage(err));\n }\n }\n\n async function handleKeyDelete(ws: WebSocket, providerId: string, label: string): Promise<void> {\n try {\n const providers = await loadConfigProviders();\n const result = deleteKeyRecord(providers, providerId, label);\n if (result.ok) {\n await saveConfigProviders(providers);\n broadcastSaved(providers);\n }\n sendOperationResult(ws, result.ok, result.message);\n } catch (err) {\n sendOperationResult(ws, false, errMessage(err));\n }\n }\n\n async function handleKeySetActive(\n ws: WebSocket,\n providerId: string,\n label: string,\n ): Promise<void> {\n try {\n const providers = await loadConfigProviders();\n const result = setActiveKeyRecord(providers, providerId, label);\n if (result.ok) {\n await saveConfigProviders(providers);\n broadcastSaved(providers);\n }\n sendOperationResult(ws, result.ok, result.message);\n } catch (err) {\n sendOperationResult(ws, false, errMessage(err));\n }\n }\n\n async function handleProviderAdd(\n ws: WebSocket,\n payload: {\n id: string;\n family: string;\n baseUrl?: string | undefined;\n apiKey?: string | undefined;\n models?: string[] | undefined;\n customModels?: ProviderConfig['customModels'] | undefined;\n },\n ): Promise<void> {\n try {\n const providers = await loadConfigProviders();\n const result = addProviderRecord(providers, payload, new Date().toISOString());\n if (result.ok) {\n await saveConfigProviders(providers);\n broadcastSaved(providers);\n }\n sendOperationResult(ws, result.ok, result.message);\n if (result.ok) {\n deps.log?.(`[WebUI] Provider \"${payload.id}\" added via provider.add`);\n }\n } catch (err) {\n sendOperationResult(ws, false, errMessage(err));\n }\n }\n\n async function handleProviderRemove(ws: WebSocket, providerId: string): Promise<void> {\n try {\n const providers = await loadConfigProviders();\n const result = removeProviderRecord(providers, providerId);\n if (result.ok) {\n await saveConfigProviders(providers);\n broadcastSaved(providers);\n }\n sendOperationResult(ws, result.ok, result.message);\n } catch (err) {\n sendOperationResult(ws, false, errMessage(err));\n }\n }\n\n /** Broadcast the current saved-provider list to every connected client. */\n function broadcastSaved(providers: Record<string, ProviderConfig>): void {\n deps.broadcast({\n type: 'providers.saved',\n payload: { providers: projectSavedProviders(providers) },\n });\n }\n\n /** Remove the saved model allowlist for a provider. */\n async function handleProviderClearModels(ws: WebSocket, providerId: string): Promise<void> {\n try {\n const providers = await loadConfigProviders();\n const cfg = providers[providerId];\n if (!cfg) {\n sendOperationResult(ws, false, `Unknown provider \"${providerId}\"`);\n return;\n }\n delete cfg.models;\n await saveConfigProviders(providers);\n sendOperationResult(ws, true, `Cleared model allowlist for ${providerId}`);\n broadcastSaved(providers);\n } catch (err) {\n sendOperationResult(ws, false, errMessage(err));\n }\n }\n\n /** Restore a previously-cleared model allowlist (pairs with clear). */\n async function handleProviderUndoClear(\n ws: WebSocket,\n providerId: string,\n previousModels: string[],\n ): Promise<void> {\n try {\n const providers = await loadConfigProviders();\n const cfg = providers[providerId];\n if (!cfg) {\n sendOperationResult(ws, false, `Unknown provider \"${providerId}\"`);\n return;\n }\n cfg.models = [...previousModels];\n await saveConfigProviders(providers);\n sendOperationResult(ws, true, `Restored ${previousModels.length} model(s) for ${providerId}`);\n broadcastSaved(providers);\n } catch (err) {\n sendOperationResult(ws, false, errMessage(err));\n }\n }\n\n /** Update a saved provider's wire config (family / baseUrl / envVars / models / customModels). */\n async function handleProviderUpdate(\n ws: WebSocket,\n payload: {\n id: string;\n family?: string | undefined;\n baseUrl?: string | undefined;\n envVars?: string[] | undefined;\n models?: string[] | undefined;\n customModels?: ProviderConfig['customModels'] | undefined;\n },\n ): Promise<void> {\n try {\n const providers = await loadConfigProviders();\n const cfg = providers[payload.id];\n if (!cfg) {\n sendOperationResult(ws, false, `Unknown provider \"${payload.id}\"`);\n return;\n }\n if (payload.family !== undefined) cfg.family = payload.family as ProviderConfig['family'];\n if (payload.baseUrl !== undefined) cfg.baseUrl = payload.baseUrl;\n if (payload.envVars !== undefined) cfg.envVars = payload.envVars;\n if (payload.models !== undefined) cfg.models = payload.models;\n if (payload.customModels !== undefined) cfg.customModels = payload.customModels;\n await saveConfigProviders(providers);\n sendOperationResult(ws, true, `Updated ${payload.id}`);\n broadcastSaved(providers);\n } catch (err) {\n sendOperationResult(ws, false, errMessage(err));\n }\n }\n\n /**\n * Run a health probe against a saved provider's `/v1/models` and\n * reply with a `provider.probe` message. Never throws \u2014 the\n * `ProbeResult` carries the failure mode in its `status`.\n */\n async function handleProviderProbe(\n ws: WebSocket,\n providerId: string,\n timeoutMs?: number,\n ): Promise<void> {\n const reply = (payload: Record<string, unknown>): void =>\n sendMessage(ws, { type: 'provider.probe', payload: { providerId, ...payload } });\n try {\n const providers = await loadConfigProviders();\n const cfg = providers[providerId];\n if (!cfg) {\n reply({ ok: false, status: 'no_provider' });\n return;\n }\n if (!cfg.baseUrl) {\n reply({ ok: false, status: 'no_base_url' });\n return;\n }\n const keys = normalizeKeys(cfg);\n const active = keys.find((k) => k.label === cfg.activeKey) ?? keys[0];\n const result = await probeLocalLlm({\n baseUrl: cfg.baseUrl,\n apiKey: active?.apiKey,\n noAuth: false,\n scrubber: probeScrubber,\n ...(timeoutMs !== undefined ? { timeoutMs } : {}),\n });\n reply(result as never as Record<string, unknown>);\n } catch (err) {\n reply({ ok: false, status: 'unreachable', detail: errMessage(err) });\n }\n }\n\n // \u2500\u2500 Subscription OAuth login (ChatGPT / Claude / Copilot) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n //\n // One in-flight session per kind, shared across clients (single-user). A\n // second start for the same kind closes the prior one. The engine\n // (@wrongstack/providers/oauth) is IO-free \u2014 persistence is local below.\n\n const oauthSessions = new Map<OAuthKind, OAuthSession>();\n const customProviderIds = new Map<OAuthKind, string>();\n\n function sendOAuthStatus(\n ws: WebSocket,\n kind: OAuthKind,\n phase:\n | 'awaiting_browser'\n | 'awaiting_code'\n | 'exchanging'\n | 'fetching_models'\n | 'success'\n | 'error',\n extra: Record<string, unknown> = {},\n ): void {\n sendMessage(ws, { type: 'auth.oauth.status', payload: { kind, phase, ...extra } });\n }\n\n /** Persist a successful login by upserting the OAuth credential. */\n async function persistOAuthOutcome(\n outcome: OAuthLoginOutcome,\n customProviderId?: string,\n ): Promise<void> {\n const providers = await loadConfigProviders();\n const providerId = customProviderId ?? outcome.providerId;\n const existing = providers[providerId];\n const p: ProviderConfig = existing ? { ...existing } : { type: providerId };\n p.family = outcome.family as ProviderConfig['family'];\n if (!p.baseUrl) p.baseUrl = outcome.baseUrl;\n p.models = [...outcome.models];\n const keys = normalizeKeys(p).filter((k) => k.label !== outcome.apiKey.label);\n keys.push(outcome.apiKey);\n writeKeysBack(p, keys);\n p.activeKey = outcome.apiKey.label;\n providers[providerId] = p;\n await saveConfigProviders(providers);\n broadcastSaved(providers);\n }\n\n async function finishOAuth(\n ws: WebSocket,\n kind: OAuthKind,\n outcome: OAuthLoginOutcome | null,\n customProviderId?: string,\n ): Promise<void> {\n if (!outcome) {\n sendOAuthStatus(ws, kind, 'error', { message: 'Sign-in cancelled or timed out.' });\n return;\n }\n const providerId = customProviderId ?? outcome.providerId;\n sendOAuthStatus(ws, kind, 'fetching_models', { providerId });\n await persistOAuthOutcome(outcome, customProviderId);\n sendOAuthStatus(ws, kind, 'success', {\n providerId,\n message: `Signed in \u2014 saved as ${providerId} (${outcome.models.length} models).`,\n });\n }\n\n async function handleOAuthStart(\n ws: WebSocket,\n kind: OAuthKind,\n customProviderId?: string,\n ): Promise<void> {\n try {\n oauthSessions.get(kind)?.close();\n oauthSessions.delete(kind);\n\n const session = await beginOAuthLogin(kind, { modelsRegistry: deps.modelsRegistry });\n if (customProviderId) customProviderIds.set(kind, customProviderId);\n else customProviderIds.delete(kind);\n oauthSessions.set(kind, session);\n const providerId = customProviderId ?? session.providerId;\n\n if (kind === 'copilot') {\n sendOAuthStatus(ws, kind, 'awaiting_code', {\n providerId,\n verificationUri: session.verificationUri,\n userCode: session.userCode,\n bound: false,\n });\n } else {\n sendOAuthStatus(ws, kind, 'awaiting_browser', {\n providerId,\n authorizeUrl: session.authorizeUrl,\n bound: session.bound,\n });\n }\n\n // Drive to completion in the background when there is something to wait\n // for: the copilot device poll, or a bound loopback callback. When the\n // loopback could not bind, we wait for a manual `auth.oauth.code` paste.\n const drive = kind === 'copilot' || session.bound;\n if (drive) {\n void (async () => {\n try {\n const outcome = await session.waitForCompletion();\n await finishOAuth(ws, kind, outcome, customProviderIds.get(kind));\n } catch (err) {\n sendOAuthStatus(ws, kind, 'error', { message: errMessage(err) });\n } finally {\n if (oauthSessions.get(kind) === session) {\n oauthSessions.delete(kind);\n customProviderIds.delete(kind);\n }\n }\n })();\n }\n } catch (err) {\n sendOAuthStatus(ws, kind, 'error', { message: errMessage(err) });\n }\n }\n\n async function handleOAuthCode(ws: WebSocket, kind: OAuthKind, input: string): Promise<void> {\n const session = oauthSessions.get(kind);\n if (!session) {\n sendOAuthStatus(ws, kind, 'error', {\n message: 'No active sign-in for this provider \u2014 start the login again.',\n });\n return;\n }\n try {\n sendOAuthStatus(ws, kind, 'exchanging', {\n providerId: customProviderIds.get(kind) ?? session.providerId,\n });\n const outcome = await session.completeWithCode(input);\n await finishOAuth(ws, kind, outcome, customProviderIds.get(kind));\n } catch (err) {\n sendOAuthStatus(ws, kind, 'error', { message: errMessage(err) });\n } finally {\n session.close();\n if (oauthSessions.get(kind) === session) {\n oauthSessions.delete(kind);\n customProviderIds.delete(kind);\n }\n }\n }\n\n function handleOAuthCancel(ws: WebSocket, kind: OAuthKind): void {\n oauthSessions.get(kind)?.close();\n oauthSessions.delete(kind);\n customProviderIds.delete(kind);\n sendOAuthStatus(ws, kind, 'error', { message: 'Sign-in cancelled.' });\n }\n\n return {\n handleProvidersList,\n handleProvidersSaved,\n handleProviderModels,\n handleProviderModelsSearch,\n adoptDefaultProviderIfUnset,\n broadcastSaved,\n handleKeyUpsert,\n handleKeyDelete,\n handleKeySetActive,\n handleProviderAdd,\n handleProviderRemove,\n handleProviderClearModels,\n handleProviderUndoClear,\n handleProviderUpdate,\n handleProviderProbe,\n handleOAuthStart,\n handleOAuthCode,\n handleOAuthCancel,\n loadConfigProviders,\n };\n}\n\n/**\n * Standalone-host adapter. It preserves the existing serialized profile-file\n * persistence while delegating all provider and OAuth behavior to the\n * store-backed canonical operations factory.\n */\nexport function createProviderHandlers(deps: ProviderHandlerDeps) {\n let configWriteLock = deps.getConfigWriteLock();\n const providerStore: ProviderPersistence = {\n load: () => loadSavedProviders(deps.profileConfigPath, deps.vault),\n save: async (providers) => {\n const next = configWriteLock\n .then(() => saveProviders(deps.profileConfigPath, deps.vault, providers))\n .catch((error) => {\n console.error(\n JSON.stringify({\n level: 'error',\n event: 'webui.provider_save_failed',\n message: toErrorMessage(error),\n timestamp: new Date().toISOString(),\n }),\n );\n });\n configWriteLock = next;\n deps.setConfigWriteLock(next);\n await next;\n },\n };\n return createProviderOperations({\n providerStore,\n broadcast: (message) => deps.broadcast(deps.clients, message),\n modelsRegistry: deps.modelsRegistry,\n log: (message) => console.log(message),\n hasActiveModel: deps.hasActiveModel,\n onProvidersLoaded: deps.onProvidersLoaded,\n applyModelSwitch: deps.applyModelSwitch,\n });\n}\n", "import type { ModelsDevModel, ModelsRegistry } from '@wrongstack/core/types';\n\nexport interface CatalogModelMatch {\n providerId: string;\n providerName: string;\n modelId: string;\n name: string;\n description?: string | undefined;\n releaseDate?: string | undefined;\n contextWindow?: number | undefined;\n maxOutput?: number | undefined;\n inputCost?: number | undefined;\n outputCost?: number | undefined;\n capabilities: string[];\n}\n\ninterface RankedMatch {\n score: number;\n match: CatalogModelMatch;\n}\n\nfunction normalize(value: string): string {\n return value.trim().toLocaleLowerCase();\n}\n\nfunction scoreModel(query: string, model: ModelsDevModel): number {\n const id = normalize(model.id);\n const name = normalize(model.name);\n if (id === query) return 1_000;\n if (name === query) return 950;\n if (id.startsWith(query)) return 800 - Math.min(id.length - query.length, 100);\n if (name.startsWith(query)) return 750 - Math.min(name.length - query.length, 100);\n const idIndex = id.indexOf(query);\n if (idIndex >= 0) return 600 - Math.min(idIndex, 100);\n const nameIndex = name.indexOf(query);\n if (nameIndex >= 0) return 550 - Math.min(nameIndex, 100);\n return 0;\n}\n\nfunction describeMatch(\n providerId: string,\n providerName: string,\n model: ModelsDevModel,\n): CatalogModelMatch {\n return {\n providerId,\n providerName,\n modelId: model.id,\n name: model.name,\n ...(model.description !== undefined ? { description: model.description } : {}),\n ...(model.release_date !== undefined ? { releaseDate: model.release_date } : {}),\n ...(model.limit?.context !== undefined ? { contextWindow: model.limit.context } : {}),\n ...(model.limit?.output !== undefined ? { maxOutput: model.limit.output } : {}),\n ...(model.cost?.input !== undefined ? { inputCost: model.cost.input } : {}),\n ...(model.cost?.output !== undefined ? { outputCost: model.cost.output } : {}),\n capabilities: [\n ...(model.tool_call ? ['tools'] : []),\n ...(model.reasoning || model.reasoningConfig ? ['reasoning'] : []),\n ...(model.modalities?.input?.includes('image') ? ['vision'] : []),\n ...(model.open_weights ? ['open_weights'] : []),\n ],\n };\n}\n\n/** Search the loaded models.dev registry without sending the full catalog to the browser. */\nexport async function searchCatalogModels(\n registry: Pick<ModelsRegistry, 'listProviders'>,\n rawQuery: string,\n limit = 8,\n): Promise<CatalogModelMatch[]> {\n const query = normalize(rawQuery);\n if (!query) return [];\n const boundedLimit = Math.max(1, Math.min(Math.trunc(limit), 20));\n const ranked: RankedMatch[] = [];\n for (const provider of await registry.listProviders()) {\n for (const model of provider.models) {\n const score = scoreModel(query, model);\n if (score <= 0) continue;\n ranked.push({\n score,\n match: describeMatch(provider.id, provider.name, model),\n });\n }\n }\n ranked.sort(\n (a, b) =>\n b.score - a.score ||\n a.match.modelId.localeCompare(b.match.modelId) ||\n a.match.providerId.localeCompare(b.match.providerId),\n );\n return ranked.slice(0, boundedLimit).map(({ match }) => match);\n}\n", "/**\n * Shared config I/O helpers for the `providers` map inside a profile config.\n *\n * Extracted from both `packages/webui/src/server/index.ts` and\n * `packages/cli/src/webui-server.ts` so the CLI's `--webui` mode doesn't\n * duplicate the read-merge-decrypt / encrypt-write cycle. Callers supply\n * their own vault (already booted) and config path \u2014 this module is pure I/O\n * with no side-channel state.\n */\nimport * as fs from 'node:fs/promises';\nimport { ConfigError, type ProviderConfig, type SecretVault } from '@wrongstack/core/types';\nimport { atomicWrite } from '@wrongstack/core/utils';\nimport { decryptConfigSecrets, encryptConfigSecrets } from '@wrongstack/core/security';\n\n/**\n * Read the `providers` section from a profile config, decrypting\n * secret-bearing fields. Returns an empty record when the config file\n * doesn't exist or has no `providers` key.\n */\nexport async function loadSavedProviders(\n configPath: string,\n vault: SecretVault,\n): Promise<Record<string, ProviderConfig>> {\n let raw: string;\n try {\n raw = await fs.readFile(configPath, 'utf8');\n } catch {\n return {};\n }\n let parsed: { providers?: Record<string, ProviderConfig> } = {};\n try {\n parsed = JSON.parse(raw) as { providers?: Record<string, ProviderConfig> };\n } catch {\n return {};\n }\n if (!parsed.providers) return {};\n return decryptConfigSecrets(parsed.providers, vault);\n}\n\n/**\n * Write `providers` to the active profile config, encrypting secrets first.\n * Refuses to overwrite a corrupt-but-existing config file (the operator\n * should fix it manually). When the config file is missing (ENOENT), starts\n * from an empty object.\n */\nexport async function saveProviders(\n configPath: string,\n vault: SecretVault,\n providers: Record<string, ProviderConfig>,\n profileConfigPath?: string | undefined,\n): Promise<void> {\n const targetPath = profileConfigPath ?? configPath;\n let raw: string;\n let fileExists = true;\n try {\n raw = await fs.readFile(targetPath, 'utf8');\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw new ConfigError({\n message: `Refusing to mutate ${targetPath}: ${(err as Error).message}`,\n code: 'CONFIG_PARSE_FAILED',\n context: { filePath: targetPath },\n cause: err,\n });\n }\n fileExists = false;\n raw = '{}';\n }\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n if (fileExists) {\n throw new ConfigError({\n message:\n `Refusing to overwrite corrupt config at ${targetPath} ` +\n `(${(err as Error).message}). Fix or move the file aside before retrying.`,\n code: 'CONFIG_PARSE_FAILED',\n context: { filePath: targetPath },\n cause: err,\n });\n }\n parsed = {};\n }\n parsed.providers = providers;\n const encrypted = encryptConfigSecrets(parsed, vault);\n await atomicWrite(targetPath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\n}\n\n// createProviderConfigIO (the standalone boot-phase helper) lives in\n// provider-config-standalone.ts so this module stays vault-free.\n", "import { expectDefined } from '@wrongstack/core/utils';\nimport {\n buildProviderConfigFromPreset,\n rehydrateCanonicalProviderConfig,\n resolvePresetForAlias,\n} from '@wrongstack/providers';\n/**\n * Pure provider/API-key record transforms for the WebUI server's `key.*` and\n * `provider.*` WebSocket handlers.\n *\n * These operate on an in-memory `providers` record (the decrypted\n * `config.providers` map) and return a `{ ok, message }` result mirroring the\n * status string the handler sends back to the client. All persistence\n * (load/decrypt, encrypt/atomic-write) and WS messaging stays in `index.ts` \u2014\n * keeping this layer pure means the security-sensitive key bookkeeping (which\n * key is active, when a provider is dropped, how legacy single-key configs are\n * normalized) is unit-testable without a vault or a socket.\n *\n * Extracted from `index.ts`; transforms mutate the passed record in place, the\n * same way the original handlers did before calling `saveProviders`.\n */\nimport type { ProviderApiKey, ProviderConfig } from '@wrongstack/core/types';\nexport type ProvidersRecord = Record<string, ProviderConfig>;\n\nexport interface KeyOpResult {\n ok: boolean;\n message: string;\n}\n\n/**\n * Normalize a provider's keys to the array form, upgrading a legacy single\n * `apiKey` string to a one-element `[{ label: 'default', ... }]` list. Returns\n * fresh copies so callers can mutate without aliasing the stored config.\n */\nexport function normalizeKeys(cfg: ProviderConfig): ProviderApiKey[] {\n if (Array.isArray(cfg.apiKeys) && cfg.apiKeys.length > 0) {\n return cfg.apiKeys.map((k) => ({ ...k }));\n }\n if (typeof cfg.apiKey === 'string' && cfg.apiKey.length > 0) {\n return [{ label: 'default', apiKey: cfg.apiKey, createdAt: '' }];\n }\n return [];\n}\n\n/**\n * Write a normalized key list back onto a provider config: drop all key fields\n * when empty, otherwise sync `apiKeys` and re-point `activeKey` if it no longer\n * names a present key. Does NOT mirror the plaintext key to the legacy `apiKey`\n * field \u2014 that would leak the secret on accidental serialization. Consumers\n * that need the real key should read from `apiKeys[]` directly.\n */\nexport function writeKeysBack(cfg: ProviderConfig, keys: ProviderApiKey[]): void {\n if (keys.length === 0) {\n delete cfg.apiKeys;\n delete cfg.apiKey;\n delete cfg.activeKey;\n return;\n }\n cfg.apiKeys = keys;\n const active = keys.find((k) => k.label === cfg.activeKey) ?? expectDefined(keys[0]);\n // Do NOT mirror plaintext to cfg.apiKey \u2014 cleared to prevent serialization leaks.\n delete cfg.apiKey;\n if (!cfg.activeKey || !keys.some((k) => k.label === cfg.activeKey)) {\n cfg.activeKey = active.label;\n }\n}\n\n/** Mask a secret for display: `\u2022\u2022\u2022\u2022` for short keys, `abcd\u2026wxyz` otherwise. */\nexport function maskedKey(key: string | undefined): string {\n if (!key) return '\u2014';\n if (key.length <= 8) return '\u2022'.repeat(key.length);\n return `${key.slice(0, 4)}\u2026${key.slice(-4)}`;\n}\n\n/**\n * Hydrate a not-yet-saved provider config from a trusted preset when the\n * supplied id (or its `<id>-suffix` alias) maps to a canonical preset.\n * Mutates `dest` in place and returns the canonical preset id (which the\n * caller should use as `cfg.type` so the registry lookup still resolves).\n *\n * Returns `undefined` for unknown ids so the generic registration path\n * can take over (preserving the prior behaviour for user-typed custom\n * gateways and any third-party provider).\n */\nfunction hydratePresetConfig(providerId: string, dest: ProviderConfig): string | undefined {\n const preset = resolvePresetForAlias(providerId);\n if (!preset) return undefined;\n const template = buildProviderConfigFromPreset(preset);\n // Apply preset defaults without overwriting any field the caller may\n // already have set (e.g. `family` on a config-only custom alias). The\n // preset always wins for the four product-locked fields: `baseUrl`,\n // `envVars`, `models`, `customModels`, `quirks`.\n if (!dest.type) dest.type = preset.id;\n if (!dest.family) dest.family = preset.family;\n if (dest.baseUrl === undefined) dest.baseUrl = template.baseUrl;\n if (!dest.envVars || dest.envVars.length === 0) dest.envVars = template.envVars;\n // Model availability/capability facts are product-locked for trusted\n // presets. A generic provider.add client must not replace them with metadata\n // selected for an unrelated custom endpoint.\n dest.models = template.models;\n if (template.customModels) dest.customModels = template.customModels;\n else delete dest.customModels;\n if (template.quirks && dest.quirks === undefined) dest.quirks = template.quirks;\n return preset.id;\n}\n\n/** Add or replace a labeled key for a provider, creating the provider if new. */\nexport function upsertKey(\n providers: ProvidersRecord,\n providerId: string,\n label: string,\n apiKey: string,\n nowIso: string,\n): KeyOpResult {\n let existing: ProviderConfig | undefined = providers[providerId];\n if (!existing) {\n // New entry: hydrate from a trusted preset when the id (or its\n // <id>-suffix alias) maps to a canonical vendor entry \u2014 this is how\n // the WebUI setup card for Kimi Code / Moonshot Platform / Z.AI ends\n // up with the right baseUrl, model allowlist, and compatibility\n // quirks without the user having to type them.\n existing = { type: providerId };\n const presetId = hydratePresetConfig(providerId, existing);\n if (presetId) existing.type = presetId;\n } else {\n // Setup cards use key.upsert for already-saved providers. Repair stale\n // canonical preset metadata here without touching credentials or a\n // user-owned custom endpoint.\n rehydrateCanonicalProviderConfig(providerId, existing);\n }\n const keys = normalizeKeys(existing);\n const idx = keys.findIndex((k) => k.label === label);\n if (idx >= 0) {\n keys[idx] = { ...expectDefined(keys[idx]), apiKey, createdAt: nowIso };\n } else {\n keys.push({ label, apiKey, createdAt: nowIso });\n }\n writeKeysBack(existing, keys);\n if (!existing.activeKey) existing.activeKey = label;\n providers[providerId] = existing;\n return { ok: true, message: `Key \"${label}\" saved for ${providerId}` };\n}\n\n/** Remove a labeled key; drops the provider entirely when its last key goes. */\nexport function deleteKey(\n providers: ProvidersRecord,\n providerId: string,\n label: string,\n): KeyOpResult {\n const existing = providers[providerId];\n if (!existing) {\n return { ok: false, message: `Provider \"${providerId}\" not found` };\n }\n const keys = normalizeKeys(existing).filter((k) => k.label !== label);\n if (keys.length === 0) {\n delete providers[providerId];\n } else {\n writeKeysBack(existing, keys);\n if (existing.activeKey === label) existing.activeKey = keys[0]?.label;\n providers[providerId] = existing;\n }\n return { ok: true, message: `Key \"${label}\" deleted from ${providerId}` };\n}\n\n/** Point a provider's active key at the given label. */\nexport function setActiveKey(\n providers: ProvidersRecord,\n providerId: string,\n label: string,\n): KeyOpResult {\n const existing = providers[providerId];\n if (!existing) {\n return { ok: false, message: `Provider \"${providerId}\" not found` };\n }\n existing.activeKey = label;\n writeKeysBack(existing, normalizeKeys(existing));\n providers[providerId] = existing;\n return { ok: true, message: `Active key for ${providerId} set to \"${label}\"` };\n}\n\n/** Register a brand-new provider (optionally with an initial `default` key). */\nexport function addProvider(\n providers: ProvidersRecord,\n payload: {\n id: string;\n family: string;\n baseUrl?: string | undefined;\n apiKey?: string | undefined;\n models?: string[] | undefined;\n customModels?: ProviderConfig['customModels'] | undefined;\n },\n nowIso: string,\n): KeyOpResult {\n if (providers[payload.id]) {\n return {\n ok: false,\n message: `Provider \"${payload.id}\" already exists. Use key.add to add a key.`,\n };\n }\n // Trust the trusted-preset table for product-locked fields. If the id\n // is a known preset (canonical or `<id>-suffix`), `hydratePresetConfig`\n // populates `baseUrl`, `models`, `customModels`, and `quirks` from the\n // preset. `family` still falls back to the wire value supplied by the\n // setup flow (the WebSocket payload) \u2014 preset only fills it in when\n // absent \u2014 so a user-supplied override survives.\n const newProv: ProviderConfig = {\n type: payload.id,\n family: payload.family as ProviderConfig['family'],\n baseUrl: payload.baseUrl,\n ...(payload.models !== undefined ? { models: [...payload.models] } : {}),\n ...(payload.customModels !== undefined\n ? { customModels: structuredClone(payload.customModels) }\n : {}),\n };\n const presetId = hydratePresetConfig(payload.id, newProv);\n if (presetId) newProv.type = presetId;\n if (payload.apiKey) {\n newProv.apiKeys = [{ label: 'default', apiKey: payload.apiKey, createdAt: nowIso }];\n newProv.activeKey = 'default';\n }\n providers[payload.id] = newProv;\n return { ok: true, message: `Provider \"${payload.id}\" added` };\n}\n\n/** Remove an entire provider and all its keys. */\nexport function removeProvider(providers: ProvidersRecord, providerId: string): KeyOpResult {\n if (!providers[providerId]) {\n return { ok: false, message: `Provider \"${providerId}\" not found` };\n }\n delete providers[providerId];\n return { ok: true, message: `Provider \"${providerId}\" removed` };\n}\n", "/**\n * Session route handlers \u2014 extracted from the startWebUI closure in index.ts.\n * The largest builder: session lifecycle (new/clear/resume/save), context ops\n * (debug/compact/repair), context-mode CRUD, and checkpoint list/rewind.\n *\n * Mirrors createProviderHandlers/createModeHandlers/createProjectHandlers. The\n * mutable startWebUI bindings the handlers touch (`session`, `sessionStartedAt`,\n * and the project-switch-mutable `sessionStore`/`projectRoot`) are threaded in\n * as getters/setters so this stays a pure function of its context. Handler\n * bodies are a verbatim lift \u2014 only dependency references changed.\n */\n\nimport type { Context, TodoItem } from '@wrongstack/core/agent';\nimport type { createStrategyCompactor } from '@wrongstack/core/execution';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport type { ToolRegistry } from '@wrongstack/core/registry';\nimport { loadTodosCheckpoint } from '@wrongstack/core/storage';\nimport type { SessionStore, TokenCounter } from '@wrongstack/core/types';\nimport { DEFAULT_CONTEXT_WINDOW_MODE_ID, resolveContextWindowPolicy } from '@wrongstack/core/types';\nimport { repairToolUseAdjacency, sessionScopedPath } from '@wrongstack/core/utils';\nimport type { WebSocket } from 'ws';\nimport { buildReplayPayload } from '../protocol/index.js';\nimport {\n applyContextEditorProposal,\n buildContextEditorSnapshot,\n validateContextEditorProposal,\n} from './context-editor.js';\nimport type { CustomModeStore } from './custom-context-modes.js';\nimport { toSessionHistoryEntries } from './session-history.js';\nimport type { SessionRouteHandlers } from './session-routes.js';\nimport type { SessionIdentityTarget } from './standalone-session-identity.js';\nimport { estimateContextBreakdown } from './token-estimator.js';\nimport type { ConnectedClient } from './types.js';\nimport {\n validateContextModeCreatePayload,\n validateContextModeDeletePayload,\n validateContextModeSwitchPayload,\n validateContextModeUpdatePayload,\n} from './ws-payload-validation.js';\nimport { broadcast, errMessage, send } from './ws-utils.js';\n\ntype Session = Awaited<ReturnType<SessionStore['create']>>;\ntype WSMessageLike = { type: string; payload?: unknown | undefined };\ntype OutboundMessage = { type: string; payload: unknown };\n\nfunction isRecordPayload(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\ntype SessionStartPayload = {\n sessionId: string;\n model: string;\n provider: string;\n maxContext: number;\n inputCost: number;\n outputCost: number;\n cacheReadCost: number;\n projectName: string;\n projectRoot: string;\n cwd: string;\n mode: string;\n contextMode: string;\n};\n\nexport interface SessionHandlersContext {\n config: { provider: string; model: string };\n getConfig?: () => { provider: string; model: string };\n clients?: Map<WebSocket, ConnectedClient>;\n /** Host-neutral transport adapters. Standalone callers may keep using `clients`. */\n sendMessage?: (ws: WebSocket, message: OutboundMessage) => void;\n broadcastMessage?: (message: OutboundMessage) => void;\n context: Context;\n events?: EventBus | undefined;\n toolRegistry?: Pick<ToolRegistry, 'list'>;\n listTools?: () => ReturnType<ToolRegistry['list']>;\n compactor?: ReturnType<typeof createStrategyCompactor>;\n getCompactor?: () => ReturnType<typeof createStrategyCompactor> | undefined;\n customModeStore?: CustomModeStore;\n getCustomModeStore?: () => CustomModeStore | Promise<CustomModeStore>;\n tokenCounter: TokenCounter;\n /** Live reads of the mutable startWebUI bindings. */\n getProjectRoot: () => string;\n getSession: () => Session;\n getSessionStore: () => SessionStore;\n /** Hosts without a wired durable store may keep session.new as an in-memory reset. */\n canSwapSessions?: () => boolean;\n sessionsDir?: string;\n getSessionsDir?: () => string;\n /** Mutations of the startWebUI bindings. */\n setSession: (s: Session) => void;\n setSessionStartedAt?: (t: number) => void;\n /** Atomically reserve an explicitly selected session before opening its writer. */\n claimSession?: ((sessionId: string) => Promise<() => Promise<void>>) | undefined;\n onBeforeSessionTodosReplaced?:\n | ((sessionId: string, sessionsDir: string) => void | Promise<void>)\n | undefined;\n onSessionSwapped?: (sessionId: string, target?: SessionIdentityTarget) => void | Promise<void>;\n /**\n * Abort the in-flight agent run (if any) before the active session is\n * swapped. Without this, a run started in the previous session keeps\n * streaming/tool-calling in the background after session.new/resume.\n */\n abortActiveRun?: (() => void) | undefined;\n isRunActive?: (() => boolean) | undefined;\n sessionStartPayload: (overrides?: Record<string, unknown>) => Promise<SessionStartPayload>;\n}\n\nexport function createSessionHandlers(ctx: SessionHandlersContext): SessionRouteHandlers {\n const currentConfig = (): { provider: string; model: string } => ctx.getConfig?.() ?? ctx.config;\n const sendTo = (ws: WebSocket, message: OutboundMessage): void => {\n if (ctx.sendMessage) ctx.sendMessage(ws, message);\n else send(ws, message);\n };\n const broadcastToAll = (message: OutboundMessage): void => {\n if (ctx.broadcastMessage) ctx.broadcastMessage(message);\n else broadcast(ctx.clients ?? new Map(), message);\n };\n const result = (ws: WebSocket, success: boolean, message: string): void => {\n sendTo(ws, { type: 'key.operation_result', payload: { success, message } });\n };\n const sessionsDirectory = (): string =>\n ctx.getSessionsDir?.() ?? ctx.sessionsDir ?? `${ctx.getProjectRoot()}/.wrongstack/sessions`;\n const modeStore = async (): Promise<CustomModeStore> => {\n const store = ctx.getCustomModeStore ? await ctx.getCustomModeStore() : ctx.customModeStore;\n if (!store) throw new Error('Context mode store not available');\n return store;\n };\n const currentSessionId = (): string => ctx.getSession().id;\n const sessionPayload = <T extends object>(payload: T): T & { sessionId: string } => {\n const provided = (payload as { sessionId?: unknown }).sessionId;\n const sessionId =\n typeof provided === 'string' && provided.length > 0 ? provided : currentSessionId();\n return { ...payload, sessionId };\n };\n const requestedSessionId = (msg: WSMessageLike): string | undefined => {\n const payload = msg.payload;\n return payload &&\n typeof payload === 'object' &&\n typeof (payload as { sessionId?: unknown }).sessionId === 'string'\n ? (payload as { sessionId: string }).sessionId\n : undefined;\n };\n const ensureCurrentSession = (ws: WebSocket, msg: WSMessageLike, op: string): boolean => {\n const requested = requestedSessionId(msg);\n const current = currentSessionId();\n if (!requested || requested === current) return true;\n sendTo(ws, {\n type: 'error',\n payload: sessionPayload({\n phase: op,\n message: `Request targeted session ${requested}, but this WebUI runtime is currently on ${current}.`,\n requestedSessionId: requested,\n }),\n });\n return false;\n };\n let sessionTransitionTail = Promise.resolve();\n const serializeSessionTransition = async <T>(operation: () => Promise<T>): Promise<T> => {\n const current = sessionTransitionTail.then(operation, operation);\n sessionTransitionTail = current.then(\n () => undefined,\n () => undefined,\n );\n return current;\n };\n const finalizeSession = async (writer: Session): Promise<void> => {\n await writer\n .append({\n type: 'session_end',\n ts: new Date().toISOString(),\n usage: ctx.tokenCounter.total(),\n })\n .catch(() => undefined);\n await writer.close().catch(() => undefined);\n };\n const resetContextAccounting = (): void => {\n ctx.context.lastRequestTokens = undefined;\n ctx.context.lastRealInputTokens = undefined;\n ctx.context.state.deleteMeta?.('lastRequestTokensAt');\n ctx.context.state.deleteMeta?.('realAnchorMsgCount');\n };\n const activateSession = async (\n next: Session,\n messages: Context['messages'],\n usage?: Parameters<TokenCounter['account']>[0],\n todos: TodoItem[] = [],\n ): Promise<void> => {\n const current = ctx.getSession();\n if (current !== next) {\n // Stop the previous session's in-flight run before swapping \u2014 a slow\n // provider stream would otherwise keep running (and emitting events)\n // in the background after session.new/resume.\n try {\n ctx.abortActiveRun?.();\n } catch {\n // Aborting is best-effort; ownership/session finalization must still\n // advance so a faulty host callback cannot strand a claimed session.\n }\n await finalizeSession(current);\n }\n ctx.setSession(next);\n ctx.context.session = next;\n ctx.context.state.replaceMessages(messages);\n await ctx.context.flushConversationJournal?.();\n // Rebind durable todo persistence before replaceTodos emits. Detaching\n // afterward would flush this new-session snapshot into the previous file.\n await ctx.onBeforeSessionTodosReplaced?.(next.id, sessionsDirectory());\n // Restore the resumed session's todo board from its .todos.json sidecar\n // (empty for a fresh session). Without this a resume cleared the panel.\n ctx.context.state.replaceTodos(todos);\n resetContextAccounting();\n ctx.context.readFiles.clear();\n ctx.context.fileMtimes.clear();\n ctx.context.state.setMeta?.(\n 'plan.path',\n sessionScopedPath(sessionsDirectory(), next.id, '.plan.json'),\n );\n ctx.context.state.setMeta?.(\n 'task.path',\n sessionScopedPath(sessionsDirectory(), next.id, '.tasks.json'),\n );\n ctx.tokenCounter.reset?.();\n if (usage) ctx.tokenCounter.account(usage, currentConfig().model, ctx.context.provider.id);\n ctx.setSessionStartedAt?.(Date.now());\n await ctx.onSessionSwapped?.(next.id);\n };\n\n return {\n newSession: (ws, msg) =>\n serializeSessionTransition(async () => {\n if (!ensureCurrentSession(ws, msg, 'session.new')) return;\n const clearedSessionId = currentSessionId();\n if (ctx.canSwapSessions?.() !== false) {\n const store = ctx.getSessionStore();\n const config = currentConfig();\n const next = await store.create({\n id: '',\n title: '',\n model: config.model,\n provider: config.provider,\n });\n let rollbackClaim: (() => Promise<void>) | undefined;\n let activated = false;\n try {\n rollbackClaim = await ctx.claimSession?.(next.id);\n // activateSession cannot fail before replacing the runtime writer:\n // finalizeSession is best-effort and setSession is synchronous.\n activated = true;\n await activateSession(next, []);\n } catch (err) {\n if (!activated) {\n await rollbackClaim?.().catch(() => undefined);\n await next.close().catch(() => undefined);\n await store.delete(next.id).catch(() => undefined);\n }\n result(ws, false, errMessage(err));\n return;\n }\n } else {\n ctx.context.state.replaceMessages([]);\n ctx.context.state.replaceTodos([]);\n resetContextAccounting();\n ctx.context.readFiles.clear();\n ctx.context.fileMtimes.clear();\n ctx.tokenCounter.reset?.();\n }\n broadcastToAll({\n type: 'session.start',\n payload: await ctx.sessionStartPayload({ reset: true, clearedSessionId }),\n });\n }),\n clearContext: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.clear')) return;\n ctx.context.state.replaceMessages([]);\n ctx.context.state.replaceTodos([]);\n resetContextAccounting();\n ctx.context.readFiles.clear();\n ctx.context.fileMtimes.clear();\n ctx.tokenCounter.reset?.();\n result(ws, true, 'Context cleared');\n broadcastToAll({\n type: 'session.start',\n payload: await ctx.sessionStartPayload({ reset: true }),\n });\n },\n debugContext: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.debug')) return;\n const breakdown = estimateContextBreakdown({\n systemPrompt: ctx.context.systemPrompt,\n tools: ctx.listTools?.() ?? ctx.toolRegistry?.list() ?? [],\n messages: ctx.context.messages,\n });\n sendTo(ws, {\n type: 'context.debug',\n payload: sessionPayload({\n ...breakdown,\n mode: ctx.context.meta['contextWindowMode'] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID,\n policy: ctx.context.meta['contextWindowPolicy'],\n }),\n });\n },\n compactContext: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.compact')) return;\n const aggressive = !!(msg as { payload?: { aggressive?: boolean | undefined } }).payload\n ?.aggressive;\n try {\n const compactor = ctx.getCompactor?.() ?? ctx.compactor;\n if (!compactor) {\n result(ws, false, 'Compactor not available');\n return;\n }\n const beforeUsage = ctx.tokenCounter.total();\n const report = await compactor.compact(ctx.context, { aggressive });\n const afterUsage = ctx.tokenCounter.total();\n const before =\n typeof report.before === 'number'\n ? report.before\n : beforeUsage.input + beforeUsage.output;\n const after =\n typeof report.after === 'number' ? report.after : afterUsage.input + afterUsage.output;\n sendTo(ws, {\n type: 'context.compacted',\n payload: sessionPayload({\n before,\n after,\n saved: Math.max(0, before - after),\n reductions: report.reductions ?? [],\n repaired: report.repaired ?? false,\n }),\n });\n result(\n ws,\n true,\n `Compacted: ${before} \u2192 ${after} tokens (saved ~${Math.max(0, before - after)})`,\n );\n } catch (err) {\n result(ws, false, errMessage(err));\n }\n },\n repairContext: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.repair')) return;\n const beforeMessages = ctx.context.messages.length;\n const repaired = repairToolUseAdjacency(ctx.context.messages);\n if (repaired.report.changed) {\n ctx.context.state.replaceMessages(repaired.messages);\n }\n const payload = {\n sessionId: currentSessionId(),\n removedToolUses: repaired.report.removedToolUses,\n removedToolResults: repaired.report.removedToolResults,\n removedMessages: repaired.report.removedMessages,\n beforeMessages,\n afterMessages: ctx.context.messages.length,\n };\n broadcastToAll({ type: 'context.repaired', payload: sessionPayload(payload) });\n const removed =\n payload.removedToolUses.length +\n payload.removedToolResults.length +\n payload.removedMessages;\n result(\n ws,\n true,\n removed > 0\n ? `Context repaired: removed ${removed} orphan protocol item(s)`\n : 'Context repair found no orphan protocol blocks',\n );\n },\n openContextEditor: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.editor.open')) return;\n const snapshot = buildContextEditorSnapshot(\n ctx.context,\n ctx.listTools?.() ?? ctx.toolRegistry?.list(),\n );\n sendTo(ws, {\n type: 'context.editor.snapshot',\n payload: sessionPayload(snapshot),\n });\n },\n validateContextEditor: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.editor.validate')) return;\n const payload = isRecordPayload(msg.payload) ? msg.payload : {};\n const validation = validateContextEditorProposal({\n ctx: ctx.context,\n tools: ctx.listTools?.() ?? ctx.toolRegistry?.list(),\n baseRevision: typeof payload['baseRevision'] === 'string' ? payload['baseRevision'] : '',\n messages: payload['messages'],\n allowRepair: payload['allowRepair'] === true,\n runActive: ctx.isRunActive?.() === true,\n });\n sendTo(ws, {\n type: 'context.editor.validation',\n payload: sessionPayload(validation),\n });\n },\n applyContextEditor: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.editor.apply')) return;\n const payload = isRecordPayload(msg.payload) ? msg.payload : {};\n const applied = await applyContextEditorProposal({\n ctx: ctx.context,\n tools: ctx.listTools?.() ?? ctx.toolRegistry?.list(),\n baseRevision: typeof payload['baseRevision'] === 'string' ? payload['baseRevision'] : '',\n messages: payload['messages'],\n allowRepair: payload['allowRepair'] === true,\n runActive: ctx.isRunActive?.() === true,\n });\n if ('ok' in applied) {\n sendTo(ws, {\n type: 'context.editor.validation',\n payload: sessionPayload(applied),\n });\n return;\n }\n broadcastToAll({\n type: 'context.editor.applied',\n payload: sessionPayload(applied),\n });\n result(\n ws,\n true,\n `Context editor applied: ${applied.before.messages} \u2192 ${applied.after.messages} messages`,\n );\n },\n listContextModes: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.modes.list')) return;\n const active = String(\n ctx.context.meta['contextWindowMode'] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID,\n );\n const store = await modeStore();\n const allModes = store.list().map((m) => ({\n id: m.id,\n name: m.name,\n description: m.description,\n isActive: m.id === active,\n thresholds: m.thresholds,\n preserveK: m.preserveK,\n eliseThreshold: m.eliseThreshold,\n custom: (m as { custom?: boolean }).custom === true,\n }));\n sendTo(ws, {\n type: 'context.modes.list',\n payload: sessionPayload({ activeId: active, modes: allModes }),\n });\n },\n switchContextMode: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.mode.switch')) return;\n const parsed = validateContextModeSwitchPayload(msg.payload);\n if (!parsed.ok) {\n result(ws, false, parsed.message);\n return;\n }\n const { id } = parsed.value;\n let policy = resolveContextWindowPolicy({}, id);\n if (policy.id !== id) {\n const customModes = (await modeStore())\n .list()\n .filter((m) => (m as { custom?: boolean }).custom === true);\n const custom = customModes.find((m) => m.id === id);\n if (!custom) {\n result(ws, false, `Unknown context mode \"${id}\"`);\n return;\n }\n policy = custom as never as typeof policy;\n }\n ctx.context.meta['contextWindowMode'] = policy.id;\n ctx.context.meta['contextWindowPolicy'] = policy;\n result(ws, true, `Context mode switched to ${policy.id}`);\n broadcastToAll({\n type: 'context.mode.changed',\n payload: sessionPayload({ id: policy.id, name: policy.name, policy }),\n });\n },\n createContextMode: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.mode.create')) return;\n const parsed = validateContextModeCreatePayload(msg.payload);\n if (!parsed.ok) {\n result(ws, false, parsed.message);\n return;\n }\n const payload = parsed.value;\n const store = await modeStore();\n const operation = store.create({\n id: payload.id,\n name: payload.name,\n description: payload.description,\n thresholds: payload.thresholds,\n preserveK: payload.preserveK,\n eliseThreshold: payload.eliseThreshold,\n custom: true,\n aggressiveOn: 'soft',\n targetLoad: 0.65,\n });\n if (operation.ok) await store.save().catch(() => undefined);\n result(ws, operation.ok, operation.error ?? `Mode \"${payload.id}\" created`);\n },\n updateContextMode: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.mode.update')) return;\n const parsed = validateContextModeUpdatePayload(msg.payload);\n if (!parsed.ok) {\n result(ws, false, parsed.message);\n return;\n }\n const payload = parsed.value;\n const store = await modeStore();\n const operation = store.update(payload.id, {\n ...(payload.name !== undefined ? { name: payload.name } : {}),\n ...(payload.description !== undefined ? { description: payload.description } : {}),\n ...(payload.thresholds\n ? {\n thresholds: {\n warn: payload.thresholds.warn ?? 0.6,\n soft: payload.thresholds.soft ?? 0.75,\n hard: payload.thresholds.hard ?? 0.9,\n },\n }\n : {}),\n ...(payload.preserveK !== undefined ? { preserveK: payload.preserveK } : {}),\n ...(payload.eliseThreshold !== undefined ? { eliseThreshold: payload.eliseThreshold } : {}),\n });\n if (operation.ok) await store.save().catch(() => undefined);\n result(ws, operation.ok, operation.error ?? `Mode \"${payload.id}\" updated`);\n },\n deleteContextMode: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'context.mode.delete')) return;\n const parsed = validateContextModeDeletePayload(msg.payload);\n if (!parsed.ok) {\n result(ws, false, parsed.message);\n return;\n }\n const { id } = parsed.value;\n if (String(ctx.context.meta['contextWindowMode'] ?? '') === id) {\n ctx.context.meta['contextWindowMode'] = DEFAULT_CONTEXT_WINDOW_MODE_ID;\n ctx.context.meta['contextWindowPolicy'] = resolveContextWindowPolicy(\n {},\n DEFAULT_CONTEXT_WINDOW_MODE_ID,\n );\n }\n const store = await modeStore();\n const operation = store.remove(id);\n if (operation.ok) await store.save().catch(() => undefined);\n result(ws, operation.ok, operation.error ?? `Mode \"${id}\" deleted`);\n },\n listSessions: async (ws, msg) => {\n const limit = (msg as { payload?: { limit?: number | undefined } }).payload?.limit ?? 50;\n try {\n const list = await ctx.getSessionStore().list(limit);\n const currentId = ctx.getSession().id;\n sendTo(ws, {\n type: 'sessions.list',\n payload: {\n sessions: toSessionHistoryEntries(list, currentId),\n },\n });\n } catch (err) {\n sendTo(ws, { type: 'sessions.list', payload: { sessions: [], error: errMessage(err) } });\n }\n },\n deleteSession: async (ws, msg) => {\n const { id } = (msg as { payload: { id: string } }).payload;\n try {\n if (id === ctx.getSession().id) {\n result(ws, false, 'Cannot delete the active session');\n return;\n }\n const store = ctx.getSessionStore();\n await store.delete(id);\n result(ws, true, `Session ${id} deleted`);\n try {\n const list = await store.list(200);\n broadcastToAll({\n type: 'sessions.list',\n payload: { sessions: toSessionHistoryEntries(list, ctx.getSession().id) },\n });\n } catch {\n // The delete succeeded; a transient refresh failure must not reverse its result.\n }\n } catch (err) {\n result(ws, false, errMessage(err));\n }\n },\n renameSession: async (ws, msg) => {\n const payload = (msg as { payload?: { id?: unknown; name?: unknown } }).payload ?? {};\n const id = typeof payload.id === 'string' ? payload.id : '';\n const name = typeof payload.name === 'string' ? payload.name : '';\n if (!id) {\n result(ws, false, 'Session id is required');\n return;\n }\n try {\n await ctx.getSessionStore().rename(id, name);\n result(ws, true, name ? `Renamed session to \"${name}\"` : `Cleared session name`);\n // Broadcast the refreshed list so every open WebUI reflects the new name.\n try {\n const list = await ctx.getSessionStore().list(200);\n const currentId = ctx.getSession().id;\n broadcastToAll({\n type: 'sessions.list',\n payload: {\n sessions: toSessionHistoryEntries(list, currentId),\n },\n });\n } catch {\n // The rename succeeded; keep the optimistic name and allow manual refresh.\n }\n } catch (err) {\n result(ws, false, errMessage(err));\n }\n },\n resumeSession: (ws, msg) =>\n serializeSessionTransition(async () => {\n const { id } = (msg as { payload: { id: string } }).payload;\n if (ctx.canSwapSessions?.() === false) {\n result(ws, false, 'Session store not available');\n return;\n }\n let rollbackClaim: (() => Promise<void>) | undefined;\n let activated = false;\n try {\n const current = ctx.getSession();\n const store = ctx.getSessionStore();\n const canonicalId = store.resolveId ? await store.resolveId(id) : id;\n if (canonicalId === current.id) {\n result(ws, false, 'Session is already active');\n return;\n }\n rollbackClaim = await ctx.claimSession?.(canonicalId);\n const resumed = await store.resume(canonicalId);\n // Restore the resumed session's todo board from its sidecar so the\n // panel isn't wiped on resume (parity with the boot `--resume` path).\n const restoredTodos =\n (await loadTodosCheckpoint(\n sessionScopedPath(sessionsDirectory(), resumed.writer.id, '.todos.json'),\n ctx.events,\n ctx.context.traceId,\n resumed.writer.id,\n ).catch(() => null)) ?? [];\n activated = true;\n await activateSession(\n resumed.writer,\n resumed.data.messages,\n resumed.data.usage,\n restoredTodos,\n );\n broadcastToAll({\n type: 'session.start',\n payload: await ctx.sessionStartPayload({\n reset: true,\n // Same builder the connect path uses, so a resume and a reconnect\n // hand the client an identical transcript (markers included).\n ...buildReplayPayload({\n messages: resumed.data.messages,\n events: resumed.data.events,\n usage: resumed.data.usage,\n }),\n }),\n });\n // The client resets todos to [] on session.start(reset); push the\n // restored board AFTER so the panel repopulates.\n broadcastToAll({\n type: 'todos.updated',\n payload: { sessionId: resumed.writer.id, todos: restoredTodos },\n });\n result(ws, true, `Resumed session ${id}`);\n } catch (err) {\n if (!activated) await rollbackClaim?.().catch(() => undefined);\n result(ws, false, errMessage(err));\n }\n }),\n saveSession: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'session.save')) return;\n result(ws, true, `Session ${ctx.getSession().id} is auto-saved`);\n },\n listCheckpoints: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'session.checkpoints')) return;\n try {\n const { DefaultSessionRewinder } = await import('@wrongstack/core/storage');\n const projectRoot = ctx.getProjectRoot();\n const rewinder = new DefaultSessionRewinder(sessionsDirectory(), projectRoot);\n const checkpoints = await rewinder.listCheckpoints(ctx.getSession().id);\n sendTo(ws, { type: 'session.checkpoints', payload: sessionPayload({ checkpoints }) });\n } catch {\n sendTo(ws, { type: 'session.checkpoints', payload: sessionPayload({ checkpoints: [] }) });\n }\n },\n rewindSession: async (ws, msg) => {\n if (!ensureCurrentSession(ws, msg, 'session.rewind')) return;\n const { checkpointIndex } = (msg as { payload: { checkpointIndex: number } }).payload;\n try {\n const { applyRewindToConversation, DefaultSessionRewinder } = await import(\n '@wrongstack/core/storage'\n );\n const projectRoot = ctx.getProjectRoot();\n const rewinder = new DefaultSessionRewinder(sessionsDirectory(), projectRoot);\n const reverted = await rewinder.rewindToCheckpoint(ctx.getSession().id, checkpointIndex);\n // Cut the live conversation too \u2014 sessionStartPayload() below replays\n // from ctx.context.state, so truncating only the JSONL would replay the\n // rewound turns straight back to the client and leave them in the\n // model's working set.\n await applyRewindToConversation({\n session: ctx.context.session,\n state: ctx.context.state,\n sessionsDir: sessionsDirectory(),\n promptIndex: checkpointIndex,\n revertedFiles: reverted.revertedFiles,\n });\n result(ws, true, `Rewound to checkpoint ${checkpointIndex}`);\n broadcastToAll({\n type: 'session.start',\n payload: await ctx.sessionStartPayload({ reset: true }),\n });\n } catch (err) {\n result(ws, false, errMessage(err));\n }\n },\n };\n}\n", "export type SurfaceConnectionPhase = 'idle' | 'connecting' | 'open' | 'reconnecting' | 'closed';\n\nexport interface SurfaceConnectionConfig {\n maxReconnectAttempts: number;\n initialBackoffMs: number;\n maxBackoffMs: number;\n backoffMultiplier: number;\n jitterRatio: number;\n queueLimit: number;\n heartbeatIntervalMs: number;\n heartbeatTimeoutMs: number;\n}\n\nexport interface SurfaceConnectionState {\n phase: SurfaceConnectionPhase;\n reconnectAttempt: number;\n lastActivityAt: number | null;\n stopped: boolean;\n}\n\nexport interface ReconnectPlan {\n attempt: number;\n delayMs: number;\n retryAt: number;\n}\n\nexport const DEFAULT_SURFACE_CONNECTION_CONFIG: SurfaceConnectionConfig = {\n maxReconnectAttempts: 10,\n initialBackoffMs: 1_000,\n maxBackoffMs: 30_000,\n backoffMultiplier: 2,\n jitterRatio: 0,\n queueLimit: 1_000,\n heartbeatIntervalMs: 0,\n heartbeatTimeoutMs: 0,\n};\n\nexport function createSurfaceConnectionState(): SurfaceConnectionState {\n return { phase: 'idle', reconnectAttempt: 0, lastActivityAt: null, stopped: false };\n}\n\nexport function markConnectionConnecting(state: SurfaceConnectionState): SurfaceConnectionState {\n if (state.stopped) return state;\n return { ...state, phase: 'connecting' };\n}\n\nexport function markConnectionOpen(\n state: SurfaceConnectionState,\n now = Date.now(),\n): SurfaceConnectionState {\n return {\n ...state,\n phase: 'open',\n reconnectAttempt: 0,\n lastActivityAt: now,\n stopped: false,\n };\n}\n\nexport function markConnectionActivity(\n state: SurfaceConnectionState,\n now = Date.now(),\n): SurfaceConnectionState {\n return { ...state, lastActivityAt: now };\n}\n\nexport function stopConnection(state: SurfaceConnectionState): SurfaceConnectionState {\n return { ...state, phase: 'closed', stopped: true };\n}\n\nexport function resetConnection(state: SurfaceConnectionState): SurfaceConnectionState {\n return { ...state, phase: 'idle', reconnectAttempt: 0, stopped: false };\n}\n\nexport function planConnectionReconnect(\n state: SurfaceConnectionState,\n config: SurfaceConnectionConfig,\n now = Date.now(),\n random = Math.random,\n): { state: SurfaceConnectionState; plan: ReconnectPlan | null } {\n if (state.stopped || state.reconnectAttempt >= config.maxReconnectAttempts) {\n return { state: { ...state, phase: 'closed' }, plan: null };\n }\n const attempt = state.reconnectAttempt + 1;\n const base = Math.min(\n config.initialBackoffMs * config.backoffMultiplier ** (attempt - 1),\n config.maxBackoffMs,\n );\n const centeredJitter = (random() * 2 - 1) * config.jitterRatio;\n const delayMs = Math.max(0, Math.round(base * (1 + centeredJitter)));\n return {\n state: { ...state, phase: 'reconnecting', reconnectAttempt: attempt },\n plan: { attempt, delayMs, retryAt: now + delayMs },\n };\n}\n\nexport function isConnectionHeartbeatTimedOut(\n state: SurfaceConnectionState,\n config: SurfaceConnectionConfig,\n now = Date.now(),\n): boolean {\n if (state.phase !== 'open' || state.lastActivityAt === null) return false;\n if (config.heartbeatIntervalMs <= 0) return false;\n return now - state.lastActivityAt > config.heartbeatIntervalMs + config.heartbeatTimeoutMs;\n}\n\nexport function enqueueBounded<T>(\n queue: readonly T[],\n item: T,\n limit: number,\n): { queue: T[]; dropped: T | null } {\n if (limit <= 0) return { queue: [], dropped: item };\n if (queue.length < limit) return { queue: [...queue, item], dropped: null };\n return { queue: [...queue.slice(queue.length - limit + 1), item], dropped: queue[0] ?? null };\n}\n", "export const CLIENT_CONVERSATION_MESSAGE_TYPES = [\n 'abort',\n 'ping',\n 'user_message',\n 'tool.confirm_result',\n 'completion.request',\n 'model.switch',\n 'model.refine',\n 'autonomy.switch',\n 'context.clear',\n 'context.compact',\n 'context.debug',\n 'context.editor.open',\n 'context.editor.validate',\n 'context.editor.apply',\n 'context.mode.create',\n 'context.mode.delete',\n 'context.mode.switch',\n 'context.mode.update',\n 'context.modes.list',\n 'context.repair',\n 'mode.switch',\n 'modes.list',\n 'session.checkpoints',\n 'session.delete',\n 'session.new',\n 'session.rename',\n 'session.resume',\n 'session.rewind',\n 'session.save',\n 'sessions.list',\n 'side_effects.list',\n 'stats.get',\n 'todo.update',\n 'todos.clear',\n 'todos.get',\n 'todos.remove',\n] as const;\n\nexport const CLIENT_COLLABORATION_MESSAGE_TYPES = [\n 'collab.join',\n 'collab.leave',\n 'collab.annotate',\n 'collab.resolve',\n 'collab.request_pause',\n 'collab.resume',\n 'collab.grant_control',\n 'collab.inject_tool',\n 'mailbox.action',\n 'mailbox.agents',\n 'mailbox.clear',\n 'mailbox.compact',\n 'mailbox.messages',\n 'mailbox.purge',\n 'mailbox.send',\n] as const;\n", "export const CLIENT_KNOWLEDGE_MESSAGE_TYPES = [\n 'brain.ask',\n 'brain.config.get',\n 'brain.config.set',\n 'brain.risk',\n 'brain.status',\n 'chronicle.facet',\n 'chronicle.facets',\n 'chronicle.graph',\n 'chronicle.metrics',\n 'chronicle.query',\n 'chronicle.status',\n 'config.doctor',\n 'design.list',\n 'design.materialize',\n 'design.set',\n 'design.state',\n 'design.swap',\n 'design.tune',\n 'design.use',\n 'design.verify',\n 'memory.list',\n 'memory.sage.backfillRecoverable',\n 'memory.sage.candidateResolve',\n 'memory.sage.delete',\n 'memory.sage.forFile',\n 'memory.sage.get',\n 'memory.sage.graph',\n 'memory.sage.list',\n 'memory.sage.listPage',\n 'memory.sage.recover',\n 'memory.sage.remember',\n 'memory.sage.update',\n] as const;\n\nexport const CLIENT_EXTENSION_MESSAGE_TYPES = [\n 'auth.oauth.cancel',\n 'auth.oauth.code',\n 'auth.oauth.start',\n 'mcp.add',\n 'mcp.disable',\n 'mcp.discover',\n 'mcp.enable',\n 'mcp.list',\n 'mcp.prompt.get',\n 'mcp.prompts',\n 'mcp.remove',\n 'mcp.resource.read',\n 'mcp.resources',\n 'mcp.restart',\n 'mcp.sleep',\n 'mcp.update',\n 'mcp.wake',\n 'prompts.content',\n 'prompts.create',\n 'prompts.favorite',\n 'prompts.list',\n 'prompts.recent',\n 'prompts.search',\n 'prompts.used',\n 'skills.content',\n 'skills.create',\n 'skills.edit',\n 'skills.export',\n 'skills.install',\n 'skills.list',\n 'skills.uninstall',\n 'skills.update',\n] as const;\n", "export const CLIENT_GOAL_MESSAGE_TYPES = [\n 'goal-state.get',\n 'goal.addTask',\n 'goal.assess',\n 'goal.assignTask',\n 'goal.clear',\n 'goal.get',\n 'goal.list',\n 'goal.load',\n 'goal.moveTask',\n 'goal.pause',\n 'goal.resume',\n 'goal.retryTask',\n 'goal.revert',\n 'goal.runTask',\n 'goal.save',\n 'goal.selectPhase',\n 'goal.start',\n 'goal.state',\n 'goal.status',\n 'goal.stop',\n 'goal.taskStatus',\n 'goal.toggleAutonomous',\n 'plan.get',\n 'plan.item.update',\n 'plan.template_use',\n 'task.update',\n 'tasks.get',\n] as const;\n\nexport const CLIENT_SDD_MESSAGE_TYPES = [\n 'sdd.board.cancel_task',\n 'sdd.board.cleanup_worktrees',\n 'sdd.board.delete_task',\n 'sdd.board.destroy',\n 'sdd.board.get',\n 'sdd.board.list',\n 'sdd.board.pause',\n 'sdd.board.reassign',\n 'sdd.board.resume',\n 'sdd.board.retry',\n 'sdd.board.retry_all_failed',\n 'sdd.board.rollback',\n 'sdd.board.set_task_fallbacks',\n 'sdd.board.set_task_model',\n 'sdd.board.set_task_verification',\n 'sdd.board.split_task',\n 'sdd.board.stop',\n 'sdd.run.from_graph',\n 'sdd.run.from_spec',\n 'sdd.run.start',\n 'sdd.spec.approve',\n 'sdd.spec.discard',\n 'sdd.spec.get',\n 'sdd.spec.message',\n 'sdd.spec.start',\n 'specs.get',\n 'specs.list',\n 'specs.taskStatus',\n] as const;\n", "export const CLIENT_WORKSPACE_MESSAGE_TYPES = [\n 'files.list',\n 'files.read',\n 'files.tree',\n 'files.write',\n 'git.changes',\n 'git.diff',\n 'git.info',\n 'projects.add',\n 'projects.list',\n 'projects.select',\n 'working_dir.set',\n 'worktree.cleanup',\n 'worktree.diff',\n 'worktree.merge',\n 'worktree.remove',\n 'worktree.scan',\n 'shell.open',\n 'process.kill',\n 'process.killAll',\n 'process.list',\n 'terminal.close',\n 'terminal.create',\n 'terminal.input',\n 'terminal.resize',\n] as const;\n\nexport const CLIENT_CONFIGURATION_MESSAGE_TYPES = [\n 'codebase.index.server.shutdown',\n 'connections.health',\n 'connections.service_action',\n 'diag.get',\n 'key.add',\n 'key.delete',\n 'key.set_active',\n 'key.update',\n 'prefs.get',\n 'prefs.update',\n 'provider.add',\n 'provider.clear_models',\n 'provider.models',\n 'provider.models.search',\n 'provider.probe',\n 'provider.remove',\n 'provider.status.clear',\n 'provider.status.get',\n 'provider.status.retry',\n 'provider.undo_clear',\n 'provider.update',\n 'providers.list',\n 'providers.saved',\n 'tool.disable',\n 'tool.enable',\n 'tools.list',\n 'webui.shutdown',\n] as const;\n", "export const SERVER_CONVERSATION_MESSAGE_TYPES = [\n 'error',\n 'log',\n 'pong',\n 'side_effects',\n 'agent.status_changed',\n 'agent.timeline.message',\n 'client.status_update',\n 'compaction.failed',\n 'completion.result',\n 'context.compacted',\n 'context.debug',\n 'context.editor.snapshot',\n 'context.editor.validation',\n 'context.editor.applied',\n 'context.mode.changed',\n 'context.modes.list',\n 'context.repaired',\n 'ctx.max_context',\n 'ctx.pct',\n 'delegate.completed',\n 'delegate.started',\n 'iteration.completed',\n 'iteration.limit_reached',\n 'iteration.started',\n 'model.refine_result',\n 'modes.list',\n 'provider.active_blocked',\n 'provider.error',\n 'provider.fallback',\n 'provider.response',\n 'provider.retry',\n 'provider.status_changed',\n 'provider.stream_error',\n 'provider.text_delta',\n 'provider.thinking_delta',\n 'run.result',\n 'session.checkpoints',\n 'session.damaged',\n 'session.end',\n 'session.rewound',\n 'session.start',\n 'session.stats',\n 'sessions.list',\n 'sessions.status_update',\n 'stats.get',\n 'token.cost_estimate_unavailable',\n 'token.threshold',\n 'tool.confirm_needed',\n 'tool.disabled',\n 'tool.enabled',\n 'tool.executed',\n 'tool.loop_detected',\n 'tool.progress',\n 'tool.started',\n 'tools.list',\n 'trust.persisted',\n] as const;\n\nexport const SERVER_COLLABORATION_MESSAGE_TYPES = [\n 'collab.annotation.added',\n 'collab.annotation.resolved',\n 'collab.event',\n 'collab.injection.granted',\n 'collab.participant.joined',\n 'collab.participant.left',\n 'collab.pause.granted',\n 'collab.pause.released',\n 'collab.state',\n 'mailbox.action_result',\n 'mailbox.agent_registered',\n 'mailbox.agents',\n 'mailbox.cleared',\n 'mailbox.compacted',\n 'mailbox.event',\n 'mailbox.messages',\n 'mailbox.sent',\n 'mailbox.purged',\n 'mailbox.received',\n 'subagent.budget_extended',\n 'subagent.event',\n] as const;\n", "export const SERVER_KNOWLEDGE_MESSAGE_TYPES = [\n 'brain.answer',\n 'brain.config',\n 'brain.event',\n 'brain.status',\n 'chronicle.error',\n 'chronicle.facet_result',\n 'chronicle.facets_result',\n 'chronicle.graph_result',\n 'chronicle.metrics_result',\n 'chronicle.query_result',\n 'chronicle.status_result',\n 'config.doctor.result',\n 'design.list',\n 'design.materialize',\n 'design.set',\n 'design.state',\n 'design.swap',\n 'design.tune',\n 'design.use',\n 'design.verify',\n 'memory.event',\n 'memory.list',\n 'memory.sage.backfillRecoverable',\n 'memory.sage.candidateResolve',\n 'memory.sage.delete',\n 'memory.sage.forFile',\n 'memory.sage.get',\n 'memory.sage.graph',\n 'memory.sage.list',\n 'memory.sage.listPage',\n 'memory.sage.recover',\n 'memory.sage.remember',\n 'memory.sage.update',\n] as const;\n\nexport const SERVER_EXTENSION_MESSAGE_TYPES = [\n 'mcp.content.error',\n 'mcp.content.selected',\n 'mcp.list',\n 'mcp.operation_result',\n 'mcp.prompts',\n 'mcp.resources',\n 'mcp.server.added',\n 'mcp.server.connected',\n 'mcp.server.disconnected',\n 'mcp.server.discovered',\n 'mcp.server.error',\n 'mcp.server.reconnected',\n 'mcp.server.removed',\n 'mcp.server.sleeping',\n 'mcp.server.updated',\n 'mcp.server.waking',\n 'prompts.content',\n 'prompts.created',\n 'prompts.favorite',\n 'prompts.list',\n 'prompts.recent',\n 'prompts.search',\n 'prompts.used',\n 'skills.content',\n 'skills.created',\n 'skills.edited',\n 'skills.exported',\n 'skills.installed',\n 'skills.list',\n 'skills.uninstalled',\n 'skills.updated',\n] as const;\n", "export const SERVER_GOAL_MESSAGE_TYPES = [\n 'budget.decision',\n 'budget.threshold_reached',\n 'coordinator.stats',\n 'coordinator.status',\n 'eternal.iteration',\n 'fleet.concurrency_update',\n 'goal-state.updated',\n 'goal.assess.result',\n 'goal.list',\n 'goal.paused',\n 'goal.resumed',\n 'goal.saved',\n 'goal.error',\n 'goal.stopped',\n 'goal.failed',\n 'goal.completed',\n 'goal.cleared',\n 'goal.reverted',\n 'goal.progress',\n 'goal.state',\n 'in_flight.ended',\n 'in_flight.started',\n 'plan.updated',\n 'task.completed',\n 'task.failed',\n 'task.pending',\n 'task.started',\n 'tasks.updated',\n 'todos.cleared',\n 'todos.updated',\n] as const;\n\nexport const SERVER_SDD_MESSAGE_TYPES = [\n 'kanban.task.activity',\n 'sdd.board.lifecycle_result',\n 'sdd.board.list',\n 'sdd.board.snapshot',\n 'sdd.run.started',\n 'sdd.spec.agent_text',\n 'sdd.spec.error',\n 'sdd.spec.snapshot',\n 'specs.detail',\n 'specs.list',\n] as const;\n\nexport const SERVER_AUTOMATION_MESSAGE_TYPES = [\n 'consensus.vote_cast',\n 'consensus.vote_initiated',\n 'consensus.vote_resolved',\n 'cron.job_fired',\n 'cron.snapshot',\n 'techstack.job.cancelled',\n 'techstack.job.failed',\n 'techstack.job.progress',\n 'techstack.job.started',\n 'techstack.report.delivered',\n 'techstack.report.ready',\n 'techstack.snapshot.updated',\n 'techstack.workspace.completed',\n] as const;\n", "export const SERVER_WORKSPACE_MESSAGE_TYPES = [\n 'checkpoint.written',\n 'codemap.file_event',\n 'codemap.index_updated',\n 'codemap.tool_executed',\n 'codemap.tool_started',\n 'file.saved',\n 'files.list',\n 'files.read',\n 'files.tree',\n 'files.written',\n 'git.changes',\n 'git.diff',\n 'git.info',\n 'process.list',\n 'projects.added',\n 'projects.list',\n 'projects.selected',\n 'terminal.exit',\n 'terminal.output',\n 'working_dir.changed',\n 'worktree.cleanup_result',\n 'worktree.diff_result',\n 'worktree.event',\n 'worktree.merge_result',\n 'worktree.orphans',\n 'worktree.state',\n] as const;\n\nexport const SERVER_CONFIGURATION_MESSAGE_TYPES = [\n 'auth.oauth.status',\n 'codebase.index.server.shutdown_result',\n 'connections.health_error',\n 'connections.health_result',\n 'connections.service_action_result',\n 'diag.get',\n 'key.operation_result',\n 'model.switch_result',\n 'prefs.updated',\n 'provider.catalog',\n 'provider.models',\n 'provider.models.search_result',\n 'provider.probe',\n 'provider.status.snapshot',\n 'providers.saved',\n] as const;\n", "import {\n CLIENT_COLLABORATION_MESSAGE_TYPES,\n CLIENT_CONVERSATION_MESSAGE_TYPES,\n} from './client-conversation.js';\nimport {\n CLIENT_EXTENSION_MESSAGE_TYPES,\n CLIENT_KNOWLEDGE_MESSAGE_TYPES,\n} from './client-integrations.js';\nimport { CLIENT_GOAL_MESSAGE_TYPES, CLIENT_SDD_MESSAGE_TYPES } from './client-operations.js';\nimport {\n CLIENT_CONFIGURATION_MESSAGE_TYPES,\n CLIENT_WORKSPACE_MESSAGE_TYPES,\n} from './client-workspace.js';\nimport {\n SERVER_COLLABORATION_MESSAGE_TYPES,\n SERVER_CONVERSATION_MESSAGE_TYPES,\n} from './server-conversation.js';\nimport {\n SERVER_EXTENSION_MESSAGE_TYPES,\n SERVER_KNOWLEDGE_MESSAGE_TYPES,\n} from './server-integrations.js';\nimport {\n SERVER_AUTOMATION_MESSAGE_TYPES,\n SERVER_GOAL_MESSAGE_TYPES,\n SERVER_SDD_MESSAGE_TYPES,\n} from './server-operations.js';\nimport {\n SERVER_CONFIGURATION_MESSAGE_TYPES,\n SERVER_WORKSPACE_MESSAGE_TYPES,\n} from './server-workspace.js';\n\nexport const CLIENT_MESSAGE_TYPES = [\n ...CLIENT_CONVERSATION_MESSAGE_TYPES,\n ...CLIENT_COLLABORATION_MESSAGE_TYPES,\n ...CLIENT_WORKSPACE_MESSAGE_TYPES,\n ...CLIENT_CONFIGURATION_MESSAGE_TYPES,\n ...CLIENT_GOAL_MESSAGE_TYPES,\n ...CLIENT_SDD_MESSAGE_TYPES,\n ...CLIENT_KNOWLEDGE_MESSAGE_TYPES,\n ...CLIENT_EXTENSION_MESSAGE_TYPES,\n] as const;\n\nexport const SERVER_MESSAGE_TYPES = [\n ...SERVER_CONVERSATION_MESSAGE_TYPES,\n ...SERVER_COLLABORATION_MESSAGE_TYPES,\n ...SERVER_WORKSPACE_MESSAGE_TYPES,\n ...SERVER_CONFIGURATION_MESSAGE_TYPES,\n ...SERVER_GOAL_MESSAGE_TYPES,\n ...SERVER_SDD_MESSAGE_TYPES,\n ...SERVER_AUTOMATION_MESSAGE_TYPES,\n ...SERVER_KNOWLEDGE_MESSAGE_TYPES,\n ...SERVER_EXTENSION_MESSAGE_TYPES,\n] as const;\n\nexport type ExactClientMessageType = (typeof CLIENT_MESSAGE_TYPES)[number];\nexport type ExactServerMessageType = (typeof SERVER_MESSAGE_TYPES)[number];\n\nconst CLIENT_TYPE_SET: ReadonlySet<string> = new Set(CLIENT_MESSAGE_TYPES);\nconst SERVER_TYPE_SET: ReadonlySet<string> = new Set(SERVER_MESSAGE_TYPES);\n\nexport function isRegisteredMessageType(type: string, direction: 'client' | 'server'): boolean {\n const exact = direction === 'client' ? CLIENT_TYPE_SET : SERVER_TYPE_SET;\n return (\n exact.has(type) ||\n (type.startsWith('kanban.') && type.length > 'kanban.'.length) ||\n (type.startsWith('agent-roster.') && type.length > 'agent-roster.'.length)\n );\n}\n", "import { isRegisteredMessageType } from './registry.js';\nimport type {\n CanonicalClientMessage,\n CanonicalServerMessage,\n ProtocolDecodeIssue,\n ProtocolDecodeResult,\n ProtocolDirection,\n ProtocolEnvelope,\n} from './types.js';\n\nconst FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);\nconst MAX_PAYLOAD_DEPTH = 32;\n\nfunction inspectValue(value: unknown, path: string, depth: number): ProtocolDecodeIssue | null {\n if (depth > MAX_PAYLOAD_DEPTH) {\n return { code: 'too_deep', message: 'Protocol payload exceeds the nesting limit', path };\n }\n if (value === null || typeof value !== 'object') return null;\n\n for (const key of Object.keys(value)) {\n const childPath = `${path}.${key}`;\n if (FORBIDDEN_KEYS.has(key)) {\n return { code: 'unsafe_key', message: `Unsafe protocol key: ${key}`, path: childPath };\n }\n const issue = inspectValue((value as Record<string, unknown>)[key], childPath, depth + 1);\n if (issue) return issue;\n }\n return null;\n}\n\nexport function decodeProtocolMessage(\n input: unknown,\n direction: 'client',\n): ProtocolDecodeResult<CanonicalClientMessage>;\nexport function decodeProtocolMessage(\n input: unknown,\n direction: 'server',\n): ProtocolDecodeResult<CanonicalServerMessage>;\nexport function decodeProtocolMessage(\n input: unknown,\n direction: ProtocolDirection,\n): ProtocolDecodeResult<ProtocolEnvelope> {\n if (input === null || typeof input !== 'object' || Array.isArray(input)) {\n return {\n ok: false,\n issue: { code: 'invalid_envelope', message: 'Protocol message must be an object' },\n };\n }\n\n const envelope = input as Record<string, unknown>;\n if (typeof envelope['type'] !== 'string' || envelope['type'].length === 0) {\n return {\n ok: false,\n issue: { code: 'invalid_type', message: 'Protocol message type must be a non-empty string' },\n };\n }\n if (!isRegisteredMessageType(envelope['type'], direction)) {\n return {\n ok: false,\n issue: { code: 'unknown_type', message: `Unknown ${direction} message: ${envelope['type']}` },\n };\n }\n if (direction === 'server' && !Object.hasOwn(envelope, 'payload')) {\n return {\n ok: false,\n issue: { code: 'invalid_envelope', message: 'Server protocol messages require a payload' },\n };\n }\n\n const issue = inspectValue(envelope, '$', 0);\n if (issue) return { ok: false, issue };\n return { ok: true, message: input as ProtocolEnvelope };\n}\n\nexport function decodeProtocolFrame(\n frame: string,\n direction: 'client',\n): ProtocolDecodeResult<CanonicalClientMessage>;\nexport function decodeProtocolFrame(\n frame: string,\n direction: 'server',\n): ProtocolDecodeResult<CanonicalServerMessage>;\nexport function decodeProtocolFrame(\n frame: string,\n direction: ProtocolDirection,\n): ProtocolDecodeResult<ProtocolEnvelope> {\n try {\n return decodeProtocolMessage(JSON.parse(frame), direction as 'client');\n } catch {\n return {\n ok: false,\n issue: { code: 'invalid_envelope', message: 'Protocol frame is not valid JSON' },\n };\n }\n}\n", "import type { HqAlertMessage, HqCommandAuditEntry, HqEventEnvelope, HqSnapshot } from '@wrongstack/core/hq';\nimport type { ProtocolEnvelope } from './types.js';\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction text(value: unknown, fallback = ''): string {\n return typeof value === 'string' ? value : fallback;\n}\n\nfunction finite(value: unknown, fallback = 0): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback;\n}\n\n/** When a key is present it must be an array; when absent it is acceptable. */\nfunction optionalArray(value: unknown): boolean {\n return value === undefined || Array.isArray(value);\n}\n\n/** Validate that all required numeric fields of a totals object are finite. */\nfunction isValidHqTotals(totals: Record<string, unknown>): boolean {\n return (\n finite(totals['activeProjects']) === totals['activeProjects'] &&\n finite(totals['activeClients']) === totals['activeClients'] &&\n finite(totals['activeSessions']) === totals['activeSessions'] &&\n finite(totals['activeSubagents']) === totals['activeSubagents'] &&\n finite(totals['unreadMailboxMessages']) === totals['unreadMailboxMessages'] &&\n finite(totals['incompleteMailboxMessages']) === totals['incompleteMailboxMessages'] &&\n finite(totals['totalCostUsd']) === totals['totalCostUsd']\n );\n}\n\nexport interface SessionProjection {\n kind: 'session';\n id: string;\n provider: string;\n model: string;\n projectName: string;\n cwd: string;\n maxContext: number;\n reset: boolean;\n replayMessages: unknown[] | null;\n /** Audit markers replayed alongside the conversation. */\n replayMarkers: unknown[] | null;\n replayUsage: Record<string, unknown> | null;\n}\n\nexport function projectSessionMessage(message: ProtocolEnvelope): SessionProjection | null {\n if (message.type !== 'session.start') return null;\n const payload = record(message.payload);\n if (!payload) return null;\n return {\n kind: 'session',\n id: text(payload['sessionId']),\n provider: text(payload['provider']),\n model: text(payload['model']),\n projectName: text(payload['projectName'], 'Project'),\n cwd: text(payload['cwd']),\n maxContext: finite(payload['maxContext']),\n reset: payload['reset'] === true,\n replayMessages: Array.isArray(payload['replayMessages']) ? payload['replayMessages'] : null,\n replayMarkers: Array.isArray(payload['replayMarkers']) ? payload['replayMarkers'] : null,\n replayUsage: record(payload['replayUsage']),\n };\n}\n\nexport type ChatProjection =\n | { kind: 'thinking-delta'; text: string }\n | { kind: 'text-delta'; text: string; messageId: string }\n /** `stopReason` distinguishes the turn's final response from a mid-turn one\n * that stopped to call a tool \u2014 surfaces gate `<nextsteps>` on it. */\n | { kind: 'response'; content: unknown; stopReason: string }\n | { kind: 'run-result'; status: string; iterations: number; finalText?: string | undefined }\n | { kind: 'error'; message: string };\n\nexport function projectChatMessage(message: ProtocolEnvelope): ChatProjection | null {\n const payload = record(message.payload);\n if (!payload) return null;\n switch (message.type) {\n case 'provider.thinking_delta': {\n const value = text(payload['text']);\n return value ? { kind: 'thinking-delta', text: value } : null;\n }\n case 'provider.text_delta': {\n const value = text(payload['text']);\n return value\n ? { kind: 'text-delta', text: value, messageId: text(payload['messageId']) }\n : null;\n }\n case 'provider.response':\n return {\n kind: 'response',\n content: payload['content'],\n stopReason: text(payload['stopReason']),\n };\n case 'run.result':\n return {\n kind: 'run-result',\n status: text(payload['status']),\n iterations: finite(payload['iterations'], 1),\n ...(typeof payload['finalText'] === 'string' ? { finalText: payload['finalText'] } : {}),\n };\n case 'error':\n return { kind: 'error', message: text(payload['message'], 'Run failed') };\n default:\n return null;\n }\n}\n\nexport type ToolProjection =\n | { kind: 'started'; id: string; name: string; input: unknown; messageId: string }\n | { kind: 'progress'; id: string; name: string; eventType: string; text: string }\n | {\n kind: 'executed';\n id: string;\n name: string;\n ok: boolean;\n output?: string | undefined;\n /**\n * SAGE Memory Injector block (header line first) split off the tool text\n * at the emit site. Clients render it as a memory card \u2014 it must never be\n * concatenated back into `output`.\n */\n sage?: string[] | undefined;\n durationMs: number;\n };\n\nexport function projectToolMessage(message: ProtocolEnvelope): ToolProjection | null {\n const payload = record(message.payload);\n if (!payload) return null;\n if (message.type === 'tool.started') {\n const name = text(payload['name'], 'tool');\n return {\n kind: 'started',\n id: text(payload['id'], name),\n name,\n input: payload['input'],\n messageId: text(payload['messageId']),\n };\n }\n if (message.type === 'tool.progress') {\n const event = record(payload['event']);\n return {\n kind: 'progress',\n id: text(payload['id']),\n name: text(payload['name'], 'tool'),\n eventType: text(event?.['type']),\n text: text(event?.['text']).trim(),\n };\n }\n if (message.type === 'tool.executed') {\n return {\n kind: 'executed',\n id: text(payload['id']),\n name: text(payload['name']),\n ok: payload['ok'] !== false,\n durationMs: finite(payload['durationMs']),\n ...(typeof payload['output'] === 'string' ? { output: payload['output'] } : {}),\n ...(Array.isArray(payload['sage'])\n ? { sage: payload['sage'].filter((line): line is string => typeof line === 'string') }\n : {}),\n };\n }\n return null;\n}\n\nexport type FleetProjection =\n | { kind: 'concurrency'; active: number; maximum: number }\n | { kind: 'client-status'; status: Record<string, unknown> }\n | { kind: 'sessions'; sessions: unknown[] }\n | { kind: 'coordinator'; agents: Array<Record<string, unknown>> };\n\nexport function projectFleetMessage(message: ProtocolEnvelope): FleetProjection | null {\n const payload = record(message.payload);\n if (!payload) return null;\n switch (message.type) {\n case 'fleet.concurrency_update':\n return {\n kind: 'concurrency',\n active: finite(payload['fleetConcurrency']),\n maximum: finite(payload['fleetConcurrencyMax']),\n };\n case 'client.status_update':\n return { kind: 'client-status', status: payload };\n case 'sessions.status_update':\n return {\n kind: 'sessions',\n sessions: Array.isArray(payload['sessions']) ? payload['sessions'] : [],\n };\n case 'coordinator.stats':\n return {\n kind: 'coordinator',\n agents: Array.isArray(payload['subagentStatuses'])\n ? payload['subagentStatuses'].filter(\n (item): item is Record<string, unknown> => record(item) !== null,\n )\n : [],\n };\n default:\n return null;\n }\n}\n\nexport interface HqFleetProjection {\n kind: 'hq-snapshot';\n snapshot: HqSnapshot;\n}\n\n/**\n * Validate the stable outer shape of an HQ fleet snapshot before a browser\n * surface commits it to state. Domain-specific records remain owned by Core;\n * this boundary only rejects truncated or unrelated wire frames.\n */\nexport function projectHqFleetMessage(message: {\n type: string;\n snapshot?: unknown;\n}): HqFleetProjection | null {\n if (message.type !== 'hq.snapshot') return null;\n const snapshot = record(message.snapshot);\n const totals = snapshot ? record(snapshot['totals']) : null;\n if (\n !snapshot ||\n typeof snapshot['generatedAt'] !== 'string' ||\n !Array.isArray(snapshot['clients']) ||\n !Array.isArray(snapshot['projects']) ||\n !Array.isArray(snapshot['sessions']) ||\n !Array.isArray(snapshot['fleets']) ||\n !Array.isArray(snapshot['mailboxes']) ||\n !totals ||\n !isValidHqTotals(totals) ||\n !optionalArray(snapshot['machines']) ||\n !optionalArray(snapshot['liveSessions']) ||\n !optionalArray(snapshot['mcpServers'])\n ) {\n return null;\n }\n return { kind: 'hq-snapshot', snapshot: snapshot as unknown as HqSnapshot };\n}\n\n// \u2500\u2500 HQ sibling projections (event, alert, command_status) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n//\n// These mirrors of projectHqFleetMessage validate the outer envelope shape of\n// hq.event / hq.alert / hq.command_status frames before the browser surface\n// commits them to store state, closing the trust-boundary gap flagged in\n// review \u2014 every branch now passes through a projection, not just hq.snapshot.\n\nexport interface HqEventProjection {\n kind: 'hq-event';\n event: HqEventEnvelope;\n}\n\nexport function projectHqEventMessage(message: {\n type: string;\n event?: unknown;\n}): HqEventProjection | null {\n if (message.type !== 'hq.event') return null;\n const event = record(message.event);\n if (\n !event ||\n typeof event['id'] !== 'string' ||\n typeof event['type'] !== 'string' ||\n typeof event['timestamp'] !== 'string' ||\n typeof event['clientId'] !== 'string' ||\n typeof event['projectId'] !== 'string' ||\n typeof event['seq'] !== 'number'\n ) {\n return null;\n }\n return { kind: 'hq-event', event: event as unknown as HqEventEnvelope };\n}\n\nexport interface HqAlertProjection {\n kind: 'hq-alert';\n alert: HqAlertMessage;\n}\n\nexport function projectHqAlertMessage(message: {\n type: string;\n severity?: unknown;\n message?: unknown;\n timestamp?: unknown;\n}): HqAlertProjection | null {\n if (message.type !== 'hq.alert') return null;\n if (\n typeof message['severity'] !== 'string' ||\n !['info', 'warn', 'error'].includes(message['severity']) ||\n typeof message['message'] !== 'string' ||\n typeof message['timestamp'] !== 'string'\n ) {\n return null;\n }\n return { kind: 'hq-alert', alert: message as unknown as HqAlertMessage };\n}\n\nexport interface HqCommandStatusProjection {\n kind: 'hq-command-status';\n command: HqCommandAuditEntry;\n}\n\nexport function projectHqCommandStatusMessage(message: {\n type: string;\n command?: unknown;\n}): HqCommandStatusProjection | null {\n if (message.type !== 'hq.command_status') return null;\n const command = record(message.command);\n if (\n !command ||\n typeof command['commandId'] !== 'string' ||\n typeof command['type'] !== 'string' ||\n typeof command['clientId'] !== 'string' ||\n typeof command['enqueuedBy'] !== 'string' ||\n typeof command['enqueuedAt'] !== 'string' ||\n typeof command['status'] !== 'string' ||\n !['queued', 'delivered', 'acked'].includes(command['status'])\n ) {\n return null;\n }\n return { kind: 'hq-command-status', command: command as unknown as HqCommandAuditEntry };\n}\n", "/**\n * Replay payload assembly for `session.start`.\n *\n * Two servers build this frame \u2014 the standalone WebUI server and the\n * CLI-hosted bridge \u2014 and they had already drifted (one fell back to the live\n * in-memory conversation, the other did not; only one applied the message cap\n * consistently). Both now call this, so the wire shape has a single definition.\n *\n * `replayMarkers` carries audit markers (compaction, mode switch, skill\n * activation, subagent lifecycle, provider retries, truncation) that a live\n * client renders as they stream in. Without them a reconnect or a session\n * resume silently drops everything except the conversation, so the same\n * session reads differently before and after a reload. Only the *projected*\n * markers cross the wire \u2014 never the raw event stream \u2014 so a 50k-event session\n * still costs a few dozen short strings.\n */\nimport type { Message, SessionEvent, SessionMarker, Usage } from '@wrongstack/core/types';\n// Narrow subpath, not the `types` barrel: this module is the only value import\n// in `src/protocol/`, which the browser bundles pull in wholesale. Going\n// through the barrel reached `types/mode.ts` \u2192 `types/mode-prompts.ts` and\n// dragged `node:fs`/`node:path`/`node:url` into every UI build.\nimport { CHAT_MARKER_SOURCES, projectSessionMarkers } from '@wrongstack/core/types/session-markers';\n\n/**\n * Upper bound on replayed conversation messages. A very long session would\n * otherwise push a multi-megabyte frame on every connect; the full transcript\n * remains on disk and in the session store.\n */\nexport const REPLAY_MESSAGE_CAP = 2_000;\n\nexport interface ReplaySource {\n messages: readonly Message[];\n /** Raw JSONL events, when the caller loaded them. Markers are projected from these. */\n events?: readonly SessionEvent[] | undefined;\n usage?: Usage | undefined;\n}\n\nexport interface ReplayPayloadFields {\n replayMessages?: Message[] | undefined;\n replayMarkers?: SessionMarker[] | undefined;\n replayUsage?: Usage | undefined;\n}\n\n/**\n * Build the replay fields of a `session.start` payload. Fields are omitted\n * rather than sent empty, so an existing client's \"did the server send a\n * replay?\" checks keep working unchanged.\n */\nexport function buildReplayPayload(source: ReplaySource): ReplayPayloadFields {\n const out: ReplayPayloadFields = {};\n\n const messages = source.messages;\n if (messages.length > 0) {\n out.replayMessages =\n messages.length > REPLAY_MESSAGE_CAP\n ? messages.slice(-REPLAY_MESSAGE_CAP)\n : [...messages];\n }\n\n if (source.events && source.events.length > 0) {\n const markers = projectSessionMarkers(source.events, CHAT_MARKER_SOURCES);\n if (markers.length > 0) out.replayMarkers = markers;\n }\n\n const usage = source.usage;\n if (\n usage &&\n usage.input + usage.output + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0) > 0\n ) {\n out.replayUsage = {\n input: usage.input,\n output: usage.output,\n cacheRead: usage.cacheRead ?? 0,\n cacheWrite: usage.cacheWrite ?? 0,\n };\n }\n\n return out;\n}\n", "export const SURFACE_PROTOCOL_VERSION = 1 as const;\nexport const SURFACE_PROTOCOL_MIN_VERSION = 1 as const;\n\nexport const SURFACE_PROTOCOL_CAPABILITIES = [\n 'protocol.directional-decoder',\n 'protocol.recursive-key-safety',\n 'chronicle.query',\n 'chronicle.facet',\n 'chronicle.facets',\n 'chronicle.graph',\n 'chronicle.metrics',\n 'chronicle.status',\n 'connections.health',\n /** Interview resume/discard + lastAgentText/lastRunId continuity. */\n 'sdd.interview.continuity',\n /** Launch multi-agent runs from a graph id or resolved spec id. */\n 'sdd.run.from_graph',\n] as const;\n\nexport type SurfaceProtocolCapability = (typeof SURFACE_PROTOCOL_CAPABILITIES)[number];\n\nexport interface ProtocolAdvertisement {\n protocolVersion?: number | undefined;\n protocolCapabilities?: readonly string[] | undefined;\n}\n\nexport interface ProtocolNegotiation {\n compatible: boolean;\n legacyPeer: boolean;\n version: number;\n capabilities: SurfaceProtocolCapability[];\n}\n\nexport function protocolAdvertisement(): {\n protocolVersion: typeof SURFACE_PROTOCOL_VERSION;\n protocolCapabilities: SurfaceProtocolCapability[];\n} {\n return {\n protocolVersion: SURFACE_PROTOCOL_VERSION,\n protocolCapabilities: [...SURFACE_PROTOCOL_CAPABILITIES],\n };\n}\n\nexport function negotiateProtocol(peer: ProtocolAdvertisement): ProtocolNegotiation {\n const peerVersion = peer.protocolVersion;\n const legacyPeer = peerVersion === undefined;\n const version = legacyPeer\n ? SURFACE_PROTOCOL_VERSION\n : Math.min(peerVersion, SURFACE_PROTOCOL_VERSION);\n const compatible =\n legacyPeer || (Number.isInteger(peerVersion) && peerVersion >= SURFACE_PROTOCOL_MIN_VERSION);\n const advertised = new Set(peer.protocolCapabilities ?? []);\n return {\n compatible,\n legacyPeer,\n version,\n capabilities: SURFACE_PROTOCOL_CAPABILITIES.filter((item) => advertised.has(item)),\n };\n}\n", "import type { SessionSummary } from '@wrongstack/core/types';\n\n/**\n * Stable WebSocket projection for the WebUI history surfaces.\n *\n * Keep this mapping shared by the standalone and CLI-hosted WebUI servers so\n * an initial list, rename refresh, and delete refresh cannot silently expose\n * different session metadata.\n */\nexport interface SessionHistoryWireEntry {\n id: string;\n title: string;\n name?: string | undefined;\n startedAt: string;\n endedAt?: string | undefined;\n model: string;\n provider: string;\n tokenTotal: number;\n lastActivityAt?: string | undefined;\n messageCount?: number | undefined;\n lastUserMessage?: string | undefined;\n iterationCount?: number | undefined;\n toolCallCount?: number | undefined;\n toolErrorCount?: number | undefined;\n fileChangeCount?: number | undefined;\n toolBreakdown?: Record<string, number> | undefined;\n compactionCount?: number | undefined;\n outcome?: SessionSummary['outcome'];\n isCurrent: boolean;\n}\n\nexport function toSessionHistoryEntry(\n summary: SessionSummary,\n currentSessionId: string,\n): SessionHistoryWireEntry {\n return {\n id: summary.id,\n title: summary.title,\n ...(summary.name !== undefined ? { name: summary.name } : {}),\n startedAt: summary.startedAt,\n ...(summary.endedAt !== undefined ? { endedAt: summary.endedAt } : {}),\n model: summary.model,\n provider: summary.provider,\n tokenTotal: summary.tokenTotal,\n ...(summary.lastActivityAt !== undefined ? { lastActivityAt: summary.lastActivityAt } : {}),\n ...(summary.messageCount !== undefined ? { messageCount: summary.messageCount } : {}),\n ...(summary.lastUserMessage !== undefined ? { lastUserMessage: summary.lastUserMessage } : {}),\n ...(summary.iterationCount !== undefined ? { iterationCount: summary.iterationCount } : {}),\n ...(summary.toolCallCount !== undefined ? { toolCallCount: summary.toolCallCount } : {}),\n ...(summary.toolErrorCount !== undefined ? { toolErrorCount: summary.toolErrorCount } : {}),\n ...(summary.fileChangeCount !== undefined ? { fileChangeCount: summary.fileChangeCount } : {}),\n ...(summary.toolBreakdown !== undefined ? { toolBreakdown: summary.toolBreakdown } : {}),\n ...(summary.compactionCount !== undefined ? { compactionCount: summary.compactionCount } : {}),\n ...(summary.outcome !== undefined ? { outcome: summary.outcome } : {}),\n isCurrent: summary.id === currentSessionId,\n };\n}\n\nexport function toSessionHistoryEntries(\n summaries: SessionSummary[],\n currentSessionId: string,\n): SessionHistoryWireEntry[] {\n return summaries.map((summary) => toSessionHistoryEntry(summary, currentSessionId));\n}\n", "import type { Agent } from '@wrongstack/core/agent';\nimport type { ProviderModelStatusTracker } from '@wrongstack/core/coordination';\nimport type { TrustBoundary } from '@wrongstack/core/security';\nimport type { Logger, MemoryPort } from '@wrongstack/core/types';\nimport type { MCPRegistry } from '@wrongstack/mcp';\nimport { makeProviderFromConfig } from '@wrongstack/providers';\nimport type { WebSocket } from 'ws';\nimport { AgentRosterWSHandler } from './agent-roster-handlers.js';\nimport { createAutonomyRouteHandlers } from './autonomy-routes.js';\nimport {\n type BrainHandlerContext,\n handleBrainAsk,\n handleBrainConfigGet,\n handleBrainConfigSet,\n handleBrainRisk,\n handleBrainStatus,\n} from './brain-handlers.js';\nimport type { BrainRouteHandlers } from './brain-routes.js';\nimport type { ClientTransportRouteHandlers } from './client-transport-routes.js';\nimport { handleCodebaseIndexServerControl } from './codebase-index-server-control.js';\nimport { createToolLspCompletionSource, handleCompletionRequest } from './completion-handlers.js';\nimport type { CompletionRouteHandlers } from './completion-routes.js';\nimport {\n handleConnectionsHealthRoute,\n handleConnectionsServiceAction,\n} from './connections-health-route.js';\nimport type { DesignContext } from './design-handlers.js';\nimport {\n applyEmbeddedModelSwitch,\n broadcastEmbeddedGoalSnapshot,\n createEmbeddedConversationRoutes,\n createEmbeddedProjectRoutes,\n createEmbeddedSessionRoutes,\n type EmbeddedAgentConfigContext,\n type EmbeddedConversationContext,\n type EmbeddedProjectContext,\n type EmbeddedProviderContext,\n type EmbeddedSessionContext,\n} from './embedded-host-adapters.js';\nimport { handleGitChanges, handleGitDiff, handleGitInfo } from './git-handlers.js';\nimport type { GoalRouteHandlers } from './goal-routes.js';\nimport type { GoalSnapshotRouteHandlers } from './goal-snapshot-routes.js';\nimport type { GoalWebSocketHandler } from './goal-ws-handler.js';\nimport type { WorklistContext } from './handlers/worklist-handlers.js';\nimport type { HostRouteHandlers } from './host-routes.js';\nimport type { IntrospectionRouteContext } from './introspection-routes.js';\nimport type { KanbanTaskDispatcher } from './kanban-dispatch.js';\nimport type { KanbanHostRouteHandlers } from './kanban-host-routes.js';\nimport type { MailboxRouteHandlers } from './mailbox-routes.js';\nimport {\n handleMcpAdd,\n handleMcpDisable,\n handleMcpDiscover,\n handleMcpEnable,\n handleMcpList,\n handleMcpPromptGet,\n handleMcpPrompts,\n handleMcpRemove,\n handleMcpResourceRead,\n handleMcpResources,\n handleMcpRestart,\n handleMcpSleep,\n handleMcpUpdate,\n handleMcpWake,\n} from './mcp-handlers.js';\nimport type { McpRouteHandlers } from './mcp-routes.js';\nimport { createModeRouteHandlers } from './mode-routes.js';\nimport { createModelOperations } from './model-operations.js';\nimport type { PrefsHandlerContext } from './prefs-handlers.js';\nimport { createPrefsRouteHandlers } from './prefs-routes.js';\nimport { authorizeWebUIAction } from './privileged-actions.js';\nimport { handleProcessKill, handleProcessKillAll, handleProcessList } from './process-handlers.js';\nimport type { ProcessRouteHandlers } from './process-routes.js';\nimport type { PromptsContext } from './prompts-handlers.js';\nimport { createProviderOperations } from './provider-handlers.js';\nimport type { ProviderRouteHandlers } from './provider-routes.js';\nimport { createRouteFamilyDispatcher } from './route-family-dispatcher.js';\nimport type { SddBoardRouteHandlers } from './sdd-board-routes.js';\nimport type { SddBoardWebSocketHandler } from './sdd-board-ws-handler.js';\nimport type { SddWizardRouteHandlers } from './sdd-wizard-routes.js';\nimport type { SddWizardWebSocketHandler } from './sdd-wizard-ws-handler.js';\nimport type { ShellGitRouteHandlers } from './shell-git-routes.js';\nimport { handleShellOpen, normalizeShellOpenTarget, type ShellOpenTarget } from './shell-open.js';\nimport type { SkillsContext } from './skills-handlers.js';\nimport type { SpecsRouteHandlers } from './specs-routes.js';\nimport type { SpecsWebSocketHandler } from './specs-ws-handler.js';\nimport type { TerminalWebSocketHandler } from './terminal-ws-handler.js';\nimport type { WSClientMessage, WSServerMessage } from './types.js';\nimport { createWorklistRouteHandlers } from './worklist-routes.js';\nimport type { WorktreeWebSocketHandler } from './worktree-ws-handler.js';\n\nexport interface EmbeddedMessageRouterOptions {\n agent: Agent;\n projectRoot?: string | undefined;\n profileConfigPath: string;\n mcpRegistry?: MCPRegistry | undefined;\n memoryStore?: MemoryPort | undefined;\n onKanbanDispatch?: KanbanTaskDispatcher | undefined;\n}\n\nexport interface EmbeddedMessageRouterDeps {\n trustBoundary: TrustBoundary;\n opts: EmbeddedMessageRouterOptions;\n logger: Logger;\n send: (ws: WebSocket, message: WSServerMessage) => void;\n sendResult: (ws: WebSocket, success: boolean, message: string) => void;\n sessionPayload: <T extends Record<string, unknown>>(payload: T) => T & { sessionId: string };\n currentSessionId: () => string;\n shutdown: () => void;\n providerCtx: EmbeddedProviderContext;\n brainCtx: BrainHandlerContext;\n introspectionCtx: IntrospectionRouteContext;\n skillsCtx: SkillsContext;\n promptsCtx: PromptsContext;\n designCtx: DesignContext;\n agentConfigCtx: EmbeddedAgentConfigContext;\n prefsCtx: PrefsHandlerContext;\n projectCtx: EmbeddedProjectContext;\n sessionCtx: EmbeddedSessionContext;\n conversationCtx: EmbeddedConversationContext;\n mailboxRoutes: MailboxRouteHandlers;\n goalHandler: GoalWebSocketHandler;\n specsHandler: SpecsWebSocketHandler;\n sddBoardHandler: SddBoardWebSocketHandler;\n sddWizardHandler: SddWizardWebSocketHandler | null;\n worktreeHandler: WorktreeWebSocketHandler;\n terminalHandler: TerminalWebSocketHandler;\n kanbanHostRoutes: KanbanHostRouteHandlers;\n /** Shared provider/model health tracker for the WebUI waiting-room panel.\n * Undefined when the host has not wired one (e.g. test harnesses). */\n statusTracker?: ProviderModelStatusTracker | undefined;\n}\n\nexport type EmbeddedMessageRouter = (\n ws: WebSocket,\n client: unknown,\n message: WSClientMessage,\n) => Promise<void>;\n\nexport function createEmbeddedMessageRouter(\n deps: EmbeddedMessageRouterDeps,\n): EmbeddedMessageRouter {\n const { opts, send, sendResult } = deps;\n const projectRoot = () => opts.projectRoot ?? opts.agent.ctx.projectRoot ?? '';\n\n const terminal = async (ws: WebSocket, message: WSClientMessage) => {\n await deps.terminalHandler.handleMessage(ws, message).catch((error) => {\n const text = error instanceof Error ? error.message : String(error);\n const id = (message.payload as { id?: string } | undefined)?.id ?? '';\n send(ws, {\n type: 'terminal.output',\n payload: { id, data: `Internal terminal error: ${text}\\r\\n` },\n });\n send(ws, { type: 'terminal.exit', payload: { id, exitCode: -1 } });\n });\n };\n\n const guardedTypes = new Set([\n 'user_message',\n 'abort',\n 'tool.confirm_result',\n 'session.new',\n 'session.resume',\n 'session.save',\n 'session.checkpoints',\n 'session.rewind',\n 'context.clear',\n 'context.compact',\n 'context.repair',\n 'context.debug',\n 'context.editor.open',\n 'context.editor.validate',\n 'context.editor.apply',\n 'context.modes.list',\n 'context.mode.switch',\n 'context.mode.create',\n 'context.mode.update',\n 'context.mode.delete',\n 'todos.get',\n 'todos.clear',\n 'todos.remove',\n 'todo.update',\n 'tasks.get',\n 'task.update',\n 'plan.get',\n 'plan.template_use',\n 'plan.item.update',\n ]);\n const guardSession = (ws: WebSocket, message: WSClientMessage): boolean => {\n if (!guardedTypes.has(message.type)) return true;\n const payload = message.payload;\n const requested =\n payload &&\n typeof payload === 'object' &&\n typeof (payload as { sessionId?: unknown }).sessionId === 'string'\n ? (payload as { sessionId: string }).sessionId\n : undefined;\n const current = deps.currentSessionId();\n if (!requested || requested === current) return true;\n send(ws, {\n type: 'error',\n payload: deps.sessionPayload({\n phase: message.type,\n message: `Request targeted session ${requested}, but this WebUI runtime is currently on ${current}.`,\n requestedSessionId: requested,\n }),\n });\n return false;\n };\n\n const mcp: McpRouteHandlers = {\n list: (ws, msg) => handleMcpList(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n add: (ws, msg) => handleMcpAdd(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n update: (ws, msg) => handleMcpUpdate(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n remove: (ws, msg) => handleMcpRemove(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n enable: (ws, msg) => handleMcpEnable(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n disable: (ws, msg) => handleMcpDisable(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n sleep: (ws, msg) => handleMcpSleep(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n wake: (ws, msg) => handleMcpWake(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n restart: (ws, msg) => handleMcpRestart(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n discover: (ws, msg) => handleMcpDiscover(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n resources: (ws, msg) => handleMcpResources(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n prompts: (ws, msg) => handleMcpPrompts(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n resourceRead: (ws, msg) =>\n handleMcpResourceRead(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n promptGet: (ws, msg) => handleMcpPromptGet(ws, msg, opts.profileConfigPath, opts.mcpRegistry),\n };\n\n const shellGit: ShellGitRouteHandlers = {\n gitInfo: (ws) => handleGitInfo(ws, projectRoot()),\n gitChanges: (ws) => handleGitChanges(ws, projectRoot()),\n gitDiff: (ws, msg) =>\n handleGitDiff(ws, projectRoot(), (msg.payload as { path?: string } | undefined)?.path ?? ''),\n shellOpen: async (ws, msg) => {\n const payload = msg.payload as { path?: unknown; target?: unknown } | undefined;\n if (typeof payload?.path !== 'string')\n return sendResult(ws, false, 'shell.open path must be a string');\n const targets = ['file', 'file-manager', 'terminal'] as const;\n if (payload.target !== undefined && !targets.includes(payload.target as never)) {\n return sendResult(\n ws,\n false,\n `shell.open target must be one of: ${targets.join(', ')} when provided`,\n );\n }\n const target = payload.target as (typeof targets)[number] | undefined;\n // Normalize before authorization so the trust boundary audit log\n // records the same target that handleShellOpen actually executes.\n const normalizedTarget: ShellOpenTarget = normalizeShellOpenTarget(target);\n const authorization = await authorizeWebUIAction(deps.trustBoundary, {\n capability: normalizedTarget === 'terminal' ? 'process.spawn' : 'filesystem.open-native',\n subject: {\n kind: normalizedTarget === 'terminal' ? 'command' : 'path',\n id: payload.path,\n attributes: { target: normalizedTarget },\n },\n risk: 'elevated',\n cwd: projectRoot(),\n metadata: { backend: 'cli-embedded' },\n });\n if (!authorization.allowed)\n return sendResult(ws, false, `Shell action denied: ${authorization.reason}`);\n const result = await handleShellOpen(\n { path: payload.path, target: normalizedTarget },\n deps.logger,\n { projectRoot: projectRoot() },\n );\n sendResult(ws, result.success, result.message);\n },\n };\n\n const providerOperations = createProviderOperations({\n providerStore: deps.providerCtx.providerStore,\n broadcast: deps.providerCtx.broadcast,\n send: deps.providerCtx.send,\n modelsRegistry: deps.providerCtx.modelsRegistry,\n log: deps.providerCtx.log,\n hasActiveModel: () => Boolean(deps.agentConfigCtx.agent.ctx.model),\n applyModelSwitch: (providerId, modelId) =>\n applyEmbeddedModelSwitch(deps.agentConfigCtx, providerId, modelId),\n });\n const modelOperations = createModelOperations({\n context: deps.agentConfigCtx.agent.ctx,\n memoryStore: deps.agentConfigCtx.memoryStore,\n modelsRegistry: deps.agentConfigCtx.modelsRegistry,\n getConfig: () => deps.agentConfigCtx.getConfig?.(),\n getLiveProviderId: () => deps.agentConfigCtx.agent.ctx.provider.id,\n buildProvider: async (providerId) => {\n const saved = await deps.agentConfigCtx.loadSavedProviders();\n return makeProviderFromConfig(providerId, saved[providerId] ?? { type: providerId });\n },\n applyModelSwitch: (providerId, modelId) =>\n applyEmbeddedModelSwitch(deps.agentConfigCtx, providerId, modelId),\n isRunActive: () => deps.conversationCtx.abortControllers.size > 0,\n send: deps.agentConfigCtx.send,\n broadcast: deps.providerCtx.broadcast,\n log: deps.agentConfigCtx.log,\n });\n const provider: ProviderRouteHandlers = {\n listProviders: (ws) => providerOperations.handleProvidersList(ws),\n listSavedProviders: (ws) => providerOperations.handleProvidersSaved(ws),\n listProviderModels: (ws, msg) =>\n providerOperations.handleProviderModels(\n ws,\n (msg.payload as { providerId: string }).providerId,\n ),\n searchProviderModels: (ws, query, limit) =>\n providerOperations.handleProviderModelsSearch(ws, query, limit),\n switchModel: (ws, msg) => modelOperations.switchModel(ws, msg.payload),\n refineModel: (ws, msg) => modelOperations.refineModel(ws, msg.payload as never),\n adoptDefaultProviderIfUnset: providerOperations.adoptDefaultProviderIfUnset,\n providerHandlers: providerOperations,\n statusTracker: deps.statusTracker,\n };\n\n const session = createEmbeddedSessionRoutes({\n ...deps.sessionCtx,\n // Abort every in-flight run before a session swap \u2014 a slow provider\n // stream from the previous session would otherwise keep running in the\n // background after session.new/resume. The run's own end() cleanup\n // removes controllers from the map when it unwinds.\n abortActiveRun: () => {\n for (const controller of deps.conversationCtx.abortControllers.values()) {\n controller.abort();\n }\n },\n isRunActive: () => deps.conversationCtx.abortControllers.size > 0,\n });\n const project = createEmbeddedProjectRoutes(deps.projectCtx);\n const mode = createModeRouteHandlers({\n modeStore: deps.agentConfigCtx.modeStore,\n getSession: () => deps.agentConfigCtx.agent.ctx.session,\n applyModeId: (id) => {\n deps.agentConfigCtx.agent.ctx.meta['mode'] = id;\n },\n send: deps.agentConfigCtx.send,\n afterSwitch: async (id) =>\n deps.agentConfigCtx.broadcast({\n type: 'session.start',\n payload: await deps.agentConfigCtx.buildSessionStart({ mode: id }),\n }),\n });\n const prefs = createPrefsRouteHandlers(deps.prefsCtx);\n const brain: BrainRouteHandlers = {\n status: (ws) => handleBrainStatus(deps.brainCtx, ws),\n risk: (ws, msg) =>\n handleBrainRisk(\n deps.brainCtx,\n ws,\n (msg.payload as { level?: string } | undefined)?.level ?? '',\n ),\n ask: (ws, msg) =>\n handleBrainAsk(\n deps.brainCtx,\n ws,\n (msg.payload as { question?: string } | undefined)?.question,\n ),\n configGet: (ws) => handleBrainConfigGet(deps.brainCtx, ws),\n configSet: (ws, msg) => handleBrainConfigSet(deps.brainCtx, ws, msg.payload),\n };\n const worklist = createWorklistRouteHandlers({\n getContext: (): WorklistContext => ({\n context: {\n todos: opts.agent.ctx.todos,\n meta: opts.agent.ctx.meta,\n session: opts.agent.ctx.session ? { id: opts.agent.ctx.session.id } : null,\n },\n send,\n broadcast: deps.providerCtx.broadcast,\n replaceTodos: (todos) => opts.agent.ctx.state.replaceTodos(todos),\n }),\n });\n const processRoutes: ProcessRouteHandlers = {\n list: handleProcessList,\n kill: (ws, msg) =>\n handleProcessKill(ws, msg.payload, deps.trustBoundary, undefined, {\n backend: 'cli-embedded',\n }),\n killAll: (ws) =>\n handleProcessKillAll(ws, deps.trustBoundary, undefined, { backend: 'cli-embedded' }),\n };\n const host: HostRouteHandlers = {\n shutdown: async (ws) => {\n const result = await authorizeWebUIAction(deps.trustBoundary, {\n capability: 'host.shutdown',\n subject: { kind: 'process', id: String(process.pid) },\n risk: 'elevated',\n metadata: { backend: 'cli-embedded' },\n });\n if (result.allowed) deps.shutdown();\n else sendResult(ws, false, `Shutdown denied: ${result.reason}`);\n },\n };\n const clientTransport: ClientTransportRouteHandlers = {\n collaboration: (ws, msg) =>\n send(ws, {\n type: 'error',\n payload: { phase: msg.type, message: 'Collaboration not available in this surface' },\n }),\n terminal,\n };\n const completion: CompletionRouteHandlers = {\n request: (ws, msg) =>\n handleCompletionRequest(ws, msg, {\n projectRoot: projectRoot(),\n provider: opts.agent.ctx.provider,\n model: opts.agent.ctx.model,\n indexDir:\n typeof opts.agent.ctx.meta['codebaseIndexDir'] === 'string'\n ? opts.agent.ctx.meta['codebaseIndexDir']\n : undefined,\n lspCompletion: createToolLspCompletionSource(\n opts.agent.ctx.tools.find((tool) => tool.name === 'lsp_completion'),\n opts.agent.ctx,\n ),\n }),\n };\n const goalSnapshot: GoalSnapshotRouteHandlers = {\n getSnapshot: async () => broadcastEmbeddedGoalSnapshot(deps.sessionCtx),\n };\n const goal: GoalRouteHandlers = {\n handleMessage: (ws, msg) => deps.goalHandler.handleMessage(ws, msg),\n };\n const specs: SpecsRouteHandlers = {\n handleMessage: (msg) => deps.specsHandler.handleMessage(msg),\n };\n const sddBoard: SddBoardRouteHandlers = {\n handleMessage: (msg) => deps.sddBoardHandler.handleMessage(msg),\n };\n const sddWizard: SddWizardRouteHandlers = {\n handleMessage: (msg) => deps.sddWizardHandler?.handleMessage(msg) ?? Promise.resolve(),\n };\n\n const dispatch = createRouteFamilyDispatcher({\n routes: {\n shellGit,\n mailbox: deps.mailboxRoutes,\n mcp,\n provider,\n session,\n project,\n mode,\n prefs,\n brain,\n worklist,\n process: processRoutes,\n host,\n clientTransport,\n conversation: createEmbeddedConversationRoutes(deps.conversationCtx),\n completion,\n autonomy: createAutonomyRouteHandlers(deps.prefsCtx),\n goalSnapshot,\n goal,\n specs,\n sddBoard,\n sddWizard,\n worktree: deps.worktreeHandler,\n kanbanHost: deps.kanbanHostRoutes,\n agentRoster: {\n rosterHandler: new AgentRosterWSHandler({\n projectRoot,\n getLlm: () => {\n const ctx = opts.agent.ctx;\n return ctx.provider && ctx.model\n ? { provider: ctx.provider, model: ctx.model }\n : undefined;\n },\n broadcast: (m) => deps.providerCtx.broadcast(m),\n }),\n },\n },\n memory: { getMemoryStore: () => opts.memoryStore, send, sendResult },\n content: {\n getProjectRoot: projectRoot,\n getSkillsContext: () => deps.skillsCtx,\n getPromptsContext: () => deps.promptsCtx,\n getDesignContext: () => deps.designCtx,\n },\n chronicle: { getProjectRoot: projectRoot, send },\n introspection: deps.introspectionCtx,\n getKanbanContext: () => ({\n projectRoot: opts.projectRoot ?? '',\n context: opts.agent.ctx,\n broadcast: deps.providerCtx.broadcast,\n ...(opts.onKanbanDispatch ? { dispatchTask: opts.onKanbanDispatch } : {}),\n }),\n beforeDispatch: guardSession,\n onUnknown: (_ws, msg) => {\n if (!msg.type.startsWith('chronicle.'))\n console.debug(`[WebUI] Unhandled message type: ${msg.type}`);\n },\n });\n return async (ws, _client, message) => {\n if (\n await handleConnectionsHealthRoute(\n {\n getProjectRoot: projectRoot,\n getIndexDir: () =>\n typeof opts.agent.ctx.meta['codebaseIndexDir'] === 'string'\n ? opts.agent.ctx.meta['codebaseIndexDir']\n : undefined,\n send,\n backend: 'cli-embedded',\n },\n ws,\n message,\n )\n )\n return;\n if (\n await handleConnectionsServiceAction(ws, message, {\n getProjectRoot: projectRoot,\n getIndexDir: () =>\n typeof opts.agent.ctx.meta['codebaseIndexDir'] === 'string'\n ? opts.agent.ctx.meta['codebaseIndexDir']\n : undefined,\n send,\n backend: 'cli-embedded',\n })\n )\n return;\n if (\n await handleCodebaseIndexServerControl(ws, message, {\n trustBoundary: deps.trustBoundary,\n logger: deps.logger,\n getProjectRoot: projectRoot,\n getIndexDir: () =>\n typeof opts.agent.ctx.meta['codebaseIndexDir'] === 'string'\n ? opts.agent.ctx.meta['codebaseIndexDir']\n : undefined,\n send,\n backend: 'cli-embedded',\n })\n )\n return;\n await dispatch(ws, message);\n };\n}\n", "/**\n * Agent Roster WS Handlers \u2014 exposes project-agent-identity.ts functions\n * to the WebUI for monitoring and editing custom roster agents.\n *\n * Message types (client \u2192 server):\n * agent-roster.list \u2192 { roles, stats, catalog }\n * agent-roster.stats \u2192 { role stats }\n * agent-roster.llm-improve { role, prompt } \u2192 LLM-suggested changes\n * agent-roster.update-identity { role, content } \u2192 saved path\n * agent-roster.update-learned { role, content } \u2192 saved path\n * agent-roster.update-config { role, config } \u2192 saved path\n * agent-roster.create { name, role?, baseRole?, purpose, taskTypes } \u2192 cloned project role\n * agent-roster.reset { role } \u2192 removed paths\n * agent-roster.capture { role, output? } \u2192 captured count\n * agent-roster.consolidate { role } \u2192 consolidation instruction + metadata\n * agent-roster.save-consolidated { role, content, trigger?, model? } \u2192 saved path + stats\n * agent-roster.read-consolidated { role } \u2192 consolidated content + metadata\n * agent-roster.clear-consolidated { role } \u2192 cleared\n */\n\nimport {\n applyProjectAgentConfig,\n buildConsolidationInstruction,\n captureLearnedFromAgentOutputDetailed,\n clearProjectAgentConsolidated,\n createProjectAgent,\n detectLearnedConflicts,\n FLEET_ROSTER,\n getProjectAgentLearnStats,\n isConsolidated,\n listProjectAgentLearnedEntries,\n listProjectAgentRoles,\n loadConsolidationMetadata,\n loadProjectAgentConfig,\n loadProjectAgentConsolidated,\n loadProjectAgentIdentity,\n loadProjectAgentLearned,\n loadProjectAgentProfile,\n resetProjectAgentIdentity,\n saveProjectAgentConsolidated,\n slugifyProjectAgentRole,\n updateProjectAgentConfig,\n updateProjectAgentIdentity,\n updateProjectAgentLearned,\n updateProjectAgentLearningPolicy,\n} from '@wrongstack/core/coordination';\nimport { isTextBlock } from '@wrongstack/core/types';\nimport type { Provider, Request } from '@wrongstack/core/types';\nimport type { WebSocket } from 'ws';\nimport type { WSServerMessage } from './types.js';\n\n/**\n * Resolved LLM handle used for headless (chat-free) consolidation. Both the\n * embedded and standalone routers can supply this from the active agent\n * context (`agent.ctx.provider` / `agent.ctx.model`).\n */\nexport interface AgentRosterLlm {\n provider: Provider;\n model: string;\n}\n\nexport interface AgentRosterHandlerOptions {\n projectRoot: string | (() => string);\n /**\n * Resolves the LLM used to synthesize consolidations directly on the server,\n * without routing the instruction back through the chat loop. When it\n * returns undefined (no active model), the handler degrades gracefully to\n * returning the instruction for a caller-driven consolidation.\n */\n getLlm?: () => AgentRosterLlm | undefined;\n /**\n * Broadcasts a message to every connected client. Used to push\n * `agent-roster.updated` after a headless consolidation so other open\n * clients refresh the affected roster card without a manual reload.\n */\n broadcast?: (msg: WSServerMessage) => void;\n}\n\n/** Hard cap on synthesized consolidation output. */\nconst CONSOLIDATION_MAX_TOKENS = 8000;\n/** Wall-clock budget for a single headless consolidation LLM call. */\nconst CONSOLIDATION_TIMEOUT_MS = 120_000;\n\nexport class AgentRosterWSHandler {\n private readonly getProjectRoot: () => string;\n private readonly getLlm: () => AgentRosterLlm | undefined;\n private readonly broadcast: (msg: WSServerMessage) => void;\n\n constructor(opts: AgentRosterHandlerOptions) {\n this.getProjectRoot =\n typeof opts.projectRoot === 'function' ? opts.projectRoot : () => opts.projectRoot as string;\n this.getLlm = opts.getLlm ?? (() => undefined);\n this.broadcast = opts.broadcast ?? (() => {});\n }\n\n /**\n * Run the consolidation LLM synthesis headlessly and return the cleaned\n * document text. Returns undefined when no LLM is available so the caller\n * can fall back to the instruction-only path.\n */\n private async synthesizeConsolidation(\n instruction: string,\n ): Promise<{ content: string; model: string } | undefined> {\n const llm = this.getLlm();\n if (!llm) return undefined;\n\n const req: Request = {\n model: llm.model,\n system: [\n {\n type: 'text',\n text:\n 'You are a precise technical editor. You consolidate an AI agent role\\'s ' +\n 'captured learning entries into a single, durable, role-scoped instruction ' +\n 'document. Output ONLY the consolidated markdown document \u2014 no preamble, no ' +\n 'code fences, no commentary about the consolidation process.',\n },\n ],\n messages: [{ role: 'user', content: instruction }],\n maxTokens: CONSOLIDATION_MAX_TOKENS,\n };\n\n const timer = new AbortController();\n let timedOut = false;\n const to = setTimeout(() => {\n timedOut = true;\n timer.abort(new Error('consolidation timeout'));\n }, CONSOLIDATION_TIMEOUT_MS);\n to.unref();\n try {\n const res = await llm.provider.complete(req, { signal: timer.signal });\n const text = res.content\n .filter(isTextBlock)\n .map((block) => block.text)\n .join('\\n')\n .trim();\n // Strip an accidental ```markdown / ``` fence wrapper if the model wrapped\n // the WHOLE document in one. Gate on a single wrapper fence that spans the\n // entire output so a doc that legitimately starts or ends with a real code\n // block is not corrupted (that doc has an interior closing/opening fence,\n // so the whole-document pattern below will not match).\n const wholeDocFence = /^```(?:markdown|md)?[^\\n]*\\n([\\s\\S]*?)\\n?```\\s*$/i;\n const wrapped = wholeDocFence.exec(text);\n const inner = wrapped?.[1];\n const unfenced = inner !== undefined ? inner.trim() : text;\n return { content: unfenced, model: llm.model };\n } catch (err) {\n // Providers surface an abort as a generic AbortError; translate the\n // timeout case into a clear, caller-facing message.\n if (timedOut) {\n throw new Error(`consolidation timed out after ${CONSOLIDATION_TIMEOUT_MS}ms`);\n }\n throw err;\n } finally {\n // The AbortController exists solely to cancel the in-flight request on\n // timeout; the timeout path aborts itself. On the success path there is\n // nothing left to cancel, so only clear the pending timer here.\n clearTimeout(to);\n }\n }\n\n /** Handle an incoming client message. Returns a response payload. */\n async handleMessage(_ws: WebSocket, type: string, payload: unknown): Promise<WSServerMessage> {\n const p = (payload ?? {}) as Record<string, unknown>;\n const role = typeof p.role === 'string' ? p.role : '';\n const projectRoot = this.getProjectRoot();\n\n switch (type) {\n // \u2500\u2500 List all customized roles \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.list': {\n const roles = [\n ...new Set([...Object.keys(FLEET_ROSTER), ...listProjectAgentRoles(projectRoot)]),\n ].sort((a, b) => a.localeCompare(b));\n const stats = roles.map((r) => getProjectAgentLearnStats(r, projectRoot));\n const catalog = roles.map((catalogRole) => {\n const profile = loadProjectAgentProfile(catalogRole, projectRoot);\n const baseConfig =\n FLEET_ROSTER[catalogRole] ??\n (profile ? FLEET_ROSTER[profile.baseRole] : FLEET_ROSTER['generic']);\n const projectConfig = loadProjectAgentConfig(catalogRole, projectRoot);\n const config = baseConfig\n ? applyProjectAgentConfig(baseConfig, projectConfig, {\n protectSystemRole: !profile && Boolean(FLEET_ROSTER[catalogRole]),\n })\n : undefined;\n return {\n role: catalogRole,\n name: profile?.name ?? config?.name ?? catalogRole,\n summary:\n profile?.purpose ??\n config?.prompt\n ?.split('\\n')\n .find((line) => line.trim().length > 20)\n ?.trim() ??\n '',\n tools: projectConfig?.tools?.length ?? config?.tools?.length ?? 0,\n custom: Boolean(profile),\n systemProtected: !profile && Boolean(FLEET_ROSTER[catalogRole]),\n baseRole: profile?.baseRole,\n taskTypes: profile?.taskTypes ?? [],\n budget: {\n timeoutMs: projectConfig?.budget?.timeoutMs ?? config?.timeoutMs,\n maxIterations: projectConfig?.budget?.maxIterations ?? config?.maxIterations,\n maxToolCalls: projectConfig?.budget?.maxToolCalls ?? config?.maxToolCalls,\n },\n };\n });\n return { type: 'agent-roster.list', payload: { roles, stats, catalog } };\n }\n\n // \u2500\u2500 Stats for one role \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.stats': {\n if (!role) return { type, payload: { error: 'role required' } };\n const stats = getProjectAgentLearnStats(role, projectRoot);\n return { type, payload: stats };\n }\n\n // \u2500\u2500 LLM-driven improvement \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.llm-improve': {\n const prompt = typeof p.prompt === 'string' ? p.prompt : '';\n if (!role || !prompt) {\n return { type, payload: { error: 'role and prompt required' } };\n }\n // Read current files\n const currentStats = getProjectAgentLearnStats(role, projectRoot);\n\n // The CLI/agent will process this via `/agent-improve` flow.\n // Return a structured suggestion request that the frontend submits\n // to the leader agent.\n return {\n type: 'agent-roster.llm-improve',\n payload: {\n role,\n prompt,\n currentStats,\n instruction:\n `Inspect and improve the \"${role}\" roster agent for this project. Apply safe, focused changes directly to its project-level agent files and verify them.\\n\\n` +\n `Current state:\\n` +\n ` identity length: ${currentStats.hasIdentity ? 'present' : 'none'}\\n` +\n ` learned entries: ${currentStats.entryCount}\\n` +\n ` total bytes: ${currentStats.totalBytes}\\n\\n` +\n `User request: ${prompt}\\n\\n` +\n `Preserve useful existing knowledge, do not reset unrelated agent data, and finish with a concise summary of files changed and verification performed.`,\n },\n };\n }\n\n // \u2500\u2500 Update identity.md \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.update-identity': {\n if (!role || typeof p.content !== 'string') {\n return { type, payload: { error: 'role and content required' } };\n }\n const fp = updateProjectAgentIdentity(role, p.content, projectRoot);\n return { type, payload: { role, path: fp, success: true } };\n }\n\n // \u2500\u2500 Read learned.md raw content \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.read-learned': {\n if (!role) return { type, payload: { error: 'role required' } };\n const content = loadProjectAgentLearned(role, projectRoot) ?? '';\n const entries = listProjectAgentLearnedEntries(role, projectRoot);\n return { type, payload: { role, content, entries, entryCount: entries.length } };\n }\n\n case 'agent-roster.read-customization': {\n if (!role) return { type, payload: { error: 'role required' } };\n const profile = loadProjectAgentProfile(role, projectRoot);\n return {\n type,\n payload: {\n role,\n identity: loadProjectAgentIdentity(role, projectRoot),\n learned: loadProjectAgentLearned(role, projectRoot),\n config: loadProjectAgentConfig(role, projectRoot) ?? {},\n profile,\n systemProtected: !profile && Boolean(FLEET_ROSTER[role]),\n },\n };\n }\n\n case 'agent-roster.create':\n case 'agent-roster.create-generic': {\n const name = typeof p.name === 'string' ? p.name : '';\n const requestedRole = typeof p.role === 'string' ? p.role : '';\n const baseRole =\n typeof p.baseRole === 'string' && p.baseRole.trim()\n ? p.baseRole.trim().toLowerCase()\n : 'generic';\n const purpose = typeof p.purpose === 'string' ? p.purpose : '';\n const taskTypes = Array.isArray(p.taskTypes)\n ? p.taskTypes.filter((item): item is string => typeof item === 'string')\n : [];\n if (!name || !purpose || taskTypes.length === 0) {\n return { type, payload: { error: 'name, purpose and at least one task type required' } };\n }\n const newRole = (requestedRole.trim() || slugifyProjectAgentRole(name)).toLowerCase();\n if (FLEET_ROSTER[newRole]) {\n return { type, payload: { error: `built-in roster role \"${newRole}\" already exists` } };\n }\n const availableBaseRoles = new Set([\n ...Object.keys(FLEET_ROSTER),\n ...listProjectAgentRoles(projectRoot),\n ]);\n if (!availableBaseRoles.has(baseRole) || baseRole === newRole) {\n return { type, payload: { error: `unknown or circular base roster role \"${baseRole}\"` } };\n }\n const profile = createProjectAgent(\n { role: newRole, name, purpose, taskTypes, baseRole },\n projectRoot,\n );\n return {\n type,\n payload: {\n role: profile.role,\n profile,\n stats: getProjectAgentLearnStats(profile.role, projectRoot),\n success: true,\n },\n };\n }\n\n // \u2500\u2500 Update learned.md \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.update-learned': {\n if (!role || typeof p.content !== 'string') {\n return { type, payload: { error: 'role and content required' } };\n }\n const fp = updateProjectAgentLearned(role, p.content, projectRoot, 'replace');\n return { type, payload: { role, path: fp, success: true } };\n }\n\n // \u2500\u2500 Append to learned.md (teach flow) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.append-learned': {\n const appendix = typeof p.content === 'string' ? p.content : '';\n if (!role || !appendix) {\n return { type, payload: { error: 'role and content required' } };\n }\n const fp = updateProjectAgentLearned(role, appendix, projectRoot, 'append');\n return { type, payload: { role, path: fp, success: true } };\n }\n\n // \u2500\u2500 Update config.json \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.update-config': {\n if (!role || typeof p.config !== 'object' || p.config === null || Array.isArray(p.config)) {\n return { type, payload: { error: 'role and config required' } };\n }\n const fp = updateProjectAgentConfig(\n role,\n p.config as Parameters<typeof updateProjectAgentConfig>[1],\n projectRoot,\n );\n return { type, payload: { role, path: fp, success: true } };\n }\n\n case 'agent-roster.update-learning': {\n if (!role || typeof p.enabled !== 'boolean') {\n return { type, payload: { error: 'role and boolean enabled required' } };\n }\n const policy = updateProjectAgentLearningPolicy(role, { enabled: p.enabled }, projectRoot);\n return {\n type,\n payload: {\n role,\n policy,\n stats: getProjectAgentLearnStats(role, projectRoot),\n success: true,\n },\n };\n }\n\n // \u2500\u2500 Reset / refresh \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.reset': {\n if (!role) return { type, payload: { error: 'role required; use \"*\" explicitly for all' } };\n // The underlying `resetProjectAgentIdentity` treats both `undefined` and\n // `'*'` as \"reset every role\". The CLI's `/agent-improve reset` slash\n // command normalises `'*'` to `undefined` before calling; the WS handler\n // does the same so both entry points agree on the wildcard contract.\n const removed = resetProjectAgentIdentity(role === '*' ? undefined : role, projectRoot);\n return { type, payload: { role, removed, success: removed.length > 0 } };\n }\n\n // \u2500\u2500 Manually trigger capture \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.capture': {\n const output = typeof p.output === 'string' ? p.output : '';\n if (!role) return { type, payload: { error: 'role required' } };\n // Coerce optional content to a string so the fallback never interpolates\n // the literal token \"undefined\" into a LEARNED block.\n const fallback = `## LEARNED\\n${String(p.content ?? '')}`;\n const result = captureLearnedFromAgentOutputDetailed(\n output || fallback,\n role,\n projectRoot,\n true,\n );\n return { type, payload: result };\n }\n\n // \u2500\u2500 Detect conflicts \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.conflicts': {\n const conflicts = detectLearnedConflicts(projectRoot);\n return { type, payload: { conflicts } };\n }\n\n // \u2500\u2500 Consolidate learned entries (headless LLM synthesis) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Runs the whole optimization on the server: read raw entries \u2192\n // synthesize with the active model \u2192 write consolidated.md +\n // consolidation.json. No chat round-trip. When no LLM is available the\n // handler degrades to returning the instruction so a caller (e.g. the\n // chat agent) can still perform the consolidation manually.\n case 'agent-roster.consolidate': {\n if (!role) return { type, payload: { error: 'role required' } };\n const { instruction, rawEntries, hasExistingConsolidation } =\n buildConsolidationInstruction(role, projectRoot);\n\n // Nothing to optimize \u2014 surface a clear, non-error signal.\n if (rawEntries.length === 0) {\n return {\n type: 'agent-roster.consolidate',\n payload: {\n role,\n consolidated: false,\n rawEntryCount: 0,\n hasExistingConsolidation,\n currentStats: getProjectAgentLearnStats(role, projectRoot),\n },\n };\n }\n\n // Headless path: synthesize + persist directly on the server.\n let synth: { content: string; model: string } | undefined;\n try {\n synth = await this.synthesizeConsolidation(instruction);\n } catch (err) {\n return {\n type: 'agent-roster.consolidate',\n payload: {\n role,\n consolidated: false,\n rawEntryCount: rawEntries.length,\n hasExistingConsolidation,\n currentStats: getProjectAgentLearnStats(role, projectRoot),\n error: err instanceof Error ? err.message : 'consolidation failed',\n },\n };\n }\n\n if (synth && synth.content.length > 0) {\n let stats: ReturnType<typeof getProjectAgentLearnStats>;\n let metadata: ReturnType<typeof loadConsolidationMetadata>;\n try {\n saveProjectAgentConsolidated(role, synth.content, projectRoot, {\n trigger: 'manual',\n model: synth.model,\n });\n stats = getProjectAgentLearnStats(role, projectRoot);\n metadata = loadConsolidationMetadata(role, projectRoot);\n } catch (err) {\n // Persisting the consolidated document failed (e.g. filesystem\n // error). Surface a structured failure instead of rejecting.\n return {\n type: 'agent-roster.consolidate',\n payload: {\n role,\n consolidated: false,\n rawEntryCount: rawEntries.length,\n hasExistingConsolidation,\n currentStats: getProjectAgentLearnStats(role, projectRoot),\n error: err instanceof Error ? err.message : 'failed to persist consolidation',\n },\n };\n }\n // Push a fresh roster card to every other connected client so they\n // reflect the new consolidated state without a manual reload. The\n // document is already persisted, so a broadcast failure (e.g. a\n // disconnected client iterator) must not reject the handler and\n // swallow the success response below.\n try {\n this.broadcast({\n type: 'agent-roster.updated',\n payload: { role, reason: 'consolidated', currentStats: stats, metadata },\n });\n } catch (e) {\n // Best-effort notification only; the consolidation itself succeeded.\n // Log so a real bug in `broadcast` (TypeError, malformed message) is\n // surfaced instead of silently swallowed alongside dead-client errors.\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'agent_roster.broadcast_failed',\n role,\n message: e instanceof Error ? e.message : String(e),\n timestamp: new Date().toISOString(),\n }),\n );\n }\n return {\n type: 'agent-roster.consolidate',\n payload: {\n role,\n consolidated: true,\n rawEntryCount: rawEntries.length,\n content: synth.content,\n model: synth.model,\n currentStats: stats,\n metadata,\n },\n };\n }\n\n // The model was available and ran, but produced only whitespace /\n // fencing. This is distinct from \"no model available\": signal it\n // explicitly so a caller can tell an empty synthesis apart from the\n // instruction-fallback path below and avoid corrupting the doc.\n if (synth) {\n return {\n type: 'agent-roster.consolidate',\n payload: {\n role,\n consolidated: false,\n emptySynthesis: true,\n model: synth.model,\n rawEntryCount: rawEntries.length,\n hasExistingConsolidation,\n currentStats: getProjectAgentLearnStats(role, projectRoot),\n },\n };\n }\n\n // Fallback path (no active model): return the instruction so a\n // caller can drive the consolidation through the chat agent.\n return {\n type: 'agent-roster.consolidate',\n payload: {\n role,\n consolidated: false,\n instruction,\n rawEntryCount: rawEntries.length,\n hasExistingConsolidation,\n currentStats: getProjectAgentLearnStats(role, projectRoot),\n // Instruction for the leader agent to execute the consolidation\n leaderInstruction:\n `Optimize what the \"${role}\" agent has learned. Read its raw learned entries, ` +\n `synthesize them into a single narrowly-scoped document preserving every fact, and ` +\n `save the result. The instruction text contains the full details and raw entries.`,\n },\n };\n }\n\n // \u2500\u2500 Save consolidated document \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.save-consolidated': {\n if (!role || typeof p.content !== 'string') {\n return { type, payload: { error: 'role and content required' } };\n }\n const trigger =\n typeof p.trigger === 'string' && p.trigger === 'automatic' ? 'automatic' : 'manual';\n const model = typeof p.model === 'string' ? p.model : undefined;\n const fp = saveProjectAgentConsolidated(role, p.content, projectRoot, {\n trigger,\n ...(model ? { model } : {}),\n });\n const stats = getProjectAgentLearnStats(role, projectRoot);\n return {\n type: 'agent-roster.save-consolidated',\n payload: { role, path: fp, success: true, stats },\n };\n }\n\n // \u2500\u2500 Read consolidated document \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.read-consolidated': {\n if (!role) return { type, payload: { error: 'role required' } };\n const content = loadProjectAgentConsolidated(role, projectRoot);\n const metadata = loadConsolidationMetadata(role, projectRoot);\n const consolidated = isConsolidated(role, projectRoot);\n return {\n type: 'agent-roster.read-consolidated',\n payload: { role, content, metadata, isConsolidated: consolidated },\n };\n }\n\n // \u2500\u2500 Clear consolidated document \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n case 'agent-roster.clear-consolidated': {\n if (!role) return { type, payload: { error: 'role required' } };\n clearProjectAgentConsolidated(role, projectRoot);\n return { type, payload: { role, success: true } };\n }\n\n default:\n return { type, payload: { error: `Unknown agent-roster action: ${type}` } };\n }\n }\n}\n", "import type { TrustBoundary } from '@wrongstack/core/security';\nimport type { Logger } from '@wrongstack/core/types';\nimport { shutdownCodebaseIndexServer } from '@wrongstack/tools';\nimport type { WebSocket } from 'ws';\nimport { authorizeWebUIAction } from './privileged-actions.js';\nimport type { WSClientMessage, WSServerMessage } from './types.js';\n\nexport interface CodebaseIndexServerControlDeps {\n trustBoundary: TrustBoundary;\n logger?: Logger | undefined;\n getProjectRoot(): string;\n getIndexDir(): string | undefined;\n send(ws: WebSocket, message: WSServerMessage): void;\n backend: 'standalone' | 'cli-embedded';\n}\n\n/** Handle the WebSocket control message that stops this project's index server. */\nexport async function handleCodebaseIndexServerControl(\n ws: WebSocket,\n message: WSClientMessage,\n deps: CodebaseIndexServerControlDeps,\n): Promise<boolean> {\n if (message.type !== 'codebase.index.server.shutdown') return false;\n\n const requestId =\n message.payload &&\n typeof message.payload === 'object' &&\n typeof (message.payload as { requestId?: unknown }).requestId === 'string'\n ? (message.payload as { requestId: string }).requestId\n : '';\n const projectRoot = deps.getProjectRoot();\n const authorization = await authorizeWebUIAction(\n deps.trustBoundary,\n {\n capability: 'codebase-index.server.shutdown',\n subject: { kind: 'process', id: projectRoot },\n risk: 'elevated',\n cwd: projectRoot,\n metadata: { transport: 'websocket', backend: deps.backend },\n },\n deps.logger,\n );\n if (!authorization.allowed) {\n deps.send(ws, {\n type: 'codebase.index.server.shutdown_result',\n payload: {\n requestId,\n stopped: false,\n reason: `Shutdown denied: ${authorization.reason}`,\n },\n });\n return true;\n }\n\n const result = await shutdownCodebaseIndexServer(\n projectRoot,\n deps.getIndexDir(),\n 'websocket-request',\n );\n deps.send(ws, {\n type: 'codebase.index.server.shutdown_result',\n payload: { requestId, ...result },\n });\n return true;\n}\n", "import type { WebSocket } from 'ws';\nimport type { AgentRosterWSHandler } from './agent-roster-handlers.js';\nimport type { WSClientMessage } from './types.js';\nimport { send } from './ws-utils.js';\n\nexport interface AgentRosterRouteHandlers {\n rosterHandler: AgentRosterWSHandler;\n}\n\nexport async function handleAgentRosterRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: AgentRosterRouteHandlers,\n): Promise<boolean> {\n if (!msg.type.startsWith('agent-roster.')) return false;\n try {\n const response = await handlers.rosterHandler.handleMessage(\n ws,\n msg.type,\n msg.payload as Record<string, unknown> | undefined,\n );\n send(ws, response);\n } catch (error) {\n send(ws, {\n type: msg.type,\n payload: { error: error instanceof Error ? error.message : String(error) },\n });\n }\n return true;\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface ProjectRouteHandlers {\n listProjects: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n addProject: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n selectProject: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n setWorkingDir: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n}\n\nexport async function handleProjectRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: ProjectRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'projects.list':\n await handlers.listProjects(ws, msg);\n return true;\n case 'projects.add':\n await handlers.addProject(ws, msg);\n return true;\n case 'projects.select':\n await handlers.selectProject(ws, msg);\n return true;\n case 'working_dir.set':\n await handlers.setWorkingDir(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import type { ProviderModelStatusTracker } from '@wrongstack/core/coordination';\nimport type { ProviderConfig } from '@wrongstack/core/types';\nimport type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\nimport { send, sendResult } from './ws-utils.js';\n\ntype OAuthKind = 'chatgpt' | 'claude' | 'copilot';\n\nexport interface ProviderMutationHandlers {\n handleKeyUpsert: (\n ws: WebSocket,\n providerId: string,\n label: string,\n apiKey: string,\n ) => Promise<void>;\n handleKeyDelete: (ws: WebSocket, providerId: string, label: string) => Promise<void>;\n handleKeySetActive: (ws: WebSocket, providerId: string, label: string) => Promise<void>;\n handleProviderAdd: (\n ws: WebSocket,\n payload: {\n id: string;\n family: string;\n baseUrl?: string | undefined;\n apiKey?: string | undefined;\n models?: string[] | undefined;\n customModels?: ProviderConfig['customModels'] | undefined;\n },\n ) => Promise<void>;\n handleProviderRemove: (ws: WebSocket, providerId: string) => Promise<void>;\n handleProviderClearModels: (ws: WebSocket, providerId: string) => Promise<void>;\n handleProviderUndoClear: (\n ws: WebSocket,\n providerId: string,\n previousModels: string[],\n ) => Promise<void>;\n handleProviderUpdate: (\n ws: WebSocket,\n payload: {\n id: string;\n family?: string | undefined;\n baseUrl?: string | undefined;\n envVars?: string[] | undefined;\n models?: string[] | undefined;\n customModels?: ProviderConfig['customModels'] | undefined;\n },\n ) => Promise<void>;\n handleProviderProbe: (\n ws: WebSocket,\n providerId: string,\n timeoutMs?: number | undefined,\n ) => Promise<void>;\n handleOAuthStart: (\n ws: WebSocket,\n kind: OAuthKind,\n providerId?: string | undefined,\n ) => Promise<void>;\n handleOAuthCode: (ws: WebSocket, kind: OAuthKind, input: string) => Promise<void>;\n handleOAuthCancel: (ws: WebSocket, kind: OAuthKind) => void;\n}\n\nexport interface ProviderRouteHandlers {\n listProviders: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n listSavedProviders: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n listProviderModels: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n searchProviderModels: (ws: WebSocket, query: string, limit?: number | undefined) => Promise<void>;\n switchModel: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n refineModel: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n /** Adopt a just-added provider as the live default when no model is active. */\n adoptDefaultProviderIfUnset: (providerId: string) => Promise<void>;\n providerHandlers: ProviderMutationHandlers;\n /** Live provider/model health tracker (the \"waiting room\"). Undefined when\n * the host is not wired with a tracker (e.g. test harnesses). */\n statusTracker?: ProviderModelStatusTracker | undefined;\n}\n\nfunction asPayloadRecord(msg: WSClientMessage): Record<string, unknown> | null {\n const payload = msg.payload;\n return typeof payload === 'object' && payload !== null && !Array.isArray(payload)\n ? (payload as Record<string, unknown>)\n : null;\n}\n\nfunction requiredString(payload: Record<string, unknown>, key: string): string | null {\n const value = payload[key];\n return typeof value === 'string' && value.trim().length > 0 ? value : null;\n}\n\nfunction optionalNumber(payload: Record<string, unknown>, key: string): number | undefined | null {\n const value = payload[key];\n if (value === undefined) return undefined;\n return typeof value === 'number' && Number.isFinite(value) ? value : null;\n}\n\nfunction optionalStringArray(\n payload: Record<string, unknown>,\n key: string,\n): string[] | undefined | null {\n const value = payload[key];\n if (value === undefined) return undefined;\n return Array.isArray(value) && value.every((item) => typeof item === 'string') ? value : null;\n}\n\nconst SAFE_CONFIG_KEY = /^(?!__proto__$|prototype$|constructor$)[^\\u0000-\\u001f]{1,256}$/;\nconst CUSTOM_MODEL_BOOLEAN_CAPS = new Set([\n 'tools',\n 'vision',\n 'reasoning',\n 'streaming',\n 'jsonMode',\n]);\nconst INLINE_DEFINITION_KEYS = new Set(['name', 'maxOutput', 'capabilities', 'provider']);\n\nfunction optionalCustomModels(\n payload: Record<string, unknown>,\n): ProviderConfig['customModels'] | undefined | null {\n const value = payload['customModels'];\n if (value === undefined) return undefined;\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return null;\n const out: NonNullable<ProviderConfig['customModels']> = Object.create(null) as NonNullable<\n ProviderConfig['customModels']\n >;\n for (const [modelId, rawDefinition] of Object.entries(value)) {\n if (!SAFE_CONFIG_KEY.test(modelId)) return null;\n if (\n typeof rawDefinition !== 'object' ||\n rawDefinition === null ||\n Array.isArray(rawDefinition)\n ) {\n return null;\n }\n const definition = rawDefinition as Record<string, unknown>;\n if (Object.keys(definition).some((key) => !INLINE_DEFINITION_KEYS.has(key))) return null;\n if (definition['name'] !== undefined && typeof definition['name'] !== 'string') return null;\n if (definition['provider'] !== undefined && typeof definition['provider'] !== 'string')\n return null;\n if (\n definition['maxOutput'] !== undefined &&\n (typeof definition['maxOutput'] !== 'number' ||\n !Number.isFinite(definition['maxOutput']) ||\n definition['maxOutput'] <= 0)\n ) {\n return null;\n }\n const rawCaps = definition['capabilities'];\n let capabilities:\n | NonNullable<ProviderConfig['customModels']>[string]['capabilities']\n | undefined;\n if (rawCaps !== undefined) {\n if (typeof rawCaps !== 'object' || rawCaps === null || Array.isArray(rawCaps)) return null;\n const entry = rawCaps as Record<string, unknown>;\n const allowedCaps = new Set([...CUSTOM_MODEL_BOOLEAN_CAPS, 'maxContext', 'maxOutput']);\n if (Object.keys(entry).some((key) => !allowedCaps.has(key))) return null;\n const built: Partial<{\n maxContext: number;\n maxOutput: number;\n tools: boolean;\n vision: boolean;\n reasoning: boolean;\n streaming: boolean;\n jsonMode: boolean;\n }> = {};\n for (const [key, capValue] of Object.entries(entry)) {\n if (CUSTOM_MODEL_BOOLEAN_CAPS.has(key)) {\n if (typeof capValue !== 'boolean') return null;\n (built as Record<string, unknown>)[key] = capValue;\n } else if (typeof capValue !== 'number' || !Number.isFinite(capValue) || capValue <= 0) {\n return null;\n } else {\n (built as Record<string, unknown>)[key] = capValue;\n }\n }\n capabilities = built;\n }\n out[modelId] = {\n ...(typeof definition['name'] === 'string' ? { name: definition['name'] } : {}),\n ...(typeof definition['provider'] === 'string' ? { provider: definition['provider'] } : {}),\n ...(typeof definition['maxOutput'] === 'number'\n ? { maxOutput: definition['maxOutput'] }\n : {}),\n ...(capabilities ? { capabilities } : {}),\n };\n }\n return out;\n}\n\nfunction invalidPayload(ws: WebSocket, type: string): true {\n sendResult(ws, false, `${type} payload is invalid`);\n return true;\n}\n\nconst OAUTH_KINDS = new Set(['chatgpt', 'claude', 'copilot']);\nfunction oauthKind(\n payload: Record<string, unknown> | null,\n): 'chatgpt' | 'claude' | 'copilot' | null {\n const kind = payload?.['kind'];\n return typeof kind === 'string' && OAUTH_KINDS.has(kind)\n ? (kind as 'chatgpt' | 'claude' | 'copilot')\n : null;\n}\n\nexport async function handleProviderRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n routes: ProviderRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'providers.list':\n await routes.listProviders(ws, msg);\n return true;\n case 'providers.saved':\n await routes.listSavedProviders(ws, msg);\n return true;\n case 'provider.models':\n await routes.listProviderModels(ws, msg);\n return true;\n case 'provider.models.search': {\n const payload = asPayloadRecord(msg);\n const query = payload ? requiredString(payload, 'query') : null;\n const limit = payload ? optionalNumber(payload, 'limit') : null;\n if (\n !query ||\n limit === null ||\n (limit !== undefined && (limit <= 0 || !Number.isInteger(limit)))\n ) {\n return invalidPayload(ws, msg.type);\n }\n await routes.searchProviderModels(ws, query, limit);\n return true;\n }\n case 'model.switch':\n await routes.switchModel(ws, msg);\n return true;\n case 'model.refine':\n await routes.refineModel(ws, msg);\n return true;\n\n case 'key.add':\n case 'key.update': {\n const payload = asPayloadRecord(msg);\n const providerId = payload ? requiredString(payload, 'providerId') : null;\n const label = payload ? requiredString(payload, 'label') : null;\n const apiKey = payload ? requiredString(payload, 'apiKey') : null;\n if (!providerId || !label || !apiKey) return invalidPayload(ws, msg.type);\n await routes.providerHandlers.handleKeyUpsert(ws, providerId, label, apiKey);\n return true;\n }\n\n case 'key.delete': {\n const payload = asPayloadRecord(msg);\n const providerId = payload ? requiredString(payload, 'providerId') : null;\n const label = payload ? requiredString(payload, 'label') : null;\n if (!providerId || !label) return invalidPayload(ws, msg.type);\n await routes.providerHandlers.handleKeyDelete(ws, providerId, label);\n return true;\n }\n\n case 'key.set_active': {\n const payload = asPayloadRecord(msg);\n const providerId = payload ? requiredString(payload, 'providerId') : null;\n const label = payload ? requiredString(payload, 'label') : null;\n if (!providerId || !label) return invalidPayload(ws, msg.type);\n await routes.providerHandlers.handleKeySetActive(ws, providerId, label);\n return true;\n }\n\n case 'provider.add': {\n const payload = asPayloadRecord(msg);\n const id = payload ? requiredString(payload, 'id') : null;\n const family = payload ? requiredString(payload, 'family') : null;\n const baseUrl = payload?.['baseUrl'];\n const apiKey = payload?.['apiKey'];\n const models = payload ? optionalStringArray(payload, 'models') : null;\n const customModels = payload ? optionalCustomModels(payload) : null;\n if (!id || !family) return invalidPayload(ws, msg.type);\n if (baseUrl !== undefined && typeof baseUrl !== 'string') return invalidPayload(ws, msg.type);\n if (apiKey !== undefined && typeof apiKey !== 'string') return invalidPayload(ws, msg.type);\n if (models === null || customModels === null) return invalidPayload(ws, msg.type);\n await routes.providerHandlers.handleProviderAdd(ws, {\n id,\n family,\n baseUrl: baseUrl as string | undefined,\n apiKey: apiKey as string | undefined,\n models,\n customModels,\n });\n // Adopt the just-added provider as the live default when nothing is\n // active yet \u2014 parity with the boot auto-select (immediately usable).\n await routes.adoptDefaultProviderIfUnset(id);\n return true;\n }\n\n case 'provider.remove': {\n const payload = asPayloadRecord(msg);\n const providerId = payload ? requiredString(payload, 'providerId') : null;\n if (!providerId) return invalidPayload(ws, msg.type);\n await routes.providerHandlers.handleProviderRemove(ws, providerId);\n return true;\n }\n\n case 'provider.clear_models': {\n const payload = asPayloadRecord(msg);\n const providerId = payload ? requiredString(payload, 'providerId') : null;\n if (!providerId) return invalidPayload(ws, msg.type);\n await routes.providerHandlers.handleProviderClearModels(ws, providerId);\n return true;\n }\n\n case 'provider.undo_clear': {\n const payload = asPayloadRecord(msg);\n const providerId = payload ? requiredString(payload, 'providerId') : null;\n const previousModels = payload ? optionalStringArray(payload, 'previousModels') : null;\n if (!providerId || !previousModels) return invalidPayload(ws, msg.type);\n await routes.providerHandlers.handleProviderUndoClear(ws, providerId, previousModels);\n return true;\n }\n\n case 'provider.update': {\n const payload = asPayloadRecord(msg);\n const id = payload ? requiredString(payload, 'id') : null;\n const envVars = payload ? optionalStringArray(payload, 'envVars') : null;\n const models = payload ? optionalStringArray(payload, 'models') : null;\n const customModels = payload ? optionalCustomModels(payload) : null;\n if (!payload || !id || envVars === null || models === null || customModels === null)\n return invalidPayload(ws, msg.type);\n for (const key of ['family', 'baseUrl'] as const) {\n if (payload[key] !== undefined && typeof payload[key] !== 'string')\n return invalidPayload(ws, msg.type);\n }\n await routes.providerHandlers.handleProviderUpdate(ws, {\n id,\n family: payload['family'] as string | undefined,\n baseUrl: payload['baseUrl'] as string | undefined,\n envVars,\n models,\n customModels,\n });\n return true;\n }\n\n case 'provider.probe': {\n const payload = asPayloadRecord(msg);\n const providerId = payload ? requiredString(payload, 'providerId') : null;\n const timeoutMs = payload ? optionalNumber(payload, 'timeoutMs') : null;\n if (!providerId || timeoutMs === null) return invalidPayload(ws, msg.type);\n await routes.providerHandlers.handleProviderProbe(ws, providerId, timeoutMs);\n return true;\n }\n\n case 'auth.oauth.start': {\n const payload = asPayloadRecord(msg);\n const kind = oauthKind(payload);\n const providerId = payload?.['providerId'];\n if (!kind) return invalidPayload(ws, msg.type);\n if (providerId !== undefined && typeof providerId !== 'string') {\n return invalidPayload(ws, msg.type);\n }\n await routes.providerHandlers.handleOAuthStart(ws, kind, providerId);\n return true;\n }\n\n case 'auth.oauth.code': {\n const payload = asPayloadRecord(msg);\n const kind = oauthKind(payload);\n const input = payload ? requiredString(payload, 'input') : null;\n if (!kind || !input) return invalidPayload(ws, msg.type);\n await routes.providerHandlers.handleOAuthCode(ws, kind, input);\n return true;\n }\n\n case 'auth.oauth.cancel': {\n const kind = oauthKind(asPayloadRecord(msg));\n if (!kind) return invalidPayload(ws, msg.type);\n routes.providerHandlers.handleOAuthCancel(ws, kind);\n return true;\n }\n\n case 'provider.status.get': {\n if (!routes.statusTracker) {\n send(ws, { type: 'provider.status.snapshot', payload: { error: 'not_available' } });\n return true;\n }\n send(ws, {\n type: 'provider.status.snapshot',\n payload: routes.statusTracker.getSnapshot(),\n });\n return true;\n }\n\n case 'provider.status.retry': {\n if (!routes.statusTracker) {\n sendResult(ws, false, 'provider.status.retry: tracker not available');\n return true;\n }\n const payload = asPayloadRecord(msg);\n const providerId = payload ? requiredString(payload, 'providerId') : null;\n const model = payload ? requiredString(payload, 'model') : null;\n if (!providerId || !model) return invalidPayload(ws, msg.type);\n const released = routes.statusTracker.retryNow(providerId, model);\n sendResult(\n ws,\n true,\n released\n ? `Released ${providerId}/${model} for a half-open probe on its next use.`\n : `${providerId}/${model} is not currently in the waiting room.`,\n );\n return true;\n }\n\n case 'provider.status.clear': {\n if (!routes.statusTracker) {\n sendResult(ws, false, 'provider.status.clear: tracker not available');\n return true;\n }\n const payload = asPayloadRecord(msg);\n const providerId = payload ? requiredString(payload, 'providerId') : null;\n const model = payload ? requiredString(payload, 'model') : null;\n if (!providerId || !model) return invalidPayload(ws, msg.type);\n routes.statusTracker.clear(providerId, model);\n sendResult(ws, true, `Cleared tracking for ${providerId}/${model}.`);\n return true;\n }\n\n default:\n return false;\n }\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface SddBoardRouteHandlers {\n handleMessage: (msg: { type: string; payload?: Record<string, unknown> }) => Promise<void>;\n}\n\n/** Forward any `sdd.board.*` message to the SddBoardWebSocketHandler. */\nexport async function handleSddBoardRoute(\n _ws: WebSocket,\n msg: WSClientMessage,\n handlers: SddBoardRouteHandlers,\n): Promise<boolean> {\n if (!msg.type.startsWith('sdd.board.')) return false;\n await handlers.handleMessage(msg as { type: string; payload?: Record<string, unknown> });\n return true;\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface SddWizardRouteHandlers {\n handleMessage: (msg: { type: string; payload?: Record<string, unknown> }) => Promise<void>;\n}\n\n/**\n * Forward the SDD wizard messages (`sdd.spec.*` and `sdd.run.start`) to the\n * SddWizardWebSocketHandler. Note `sdd.board.*` is handled separately by the\n * board route \u2014 the wizard owns spec-building + run kickoff, the board owns\n * live observation/control.\n */\nexport async function handleSddWizardRoute(\n _ws: WebSocket,\n msg: WSClientMessage,\n handlers: SddWizardRouteHandlers,\n): Promise<boolean> {\n if (!(msg.type.startsWith('sdd.spec.') || msg.type.startsWith('sdd.run.'))) return false;\n await handlers.handleMessage(msg as { type: string; payload?: Record<string, unknown> });\n return true;\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface SessionRouteHandlers {\n newSession: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n clearContext: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n debugContext: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n compactContext: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n repairContext: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n openContextEditor: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n validateContextEditor: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n applyContextEditor: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n listContextModes: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n switchContextMode: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n createContextMode: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n updateContextMode: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n deleteContextMode: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n listSessions: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n renameSession: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n deleteSession: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n resumeSession: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n saveSession: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n listCheckpoints: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n rewindSession: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n}\n\nexport async function handleSessionRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: SessionRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'session.new':\n await handlers.newSession(ws, msg);\n return true;\n case 'context.clear':\n await handlers.clearContext(ws, msg);\n return true;\n case 'context.debug':\n await handlers.debugContext(ws, msg);\n return true;\n case 'context.compact':\n await handlers.compactContext(ws, msg);\n return true;\n case 'context.repair':\n await handlers.repairContext(ws, msg);\n return true;\n case 'context.editor.open':\n await handlers.openContextEditor(ws, msg);\n return true;\n case 'context.editor.validate':\n await handlers.validateContextEditor(ws, msg);\n return true;\n case 'context.editor.apply':\n await handlers.applyContextEditor(ws, msg);\n return true;\n case 'context.modes.list':\n await handlers.listContextModes(ws, msg);\n return true;\n case 'context.mode.switch':\n await handlers.switchContextMode(ws, msg);\n return true;\n case 'context.mode.create':\n await handlers.createContextMode(ws, msg);\n return true;\n case 'context.mode.update':\n await handlers.updateContextMode(ws, msg);\n return true;\n case 'context.mode.delete':\n await handlers.deleteContextMode(ws, msg);\n return true;\n case 'sessions.list':\n await handlers.listSessions(ws, msg);\n return true;\n case 'session.rename':\n await handlers.renameSession(ws, msg);\n return true;\n case 'session.delete':\n await handlers.deleteSession(ws, msg);\n return true;\n case 'session.resume':\n await handlers.resumeSession(ws, msg);\n return true;\n case 'session.save':\n await handlers.saveSession(ws, msg);\n return true;\n case 'session.checkpoints':\n await handlers.listCheckpoints(ws, msg);\n return true;\n case 'session.rewind':\n await handlers.rewindSession(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface ShellGitRouteHandlers {\n gitInfo: (ws: WebSocket) => Promise<void>;\n gitChanges: (ws: WebSocket) => Promise<void>;\n gitDiff: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n shellOpen: (ws: WebSocket, msg: WSClientMessage) => Promise<void>;\n}\n\nexport async function handleShellGitRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: ShellGitRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'git.info':\n await handlers.gitInfo(ws);\n return true;\n case 'git.changes':\n await handlers.gitChanges(ws);\n return true;\n case 'git.diff':\n await handlers.gitDiff(ws, msg);\n return true;\n case 'shell.open':\n await handlers.shellOpen(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface SpecsRouteHandlers {\n handleMessage: (msg: { type: string; payload?: Record<string, unknown> }) => Promise<void>;\n}\n\n/** Forward any `specs.*` message to the SpecsWebSocketHandler. */\nexport async function handleSpecsRoute(\n _ws: WebSocket,\n msg: WSClientMessage,\n handlers: SpecsRouteHandlers,\n): Promise<boolean> {\n if (!msg.type.startsWith('specs.')) return false;\n await handlers.handleMessage(msg as { type: string; payload?: Record<string, unknown> });\n return true;\n}\n", "import type { WebSocket } from 'ws';\nimport {\n handleWorklistMessage,\n type WorklistContext,\n type WorklistMessage,\n} from './handlers/worklist-handlers.js';\nimport type { WSClientMessage } from './types.js';\n\nexport interface WorklistRouteHandlers {\n getTodos: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n clearTodos: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n removeTodo: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n updateTodo: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n getTasks: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n updateTask: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n getPlan: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n usePlanTemplate: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n updatePlanItem: (ws: WebSocket, msg: WSClientMessage) => Promise<void> | void;\n}\n\nexport interface WorklistRouteContext {\n getContext: () => WorklistContext;\n allowMessage?: ((ws: WebSocket, message: WSClientMessage) => boolean) | undefined;\n}\n\nexport function createWorklistRouteHandlers(ctx: WorklistRouteContext): WorklistRouteHandlers {\n const dispatch = async (ws: WebSocket, message: WSClientMessage): Promise<void> => {\n if (ctx.allowMessage && !ctx.allowMessage(ws, message)) return;\n await handleWorklistMessage(ctx.getContext(), ws, message as WorklistMessage);\n };\n return {\n getTodos: dispatch,\n clearTodos: dispatch,\n removeTodo: dispatch,\n updateTodo: dispatch,\n getTasks: dispatch,\n updateTask: dispatch,\n getPlan: dispatch,\n usePlanTemplate: dispatch,\n updatePlanItem: dispatch,\n };\n}\n\nexport async function handleWorklistRoute(\n ws: WebSocket,\n msg: WSClientMessage,\n handlers: WorklistRouteHandlers,\n): Promise<boolean> {\n switch (msg.type) {\n case 'todos.get':\n await handlers.getTodos(ws, msg);\n return true;\n case 'todos.clear':\n await handlers.clearTodos(ws, msg);\n return true;\n case 'todos.remove':\n await handlers.removeTodo(ws, msg);\n return true;\n case 'todo.update':\n await handlers.updateTodo(ws, msg);\n return true;\n case 'tasks.get':\n await handlers.getTasks(ws, msg);\n return true;\n case 'task.update':\n await handlers.updateTask(ws, msg);\n return true;\n case 'plan.get':\n await handlers.getPlan(ws, msg);\n return true;\n case 'plan.template_use':\n await handlers.usePlanTemplate(ws, msg);\n return true;\n case 'plan.item.update':\n await handlers.updatePlanItem(ws, msg);\n return true;\n default:\n return false;\n }\n}\n", "import type { WebSocket } from 'ws';\nimport type { WSClientMessage } from './types.js';\n\nexport interface WorktreeRouteHandlers {\n handleMessage: (msg: { type: string; payload?: Record<string, unknown> }) => Promise<boolean>;\n}\n\nexport async function handleWorktreeRoute(\n _ws: WebSocket,\n msg: WSClientMessage,\n handlers: WorktreeRouteHandlers,\n): Promise<boolean> {\n if (!msg.type.startsWith('worktree.')) return false;\n return handlers.handleMessage(msg as { type: string; payload?: Record<string, unknown> });\n}\n", "import type { WebSocket } from 'ws';\nimport { type AgentRosterRouteHandlers, handleAgentRosterRoute } from './agent-roster-routes.js';\nimport { type AutonomyRouteHandlers, handleAutonomyRoute } from './autonomy-routes.js';\nimport { type BrainRouteHandlers, handleBrainRoute } from './brain-routes.js';\nimport { type ChronicleRouteContext, handleChronicleRoute } from './chronicle-routes.js';\nimport {\n type ClientTransportRouteHandlers,\n handleClientTransportRoute,\n} from './client-transport-routes.js';\nimport { type CompletionRouteHandlers, handleCompletionRoute } from './completion-routes.js';\nimport { type ContentRouteContext, handleContentRoute } from './content-routes.js';\nimport { type ConversationRouteHandlers, handleConversationRoute } from './conversation-routes.js';\nimport { type GoalRouteHandlers, handleGoalRoute } from './goal-routes.js';\nimport { type GoalSnapshotRouteHandlers, handleGoalSnapshotRoute } from './goal-snapshot-routes.js';\nimport { type HostRouteHandlers, handleHostRoute } from './host-routes.js';\nimport {\n handleIntrospectionRoute,\n type IntrospectionRouteContext,\n} from './introspection-routes.js';\nimport { handleKanbanHostRoute, type KanbanHostRouteHandlers } from './kanban-host-routes.js';\nimport { handleKanbanRoute, type KanbanRouteContext } from './kanban-routes.js';\nimport { handleMailboxRoute, type MailboxRouteHandlers } from './mailbox-routes.js';\nimport { handleMcpRoute, type McpRouteHandlers } from './mcp-routes.js';\nimport { handleMemoryRoute, type MemoryRouteContext } from './memory-routes.js';\nimport { handleModeRoute, type ModeRouteHandlers } from './mode-routes.js';\nimport { handlePrefsRoute, type PrefsRouteHandlers } from './prefs-routes.js';\nimport { handleProcessRoute, type ProcessRouteHandlers } from './process-routes.js';\nimport { handleProjectRoute, type ProjectRouteHandlers } from './project-routes.js';\nimport { handleProviderRoute, type ProviderRouteHandlers } from './provider-routes.js';\nimport { handleSddBoardRoute, type SddBoardRouteHandlers } from './sdd-board-routes.js';\nimport { handleSddWizardRoute, type SddWizardRouteHandlers } from './sdd-wizard-routes.js';\nimport { handleSessionRoute, type SessionRouteHandlers } from './session-routes.js';\nimport { handleShellGitRoute, type ShellGitRouteHandlers } from './shell-git-routes.js';\nimport { handleSpecsRoute, type SpecsRouteHandlers } from './specs-routes.js';\nimport type { WSClientMessage } from './types.js';\nimport { handleWorklistRoute, type WorklistRouteHandlers } from './worklist-routes.js';\nimport { handleWorktreeRoute, type WorktreeRouteHandlers } from './worktree-routes.js';\n\n/** Host capabilities grouped by protocol family. Dispatch order lives here. */\nexport interface RouteFamilyTable {\n shellGit: ShellGitRouteHandlers;\n mailbox: MailboxRouteHandlers;\n mcp: McpRouteHandlers;\n provider: ProviderRouteHandlers;\n session: SessionRouteHandlers;\n project: ProjectRouteHandlers;\n mode: ModeRouteHandlers;\n prefs: PrefsRouteHandlers;\n brain: BrainRouteHandlers;\n worklist: WorklistRouteHandlers;\n process: ProcessRouteHandlers;\n host: HostRouteHandlers;\n clientTransport: ClientTransportRouteHandlers;\n conversation: ConversationRouteHandlers;\n completion: CompletionRouteHandlers;\n autonomy: AutonomyRouteHandlers;\n goalSnapshot: GoalSnapshotRouteHandlers;\n goal: GoalRouteHandlers;\n specs: SpecsRouteHandlers;\n sddBoard: SddBoardRouteHandlers;\n sddWizard: SddWizardRouteHandlers;\n worktree: WorktreeRouteHandlers;\n kanbanHost: KanbanHostRouteHandlers;\n agentRoster: AgentRosterRouteHandlers;\n}\n\nexport interface RouteFamilyDispatcherOptions {\n routes: RouteFamilyTable;\n memory: MemoryRouteContext;\n content: ContentRouteContext;\n chronicle: ChronicleRouteContext;\n introspection: IntrospectionRouteContext;\n getKanbanContext: () => KanbanRouteContext;\n beforeDispatch?:\n | ((ws: WebSocket, message: WSClientMessage) => boolean | Promise<boolean>)\n | undefined;\n onUnknown: (ws: WebSocket, message: WSClientMessage) => void | Promise<void>;\n}\n\nexport type RouteFamilyDispatcher = (ws: WebSocket, message: WSClientMessage) => Promise<void>;\n\nexport function createRouteFamilyDispatcher(\n options: RouteFamilyDispatcherOptions,\n): RouteFamilyDispatcher {\n const { routes } = options;\n return async (ws, message) => {\n if (options.beforeDispatch && !(await options.beforeDispatch(ws, message))) return;\n if (await handleShellGitRoute(ws, message, routes.shellGit)) return;\n if (await handleMailboxRoute(ws, message, routes.mailbox)) return;\n if (await handleMcpRoute(ws, message, routes.mcp)) return;\n if (await handleProviderRoute(ws, message, routes.provider)) return;\n if (await handleSessionRoute(ws, message, routes.session)) return;\n if (await handleProjectRoute(ws, message, routes.project)) return;\n if (await handleModeRoute(ws, message, routes.mode)) return;\n if (await handlePrefsRoute(ws, message, routes.prefs)) return;\n if (await handleBrainRoute(ws, message, routes.brain)) return;\n if (await handleWorklistRoute(ws, message, routes.worklist)) return;\n if (await handleProcessRoute(ws, message, routes.process)) return;\n if (await handleHostRoute(ws, message, routes.host)) return;\n if (await handleClientTransportRoute(ws, message, routes.clientTransport)) return;\n if (await handleConversationRoute(ws, message, routes.conversation)) return;\n if (await handleCompletionRoute(ws, message, routes.completion)) return;\n if (await handleAutonomyRoute(ws, message, routes.autonomy)) return;\n if (await handleGoalSnapshotRoute(ws, message, routes.goalSnapshot)) return;\n if (await handleGoalRoute(ws, message, routes.goal)) return;\n if (await handleSpecsRoute(ws, message, routes.specs)) return;\n if (await handleSddBoardRoute(ws, message, routes.sddBoard)) return;\n if (await handleSddWizardRoute(ws, message, routes.sddWizard)) return;\n if (await handleWorktreeRoute(ws, message, routes.worktree)) return;\n if (await handleKanbanHostRoute(ws, message, routes.kanbanHost)) return;\n if (await handleAgentRosterRoute(ws, message, routes.agentRoster)) return;\n if (await handleMemoryRoute(options.memory, ws, message)) return;\n if (await handleContentRoute(options.content, ws, message)) return;\n if (await handleChronicleRoute(options.chronicle, ws, message)) return;\n if (await handleIntrospectionRoute(options.introspection, ws, message)) return;\n if (await handleKanbanRoute(ws, message, options.getKanbanContext())) return;\n await options.onUnknown(ws, message);\n };\n}\n", "// Open the OS file manager or a terminal at a given path (the\n// `shell.open` WS message handler).\n//\n// Both the standalone `startWebUI` and the CLI's `runWebUI` needed\n// the same logic \\u2014 metacharacter guard, `path.resolve` to fold\n// any `..` traversal, and a cross-platform `spawn()` for the\n// platform's file manager (`explorer`/`open`/`xdg-open`) or\n// terminal (`cmd /c start cmd /k` / `open -a Terminal` /\n// `x-terminal-emulator` \\u2192 `gnome-terminal` \\u2192 `xterm` fallback chain).\n// Phase 1.2 added the `spawn`-based version on the CLI side; the\n// standalone got it shortly after. The two implementations have\n// drifted slightly (CLI lacks the `logger.warn` on spawn failure),\n// which is exactly the class of bug extraction prevents.\n//\n// This module returns a `ShellOpenResult` so the caller (the WS\n// router in either entry point) can pipe it through `sendResult`\n// with the same `success`/`message` shape both sides already use.\n// Spawn is async + detached + unref'd so a missing terminal\n// emulator (which fires `error` async) never crashes the server\n// \\u2014 the fallback chain tries the next one, the file-manager\n// branch just logs.\n//\n// SECURITY: the path arrives over the WebSocket. The\n// metacharacter guard (`/[&|<>^\\\"'`\\n\\r]/`) closes the cmd.exe\n// re-parsing injection class (`\"foo\" && calc.exe`,\n// `'$(...)'`, backticks, redirections) before anything reaches\n// the argv array. The `path.resolve` then folds any\n// `..` traversal, and `fs.access(resolved)` enforces that the\n// target exists \\u2014 callers can't ask us to open a non-existent\n// path. Defense in depth: the spawn below uses an argv array\n// (no string concatenation), and `windowsHide` keeps the\n// launcher console out of the way.\n\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { spawn } from 'node:child_process';\nimport type { Logger } from '@wrongstack/core/types';\n\nexport type ShellOpenTarget = 'terminal' | 'file-manager';\n\nexport interface ShellOpenRequest {\n path: string;\n target: ShellOpenTarget;\n}\n\n/**\n * Normalize a raw wire-format target value to a valid `ShellOpenTarget`.\n *\n * Maps `'terminal'` \u2192 `'terminal'`, everything else (including `'file'`,\n * `'file-manager'`, `undefined`, unknown strings) \u2192 `'file-manager'`.\n *\n * This reconciles the legacy wire format (`target: 'file'`) which the\n * payload validators may still accept, with the handler contract\n * (`'terminal' | 'file-manager'`), and ensures consistent behavior\n * across both the standalone and embedded WebUI routers.\n */\nexport function normalizeShellOpenTarget(\n target: string | undefined,\n): ShellOpenTarget {\n return target === 'terminal' ? 'terminal' : 'file-manager';\n}\n\n/**\n * Optional security options for `handleShellOpen`.\n *\n * `projectRoot`, when provided, confines the resolved path to the project\n * directory \u2014 the OS file manager / terminal will never be launched at a\n * location outside the project. This is defense-in-depth: the TrustBoundary\n * authorization may use a permissive compatibility policy, so the path\n * containment must be enforced at the executor as well.\n */\nexport interface ShellOpenOptions {\n projectRoot?: string;\n}\n\nexport interface ShellOpenResult {\n success: boolean;\n message: string;\n}\n\n/** Metacharacters that would let a path slip past an argv-array\n * spawn and into a shell re-parse on Windows. Real directory\n * paths virtually never contain these. Single-quote is included\n * because an unescaped ' inside a single-quoted shell string\n * (e.g. cd '$path') breaks the literal and enables injection. */\nconst METACHAR_REGEX = /[&|<>^\"'`'\\n\\r]/;\n\n/** Escape a string for safe use as a single-quoted shell argument.\n * Replaces ' -> '\\'' (end quote, escaped quote, restart quote). */\nfunction shellQuote(s: string): string {\n return s.replaceAll(\"'\", \"'\\\"'\\\"'\");\n}\n\nexport async function handleShellOpen(\n req: ShellOpenRequest,\n logger: Logger,\n options?: ShellOpenOptions,\n): Promise<ShellOpenResult> {\n try {\n const resolved = path.resolve(req.path);\n\n // SECURITY: when a projectRoot is provided, confine the path to the\n // project directory. Without this, a WebSocket client can open the OS\n // file manager or terminal at ANY existing path on the system\n // (/etc, ~/.ssh, C:\\Windows). The TrustBoundary policy may be the\n // permissive compatibility default, so containment is enforced here\n // as defense-in-depth.\n if (options?.projectRoot) {\n const root = path.resolve(options.projectRoot);\n const relative = path.relative(root, resolved);\n const escapes = relative.startsWith('..') || path.isAbsolute(relative);\n if (escapes) {\n return {\n success: false,\n message: 'Path must be inside the project directory.',\n };\n }\n }\n\n await fs.access(resolved);\n if (METACHAR_REGEX.test(resolved)) {\n return { success: false, message: 'Path contains unsupported characters.' };\n }\n\n const platform = process.platform;\n const launch = (cmd: string, args: string[], onError?: () => void) => {\n const child = spawn(cmd, args, {\n detached: true,\n stdio: 'ignore',\n windowsHide: true,\n });\n // `error` fires when the binary is missing (e.g. xterm not\n // installed) \\u2014 log it, but never block the WS caller. The\n // fallback chain in the terminal branch uses onError to try\n // the next emulator.\n child.on('error', (err) => {\n logger.warn(`shell.open spawn failed: ${err.message}`);\n onError?.();\n });\n child.unref();\n };\n\n if (req.target === 'file-manager') {\n if (platform === 'win32') launch('explorer', [resolved]);\n else if (platform === 'darwin') launch('open', [resolved]);\n else launch('xdg-open', [resolved]);\n } else if (req.target === 'terminal') {\n if (platform === 'win32') {\n // `start` is a cmd builtin; each token is a separate argv\n // entry (Node quotes them individually \\u2014 no string\n // concatenation). This replaces the previous\n // `start cmd /k cd /d \"...\"` exec() call that was\n // shell-injectable.\n launch('cmd', ['/c', 'start', 'cmd', '/k', 'cd', '/d', resolved]);\n } else if (platform === 'darwin') {\n launch('open', ['-a', 'Terminal', resolved]);\n } else {\n // Try several terminal emulators\n launch('x-terminal-emulator', [`--working-directory=${resolved}`], () =>\n launch('gnome-terminal', [`--working-directory=${resolved}`], () =>\n // Pass argv array so sh -c sees a literal string, not an interpolated one.\n // shellQuote() guards against paths that somehow slipped the METACHAR_REGEX.\n launch('xterm', ['-e', 'sh', '-c', `cd ${shellQuote(resolved)} && ${process.env['SHELL'] ?? 'sh'}`]),\n ),\n );\n }\n } else {\n return { success: false, message: `Unknown shell.open target: ${String(req.target)}` };\n }\n return { success: true, message: `Opened ${req.target} at ${resolved}` };\n } catch (err) {\n return { success: false, message: err instanceof Error ? err.message : String(err) };\n }\n}\n", "/**\n * Standalone WebUI server helper (boot phase \u2014 not WS-connected), split out\n * of provider-config-io.ts so chunks that only need the pure load/save I/O\n * don't bundle the AES-GCM `DefaultSecretVault`.\n */\nimport * as path from 'node:path';\nimport { DefaultSecretVault } from '@wrongstack/core/security';\nimport type { ProviderConfig } from '@wrongstack/core/types';\nimport { loadSavedProviders, saveProviders } from './provider-config-io.js';\n\n/**\n * Small helper for the standalone WebUI entry point: create a\n * `{ load, save }` pair from a config path alone. Profile configs still use\n * the shared `~/.wrongstack/.key` vault key. The `--webui`\n * CLI mode and the standalone server both need to read/write the\n * `providers` map identically.\n */\nexport function createProviderConfigIO(configPath: string) {\n const keyFile = vaultKeyFileForConfigPath(configPath);\n const vault = new DefaultSecretVault({ keyFile });\n\n return {\n load: () => loadSavedProviders(configPath, vault),\n save: (providers: Record<string, ProviderConfig>) =>\n saveProviders(configPath, vault, providers),\n };\n}\n\n/** Resolve the shared vault key for either a root bootstrap or profile config path. */\nexport function vaultKeyFileForConfigPath(configPath: string): string {\n const configDir = path.dirname(configPath);\n const parentDir = path.dirname(configDir);\n const globalRoot = path.basename(parentDir) === 'profiles' ? path.dirname(parentDir) : configDir;\n return path.join(globalRoot, '.key');\n}\n", "import { expectDefined } from '@wrongstack/core/utils';\nimport * as fs from 'node:fs/promises';\nimport { decryptConfigSecrets, encryptConfigSecrets } from '@wrongstack/core/security';\nimport { atomicWrite } from '@wrongstack/core/utils';\nimport type { DefaultSecretVault } from '@wrongstack/core/security';\nimport type { ProviderApiKey, ProviderConfig } from '@wrongstack/core/types';\nexport interface ProviderStoreDeps {\n /** Active profile config path. */\n profileConfigPath: string;\n vault: DefaultSecretVault;\n}\n\n/**\n * Serializes concurrent config writes to prevent races between model.switch\n * and key.add/key.update handlers that both mutate the profile config.\n */\nexport function createConfigWriteLock() {\n let lock: Promise<void> = Promise.resolve();\n return {\n get current() { return lock; },\n acquire() {\n const prev = lock;\n let release: () => void = () => undefined;\n lock = new Promise<void>((resolve) => { release = resolve; });\n return { prev, release };\n },\n };\n}\n\nexport interface ProviderStore {\n load(): Promise<Record<string, ProviderConfig>>;\n save(providers: Record<string, ProviderConfig>): Promise<void>;\n normalizeKeys(cfg: ProviderConfig): ProviderApiKey[];\n writeKeysBack(cfg: ProviderConfig, keys: ProviderApiKey[]): void;\n maskedKey(key: string | undefined): string;\n}\n\nexport function createProviderStore(deps: ProviderStoreDeps): ProviderStore {\n const { profileConfigPath, vault } = deps;\n const configWriteLock = createConfigWriteLock();\n\n async function loadSavedProviders(): Promise<Record<string, ProviderConfig>> {\n try {\n const raw = await fs.readFile(profileConfigPath, 'utf8');\n const parsed = JSON.parse(raw) as { providers?: Record<string, ProviderConfig> };\n if (!parsed.providers) return {};\n return decryptConfigSecrets(parsed.providers, vault);\n } catch {\n return {};\n }\n }\n\n async function saveProviders(providers: Record<string, ProviderConfig>): Promise<void> {\n const { prev, release } = configWriteLock.acquire();\n try {\n await prev;\n let parsed: Record<string, unknown>;\n try {\n const raw = await fs.readFile(profileConfigPath, 'utf8');\n parsed = JSON.parse(raw) as Record<string, unknown>;\n } catch {\n parsed = {};\n }\n parsed['providers'] = providers;\n const encrypted = encryptConfigSecrets(parsed, vault);\n await atomicWrite(profileConfigPath, JSON.stringify(encrypted, null, 2), { mode: 0o600 });\n } finally {\n release();\n }\n }\n\n function normalizeKeys(cfg: ProviderConfig): ProviderApiKey[] {\n if (Array.isArray(cfg.apiKeys) && cfg.apiKeys.length > 0) {\n return cfg.apiKeys.map((k) => ({ ...k }));\n }\n if (typeof cfg.apiKey === 'string' && cfg.apiKey.length > 0) {\n return [{ label: 'default', apiKey: cfg.apiKey, createdAt: '' }];\n }\n return [];\n }\n\n function writeKeysBack(cfg: ProviderConfig, keys: ProviderApiKey[]): void {\n if (keys.length === 0) {\n delete cfg.apiKeys;\n delete cfg.apiKey;\n delete cfg.activeKey;\n return;\n }\n cfg.apiKeys = keys;\n const active = keys.find((k) => k.label === cfg.activeKey) ?? expectDefined(keys[0]);\n // Do NOT mirror plaintext to cfg.apiKey \u2014 cleared to prevent serialization leaks.\n delete cfg.apiKey;\n if (!cfg.activeKey || !keys.some((k) => k.label === cfg.activeKey)) {\n cfg.activeKey = active.label;\n }\n }\n\n function maskedKey(key: string | undefined): string {\n if (!key) return '\u2014';\n if (key.length <= 8) return '\u2022'.repeat(key.length);\n return `${key.slice(0, 4)}\u2026${key.slice(-4)}`;\n }\n\n return {\n load: loadSavedProviders,\n save: saveProviders,\n normalizeKeys,\n writeKeysBack,\n maskedKey,\n };\n}\n", "import type { EventBus } from '@wrongstack/core/kernel';\nimport type { TrustBoundary } from '@wrongstack/core/security';\nimport type { Logger } from '@wrongstack/core/types';\nimport {\n enqueueKanbanWorkflowCommand,\n kanbanWorkflowId,\n listBoards,\n listKanbanWorkflowStates,\n} from '@wrongstack/kanban';\nimport {\n applySddLifecycle,\n extractVerificationCommand,\n type SddBoardIndexEntry,\n type SddBoardSnapshot,\n SddBoardStore,\n type SddLifecycleOp,\n} from '@wrongstack/sdd';\nimport type { WebSocket } from 'ws';\nimport { authorizeWebUIAction } from './privileged-actions.js';\nimport { sendSerialized } from './ws-utils.js';\n\ninterface WSClient {\n ws: WebSocket;\n id: string;\n}\n\ninterface SddBoardWSMessage {\n type: string;\n payload?: Record<string, unknown>;\n}\n\n/**\n * Commands enqueued through the project-scoped Kanban IPC owner and drained by\n * the live run. Only meaningful while the run is active.\n */\nconst CONTROL_TYPES = new Set([\n 'pause',\n 'resume',\n 'stop',\n 'retry',\n 'retry_all_failed',\n 'reassign',\n // Per-task model / fallback / verification assignment + stop/delete (drained by start-sdd-run).\n 'set_task_model',\n 'set_task_fallbacks',\n 'set_task_verification',\n 'cancel_task',\n 'delete_task',\n 'split_task',\n]);\n\n/**\n * Post-run lifecycle ops applied directly from durable workflow state by this\n * handler (not via the command queue \u2014 nothing drains it once the run settles).\n * Each operates on git + persisted state and is gated on \"no active run\". `destroy` accepts a\n * `revertMerged` flag to also undo merged commits.\n */\nconst LIFECYCLE_TYPES = new Set<SddLifecycleOp>(['cleanup_worktrees', 'rollback', 'destroy']);\n\n/** Project paths the handler needs to apply lifecycle ops directly. */\nexport interface SddBoardLifecycleDeps {\n projectRoot: string;\n /** Explicit compatibility hook for file-codec tests and old integrations. */\n controlTransport?: 'kanban' | 'legacy-file' | undefined;\n /** Explicit compatibility hook for legacy snapshot-file readers. */\n stateTransport?: 'kanban' | 'legacy-file' | undefined;\n paths: {\n projectSpecs: string;\n projectTaskGraphs: string;\n projectSddSession: string;\n projectSddBoards: string;\n };\n}\n\nexport interface SddBoardSecurityDeps {\n trustBoundary: TrustBoundary;\n logger?: Logger | undefined;\n}\n\n/**\n * SddBoardWebSocketHandler \u2014 streams the live SDD multi-agent board to clients\n * and relays control commands back to the CLI-owned run.\n *\n * Two observe modes (one class, shared by both webui servers):\n * \u2022 in-process (CLI-hosted): subscribe the shared EventBus `sdd.board.snapshot`\n * for instant updates;\n * \u2022 standalone (separate process): poll the project-scoped Kanban workflow\n * state owned by the daemon.\n *\n * Control is uniform + cross-process: every command is durably enqueued in the\n * Kanban project daemon, which the CLI run drains and applies \u2014 so the run stays\n * the single driver and nothing races on shared state.\n */\nexport class SddBoardWebSocketHandler {\n private readonly store: SddBoardStore;\n private readonly clients = new Set<WSClient>();\n private readonly lifecycle?: SddBoardLifecycleDeps | undefined;\n private readonly security?: SddBoardSecurityDeps | undefined;\n private readonly standalonePollingEnabled: boolean;\n private latest: SddBoardSnapshot | null = null;\n private poll: ReturnType<typeof setInterval> | null = null;\n private pollInFlight = false;\n private unsub: (() => void) | null = null;\n\n constructor(\n boardsDir: string,\n events?: EventBus,\n lifecycle?: SddBoardLifecycleDeps,\n security?: SddBoardSecurityDeps,\n ) {\n this.store = new SddBoardStore({ baseDir: boardsDir });\n this.lifecycle = lifecycle;\n this.security = security;\n this.standalonePollingEnabled = events === undefined;\n\n if (events) {\n // Instant updates in the CLI-hosted server (shared bus).\n const handler = (e: { runId: string; snapshot: SddBoardSnapshot }) => {\n this.latest = e.snapshot;\n this.broadcast({ type: 'sdd.board.snapshot', payload: e.snapshot });\n };\n this.unsub = events.on('sdd.board.snapshot', handler as (p: unknown) => void);\n }\n }\n\n addClient(ws: WebSocket): void {\n const client: WSClient = { ws, id: crypto.randomUUID() };\n this.clients.add(client);\n const remove = () => {\n this.clients.delete(client);\n if (this.clients.size === 0) this.stopPolling();\n };\n ws.on('close', remove);\n ws.on('error', remove);\n this.startPolling();\n // Send the current board immediately (from memory or project state). Best-effort:\n // a corrupt/locked snapshot must not become an unhandled rejection.\n void this.sendCurrent(client).catch((err) => {\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'sdd_board.initial_send_failed',\n message: err instanceof Error ? err.message : String(err),\n }),\n );\n });\n }\n\n async handleMessage(msg: SddBoardWSMessage): Promise<void> {\n if (msg.type === 'sdd.board.get') {\n await this.broadcastCurrent();\n return;\n }\n if (msg.type === 'sdd.board.list') {\n const boards = await this.listBoardEntries();\n this.broadcast({ type: 'sdd.board.list', payload: { boards } });\n return;\n }\n const action = msg.type.replace(/^sdd\\.board\\./, '');\n\n // Post-run lifecycle ops are applied here from durable workflow state. The\n // live run's command drain is gone once it finishes, so queueing these\n // operations (as the old Clean/Rollback buttons did) would be a no-op.\n if (LIFECYCLE_TYPES.has(action as SddLifecycleOp)) {\n await this.applyLifecycle(action as SddLifecycleOp, msg.payload);\n return;\n }\n\n if (CONTROL_TYPES.has(action)) {\n const verificationCommands: Array<{ command: string; operation: string }> = [];\n if (action === 'set_task_verification') {\n const command = msg.payload?.verificationCommand;\n if (command !== undefined && (typeof command !== 'string' || command.length > 8_192))\n return;\n if (typeof command === 'string' && command.trim()) {\n verificationCommands.push({ command, operation: 'sdd.set_task_verification' });\n }\n } else if (action === 'split_task') {\n const subtasks = msg.payload?.subtasks;\n if (Array.isArray(subtasks)) {\n for (const subtask of subtasks) {\n if (!subtask || typeof subtask !== 'object') continue;\n const criterion = (subtask as Record<string, unknown>).successCriterion;\n if (criterion === undefined) continue;\n if (typeof criterion !== 'string') return;\n const command = extractVerificationCommand([criterion]);\n if (!command) continue;\n if (command.length > 8_192) return;\n verificationCommands.push({ command, operation: 'sdd.split_task_verification' });\n }\n }\n }\n for (const { command, operation } of verificationCommands) {\n if (!this.security) return;\n const authorization = await authorizeWebUIAction(\n this.security.trustBoundary,\n {\n capability: 'process.spawn',\n subject: { kind: 'command', id: command },\n risk: 'high',\n cwd: this.lifecycle?.projectRoot,\n metadata: { operation },\n },\n this.security.logger,\n );\n if (!authorization.allowed) return;\n }\n const runId =\n (msg.payload?.runId as string | undefined) ??\n this.latest?.runId ??\n (await this.listBoardEntries())[0]?.runId;\n if (runId) {\n if (this.lifecycle && this.lifecycle.controlTransport !== 'legacy-file') {\n await enqueueKanbanWorkflowCommand(\n this.lifecycle.projectRoot,\n kanbanWorkflowId('sdd', runId),\n { type: action, payload: msg.payload },\n );\n } else {\n await this.store.appendControl(runId, {\n ts: Date.now(),\n type: action,\n payload: msg.payload,\n });\n }\n }\n }\n }\n\n /**\n * Apply a cleanup/rollback/destroy from durable state and broadcast a structured\n * `sdd.board.lifecycle_result`. Refuses (no-op) while a run is still active \u2014\n * the user must stop it first; the UI gates the buttons on `!active` and the\n * Destroy flow auto-stops then waits before sending `destroy`.\n */\n private async applyLifecycle(\n op: SddLifecycleOp,\n payload?: Record<string, unknown>,\n ): Promise<void> {\n if (!this.lifecycle) {\n this.broadcast({\n type: 'sdd.board.lifecycle_result',\n payload: {\n op,\n ok: false,\n reason: 'Lifecycle operations are not available in this session.',\n },\n });\n return;\n }\n // Refuse while live \u2014 these force-remove worktrees / rewrite the base branch.\n if (this.latest && (this.latest.status === 'running' || this.latest.status === 'paused')) {\n this.broadcast({\n type: 'sdd.board.lifecycle_result',\n payload: { op, ok: false, reason: 'Stop the run first, then retry.' },\n });\n return;\n }\n\n const runId = (payload?.runId as string | undefined) ?? this.latest?.runId;\n const result = await applySddLifecycle(op, {\n projectRoot: this.lifecycle.projectRoot,\n paths: this.lifecycle.paths,\n runId,\n stateTransport: this.lifecycle.stateTransport ?? 'kanban',\n revertMerged: payload?.revertMerged === true,\n });\n\n this.broadcast({ type: 'sdd.board.lifecycle_result', payload: result });\n\n // A destroy wipes the board; clear the in-memory snapshot and push an empty\n // board so every client returns to the \"No active SDD run\" state.\n if (op === 'destroy' && result.ok) {\n this.latest = null;\n this.broadcast({ type: 'sdd.board.snapshot', payload: null });\n // Refresh the Kanban list so mirror boards removed by destroySddProject\n // disappear from the UI without a manual reload.\n if (this.lifecycle) {\n try {\n const boards = await listBoards(this.lifecycle.projectRoot);\n this.broadcast({\n type: 'kanban.list',\n payload: { success: true, data: boards },\n });\n } catch {\n // best-effort\n }\n }\n }\n }\n\n dispose(): void {\n this.stopPolling();\n this.unsub?.();\n this.unsub = null;\n }\n\n // \u2500\u2500 internal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async pollLatest(): Promise<void> {\n if (this.pollInFlight) return;\n this.pollInFlight = true;\n try {\n const snap = await this.loadLatestSnapshot();\n if (!snap) return;\n if (\n this.latest &&\n this.latest.updatedAt >= snap.updatedAt &&\n this.latest.runId === snap.runId\n ) {\n return; // nothing newer\n }\n this.latest = snap;\n this.broadcast({ type: 'sdd.board.snapshot', payload: snap });\n } catch (err) {\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'sdd_board.poll_failed',\n message: err instanceof Error ? err.message : String(err),\n }),\n );\n } finally {\n this.pollInFlight = false;\n }\n }\n\n private startPolling(): void {\n if (!this.standalonePollingEnabled || this.poll !== null || this.clients.size === 0) return;\n this.poll = setInterval(() => void this.pollLatest(), 1000);\n this.poll.unref?.();\n }\n\n private stopPolling(): void {\n if (this.poll === null) return;\n clearInterval(this.poll);\n this.poll = null;\n }\n\n private async sendCurrent(client: WSClient): Promise<void> {\n const snap = this.latest ?? (await this.loadLatestSnapshot());\n if (snap) this.send(client, { type: 'sdd.board.snapshot', payload: snap });\n }\n\n private async broadcastCurrent(): Promise<void> {\n const snap = this.latest ?? (await this.loadLatestSnapshot());\n if (snap) this.broadcast({ type: 'sdd.board.snapshot', payload: snap });\n }\n\n private async loadLatestSnapshot(): Promise<SddBoardSnapshot | null> {\n if (this.usesKanbanState()) {\n const states = await listKanbanWorkflowStates(this.lifecycle!.projectRoot, 'sdd:');\n const snapshots = states\n .map((state) => state.value)\n .filter(isSddBoardSnapshot)\n .sort((a, b) => b.updatedAt - a.updatedAt);\n return snapshots[0] ?? null;\n }\n const entry = await this.store.latest();\n return entry ? this.store.load(entry.runId) : null;\n }\n\n private async listBoardEntries(): Promise<SddBoardIndexEntry[]> {\n if (!this.usesKanbanState()) return this.store.list();\n const states = await listKanbanWorkflowStates(this.lifecycle!.projectRoot, 'sdd:');\n return states.flatMap((state) => {\n if (!isSddBoardSnapshot(state.value)) return [];\n const snapshot = state.value;\n return [\n {\n runId: snapshot.runId,\n ...(snapshot.specId ? { specId: snapshot.specId } : {}),\n title: snapshot.title,\n status: snapshot.status,\n total: snapshot.progress.total,\n completed: snapshot.progress.completed,\n updatedAt: snapshot.updatedAt,\n },\n ];\n });\n }\n\n private usesKanbanState(): boolean {\n return Boolean(this.lifecycle && this.lifecycle.stateTransport !== 'legacy-file');\n }\n\n private broadcast(msg: { type: string; payload: unknown }): void {\n const data = JSON.stringify(msg);\n for (const client of this.clients) {\n sendSerialized(client.ws, data);\n }\n }\n\n private send(client: WSClient, msg: { type: string; payload: unknown }): void {\n sendSerialized(client.ws, JSON.stringify(msg));\n }\n}\n\nfunction isSddBoardSnapshot(value: unknown): value is SddBoardSnapshot {\n if (!value || typeof value !== 'object') return false;\n const snapshot = value as Partial<SddBoardSnapshot>;\n return (\n typeof snapshot.runId === 'string' &&\n typeof snapshot.title === 'string' &&\n typeof snapshot.status === 'string' &&\n typeof snapshot.updatedAt === 'number' &&\n Array.isArray(snapshot.tasks) &&\n Boolean(snapshot.progress && typeof snapshot.progress.total === 'number')\n );\n}\n", "import * as path from 'node:path';\nimport type { Agent } from '@wrongstack/core/agent';\nimport type { AgentFactory, BrainArbiter } from '@wrongstack/core/coordination';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport { DefaultTaskStore, type TaskStore, TaskTracker } from '@wrongstack/core/tasking';\nimport type { TaskGraph } from '@wrongstack/core/types';\nimport { ToolValidationError } from '@wrongstack/core/types';\nimport { WorktreeManager } from '@wrongstack/core/worktree';\nimport {\n cleanupStaleSddWorktrees,\n createKanbanSddSessionPersistence,\n decomposeNonAtomicTasks,\n gatherProjectContext,\n makeAcceptanceCriteriaVerifier,\n makeCommandVerifier,\n makeCompositeVerifier,\n makeLlmSubtaskGenerator,\n makePlanningDecomposer,\n SddBoardStore,\n SddInterviewDriver,\n type SddRunHandle,\n SddRunRegistry,\n SddSupervisor,\n SpecStore,\n startSddRun,\n TaskGraphStore,\n} from '@wrongstack/sdd';\nimport { isGitWorkTree } from './git-process.js';\nimport type { SddRunStartOpts, SddWizardDeps } from './sdd-wizard-ws-handler.js';\n\n/** Config knobs shared by the wizard start and the launch-from-board start. */\nexport interface StartSddRunFromGraphConfig {\n parallelSlots?: number | undefined;\n defaultModel?: string | undefined;\n defaultProvider?: string | undefined;\n fallbackModels?: string[] | undefined;\n /** Per-run git-worktree isolation. Omit \u2192 env default (WRONGSTACK_SDD_WORKTREES). */\n worktrees?: boolean | undefined;\n /**\n * Planning-time proactive decomposition of `needs_decomposition` leaves\n * before the run starts. Omit \u2192 env default (WRONGSTACK_SDD_PLAN_DECOMPOSE,\n * off unless set to '1'). Requires deps.runIsolatedTurn.\n */\n planDecompose?: boolean | undefined;\n}\n\nexport interface StartSddRunFromGraphDeps {\n agent: Agent;\n events: EventBus;\n projectRoot: string;\n subagentFactory: AgentFactory;\n brain?: BrainArbiter | undefined;\n projectSddBoards: string;\n /** Persist task status transitions so a replacement process can resume. */\n taskStore?: TaskStore | undefined;\n registry?: SddRunRegistry | undefined;\n /** Isolated read-only LLM turn for the supervisor's auto-split. Omit \u2192 no split. */\n runIsolatedTurn?: ((prompt: string, name: string) => Promise<string>) | undefined;\n}\n\n/**\n * Start a multi-agent SDD run from a ready TaskGraph \u2014 the shared core behind\n * BOTH the wizard's `startRun` and launching a run from a kanban board. Builds a\n * TaskTracker from the graph (when none is supplied), sets up worktree isolation,\n * the completion-gate verifier and the Brain failure supervisor, then defers to\n * `startSddRun` (which owns the projector + cross-process control drain, so the\n * run is steerable from any surface). Resolves to the run handle after the\n * non-blocking git worktree capability probe completes.\n */\nexport async function startSddRunFromGraph(\n graph: TaskGraph,\n deps: StartSddRunFromGraphDeps,\n config: StartSddRunFromGraphConfig = {},\n tracker?: TaskTracker,\n): Promise<SddRunHandle> {\n const runTracker =\n tracker ??\n (() => {\n const t = new TaskTracker({ store: deps.taskStore ?? new DefaultTaskStore() });\n t.setGraph(graph);\n return t;\n })();\n\n // Per-task git-worktree isolation (per-run toggle wins; env default otherwise).\n const worktreesEnabled = config.worktrees ?? process.env['WRONGSTACK_SDD_WORKTREES'] !== '0';\n let worktrees: WorktreeManager | undefined;\n if (worktreesEnabled && (await isGitWorkTree(deps.projectRoot))) {\n void cleanupStaleSddWorktrees({\n projectRoot: deps.projectRoot,\n boardsDir: deps.projectSddBoards,\n stateTransport: 'kanban',\n }).catch(() => undefined);\n worktrees = new WorktreeManager({\n projectRoot: deps.projectRoot,\n events: deps.events,\n sessionId: () => deps.agent.ctx.session?.id,\n });\n }\n\n // Proactive planning-time decomposition: split leaves the atomicity engine\n // judged too large BEFORE dispatch, using the same graph surgery as run-time\n // splits. Auto mode \u2014 the wizard plan was already human-approved. Guarded by\n // config/env and bounded inside decomposeNonAtomicTasks (max 10 per graph).\n const planDecomposeEnabled =\n config.planDecompose ?? process.env['WRONGSTACK_SDD_PLAN_DECOMPOSE'] === '1';\n if (planDecomposeEnabled && deps.runIsolatedTurn) {\n try {\n const decomposition = await decomposeNonAtomicTasks({\n tracker: runTracker,\n decompose: makePlanningDecomposer({\n run: (prompt) => deps.runIsolatedTurn!(prompt, 'Task Splitter'),\n }),\n mode: 'auto',\n });\n for (const applied of decomposition.applied) {\n deps.events.emit('sdd.task.decomposed', {\n graphId: graph.id,\n taskId: applied.nodeId,\n subtaskIds: applied.subtaskIds,\n mode: 'auto',\n phase: 'planning',\n });\n }\n } catch {\n // Planning decomposition is best-effort \u2014 a failed splitter turn must\n // never block starting the run.\n }\n }\n\n const superviseFailure =\n deps.brain && deps.runIsolatedTurn\n ? new SddSupervisor({\n brain: deps.brain,\n reassignModels: config.fallbackModels,\n generateSubtasks: makeLlmSubtaskGenerator({\n run: (prompt) => deps.runIsolatedTurn!(prompt, 'Task Splitter'),\n }),\n requestLlmVerdict: true,\n }).superviseFailure\n : deps.brain\n ? new SddSupervisor({\n brain: deps.brain,\n reassignModels: config.fallbackModels,\n requestLlmVerdict: true,\n }).superviseFailure\n : undefined;\n\n return startSddRun({\n tracker: runTracker,\n graph,\n agent: deps.agent,\n projectRoot: deps.projectRoot,\n events: deps.events,\n sessionId: () => deps.agent.ctx.session?.id,\n subagentFactory: deps.subagentFactory,\n boardStore: new SddBoardStore({ baseDir: deps.projectSddBoards }),\n registry: deps.registry ?? new SddRunRegistry(),\n // Composite completion gate: the deterministic command check always runs;\n // the LLM acceptance-criteria judge is added only when an isolated-turn\n // runner exists (it degrades open on judge errors, so it can't wedge runs).\n verifyTask: deps.runIsolatedTurn\n ? makeCompositeVerifier([\n makeCommandVerifier(),\n makeAcceptanceCriteriaVerifier({\n run: (prompt) => deps.runIsolatedTurn!(prompt, 'Acceptance Reviewer'),\n }),\n ])\n : makeCommandVerifier(),\n ...(superviseFailure ? { superviseFailure } : {}),\n ...(config.parallelSlots !== undefined ? { parallelSlots: config.parallelSlots } : {}),\n ...(config.defaultModel !== undefined ? { defaultModel: config.defaultModel } : {}),\n ...(config.defaultProvider !== undefined ? { defaultProvider: config.defaultProvider } : {}),\n ...(config.fallbackModels !== undefined ? { fallbackModels: config.fallbackModels } : {}),\n ...(worktrees ? { worktrees } : {}),\n });\n}\n\nexport interface SddWizardWiringOptions {\n /** Leader agent \u2014 seeds the run's default factory + project context. */\n agent: Agent;\n /** Shared EventBus \u2014 the board projector emits sdd.board.snapshot on it. */\n events: EventBus;\n projectRoot: string;\n /** Per-task agent factory: CLI's director-backed one, or the runtime light one. */\n subagentFactory: AgentFactory;\n /**\n * Decision authority for the failure supervisor (the server's bound\n * TOKENS.BrainArbiter). Omit to run without a supervisor (plain terminal-fail,\n * matching a bare run) \u2014 but parity with the CLI wants it wired.\n */\n brain?: BrainArbiter | undefined;\n /** Persisted-store directories (from resolveWstackPaths). */\n paths: {\n projectSpecs: string;\n projectTaskGraphs: string;\n projectSddBoards: string;\n projectDir: string;\n /** Legacy interview session file imported into project workflow state. */\n projectSddSession?: string | undefined;\n };\n}\n\n/**\n * Prepended to every isolated interview/splitter turn. Keeps the spec interview\n * a pure planning conversation \u2014 no file writes, no shell \u2014 regardless of how\n * \"implement\"-flavoured the underlying phase prompt reads.\n */\nconst PLANNING_ONLY_GUARD =\n 'SYSTEM: You are running a PLANNING-ONLY specification interview. Do NOT write, ' +\n 'create, or edit any files, and do NOT run shell/terminal commands or use any ' +\n 'code-editing tools \u2014 they are disabled here and any attempt will fail and waste ' +\n 'the turn. Respond with TEXT ONLY: ask your question, or emit the requested spec / ' +\n 'plan / task JSON. All code is written later, automatically, once the plan is ' +\n 'approved and the multi-agent run starts.\\n\\n---\\n\\n';\n\n/**\n * Build the {@link SddWizardDeps} shared by both webui servers from a single\n * per-task `subagentFactory`. Gathers project context asynchronously (exposed\n * via `ensureReady`) so the first interview turn always sees package/src layout.\n */\nexport function buildSddWizardDeps(opts: SddWizardWiringOptions): SddWizardDeps {\n const registry = new SddRunRegistry();\n let isolatedSeq = 0;\n let projectContext = '';\n const contextReady = gatherProjectContext(opts.projectRoot)\n .then((ctx) => {\n projectContext = ctx;\n })\n .catch(() => {\n projectContext = '';\n });\n\n // Legacy session files are imported once; project-scoped IPC owns all new\n // interview state shared by CLI and standalone WebUI.\n const legacySessionPath =\n opts.paths.projectSddSession ?? path.join(opts.paths.projectDir, 'sdd-session.json');\n const sessionPersistence = createKanbanSddSessionPersistence(opts.projectRoot, legacySessionPath);\n const specStore = new SpecStore({ baseDir: opts.paths.projectSpecs });\n const graphStore = new TaskGraphStore({ baseDir: opts.paths.projectTaskGraphs });\n\n /**\n * Run one self-contained, read-only LLM turn on a fresh isolated agent (off the\n * main chat bus). Shared by the interview and the supervisor's subtask splitter.\n */\n const runIsolatedTurn = async (prompt: string, name: string): Promise<string> => {\n const result = await opts.subagentFactory({\n id: `sdd-${name.toLowerCase().replace(/\\s+/g, '-')}-${isolatedSeq++}`,\n role: 'executor',\n name,\n disabledTools: ['delegate', 'write', 'edit', 'patch', 'bash', 'exec'],\n allowedCapabilities: ['fs.read', 'net.outbound'],\n });\n try {\n const res = await result.agent.run([{ type: 'text', text: PLANNING_ONLY_GUARD + prompt }]);\n return res.finalText ?? '';\n } finally {\n await result.dispose?.();\n }\n };\n\n const makeDriver = (): SddInterviewDriver =>\n new SddInterviewDriver({\n specStore,\n graphStore,\n sessionPersistence,\n projectContext,\n });\n\n const launchFromGraph = async (\n graph: TaskGraph,\n config: SddRunStartOpts,\n tracker?: TaskTracker,\n ): Promise<{ runId: string }> => {\n const handle = await startSddRunFromGraph(\n graph,\n {\n agent: opts.agent,\n events: opts.events,\n projectRoot: opts.projectRoot,\n subagentFactory: opts.subagentFactory,\n projectSddBoards: opts.paths.projectSddBoards,\n taskStore: graphStore,\n registry,\n runIsolatedTurn,\n ...(opts.brain ? { brain: opts.brain } : {}),\n },\n {\n ...(config.parallelSlots !== undefined ? { parallelSlots: config.parallelSlots } : {}),\n ...(config.defaultModel !== undefined ? { defaultModel: config.defaultModel } : {}),\n ...(config.defaultProvider !== undefined\n ? { defaultProvider: config.defaultProvider }\n : {}),\n ...(config.fallbackModels !== undefined ? { fallbackModels: config.fallbackModels } : {}),\n ...(config.worktrees !== undefined ? { worktrees: config.worktrees } : {}),\n ...(config.planDecompose !== undefined ? { planDecompose: config.planDecompose } : {}),\n },\n tracker,\n );\n void handle.completion.catch(() => {});\n return { runId: handle.runId };\n };\n\n return {\n makeDriver,\n ensureReady: () => contextReady,\n\n runInterviewTurn: (prompt: string): Promise<string> =>\n runIsolatedTurn(prompt, 'Spec Architect'),\n\n startRun: async (driver, config) => {\n const graph = driver.getGraph();\n const tracker = driver.getTracker();\n if (!graph || !tracker) {\n throw new ToolValidationError({\n message: 'No task graph to run \u2014 finish the interview first.',\n field: 'taskGraph',\n });\n }\n return launchFromGraph(graph, config, tracker);\n },\n\n startRunFromGraphId: async (graphId, config) => {\n const graph = await graphStore.load(graphId);\n if (!graph) {\n throw new ToolValidationError({\n message: `Task graph not found: ${graphId}`,\n field: 'graphId',\n });\n }\n return launchFromGraph(graph, config);\n },\n\n resolveGraphIdForSpec: async (specId) => {\n const entry = (await graphStore.list()).find((g) => g.specId === specId);\n return entry?.id ?? null;\n },\n };\n}\n", "import type { SddInterviewDriver, SddInterviewSnapshot } from '@wrongstack/sdd';\nimport type { WebSocket } from 'ws';\nimport { sendSerialized } from './ws-utils.js';\n\ninterface WSClient {\n ws: WebSocket;\n id: string;\n}\n\ninterface WizardMessage {\n type: string;\n payload?: Record<string, unknown>;\n}\n\n/** Short, single-line heading derived from a (possibly long) goal prompt. */\nfunction deriveTitle(goal: string): string {\n const firstLine = goal\n .split('\\n')\n .map((l) => l.trim())\n .find(Boolean);\n if (!firstLine) return 'New SDD Project';\n const sentence = firstLine.split(/(?<=[.!?])\\s/)[0] ?? firstLine;\n return sentence.length <= 64 ? sentence : `${sentence.slice(0, 63).trimEnd()}\u2026`;\n}\n\nexport interface SddRunStartOpts {\n parallelSlots?: number | undefined;\n defaultModel?: string | undefined;\n defaultProvider?: string | undefined;\n fallbackModels?: string[] | undefined;\n /** Per-run worktree-isolation override; undefined \u2192 env default. */\n worktrees?: boolean | undefined;\n /** Planning-time non-atomic task split before dispatch. */\n planDecompose?: boolean | undefined;\n}\n\n/**\n * Dependencies each webui server supplies. The handler is deliberately\n * agent-agnostic: every surface decides how to build a driver, how to run an\n * interview turn (on an isolated agent, off the main chat bus), and how to\n * start the real multi-agent run (CLI's director-backed factory vs the runtime\n * light factory). This keeps the wizard protocol identical across both servers.\n */\nexport interface SddWizardDeps {\n /** Build a fresh interview driver (artifact stores + durable session owner). */\n makeDriver: () => SddInterviewDriver;\n /**\n * Await before the first message / client snapshot so project context and any\n * durable resume finish loading. Optional for unit tests that inject a ready driver.\n */\n ensureReady?: (() => Promise<void>) | undefined;\n /**\n * Run one interview turn: feed the AI prompt to an isolated agent and return\n * its final text. MUST NOT run on the main chat agent's bus \u2014 the wizard owns\n * this conversation, separate from the user's chat.\n */\n runInterviewTurn: (prompt: string) => Promise<string>;\n /**\n * Start the real multi-agent SDD run for the driver's task graph. Returns the\n * runId; the live board flows through the existing board handler.\n */\n startRun: (driver: SddInterviewDriver, opts: SddRunStartOpts) => Promise<{ runId: string }>;\n /**\n * Start a multi-agent SDD run from an already-persisted task graph (Specs\n * \"Run as SDD\"). Omit \u2192 `sdd.run.from_graph` / `sdd.run.from_spec` error.\n */\n startRunFromGraphId?:\n | ((graphId: string, opts: SddRunStartOpts) => Promise<{ runId: string }>)\n | undefined;\n /**\n * Resolve the latest task-graph id for a persisted spec. Used by\n * `sdd.run.from_spec`. Omit \u2192 that message type is unavailable.\n */\n resolveGraphIdForSpec?: ((specId: string) => Promise<string | null>) | undefined;\n}\n\n/**\n * SddWizardWebSocketHandler \u2014 drives the interactive \"New SDD Project\" wizard\n * (goal \u2192 Q&A \u2192 spec \u2192 task graph \u2192 start run) over WebSocket. Shared by both\n * webui servers; server-specific construction (agent, factory) is injected via\n * {@link SddWizardDeps}.\n *\n * Continuity: on construction (and before the first client message) the handler\n * rehydrates the durable interview session so a browser refresh or process\n * restart resumes mid-Q&A / mid-review without re-running the model.\n */\nexport class SddWizardWebSocketHandler {\n private readonly clients = new Set<WSClient>();\n private driver: SddInterviewDriver | null = null;\n /** The agent's most recent question \u2014 paired with the next user answer. */\n private lastAgentText = '';\n /** Guards against overlapping interview turns (one in flight at a time). */\n private busy = false;\n /** Set when authoritative session state could not be read during bootstrap. */\n private resumeError: string | null = null;\n /** Resolves once project-context gather + durable resume finish. */\n private readonly ready: Promise<void>;\n /**\n * Single-flight slot for the resume probe. `handleMessage` awaits this\n * when `resumeError` is set, so concurrent frames cannot race the retry\n * \u2014 one probe either clears the gate or re-latches it, then every\n * queued frame re-checks and proceeds. `null` when no probe is in\n * flight (or after the probe has settled).\n */\n private resumeProbe: Promise<void> | null = null;\n\n constructor(private readonly deps: SddWizardDeps) {\n this.ready = this.bootstrap();\n }\n\n private async bootstrap(): Promise<void> {\n try {\n await this.deps.ensureReady?.();\n } catch {\n // Context gather is best-effort.\n }\n await this.tryResume();\n }\n\n /** Rehydrate a persisted interview if one exists. */\n private async tryResume(): Promise<void> {\n if (this.driver) return;\n // Keep any previous error latched while the probe is in flight. Clearing\n // it before `loadExisting()` settles would let another concurrent frame\n // bypass the fail-closed gate and start a second session. The error is\n // released only after the authoritative read succeeds.\n try {\n const driver = this.deps.makeDriver();\n if (await driver.loadExisting()) {\n this.driver = driver;\n this.lastAgentText = driver.getLastAgentText() ?? '';\n }\n this.resumeError = null;\n } catch (error) {\n // IPC failure cannot prove that no session exists. Fail closed so a fresh\n // start cannot overwrite another process's interview.\n this.driver = null;\n this.lastAgentText = '';\n this.resumeError = error instanceof Error ? error.message : String(error);\n }\n }\n\n addClient(ws: WebSocket): void {\n const client: WSClient = { ws, id: crypto.randomUUID() };\n this.clients.add(client);\n ws.on('close', () => this.clients.delete(client));\n ws.on('error', () => this.clients.delete(client));\n // Catch up reconnecting clients after resume completes.\n void this.ready.then(() => {\n if (this.resumeError) {\n this.send(client, { type: 'sdd.spec.error', payload: { message: this.resumeError } });\n return;\n }\n if (this.driver) {\n this.send(client, this.snapshotMsg());\n if (this.lastAgentText) {\n this.send(client, { type: 'sdd.spec.agent_text', payload: { text: this.lastAgentText } });\n }\n }\n });\n }\n\n async handleMessage(msg: WizardMessage): Promise<void> {\n try {\n await this.ready;\n if (this.resumeError) {\n // Latched transient failure. A surviving client message must not\n // be silently dropped \u2014 re-probe the IPC layer so a recovered\n // daemon unblocks the wizard on the very next frame. Concurrent\n // frames await the same in-flight probe to avoid stampeding the\n // IPC client (single-flight via `resumeProbe`).\n if (this.resumeProbe === null) {\n // Defer the actual probe by one microtask so the single-flight slot\n // is published before `makeDriver` or `loadExisting` can re-enter.\n const probe = Promise.resolve().then(() => this.tryResume());\n this.resumeProbe = probe;\n void probe.finally(() => {\n // Keep a settled probe visible through the rest of this event-loop\n // turn. Concurrent WebSocket frames may resume from `await ready`\n // in separate microtasks; clearing immediately would let the later\n // frame start a duplicate IPC probe after the first one settled.\n setTimeout(() => {\n if (this.resumeProbe === probe) this.resumeProbe = null;\n }, 0);\n });\n }\n await this.resumeProbe;\n if (this.resumeError) {\n // Re-probe did not recover; broadcast the error and reject.\n this.broadcast({ type: 'sdd.spec.error', payload: { message: this.resumeError } });\n return;\n }\n }\n switch (msg.type) {\n case 'sdd.spec.start':\n await this.onStart(String(msg.payload?.goal ?? '').trim(), {\n force: msg.payload?.force === true,\n });\n break;\n case 'sdd.spec.message':\n await this.onMessage(String(msg.payload?.text ?? ''));\n break;\n case 'sdd.spec.approve':\n await this.onApprove();\n break;\n case 'sdd.spec.get':\n if (this.driver) {\n this.broadcast(this.snapshotMsg());\n if (this.lastAgentText) {\n this.broadcast({\n type: 'sdd.spec.agent_text',\n payload: { text: this.lastAgentText },\n });\n }\n }\n break;\n case 'sdd.spec.discard':\n await this.onDiscard();\n break;\n case 'sdd.run.start':\n await this.onRunStart(this.parseRunOpts(msg.payload));\n break;\n case 'sdd.run.from_graph':\n await this.onRunFromGraph(\n String(msg.payload?.graphId ?? '').trim(),\n this.parseRunOpts(msg.payload),\n );\n break;\n case 'sdd.run.from_spec':\n await this.onRunFromSpec(\n String(msg.payload?.specId ?? '').trim(),\n this.parseRunOpts(msg.payload),\n );\n break;\n }\n } catch (err) {\n this.busy = false;\n this.broadcast({\n type: 'sdd.spec.error',\n payload: { message: err instanceof Error ? err.message : String(err) },\n });\n }\n }\n\n // \u2500\u2500 message handlers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private parseRunOpts(payload?: Record<string, unknown>): SddRunStartOpts {\n return {\n parallelSlots: payload?.parallelSlots as number | undefined,\n defaultModel:\n (payload?.model as string | undefined) ?? (payload?.defaultModel as string | undefined),\n defaultProvider:\n (payload?.provider as string | undefined) ??\n (payload?.defaultProvider as string | undefined),\n fallbackModels: Array.isArray(payload?.fallbackModels)\n ? (payload?.fallbackModels as string[])\n : undefined,\n worktrees: typeof payload?.worktrees === 'boolean' ? payload.worktrees : undefined,\n planDecompose:\n typeof payload?.planDecompose === 'boolean' ? payload.planDecompose : undefined,\n };\n }\n\n private async onStart(goal: string, opts: { force?: boolean }): Promise<void> {\n if (!goal) {\n this.broadcast({ type: 'sdd.spec.error', payload: { message: 'A goal is required.' } });\n return;\n }\n if (this.busy) return;\n\n // Resume-friendly: an in-progress interview is kept unless the operator\n // explicitly forces a new start (discard-then-start, or force: true).\n if (this.driver && !opts.force) {\n const phase = this.driver.phase();\n const midInterview =\n phase === 'questioning' ||\n phase === 'spec_review' ||\n phase === 'implementation' ||\n phase === 'task_review';\n if (midInterview) {\n // Still mid-flow \u2014 surface the existing session instead of clobbering.\n this.broadcast(this.snapshotMsg());\n if (this.lastAgentText) {\n this.broadcast({ type: 'sdd.spec.agent_text', payload: { text: this.lastAgentText } });\n }\n this.broadcast({\n type: 'sdd.spec.error',\n payload: {\n message:\n 'An interview is already in progress. Continue it, or discard and start a new one.',\n },\n });\n return;\n }\n }\n\n // Force / post-completion restart: drop any leftover on-disk session first so\n // a crash mid-start cannot rehydrate the previous interview.\n if (opts.force || this.driver) {\n try {\n if (this.driver) await this.driver.discard();\n else await this.deps.makeDriver().discard();\n } catch {\n /* best-effort */\n }\n }\n this.driver = this.deps.makeDriver();\n this.lastAgentText = '';\n // Keep the operator's full prompt as the interview's intent/goal, but give\n // the session a short readable title \u2014 pasting the whole prompt as the title\n // made the wizard header unreadable.\n const prompt = this.driver.start(deriveTitle(goal), goal);\n await this.runTurn(prompt);\n }\n\n private async onDiscard(): Promise<void> {\n if (this.busy) return;\n if (this.driver) {\n await this.driver.discard();\n } else {\n // Still clear any on-disk session even if we never loaded a driver.\n const d = this.deps.makeDriver();\n await d.discard();\n }\n this.driver = null;\n this.lastAgentText = '';\n this.broadcast({\n type: 'sdd.spec.snapshot',\n payload: { phase: 'idle', busy: false, discarded: true },\n });\n }\n\n private async onMessage(text: string): Promise<void> {\n if (!this.driver || this.busy) return;\n // In the questioning phase, the user's message answers the agent's last\n // question. In review phases a free-form message is fed back as context.\n if (this.driver.phase() === 'questioning' && this.lastAgentText) {\n this.driver.submitAnswer(this.lastAgentText, text);\n } else {\n this.driver.submitAnswer(this.lastAgentText || '(feedback)', text);\n }\n await this.runTurn(this.driver.currentPrompt());\n }\n\n private async onApprove(): Promise<void> {\n if (!this.driver || this.busy) return;\n const { phase, prompt } = await this.driver.approve();\n // Executing phase needs no further AI turn \u2014 the graph is ready to run.\n if (phase === 'executing') {\n this.broadcast(this.snapshotMsg());\n return;\n }\n await this.runTurn(prompt);\n }\n\n private async onRunStart(opts: SddRunStartOpts): Promise<void> {\n if (!this.driver) {\n this.broadcast({ type: 'sdd.spec.error', payload: { message: 'No active spec session.' } });\n return;\n }\n // Guarantee a graph exists (deterministic fallback if the agent never\n // emitted a task array).\n const graph = await this.driver.ensureTaskGraph();\n if (!graph) {\n this.broadcast({\n type: 'sdd.spec.error',\n payload: { message: 'No spec yet \u2014 finish the interview before starting a run.' },\n });\n return;\n }\n const { runId } = await this.deps.startRun(this.driver, opts);\n await this.driver.setLastRunId(runId);\n // Persist \"executing\" so a restart can deep-link to the live board.\n if (this.driver.phase() !== 'executing' && this.driver.phase() !== 'done') {\n try {\n // Approve into executing if still on task_review.\n if (this.driver.phase() === 'task_review') await this.driver.approve();\n } catch {\n /* phase already advanced */\n }\n }\n await this.driver.builder.saveSession();\n this.broadcast({ type: 'sdd.run.started', payload: { runId } });\n this.broadcast(this.snapshotMsg());\n }\n\n private async onRunFromGraph(graphId: string, opts: SddRunStartOpts): Promise<void> {\n if (!graphId) {\n this.broadcast({ type: 'sdd.spec.error', payload: { message: 'graphId is required.' } });\n return;\n }\n if (!this.deps.startRunFromGraphId) {\n this.broadcast({\n type: 'sdd.spec.error',\n payload: { message: 'SDD run-from-graph is not available on this host.' },\n });\n return;\n }\n const { runId } = await this.deps.startRunFromGraphId(graphId, opts);\n this.broadcast({ type: 'sdd.run.started', payload: { runId, graphId } });\n }\n\n private async onRunFromSpec(specId: string, opts: SddRunStartOpts): Promise<void> {\n if (!specId) {\n this.broadcast({ type: 'sdd.spec.error', payload: { message: 'specId is required.' } });\n return;\n }\n if (!this.deps.resolveGraphIdForSpec || !this.deps.startRunFromGraphId) {\n this.broadcast({\n type: 'sdd.spec.error',\n payload: { message: 'SDD run-from-spec is not available on this host.' },\n });\n return;\n }\n const graphId = await this.deps.resolveGraphIdForSpec(specId);\n if (!graphId) {\n this.broadcast({\n type: 'sdd.spec.error',\n payload: { message: 'No task graph found for this specification.' },\n });\n return;\n }\n const { runId } = await this.deps.startRunFromGraphId(graphId, opts);\n this.broadcast({ type: 'sdd.run.started', payload: { runId, graphId, specId } });\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Run one interview turn against the isolated agent, then ingest + broadcast. */\n private async runTurn(prompt: string): Promise<void> {\n this.busy = true;\n this.broadcast(this.snapshotMsg());\n try {\n const text = await this.deps.runInterviewTurn(prompt);\n this.lastAgentText = text;\n if (this.driver) {\n await this.driver.ingestAgentOutput(text);\n await this.driver.setLastAgentText(text);\n }\n this.broadcast({ type: 'sdd.spec.agent_text', payload: { text } });\n } finally {\n this.busy = false;\n this.broadcast(this.snapshotMsg());\n }\n }\n\n private snapshotMsg(): { type: string; payload: SddInterviewSnapshot & { busy: boolean } } {\n const snap = this.driver?.snapshot();\n return {\n type: 'sdd.spec.snapshot',\n payload: { ...(snap as SddInterviewSnapshot), busy: this.busy },\n };\n }\n\n private broadcast(msg: { type: string; payload: unknown }): void {\n const data = JSON.stringify(msg);\n for (const client of this.clients) {\n sendSerialized(client.ws, data);\n }\n }\n\n private send(client: WSClient, msg: { type: string; payload: unknown }): void {\n sendSerialized(client.ws, JSON.stringify(msg));\n }\n}\n", "import type { Context } from '@wrongstack/core/agent';\nimport type {\n EventBus,\n EventName,\n Listener,\n} from '@wrongstack/core/kernel';\nimport type { SessionEventBridge } from '@wrongstack/core/storage';\nimport type { WstackPaths } from '@wrongstack/core/utils';\nimport { recordTaskFileActivity } from '@wrongstack/kanban';\nimport type { WebSocket } from 'ws';\nimport { extractCodeMapFileTargets, normalizeCodeMapFileTarget } from './codemap-telemetry.js';\nimport type { PendingConfirm } from './pending-confirms.js';\nimport type { SetupEventProjection } from './setup-event-projection.js';\nimport { registerSetupEventsFleetBroadcaster } from './setup-events-fleet-broadcaster.js';\nimport { registerSetupEventsProviderHandlers } from './setup-events-provider-handlers.js';\nimport { createSetupEventSessionHelpers } from './setup-events-session-helpers.js';\nimport { registerSetupEventsStatusWatcher } from './setup-events-status-watcher.js';\nimport {\n registerSetupEventsClientStatusWriter,\n registerSetupEventsCoreWatchers,\n} from './setup-events-core-watchers.js';\nimport type { FileWatcherMetrics } from './setup-events-watcher.js';\nimport type { ConnectedClient, WSServerMessage } from './types.js';\nexport type { FileWatcherMetrics } from './setup-events-watcher.js';\n\nexport interface SetupEventsDeps {\n events: EventBus;\n broadcast: (clients: Map<WebSocket, ConnectedClient>, msg: WSServerMessage) => void;\n clients: Map<WebSocket, ConnectedClient>;\n config: { tools?: { maxIterations?: number | undefined } };\n context: Context;\n pendingConfirms: Map<string, PendingConfirm>;\n /** Optional global config dir (~/.wrongstack) \u2014 enables SessionRegistry poll for fleet view. */\n globalConfigPath?: string | undefined;\n /**\n * Audit-level-aware session log bridge. When provided, tool/error/provider\n * events are persisted to the session JSONL (same contract as the CLI) \u2014\n * without it, standalone-WebUI sessions carry no audit events and resume\n * with no tool history.\n */\n sessionBridge?: SessionEventBridge | undefined;\n /** Optional wpaths for writing status.json file. */\n wpaths?: WstackPaths | undefined;\n /** Optional live file-watcher metrics sink. */\n watcherMetrics?: FileWatcherMetrics | undefined;\n /**\n * Receives the internal `broadcastSessions` fn so the HTTP layer can trigger\n * an immediate fleet re-broadcast on `POST /api/fleet/ping` (push-on-write\n * from a TUI/REPL), instead of waiting on the registry file-watch/poll.\n */\n onFleetBroadcaster?: ((fn: () => Promise<void>) => void) | undefined;\n /** Optional high-volume/sensitive event adapter used by embedded hosts. */\n projection?: SetupEventProjection | undefined;\n}\n\nexport { statusProjectHashFromWatchFilename } from './setup-events-watcher.js';\n\n/**\n * Wire kernel events to WS broadcasts and (when wpaths/globalConfigPath are\n * given) start the status-file watcher and session-poll interval.\n *\n * Returns a disposer that stops the watcher, clears the metrics/poll\n * intervals, and flushes pending debounce timers. Callers MUST invoke it on\n * shutdown \u2014 the watcher is `persistent: true` and the metrics interval is not\n * `unref`'d, so without disposal they keep the process alive and leak across\n * server restarts. (Previously this was hung off a non-existent\n * `process.on('cleanup')` event that never fired.)\n */\nexport function setupEvents(deps: SetupEventsDeps): () => void {\n const {\n events,\n broadcast,\n clients,\n config,\n context,\n pendingConfirms,\n globalConfigPath,\n sessionBridge,\n wpaths,\n watcherMetrics,\n onFleetBroadcaster,\n projection,\n } = deps;\n const scrub = <T>(value: T): T => (projection?.scrubObject?.(value) ?? value) as T;\n const disposers: Array<() => void> = [];\n let disposed = false;\n const on = <E extends EventName>(event: E, listener: Listener<E>): void => {\n disposers.push(events.on(event, listener));\n };\n disposers.push(\n ...registerSetupEventsCoreWatchers({ events, broadcast, clients, context, wpaths }),\n );\n const projectRoot = context.projectRoot;\n const { sessionPayload, appendForCurrentSession } = createSetupEventSessionHelpers(\n context,\n sessionBridge,\n );\n\n on('iteration.started', (e) => {\n // Read maxIterations from context.meta so the UI reflects the\n // webui setting, falling back to the startup config default.\n const maxIt =\n typeof context.meta['maxIterations'] === 'number'\n ? context.meta['maxIterations']\n : (config.tools?.maxIterations ?? 100);\n broadcast(clients, {\n type: 'iteration.started',\n payload: sessionPayload({ sessionId: e.sessionId, index: e.index, maxIterations: maxIt }),\n });\n });\n\n on('iteration.completed', (e) => {\n broadcast(clients, {\n type: 'iteration.completed',\n payload: sessionPayload({\n sessionId: e.sessionId,\n index: e.index,\n totalIterations: e.index + 1,\n }),\n });\n });\n\n on('iteration.limit_reached', (e) => {\n broadcast(clients, {\n type: 'iteration.limit_reached',\n payload: sessionPayload({\n sessionId: e.sessionId,\n currentIterations: e.currentIterations,\n currentLimit: e.currentLimit,\n }),\n });\n });\n\n on('provider.text_delta', (e) => {\n if (projection?.queueTextDelta) {\n projection.flushThinkingDelta?.();\n projection.queueTextDelta(e.text, e.sessionId);\n return;\n }\n broadcast(clients, {\n type: 'provider.text_delta',\n payload: sessionPayload({ sessionId: e.sessionId, text: e.text, messageId: 'current' }),\n });\n });\n\n on('provider.thinking_delta', (e) => {\n if (projection?.queueThinkingDelta) {\n projection.queueThinkingDelta(e.text, e.sessionId);\n return;\n }\n broadcast(clients, {\n type: 'provider.thinking_delta',\n payload: sessionPayload({ sessionId: e.sessionId, text: e.text }),\n });\n });\n\n on('provider.stream_error', (e) => {\n broadcast(clients, {\n type: 'provider.stream_error',\n payload: sessionPayload({ sessionId: e.sessionId, eventType: e.eventType, message: e.msg }),\n });\n });\n\n on('tool.started', (e) => {\n projection?.flushAllStreamBuffers?.();\n broadcast(clients, {\n type: 'tool.started',\n payload: sessionPayload({\n sessionId: e.sessionId,\n traceId: e.traceId,\n agentId: e.agentId,\n agentName: e.agentName,\n id: e.id,\n name: e.name,\n input: scrub(e.input),\n fileTargets: extractCodeMapFileTargets(projectRoot || '.', e.name, e.input),\n messageId: `tool_${e.id}`,\n }),\n });\n // Persist for audit + resume tool history (respects auditLevel).\n appendForCurrentSession(e.sessionId, {\n type: 'tool_call_start',\n ts: new Date().toISOString(),\n name: e.name,\n id: e.id,\n input: scrub(e.input),\n });\n });\n\n on('tool.progress', (e) => {\n const rawProgressPath =\n e.event.path ??\n (typeof e.event.data?.['path'] === 'string' ? e.event.data['path'] : undefined);\n const progressTarget = rawProgressPath\n ? normalizeCodeMapFileTarget(\n projectRoot || '.',\n rawProgressPath,\n e.event.operation ?? 'edit',\n e.event.line,\n e.event.endLine,\n )\n : undefined;\n const progressPayload = sessionPayload({\n sessionId: e.sessionId,\n traceId: e.traceId,\n agentId: e.agentId,\n agentName: e.agentName,\n id: e.id,\n name: e.name,\n event: {\n type: e.event.type,\n text: e.event.text,\n data: e.event.data,\n path: progressTarget?.filePath,\n operation: e.event.operation,\n line: progressTarget?.line,\n endLine: progressTarget?.endLine,\n },\n });\n if (projection?.queueToolProgress) {\n projection.queueToolProgress(progressPayload);\n } else\n broadcast(clients, {\n type: 'tool.progress',\n // Nested `event` shape \u2014 the client handler reads `payload.event?.text`\n // and early-returns on a falsy text, so a flat { eventType, text } payload\n // makes live tool progress (bash streaming, partial_output, warnings)\n // never render. Must match WSToolProgress and the CLI server.\n payload: progressPayload,\n });\n appendForCurrentSession(e.sessionId, {\n type: 'tool_progress',\n ts: new Date().toISOString(),\n name: e.name,\n id: e.id,\n event: {\n type: e.event.type,\n ...(e.event.text !== undefined ? { text: e.event.text } : {}),\n ...(e.event.data !== undefined ? { data: e.event.data } : {}),\n },\n });\n });\n\n on('tool.executed', (e) => {\n projection?.flushAllStreamBuffers?.();\n broadcast(clients, {\n type: 'tool.executed',\n payload: sessionPayload({\n sessionId: e.sessionId,\n traceId: e.traceId,\n agentId: e.agentId,\n agentName: e.agentName,\n id: e.id,\n name: e.name,\n durationMs: e.durationMs,\n ok: e.ok,\n input: scrub(e.input),\n fileTargets: extractCodeMapFileTargets(projectRoot || '.', e.name, e.input),\n output: scrub(e.output),\n // SAGE-injected memory rides beside the tool text so the client renders\n // it as a memory card. Never folded back into `output`.\n ...(e.sage && e.sage.length > 0 ? { sage: e.sage.map((line) => scrub(line)) } : {}),\n outputBytes: e.outputBytes,\n outputTokens: e.outputTokens,\n outputLines: e.outputLines,\n metadata: e.metadata,\n }),\n });\n appendForCurrentSession(e.sessionId, {\n type: 'tool_call_end',\n ts: new Date().toISOString(),\n name: e.name,\n id: e.id ?? '',\n durationMs: e.durationMs,\n outputSize: e.outputBytes ?? 0,\n ok: e.ok,\n outputBytes: e.outputBytes,\n outputTokens: e.outputTokens,\n outputLines: e.outputLines,\n });\n broadcast(clients, {\n type: 'todos.updated',\n payload: sessionPayload({ sessionId: e.sessionId, todos: [...context.todos] }),\n });\n\n // P2 #5: push updated side effects after every tool execution so the\n // Audit tab refreshes automatically \u2014 no manual refresh needed.\n const sideEffects = context.sideEffects ?? [];\n if (sideEffects.length > 0) {\n broadcast(clients, {\n type: 'side_effects',\n payload: sessionPayload({\n sessionId: e.sessionId,\n sideEffects: sideEffects.slice(-50).map((se) => ({\n toolUseId: se.toolUseId,\n toolName: se.toolName,\n ts: se.ts,\n input: se.input,\n outcome: se.outcome,\n risk: se.risk,\n })),\n }),\n });\n }\n\n // Broadcast task/plan updates after task/plan/todo tool executions.\n if (e.name === 'task' || e.name === 'plan' || e.name === 'todo') {\n void (async () => {\n try {\n const taskPath = (context.meta as Record<string, unknown>)['task.path'];\n if (typeof taskPath === 'string' && taskPath) {\n const { loadTasks } = await import('@wrongstack/core/storage');\n const file = await loadTasks(taskPath);\n broadcast(clients, {\n type: 'tasks.updated',\n payload: sessionPayload({ sessionId: e.sessionId, tasks: file?.tasks ?? [] }),\n });\n }\n } catch {\n /* best-effort */\n }\n try {\n const planPath = (context.meta as Record<string, unknown>)['plan.path'];\n if (typeof planPath === 'string' && planPath) {\n const { loadPlan } = await import('@wrongstack/core/storage');\n const plan = await loadPlan(planPath);\n broadcast(clients, {\n type: 'plan.updated',\n payload: sessionPayload({\n sessionId: e.sessionId,\n plan: plan ?? {\n version: 1,\n sessionId: e.sessionId ?? context.session?.id ?? '',\n updatedAt: new Date().toISOString(),\n items: [],\n },\n }),\n });\n }\n } catch {\n /* best-effort */\n }\n })();\n }\n });\n\n on('file.activity', (e) => {\n broadcast(clients, { type: 'codemap.file_event', payload: e });\n });\n\n on('codemap.index_updated', (e) => {\n broadcast(clients, { type: 'codemap.index_updated', payload: e });\n });\n\n on('file.event', (e) => {\n if (e.scope !== 'task' || !e.boardId || !e.taskId || !projectRoot) return;\n void recordTaskFileActivity(projectRoot, e.boardId, e.taskId, e)\n .then((recorded) => {\n if (recorded) {\n broadcast(clients, {\n type: 'kanban.task.activity.changed',\n payload: { boardId: e.boardId, taskId: e.taskId },\n });\n }\n })\n .catch(() => {});\n });\n\n on('tool.loop_detected', (e) => {\n broadcast(clients, {\n type: 'tool.loop_detected',\n payload: sessionPayload({\n sessionId: e.sessionId,\n tools: e.tools,\n repeatCount: e.repeatCount,\n iteration: e.iteration,\n kind: e.kind,\n action: e.action,\n scope: e.scope,\n }),\n });\n });\n\n on('trust.persisted', (e) => {\n broadcast(clients, {\n type: 'trust.persisted',\n payload: sessionPayload({\n sessionId: e.sessionId,\n tool: e.tool,\n pattern: e.pattern,\n decision: e.decision,\n }),\n });\n });\n\n on('delegate.started', (e) => {\n broadcast(clients, {\n type: 'delegate.started',\n payload: sessionPayload({ sessionId: e.sessionId, target: e.target, task: e.task }),\n });\n });\n\n on('delegate.completed', (e) => {\n broadcast(clients, {\n type: 'delegate.completed',\n payload: sessionPayload({\n sessionId: e.sessionId,\n target: e.target,\n task: e.task,\n ok: e.ok,\n status: e.status,\n summary: e.summary,\n durationMs: e.durationMs,\n iterations: e.iterations,\n toolCalls: e.toolCalls,\n costUsd: e.costUsd,\n subagentId: e.subagentId,\n }),\n });\n });\n\n registerSetupEventsProviderHandlers({\n on,\n broadcast,\n clients,\n projection,\n sessionPayload,\n });\n\n on('tool.confirm_needed', (e) => {\n const id = e.toolUseId ?? `confirm_${Date.now()}`;\n const payload = sessionPayload({\n sessionId: e.sessionId,\n id,\n toolName: e.tool?.name ?? 'unknown',\n input: scrub(e.input),\n suggestedPattern: e.suggestedPattern,\n decisionSource: e.decisionSource,\n riskTier: e.riskTier,\n boundaryReason: e.boundaryReason,\n });\n pendingConfirms.set(id, {\n resolve: e.resolve,\n decisionSource: e.decisionSource,\n riskTier: e.riskTier,\n boundaryReason: e.boundaryReason,\n payload,\n });\n broadcast(clients, { type: 'tool.confirm_needed', payload });\n });\n\n on('error', (e) => {\n broadcast(clients, {\n type: 'error',\n payload: sessionPayload({\n sessionId: e.sessionId,\n phase: e.phase,\n message: e.err instanceof Error ? e.err.message : String(e.err),\n }),\n });\n appendForCurrentSession(e.sessionId, {\n type: 'error',\n ts: new Date().toISOString(),\n message: e.err instanceof Error ? e.err.message : String(e.err),\n phase: e.phase,\n });\n });\n\n on('session.damaged', (e) => {\n broadcast(clients, {\n type: 'session.damaged',\n payload: { sessionId: e.sessionId, detail: e.detail },\n });\n });\n\n on('session.rewound', (e) => {\n broadcast(clients, {\n type: 'session.rewound',\n payload: sessionPayload({\n sessionId: e.sessionId,\n toPromptIndex: e.toPromptIndex,\n revertedFiles: e.revertedFiles,\n removedEvents: e.removedEvents,\n }),\n });\n });\n\n on('checkpoint.written', (e) => {\n broadcast(clients, {\n type: 'checkpoint.written',\n payload: sessionPayload({\n sessionId: e.sessionId,\n promptIndex: e.promptIndex,\n promptPreview: e.promptPreview,\n ts: e.ts,\n fileCount: e.fileCount,\n }),\n });\n });\n\n on('in_flight.started', (e) => {\n broadcast(clients, {\n type: 'in_flight.started',\n payload: sessionPayload({ sessionId: e.sessionId, context: e.context, ts: e.ts }),\n });\n });\n\n on('in_flight.ended', (e) => {\n broadcast(clients, {\n type: 'in_flight.ended',\n payload: sessionPayload({ sessionId: e.sessionId, reason: e.reason, ts: e.ts }),\n });\n });\n\n // Provider visibility \u2014 retry storms and provider failures in the JSONL\n // for forensics, mirroring the CLI's bridge wiring.\n on('provider.retry', (e) => {\n broadcast(clients, {\n type: 'provider.retry',\n payload: sessionPayload({\n sessionId: e.sessionId,\n providerId: e.providerId,\n attempt: e.attempt,\n delayMs: e.delayMs,\n status: e.status,\n description: e.description,\n }),\n });\n appendForCurrentSession(e.sessionId, {\n type: 'provider_retry',\n ts: new Date().toISOString(),\n providerId: e.providerId,\n attempt: e.attempt,\n delayMs: e.delayMs,\n status: e.status,\n description: e.description,\n });\n });\n\n on('provider.status_changed', (e) => {\n broadcast(clients, {\n type: 'provider.status_changed',\n payload: sessionPayload({\n providerId: e.providerId,\n model: e.model,\n oldState: e.oldState,\n newState: e.newState,\n reason: e.reason,\n timestamp: e.timestamp,\n stateExpiresAt: e.stateExpiresAt,\n }),\n });\n });\n\n on('provider.active_blocked', (e) => {\n broadcast(clients, {\n type: 'provider.active_blocked',\n payload: sessionPayload({\n sessionId: e.sessionId,\n providerId: e.providerId,\n model: e.model,\n state: e.state,\n fallbackProviderId: e.fallbackProviderId,\n fallbackModel: e.fallbackModel,\n lastError: e.lastError,\n timestamp: e.timestamp,\n }),\n });\n });\n\n on('provider.error', (e) => {\n broadcast(clients, {\n type: 'provider.error',\n payload: sessionPayload({\n sessionId: e.sessionId,\n providerId: e.providerId,\n status: e.status,\n description: e.description,\n retryable: e.retryable,\n }),\n });\n appendForCurrentSession(e.sessionId, {\n type: 'provider_error',\n ts: new Date().toISOString(),\n providerId: e.providerId,\n status: e.status,\n description: e.description,\n retryable: e.retryable,\n });\n });\n\n on('provider.fallback', (e) => {\n broadcast(clients, {\n type: 'provider.fallback',\n payload: sessionPayload({\n sessionId: e.sessionId,\n from: e.from,\n to: e.to,\n status: e.status,\n providerSwitched: e.providerSwitched,\n }),\n });\n });\n\n on('compaction.fired', (e) => {\n broadcast(clients, {\n type: 'context.compacted',\n payload: sessionPayload({\n sessionId: e.sessionId,\n before: e.report.before,\n after: e.report.after,\n saved: Math.max(0, e.report.before - e.report.after),\n reductions: e.report.reductions,\n }),\n });\n });\n\n on('compaction.failed', (e) => {\n broadcast(clients, {\n type: 'compaction.failed',\n payload: sessionPayload({\n sessionId: e.sessionId,\n message: e.err.message,\n aggressive: e.aggressive,\n level: e.level,\n tokens: e.tokens,\n maxContext: e.maxContext,\n load: e.load,\n fatal: e.fatal,\n }),\n });\n });\n\n on('mcp.server.connected', (e) => {\n broadcast(clients, {\n type: 'mcp.server.connected',\n payload: { name: e.name, toolCount: e.toolCount },\n });\n });\n\n on('mcp.server.reconnected', (e) => {\n broadcast(clients, {\n type: 'mcp.server.reconnected',\n payload: { name: e.name, toolCount: e.toolCount },\n });\n });\n\n on('mcp.server.disconnected', (e) => {\n broadcast(clients, {\n type: 'mcp.server.disconnected',\n payload: { name: e.name, reason: e.reason },\n });\n });\n\n on('coordinator.stats', (e) => {\n broadcast(clients, {\n type: 'coordinator.stats',\n payload: sessionPayload({\n sessionId: e.sessionId,\n total: e.total,\n running: e.running,\n idle: e.idle,\n stopped: e.stopped,\n inFlight: e.inFlight,\n pending: e.pending,\n completed: e.completed,\n subagentStatuses: e.subagentStatuses.map((s) => ({\n id: s.subagentId,\n name: s.subagentId,\n status: s.status,\n currentTask: s.taskId,\n })),\n }),\n });\n });\n\n // \u2500\u2500 Inter-agent mailbox visibility \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n // Forward cross-session mailbox activity (messages received by this\n // process's agents, new agent registrations on the project) to the\n // browser so the user sees multi-terminal/multi-surface chatter live.\n // These events are emitted via emit() with untyped names (the mailbox\n // + mailbox-loop), so subscribe by pattern like the TUI does.\n disposers.push(\n events.onPattern('mailbox.received', (_e, payload) => {\n broadcast(clients, { type: 'mailbox.received', payload } as never as WSServerMessage);\n }),\n events.onPattern('mailbox.agent_registered', (_e, payload) => {\n broadcast(clients, {\n type: 'mailbox.agent_registered',\n payload,\n } as never as WSServerMessage);\n }),\n );\n\n // Subagent fleet lifecycle\n const forwardSubagent = (kind: string, payload: Record<string, unknown>) =>\n broadcast(clients, { type: 'subagent.event', payload: sessionPayload({ kind, ...payload }) });\n\n on('subagent.spawned', (e) =>\n forwardSubagent('spawned', {\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n taskId: e.taskId,\n name: e.name,\n provider: e.provider,\n model: e.model,\n description: e.description,\n }),\n );\n on('subagent.task_started', (e) =>\n forwardSubagent('task_started', {\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n taskId: e.taskId,\n description: e.description,\n }),\n );\n on('subagent.tool_started', (e) => {\n broadcast(clients, {\n type: 'codemap.tool_started',\n payload: {\n sessionId: e.agentSessionId ?? e.sessionId ?? '',\n parentSessionId: e.sessionId,\n traceId: e.traceId,\n agentId: e.subagentId,\n agentName: e.agentName ?? e.subagentId,\n id: e.id,\n name: e.name,\n input: scrub(e.input),\n fileTargets: extractCodeMapFileTargets(projectRoot || '.', e.name, e.input),\n },\n });\n });\n on('subagent.tool_executed', (e) => {\n broadcast(clients, {\n type: 'codemap.tool_executed',\n payload: {\n sessionId: e.agentSessionId ?? e.sessionId ?? '',\n parentSessionId: e.sessionId,\n traceId: e.traceId,\n agentId: e.subagentId,\n agentName: e.agentName ?? e.subagentId,\n id: e.id,\n name: e.name,\n durationMs: e.durationMs,\n ok: e.ok,\n input: scrub(e.input),\n fileTargets: extractCodeMapFileTargets(projectRoot || '.', e.name, e.input),\n output: scrub(e.output),\n outputBytes: e.outputBytes,\n outputTokens: e.outputTokens,\n outputLines: e.outputLines,\n },\n });\n forwardSubagent('tool_executed', {\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n toolName: e.name,\n durationMs: e.durationMs,\n ok: e.ok,\n });\n });\n on('subagent.iteration_summary', (e) =>\n forwardSubagent('iteration_summary', {\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n iteration: e.iteration,\n toolCalls: e.toolCalls,\n costUsd: e.costUsd,\n currentTool: e.currentTool,\n partialText: e.partialText,\n }),\n );\n on('subagent.budget_warning', (e) =>\n forwardSubagent('budget_warning', {\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n budgetKind: e.kind,\n used: e.used,\n limit: e.limit,\n }),\n );\n on('subagent.budget_extended', (e) =>\n forwardSubagent('budget_extended', {\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n budgetKind: e.kind,\n newLimit: e.newLimit,\n totalExtensions: e.totalExtensions,\n }),\n );\n on('subagent.ctx_pct', (e) =>\n forwardSubagent('ctx_pct', {\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n load: e.load,\n tokens: e.tokens,\n maxContext: e.maxContext,\n }),\n );\n on('subagent.task_completed', (e) =>\n forwardSubagent('task_completed', {\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n status: e.status,\n iterations: e.iterations,\n toolCalls: e.toolCalls,\n finalText: (e as Record<string, unknown>).finalText as string | undefined,\n failureReason: e.error?.kind,\n error: e.error ? { kind: e.error.kind, message: e.error.message } : undefined,\n }),\n );\n on('subagent.removed', (e) =>\n forwardSubagent('removed', {\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n reason: e.reason,\n }),\n );\n\n on('agent.timeline.message', (e) => {\n const timeline = e as typeof e & { toolOk?: boolean };\n broadcast(clients, {\n type: 'agent.timeline.message',\n payload: sessionPayload({\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n agentName: e.agentName,\n content: e.content,\n kind: e.kind,\n iteration: e.iteration,\n ts: e.ts,\n toolName: e.toolName,\n ...(typeof timeline.toolOk === 'boolean' ? { toolOk: timeline.toolOk } : {}),\n costUsd: e.costUsd,\n }),\n });\n });\n on('agent.status_changed', (e) => {\n broadcast(clients, {\n type: 'agent.status_changed',\n payload: sessionPayload({\n sessionId: e.sessionId,\n subagentId: e.subagentId,\n agentName: e.agentName,\n status: e.status,\n ts: e.ts,\n summary: e.summary,\n task: e.task,\n }),\n });\n });\n\n // \u2500\u2500 Leader (main session) events \u2014 forwarded as subagent.event with subagentId 'leader' \u2500\u2500\n // These give the AgentsPage a live leader row with real-time tool tracking,\n // context pressure \u2014 matching the TUI's leader entry.\n // Iteration counts, cost, and overall status come from the sessionStore on the frontend.\n\n // Leader spawned: sent on first iteration so the frontend creates the leader row.\n let leaderSpawned = false;\n on('iteration.started', (e) => {\n if (!leaderSpawned) {\n leaderSpawned = true;\n const provider = (context.provider as { id?: string } | undefined)?.id ?? 'unknown';\n forwardSubagent('spawned', {\n sessionId: e.sessionId,\n subagentId: 'leader',\n name: 'LEADER',\n provider,\n model: context.model,\n description: `Main agent session (${context.session.id})`,\n });\n }\n });\n\n // Leader tool execution: emitted on every tool.executed in the main session.\n on('tool.executed', (e) => {\n forwardSubagent('tool_executed', {\n sessionId: e.sessionId,\n subagentId: 'leader',\n toolName: e.name,\n durationMs: e.durationMs,\n ok: e.ok,\n });\n });\n\n // Leader context pressure + cost: emitted on every provider response.\n on('provider.response', (e) => {\n if (e.usage?.input != null) {\n const maxCtx = context.provider.capabilities.maxContext;\n const rawLoad = maxCtx > 0 ? e.usage.input / maxCtx : 0;\n const load = Math.max(0, Math.min(1, rawLoad));\n const costUsd = context.tokenCounter.estimateCost().total;\n forwardSubagent('ctx_pct', {\n sessionId: e.sessionId,\n subagentId: 'leader',\n load,\n rawLoad,\n tokens: e.usage.input,\n maxContext: maxCtx,\n costUsd,\n });\n }\n });\n\n // Leader iteration updates: we already track iteration started above.\n // The frontend uses sessionStore for accurate cost/iteration counts.\n // When the run completes, the frontend's run.result handler resets isLoading,\n // making the leader go idle. We reset leader state on iteration.started.\n on('iteration.completed', (e) => {\n // Respawn leader if it was cleared (e.g., on session resume).\n if (!leaderSpawned) {\n leaderSpawned = true;\n const provider = (context.provider as { id?: string } | undefined)?.id ?? 'unknown';\n forwardSubagent('spawned', {\n sessionId: e.sessionId,\n subagentId: 'leader',\n name: 'LEADER',\n provider,\n model: context.model,\n description: `Main agent session (${context.session.id})`,\n });\n }\n });\n\n // \u2500\u2500 Mailbox events \u2014 broadcast to WebUI for real-time per-project visibility \u2500\u2500\n disposers.push(\n events.onPattern('mailbox.*', (eventName, payload) => {\n broadcast(clients, {\n type: 'mailbox.event',\n payload: sessionPayload({ event: eventName, ...(payload as Record<string, unknown>) }),\n });\n }),\n\n // \u2500\u2500 Brain events \u2014 decisions + proactive interventions, live in the browser \u2500\u2500\n events.onPattern('brain.*', (eventName, payload) => {\n broadcast(clients, {\n type: 'brain.event',\n payload: sessionPayload({ event: eventName, ...(payload as Record<string, unknown>) }),\n } as never as WSServerMessage);\n }),\n\n // \u2500\u2500 SAGE events \u2014 retrieval, verification and hygiene observability \u2500\u2500\n events.onPattern('memory.*', (eventName, payload) => {\n broadcast(clients, {\n type: 'memory.event',\n payload: sessionPayload({ event: eventName, ...(payload as Record<string, unknown>) }),\n });\n }),\n\n // \u2500\u2500 Cron plugin events \u2014 broadcast state snapshots so WebUI tracks active jobs \u2500\u2500\n events.onPattern('cron:state_snapshot', (_eventName, payload) => {\n broadcast(clients, {\n type: 'cron.snapshot',\n payload,\n } as never as WSServerMessage);\n }),\n events.onPattern('cron:job_fired', (_eventName, payload) => {\n broadcast(clients, {\n type: 'cron.job_fired',\n payload,\n } as never as WSServerMessage);\n }),\n );\n\n disposers.push(\n registerSetupEventsClientStatusWriter({ events, broadcast, clients, context, wpaths }),\n );\n\n const statusWatcherDispose = registerSetupEventsStatusWatcher({\n wpaths,\n watcherMetrics,\n clients,\n broadcast,\n on,\n isDisposed: () => disposed,\n });\n if (statusWatcherDispose) disposers.push(statusWatcherDispose);\n\n const fleetBroadcasterDispose = registerSetupEventsFleetBroadcaster({\n globalConfigPath,\n wpaths,\n context,\n clients,\n broadcast,\n onFleetBroadcaster,\n isDisposed: () => disposed,\n });\n if (fleetBroadcasterDispose) disposers.push(fleetBroadcasterDispose);\n\n return () => {\n if (disposed) return;\n disposed = true;\n for (const dispose of disposers) {\n try {\n dispose();\n } catch {\n /* best-effort teardown */\n }\n }\n };\n}\n", "import { watch as fsWatch } from 'node:fs';\nimport * as path from 'node:path';\nimport type { Context } from '@wrongstack/core/agent';\nimport type { WstackPaths } from '@wrongstack/core/utils';\nimport type { WebSocket } from 'ws';\nimport type { ConnectedClient, WSServerMessage } from './types.js';\n\nexport interface SetupEventsFleetBroadcasterDeps {\n globalConfigPath?: string | undefined;\n wpaths?: WstackPaths | undefined;\n context: Context;\n clients: Map<WebSocket, ConnectedClient>;\n broadcast: (clients: Map<WebSocket, ConnectedClient>, msg: WSServerMessage) => void;\n onFleetBroadcaster?: ((fn: () => Promise<void>) => void) | undefined;\n isDisposed: () => boolean;\n}\n\nexport function registerSetupEventsFleetBroadcaster(\n deps: SetupEventsFleetBroadcasterDeps,\n): (() => void) | undefined {\n const { globalConfigPath, wpaths, context, clients, broadcast, onFleetBroadcaster, isDisposed } =\n deps;\n const globalRoot = globalConfigPath ? path.dirname(globalConfigPath) : undefined;\n if (!globalRoot) return undefined;\n\n const disposers: Array<() => void> = [];\n const broadcastSessions = async () => {\n try {\n const { SessionRegistry } = await import('@wrongstack/core/storage');\n const registry = new SessionRegistry(globalRoot);\n const sessions = await registry.list();\n const ownEntry = sessions.find((s) => s.pid === process.pid);\n const mySlug = ownEntry?.projectSlug ?? wpaths?.projectSlug;\n const myRoot = path.resolve(context.projectRoot);\n const live = sessions\n .filter((s) => s.status === 'active' || s.status === 'idle')\n .filter((s) => (mySlug ? s.projectSlug === mySlug : path.resolve(s.projectRoot) === myRoot))\n .map((s) => ({\n sessionId: s.sessionId,\n projectName: s.projectName,\n projectSlug: s.projectSlug,\n projectRoot: s.projectRoot,\n workingDir: s.workingDir,\n gitBranch: s.gitBranch,\n clientType: s.clientType,\n status: s.status,\n pid: s.pid,\n startedAt: s.startedAt,\n lastHeartbeatAt: s.lastHeartbeatAt,\n agentCount: s.agentCount,\n agents: (s.agents ?? []).map((a) => ({\n id: a.id,\n name: a.name,\n status: a.status,\n currentTool: a.currentTool,\n currentTask: a.currentTask,\n taskId: a.taskId,\n iterations: a.iterations,\n toolCalls: a.toolCalls,\n costUsd: a.costUsd,\n tokensIn: a.tokensIn,\n tokensOut: a.tokensOut,\n ctxPct: a.ctxPct,\n model: a.model,\n partialText: a.partialText,\n recentTools: a.recentTools,\n recentMail: a.recentMail,\n todos: a.todos,\n latestPrompt: a.latestPrompt,\n latestPromptAt: a.latestPromptAt,\n activity: a.activity,\n lastActivityAt: a.lastActivityAt,\n })),\n }));\n broadcast(clients, { type: 'sessions.status_update', payload: { sessions: live } });\n } catch {\n // Best-effort \u2014 never crash for status broadcasting errors.\n }\n };\n\n onFleetBroadcaster?.(broadcastSessions);\n\n let regWatchLive = false;\n let statusTimer: ReturnType<typeof setTimeout> | undefined;\n const scheduleStatusPoll = (): void => {\n if (isDisposed()) return;\n statusTimer = setTimeout(\n () => {\n void broadcastSessions();\n scheduleStatusPoll();\n },\n regWatchLive ? 30_000 : 5_000,\n );\n if (statusTimer.unref) statusTimer.unref();\n };\n disposers.push(() => {\n if (statusTimer) clearTimeout(statusTimer);\n });\n\n let regDebounce: ReturnType<typeof setTimeout> | undefined;\n try {\n const regWatcher = fsWatch(globalRoot, { persistent: false }, (_event, filename) => {\n const name = filename ? String(filename) : '';\n if (!name.startsWith('session-registry.json') || name.endsWith('.lock')) return;\n if (regDebounce) clearTimeout(regDebounce);\n regDebounce = setTimeout(() => void broadcastSessions(), 150);\n });\n regWatcher.on('error', () => {\n regWatchLive = false;\n try {\n regWatcher.close();\n } catch {\n /* already closed */\n }\n });\n regWatchLive = true;\n disposers.push(() => {\n if (regDebounce) clearTimeout(regDebounce);\n regWatcher.close();\n });\n } catch {\n // Watch unsupported on this platform \u2014 the 5s poll still covers it.\n }\n scheduleStatusPoll();\n void broadcastSessions();\n\n return () => {\n for (const dispose of disposers) {\n dispose();\n }\n };\n}\n", "import type { EventName, Listener } from '@wrongstack/core/kernel';\nimport type { WebSocket } from 'ws';\nimport type { SetupEventProjection } from './setup-event-projection.js';\nimport type { ConnectedClient, WSServerMessage } from './types.js';\n\ntype SetupEventOn = <E extends EventName>(event: E, listener: Listener<E>) => void;\ntype SetupEventBroadcast = (\n clients: Map<WebSocket, ConnectedClient>,\n msg: WSServerMessage,\n) => void;\ntype SessionPayload = <T extends Record<string, unknown>>(payload: T) => T & { sessionId: string };\n\nexport interface SetupEventsProviderHandlersDeps {\n on: SetupEventOn;\n broadcast: SetupEventBroadcast;\n clients: Map<WebSocket, ConnectedClient>;\n projection?: SetupEventProjection | undefined;\n sessionPayload: SessionPayload;\n}\n\nexport function registerSetupEventsProviderHandlers({\n on,\n broadcast,\n clients,\n projection,\n sessionPayload,\n}: SetupEventsProviderHandlersDeps): void {\n on('provider.response', (e) => {\n projection?.flushAllStreamBuffers?.();\n broadcast(clients, {\n type: 'provider.response',\n payload: sessionPayload({\n sessionId: e.sessionId,\n content: e.content,\n usage: e.usage,\n stopReason: e.stopReason,\n messageId: 'current',\n }),\n });\n });\n\n on('ctx.pct', (e) => {\n broadcast(clients, {\n type: 'ctx.pct',\n payload: sessionPayload({\n sessionId: e.sessionId,\n load: e.load,\n tokens: e.tokens,\n maxContext: e.maxContext,\n }),\n });\n broadcast(clients, {\n type: 'subagent.event',\n payload: sessionPayload({\n sessionId: e.sessionId,\n kind: 'ctx_pct',\n subagentId: 'leader',\n load: e.load,\n tokens: e.tokens,\n maxContext: e.maxContext,\n }),\n });\n });\n\n on('ctx.max_context', (e) => {\n broadcast(clients, {\n type: 'ctx.max_context',\n payload: sessionPayload({\n sessionId: e.sessionId,\n providerId: e.providerId,\n modelId: e.modelId,\n maxContext: e.maxContext,\n }),\n });\n });\n\n on('token.threshold', (e) => {\n broadcast(clients, {\n type: 'token.threshold',\n payload: sessionPayload({ sessionId: e.sessionId, used: e.used, limit: e.limit }),\n });\n });\n\n on('token.cost_estimate_unavailable', (e) => {\n broadcast(clients, {\n type: 'token.cost_estimate_unavailable',\n payload: sessionPayload({ sessionId: e.sessionId, model: e.model }),\n });\n });\n\n on('context.repaired', (e) => {\n broadcast(clients, {\n type: 'context.repaired',\n payload: sessionPayload({\n sessionId: e.sessionId,\n removedToolUses: e.removedToolUses,\n removedToolResults: e.removedToolResults,\n removedMessages: e.removedMessages,\n }),\n });\n });\n}\n", "import type { Context } from '@wrongstack/core/agent';\nimport type { SessionEventBridge } from '@wrongstack/core/storage';\n\nexport function createSetupEventSessionHelpers(\n context: Context,\n sessionBridge: SessionEventBridge | undefined,\n) {\n const currentSessionId = (): string => context.session?.id ?? '';\n const sessionPayload = <T extends Record<string, unknown>>(\n payload: T,\n ): T & { sessionId: string } => {\n const provided = payload['sessionId'];\n const sessionId =\n typeof provided === 'string' && provided.length > 0 ? provided : currentSessionId();\n return { ...payload, sessionId };\n };\n const isCurrentSession = (sessionId?: string | undefined): boolean => {\n const current = currentSessionId();\n return !sessionId || !current || sessionId === current;\n };\n const appendForCurrentSession = (\n sessionId: string | undefined,\n event: Parameters<SessionEventBridge['append']>[0],\n ): void => {\n if (!isCurrentSession(sessionId)) return;\n sessionBridge?.append(event).catch(() => {\n /* best-effort */\n });\n };\n\n return { currentSessionId, sessionPayload, appendForCurrentSession };\n}\n", "import { watch as fsWatch } from 'node:fs';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n EventName,\n Listener,\n} from '@wrongstack/core/kernel';\nimport type { WstackPaths } from '@wrongstack/core/utils';\nimport type { WebSocket } from 'ws';\nimport type { ConnectedClient, WSServerMessage } from './types.js';\nimport {\n averageFileWatcherDebounceDelay,\n type FileWatcherMetrics,\n initializeFileWatcherMetrics,\n logFileWatcherMetrics,\n shouldLogWatcherStats,\n statusProjectHashFromWatchFilename,\n} from './setup-events-watcher.js';\n\nexport interface SetupEventsStatusWatcherDeps {\n wpaths?: WstackPaths | undefined;\n watcherMetrics?: FileWatcherMetrics | undefined;\n clients: Map<WebSocket, ConnectedClient>;\n broadcast: (clients: Map<WebSocket, ConnectedClient>, msg: WSServerMessage) => void;\n on: <E extends EventName>(event: E, listener: Listener<E>) => void;\n isDisposed: () => boolean;\n}\n\nexport function registerSetupEventsStatusWatcher(\n deps: SetupEventsStatusWatcherDeps,\n): (() => void) | undefined {\n const { wpaths, watcherMetrics, clients, broadcast, on, isDisposed } = deps;\n if (!wpaths?.projectStatus || !wpaths.globalRoot) return undefined;\n\n const projectsDir = path.join(wpaths.globalRoot, 'projects');\n const knownProjectHashes = new Set<string>();\n const debounceTimers = new Map<string, ReturnType<typeof setTimeout>>();\n const DEBOUNCE_MS = 150;\n const pendingStatuses = new Map<string, { data: unknown; firstWriteAt: number }>();\n\n if (watcherMetrics) initializeFileWatcherMetrics(watcherMetrics);\n\n const logWatcherMetricsEnabled = shouldLogWatcherStats();\n const logWatcherMetrics = () => logFileWatcherMetrics(watcherMetrics);\n const metricsInterval = logWatcherMetricsEnabled\n ? setInterval(logWatcherMetrics, 60_000)\n : undefined;\n\n const broadcastStatus = (_projectHash: string, statusData: unknown, actualDelayMs: number) => {\n broadcast(clients, { type: 'client.status_update', payload: statusData });\n if (watcherMetrics) {\n watcherMetrics.broadcastsSent++;\n watcherMetrics.totalDebounceDelayMs += actualDelayMs;\n watcherMetrics.averageDebounceDelayMs = averageFileWatcherDebounceDelay(watcherMetrics);\n }\n };\n\n const scheduleBroadcast = (projectHash: string, statusData: unknown) => {\n const now = Date.now();\n const existing = pendingStatuses.get(projectHash);\n\n if (existing && watcherMetrics) {\n watcherMetrics.debounceResets++;\n }\n\n pendingStatuses.set(projectHash, {\n data: statusData,\n firstWriteAt: existing ? existing.firstWriteAt : now,\n });\n\n const existingTimer = debounceTimers.get(projectHash);\n if (existingTimer) {\n clearTimeout(existingTimer);\n }\n\n const timer = setTimeout(() => {\n debounceTimers.delete(projectHash);\n const pending = pendingStatuses.get(projectHash);\n if (pending) {\n const actualDelay = Date.now() - pending.firstWriteAt;\n broadcastStatus(projectHash, pending.data, actualDelay);\n pendingStatuses.delete(projectHash);\n }\n }, DEBOUNCE_MS);\n\n debounceTimers.set(projectHash, timer);\n };\n\n let watcher: import('fs').FSWatcher | undefined;\n\n const startWatcher = async () => {\n try {\n await fs.mkdir(projectsDir, { recursive: true });\n if (isDisposed()) return;\n\n watcher = fsWatch(\n projectsDir,\n { persistent: true, recursive: true },\n async (eventType, filename) => {\n if (eventType !== 'change' && eventType !== 'rename') return;\n if (filename == null) return;\n const projectHash = statusProjectHashFromWatchFilename(projectsDir, filename);\n if (!projectHash) return;\n\n if (watcherMetrics) watcherMetrics.fileChangesDetected++;\n if (!knownProjectHashes.has(projectHash)) return;\n if (watcherMetrics) watcherMetrics.filesProcessed++;\n\n try {\n const targetFile = path.join(projectsDir, projectHash, 'status.json');\n const content = await fs.readFile(targetFile, 'utf-8');\n const statusData = JSON.parse(content);\n scheduleBroadcast(projectHash, statusData);\n } catch {\n // File may not exist, be readable yet, or contain complete JSON yet.\n }\n },\n );\n\n if (logWatcherMetricsEnabled) {\n console.log(\n `[setup-events] Watching ${projectsDir} for status.json changes (hash-filtered, debounced)`,\n );\n }\n } catch (err) {\n console.error(\n JSON.stringify({\n level: 'error',\n event: 'setup_events.status_watcher_start_failed',\n message: err instanceof Error ? err.message : String(err),\n timestamp: new Date().toISOString(),\n }),\n );\n }\n };\n\n on('client.status', (e) => {\n if (e.projectHash) {\n const hash = String(e.projectHash);\n if (!knownProjectHashes.has(hash)) {\n knownProjectHashes.add(hash);\n if (watcherMetrics) watcherMetrics.activeProjects = knownProjectHashes.size;\n }\n }\n });\n\n startWatcher();\n\n return () => {\n if (metricsInterval) clearInterval(metricsInterval);\n logWatcherMetrics();\n\n if (watcherMetrics) watcherMetrics.watcherActive = false;\n\n for (const [projectHash, pending] of pendingStatuses) {\n const timer = debounceTimers.get(projectHash);\n if (timer) {\n clearTimeout(timer);\n broadcastStatus(projectHash, pending.data, 0);\n }\n }\n\n for (const timer of debounceTimers.values()) {\n clearTimeout(timer);\n }\n debounceTimers.clear();\n pendingStatuses.clear();\n\n if (watcher) {\n watcher.close();\n if (logWatcherMetricsEnabled) console.log('[setup-events] Closed status file watcher');\n }\n };\n}\n", "import * as path from 'node:path';\n\nexport interface FileWatcherMetrics {\n fileChangesDetected: number;\n filesProcessed: number;\n broadcastsSent: number;\n debounceResets: number;\n totalDebounceDelayMs: number;\n activeProjects: number;\n averageDebounceDelayMs: number;\n watcherActive: boolean;\n}\n\nexport function statusProjectHashFromWatchFilename(\n projectsDir: string,\n filename: string | Buffer,\n): string | null {\n const raw = String(filename);\n const relative = path.isAbsolute(raw) ? path.relative(projectsDir, raw) : raw;\n const parts = relative.split(/[\\\\/]+/).filter(Boolean);\n if (parts.length < 2 || parts.at(-1) !== 'status.json') return null;\n return parts.at(-2) ?? null;\n}\n\nexport function shouldLogWatcherStats(): boolean {\n const value = process.env['WRONGSTACK_WEBUI_WATCHER_STATS']?.trim().toLowerCase();\n return value === '1' || value === 'true' || value === 'yes' || value === 'on';\n}\n\nexport function initializeFileWatcherMetrics(metrics: FileWatcherMetrics): void {\n metrics.fileChangesDetected = 0;\n metrics.filesProcessed = 0;\n metrics.broadcastsSent = 0;\n metrics.debounceResets = 0;\n metrics.totalDebounceDelayMs = 0;\n metrics.activeProjects = 0;\n metrics.averageDebounceDelayMs = 0;\n metrics.watcherActive = true;\n}\n\nexport function averageFileWatcherDebounceDelay(metrics: FileWatcherMetrics | undefined): number {\n if (!metrics || metrics.broadcastsSent === 0) return 0;\n return metrics.totalDebounceDelayMs / metrics.broadcastsSent;\n}\n\nexport function logFileWatcherMetrics(metrics: FileWatcherMetrics | undefined): void {\n if (!metrics || !shouldLogWatcherStats()) return;\n metrics.averageDebounceDelayMs = averageFileWatcherDebounceDelay(metrics);\n console.log(\n `[setup-events] File watcher stats: ` +\n `${metrics.broadcastsSent} broadcasts, ` +\n `${metrics.fileChangesDetected} file changes, ` +\n `${metrics.debounceResets} debounce resets, ` +\n `avg delay: ${metrics.averageDebounceDelayMs.toFixed(1)}ms, ` +\n `${metrics.activeProjects} active projects`,\n );\n}\n", "import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { Context } from '@wrongstack/core/agent';\nimport type { EventBus, EventName, Listener } from '@wrongstack/core/kernel';\nimport type { WstackPaths } from '@wrongstack/core/utils';\nimport { subscribeKanbanDaemonEvents } from './kanban-daemon-subscriber.js';\nimport type { WebSocket } from 'ws';\nimport type { ConnectedClient, WSServerMessage } from './types.js';\n\nexport interface SetupEventsCoreWatcherDeps {\n events: EventBus;\n broadcast: (clients: Map<WebSocket, ConnectedClient>, msg: WSServerMessage) => void;\n clients: Map<WebSocket, ConnectedClient>;\n context: Context;\n wpaths?: WstackPaths | undefined;\n}\n\nexport function registerSetupEventsCoreWatchers(\n deps: SetupEventsCoreWatcherDeps,\n): Array<() => void> {\n const { broadcast, clients, context } = deps;\n const disposers: Array<() => void> = [];\n const conversationState = (context as { state?: Context['state'] }).state;\n if (typeof conversationState?.onChange === 'function') {\n disposers.push(\n conversationState.onChange((change) => {\n if (change.kind !== 'todos_replaced') return;\n broadcast(clients, {\n type: 'todos.updated',\n payload: {\n sessionId: context.session?.id ?? '',\n todos: [...change.todos],\n revision: conversationState.revision,\n },\n });\n }),\n );\n }\n\n const projectRoot = context.projectRoot;\n if (projectRoot) {\n disposers.push(\n subscribeKanbanDaemonEvents(projectRoot, (message) => broadcast(clients, message)),\n );\n }\n return disposers;\n}\n\nexport function registerSetupEventsClientStatusWriter(\n deps: SetupEventsCoreWatcherDeps,\n): () => void {\n const { broadcast, clients, events, wpaths } = deps;\n const on = <E extends EventName>(event: E, listener: Listener<E>): (() => void) =>\n events.on(event, listener);\n\n return on('client.status', async (e) => {\n broadcast(clients, { type: 'client.status_update', payload: e });\n\n if (wpaths?.projectStatus) {\n try {\n const statusFile = wpaths.projectStatus(e.projectHash);\n const dir = path.dirname(statusFile);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(statusFile, JSON.stringify(e, null, 2), 'utf-8');\n } catch (err) {\n console.error(\n JSON.stringify({\n level: 'error',\n event: 'setup_events.status_write_failed',\n message: err instanceof Error ? err.message : String(err),\n timestamp: new Date().toISOString(),\n }),\n );\n }\n }\n });\n}\n", "import type { WebSocket } from 'ws';\nimport { computeTaskProgress } from '@wrongstack/core/tasking';\nimport type { Specification, TaskGraph, TaskNode } from '@wrongstack/core/types';\nimport { SpecStore, TaskGraphStore } from '@wrongstack/sdd';\nimport { sendSerialized } from './ws-utils.js';\n\ninterface WSClient {\n ws: WebSocket;\n id: string;\n}\n\ninterface SpecsWSMessage {\n type: string;\n payload?: Record<string, unknown>;\n}\n\n/** A task as rendered on the FORGE-style dependency board. */\ninterface BoardTask {\n id: string;\n shortId: string;\n title: string;\n description: string;\n priority: TaskNode['priority'];\n type: TaskNode['type'];\n status: TaskNode['status'];\n /** Derived label for the legend: 'queued' = pending with all blockers done. */\n displayStatus: TaskNode['status'] | 'queued';\n deps: string[];\n}\n\n/**\n * SpecsWebSocketHandler \u2014 read-only-ish browser of persisted SDD specs and their\n * task graphs, rendered as a FORGE-style dependency board (topological phase\n * columns + dependency refs). Shared by both webui servers via specs-routes.\n *\n * Message types:\n * specs.list \u2192 all specs + progress\n * specs.get { specId } \u2192 one spec's dependency board\n * specs.taskStatus { graphId, taskId, status } \u2192 update + rebroadcast\n */\nexport class SpecsWebSocketHandler {\n private specStore: SpecStore;\n private graphStore: TaskGraphStore;\n private clients = new Set<WSClient>();\n\n constructor(specsDir: string, taskGraphsDir: string) {\n this.specStore = new SpecStore({ baseDir: specsDir });\n this.graphStore = new TaskGraphStore({ baseDir: taskGraphsDir });\n }\n\n addClient(ws: WebSocket): void {\n const client: WSClient = { ws, id: crypto.randomUUID() };\n this.clients.add(client);\n ws.on('close', () => this.clients.delete(client));\n ws.on('error', () => this.clients.delete(client));\n void this.sendList(client);\n }\n\n async handleMessage(msg: SpecsWSMessage): Promise<void> {\n switch (msg.type) {\n case 'specs.list':\n await this.broadcastList();\n break;\n case 'specs.get': {\n const specId = msg.payload?.specId as string | undefined;\n if (specId) await this.broadcastDetail(specId);\n break;\n }\n case 'specs.taskStatus': {\n const { graphId, taskId, status } = msg.payload as {\n graphId: string;\n taskId: string;\n status: TaskNode['status'];\n };\n await this.updateTaskStatus(graphId, taskId, status);\n break;\n }\n }\n }\n\n // \u2500\u2500 List \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async buildList(): Promise<unknown[]> {\n const [specs, graphs] = await Promise.all([this.specStore.list(), this.graphStore.list()]);\n return specs.map((s, i) => {\n const graph = graphs.find((g) => g.specId === s.id);\n return {\n id: s.id,\n // FORGE-style display id (spec-001\u2026). The real UUID stays in `id`.\n displayId: `spec-${String(i + 1).padStart(3, '0')}`,\n title: s.title,\n status: s.status,\n graphId: graph?.id,\n total: graph?.nodeCount ?? 0,\n completed: graph?.completedCount ?? 0,\n };\n });\n }\n\n private async broadcastList(): Promise<void> {\n this.broadcast({ type: 'specs.list', payload: { specs: await this.buildList() } });\n }\n\n private async sendList(client: WSClient): Promise<void> {\n this.send(client, { type: 'specs.list', payload: { specs: await this.buildList() } });\n }\n\n // \u2500\u2500 Detail (dependency board) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async broadcastDetail(specId: string): Promise<void> {\n const spec = await this.specStore.load(specId);\n const graph = await this.findGraphForSpec(specId);\n if (!spec || !graph) {\n this.broadcast({ type: 'specs.detail', payload: { specId, columns: [], notFound: true } });\n return;\n }\n this.broadcast({ type: 'specs.detail', payload: this.buildDetail(spec, graph) });\n }\n\n private async findGraphForSpec(specId: string): Promise<TaskGraph | null> {\n const entry = (await this.graphStore.list()).find((g) => g.specId === specId);\n if (!entry) return null;\n return this.graphStore.load(entry.id);\n }\n\n private buildDetail(spec: Specification, graph: TaskGraph): Record<string, unknown> {\n const nodes = Array.from(graph.nodes.values()).sort((a, b) => a.createdAt - b.createdAt);\n // Stable short ids (t01, t02, \u2026) in creation order, FORGE-style.\n const shortId = new Map<string, string>();\n nodes.forEach((n, i) => {\n shortId.set(n.id, `t${String(i + 1).padStart(2, '0')}`);\n });\n\n // Blockers per node (depends_on edges pointing at the node).\n const blockers = new Map<string, string[]>();\n for (const n of nodes) blockers.set(n.id, []);\n for (const e of graph.edges) {\n if (e.type === 'depends_on') blockers.get(e.to)?.push(e.from);\n }\n\n const statusOf = (id: string) => graph.nodes.get(id)?.status;\n const depthCache = new Map<string, number>();\n const depthOf = (id: string, seen = new Set<string>()): number => {\n const cached = depthCache.get(id);\n if (cached !== undefined) return cached;\n if (seen.has(id)) return 0; // cycle guard\n seen.add(id);\n const deps = blockers.get(id) ?? [];\n const d = deps.length === 0 ? 0 : 1 + Math.max(...deps.map((b) => depthOf(b, seen)));\n depthCache.set(id, d);\n return d;\n };\n\n const toBoardTask = (n: TaskNode): BoardTask => {\n const deps = blockers.get(n.id) ?? [];\n const allDepsDone = deps.every((b) => statusOf(b) === 'completed');\n const displayStatus = n.status === 'pending' && deps.length > 0 && allDepsDone ? 'queued' : n.status;\n return {\n id: n.id,\n shortId: shortId.get(n.id) ?? n.id.slice(0, 6),\n title: n.title,\n description: n.description,\n priority: n.priority,\n type: n.type,\n status: n.status,\n displayStatus,\n deps: deps.map((b) => shortId.get(b) ?? b.slice(0, 6)),\n };\n };\n\n // Group into topological columns: depth 0 \u2192 \"Start\", depth k \u2192 \"Phase k\".\n const byDepth = new Map<number, BoardTask[]>();\n for (const n of nodes) {\n const d = depthOf(n.id);\n if (!byDepth.has(d)) byDepth.set(d, []);\n byDepth.get(d)?.push(toBoardTask(n));\n }\n const columns = [...byDepth.keys()]\n .sort((a, b) => a - b)\n .map((d) => ({ label: d === 0 ? 'Start' : `Phase ${d}`, tasks: byDepth.get(d) ?? [] }));\n\n const progress = computeTaskProgress(graph);\n return {\n specId: spec.id,\n graphId: graph.id,\n title: spec.title,\n overview: spec.overview,\n status: spec.status,\n total: progress.total,\n completed: progress.completed,\n running: progress.inProgress,\n pending: progress.pending,\n columns,\n };\n }\n\n private async updateTaskStatus(\n graphId: string,\n taskId: string,\n status: TaskNode['status'],\n ): Promise<void> {\n const graph = await this.graphStore.load(graphId);\n const node = graph?.nodes.get(taskId);\n if (!graph || !node) return;\n node.status = status;\n node.updatedAt = Date.now();\n graph.updatedAt = Date.now();\n await this.graphStore.save(graph);\n this.broadcastDetail(graph.specId).catch(() => {});\n await this.broadcastList();\n }\n\n // \u2500\u2500 Transport \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private broadcast(msg: { type: string; payload: unknown }): void {\n const data = JSON.stringify(msg);\n for (const client of this.clients) {\n sendSerialized(client.ws, data);\n }\n }\n\n private send(client: WSClient, msg: { type: string; payload: unknown }): void {\n sendSerialized(client.ws, JSON.stringify(msg));\n }\n}\n", "/**\n * Standalone WebUI server entry point.\n *\n * Phase 1d of the god-module split: `startWebUI` moved here from\n * `./index.ts` so that `index.ts` is a pure re-export barrel.\n * This module owns the full server lifecycle: port resolution, boot,\n * service construction (Phase 1c), route/dispatcher/connection wiring\n * (Phase 1b/1a), WS + HTTP server creation, and graceful shutdown.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport * as http from 'node:http';\nimport * as path from 'node:path';\nimport { createDefaultPipelines } from '@wrongstack/core/agent';\nimport { getSharedProjectMailbox, resolveProjectDir } from '@wrongstack/core/coordination';\nimport { createCompatibilityTrustBoundary } from '@wrongstack/core/security';\nimport {\n attachTodosCheckpoint,\n createSessionEventBridge,\n resolveSessionLoggingConfig,\n watchProviderConfig,\n} from '@wrongstack/core/storage';\nimport { DEFAULT_CONTEXT_WINDOW_MODE_ID, type ProviderConfig } from '@wrongstack/core/types';\nimport {\n expectDefined,\n sessionScopedPath,\n startSharedHeapWatchdog,\n toErrorMessage,\n wstackGlobalRoot,\n} from '@wrongstack/core/utils';\nimport { makeProviderFromConfig } from '@wrongstack/providers';\nimport { type PackageOperation, toLanguagePackageInput } from '@wrongstack/techstack';\nimport { ensureSessionShell } from '@wrongstack/tools';\nimport { createAgentServices } from './backend-services.js';\nimport { bootConfig, patchConfig } from './boot.js';\nimport { createConnectionHandler } from './connection-handler.js';\nimport { createEternalSubscription } from './eternal-iteration-broadcast.js';\nimport { unregisterInstance } from './instance-registry.js';\nimport { createMessageDispatcher } from './message-dispatcher.js';\nimport { formatExternalAccessUrls } from './network-info.js';\nimport type { PendingConfirm } from './pending-confirms.js';\nimport { createPreContextServices } from './pre-context-services.js';\nimport {\n type ConfigWriteLockHolder,\n type PrefHelperDeps,\n persistPrefsToConfig as persistPrefsToConfigImpl,\n prefSnapshot as prefSnapshotImpl,\n updateGlobalConfig as updateGlobalConfigImpl,\n} from './pref-helpers.js';\nimport {\n ensureProjectDataDir,\n generateProjectSlug,\n loadManifest,\n saveManifest,\n} from './projects-manifest.js';\nimport { projectSavedProviders } from './provider-handlers.js';\nimport {\n buildRoutes,\n type WebuiCallbacks,\n type WebuiDeps,\n type WebuiMutableState,\n} from './routes.js';\nimport {\n armEvents,\n createSessionStartPayload,\n createWsServers,\n registerShutdown,\n resolvePorts,\n startHttpServer,\n} from './server-runtime.js';\nimport type { FileWatcherMetrics } from './setup-events.js';\nimport type { WebUIOptions } from './types.js';\nimport { broadcast, resolveAuthToken } from './ws-utils.js';\n\nexport function createStandaloneTodosCheckpointLifecycle(input: {\n state: Parameters<typeof attachTodosCheckpoint>[0];\n sessionsDir: string;\n sessionId: string;\n events?: Parameters<typeof attachTodosCheckpoint>[3];\n traceId?: string | undefined;\n warn?: ((message: string) => void) | undefined;\n}): {\n rebind: (sessionId: string, sessionsDir: string) => Promise<void>;\n detach: () => Promise<void>;\n} {\n let checkpointSessionId = input.sessionId;\n let checkpointSessionsDir = input.sessionsDir;\n const attachCheckpoint = (sessionId: string, sessionsDir: string) =>\n attachTodosCheckpoint(\n input.state,\n sessionScopedPath(sessionsDir, sessionId, '.todos.json'),\n sessionId,\n input.events,\n input.traceId,\n input.warn,\n );\n let detachCurrent = attachCheckpoint(input.sessionId, input.sessionsDir);\n let checkpointAttached = true;\n const detachCurrentCheckpoint = async (): Promise<void> => {\n if (!checkpointAttached) return;\n checkpointAttached = false;\n await detachCurrent();\n };\n let transitionTail = Promise.resolve();\n\n const rebind = (nextSessionId: string, sessionsDir: string): Promise<void> => {\n const transition = transitionTail.then(async () => {\n if (\n checkpointAttached &&\n nextSessionId === checkpointSessionId &&\n sessionsDir === checkpointSessionsDir\n ) {\n return;\n }\n let detachFailed = false;\n let detachError: unknown;\n try {\n await detachCurrentCheckpoint();\n } catch (error) {\n // The listener unsubscribes before its final flush. The runtime has\n // already selected the next session, so bind that session even when\n // the old flush reports a failure; reattaching the old session would\n // persist future todos into the wrong sidecar.\n detachFailed = true;\n detachError = error;\n }\n const nextDetach = attachCheckpoint(nextSessionId, sessionsDir);\n checkpointSessionId = nextSessionId;\n checkpointSessionsDir = sessionsDir;\n detachCurrent = nextDetach;\n checkpointAttached = true;\n if (detachFailed) throw detachError;\n });\n transitionTail = transition.catch(() => undefined);\n return transition;\n };\n\n return {\n rebind,\n detach: async (): Promise<void> => {\n await transitionTail;\n await detachCurrentCheckpoint();\n },\n };\n}\n\nexport async function startWebUI(\n opts: WebUIOptions & {\n wsHost?: string | undefined;\n httpPort?: number | undefined;\n accessToken?: string | undefined;\n publicUrl?: string | undefined;\n publicWsUrl?: string | undefined;\n requireToken?: boolean | undefined;\n open?: boolean | undefined;\n } = {},\n): Promise<void> {\n // Pin one stable shell for the session on Windows (PowerShell by default) via\n // WRONGSTACK_SHELL before the system-prompt builder is constructed below, so\n // the model is told exactly which shell + syntax to use. No-op on POSIX / when\n // the user already set WRONGSTACK_SHELL.\n ensureSessionShell();\n\n const ports = await resolvePorts(opts);\n const { wsHost, httpPort, publicUrl, publicWsUrl, requireToken } = ports;\n\n console.log('[WebUI] Starting backend services...');\n\n // Boot configuration\n const boot = await bootConfig();\n const { config: baseConfig, globalConfigPath, wpaths, logger } = boot;\n // PR 5 of Phase 2: when the caller (typically the CLI) supplies a\n // pre-built `BackendServices`, prefer its `vault` over the one the\n // default boot would construct. This lets `runWebUI` keep owning the\n // vault lifecycle (so it can decrypt/encrypt its own config writes\n // in lockstep with the rest of the CLI session) instead of having\n // the webui build a parallel vault it can never see.\n const vault = opts.services?.vault ?? boot.vault;\n let config = baseConfig;\n\n /** Mutable project root. File handlers,\n * sessionStartPayload, and session store use this value. */\n let projectRoot = boot.projectRoot;\n /** Mutable working directory \u2014 starts at projectRoot, changeable via\n * `working_dir.set` WS message. Must always stay inside projectRoot. */\n let workingDir = projectRoot;\n\n // Serialize concurrent profile-config writes to prevent races between\n // model.switch and key.add/key.update handlers.\n // Held in a mutable object so the pref-helpers (./pref-helpers.ts, Phase 1c)\n // can update the lock in place \u2014 TypeScript flattens Promise<Promise<void>>,\n // so we can't return the new lock from an async helper.\n const configWriteLock: ConfigWriteLockHolder = { lock: Promise.resolve() };\n\n // Unified global config mutation: read \u2192 decrypt \u2192 mutate \u2192 encrypt \u2192 write,\n // serialized behind configWriteLock. Implementation lives in\n // ./pref-helpers.ts; this thin wrapper preserves the two-arg signature the\n // route layer (provider routes, key handlers) expects.\n // Resolve the active profile config path so updateGlobalConfig writes settings\n // to the canonical profile file (~/.wrongstack/profiles/<name>/config.json)\n // instead of the thin root bootstrap (~/.wrongstack/config.json).\n const activeProfile =\n (config as { activeProfile?: string | undefined }).activeProfile ?? 'default';\n const profileConfigPath = wpaths.profileConfig(activeProfile);\n const prefHelperDeps: PrefHelperDeps = { profileConfigPath, vault, logger };\n const updateGlobalConfig = async (\n mutate: (cfg: Record<string, unknown>) => void,\n errorLabel: string,\n ): Promise<void> => updateGlobalConfigImpl(prefHelperDeps, configWriteLock, mutate, errorLabel);\n\n console.log('[WebUI] Config loaded:', config.provider ?? '(none)', '/', config.model ?? '(none)');\n\n // If no active provider is set but there are saved providers, pick the first one.\n // This handles configs written in older formats or by external tools.\n // Guard against config.providers being a string or other non-object value\n // (e.g., from a corrupted config or YAML parser misreading the value).\n if (\n !config.provider &&\n config.providers &&\n typeof config.providers === 'object' &&\n config.providers !== null &&\n !Array.isArray(config.providers) &&\n Object.keys(config.providers).length > 0\n ) {\n const firstKey = expectDefined(Object.keys(config.providers)[0]);\n // Also adopt a model when the provider carries a saved `models` allowlist.\n // Without this the auto-selected provider lands with a BLANK active model\n // (needsProvider stays true \u2192 chat opens with no model in the header).\n // A provider without a saved allowlist (e.g. a custom one to be probed)\n // still gets the provider; the model dropdown is populated on demand.\n const adoptModel = !config.model ? config.providers[firstKey]?.models?.[0] : undefined;\n config = patchConfig(config, {\n provider: firstKey,\n ...(adoptModel ? { model: adoptModel } : {}),\n });\n console.log(\n '[WebUI] No active provider \u2014 auto-selected:',\n firstKey,\n adoptModel ? `/ ${adoptModel}` : '',\n );\n }\n\n // If still no provider, the frontend will show a setup screen.\n // We still start the HTTP/WS servers so the user can configure via the UI.\n const needsProvider = !config.provider || !config.model;\n\n // \u2500\u2500 Pre-context services (registries, stores, session, system prompt,\n // provider, context) \u2014 built in ./pre-context-services.ts (Phase 1f).\n // The factory returns all services + the initial values of the mutable\n // bindings the route layer swaps at runtime (session, sessionStore,\n // sessionStartedAt, modeId). Those stay as `let` here so state setters\n // can update them.\n const preContext = await createPreContextServices({\n config,\n wpaths,\n logger,\n opts,\n vault,\n globalConfigPath,\n projectRoot,\n workingDir,\n needsProvider,\n touchProject: (root, wd) => touchProjectEntry(root, wd),\n });\n const {\n modelsRegistry,\n container,\n configStore,\n providerRegistry,\n toolRegistry,\n memoryStore,\n events,\n mcpRegistry,\n sessionReader,\n annotationsStore,\n tokenCounter,\n modeStore,\n customModeStore,\n skillLoader,\n skillInstaller,\n promptsCtx,\n modelCapabilitiesRef,\n provider,\n context,\n sessionIdentity,\n } = preContext;\n let sessionStore = preContext.sessionStore;\n let session = preContext.session;\n const todosCheckpoint = createStandaloneTodosCheckpointLifecycle({\n state: context.state,\n sessionsDir: wpaths.projectSessions,\n sessionId: session.id,\n events,\n traceId: context.traceId,\n warn: (message) => logger.warn(message),\n });\n let sessionStartedAt = preContext.sessionStartedAt;\n let modeId = preContext.modeId;\n const needsSetup = preContext.needsSetup;\n\n // Pref keys + snapshot + persistence live in ./pref-helpers.ts (Phase 1c).\n // Thin closures below keep the original signatures the route layer expects\n // while threading the live configWriteLock holder.\n const prefSnapshot = (): Record<string, unknown> => prefSnapshotImpl(context.meta);\n const persistPrefsToConfig = async (payload: Record<string, unknown>): Promise<void> =>\n persistPrefsToConfigImpl(prefHelperDeps, configWriteLock, payload);\n\n // \u2500\u2500 Post-context agent services (pipelines, compaction, agent, Brain,\n // per-feature WS handlers) \u2014 built in ./backend-services.ts (Phase 1c).\n // The factory returns everything startWebUI needs to wire routes + the\n // dispatcher; the updateAutoCompactionMaxContext closure captures the\n // live autoCompactor / modelCapabilitiesRef it built.\n const trustBoundary =\n opts.trustBoundary ??\n createCompatibilityTrustBoundary({ policyId: 'webui-trusted-host-compat-v1' });\n const agentServices = await createAgentServices({\n trustBoundary,\n config,\n wpaths,\n logger,\n projectRoot,\n workingDir,\n context,\n provider,\n container,\n toolRegistry,\n providerRegistry,\n modelsRegistry,\n events,\n mcpRegistry,\n memoryStore,\n modeStore,\n customModeStore,\n skillLoader,\n skillInstaller,\n tokenCounter,\n pipelines: createDefaultPipelines(),\n modelCapabilitiesRef,\n sessionGetter: () => session,\n sessionReader,\n annotationsStore,\n // Brain settings persist to the GLOBAL config only (config.brain is on\n // the in-project deny list), serialized behind the shared write lock.\n persistBrainConfig: (brainConfig) =>\n updateGlobalConfig((decrypted) => {\n decrypted['brain'] = brainConfig;\n }, 'brain.config'),\n });\n const {\n compactor,\n autoCompactor,\n agent,\n toolExecutor,\n permissionPolicy,\n pipelines,\n brain,\n brainSettings,\n brainRuntime,\n brainLog,\n brainMonitor,\n codebaseIndexing,\n goalHandler,\n specsHandler,\n sddBoardHandler,\n sddWizardHandler,\n worktreeHandler,\n terminalHandler,\n collabHandler,\n disposeRealtimeHandlers,\n updateAutoCompactionMaxContext,\n } = agentServices;\n if (typeof context.meta['yolo'] === 'boolean') {\n permissionPolicy.setYolo?.(context.meta['yolo']);\n }\n\n // Helper: build the rich session.start payload from current runtime state.\n // Centralised so initial connect, post-/new, and post-model.switch all\n // broadcast the same shape \u2014 frontend treats this as the single source of\n // truth for everything in the status bar (model, context window, project).\n const sessionStartPayload = createSessionStartPayload({\n getConfig: () => config,\n getSessionId: () => session.id,\n getProjectRoot: () => projectRoot,\n getWorkingDir: () => workingDir,\n getModeId: () => modeId,\n getContextMode: () =>\n String(context.meta['contextWindowMode'] ?? DEFAULT_CONTEXT_WINDOW_MODE_ID),\n getNeedsSetup: () => needsSetup,\n modelsRegistry,\n });\n\n const watcherMetricsRef: FileWatcherMetrics = {\n fileChangesDetected: 0,\n filesProcessed: 0,\n broadcastsSent: 0,\n debounceResets: 0,\n totalDebounceDelayMs: 0,\n activeProjects: 0,\n averageDebounceDelayMs: 0,\n watcherActive: false,\n };\n\n // Resolve the auth token once so the HTTP /ws-auth cookie and the WS\n // verifyClient share the SAME token. When opts.accessToken is undefined\n // (common) and no WEBUI_TOKEN env var is set, resolveAuthToken() generates\n // a fresh randomBytes token on EACH call \u2014 without this hoist the HTTP\n // server's cookie (tokenA) and the WS verifyClient (tokenB) would diverge,\n // locking browsers out of the WS upgrade when requireToken is active.\n const accessToken = resolveAuthToken(opts.accessToken);\n const httpServer = startHttpServer({\n wsHost,\n httpPort,\n wsToken: accessToken,\n publicWsUrl,\n publicUrl,\n requireToken,\n globalRoot: wpaths.globalRoot,\n globalConfigPath,\n projectRoot,\n openBrowser: !!opts.open,\n watcherMetrics: watcherMetricsRef,\n onFleetPing: () => {\n void eventArming.getFleetBroadcast()?.();\n },\n onTechStackEvent: (event) => broadcast(clients, event),\n // Read through `context` on every call rather than capturing: the running\n // loop swaps provider/model when the user switches (same live source the\n // completion handler reads).\n getLlm: () =>\n context.provider && context.model\n ? { provider: context.provider, model: context.model }\n : undefined,\n executePackageOperation: async (operation: PackageOperation, workspace?: string) => {\n const input = toLanguagePackageInput(operation, workspace);\n const use = {\n type: 'tool_use' as const,\n id: `techstack-remediation-${randomUUID()}`,\n name: 'language_package',\n input: { ...input },\n };\n const execute = async () => {\n const { outputs } = await toolExecutor.executeBatch([use], context, 'sequential');\n const output = outputs[0];\n if (!output) throw new Error('language_package returned no result');\n return output;\n };\n let output = await execute();\n if (output.result.type === 'tool_confirm_pending') {\n const pending = output.result;\n const confirmTool = output.tool;\n if (!confirmTool) throw new Error('Permission confirmation is missing its tool');\n if (events.listenerCount('tool.confirm_needed') === 0) {\n throw new Error('No permission confirmation surface is connected');\n }\n const decision = await new Promise<'yes' | 'no' | 'always' | 'deny'>((resolve) => {\n events.emit('tool.confirm_needed', {\n sessionId: context.session.id,\n tool: confirmTool,\n input: pending.input,\n toolUseId: pending.toolUseId,\n suggestedPattern: pending.suggestedPattern,\n decisionSource: pending.decisionSource,\n riskTier: pending.riskTier,\n boundaryReason: pending.boundaryReason,\n resolve,\n });\n });\n const rule = { tool: 'language_package', pattern: pending.suggestedPattern };\n if (decision === 'always') await permissionPolicy.trust(rule);\n else if (decision === 'yes') permissionPolicy.allowOnce(rule);\n else if (decision === 'deny') await permissionPolicy.deny(rule);\n else permissionPolicy.denyOnce(rule);\n if (decision === 'deny' || decision === 'no')\n throw new Error('Package operation was denied');\n output = await execute();\n }\n if (output.result.type === 'tool_confirm_pending') {\n throw new Error('Package operation still requires confirmation');\n }\n if (output.result.is_error) throw new Error(output.result.content);\n return { detail: output.result.content };\n },\n distDir: opts.distDir,\n });\n\n const wsResult = createWsServers(httpServer, ports, accessToken);\n const { wssPrimary, wssSecondary, clients } = wsResult;\n\n // Subscribe to working directory changes from the CLI.\n context.onWorkingDirChanged((newDir) => {\n workingDir = newDir;\n broadcast(clients, { type: 'working_dir.changed', payload: { cwd: newDir, projectRoot } });\n });\n\n // Eternal-autonomy iteration broadcast.\n let eternalSubscription: { dispose: () => void } | null = null;\n if (opts.subscribeEternalIteration) {\n eternalSubscription = createEternalSubscription(\n opts.subscribeEternalIteration,\n broadcast,\n () => clients,\n );\n }\n\n let _runLock: AbortController | null = null;\n const runLockControl = {\n get: () => _runLock,\n set: (ctrl: AbortController | null) => {\n _runLock = ctrl;\n },\n };\n\n const pendingConfirms = new Map<string, PendingConfirm>();\n\n // Audit-level-aware session log bridge \u2014 persists tool/error/provider\n // events to the session JSONL with the same contract as the CLI. The\n // getter form resolves the CURRENT writer on every append so events\n // follow session.new / session.resume swaps.\n const sessionLogging = resolveSessionLoggingConfig(\n config as never as Parameters<typeof resolveSessionLoggingConfig>[0],\n );\n const sessionBridge = createSessionEventBridge(\n () => context.session ?? session,\n sessionLogging.auditLevel,\n { sampling: sessionLogging.sampling },\n );\n\n // Event arming + WS error handlers live in ./server-runtime.ts (Phase 1e).\n // The WS server's 'listening' event fires when the shared HTTP server\n // starts listening below.\n const eventArming = armEvents(\n wssPrimary,\n wssSecondary,\n wsHost,\n httpPort,\n {\n events,\n broadcast,\n clients,\n config,\n context,\n pendingConfirms,\n globalConfigPath,\n sessionBridge,\n wpaths,\n },\n watcherMetricsRef,\n );\n\n // Start the shared HTTP+WebSocket server. The WS server is attached to this\n // HTTP server via {server: httpServer}, so a single listen() binds both the\n // HTTP frontend and the WS upgrade handler on the same port.\n httpServer.listen(httpPort, wsHost, () => {\n console.log(`[WebUI] HTTP server running on http://${wsHost}:${httpPort}`);\n // For wildcard binds, enumerate external network addresses so the\n // operator can see Tailscale/LAN URLs without manual lookup.\n const extraUrls = formatExternalAccessUrls({\n bindHost: wsHost,\n port: httpPort,\n token: accessToken,\n publicUrl,\n });\n if (extraUrls.length > 0) {\n console.log('[WebUI] Accessible on external interfaces:\\n' + extraUrls.join('\\n'));\n }\n });\n\n // Dual-stack / IPv6 companion listener.\n //\n // When the primary bind is IPv4-only, also try the IPv6 equivalent so\n // peers using IPv6 can connect. Tailscale assigns both v4 (100.x.x.x)\n // and v6 (fd7a:\u2026) addresses; Chrome/Edge on Windows resolve `localhost`\n // to [::1] before 127.0.0.1. Without the companion listener, a v4-only\n // bind causes ECONNREFUSED for all IPv6 peers.\n //\n // When the primary bind is IPv6-only (::), try the IPv4 companion as a\n // fallback for systems where `::` does not accept IPv4-mapped\n // connections (net.ipv6.bindv6only=1, some Windows configs).\n //\n // Best-effort: on systems with dual-stack IPv6 sockets (bindv6only=0,\n // the Linux/macOS default), the companion listener may raise\n // EADDRINUSE because the primary's port is already covered. We\n // swallow EADDRINUSE along with EAFNOSUPPORT / EADDRNOTAVAIL (no IPv6\n // stack, IPv6 disabled, or companion already covered by dual-stack).\n const companion =\n wsHost === '127.0.0.1'\n ? '::1'\n : wsHost === '0.0.0.0' || wsHost === undefined\n ? '::'\n : wsHost === '::' || wsHost === '[::]'\n ? '0.0.0.0'\n : null;\n let companionServer: http.Server | null = null;\n if (companion) {\n const companionLabel = companion.includes(':') ? `[${companion}]` : companion;\n // A single http.Server cannot bind two addresses. Calling .listen() a\n // second time either throws ERR_SERVER_ALREADY_LISTEN (when the first\n // bind has completed) or silently overwrites the first (when both\n // calls run in the same synchronous tick \u2014 which is exactly this case).\n // Create a separate server that shares the request handler, and forward\n // 'upgrade' events so the WebSocketServer on the primary also serves WS\n // connections arriving on the companion address.\n companionServer = http.createServer();\n companionServer.on('request', (req, res) => httpServer.emit('request', req, res));\n companionServer.on('upgrade', (req, socket, head) =>\n httpServer.emit('upgrade', req, socket, head),\n );\n companionServer.on('error', (err: NodeJS.ErrnoException) => {\n if (\n err.code !== 'EAFNOSUPPORT' &&\n err.code !== 'EADDRNOTAVAIL' &&\n err.code !== 'EADDRINUSE'\n ) {\n throw err;\n }\n });\n companionServer.listen(httpPort, companion, () => {\n console.log(`[WebUI] HTTP server running on http://${companionLabel}:${httpPort}`);\n });\n }\n\n // \u2500\u2500 Project manifest helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /**\n * Idempotent manifest registration (mirrors the CLI's\n * touchProjectInManifest): create the projects.json entry when missing,\n * refresh lastSeen/lastWorkingDir when present.\n */\n async function touchProjectEntry(root: string, workDir?: string): Promise<void> {\n const resolved = path.resolve(root);\n const manifest = await loadManifest(globalConfigPath);\n const now = new Date().toISOString();\n const existing = manifest.projects.find((p) => path.resolve(p.root) === resolved);\n if (existing) {\n existing.lastSeen = now;\n if (workDir) existing.lastWorkingDir = path.resolve(workDir);\n } else {\n manifest.projects.push({\n name: path.basename(resolved),\n root: resolved,\n slug: generateProjectSlug(resolved),\n createdAt: now,\n lastSeen: now,\n lastWorkingDir: workDir ? path.resolve(workDir) : undefined,\n });\n }\n await saveManifest(manifest, globalConfigPath);\n await ensureProjectDataDir(generateProjectSlug(resolved), globalConfigPath);\n }\n\n // ---- Route table (extracted to ./routes.ts in Phase 1a) ----\n // The 947-line inline construction block that used to live here\n // moved into buildRoutes() in ./routes.ts. We bind the local mutables\n // (`config`, `projectRoot`, `workingDir`, ...) into a `state` object so\n // routes observe live updates (config switch, project swap, mode\n // change), pass the static services as `deps`, and forward the\n // handful of boot-local closures (config persistence, pref snapshot,\n // \u2026) as `cb`.\n //\n // The 13 destructured names (`providerRoutes`, `sessionRoutes`, \u2026)\n // are then referenced by `handleMessage` exactly the way the inline\n // `let *Routes` block was \u2014 no surface change.\n\n // Mutable bindings \u2014 wrapped by `state` for buildRoutes().\n const state: WebuiMutableState = {\n getConfig: () => config,\n setConfig: (next) => {\n config = next;\n },\n getProjectRoot: () => projectRoot,\n setProjectRoot: (next) => {\n projectRoot = next;\n },\n getWorkingDir: () => workingDir,\n setWorkingDir: (next) => {\n workingDir = next;\n },\n getSession: () => session,\n setSession: (next) => {\n session = next;\n },\n getSessionStartedAt: () => sessionStartedAt,\n setSessionStartedAt: (next) => {\n sessionStartedAt = next;\n },\n getSessionStore: () => sessionStore,\n setSessionStore: (next) => {\n sessionStore = next;\n },\n getModeId: () => modeId,\n setModeId: (next) => {\n modeId = next;\n },\n getModelCapabilities: () => modelCapabilitiesRef.current,\n getConfigWriteLock: () => configWriteLock.lock,\n setConfigWriteLock: (next) => {\n configWriteLock.lock = next;\n },\n abortRunLock: () => {\n const ctrl = runLockControl.get();\n if (ctrl) {\n ctrl.abort();\n runLockControl.set(null);\n }\n },\n isRunActive: () => runLockControl.get() !== null,\n getClients: () => clients,\n };\n\n const deps: WebuiDeps = {\n trustBoundary,\n agent,\n context,\n container,\n toolRegistry,\n modelsRegistry,\n providerRegistry,\n provider,\n mcpRegistry,\n vault,\n globalConfigPath,\n profileConfigPath,\n wpaths,\n configStore,\n tokenCounter,\n permissionPolicy,\n pendingConfirms,\n pipelines,\n logger,\n memoryStore,\n modeStore,\n skillLoader,\n skillInstaller,\n customModeStore,\n compactor,\n autoCompactor,\n events,\n wsHost,\n requireToken,\n publicUrl,\n publicWsUrl,\n wsPort: httpPort,\n httpPort,\n wssPrimary,\n wssSecondary,\n goalHandler,\n specsHandler,\n sddBoardHandler,\n sddWizardHandler,\n worktreeHandler,\n collabHandler,\n terminalHandler,\n brain,\n brainSettings,\n brainRuntime,\n brainLog,\n };\n\n const cb: WebuiCallbacks = {\n sessionStartPayload,\n claimSession: (sessionId, target) => sessionIdentity.claim(sessionId, target),\n onBeforeSessionTodosReplaced: todosCheckpoint.rebind,\n onSessionSwapped: async (sessionId, target) => {\n await sessionIdentity.activate(sessionId, target);\n const { hydrateSessionKanban } = await import('@wrongstack/tools/session-kanban');\n await hydrateSessionKanban(deps.context);\n },\n updateAutoCompactionMaxContext,\n updateGlobalConfig,\n persistPrefsToConfig,\n prefSnapshot,\n };\n\n // Hot-reload provider credentials when config file changes on disk (another\n // terminal's `wstack auth`, a provider panel in another window, or a manual\n // edit). Rebuild the live agent's provider so the next message uses the\n // new key without restarting the server, and re-broadcast the saved-providers\n // projection so every connected panel re-renders. Mirrors `switchModel`'s\n // live-swap (routes.ts). Escape hatch: WRONGSTACK_DISABLE_CONFIG_WATCH=1.\n //\n // Watches the ACTIVE PROFILE config (~/.wrongstack/profiles/<name>/config.json)\n // where all user settings, providers, and routing configs live. The root\n // bootstrap is deliberately not watched as a settings source.\n const watchConfigPath = profileConfigPath;\n let credentialWatcherClose: (() => void) | undefined;\n if (process.env['WRONGSTACK_DISABLE_CONFIG_WATCH'] !== '1') {\n let lastActiveCfg = JSON.stringify(\n state.getConfig().providers?.[deps.context.provider.id] ?? null,\n );\n // Track the shared display language so a cross-process change (e.g. the\n // desktop shell writing config.uiLocale) propagates to every connected\n // webui client live, without a restart.\n let lastUiLocale: string | undefined = state.getConfig().uiLocale;\n const credentialWatcher = watchProviderConfig(\n watchConfigPath,\n vault,\n (snapshot) => {\n // Refresh in-memory config + store so panels and the next switch read fresh.\n state.setConfig(\n patchConfig(state.getConfig(), {\n providers: snapshot.providers,\n ...(snapshot.apiKey !== undefined ? { apiKey: snapshot.apiKey } : {}),\n ...(snapshot.baseUrl !== undefined ? { baseUrl: snapshot.baseUrl } : {}),\n }),\n );\n deps.configStore.update({\n providers: snapshot.providers,\n ...(snapshot.apiKey !== undefined ? { apiKey: snapshot.apiKey } : {}),\n ...(snapshot.baseUrl !== undefined ? { baseUrl: snapshot.baseUrl } : {}),\n ...(snapshot.fallbackModels !== undefined\n ? { fallbackModels: snapshot.fallbackModels }\n : {}),\n ...(snapshot.fallbackProfiles !== undefined\n ? { fallbackProfiles: snapshot.fallbackProfiles }\n : {}),\n ...(snapshot.favoriteModels !== undefined\n ? { favoriteModels: snapshot.favoriteModels }\n : {}),\n ...(snapshot.favoriteModelsOnly !== undefined\n ? { favoriteModelsOnly: snapshot.favoriteModelsOnly }\n : {}),\n ...(snapshot.modelMatrix !== undefined ? { modelMatrix: snapshot.modelMatrix } : {}),\n ...(snapshot.fallbackAuto !== undefined ? { fallbackAuto: snapshot.fallbackAuto } : {}),\n } as never);\n broadcast(clients, {\n type: 'providers.saved',\n payload: { providers: projectSavedProviders(snapshot.providers) },\n });\n\n // Display language live-propagation: when config.uiLocale changes in\n // another process, seed context.meta + broadcast prefs.updated so every\n // connected client re-renders in the new language (handlePrefsUpdated \u2192\n // useLocalPrefs \u2192 i18n.changeLanguage).\n const newUi = snapshot.uiLocale;\n if (newUi !== lastUiLocale) {\n lastUiLocale = newUi;\n if (newUi) {\n deps.context.meta['uiLocale'] = newUi;\n broadcast(clients, { type: 'prefs.updated', payload: { uiLocale: newUi } });\n }\n }\n\n const activeId = deps.context.provider.id;\n const newCfgStr = JSON.stringify(snapshot.providers[activeId] ?? null);\n if (newCfgStr === lastActiveCfg) return; // active provider creds unchanged\n lastActiveCfg = newCfgStr;\n try {\n const providerCfg: ProviderConfig = snapshot.providers[activeId] ?? {\n type: activeId,\n ...(snapshot.apiKey !== undefined ? { apiKey: snapshot.apiKey } : {}),\n ...(snapshot.baseUrl !== undefined ? { baseUrl: snapshot.baseUrl } : {}),\n };\n const newProv = deps.providerRegistry.has(activeId)\n ? deps.providerRegistry.create({ ...providerCfg, type: activeId } as never)\n : makeProviderFromConfig(activeId, { ...providerCfg, type: activeId });\n deps.context.provider = newProv;\n void updateAutoCompactionMaxContext(newProv).catch(() => undefined);\n console.log(`[WebUI] Provider credentials reloaded from config.json (${activeId})`);\n } catch (err) {\n console.warn(\n `[WebUI] Credential hot-reload failed for ${activeId}: ${toErrorMessage(err)}`,\n );\n }\n },\n { warn: (m) => logger.warn(`Config watcher: ${m}`) },\n );\n credentialWatcherClose = credentialWatcher.close;\n }\n\n // WebUI/SimpleUI joins the process flight recorder, including standalone servers.\n const stopHeapWatchdog = startSharedHeapWatchdog({\n collectStats: () => ({\n surface: opts.surface ?? 'webui',\n sessionId: context.session.id,\n messages: context.state.messages.length,\n messageEstimatedTokens: context.state.messages.reduce(\n (sum, message) => sum + (message._estTokens ?? 0),\n 0,\n ),\n webClients: clients.size,\n pendingConfirms: pendingConfirms.size,\n runActive: runLockControl.get() !== null,\n }),\n });\n // Build the route table (Phase 1a) + the message dispatcher and connection\n // handler (Phase 1b). The dispatcher owns the inbound `switch (msg.type)`\n // and the runLock guard; the connection handler owns rate-limiting, F5\n // transcript replay, and per-client lifecycle. Both live in their own\n // modules so `startWebUI` reads as orchestration.\n const routes = buildRoutes(state, deps, cb);\n const handleMessage = createMessageDispatcher({\n state,\n deps,\n routes,\n promptsCtx,\n codebaseIndexing,\n runLock: runLockControl,\n pendingConfirms,\n });\n // Fire-and-forget callback wired on the connection lifecycle for\n // `unsafe_key` / `too_deep` decoder rejections. Sends a high-priority\n // mailbox note to leaders so the running agent-loop can respond if\n // configured to alert (e.g. slash handler or tool watcher).\n const mailbox = getSharedProjectMailbox(\n resolveProjectDir(context.projectRoot, wstackGlobalRoot()),\n events,\n );\n const handleConnection = createConnectionHandler({\n getSessionId: () => session.id,\n sessionStartPayload,\n tokenCounter,\n context,\n loadReplay: async () => {\n await session.flush().catch(() => undefined);\n const data = await sessionStore.load(session.id);\n // `events` feeds the audit markers; the load already parsed them.\n return { messages: data.messages, events: data.events, usage: data.usage };\n },\n clients,\n pendingConfirms,\n onSecurityRejection: (ev) => {\n try {\n void mailbox.send({\n from: context.agentId,\n to: '*',\n type: 'note',\n audience: 'leaders',\n subject: `Security rejection: ${ev.issueCode}`,\n body:\n `Decoder tripwire ${ev.issueCode}: ${ev.issueMessage}\\n\\n` +\n `connectionId: ${ev.connectionId ?? '?'}\\n` +\n `sessionId: ${ev.sessionId ?? '?'}\\n` +\n `agentId: ${ev.agentId ?? '?'}\\n` +\n `projectRoot: ${ev.projectRoot ?? '?'}`,\n priority: 'high',\n senderSessionId: session.id,\n });\n } catch {\n // Mailbox send is best-effort \u2014 a failure here must not crash\n // the message handler or block future messages.\n }\n },\n goalHandler,\n specsHandler,\n sddBoardHandler,\n sddWizardHandler,\n worktreeHandler,\n collabHandler,\n terminalHandler,\n handleMessage,\n });\n wssPrimary.on('connection', handleConnection);\n if (wssSecondary) wssSecondary.on('connection', handleConnection);\n // HTTP server for the React frontend (port 3456) \u2014 see `http-server.ts`\n // for the static-serve, MIME matching, path-traversal guard, and CSP\n // header logic. Constructed here, listen()d below alongside the WS server.\n // `globalRoot` powers the /api/sessions and /api/sessions/:id/agents\n // handlers (read the cross-process SessionRegistry); `apiToken` is the\n // shared auth token the HTTP API requires when bound to a non-loopback\n // host (LAN exposure). Loopback binds skip the token check, mirroring\n // the WS verifyClient loopback-bootstrap policy.\n\n registerShutdown({\n flushSession: async () => {\n await session.append({\n type: 'session_end',\n ts: new Date().toISOString(),\n usage: tokenCounter.total(),\n });\n await session.close();\n },\n clients: () => clients.keys(),\n servers: [\n httpServer,\n ...(companionServer ? [companionServer] : []),\n wssPrimary,\n ...(wssSecondary ? [wssSecondary] : []),\n ],\n onShutdown: async () => {\n await todosCheckpoint.detach();\n await stopHeapWatchdog();\n credentialWatcherClose?.();\n disposeRealtimeHandlers();\n brainMonitor.stop();\n // Read via the services getter \u2014 ledger toggles swap the instance.\n await agentServices.brainLedger?.stop().catch(() => {});\n await mcpRegistry.stopAll().catch(() => undefined);\n await sessionIdentity.stop();\n eventArming.getDispose()?.();\n if (eternalSubscription) {\n eternalSubscription.dispose();\n eternalSubscription = null;\n }\n codebaseIndexing.dispose();\n if (config.Sage?.enabled !== false && config.Sage?.hygiene?.autoAfterSession !== false) {\n const candidate = memoryStore as unknown as {\n hygiene?: (options?: object) => Promise<unknown>;\n };\n await candidate\n .hygiene?.({\n retentionDays: config.Sage?.hygiene?.retentionDays,\n archiveLowConfidenceAfterDays: config.Sage?.hygiene?.archiveLowConfidenceAfterDays,\n })\n .catch((err: unknown) =>\n logger.warn(`sage session hygiene failed: ${toErrorMessage(err)}`),\n );\n }\n await memoryStore\n .dispose()\n .catch((err: unknown) =>\n logger.warn(`sage connection disposal failed: ${toErrorMessage(err)}`),\n );\n await unregisterInstance(process.pid, path.dirname(globalConfigPath));\n },\n });\n}\n\n/**\n * Webui-side mailbox bridge discovery.\n *\n * The webui doesn't spawn a bridge \u2014 the bridge (`wstack mailbox serve`)\n * is spawned by any CLI surface via the auto-bootstrap wiring. We just\n * probe the per-project lock for an already-running instance and stash\n * the discovered handle on `ctx.meta['mailboxBridge']` so any later\n * code (the `/mailbox` HTTP surface, agent-status broadcasters,\n * external-agent proxy) can find it without re-running discovery.\n *\n * If no bridge is running, we log a breadcrumb so the user knows\n * to start one (`wstack --repl`, `wstack --webui`, or\n * `wstack mailbox serve` standalone).\n *\n * Best-effort: never throws. A failure (missing lock dir, ENOENT,\n * etc.) logs at warn level and returns \u2014 the webui keeps running.\n */\n// discoverMailboxBridgeForWebui extracted \u2192 ./discover-mailbox-bridge.ts\n", "/**\n * Post-context backend service construction for the standalone WebUI server.\n *\n * Phase 1c of the god-module split (issue: God-modules >1500 lines).\n * `startWebUI` previously inlined ~400 lines of construction that runs\n * AFTER `context` exists: the agent pipelines + collab middleware, the\n * strategy compactor + auto-compaction middleware, the tool executor +\n * agent, the tiered Brain + monitor, and the per-feature WebSocket\n * handlers (Goal, specs, SDD board/wizard, worktree, terminal, collab).\n *\n * All of that moves into `createAgentServices()`. The pre-context\n * registries/stores (modelsRegistry, container, toolRegistry, session,\n * tokenCounter, \u2026) stay in `startWebUI` because they are interleaved with\n * the `opts.services?` injection contract the CLI's embedded server\n * relies on; lifting them would restructure that contract, which is a\n * separate, higher-risk task.\n *\n * The factory is pure construction \u2014 no behaviour change. It returns a\n * typed `AgentServices` object plus the `updateAutoCompactionMaxContext`\n * closure (which needs the live `context`, `autoCompactor`, and\n * `modelCapabilitiesRef` it just built).\n */\nimport { join } from 'node:path';\nimport type { AgentPipelines, Context } from '@wrongstack/core/agent';\nimport type { CollaborationBus, ObservableBrainArbiter } from '@wrongstack/core/coordination';\nimport type {\n AutoCompactionMiddleware,\n BrainAutoRisk,\n BrainRuntime,\n} from '@wrongstack/core/execution';\nimport type { DefaultTokenCounter } from '@wrongstack/core/infrastructure';\nimport type { Container, EventBus } from '@wrongstack/core/kernel';\nimport type { DefaultModeStore } from '@wrongstack/core/models';\nimport type { ProviderRegistry, ToolRegistry } from '@wrongstack/core/registry';\nimport type { TrustBoundary } from '@wrongstack/core/security';\nimport type { SkillInstaller } from '@wrongstack/core/skills';\nimport type { ConsolidatorSage, SessionReader } from '@wrongstack/core/storage';\nimport type {\n Compactor,\n Logger,\n MemoryPort,\n ModelsRegistry,\n PermissionPolicy,\n Provider,\n SessionStore,\n SkillLoader,\n} from '@wrongstack/core/types';\n\n/** Session shape returned by `SessionStore.create()`. */\ntype Session = Awaited<ReturnType<SessionStore['create']>>;\n\nimport { Agent } from '@wrongstack/core/agent';\nimport {\n BrainDecisionLedger,\n BrainMonitor,\n CollaborationBus as CollaborationBusCtor,\n collabInjectMiddleware,\n collabPauseMiddleware,\n EscalationRoutingBrainArbiter,\n getSharedProjectMailbox,\n mailboxSessionTag,\n ObservableBrainArbiter as ObservableBrainArbiterCtor,\n} from '@wrongstack/core/coordination';\nimport { DEFAULT_TOOLS_CONFIG } from '@wrongstack/core/defaults';\nimport { installDesignStudioMiddleware } from '@wrongstack/core/design';\nimport {\n AutoCompactionMiddleware as AutoCompactionMiddlewareCtor,\n createBrainRuntime,\n createStrategyCompactor,\n resolveBrainConfigDefaults,\n ToolExecutor,\n} from '@wrongstack/core/execution';\nimport { TOKENS } from '@wrongstack/core/kernel';\nimport { type AnnotationsStore, SessionMemoryConsolidator } from '@wrongstack/core/storage';\nimport {\n type Config,\n type ProviderConfig,\n resolveContextWindowPolicy,\n} from '@wrongstack/core/types';\nimport {\n estimateRequestTokensCalibrated,\n toErrorMessage,\n type WstackPaths,\n} from '@wrongstack/core/utils';\nimport type { MCPRegistry } from '@wrongstack/mcp';\nimport { makeLightSubagentFactory } from '@wrongstack/runtime';\nimport {\n createSageToolCallMiddleware,\n createSageTurnMiddleware,\n getSageRetrieval,\n getSageService,\n} from '@wrongstack/sage';\nimport { setupWebUICodebaseIndexing } from './codebase-indexing.js';\nimport { CollaborationWebSocketHandler } from './collaboration-ws-handler.js';\nimport { discoverMailboxBridgeForWebui } from './discover-mailbox-bridge.js';\nimport { GoalWebSocketHandler } from './goal-ws-handler.js';\nimport { resolveProviderModelMetadata } from './model-catalog.js';\nimport { SddBoardWebSocketHandler } from './sdd-board-ws-handler.js';\nimport { buildSddWizardDeps } from './sdd-wizard-wiring.js';\nimport { SddWizardWebSocketHandler } from './sdd-wizard-ws-handler.js';\nimport { SpecsWebSocketHandler } from './specs-ws-handler.js';\nimport { TerminalWebSocketHandler } from './terminal-ws-handler.js';\nimport { WorktreeWebSocketHandler } from './worktree-ws-handler.js';\n\ninterface AgentServicesInput {\n trustBoundary: TrustBoundary;\n config: Config;\n wpaths: WstackPaths;\n logger: Logger;\n projectRoot: string;\n workingDir: string;\n /** Pre-context services (built in startWebUI with opts.services injection). */\n context: Context;\n provider: Provider;\n container: Container;\n toolRegistry: ToolRegistry;\n providerRegistry: ProviderRegistry;\n modelsRegistry: ModelsRegistry;\n events: EventBus;\n mcpRegistry: MCPRegistry;\n memoryStore: MemoryPort;\n modeStore: DefaultModeStore;\n customModeStore: import('./custom-context-modes.js').CustomModeStore;\n skillLoader: SkillLoader | undefined;\n skillInstaller: SkillInstaller | undefined;\n tokenCounter: DefaultTokenCounter;\n pipelines: AgentPipelines;\n /** Mutable capabilities ref \u2014 the factory populates `.current`. */\n modelCapabilitiesRef: { current: unknown };\n /** Returns the LIVE session (swapped on /new + resume) \u2014 read at send time. */\n sessionGetter: () => Session;\n /** Read-only session reader (collab replay-on-join). */\n sessionReader: SessionReader;\n /** Annotations store (collab notes). */\n annotationsStore: AnnotationsStore;\n /**\n * Persist the canonical `config.brain` to the GLOBAL config (serialized\n * behind startWebUI's config write lock). Absent = Brain edits are\n * live-only.\n */\n persistBrainConfig?:\n | ((config: import('@wrongstack/core/types').BrainConfig) => Promise<void>)\n | undefined;\n}\n\ninterface AgentServices {\n collabBus: CollaborationBus;\n compactor: Compactor;\n autoCompactor: AutoCompactionMiddleware | undefined;\n toolExecutor: ToolExecutor;\n agent: Agent;\n permissionPolicy: PermissionPolicy;\n pipelines: AgentPipelines;\n brain: ObservableBrainArbiter;\n brainSettings: { maxAutoRisk: BrainAutoRisk };\n /** Live-editable Brain config owner (brain.config.get/set routes). */\n brainRuntime: BrainRuntime;\n brainLog: Array<{ at: number; kind: string; question: string; outcome: string }>;\n brainMonitor: BrainMonitor;\n /** LIVE persistent decision ledger (undefined when disabled). Read via the\n * services object at shutdown \u2014 ledger toggles swap the instance. */\n brainLedger: BrainDecisionLedger | undefined;\n codebaseIndexing: { onFileWritten(filePath: string): void; dispose(): void };\n goalHandler: GoalWebSocketHandler;\n specsHandler: SpecsWebSocketHandler;\n sddBoardHandler: SddBoardWebSocketHandler;\n sddWizardHandler: SddWizardWebSocketHandler;\n worktreeHandler: WorktreeWebSocketHandler;\n terminalHandler: TerminalWebSocketHandler;\n collabHandler: CollaborationWebSocketHandler;\n /** Release event subscriptions, timers, subprocesses and socket references\n * owned by the per-feature handlers. Idempotent handler disposers make this\n * safe during both signal shutdown and programmatic server restarts. */\n disposeRealtimeHandlers(): void;\n /** Refresh auto-compaction denominator on model switch. */\n updateAutoCompactionMaxContext: (\n newProvider: Provider,\n providerId?: string,\n providerCfg?: ProviderConfig | undefined,\n ) => Promise<void>;\n}\n\n/**\n * Build the post-context agent services: pipelines + middleware, compaction,\n * tool executor + agent, Brain, and the per-feature WebSocket handlers.\n *\n * Returns everything `startWebUI` needs to wire routes + the dispatcher.\n * The `updateAutoCompactionMaxContext` closure captures the live\n * `autoCompactor` / `modelCapabilitiesRef` it built.\n */\nexport async function createAgentServices(input: AgentServicesInput): Promise<AgentServices> {\n const {\n config,\n wpaths,\n logger,\n projectRoot,\n workingDir,\n context,\n provider,\n container,\n toolRegistry,\n providerRegistry,\n modelsRegistry,\n events,\n memoryStore,\n modelCapabilitiesRef,\n } = input;\n\n // Collaboration bus \u2014 process-singleton pause/resume signal. The\n // middleware below hooks it into the toolCall pipeline so a\n // `controller` participant can halt the agent before the next tool\n // call (Phase 3 of idea #13). The same bus instance is shared with\n // the CollaborationWebSocketHandler so client pause/resume requests\n // are routed to the kernel.\n const collabBus = new CollaborationBusCtor();\n const pipelines = input.pipelines;\n // Phase 4 \u2014 collab-inject. Install it first, then prepend collab-pause\n // ahead of it so a controller can pause + inject before the next tool result\n // flows through the pipeline.\n const collabInject = collabInjectMiddleware(collabBus, { logger });\n pipelines.toolCall.prepend(collabInject);\n const collabPause = collabPauseMiddleware(collabBus, { logger });\n pipelines.toolCall.prepend(collabPause);\n // Design Studio \u2014 per-turn UI-intent detection + kit-menu injection.\n installDesignStudioMiddleware({ pipelines, ctx: context });\n const memoryRetrieval = getSageRetrieval(memoryStore);\n if (config.features.memory !== false && config.Sage?.enabled !== false && memoryRetrieval) {\n if (config.Sage?.inject?.toolResults !== false) {\n pipelines.toolCall.use(\n createSageToolCallMiddleware({\n memory: memoryRetrieval,\n maxHintsPerTool: config.Sage?.inject?.maxHintsPerTool,\n maxCharsPerTool: config.Sage?.inject?.maxCharsPerTool,\n taskAware: config.Sage?.inject?.taskAware,\n minScore: config.Sage?.inject?.minScore,\n minImportance: config.Sage?.inject?.minImportance,\n repeatCooldownMs: config.Sage?.inject?.repeatCooldownMs,\n verifyOnMutation: config.Sage?.hygiene?.autoOnFileChange,\n triggers: config.Sage?.inject?.triggers,\n }),\n );\n }\n // Opt-in only (default OFF), matching the CLI wiring. Turn-context injection\n // appends a query-dependent block to the system prompt every turn, which\n // moves the provider cache breakpoint and defeats prefix caching. The\n // default retrieval path is the contextual tool-result injection above plus\n // the on-demand memory_* tools. See wiring/sage.ts.\n if (config.Sage?.inject?.turnContext === true) {\n pipelines.request.use(\n createSageTurnMiddleware({\n memory: memoryRetrieval,\n maxMemories: config.Sage?.inject?.maxTurnMemories,\n maxChars: config.Sage?.inject?.maxCharsPerTurn,\n minScore: config.Sage?.inject?.minScore,\n }),\n );\n }\n }\n const codebaseIndexing = setupWebUICodebaseIndexing({\n config,\n context,\n projectRoot,\n logger,\n events,\n });\n // Compactor \u2014 honors config.context.strategy ('hybrid' default, lossless\n // rules; 'intelligent'/'selective' resolve their provider from ctx at\n // compact()-time). eliseThreshold is a TOKEN COUNT (not a fraction).\n const compactor = createStrategyCompactor({\n strategy: config.context?.strategy,\n preserveK: config.context?.preserveK ?? 10,\n eliseThreshold: config.context?.eliseThreshold ?? 2000,\n summarizerModel: config.context?.summarizerModel,\n llmSelector: config.context?.llmSelector,\n });\n\n const initialContextPolicy = resolveContextWindowPolicy(config.context);\n // Auto-compaction\n let autoCompactor: AutoCompactionMiddleware | undefined;\n if (config.context?.autoCompact !== false) {\n let effectiveMaxContext = config.context?.effectiveMaxContext ?? 0;\n if (!effectiveMaxContext) {\n try {\n const m = await resolveProviderModelMetadata(\n modelsRegistry,\n config.provider,\n context.model,\n config.providers?.[config.provider],\n );\n effectiveMaxContext = m?.capabilities?.maxContext ?? 0;\n } catch {\n // best-effort: fall through to provider capability\n }\n }\n if (!effectiveMaxContext) effectiveMaxContext = provider.capabilities.maxContext;\n autoCompactor = new AutoCompactionMiddlewareCtor(\n compactor,\n effectiveMaxContext,\n (ctx) =>\n estimateRequestTokensCalibrated(\n ctx.messages,\n ctx.systemPrompt,\n ctx.tools ?? [],\n `${ctx.provider?.id ?? 'unknown'}/${ctx.model}`,\n ).total,\n {\n warn: initialContextPolicy.thresholds.warn,\n soft: initialContextPolicy.thresholds.soft,\n hard: initialContextPolicy.thresholds.hard,\n },\n {\n events,\n aggressiveOn: initialContextPolicy.aggressiveOn,\n policyProvider: (ctx) => {\n const policy = ctx.meta['contextWindowPolicy'];\n return policy && typeof policy === 'object'\n ? (policy as ReturnType<typeof resolveContextWindowPolicy>)\n : initialContextPolicy;\n },\n },\n );\n pipelines.contextWindow.use({ name: 'AutoCompaction', handler: autoCompactor.handler() });\n }\n\n /** Refresh AutoCompactionMiddleware denominator when the active model changes. */\n const updateAutoCompactionMaxContext = async (\n newProvider: Provider,\n providerId = newProvider.id,\n providerCfg?: ProviderConfig | undefined,\n ): Promise<void> => {\n await modelsRegistry.refresh().catch((err) => {\n logger.warn(\n `models.dev refresh failed for ${providerId}/${context.model}: ${toErrorMessage(err)}; using cached catalog`,\n );\n });\n const currentConfig = input.config;\n let newMaxContext =\n currentConfig.context?.effectiveMaxContext ?? newProvider.capabilities.maxContext;\n try {\n const m = await resolveProviderModelMetadata(\n modelsRegistry,\n providerId,\n context.model,\n providerCfg ?? currentConfig.providers?.[providerId],\n );\n newMaxContext = m?.capabilities?.maxContext ?? newMaxContext;\n } catch {\n // best-effort: use provider capability\n }\n newProvider.capabilities.maxContext = newMaxContext;\n modelCapabilitiesRef.current =\n newMaxContext > 0\n ? {\n maxContextTokens: newMaxContext,\n supportsTools: !!newProvider.capabilities.tools,\n supportsVision: !!newProvider.capabilities.vision,\n supportsReasoning: !!newProvider.capabilities.reasoning,\n }\n : undefined;\n if (newMaxContext > 0) {\n context.meta['effectiveMaxContext'] = newMaxContext;\n autoCompactor?.setMaxContext(newMaxContext);\n autoCompactor?.setEnabled(config.context?.autoCompact !== false);\n } else {\n delete context.meta['effectiveMaxContext'];\n autoCompactor?.setEnabled(false);\n }\n events.emit('ctx.max_context', {\n sessionId: context.session.id,\n providerId: newProvider.id,\n modelId: context.model,\n maxContext: newMaxContext,\n });\n };\n\n // Agent\n const secretScrubber = container.resolve(TOKENS.SecretScrubber);\n const renderer = container.has(TOKENS.Renderer) ? container.resolve(TOKENS.Renderer) : undefined;\n const permissionPolicy = container.resolve(TOKENS.PermissionPolicy);\n const toolExecutor = new ToolExecutor(toolRegistry, {\n permissionPolicy,\n secretScrubber,\n renderer,\n events,\n confirmAwaiter: undefined,\n iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,\n perIterationOutputCapBytes:\n config.tools?.perIterationOutputCapBytes ?? DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,\n tracer: undefined,\n });\n\n // Mailbox bridge discovery \u2014 fire-and-forget. Best-effort: a failed\n // discovery never blocks the WebUI from starting.\n const webuiLogger = container.resolve(TOKENS.Logger);\n void discoverMailboxBridgeForWebui({\n projectRoot,\n config,\n logger: webuiLogger,\n ctx: context,\n }).catch((err: unknown) => {\n webuiLogger.warn('mailbox bridge discovery threw on webui boot', {\n err: err instanceof Error ? err.message : String(err),\n });\n });\n\n const agent = new Agent({\n container,\n tools: toolRegistry,\n providers: providerRegistry,\n events,\n pipelines,\n context,\n maxIterations: config.tools?.maxIterations ?? DEFAULT_TOOLS_CONFIG.maxIterations,\n iterationTimeoutMs: config.tools?.iterationTimeoutMs ?? DEFAULT_TOOLS_CONFIG.iterationTimeoutMs,\n executionStrategy:\n config.tools?.defaultExecutionStrategy ?? DEFAULT_TOOLS_CONFIG.defaultExecutionStrategy,\n perIterationOutputCapBytes:\n config.tools?.perIterationOutputCapBytes ?? DEFAULT_TOOLS_CONFIG.perIterationOutputCapBytes,\n loopDetection: config.tools?.loopDetection ?? DEFAULT_TOOLS_CONFIG.loopDetection,\n confirmAwaiter: undefined,\n toolExecutor,\n });\n if (config.features.memory && config.features.memoryConsolidation !== false) {\n const consSage = getSageService(memoryStore) as ConsolidatorSage | undefined;\n agent.extensions.register(\n new SessionMemoryConsolidator({\n memoryStore,\n ...(consSage ? { Sage: consSage } : {}),\n }),\n );\n }\n console.log('[WebUI] Agent initialized');\n\n // \u2500\u2500 Brain \u2014 policy \u2192 LLM/council \u2192 terminal-policy decision layer \u2500\u2500\u2500\u2500\u2500\u2500\n // The standalone WebUI has no blocking human prompt surface, so the\n // escalation tier always resolves through the terminal policy (safe\n // default or deny) \u2014 the Brain never returns a dangling `ask_human`.\n // The whole `config.brain` surface is owned by a BrainRuntime: the\n // brain.config.set route live-rebuilds the tiers AND persists globally\n // (config.brain is on the in-project deny list).\n // Product defaults (minimum-human): pool seeded from fallbackModels,\n // adaptive risk ceiling. Explicit config.brain fields always win.\n const brainCfg = resolveBrainConfigDefaults(config.brain, {\n fallbackModels: config.fallbackModels,\n });\n const brainLedgerPath = join(wpaths.projectDir, 'brain-ledger.jsonl');\n let brainLedgerEnabled = brainCfg.ledger?.enabled !== false;\n let brainLedger: BrainDecisionLedger | undefined;\n const startBrainLedger = (): void => {\n if (brainLedger) return;\n brainLedger = new BrainDecisionLedger({ events, filePath: brainLedgerPath });\n void brainLedger.start();\n };\n if (brainLedgerEnabled) startBrainLedger();\n // Declared before the runtime so `onApplied` can re-tune it; assigned below,\n // once the Brain chain it consults exists.\n let brainMonitor: BrainMonitor | undefined;\n const brainRuntime = createBrainRuntime({\n initialConfig: brainCfg,\n defaultProviderId: config.provider,\n sessionProvider: () => provider,\n sessionModel: () => context.model,\n resolveProvider: (providerId) => {\n const savedCfg: Partial<import('@wrongstack/core/types').ProviderConfig> =\n config.providers?.[providerId] ?? {};\n return providerRegistry.create({\n ...savedCfg,\n apiKey: savedCfg.apiKey ?? config.apiKey,\n baseUrl: savedCfg.baseUrl ?? config.baseUrl,\n type: providerId,\n } as never);\n },\n ledger: {\n getPath: () => (brainLedgerEnabled ? brainLedgerPath : undefined),\n isEnabled: () => brainLedgerEnabled,\n setEnabled: (on) => {\n brainLedgerEnabled = on;\n if (on) {\n startBrainLedger();\n } else {\n void brainLedger?.stop();\n brainLedger = undefined;\n }\n },\n failureStreakFor: (request) => brainLedger?.failureStreakFor(request) ?? 0,\n getDecisionDigest: (request) => brainLedger?.digestFor(request),\n },\n persist: input.persistBrainConfig,\n // Keep the monitor's thresholds live, same as the CLI host. `reconfigure`\n // no-ops when the monitor block is unchanged, so unrelated Brain edits\n // (risk, pool, council) do not reset its in-flight failure streaks.\n onApplied: (snapshot) => {\n brainMonitor?.reconfigure(snapshot.monitor);\n },\n });\n // Back-compat facade for the risk-only route: assignment routes through\n // runtime.apply(), which live-applies AND persists.\n const brainSettings: { maxAutoRisk: BrainAutoRisk } = {\n get maxAutoRisk() {\n return brainRuntime.getMaxAutoRisk();\n },\n set maxAutoRisk(level: BrainAutoRisk) {\n void brainRuntime.apply({ maxAutoRisk: level }).persisted;\n },\n };\n const brain = new ObservableBrainArbiterCtor(\n new EscalationRoutingBrainArbiter(brainRuntime.arbiter, undefined, () => 'headless'),\n events,\n );\n container.bind(TOKENS.BrainArbiter, () => brain);\n\n // Decision log for the /brain command \u2014 last 20 decisions, newest last.\n const brainLog: Array<{ at: number; kind: string; question: string; outcome: string }> = [];\n const pushBrainLog = (entry: (typeof brainLog)[number]) => {\n brainLog.push(entry);\n if (brainLog.length > 20) brainLog.shift();\n };\n const brainLogOffs = [\n events.on('brain.decision_answered', (e) =>\n pushBrainLog({\n at: e.at,\n kind: 'answered',\n question: e.request.question,\n outcome: e.decision.type === 'answer' ? (e.decision.optionId ?? e.decision.text) : '',\n }),\n ),\n events.on('brain.decision_ask_human', (e) =>\n pushBrainLog({\n at: e.at,\n kind: 'ask_human',\n question: e.request.question,\n outcome: 'needs human judgement',\n }),\n ),\n events.on('brain.decision_denied', (e) =>\n pushBrainLog({\n at: e.at,\n kind: 'denied',\n question: e.request.question,\n outcome: e.decision.type === 'deny' ? e.decision.reason : '',\n }),\n ),\n ];\n\n // Self-activation: watch for tool-failure streaks / error storms. `session`\n // is read at send time via the getter the caller passes, so the steer\n // always targets the LIVE session's leader identity.\n const brainMailbox = getSharedProjectMailbox(wpaths.projectDir, events);\n brainMonitor = new BrainMonitor({\n events,\n brain,\n // The full `config.brain.monitor` surface, matching the CLI host. Boot used\n // to skip enabled/policy/signals/errorStormWindowMs/stallCheckIntervalMs/\n // fileEditTools, so those settings were inert here \u2014 and now that\n // `reconfigure()` applies the whole block, an unrelated Brain edit would\n // have been the first thing to honour them.\n enabled: brainCfg.monitor?.enabled,\n policy: brainCfg.monitor?.policy,\n signals: brainCfg.monitor?.signals,\n toolFailureStreak: brainCfg.monitor?.toolFailureStreak,\n errorStormCount: brainCfg.monitor?.errorStormCount,\n errorStormWindowMs: brainCfg.monitor?.errorStormWindowMs,\n stallMs: brainCfg.monitor?.stallMs,\n stallCheckIntervalMs: brainCfg.monitor?.stallCheckIntervalMs,\n fileChurnThreshold: brainCfg.monitor?.fileChurnThreshold,\n fileChurnWindowMs: brainCfg.monitor?.fileChurnWindowMs,\n fileEditTools: brainCfg.monitor?.fileEditTools,\n cooldownMs: brainCfg.monitor?.cooldownMs,\n sessionId: () => context.session?.id,\n intervene: async ({ subject, body }) => {\n const tag = mailboxSessionTag(input.sessionGetter().id);\n await brainMailbox.send({\n from: `brain@${tag}`,\n to: `leader@${tag}`,\n type: 'steer',\n subject,\n body,\n priority: 'high',\n });\n },\n });\n brainMonitor.start();\n console.log('[WebUI] Brain initialized (tiered policy \u2192 LLM, monitor active)');\n\n // Per-feature WebSocket handlers.\n const goalHandler = new GoalWebSocketHandler(\n agent,\n context,\n logger,\n wpaths.projectAutophase,\n events,\n projectRoot,\n );\n const specsHandler = new SpecsWebSocketHandler(wpaths.projectSpecs, wpaths.projectTaskGraphs);\n const sddBoardHandler = new SddBoardWebSocketHandler(\n wpaths.projectSddBoards,\n undefined,\n {\n projectRoot,\n paths: {\n projectSpecs: wpaths.projectSpecs,\n projectTaskGraphs: wpaths.projectTaskGraphs,\n projectSddSession: wpaths.projectSddSession,\n projectSddBoards: wpaths.projectSddBoards,\n },\n },\n { trustBoundary: input.trustBoundary, logger },\n );\n const sddWizardHandler = new SddWizardWebSocketHandler(\n buildSddWizardDeps({\n agent,\n events,\n projectRoot,\n brain,\n subagentFactory: makeLightSubagentFactory({\n container,\n providerRegistry,\n toolRegistry,\n session: input.sessionGetter(),\n projectRoot,\n // Thread the container-provided ProviderModelStatusTracker so a 429\n // from this subagent's first call transitions the (provider, model)\n // pair to `state: 'blocked'` instead of silently no-op'ing. The\n // runtime container binds a default `ProviderModelStatusTracker`\n // (see packages/runtime/src/container.ts); without this dep, the\n // subagent's fallback extension's tracker hooks are undefined and\n // round-robin keeps reassigning the doomed model. Mirrors the CLI\n // factory wiring at host-subagent-factory.ts:337.\n statusTracker: container.safeResolve(TOKENS.ProviderModelStatusTracker),\n }),\n paths: {\n projectSpecs: wpaths.projectSpecs,\n projectTaskGraphs: wpaths.projectTaskGraphs,\n projectSddBoards: wpaths.projectSddBoards,\n projectDir: wpaths.projectDir,\n projectSddSession: wpaths.projectSddSession,\n },\n }),\n );\n const worktreeHandler = new WorktreeWebSocketHandler(events, logger, {\n projectRoot,\n boardsDir: wpaths.projectSddBoards,\n });\n const terminalHandler = new TerminalWebSocketHandler(\n () => workingDir,\n logger,\n undefined,\n undefined,\n input.trustBoundary,\n );\n const collabHandler = new CollaborationWebSocketHandler(\n events,\n logger,\n input.sessionReader,\n input.annotationsStore,\n collabBus,\n {\n getActiveSessionId: () => context.session.id,\n },\n );\n let realtimeHandlersDisposed = false;\n const disposeRealtimeHandlers = () => {\n if (realtimeHandlersDisposed) return;\n realtimeHandlersDisposed = true;\n for (const off of brainLogOffs) off();\n goalHandler.dispose();\n sddBoardHandler.dispose();\n worktreeHandler.dispose();\n terminalHandler.dispose();\n collabHandler.dispose();\n };\n\n return {\n collabBus,\n compactor,\n autoCompactor,\n toolExecutor,\n agent,\n permissionPolicy,\n pipelines,\n brain,\n brainSettings,\n brainRuntime,\n brainLog,\n brainMonitor,\n // Getter: ledger toggles swap the instance, shutdown must stop the LIVE one.\n get brainLedger() {\n return brainLedger;\n },\n codebaseIndexing,\n goalHandler,\n specsHandler,\n sddBoardHandler,\n sddWizardHandler,\n worktreeHandler,\n terminalHandler,\n collabHandler,\n disposeRealtimeHandlers,\n updateAutoCompactionMaxContext,\n };\n}\n", "import { spawn } from 'node:child_process';\nimport { createRequire } from 'node:module';\nimport { existsSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { resolveProjectDir } from '@wrongstack/core/coordination';\nimport { wstackGlobalRoot } from '@wrongstack/core/utils';\nimport { readLiveLock, type MailboxBridgeLock } from '@wrongstack/core/coordination';\n\nexport interface MailboxBridgeParams {\n projectRoot: string;\n config: { features?: { mailboxBridge?: 'auto' | 'off' | undefined } } | undefined;\n logger: {\n debug: (msg: string, meta?: Record<string, unknown>) => void;\n warn: (msg: string, meta?: Record<string, unknown>) => void;\n info: (msg: string, meta?: Record<string, unknown>) => void;\n };\n ctx: { meta: Record<string, unknown> };\n}\n\nconst MAILBOX_BRIDGE_BOOT_TIMEOUT_MS = 5_000;\n\n/**\n * Attempt to discover and join a running mailbox bridge server.\n *\n * If no healthy bridge is present, standalone WebUI surfaces try to\n * spawn `wstack mailbox serve` and wait briefly for the lock to become\n * healthy. Failure stays non-fatal: the WebUI can run without external\n * agent HTTP connectivity.\n */\nexport async function discoverMailboxBridgeForWebui(params: MailboxBridgeParams): Promise<void> {\n const mode = params.config?.features?.mailboxBridge ?? 'auto';\n if (mode === 'off') return;\n\n const projectDir = resolveProjectDir(params.projectRoot, wstackGlobalRoot());\n let result = await readLiveLock(projectDir);\n let spawnedPid: number | null = null;\n if (result.kind !== 'live') {\n spawnedPid = spawnMailboxBridge(params.projectRoot, params.logger);\n if (spawnedPid !== null) {\n const live = await waitForLiveMailboxBridge(projectDir, MAILBOX_BRIDGE_BOOT_TIMEOUT_MS);\n if (live) {\n stashBridge(params, live, projectDir, 'spawned', spawnedPid);\n params.logger.debug('webui spawned mailbox bridge', {\n url: live.url,\n lockPath: projectDir,\n childPid: spawnedPid,\n });\n return;\n }\n result = await readLiveLock(projectDir);\n }\n }\n switch (result.kind) {\n case 'live': {\n params.logger.debug('webui joined existing mailbox bridge', {\n url: result.lock.url,\n lockPath: projectDir,\n });\n stashBridge(params, result.lock, projectDir, 'joined', null);\n break;\n }\n case 'probe-failed': {\n params.logger.warn(\n 'mailbox bridge present but /healthz unreachable; webui will start without external-agent connectivity',\n { url: result.lock.url, lockPath: projectDir, spawnedPid },\n );\n stashBridge(params, result.lock, projectDir, 'unhealthy', null);\n break;\n }\n case 'absent': {\n params.logger.warn(\n 'mailbox bridge unavailable; webui will start without external-agent connectivity. Run `wstack mailbox serve` or a CLI surface to bring one up.',\n { projectDir, spawnedPid },\n );\n break;\n }\n }\n}\n\nfunction stashBridge(\n params: MailboxBridgeParams,\n lock: MailboxBridgeLock,\n lockPath: string,\n source: 'joined' | 'spawned' | 'unhealthy',\n childPid: number | null,\n): void {\n params.ctx.meta['mailboxBridge'] = {\n url: lock.url,\n token: lock.token,\n lockPath,\n childPid,\n source,\n };\n}\n\nasync function waitForLiveMailboxBridge(\n projectDir: string,\n timeoutMs: number,\n): Promise<MailboxBridgeLock | null> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n await sleep(120);\n const result = await readLiveLock(projectDir);\n if (result.kind === 'live') return result.lock;\n }\n return null;\n}\n\nfunction spawnMailboxBridge(\n projectRoot: string,\n logger: MailboxBridgeParams['logger'],\n): number | null {\n const invocation = mailboxServeInvocation(projectRoot);\n try {\n const child = spawn(invocation.command, invocation.args, {\n cwd: projectRoot,\n detached: process.platform !== 'win32' && !invocation.useShell,\n env: process.env,\n stdio: 'ignore',\n windowsHide: true,\n ...(invocation.windowsVerbatimArguments\n ? { windowsVerbatimArguments: invocation.windowsVerbatimArguments }\n : {}),\n ...(invocation.useShell ? { shell: true } : {}),\n });\n child.once('error', (err) => {\n logger.warn('failed to spawn mailbox bridge for webui', {\n command: invocation.command,\n err: err instanceof Error ? err.message : String(err),\n });\n });\n child.unref();\n return child.pid ?? null;\n } catch (err) {\n logger.warn('failed to spawn mailbox bridge for webui', {\n command: invocation.command,\n err: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n}\n\nfunction mailboxServeInvocation(projectRoot: string): {\n command: string;\n args: string[];\n windowsVerbatimArguments?: boolean | undefined;\n useShell?: boolean | undefined;\n} {\n const explicitCliEntry = process.env['WRONGSTACK_CLI_ENTRY'];\n if (explicitCliEntry) {\n return { command: process.execPath, args: [explicitCliEntry, 'mailbox', 'serve'] };\n }\n try {\n const require = createRequire(import.meta.url);\n const cliEntry = require.resolve('@wrongstack/cli');\n return { command: process.execPath, args: [cliEntry, 'mailbox', 'serve'] };\n } catch {\n // @wrongstack/cli is not in webui-server's declared dependencies, so\n // pnpm does not symlink it into this package's node_modules and\n // require.resolve() above fails. Walk up from projectRoot looking for\n // a sibling `packages/cli/dist/index.js` (the workspace layout the\n // monorepo CLI ships) and run it directly with process.execPath.\n //\n // This avoids:\n // - `spawn wstack.cmd` failing with EINVAL (Node 20+ refuses to\n // spawn `.cmd`/`.bat` without `shell: true` \u2014 CVE-2024-27980).\n // - relying on a globally-installed `wstack` that may not exist on\n // developer machines that only run the monorepo.\n const workspaceCliEntry = findWorkspaceCliEntry(projectRoot);\n if (workspaceCliEntry) {\n return {\n command: process.execPath,\n args: [workspaceCliEntry, 'mailbox', 'serve'],\n };\n }\n // Last resort: try the on-PATH shim. On Windows, spawning a `.cmd`\n // requires `shell: true` since Node 20 (CVE-2024-27980) \u2014 without\n // it, spawn() rejects with EINVAL.\n if (process.platform === 'win32') {\n return {\n command: 'wstack.cmd',\n args: ['mailbox', 'serve'],\n useShell: true,\n };\n }\n return { command: 'wstack', args: ['mailbox', 'serve'] };\n }\n}\n\n/**\n * Walk up from `projectRoot` looking for a sibling `packages/cli/dist/index.js`.\n * Works for the published monorepo layout (projectRoot = monorepo root) and\n * for extracted checkouts where the workspace sits a few levels above.\n */\nfunction findWorkspaceCliEntry(projectRoot: string): string | null {\n let dir = projectRoot;\n for (let i = 0; i < 6; i++) {\n const candidate = join(dir, 'packages', 'cli', 'dist', 'index.js');\n if (existsSync(candidate)) return candidate;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n return null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n", "import { spawn as spawnChild } from 'node:child_process';\nimport { createRequire } from 'node:module';\nimport type { Logger } from '@wrongstack/core/types';\nimport { createCompatibilityTrustBoundary, type TrustBoundary } from '@wrongstack/core/security';\nimport { buildChildEnv, toErrorMessage } from '@wrongstack/core/utils';\nimport type { WebSocket } from 'ws';\nimport { authorizeWebUIAction } from './privileged-actions.js';\nimport type { WSServerMessage } from './types.js';\nimport { sendSerialized } from './ws-utils.js';\n\n/** Loose inbound shape \u2014 matches the server's internal WSClientMessage. */\ntype IncomingMessage = { type: string; payload?: unknown };\ntype PtyExit = { exitCode: number; signal?: number | undefined };\ninterface PtyProcess {\n readonly pid?: number | undefined;\n write(data: string): void;\n resize(cols: number, rows: number): void;\n kill(): void;\n onData(cb: (data: string) => void): unknown;\n onExit(cb: (event: PtyExit) => void): unknown;\n}\ninterface NodePtyApi {\n spawn(\n file: string,\n args: string[],\n opts: {\n name: string;\n cols: number;\n rows: number;\n cwd: string;\n env: Record<string, string | undefined>;\n useConptyDll?: boolean | undefined;\n },\n ): PtyProcess;\n}\ntype LoadNodePty = () => NodePtyApi | null;\ntype KillProcessTree = (pid: number) => void;\n\n/** Hard cap on concurrent PTYs per connected client \u2014 a runaway-spawn backstop. */\nconst MAX_SESSIONS_PER_CLIENT = 8;\n/** Maximum characters accepted in a single terminal.input \u2014 a DoS backstop. */\nconst MAX_INPUT_BYTES = 1 << 16; // 64 KiB\nconst DEFAULT_COLS = 80;\nconst DEFAULT_ROWS = 24;\nconst requireFromHere = createRequire(import.meta.url);\nlet cachedNodePty: NodePtyApi | null | undefined;\n\nexport function resolveTerminalShell(\n platform: NodeJS.Platform = process.platform,\n env: NodeJS.ProcessEnv = process.env,\n): string {\n return platform === 'win32' ? env.COMSPEC || 'cmd.exe' : env.SHELL || '/bin/sh';\n}\n\n/**\n * TerminalWebSocketHandler \u2014 backs the WebUI's integrated terminal panel.\n *\n * Mirrors the lifecycle shape of WorktreeWebSocketHandler but is *per-client*\n * and *interactive*: each connected WebSocket owns a map of real node-pty\n * sessions keyed by a client-chosen id. Browser xterm.js \u21C4 pty wiring:\n * - `terminal.create` \u2192 spawn a shell pty, stream its output back\n * - `terminal.input` \u2192 write keystrokes to the pty\n * - `terminal.resize` \u2192 propagate xterm's fit dimensions\n * - `terminal.close` \u2192 kill the pty\n * When a client disconnects, every pty it owns is killed (no orphan shells).\n */\nexport class TerminalWebSocketHandler {\n /** ws \u2192 (terminalId \u2192 pty). */\n private readonly sessions = new Map<WebSocket, Map<string, PtyProcess>>();\n\n constructor(\n /** Resolves the cwd new terminals open in \u2014 tracks the live working dir. */\n private readonly getCwd: () => string,\n private readonly logger: Logger,\n private readonly loadNodePty: LoadNodePty = defaultLoadNodePty,\n private readonly killProcessTree: KillProcessTree = defaultKillProcessTree,\n private readonly trustBoundary: TrustBoundary = createCompatibilityTrustBoundary(),\n ) {}\n\n addClient(ws: WebSocket): void {\n if (!this.sessions.has(ws)) this.sessions.set(ws, new Map());\n ws.on('close', () => this.disposeClient(ws));\n ws.on('error', () => this.disposeClient(ws));\n }\n\n /** Kill every pty owned by every client (server shutdown). */\n dispose(): void {\n for (const ws of [...this.sessions.keys()]) this.disposeClient(ws);\n }\n\n /** True if this message was a terminal.* message (handled here). */\n async handleMessage(ws: WebSocket, msg: IncomingMessage): Promise<boolean> {\n const p = (msg.payload ?? {}) as Record<string, unknown>;\n switch (msg.type) {\n case 'terminal.create':\n if (isStr(p.id))\n await this.create(ws, {\n id: p.id,\n cols: numOrUndef(p.cols),\n rows: numOrUndef(p.rows),\n });\n return true;\n case 'terminal.input':\n if (isStr(p.id) && isStr(p.data)) this.input(ws, { id: p.id, data: p.data });\n return true;\n case 'terminal.resize':\n if (isStr(p.id)) this.resize(ws, { id: p.id, cols: Number(p.cols), rows: Number(p.rows) });\n return true;\n case 'terminal.close':\n if (isStr(p.id)) this.close(ws, p.id);\n return true;\n default:\n return false;\n }\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private async create(\n ws: WebSocket,\n payload: { id: string; cols?: number | undefined; rows?: number | undefined },\n ): Promise<void> {\n const map = this.sessions.get(ws) ?? new Map<string, PtyProcess>();\n this.sessions.set(ws, map);\n\n if (map.has(payload.id)) return; // idempotent \u2014 already running\n if (map.size >= MAX_SESSIONS_PER_CLIENT) {\n this.send(ws, {\n type: 'terminal.exit',\n payload: { id: payload.id, exitCode: -1 },\n });\n return;\n }\n\n const shell = resolveTerminalShell();\n const cwd = this.getCwd();\n const authorization = await authorizeWebUIAction(\n this.trustBoundary,\n {\n capability: 'process.spawn',\n subject: {\n kind: 'command',\n id: shell,\n attributes: { terminalId: payload.id },\n },\n risk: 'high',\n cwd,\n metadata: { transport: 'websocket' },\n },\n this.logger,\n );\n if (!authorization.allowed) {\n this.logger.warn?.(`terminal.create denied (id=${payload.id}): ${authorization.reason}`);\n const msg = `Integrated terminal denied: ${authorization.reason}`;\n this.send(ws, { type: 'terminal.output', payload: { id: payload.id, data: `${msg}\\r\\n` } });\n this.send(ws, { type: 'terminal.exit', payload: { id: payload.id, exitCode: -1 } });\n return;\n }\n\n const nodePty = this.loadNodePty();\n if (!nodePty) {\n const msg =\n 'Integrated terminal unavailable: optional dependency node-pty is not installed. ' +\n 'Install node-pty to enable WebUI terminal sessions.';\n this.logger.warn?.(msg);\n this.send(ws, { type: 'terminal.output', payload: { id: payload.id, data: `${msg}\\r\\n` } });\n this.send(ws, { type: 'terminal.exit', payload: { id: payload.id, exitCode: -1 } });\n return;\n }\n\n let pty: PtyProcess;\n try {\n pty = nodePty.spawn(shell, [], {\n name: 'xterm-color',\n cols: clampDim(payload.cols, DEFAULT_COLS),\n rows: clampDim(payload.rows, DEFAULT_ROWS),\n cwd,\n env: buildChildEnv(),\n ...windowsPtyOptions(),\n });\n } catch (err) {\n const msg = `Integrated terminal failed to start: ${toErrorMessage(err)}`;\n this.logger.warn?.(`terminal spawn failed: ${toErrorMessage(err)}`);\n this.send(ws, { type: 'terminal.output', payload: { id: payload.id, data: `${msg}\\r\\n` } });\n this.send(ws, { type: 'terminal.exit', payload: { id: payload.id, exitCode: -1 } });\n return;\n }\n\n map.set(payload.id, pty);\n this.logger.info?.(`terminal.create spawned (id=${payload.id}, pid=${pty.pid ?? '?'}) in ${cwd}`);\n\n pty.onData((data) => {\n this.send(ws, { type: 'terminal.output', payload: { id: payload.id, data } });\n });\n pty.onExit(({ exitCode, signal }) => {\n map.delete(payload.id);\n this.send(ws, {\n type: 'terminal.exit',\n payload: { id: payload.id, exitCode, signal: signal ?? undefined },\n });\n });\n }\n\n private input(ws: WebSocket, payload: { id: string; data: string }): void {\n const pty = this.sessions.get(ws)?.get(payload.id);\n if (pty) pty.write(payload.data.slice(0, MAX_INPUT_BYTES));\n }\n\n private resize(ws: WebSocket, payload: { id: string; cols: number; rows: number }): void {\n const pty = this.sessions.get(ws)?.get(payload.id);\n if (!pty) return;\n try {\n pty.resize(clampDim(payload.cols, DEFAULT_COLS), clampDim(payload.rows, DEFAULT_ROWS));\n } catch {\n /* pty already gone */\n }\n }\n\n private close(ws: WebSocket, id: string): void {\n const map = this.sessions.get(ws);\n const pty = map?.get(id);\n if (!pty) return;\n map?.delete(id);\n this.killPty(pty, 'terminal close');\n }\n\n private disposeClient(ws: WebSocket): void {\n const map = this.sessions.get(ws);\n if (!map) return;\n for (const pty of map.values()) {\n this.killPty(pty, 'terminal client dispose');\n }\n this.sessions.delete(ws);\n }\n\n private killPty(pty: PtyProcess, reason: string): void {\n if (process.platform === 'win32' && isPositivePid(pty.pid)) {\n this.killWindowsProcessTree(pty, reason);\n return;\n }\n try {\n pty.kill();\n } catch (err) {\n this.logger.warn?.(`${reason} failed: ${toErrorMessage(err)}`);\n }\n }\n\n private killWindowsProcessTree(pty: PtyProcess, reason: string): void {\n try {\n this.killProcessTree(pty.pid as number);\n // Give an interactive shell a chance to exit cleanly if taskkill races\n // with ConPTY setup. Avoid node-pty.kill() here: on Windows it forks\n // conpty_console_list_agent, which can emit noisy AttachConsole failures\n // when the WebUI server is hosted by Electron.\n try {\n pty.write('\\x03');\n pty.write('exit\\r');\n } catch {\n /* process tree kill is already in flight */\n }\n } catch (err) {\n this.logger.warn?.(`${reason} taskkill failed: ${toErrorMessage(err)}`);\n }\n }\n\n private send(ws: WebSocket, msg: WSServerMessage): void {\n try {\n sendSerialized(ws, JSON.stringify(msg));\n } catch {\n /* client gone */\n }\n }\n}\n\nfunction defaultLoadNodePty(): NodePtyApi | null {\n if (cachedNodePty !== undefined) return cachedNodePty;\n try {\n cachedNodePty = requireFromHere('node-pty') as NodePtyApi;\n } catch {\n cachedNodePty = null;\n }\n return cachedNodePty;\n}\n\nfunction isStr(v: unknown): v is string {\n return typeof v === 'string';\n}\n\nfunction numOrUndef(v: unknown): number | undefined {\n return typeof v === 'number' && Number.isFinite(v) ? v : undefined;\n}\n\nfunction windowsPtyOptions(): { useConptyDll?: boolean | undefined } {\n if (process.platform !== 'win32') return {};\n if (process.env.WRONGSTACK_TERMINAL_USE_CONPTY_DLL !== '1') return {};\n return { useConptyDll: true };\n}\n\nfunction defaultKillProcessTree(pid: number): void {\n const child = spawnChild('taskkill', ['/PID', String(pid), '/T', '/F'], {\n stdio: 'ignore',\n windowsHide: true,\n });\n child.once('error', () => undefined);\n}\n\nfunction isPositivePid(value: unknown): value is number {\n return Number.isInteger(value) && Number(value) > 0;\n}\n\n/** Clamp a terminal dimension into a sane range; fall back to a default. */\nfunction clampDim(value: number | undefined, fallback: number): number {\n if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;\n return Math.max(1, Math.min(1000, Math.floor(value)));\n}\n", "import { join, resolve, sep } from 'node:path';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport type { Logger } from '@wrongstack/core/types';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport { WorktreeManager } from '@wrongstack/core/worktree';\nimport { cleanupStaleSddWorktrees } from '@wrongstack/sdd';\nimport type { WebSocket } from 'ws';\nimport type { WorktreeHandleView, WorktreeOrphanView, WSServerMessage } from './types.js';\nimport { sendSerialized } from './ws-utils.js';\n\nconst MAX_ACTIVITY = 6;\n\n/** Statuses that mean a worktree is actively owned by a live in-session run. */\nconst ACTIVE_STATUSES = new Set(['allocating', 'active', 'committing', 'merging']);\n\n/**\n * Only this project's own managed branches are operable from the panel \u2014 both a\n * safety scope (never touch `main`/arbitrary refs) AND an argv-injection guard:\n * the strict charset forbids a leading `-`, so a client can't smuggle a value\n * that git would parse as a flag. Mirrors `WorktreeManager`'s `wstack/ap/<slug>`.\n */\nconst MANAGED_BRANCH_RE = /^wstack\\/ap\\/[A-Za-z0-9._/-]+$/;\n\nexport interface WorktreeManagementDeps {\n projectRoot: string;\n /** Board snapshot dir \u2014 powers the cross-process liveness guard on cleanup. */\n boardsDir: string;\n}\n\n/**\n * WorktreeWebSocketHandler \u2014 mirrors GoalWebSocketHandler. Subscribes to\n * the shared EventBus `worktree.*` lifecycle events, keeps a live snapshot of\n * every worktree, and broadcasts:\n * - `worktree.event` incrementally (drives the flowing activity strip)\n * - `worktree.state` on connect + on a 2s timer (drives swim-lanes/DAG)\n */\nexport class WorktreeWebSocketHandler {\n private readonly clients = new Set<WebSocket>();\n private readonly handles = new Map<string, WorktreeHandleView>();\n private baseBranch = '';\n private broadcastInterval: ReturnType<typeof setInterval> | null = null;\n private readonly offs: Array<() => void> = [];\n /**\n * Single-flight guard for orphan scans. Two concurrent `scanAndBroadcast()`\n * calls would race: the first call reads `wt.listManaged()`, then the\n * second call's mutation completes (e.g. `removeOne`), then the first call\n * broadcasts a stale orphan list \u2014 the user sees a row persist and clicks\n * Remove a second time, hitting \"remove failed (not a managed worktree?)\".\n *\n * We coalesce concurrent triggers: while a scan is in flight, additional\n * callers are remembered as \"need a re-scan\" and exactly one follow-up\n * scan runs after the in-flight one finishes. The re-scan picks up any\n * mutations that landed during the previous scan's `listManaged()` window.\n */\n private scanInFlight: Promise<void> | null = null;\n private scanRescanNeeded = false;\n\n constructor(\n private readonly events: EventBus,\n private readonly logger: Logger,\n private readonly management?: WorktreeManagementDeps | undefined,\n ) {\n this.subscribe();\n }\n\n addClient(ws: WebSocket): void {\n this.clients.add(ws);\n ws.on('close', () => this.clients.delete(ws));\n ws.on('error', () => this.clients.delete(ws));\n this.send(ws, this.stateMessage());\n // Push the current orphan inventory to the freshly-connected client.\n void this.scanAndBroadcast();\n }\n\n /** Handle worktree-panel control messages (scan / clean / per-row ops). */\n async handleMessage(msg: { type: string; payload?: Record<string, unknown> }): Promise<boolean> {\n if (msg.type === 'worktree.scan') {\n await this.scanAndBroadcast();\n return true;\n }\n if (msg.type === 'worktree.cleanup') {\n await this.cleanupOrphans();\n return true;\n }\n if (msg.type === 'worktree.remove') {\n await this.removeOne(\n msg.payload?.['dir'] as string | undefined,\n msg.payload?.['branch'] as string | undefined,\n );\n return true;\n }\n if (msg.type === 'worktree.merge') {\n await this.mergeBranch(msg.payload?.['branch'] as string | undefined);\n return true;\n }\n if (msg.type === 'worktree.diff') {\n await this.diffOne(\n msg.payload?.['dir'] as string | undefined,\n msg.payload?.['baseBranch'] as string | undefined,\n );\n return true;\n }\n return false;\n }\n\n dispose(): void {\n for (const off of this.offs) off();\n this.offs.length = 0;\n this.stopBroadcast();\n }\n\n // \u2500\u2500 orphan management \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Absolute managed-worktrees root for this project. */\n private worktreesRoot(): string {\n return resolve(join(this.management!.projectRoot, '.wrongstack', 'worktrees'));\n }\n\n /** True iff `dir` resolves strictly inside the managed worktrees root. */\n private underRoot(dir: string): boolean {\n const abs = resolve(dir);\n const root = this.worktreesRoot();\n return abs !== root && abs.startsWith(root + sep);\n }\n\n /** Branches of worktrees a live in-session run currently owns. */\n private liveActiveBranches(): Set<string> {\n const live = new Set<string>();\n for (const h of this.handles.values()) {\n if (ACTIVE_STATUSES.has(h.status) && h.branch) live.add(h.branch);\n }\n return live;\n }\n\n /**\n * Coalesced orphan scan entry point. Multiple concurrent callers share one\n * in-flight scan; if a caller arrives during a scan, a single follow-up\n * scan is scheduled to pick up mutations that landed mid-scan. Returns the\n * shared promise so `await this.scanAndBroadcast()` still works for callers\n * that want to chain after the next broadcast.\n */\n private scanAndBroadcast(): Promise<void> {\n if (this.scanInFlight) {\n this.scanRescanNeeded = true;\n return this.scanInFlight;\n }\n this.scanInFlight = this.runScanAndMaybeRescan();\n return this.scanInFlight;\n }\n\n /**\n * Run the actual scan, then drain a pending re-scan request if one came in\n * during the scan. The re-scan is bounded (one follow-up) \u2014 additional\n * requests that arrive during the follow-up coalesce into the next one.\n */\n private async runScanAndMaybeRescan(): Promise<void> {\n try {\n await this.runScanOnce();\n while (this.scanRescanNeeded) {\n this.scanRescanNeeded = false;\n await this.runScanOnce();\n }\n } finally {\n // Clear the in-flight slot. Any caller arriving after this point will\n // start a fresh scan through `scanAndBroadcast`. The flag is already\n // false here because the while-loop drained it; a new caller during\n // the final `runScanOnce` await would have set it via `scanAndBroadcast`,\n // which short-circuited to the in-flight promise rather than mutating\n // the flag (the flag is only set by callers that arrived after the\n // in-flight promise was published).\n this.scanInFlight = null;\n }\n }\n\n /**\n * Scan the disk for managed worktrees/branches NOT owned by a live in-session\n * run and broadcast them as orphans, with whether it is safe to clean now.\n * No-op (empty inventory) when management deps were not wired.\n */\n private async runScanOnce(): Promise<void> {\n if (!this.management) {\n this.broadcast({ type: 'worktree.orphans', payload: { orphans: [], canClean: false } });\n return;\n }\n try {\n const wt = new WorktreeManager({ projectRoot: this.management.projectRoot });\n const { worktrees, branches } = await wt.listManaged();\n const live = this.liveActiveBranches();\n const orphans: WorktreeOrphanView[] = [];\n const seenBranches = new Set<string>();\n for (const w of worktrees) {\n if (w.branch && live.has(w.branch)) continue; // owned by a live run\n if (w.branch) seenBranches.add(w.branch);\n orphans.push({ kind: 'worktree', dir: w.dir, branch: w.branch });\n }\n // Branch-only orphans (no checkout) \u2014 skip those a live run owns or that a\n // listed worktree already covers.\n for (const b of branches) {\n if (live.has(b) || seenBranches.has(b)) continue;\n orphans.push({ kind: 'branch', branch: b });\n }\n // Safe to clean when no live in-session worktree exists. (The cross-process\n // board guard is additionally enforced at cleanup time.)\n const canClean = this.liveActiveBranches().size === 0;\n this.broadcast({\n type: 'worktree.orphans',\n payload: {\n orphans,\n canClean,\n reason: canClean ? undefined : 'a run is live in this session',\n },\n });\n } catch (err) {\n this.logger.debug?.(`worktree orphan scan failed: ${toErrorMessage(err)}`);\n this.broadcast({ type: 'worktree.orphans', payload: { orphans: [], canClean: false } });\n }\n }\n\n /**\n * Force-remove every orphaned worktree + branch. Refused while a run is live \u2014\n * in this session (active handles) OR another process (the SDD board liveness\n * guard inside cleanupStaleSddWorktrees). Best-effort; reports the outcome.\n */\n private async cleanupOrphans(): Promise<void> {\n if (!this.management) {\n this.broadcast({\n type: 'worktree.cleanup_result',\n payload: { ok: false, removed: 0, reason: 'cleanup is not available in this session' },\n });\n return;\n }\n if (this.liveActiveBranches().size > 0) {\n this.broadcast({\n type: 'worktree.cleanup_result',\n payload: { ok: false, removed: 0, reason: 'a run is live in this session \u2014 stop it first' },\n });\n return;\n }\n const res = await cleanupStaleSddWorktrees({\n projectRoot: this.management.projectRoot,\n boardsDir: this.management.boardsDir,\n stateTransport: 'kanban',\n });\n if (res.skippedReason) {\n this.broadcast({\n type: 'worktree.cleanup_result',\n payload: { ok: false, removed: 0, reason: res.skippedReason },\n });\n await this.scanAndBroadcast();\n return;\n }\n // Drop any kept-for-review handles we held \u2014 their checkouts are gone now.\n for (const [id, h] of [...this.handles]) {\n if (!ACTIVE_STATUSES.has(h.status)) this.handles.delete(id);\n }\n this.broadcast({\n type: 'worktree.cleanup_result',\n payload: { ok: true, removed: res.removed },\n });\n this.broadcastState();\n await this.scanAndBroadcast();\n }\n\n /** Remove/discard ONE worktree + branch. Refused while a live run owns it. */\n private async removeOne(dir?: string, branch?: string): Promise<void> {\n if (!this.management || (!dir && !branch)) {\n this.broadcast({\n type: 'worktree.cleanup_result',\n payload: { ok: false, removed: 0, reason: 'nothing to remove' },\n });\n return;\n }\n // Validate the client-supplied targets: a branch must be one of ours (the\n // regex also blocks argv flag-smuggling) and a dir must be inside the\n // managed worktrees root (no path traversal to arbitrary checkouts).\n if (branch && !MANAGED_BRANCH_RE.test(branch)) {\n this.broadcast({\n type: 'worktree.cleanup_result',\n payload: { ok: false, removed: 0, reason: 'not a managed worktree branch' },\n });\n return;\n }\n if (dir && !this.underRoot(dir)) {\n this.broadcast({\n type: 'worktree.cleanup_result',\n payload: { ok: false, removed: 0, reason: 'path is outside the managed worktrees root' },\n });\n return;\n }\n if (branch && this.liveActiveBranches().has(branch)) {\n this.broadcast({\n type: 'worktree.cleanup_result',\n payload: {\n ok: false,\n removed: 0,\n reason: 'a run is live on this worktree \u2014 stop it first',\n },\n });\n return;\n }\n let removed = false;\n if (dir) {\n const wt = new WorktreeManager({ projectRoot: this.management.projectRoot });\n ({ removed } = await wt.removeOne(dir, branch));\n }\n // Drop our handle for this branch/dir.\n for (const [id, h] of [...this.handles]) {\n if ((branch && h.branch === branch) || (dir && h.handleId && dir.endsWith(h.handleId)))\n this.handles.delete(id);\n }\n this.broadcast({\n type: 'worktree.cleanup_result',\n payload: {\n ok: removed,\n removed: removed ? 1 : 0,\n reason: removed ? undefined : 'remove failed (not a managed worktree?)',\n },\n });\n this.broadcastState();\n await this.scanAndBroadcast();\n }\n\n /** Squash-merge ONE branch into base. Refused while a live run owns it. */\n private async mergeBranch(branch?: string): Promise<void> {\n if (!this.management || !branch) {\n this.broadcast({\n type: 'worktree.merge_result',\n payload: { ok: false, branch: branch ?? '', reason: 'no branch' },\n });\n return;\n }\n if (!MANAGED_BRANCH_RE.test(branch)) {\n this.broadcast({\n type: 'worktree.merge_result',\n payload: { ok: false, branch, reason: 'not a managed worktree branch' },\n });\n return;\n }\n if (this.liveActiveBranches().has(branch)) {\n this.broadcast({\n type: 'worktree.merge_result',\n payload: { ok: false, branch, reason: 'a run is live on this worktree \u2014 stop it first' },\n });\n return;\n }\n const wt = new WorktreeManager({ projectRoot: this.management.projectRoot });\n const res = await wt.mergeBranch(branch);\n this.broadcast({\n type: 'worktree.merge_result',\n payload: {\n ok: res.ok,\n branch,\n conflict: res.conflict,\n conflictFiles: res.conflictFiles,\n reason: res.reason,\n },\n });\n await this.scanAndBroadcast();\n }\n\n /** Compact change summary for one worktree checkout. */\n private async diffOne(dir?: string, baseBranch?: string): Promise<void> {\n // Same path guard as removeOne \u2014 never run git in an arbitrary directory.\n if (!this.management || !dir || !this.underRoot(dir)) {\n this.broadcast({ type: 'worktree.diff_result', payload: { dir: dir ?? '', summary: null } });\n return;\n }\n // A baseBranch is only ever a managed branch or omitted (\u2192 detected base);\n // reject anything that could smuggle a git flag.\n const base = baseBranch && MANAGED_BRANCH_RE.test(baseBranch) ? baseBranch : undefined;\n const wt = new WorktreeManager({ projectRoot: this.management.projectRoot });\n const summary = await wt.diffSummary(resolve(dir), base);\n this.broadcast({ type: 'worktree.diff_result', payload: { dir, summary } });\n }\n\n // \u2500\u2500 internals \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private subscribe(): void {\n const on = this.events.on.bind(this.events) as never as (\n ev: string,\n fn: (p: unknown) => void,\n ) => () => void;\n\n this.offs.push(\n on('worktree.allocated', (p) => {\n const e = p as {\n handleId: string;\n ownerId: string;\n ownerLabel: string;\n dir?: string;\n branch: string;\n baseBranch: string;\n };\n this.baseBranch = e.baseBranch || this.baseBranch;\n this.upsert(e.handleId, {\n handleId: e.handleId,\n ownerId: e.ownerId,\n ownerLabel: e.ownerLabel,\n dir: e.dir,\n branch: e.branch,\n baseBranch: e.baseBranch,\n status: 'active',\n insertions: 0,\n deletions: 0,\n files: 0,\n allocatedAt: Date.now(),\n lastEventAt: Date.now(),\n recentActivity: [],\n });\n this.activity(e.handleId, 'allocated', `branch ${e.branch}`);\n this.ensureBroadcast();\n }),\n on('worktree.committed', (p) => {\n const e = p as {\n handleId: string;\n insertions: number;\n deletions: number;\n files: number;\n committed: boolean;\n };\n this.patch(e.handleId, {\n status: 'committing',\n insertions: e.insertions,\n deletions: e.deletions,\n files: e.files,\n });\n if (e.committed)\n this.activity(e.handleId, 'committed', `+${e.insertions}/-${e.deletions} (${e.files}f)`);\n this.broadcastState();\n }),\n on('worktree.merged', (p) => {\n const e = p as { handleId: string; baseBranch: string };\n this.patch(e.handleId, { status: 'merged' });\n this.activity(e.handleId, 'merged', `\u2192 ${e.baseBranch}`);\n this.broadcastState();\n }),\n on('worktree.conflict', (p) => {\n const e = p as { handleId: string; conflictFiles: string[] };\n this.patch(e.handleId, { status: 'needs-review', conflictFiles: e.conflictFiles });\n this.activity(e.handleId, 'conflict', e.conflictFiles.join(', '));\n this.broadcastState();\n }),\n on('worktree.failed', (p) => {\n const e = p as { handleId: string; error: string };\n this.patch(e.handleId, { status: 'failed' });\n this.activity(e.handleId, 'failed', e.error);\n this.broadcastState();\n }),\n on('worktree.released', (p) => {\n const e = p as { handleId: string; kept: boolean };\n if (!e.kept) this.handles.delete(e.handleId);\n this.activity(e.handleId, 'released', e.kept ? 'kept for review' : 'removed');\n if (this.handles.size === 0) this.stopBroadcast();\n else this.broadcastState();\n }),\n );\n }\n\n private upsert(id: string, view: WorktreeHandleView): void {\n this.handles.set(id, view);\n }\n\n private patch(id: string, patch: Partial<WorktreeHandleView>): void {\n const cur = this.handles.get(id);\n if (!cur) return;\n this.handles.set(id, { ...cur, ...patch, lastEventAt: Date.now() });\n }\n\n private activity(id: string, kind: string, text: string): void {\n const cur = this.handles.get(id);\n if (cur) {\n const recentActivity = [...cur.recentActivity, { kind, text, at: Date.now() }].slice(\n -MAX_ACTIVITY,\n );\n this.handles.set(id, { ...cur, recentActivity });\n }\n this.broadcast({\n type: 'worktree.event',\n payload: { kind, handleId: id, text, at: Date.now() },\n });\n }\n\n private stateMessage(): WSServerMessage {\n return {\n type: 'worktree.state',\n payload: { worktrees: [...this.handles.values()], baseBranch: this.baseBranch },\n };\n }\n\n private broadcastState(): void {\n this.broadcast(this.stateMessage());\n }\n\n private ensureBroadcast(): void {\n this.broadcast(this.stateMessage());\n if (this.broadcastInterval) return;\n this.broadcastInterval = setInterval(() => this.broadcast(this.stateMessage()), 2000);\n }\n\n private stopBroadcast(): void {\n this.broadcast(this.stateMessage());\n if (this.broadcastInterval) {\n clearInterval(this.broadcastInterval);\n this.broadcastInterval = null;\n }\n }\n\n private broadcast(msg: WSServerMessage): void {\n const data = JSON.stringify(msg);\n for (const ws of this.clients) {\n try {\n sendSerialized(ws, data);\n } catch (err) {\n this.logger.debug?.(`worktree broadcast failed: ${toErrorMessage(err)}`);\n }\n }\n }\n\n private send(ws: WebSocket, msg: WSServerMessage): void {\n try {\n sendSerialized(ws, JSON.stringify(msg));\n } catch {\n /* client gone */\n }\n }\n}\n", "import type { Context } from '@wrongstack/core/agent';\nimport type { Message, SessionEvent, TokenCounter, Usage } from '@wrongstack/core/types';\nimport type { WebSocket } from 'ws';\nimport {\n buildReplayPayload,\n decodeProtocolFrame,\n protocolAdvertisement,\n} from '../protocol/index.js';\nimport type { CollaborationWebSocketHandler } from './collaboration-ws-handler.js';\nimport { createConnectionLifecycle } from './connection-lifecycle.js';\nimport type { GoalWebSocketHandler } from './goal-ws-handler.js';\nimport type { PendingConfirm } from './pending-confirms.js';\nimport type { SddBoardWebSocketHandler } from './sdd-board-ws-handler.js';\nimport type { SddWizardWebSocketHandler } from './sdd-wizard-ws-handler.js';\nimport type { SpecsWebSocketHandler } from './specs-ws-handler.js';\nimport type { TerminalWebSocketHandler } from './terminal-ws-handler.js';\nimport type { ConnectedClient, WSClientMessage } from './types.js';\nimport type { WorktreeWebSocketHandler } from './worktree-ws-handler.js';\nimport { send } from './ws-utils.js';\n\nexport interface ConnectionHandlerOptions {\n getSessionId(): string;\n sessionStartPayload(): Promise<Record<string, unknown>>;\n tokenCounter: TokenCounter;\n context: Context;\n loadReplay?:\n | (() => Promise<{\n messages: Message[];\n events?: readonly SessionEvent[] | undefined;\n usage?: Usage | undefined;\n } | null>)\n | undefined;\n clients: Map<WebSocket, ConnectedClient>;\n pendingConfirms: Map<string, PendingConfirm>;\n goalHandler: GoalWebSocketHandler;\n specsHandler: SpecsWebSocketHandler;\n sddBoardHandler: SddBoardWebSocketHandler;\n sddWizardHandler: SddWizardWebSocketHandler;\n worktreeHandler: WorktreeWebSocketHandler;\n collabHandler: CollaborationWebSocketHandler;\n terminalHandler: TerminalWebSocketHandler;\n handleMessage: (ws: WebSocket, client: ConnectedClient, msg: WSClientMessage) => Promise<void>;\n /**\n * Forwarded to the connection lifecycle as `onSecurityRejection`. When set,\n * the callback fires on every `unsafe_key` or `too_deep` decoder rejection\n * with connection-context details. See the lifecycle option's doc comment\n * for design constraints (fire-and-forget, no await).\n */\n onSecurityRejection?: (event: import('./connection-lifecycle.js').SecurityRejectionEvent) => void;\n}\n\nconst RATE_LIMIT_MESSAGES = Number.parseInt(process.env['WEBUI_RATE_LIMIT'] ?? '0', 10);\n\n/**\n * When true, rejection/parse-failure logs include per-connection context\n * (connectionId, sessionId, agentId, projectRoot, remoteAddress, the rejected\n * message type, and the decoder issue code) so operators can identify the\n * sender of unknown client message types \u2014 for example the recent\n * `mailbox.status` rejections whose sender is otherwise indistinguishable.\n *\n * Off by default to preserve the original log shape for downstream consumers.\n * Enable with `WEBUI_VERBOSE_WS=1` (or `=true`).\n */\nconst VERBOSE_WS_LOGGING =\n process.env['WEBUI_VERBOSE_WS'] === '1' || process.env['WEBUI_VERBOSE_WS'] === 'true';\n\nfunction readRemoteAddress(ws: WebSocket): string | undefined {\n const socket = (ws as WebSocket & { _socket?: { remoteAddress?: unknown } })._socket;\n return typeof socket?.remoteAddress === 'string' ? socket.remoteAddress : undefined;\n}\n\nexport function createConnectionHandler(\n options: ConnectionHandlerOptions,\n): (ws: WebSocket) => void {\n const handlers = [\n options.goalHandler,\n options.specsHandler,\n options.sddBoardHandler,\n options.sddWizardHandler,\n options.worktreeHandler,\n options.collabHandler,\n options.terminalHandler,\n ];\n // Server-wide identity for verbose rejection logs. `connectionId`,\n // `sessionId`, and `remoteAddress` are captured per connection on the client;\n // `agentId` and `projectRoot` come from the server-wide Context.\n const clientContext = {\n agentId: options.context.agentId,\n projectRoot: options.context.projectRoot,\n };\n const lifecycle = createConnectionLifecycle<ConnectedClient, undefined, WSClientMessage>({\n clients: options.clients,\n pendingConfirms: options.pendingConfirms,\n verboseWsLogging: VERBOSE_WS_LOGGING,\n clientContext,\n ...(options.onSecurityRejection ? { onSecurityRejection: options.onSecurityRejection } : {}),\n createClient: (ws, connectionId) => {\n const remoteAddress = VERBOSE_WS_LOGGING ? readRemoteAddress(ws) : undefined;\n return {\n ws,\n sessionId: options.getSessionId(),\n connectedAt: Date.now(),\n connId: connectionId,\n ...(remoteAddress !== undefined ? { remoteAddress } : {}),\n };\n },\n registerClient: (ws) => {\n for (const handler of handlers) handler.addClient(ws);\n },\n decode: (raw) => decodeProtocolFrame(raw, 'client') as never,\n dispatch: options.handleMessage,\n send,\n sessionPayload: (payload) => {\n const provided = payload['sessionId'];\n const sessionId =\n typeof provided === 'string' && provided.length > 0 ? provided : options.getSessionId();\n return { ...payload, sessionId };\n },\n rateLimitMax: RATE_LIMIT_MESSAGES,\n rateLimitMessage: 'Too many messages. Please wait before sending more.',\n buildInitialPayload: async () => {\n const payload = { ...(await options.sessionStartPayload()) };\n const advertisement = protocolAdvertisement();\n const priorCapabilities = Array.isArray(payload['protocolCapabilities'])\n ? payload['protocolCapabilities'].filter((item): item is string => typeof item === 'string')\n : [];\n payload['protocolVersion'] = advertisement.protocolVersion;\n payload['protocolCapabilities'] = [\n ...new Set([...priorCapabilities, ...advertisement.protocolCapabilities]),\n ];\n if (\n typeof options.context.lastRequestTokens === 'number' &&\n options.context.lastRequestTokens > 0\n ) {\n payload['lastInputTokens'] = options.context.lastRequestTokens;\n }\n try {\n const replay = await options.loadReplay?.();\n // No durable store wired: fall back to the live conversation, which has\n // no event stream behind it \u2014 markers are simply absent in that mode.\n Object.assign(\n payload,\n buildReplayPayload({\n messages: replay?.messages ?? options.context.messages ?? [],\n events: replay?.events,\n usage: replay?.usage ?? options.tokenCounter.total(),\n }),\n );\n } catch {\n // Replay is best-effort; the client may still hydrate local state.\n }\n return payload;\n },\n });\n return (ws) => {\n void lifecycle(ws, undefined);\n };\n}\n", "/**\n * WebSocket message dispatcher for the standalone WebUI server.\n *\n * Phase 1b of the god-module split (issue: God-modules >1500 lines).\n * `startWebUI` in `./index.ts` previously inlined the entire `handleMessage`\n * function (~445 lines): the 13-route delegation prefix, the per-feature\n * handler short-circuits (worktree / collab / terminal), and the big\n * `switch (msg.type)` covering user_message, tool.confirm_result, abort,\n * tools.list, memory.*, skills.*, prompts.*, design.*, diag.get, worklist,\n * files.*, completion, stats.get, side_effects.list, process.*, webui.shutdown,\n * goal.get, autonomy.switch, and the mcp/prefs tripwire arms.\n *\n * All of that moves here. The factory returns the\n * `(ws, client, msg) => Promise<void>` dispatcher that the connection handler\n * calls after parsing + rate-limiting. Behaviour is preserved verbatim \u2014\n * message shapes, ordering, validation, tripwire throws, and the runLock\n * guard around `agent.run` are all unchanged.\n */\n\nimport path from 'node:path';\nimport type { WebSocket } from 'ws';\nimport { AgentRosterWSHandler } from './agent-roster-handlers.js';\nimport type { ClientTransportRouteHandlers } from './client-transport-routes.js';\nimport { handleCodebaseIndexServerControl } from './codebase-index-server-control.js';\nimport { createToolLspCompletionSource, handleCompletionRequest } from './completion-handlers.js';\nimport type { CompletionRouteHandlers } from './completion-routes.js';\nimport { handleConnectionsHealthRoute } from './connections-health-route.js';\nimport { createConversationOperations } from './conversation-operations.js';\nimport { handleGoalGet } from './goal-handlers.js';\nimport type { GoalSnapshotRouteHandlers } from './goal-snapshot-routes.js';\nimport type { WorklistContext } from './handlers/index.js';\nimport type { HostRouteHandlers } from './host-routes.js';\nimport type { KanbanHostRouteHandlers } from './kanban-host-routes.js';\nimport { handleKanbanRoute } from './kanban-routes.js';\nimport type { PendingConfirm } from './pending-confirms.js';\nimport { authorizeWebUIAction } from './privileged-actions.js';\nimport { handleProcessKill, handleProcessKillAll, handleProcessList } from './process-handlers.js';\nimport type { ProcessRouteHandlers } from './process-routes.js';\nimport { createRouteFamilyDispatcher } from './route-family-dispatcher.js';\nimport type { AllRoutes, WebuiDeps, WebuiMutableState } from './routes.js';\nimport type { ConnectedClient, WSClientMessage } from './types.js';\nimport { createWorklistRouteHandlers } from './worklist-routes.js';\nimport { broadcast, send, sendResult } from './ws-utils.js';\n\n/**\n * Shared run-lock control. `user_message` acquires/releases it around\n * `agent.run`. Both the dispatcher and the mutable-state wiring read through this object\n * so a second user_message while running is rejected and a project swap can\n * tear down the in-flight run.\n */\ninterface RunLockControl {\n get(): AbortController | null;\n set(ctrl: AbortController | null): void;\n}\ninterface MessageDispatcherOptions {\n state: WebuiMutableState;\n deps: WebuiDeps;\n routes: AllRoutes;\n /** Prompt-library context ({ promptLoader, promptUsage }). */\n promptsCtx: { promptLoader: unknown; promptUsage: unknown };\n /** Codebase-indexing side-effect hook (files.write notifies the indexer). */\n codebaseIndexing: { onFileWritten: (filePath: string) => void };\n /** Shared run-lock guarding concurrent agent.run() calls. */\n runLock: RunLockControl;\n /** Pending permission confirmations \u2014 tool.confirm_result resolves one. */\n pendingConfirms: Map<string, PendingConfirm>;\n}\n\n/**\n * Build the inbound message dispatcher. Mirrors the `handleMessage` closure\n * that lived inline in `startWebUI`. Reads live config/session/projectRoot\n * through `state` and services through `deps` \u2014 same reference semantics,\n * no behaviour change.\n */\nexport function createMessageDispatcher(\n opts: MessageDispatcherOptions,\n): (ws: WebSocket, _client: ConnectedClient, msg: WSClientMessage) => Promise<void> {\n const { state, deps, routes, promptsCtx, codebaseIndexing, runLock, pendingConfirms } = opts;\n\n function makeWorklistContext(): WorklistContext {\n return {\n context: {\n todos: deps.context.todos,\n meta: deps.context.meta as Record<string, unknown>,\n session: deps.context.session ? { id: deps.context.session.id } : null,\n },\n send: (w, m) => send(w, m),\n broadcast: (m) => broadcast(state.getClients(), m),\n replaceTodos: (todos) => deps.context.state.replaceTodos(todos),\n };\n }\n\n function makeSkillsContext() {\n const projectRoot = state.getProjectRoot();\n return {\n skillLoader: deps.skillLoader,\n skillInstaller: deps.skillInstaller,\n projectRoot,\n projectSkillsDir: path.join(projectRoot, '.wrongstack', 'skills'),\n globalSkillsDir: deps.wpaths.globalSkills,\n };\n }\n\n function messageSessionId(msg: WSClientMessage): string | undefined {\n const payload = msg.payload;\n return payload &&\n typeof payload === 'object' &&\n typeof (payload as { sessionId?: unknown }).sessionId === 'string'\n ? (payload as { sessionId: string }).sessionId\n : undefined;\n }\n\n function sessionPayload(payload: Record<string, unknown>): Record<string, unknown> {\n const current = state.getSession().id;\n const provided = payload['sessionId'];\n const sessionId = typeof provided === 'string' && provided.length > 0 ? provided : current;\n return { ...payload, sessionId };\n }\n\n function ensureCurrentSession(ws: WebSocket, msg: WSClientMessage, phase: string): boolean {\n const requested = messageSessionId(msg);\n const current = state.getSession().id;\n if (!requested || requested === current) return true;\n send(ws, {\n type: 'error',\n payload: sessionPayload({\n phase,\n message: `Request targeted session ${requested}, but this WebUI runtime is currently on ${current}.`,\n requestedSessionId: requested,\n }),\n });\n return false;\n }\n\n const worklistRoutes = createWorklistRouteHandlers({\n getContext: makeWorklistContext,\n allowMessage: (ws, msg) => ensureCurrentSession(ws, msg, msg.type),\n });\n const processRoutes: ProcessRouteHandlers = {\n list: (ws) => handleProcessList(ws),\n kill: (ws, msg) => handleProcessKill(ws, msg.payload, deps.trustBoundary, deps.logger),\n killAll: (ws) => handleProcessKillAll(ws, deps.trustBoundary, deps.logger),\n };\n const hostRoutes: HostRouteHandlers = {\n shutdown: async (ws) => {\n const authorization = await authorizeWebUIAction(\n deps.trustBoundary,\n {\n // 'elevated' (not 'critical') so the default compatibility trust\n // boundary allows WS-authenticated clients to shut down their own\n // agent process. 'critical' is unconditionally denied for\n // remote-client actors, which would silently break the Exit button.\n capability: 'host.shutdown',\n subject: { kind: 'process', id: String(process.pid) },\n risk: 'elevated',\n metadata: { transport: 'websocket' },\n },\n deps.logger,\n );\n if (authorization.allowed) {\n console.log('[WebUI] Shutdown requested from client');\n process.kill(process.pid, 'SIGINT');\n } else {\n sendResult(ws, false, `Shutdown denied: ${authorization.reason}`);\n }\n },\n };\n const clientTransportRoutes: ClientTransportRouteHandlers = {\n collaboration: (ws, msg) => {\n deps.collabHandler.handleMessage(ws, msg as { type: string; payload?: unknown | undefined });\n },\n terminal: (ws, msg) => {\n // Detached from the connection-lifecycle try/catch, so a rejection here\n // (e.g. authorizeWebUIAction denies) would otherwise be an unhandled\n // rejection and the client would never see terminal.exit \u2014 log it.\n void deps.terminalHandler.handleMessage(ws, msg).catch((err) => {\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'webui.terminal_handler_failed',\n message: err instanceof Error ? err.message : String(err),\n }),\n );\n });\n },\n };\n const conversationRoutes = createConversationOperations({\n getAgent: () => deps.agent,\n getSessionId: () => state.getSession().id,\n runControl: {\n begin: () => {\n if (runLock.get()) return undefined;\n const controller = new AbortController();\n runLock.set(controller);\n return controller;\n },\n end: (_ws, controller) => {\n if (runLock.get() === controller) runLock.set(null);\n },\n abort: () => runLock.get()?.abort(),\n },\n pendingConfirms,\n send,\n notifyAbort: (_ws, message) => broadcast(state.getClients(), message),\n getMaxIterations: () =>\n typeof deps.context.meta['maxIterations'] === 'number'\n ? deps.context.meta['maxIterations']\n : undefined,\n });\n const completionRoutes: CompletionRouteHandlers = {\n request: (ws, msg) =>\n handleCompletionRequest(ws, msg, {\n projectRoot: state.getProjectRoot(),\n provider: deps.context.provider,\n model: deps.context.model,\n indexDir:\n typeof deps.context.meta['codebaseIndexDir'] === 'string'\n ? deps.context.meta['codebaseIndexDir']\n : undefined,\n lspCompletion: createToolLspCompletionSource(\n deps.toolRegistry.get('lsp_completion'),\n deps.context,\n ),\n }),\n };\n const goalSnapshotRoutes: GoalSnapshotRouteHandlers = {\n getSnapshot: () =>\n handleGoalGet(state.getProjectRoot(), (message) => broadcast(state.getClients(), message)),\n };\n const kanbanContext = () => ({\n projectRoot: state.getProjectRoot(),\n context: deps.context,\n broadcast: (message: object) => broadcast(state.getClients(), message),\n });\n const kanbanHostRoutes: KanbanHostRouteHandlers = {\n meta: async (ws) => {\n const skills = deps.skillLoader\n ? (await deps.skillLoader.list()).map((skill) => ({\n name: skill.name,\n description: skill.description,\n source: skill.source,\n }))\n : [];\n send(ws, {\n type: 'kanban.meta',\n payload: {\n success: true,\n data: {\n tools: deps.agent.ctx.tools.map((tool) => ({\n name: tool.name,\n description: tool.description ?? '',\n })),\n skills,\n fallbackProfiles: state.getConfig().fallbackProfiles ?? {},\n sessionProvider: deps.context.provider,\n sessionModel: deps.context.model,\n },\n },\n });\n },\n supervisorStatus: async (ws, msg) => {\n await handleKanbanRoute(ws, msg, kanbanContext());\n },\n supervisorAudit: async (ws, msg) => {\n await handleKanbanRoute(ws, msg, kanbanContext());\n },\n runStart: (ws) => {\n send(ws, {\n type: 'kanban.run.start',\n payload: {\n success: false,\n error: 'Kanban run launch is unavailable in this standalone runtime.',\n },\n });\n },\n };\n\n const dispatch = createRouteFamilyDispatcher({\n routes: {\n shellGit: routes.shellGitRoutes,\n mailbox: routes.mailboxRoutes,\n mcp: routes.mcpRoutes,\n provider: routes.providerRoutes,\n session: routes.sessionRoutes,\n project: routes.projectRoutes,\n mode: routes.modeRoutes,\n prefs: routes.prefsRoutes,\n brain: routes.brainRoutes,\n worklist: worklistRoutes,\n process: processRoutes,\n host: hostRoutes,\n clientTransport: clientTransportRoutes,\n conversation: conversationRoutes,\n completion: completionRoutes,\n autonomy: routes.autonomyRoutes,\n goalSnapshot: goalSnapshotRoutes,\n goal: routes.goalRoutes,\n specs: routes.specsRoutes,\n sddBoard: routes.sddBoardRoutes,\n sddWizard: routes.sddWizardRoutes,\n worktree: deps.worktreeHandler,\n kanbanHost: kanbanHostRoutes,\n agentRoster: {\n rosterHandler: new AgentRosterWSHandler({\n projectRoot: state.getProjectRoot,\n getLlm: () => {\n const ctx = deps.agent.ctx;\n return ctx.provider && ctx.model\n ? { provider: ctx.provider, model: ctx.model }\n : undefined;\n },\n broadcast: (m) => broadcast(state.getClients(), m),\n }),\n },\n },\n memory: { getMemoryStore: () => deps.memoryStore, send, sendResult },\n content: {\n getProjectRoot: state.getProjectRoot,\n getSkillsContext: makeSkillsContext,\n getPromptsContext: () => promptsCtx as never,\n getDesignContext: () => ({\n projectRoot: state.getProjectRoot(),\n agentMeta: deps.context,\n }),\n onFileWritten: codebaseIndexing.onFileWritten,\n },\n chronicle: { getProjectRoot: state.getProjectRoot, send },\n introspection: {\n agent: deps.agent,\n modelsRegistry: deps.modelsRegistry,\n configStore: deps.configStore,\n getConfig: state.getConfig,\n getProjectRoot: state.getProjectRoot,\n getSessionId: () => state.getSession().id,\n getSessionStartedAt: state.getSessionStartedAt,\n getModeId: state.getModeId,\n send,\n allowSessionMessage: (socket, message) => ensureCurrentSession(socket, message, message.type),\n },\n getKanbanContext: kanbanContext,\n onUnknown: (ws, msg) => {\n send(ws, {\n type: 'error',\n payload: { phase: 'handleMessage', message: `Unknown message type: ${msg.type}` },\n });\n },\n });\n\n return async (ws, _client, msg) => {\n if (\n await handleConnectionsHealthRoute(\n {\n getProjectRoot: state.getProjectRoot,\n getIndexDir: () =>\n typeof deps.context.meta['codebaseIndexDir'] === 'string'\n ? deps.context.meta['codebaseIndexDir']\n : undefined,\n send,\n backend: 'standalone',\n },\n ws,\n msg,\n )\n )\n return;\n if (\n await handleCodebaseIndexServerControl(ws, msg, {\n trustBoundary: deps.trustBoundary,\n logger: deps.logger,\n getProjectRoot: state.getProjectRoot,\n getIndexDir: () =>\n typeof deps.context.meta['codebaseIndexDir'] === 'string'\n ? deps.context.meta['codebaseIndexDir']\n : undefined,\n send,\n backend: 'standalone',\n })\n )\n return;\n await dispatch(ws, msg);\n };\n}\n", "/**\n * Pre-context backend service construction for the standalone WebUI server.\n *\n * Phase 1f of the god-module split. `startWebUI` previously inlined ~370\n * lines of construction that runs BEFORE `context` exists: modelsRegistry,\n * container, providerRegistry, toolRegistry (+ memory/mailbox tools),\n * MCPRegistry, sessionStore, session, sessionReader, annotationsStore,\n * cross-surface discovery (session registry + fleet notifier + HQ\n * telemetry), tokenCounter, modeStore, customModeStore, skillInstaller,\n * promptLoader, systemPromptBuilder, systemPrompt, provider resolution,\n * and context creation + meta seeding.\n *\n * All of that moves into `createPreContextServices()`. The block is deeply\n * interleaved with the `opts.services?` injection contract (5 injection\n * points) and mutable `let` bindings the route layer swaps at runtime\n * (session, sessionStore, sessionStartedAt, modeId). The factory returns\n * all of these; `startWebUI` keeps the mutable bindings and wraps them\n * into the `state` object exactly as before.\n *\n * No behaviour change.\n */\n\nimport { createRequire } from 'node:module';\nimport * as path from 'node:path';\nimport { Context, DefaultSystemPromptBuilder } from '@wrongstack/core/agent';\nimport {\n getSharedProjectMailbox,\n makeFleetStatusTool,\n makeMailboxTool,\n makeMailInboxTool,\n makeMailSendTool,\n} from '@wrongstack/core/coordination';\nimport {\n DefaultPromptLoader,\n DefaultSkillLoader,\n} from '@wrongstack/core/execution';\nimport {\n type Container,\n EventBus,\n TOKENS,\n} from '@wrongstack/core/kernel';\nimport { DefaultTokenCounter } from '@wrongstack/core/infrastructure';\nimport { DefaultModelsRegistry, DefaultModeStore } from '@wrongstack/core/models';\nimport { ProviderRegistry, ToolRegistry } from '@wrongstack/core/registry';\nimport { SkillInstaller } from '@wrongstack/core/skills';\nimport {\n type AgentStatusTracker,\n AnnotationsStore,\n DefaultSessionReader,\n DefaultSessionStore,\n getSessionRegistry,\n PromptUsageStore,\n} from '@wrongstack/core/storage';\nimport {\n DEFAULT_SESSION_PRUNE_DAYS,\n normalizeTokenSavingTier,\n resolveContextWindowPolicy,\n type Config,\n type ConfigStore,\n type Logger,\n type MemoryPort,\n type ModelsRegistry,\n type Provider,\n type SecretVault,\n type SessionStore,\n} from '@wrongstack/core/types';\nimport {\n configureChildEnvGitIdentity,\n sessionScopedPath,\n toErrorMessage,\n type WstackPaths,\n} from '@wrongstack/core/utils';\nimport {\n createVaultBackedMcpAuthorizationProviderFactory,\n MCPAuthorizationManager,\n MCPRegistry,\n MCPVaultTokenStore,\n} from '@wrongstack/mcp';\nimport {\n buildProviderFactoriesFromRegistry,\n installCatalogModelOutputLimits,\n} from '@wrongstack/providers';\nimport { createDefaultContainer } from '@wrongstack/runtime';\nimport { registerCanonicalHostTools } from '@wrongstack/runtime/tool-registration';\nimport { configureDangerBypass, configureExecPolicy } from '@wrongstack/tools';\nimport { attachSessionKanbanMirror, hydrateSessionKanban } from '@wrongstack/tools/session-kanban';\nimport { seedContextMeta } from './context-meta.js';\nimport type { CustomModeStore } from './custom-context-modes.js';\nimport { createCustomModeStore } from './custom-context-modes.js';\nimport { discoverAndMergeWebuiProviders } from './model-auto-discovery.js';\nimport { resolveProviderModelMetadata } from './model-catalog.js';\nimport { resolveSetupProvider } from './setup-screen.js';\nimport {\n createStandaloneSessionIdentityLifecycle,\n type StandaloneSessionIdentityLifecycle,\n} from './standalone-session-identity.js';\nimport type { WebUIOptions } from './types.js';\n\nconst GITHUB_PROVIDERS_OVERLAY_URL =\n 'https://raw.githubusercontent.com/WrongStack/WrongStack/main/packages/cli/data/providers.json';\n\ninterface PreContextServicesInput {\n config: Config;\n wpaths: WstackPaths;\n logger: Logger;\n opts: WebUIOptions;\n vault: SecretVault;\n globalConfigPath: string;\n projectRoot: string;\n workingDir: string;\n needsProvider: boolean;\n /** Callback to register/refresh the project in the manifest. */\n touchProject: (root: string, workDir?: string) => Promise<void>;\n}\n\ninterface PreContextServices {\n modelsRegistry: ModelsRegistry;\n container: Container;\n configStore: ConfigStore;\n providerRegistry: ProviderRegistry;\n toolRegistry: ToolRegistry;\n memoryStore: MemoryPort;\n events: EventBus;\n mcpRegistry: import('@wrongstack/mcp').MCPRegistry;\n sessionStore: SessionStore;\n sessionReader: DefaultSessionReader;\n annotationsStore: AnnotationsStore;\n session: Awaited<ReturnType<DefaultSessionStore['create']>>;\n sessionStartedAt: number;\n statusTracker: AgentStatusTracker | undefined;\n sessionIdentity: StandaloneSessionIdentityLifecycle;\n tokenCounter: DefaultTokenCounter;\n modeStore: DefaultModeStore;\n modeId: string;\n customModeStore: CustomModeStore;\n skillLoader: DefaultSkillLoader | undefined;\n skillInstaller: SkillInstaller | undefined;\n promptsCtx: { promptLoader: DefaultPromptLoader | undefined; promptUsage: PromptUsageStore };\n modelCapabilitiesRef: { current: unknown };\n provider: Provider;\n context: Context;\n needsSetup: boolean;\n}\n\n/**\n * Build all pre-context services: registries, stores, session, system\n * prompt, provider, and context. Returns everything `startWebUI` needs\n * for `createAgentServices` (Phase 1c) + route/dispatcher wiring.\n */\nexport async function createPreContextServices(\n input: PreContextServicesInput,\n): Promise<PreContextServices> {\n const { config, wpaths, logger, opts, vault, projectRoot, workingDir, needsProvider } = input;\n\n // \u2500\u2500 ModelsRegistry \u2500\u2500\n const modelsRegistry =\n opts.services?.modelsRegistry ??\n new DefaultModelsRegistry({\n cacheFile: wpaths.modelsCache,\n ttlSeconds: 0,\n overlayUrl: GITHUB_PROVIDERS_OVERLAY_URL,\n overlayCacheFile: wpaths.modelsOverlayCache,\n });\n\n if (!opts.services?.modelsRegistry) {\n try {\n await modelsRegistry.refresh();\n logger.info('models.dev catalog refreshed');\n } catch (err) {\n logger.warn(`models.dev refresh failed (${toErrorMessage(err)}); using cached catalog`);\n }\n }\n\n // Same per-request output-ceiling index the CLI installs. Without it every\n // wire body falls back to the adapters' 8192 literal whenever the provider\n // instance wasn't built for the model being requested.\n try {\n await installCatalogModelOutputLimits({\n registry: modelsRegistry,\n getConfig: () => config,\n log: (message) => logger.debug(message),\n });\n } catch (err) {\n logger.debug(`model output-limit index skipped: ${toErrorMessage(err)}`);\n }\n\n try {\n await discoverAndMergeWebuiProviders({\n config,\n registry: modelsRegistry,\n cacheDir: path.dirname(wpaths.modelsCache),\n logger,\n });\n } catch (err) {\n logger.debug(`provider auto-discovery skipped: ${toErrorMessage(err)}`);\n }\n\n const events = opts.services?.events ?? new EventBus();\n events.setLogger(logger);\n\n // \u2500\u2500 Container \u2500\u2500\n const container = createDefaultContainer({ config, wpaths, logger, modelsRegistry, events });\n const configStore = opts.services?.configStore ?? container.resolve(TOKENS.ConfigStore);\n\n // \u2500\u2500 Provider registry \u2500\u2500\n const providerRegistry = new ProviderRegistry();\n try {\n const factories = await buildProviderFactoriesFromRegistry({\n registry: modelsRegistry,\n log: logger,\n });\n for (const f of factories) providerRegistry.register(f);\n console.log('[WebUI] Provider registry loaded:', providerRegistry.list().length, 'providers');\n } catch (err) {\n console.warn(\n JSON.stringify({\n level: 'warn',\n event: 'webui.provider_registry_load_failed',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }),\n );\n }\n\n // \u2500\u2500 Tool registry (+ memory + mailbox tools) \u2500\u2500\n const toolRegistry = opts.services?.toolRegistry ?? new ToolRegistry();\n const memoryStore = container.resolve(TOKENS.MemoryStore);\n await memoryStore.initialize();\n if (!opts.services?.toolRegistry) {\n registerCanonicalHostTools({\n registry: toolRegistry,\n tier: normalizeTokenSavingTier(config.features.tokenSavingMode),\n memory: { enabled: config.features.memory, store: memoryStore },\n coordinationTools: [\n makeMailboxTool({ projectDir: wpaths.projectDir, events }),\n makeMailSendTool({ projectDir: wpaths.projectDir, events }),\n makeMailInboxTool({ projectDir: wpaths.projectDir, events }),\n makeFleetStatusTool({ projectDir: wpaths.projectDir, events }),\n ],\n descriptionMode: config.tools?.descriptionMode,\n resultRenderMode: config.tools?.resultRenderMode,\n disabledTools: config.tools?.disabledTools,\n });\n }\n configureExecPolicy(config.tools?.exec ?? {});\n configureDangerBypass(config.tools?.exec?.danger ?? {});\n // Commit identity for every git-touching child process. Trusted-config-only:\n // the loader strips `git` from repo-committed in-project configs.\n configureChildEnvGitIdentity(config.git?.identity ?? null);\n console.log('[WebUI] Tool registry loaded:', toolRegistry.list().length, 'tools');\n\n // \u2500\u2500 MCP registry \u2500\u2500\n const mcpTokenStore = new MCPVaultTokenStore(\n path.join(wpaths.projectDir, 'mcp-auth.json'),\n vault,\n );\n const mcpAuthorizationManager = new MCPAuthorizationManager({ store: mcpTokenStore });\n const mcpRegistry = new MCPRegistry({\n toolRegistry,\n events,\n log: logger,\n cacheDir: wpaths.cacheDir,\n authorizationProviderFactory: createVaultBackedMcpAuthorizationProviderFactory({\n store: mcpTokenStore,\n }),\n authorizationManager: mcpAuthorizationManager,\n });\n if (config.features.mcp && config.mcpServers) {\n for (const [name, cfg] of Object.entries(config.mcpServers)) {\n void mcpRegistry.start({ ...cfg, name }).catch((err) => {\n logger.warn(`MCP server \"${name}\" failed to start at boot`, err);\n });\n }\n }\n\n // \u2500\u2500 Session store + session \u2500\u2500\n const sessionStore =\n opts.services?.session ??\n new DefaultSessionStore({\n dir: wpaths.projectSessions,\n projectRoot: wpaths.projectRoot,\n // Cross-process guard for delete(): refuses to remove a session that a\n // live terminal/TUI/WebUI in this project is using.\n isSessionInUse: async (sessionId) => {\n try {\n const registry = getSessionRegistry(wpaths.globalRoot);\n const live = await registry.listByProject(wpaths.projectSlug);\n const hit = live.find((e) => e.sessionId === sessionId);\n if (hit) {\n return `active in ${hit.projectName} (PID ${hit.pid})`;\n }\n } catch {\n // registry unavailable \u2014 keep the store usable\n }\n return null;\n },\n });\n if (!opts.services?.session) {\n sessionStore\n .prune(DEFAULT_SESSION_PRUNE_DAYS)\n .then((count) => {\n if (count > 0) logger.info(`Pruned ${count} old session${count === 1 ? '' : 's'}.`);\n })\n .catch(() => undefined);\n }\n const sessionReader = new DefaultSessionReader({ store: sessionStore });\n const annotationsStore = new AnnotationsStore({ dir: wpaths.projectSessions, events });\n const session = await sessionStore.create({\n id: '',\n title: '',\n model: config.model,\n provider: config.provider,\n });\n const sessionStartedAt = Date.now();\n console.log('[WebUI] Session created:', session.id);\n\n // \u2500\u2500 Cross-surface discovery \u2500\u2500\n try {\n await input.touchProject(projectRoot, workingDir);\n } catch {\n /* best-effort */\n }\n const sessionIdentity = await createStandaloneSessionIdentityLifecycle({\n config,\n events,\n logger,\n paths: {\n globalRoot: wpaths.globalRoot,\n projectRoot,\n projectSlug: wpaths.projectSlug,\n },\n workingDir,\n initialSessionId: session.id,\n });\n const statusTracker = sessionIdentity.statusTracker;\n\n // \u2500\u2500 Token counter \u2500\u2500\n let context: Context;\n const tokenCounter = new DefaultTokenCounter({\n registry: modelsRegistry,\n providerId: config.provider,\n events,\n sessionId: () => context?.session?.id ?? session.id,\n });\n\n // \u2500\u2500 Mode store \u2500\u2500\n const modeStore = new DefaultModeStore({ directory: wpaths.configDir });\n const activeMode = await modeStore.getActiveMode();\n const modeId = activeMode?.id ?? 'default';\n const modePrompt = activeMode?.prompt ?? '';\n\n // \u2500\u2500 Custom context modes \u2500\u2500\n const customModeStore = createCustomModeStore(wpaths.configDir);\n await customModeStore.load();\n console.log(\n '[WebUI] Custom context modes loaded:',\n customModeStore.list().filter((m) => (m as { custom?: boolean }).custom).length,\n 'custom',\n );\n\n // \u2500\u2500 Model capabilities ref \u2500\u2500\n const resolvedModel = await resolveProviderModelMetadata(\n modelsRegistry,\n config.provider,\n config.model,\n config.providers?.[config.provider],\n );\n const modelCapabilities = resolvedModel?.capabilities\n ? {\n maxContextTokens: resolvedModel.capabilities.maxContext,\n supportsTools: resolvedModel.capabilities.tools,\n supportsVision: resolvedModel.capabilities.vision,\n supportsReasoning: resolvedModel.capabilities.reasoning,\n }\n : undefined;\n const modelCapabilitiesRef: { current: typeof modelCapabilities } = {\n current: modelCapabilities,\n };\n\n // \u2500\u2500 Skill loader/installer \u2500\u2500\n const skillLoader = config.features.skills\n ? new DefaultSkillLoader({ paths: wpaths })\n : undefined;\n const skillInstaller = config.features.skills\n ? new SkillInstaller({\n manifestPath: path.join(wpaths.configDir, 'installed-skills.json'),\n projectSkillsDir: wpaths.inProjectSkills,\n globalSkillsDir: wpaths.globalSkills,\n projectHash: wpaths.projectHash,\n skillLoader,\n })\n : undefined;\n\n // \u2500\u2500 Prompt library \u2500\u2500\n const promptsEnabled = config.features.prompts !== false;\n const bundledPromptsDir = promptsEnabled\n ? (() => {\n try {\n const req = createRequire(import.meta.url);\n return path.join(\n path.dirname(req.resolve('@wrongstack/core/package.json')),\n 'data',\n 'prompts',\n );\n } catch {\n return undefined;\n }\n })()\n : undefined;\n const promptLoader = promptsEnabled\n ? new DefaultPromptLoader({ paths: wpaths, bundledDir: bundledPromptsDir })\n : undefined;\n const promptUsage = new PromptUsageStore(wpaths.promptUsage);\n const promptsCtx = { promptLoader, promptUsage };\n\n // \u2500\u2500 System prompt builder \u2500\u2500\n const systemPromptBuilder = new DefaultSystemPromptBuilder({\n memoryStore,\n // SAGE's turn middleware is the single memory-injection channel;\n // don't also inject a static memory section here (avoids double injection).\n injectMemory: false,\n skillLoader,\n modeStore,\n modeId,\n modePrompt,\n modelCapabilities: () => modelCapabilitiesRef.current,\n instructionPaths: {\n globalDir: wpaths.globalInstructions,\n projectDir: wpaths.inProjectInstructions,\n systemVariant: config.systemPrompt?.variant,\n },\n });\n if (container.has(TOKENS.SystemPromptBuilder)) {\n container.override(TOKENS.SystemPromptBuilder, () => systemPromptBuilder, { owner: 'webui' });\n } else {\n container.bind(TOKENS.SystemPromptBuilder, () => systemPromptBuilder, { owner: 'webui' });\n }\n\n // \u2500\u2500 System prompt (with online agents from the shared mailbox) \u2500\u2500\n let onlineAgents: import('@wrongstack/core/coordination').MailboxAgentStatus[] = [];\n try {\n const systemMailbox = getSharedProjectMailbox(wpaths.projectDir);\n onlineAgents = await systemMailbox.getAgentStatuses();\n } catch {\n /* Non-fatal \u2014 mailbox errors should not block prompt building */\n }\n const systemPrompt = await systemPromptBuilder.build({\n cwd: projectRoot,\n projectRoot,\n tools: toolRegistry.list(),\n provider: config.provider,\n model: config.model,\n onlineAgents,\n });\n\n // \u2500\u2500 Provider resolution \u2500\u2500\n const resolvedProvider = resolveSetupProvider({ config, needsProvider, providerRegistry });\n const provider = resolvedProvider.provider;\n const needsSetup = resolvedProvider.needsSetup;\n\n // \u2500\u2500 Context \u2500\u2500\n context = new Context({\n systemPrompt,\n provider,\n session,\n signal: new AbortController().signal,\n tokenCounter,\n cwd: workingDir,\n projectRoot,\n model: config.model,\n });\n const initialContextPolicy = resolveContextWindowPolicy(config.context);\n context.meta['contextWindowMode'] = initialContextPolicy.id;\n context.meta['contextWindowPolicy'] = initialContextPolicy;\n context.state.setMeta(\n 'plan.path',\n sessionScopedPath(wpaths.projectSessions, session.id, '.plan.json'),\n );\n context.state.setMeta(\n 'task.path',\n sessionScopedPath(wpaths.projectSessions, session.id, '.tasks.json'),\n );\n await hydrateSessionKanban(context);\n attachSessionKanbanMirror(context);\n seedContextMeta(config, context);\n\n return {\n modelsRegistry,\n container,\n configStore,\n providerRegistry,\n toolRegistry,\n memoryStore,\n events,\n mcpRegistry,\n sessionStore,\n sessionReader,\n annotationsStore,\n session,\n sessionStartedAt,\n statusTracker,\n sessionIdentity,\n tokenCounter,\n modeStore,\n modeId,\n customModeStore,\n skillLoader,\n skillInstaller,\n promptsCtx,\n modelCapabilitiesRef,\n provider,\n context,\n needsSetup,\n };\n}\n", "import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n Config,\n Logger,\n ModelsDevPayload,\n ModelsDevProvider,\n ProviderConfig,\n} from '@wrongstack/core/types';\nimport { COMPATIBLE_PRESETS, discoverOpenAICompatibleModels } from '@wrongstack/providers';\n\ninterface DiscoverCacheEntry {\n fetchedAt: string;\n provider: ModelsDevProvider;\n}\n\ntype DiscoverCache = Record<string, DiscoverCacheEntry>;\n\ninterface OverlayRegistry {\n mergeOverlay(payload: ModelsDevPayload): void;\n}\n\nfunction isOverlayRegistry(value: unknown): value is OverlayRegistry {\n return !!value && typeof value === 'object' && typeof (value as OverlayRegistry).mergeOverlay === 'function';\n}\n\nfunction resolveKey(cfg: ProviderConfig): string | undefined {\n if (Array.isArray(cfg.apiKeys) && cfg.apiKeys.length > 0) {\n const active = cfg.activeKey\n ? cfg.apiKeys.find((key) => key.label === cfg.activeKey)\n : undefined;\n return (active ?? cfg.apiKeys[0])?.apiKey;\n }\n return cfg.apiKey && cfg.apiKey.length > 0 ? cfg.apiKey : undefined;\n}\n\nfunction eligibleProviders(\n config: Config,\n): Array<{ id: string; cfg: ProviderConfig; baseUrl: string; apiKey?: string | undefined }> {\n const out: Array<{ id: string; cfg: ProviderConfig; baseUrl: string; apiKey?: string | undefined }> = [];\n for (const [id, cfg] of Object.entries(config.providers ?? {})) {\n const preset = COMPATIBLE_PRESETS[id];\n const enabled = cfg.autoDiscoverModels ?? preset?.autoDiscover ?? false;\n if (!enabled) continue;\n const baseUrl = cfg.baseUrl ?? preset?.defaultBaseUrl;\n if (!baseUrl) continue;\n out.push({ id, cfg, baseUrl, apiKey: resolveKey(cfg) });\n }\n return out;\n}\n\nasync function readCache(file: string): Promise<DiscoverCache> {\n try {\n return JSON.parse(await fs.readFile(file, 'utf8')) as DiscoverCache;\n } catch {\n return {};\n }\n}\n\nexport async function discoverAndMergeWebuiProviders(opts: {\n config: Config;\n registry: unknown;\n cacheDir: string;\n logger?: Pick<Logger, 'debug' | 'info' | 'warn'> | undefined;\n fetchImpl?: typeof fetch | undefined;\n}): Promise<void> {\n const registry = opts.registry;\n if (!isOverlayRegistry(registry)) return;\n const targets = eligibleProviders(opts.config);\n if (targets.length === 0) return;\n\n const cacheFile = path.join(opts.cacheDir, 'discovered-models-cache.json');\n const cache = await readCache(cacheFile);\n let cacheDirty = false;\n\n await Promise.all(\n targets.map(async ({ id, cfg, baseUrl, apiKey }) => {\n const cacheKey = `${id}\\u0000${baseUrl}`;\n const provider = await discoverOpenAICompatibleModels(id, {\n baseUrl,\n apiKey,\n headers: cfg.headers,\n providerName: id,\n fetchImpl: opts.fetchImpl,\n });\n if (provider) {\n cache[cacheKey] = { fetchedAt: new Date().toISOString(), provider };\n cacheDirty = true;\n registry.mergeOverlay({ [id]: provider });\n opts.logger?.info?.(\n `auto-discovered ${Object.keys(provider.models).length} models for \"${id}\" from ${baseUrl}`,\n );\n return;\n }\n\n const cached = cache[cacheKey];\n if (cached) {\n registry.mergeOverlay({ [id]: cached.provider });\n opts.logger?.warn?.(\n `auto-discovery for \"${id}\" failed; using ${\n Object.keys(cached.provider.models).length\n } cached models from ${cached.fetchedAt}`,\n );\n } else {\n opts.logger?.warn?.(\n `auto-discovery for \"${id}\" failed and no cache available (server at ${baseUrl} unreachable?)`,\n );\n }\n }),\n );\n\n if (cacheDirty) {\n try {\n await fs.mkdir(path.dirname(cacheFile), { recursive: true });\n await fs.writeFile(cacheFile, JSON.stringify(cache), 'utf8');\n } catch {\n opts.logger?.debug?.('provider auto-discovery cache write failed');\n }\n }\n}\n", "/**\n * First-run setup + active-provider resolution.\n *\n * Phase 1b of the god-module split (issue: God-modules >1500 lines).\n * `startWebUI` in `./index.ts` previously inlined the provider-resolution\n * ladder (configured provider \u2192 first saved provider \u2192 stub provider +\n * `needsSetup` flag). This module lifts that ladder into a single pure-ish\n * function so `index.ts` reads as orchestration, not branching.\n *\n * No behaviour change: the three branches, the structured error logs, the\n * `needsSetup` flag, and the stub provider's exact shape are preserved\n * verbatim. The function throws on the same failures the inline code did.\n */\nimport type { ProviderRegistry } from '@wrongstack/core/registry';\nimport type { Provider, ProviderConfig } from '@wrongstack/core/types';\nimport { expectDefined } from '@wrongstack/core/utils';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport type { Config } from '@wrongstack/core/types';\nimport { makeProviderFromConfig } from '@wrongstack/providers';\n\nconst UNCONFIGURED_CAPABILITIES: Provider['capabilities'] = {\n tools: false,\n parallelTools: false,\n vision: false,\n streaming: false,\n promptCache: false,\n systemPrompt: false,\n jsonMode: false,\n reasoning: false,\n maxContext: 0,\n cacheControl: 'none',\n topK: false,\n frequencyPenalty: false,\n presencePenalty: false,\n seed: false,\n structuredOutput: false,\n logprobs: false,\n audio: false,\n multipleCompletions: false,\n};\n\nfunction makeUnconfiguredProvider(): Provider {\n const message = 'No provider configured. Complete setup before starting an agent run.';\n return {\n id: 'unconfigured',\n capabilities: UNCONFIGURED_CAPABILITIES,\n // biome-ignore lint/correctness/useYield: Provider.stream must be an async generator; this unconfigured stub always throws before it can yield.\n async *stream() {\n throw new Error(message);\n },\n async complete() {\n throw new Error(message);\n },\n };\n}\n\nexport interface ResolveSetupProviderOptions {\n config: Config;\n /** True when neither provider nor model is set in config. */\n needsProvider: boolean;\n providerRegistry: ProviderRegistry;\n}\n\nexport interface ResolvedSetupProvider {\n provider: Provider;\n /**\n * True when no provider could be resolved and a stub was created \u2014 the\n * frontend should show the onboarding/setup screen. False otherwise.\n * (The caller merges this into its existing `needsSetup` flag.)\n */\n needsSetup: boolean;\n}\n\nfunction logCreateFailure(event: string, err: unknown): void {\n console.error(\n JSON.stringify({\n level: 'error',\n event,\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }),\n );\n}\n\n/**\n * Resolve the active provider from config, mirroring the inline ladder that\n * used to live in `startWebUI`:\n *\n * 1. provider + model configured \u2192 build from the configured provider.\n * 2. no active provider but saved providers exist \u2192 build from the first\n * saved provider (vault already decrypted its key).\n * 3. no providers at all \u2192 boot with an inert placeholder provider and signal\n * `needsSetup` so the frontend shows the onboarding screen.\n *\n * Throws on provider-construction failure (same as the inline code).\n */\nexport function resolveSetupProvider(\n opts: ResolveSetupProviderOptions,\n): ResolvedSetupProvider {\n const { config, needsProvider, providerRegistry } = opts;\n\n // Branch 1 \u2014 configured provider.\n if (!needsProvider) {\n const providerConfig: ProviderConfig | Record<string, unknown> =\n config.providers?.[config.provider] ?? {\n type: config.provider,\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n };\n try {\n const cfgWithType = { ...providerConfig, type: config.provider };\n const provider: Provider =\n config.features.modelsRegistry && providerRegistry.has(config.provider)\n ? providerRegistry.create(cfgWithType)\n : makeProviderFromConfig(config.provider, cfgWithType);\n return { provider, needsSetup: false };\n } catch (err) {\n logCreateFailure('webui.provider_create_failed', err);\n throw err;\n }\n }\n\n // Branch 2 \u2014 fall back to the first saved provider (usable encrypted key).\n const savedProviders = config.providers ?? {};\n const firstKey = Object.keys(savedProviders)[0];\n if (firstKey) {\n const firstProvider = expectDefined(savedProviders[firstKey]);\n try {\n const provider = makeProviderFromConfig(firstKey, {\n ...firstProvider,\n type: firstKey,\n family: firstProvider.family,\n apiKey: firstProvider.apiKey,\n });\n console.log('[WebUI] Using saved provider:', firstKey);\n return { provider, needsSetup: false };\n } catch (err) {\n logCreateFailure('webui.provider_stub_create_failed', err);\n throw err;\n }\n }\n\n // Branch 3 \u2014 no providers at all. Boot with an inert placeholder so\n // the server initializes without smuggling in a real provider/model\n // identity; the frontend shows setup until the user picks one.\n console.log('[WebUI] No providers configured \u2014 showing setup screen');\n const provider = makeUnconfiguredProvider();\n return { provider, needsSetup: true };\n}\n", "import * as path from 'node:path';\nimport type { EventBus } from '@wrongstack/core/kernel';\nimport {\n AgentStatusTracker,\n FleetNotifier,\n getSessionRegistry,\n type SessionRegistry,\n} from '@wrongstack/core/storage';\nimport type { Config, Logger } from '@wrongstack/core/types';\nimport { WebSocket } from 'ws';\n\nexport interface StandaloneSessionIdentityPaths {\n globalRoot: string;\n projectRoot: string;\n projectSlug: string;\n}\n\nexport interface StandaloneSessionIdentityOptions {\n config: Config;\n events: EventBus;\n logger: Logger;\n paths: StandaloneSessionIdentityPaths;\n workingDir: string;\n initialSessionId: string;\n sessionRegistry?: SessionRegistry | undefined;\n /** Test/embedding escape hatch; production defaults to enabled. */\n enableHqTelemetry?: boolean | undefined;\n}\n\nexport interface SessionIdentityTarget {\n projectSlug: string;\n projectRoot: string;\n projectName: string;\n workingDir: string;\n}\n\nexport interface StandaloneSessionIdentityLifecycle {\n readonly statusTracker: AgentStatusTracker | undefined;\n /** Reserve a selected session before its writer is opened. */\n claim(sessionId: string, target?: SessionIdentityTarget): Promise<() => Promise<void>>;\n activate(sessionId: string, target?: SessionIdentityTarget): Promise<void>;\n stop(): Promise<void>;\n}\n\n/**\n * Own the cross-surface identity associated with the standalone WebUI's live\n * session writer. Session routes call {@link activate} after swapping writers;\n * shutdown calls {@link stop}. Transitions are serialized and every optional\n * external surface is fail-soft, while identity selection itself stays live.\n */\nexport async function createStandaloneSessionIdentityLifecycle(\n opts: StandaloneSessionIdentityOptions,\n): Promise<StandaloneSessionIdentityLifecycle> {\n const { paths, events, logger } = opts;\n const registry = opts.sessionRegistry ?? getSessionRegistry(paths.globalRoot);\n const fleetNotifier = new FleetNotifier({\n baseDir: paths.globalRoot,\n projectRoot: paths.projectRoot,\n selfPid: process.pid,\n });\n let activeSessionId = opts.initialSessionId;\n let activeTarget: SessionIdentityTarget = {\n projectSlug: paths.projectSlug,\n projectRoot: paths.projectRoot,\n projectName: path.basename(paths.projectRoot),\n workingDir: opts.workingDir,\n };\n let pendingClaim: { sessionId: string; previousSessionId: string; token: symbol } | undefined;\n let stopped = false;\n let transition = Promise.resolve();\n\n const statusTracker = new AgentStatusTracker({\n events,\n registry,\n sessionId: () => activeSessionId,\n onUpdate: () => fleetNotifier.notify(),\n });\n\n const register = async (\n sessionId: string,\n strict = false,\n target: SessionIdentityTarget = activeTarget,\n ): Promise<void> => {\n try {\n await registry.register({\n sessionId,\n ...target,\n clientType: 'webui',\n pid: process.pid,\n startedAt: new Date().toISOString(),\n agents: statusTracker.getAgents(),\n });\n fleetNotifier.notify();\n } catch (err) {\n logger.debug?.(`WebUI session registry update failed: ${errorMessage(err)}`);\n if (strict) throw err;\n }\n };\n\n // Ownership is mandatory even for a newly-created session. Continuing with\n // an unregistered writer would let another process resume it concurrently.\n try {\n await register(activeSessionId, true);\n } catch (err) {\n fleetNotifier.dispose();\n throw err;\n }\n statusTracker.start();\n\n let stopHqBridges = (): void => {};\n let closeHqPublisher = (): void => {};\n let restartHqBridges = (_sessionId: string): void => {};\n if (opts.enableHqTelemetry !== false) {\n try {\n const core = await import('@wrongstack/core/hq');\n type HqPublisher = NonNullable<ReturnType<typeof core.createHqPublisherFromEnv>>;\n let publisher: HqPublisher | undefined;\n\n const createPublisher = (target: SessionIdentityTarget): HqPublisher | undefined => {\n const next = core.createHqPublisherFromEnv({\n clientKind: 'webui',\n projectRoot: target.projectRoot,\n projectName: target.projectName,\n appConfig: opts.config as never as Parameters<\n typeof core.createHqPublisherFromEnv\n >[0]['appConfig'],\n socketFactory: (url: string) =>\n new WebSocket(url) as unknown as import('@wrongstack/core/hq').HqSocketLike,\n });\n next?.connect();\n return next;\n };\n\n closeHqPublisher = () => {\n publisher?.close();\n publisher = undefined;\n };\n restartHqBridges = (sessionId: string) => {\n stopHqBridges();\n if (publisher?.project.projectRoot !== activeTarget.projectRoot) {\n closeHqPublisher();\n publisher = createPublisher(activeTarget);\n }\n const activePublisher = publisher;\n if (!activePublisher) return;\n\n const stops: Array<() => void> = [];\n const add = (start: () => () => void): void => {\n try {\n stops.push(start());\n } catch {\n /* optional bridge */\n }\n };\n add(() =>\n core.startSessionTelemetryBridge({\n publisher: activePublisher,\n events,\n sessionId,\n projectRoot: activeTarget.projectRoot,\n projectName: activeTarget.projectName,\n globalRoot: paths.globalRoot,\n initialAgents: statusTracker.getAgents(),\n startedAt: new Date().toISOString(),\n }),\n );\n add(() =>\n core.startFleetTelemetryBridge({\n events,\n publisher: activePublisher,\n runId: sessionId,\n sessionId,\n }),\n );\n add(() =>\n core.startBrainTelemetryBridge({\n events,\n publisher: activePublisher,\n sessionId,\n }),\n );\n add(() =>\n core.startWorktreeTelemetryBridge({\n events,\n publisher: activePublisher,\n sessionId,\n }),\n );\n add(() =>\n core.startToolTelemetryBridge({\n events,\n publisher: activePublisher,\n projectRoot: activeTarget.projectRoot,\n sessionId,\n }),\n );\n add(() =>\n core.startCostTelemetryBridge({\n events,\n publisher: activePublisher,\n sessionId,\n }),\n );\n stopHqBridges = () => {\n for (const stop of stops.splice(0)) {\n try {\n stop();\n } catch {\n /* best effort */\n }\n }\n };\n };\n\n publisher = createPublisher(activeTarget);\n restartHqBridges(activeSessionId);\n } catch (err) {\n logger.debug?.(`WebUI HQ telemetry unavailable: ${errorMessage(err)}`);\n }\n }\n\n const activate = async (\n sessionId: string,\n target: SessionIdentityTarget = activeTarget,\n ): Promise<void> => {\n if (\n stopped ||\n (sessionId === activeSessionId &&\n target.projectSlug === activeTarget.projectSlug &&\n target.projectRoot === activeTarget.projectRoot &&\n target.workingDir === activeTarget.workingDir)\n ) {\n return;\n }\n transition = transition.then(async () => {\n if (stopped) return;\n if (pendingClaim?.sessionId === sessionId) {\n pendingClaim = undefined;\n } else {\n await register(sessionId, true, target);\n }\n activeSessionId = sessionId;\n activeTarget = target;\n fleetNotifier.setProjectRoot(target.projectRoot);\n try {\n restartHqBridges(sessionId);\n } catch (err) {\n logger.debug?.(`WebUI HQ session swap failed: ${errorMessage(err)}`);\n }\n });\n await transition;\n };\n\n const claim = async (\n sessionId: string,\n target: SessionIdentityTarget = activeTarget,\n ): Promise<() => Promise<void>> => {\n if (stopped) return async () => {};\n if (pendingClaim) {\n throw new Error(`Session transition to ${pendingClaim.sessionId} is already in progress.`);\n }\n if (sessionId === activeSessionId) return async () => {};\n const previousSessionId = activeSessionId;\n const previousTarget = activeTarget;\n const token = Symbol(sessionId);\n await register(sessionId, true, target);\n pendingClaim = { sessionId, previousSessionId, token };\n return async () => {\n if (pendingClaim?.token !== token) return;\n await register(previousSessionId, true, previousTarget);\n pendingClaim = undefined;\n };\n };\n\n const stop = async (): Promise<void> => {\n if (stopped) return;\n stopped = true;\n await transition.catch(() => undefined);\n statusTracker.stop();\n stopHqBridges();\n closeHqPublisher();\n fleetNotifier.dispose();\n try {\n await registry.markClosing();\n await registry.unregister();\n } catch {\n /* best effort */\n }\n };\n\n return { statusTracker, claim, activate, stop };\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n", "/**\n * WebUI route-table construction.\n *\n * Phase 1a of the god-module split (issue: God-modules >1500 lines).\n * `startWebUI` in `./index.ts` previously inlined the construction of\n * 13 `*Routes` records (provider / session / project / mode / prefs /\n * shell-git / mailbox / mcp / brain / goal / specs / sdd-board /\n * sdd-wizard). They totalled 947 lines \u2014 the bulk of the file \u2014 and\n * were glued together by closure capture of mutable state (config,\n * projectRoot, workingDir, session, \u2026).\n *\n * This module moves that block into a single `buildRoutes()` function.\n * The closures now read live values through `WebuiMutableState` getters\n * and write them through setters, exactly the way the original code\n * captured them by reference. No behaviour change: comments, message\n * shapes, ordering, and validation are preserved verbatim.\n *\n * The `*RouteHandlers` interfaces already living next door\n * (provider-routes.ts, prefs-routes.ts, \u2026) define the type contracts\n * this file fulfils.\n */\nimport path from 'node:path';\nimport type { Agent, AgentPipelines, Context } from '@wrongstack/core/agent';\nimport type { ObservableBrainArbiter } from '@wrongstack/core/coordination';\nimport type {\n AutoCompactionMiddleware,\n BrainAutoRisk,\n BrainRuntime,\n} from '@wrongstack/core/execution';\nimport type { DefaultTokenCounter } from '@wrongstack/core/infrastructure';\nimport type { Container, EventBus } from '@wrongstack/core/kernel';\nimport type { DefaultModeStore } from '@wrongstack/core/models';\nimport type { ProviderRegistry, ToolRegistry } from '@wrongstack/core/registry';\nimport type { SkillInstaller } from '@wrongstack/core/skills';\nimport type {\n Compactor,\n ConfigStore,\n Logger,\n MemoryPort,\n ModelsRegistry,\n PermissionPolicy,\n Provider,\n ProviderConfig,\n SecretVault,\n SessionStore,\n SkillLoader,\n} from '@wrongstack/core/types';\nimport type { WebSocket, WebSocketServer } from 'ws';\n\ntype Session = Awaited<ReturnType<SessionStore['create']>>;\n\nimport type { Config } from '@wrongstack/core/types';\nimport type { MCPRegistry } from '@wrongstack/mcp';\nimport { makeProviderFromConfig, withCatalogCapabilities } from '@wrongstack/providers';\nimport { type AutonomyRouteHandlers, createAutonomyRouteHandlers } from './autonomy-routes.js';\nimport { patchConfig } from './boot.js';\nimport {\n type BrainHandlerContext,\n handleBrainAsk,\n handleBrainConfigGet,\n handleBrainConfigSet,\n handleBrainRisk,\n handleBrainStatus,\n} from './brain-handlers.js';\nimport type { BrainRouteHandlers } from './brain-routes.js';\nimport type { CollaborationWebSocketHandler } from './collaboration-ws-handler.js';\nimport { handleConfigDoctor } from './config-doctor.js';\nimport type { CustomModeStore } from './custom-context-modes.js';\nimport { handleGitChanges, handleGitDiff, handleGitInfo } from './git-handlers.js';\nimport type { GoalRouteHandlers } from './goal-routes.js';\nimport type { GoalWebSocketHandler } from './goal-ws-handler.js';\nimport { createMailboxRouteHandlers, type MailboxRouteHandlers } from './mailbox-routes.js';\nimport {\n handleMcpAdd,\n handleMcpDisable,\n handleMcpDiscover,\n handleMcpEnable,\n handleMcpList,\n handleMcpPromptGet,\n handleMcpPrompts,\n handleMcpRemove,\n handleMcpResourceRead,\n handleMcpResources,\n handleMcpRestart,\n handleMcpSleep,\n handleMcpUpdate,\n handleMcpWake,\n} from './mcp-handlers.js';\nimport type { McpRouteHandlers } from './mcp-routes.js';\nimport { createModeHandlers } from './mode-handlers.js';\nimport type { ModeRouteHandlers } from './mode-routes.js';\nimport { createModelOperations } from './model-operations.js';\nimport type { PendingConfirm } from './pending-confirms.js';\nimport type { PrefsHandlerContext } from './prefs-handlers.js';\nimport { createPrefsRouteHandlers, type PrefsRouteHandlers } from './prefs-routes.js';\nimport { authorizeWebUIAction } from './privileged-actions.js';\nimport { createProjectHandlers } from './project-handlers.js';\nimport type { ProjectRouteHandlers } from './project-routes.js';\nimport { createProviderHandlers } from './provider-handlers.js';\nimport type { ProviderRouteHandlers } from './provider-routes.js';\nimport type { SddBoardRouteHandlers } from './sdd-board-routes.js';\nimport type { SddBoardWebSocketHandler } from './sdd-board-ws-handler.js';\nimport type { SddWizardRouteHandlers } from './sdd-wizard-routes.js';\nimport type { SddWizardWebSocketHandler } from './sdd-wizard-ws-handler.js';\nimport { createSessionHandlers } from './session-handlers.js';\nimport type { SessionRouteHandlers } from './session-routes.js';\nimport type { ShellGitRouteHandlers } from './shell-git-routes.js';\nimport {\n handleShellOpen,\n normalizeShellOpenTarget,\n type ShellOpenResult,\n type ShellOpenTarget,\n} from './shell-open.js';\nimport type { SpecsRouteHandlers } from './specs-routes.js';\nimport type { SpecsWebSocketHandler } from './specs-ws-handler.js';\nimport type { SessionIdentityTarget } from './standalone-session-identity.js';\nimport type { TerminalWebSocketHandler } from './terminal-ws-handler.js';\nimport type { ConnectedClient } from './types.js';\nimport type { WorktreeWebSocketHandler } from './worktree-ws-handler.js';\nimport { validateGitDiffPayload, validateShellOpenPayload } from './ws-payload-validation.js';\nimport { broadcast, send, sendResult } from './ws-utils.js';\n\n/**\n * Mutable session-scoped state. Handlers always read LIVE values through\n * these getters and write through setters \u2014 same closure semantics as\n * the original code captured by direct reference, but reachable through\n * an interface so the route construction can live outside `startWebUI`.\n */\nexport interface WebuiMutableState {\n getConfig(): Config;\n setConfig(next: Config): void;\n getProjectRoot(): string;\n setProjectRoot(next: string): void;\n getWorkingDir(): string;\n setWorkingDir(next: string): void;\n getSession(): Session;\n setSession(next: Session): void;\n getSessionStartedAt(): number;\n setSessionStartedAt(next: number): void;\n getSessionStore(): SessionStore;\n setSessionStore(next: SessionStore): void;\n getModeId(): string;\n setModeId(next: string): void;\n /** Snapshot of current model capabilities (refreshed on model switch). */\n getModelCapabilities(): unknown;\n getConfigWriteLock(): Promise<void>;\n setConfigWriteLock(next: Promise<void>): void;\n /**\n * Abort and clear any in-flight agent run. Routes shouldn't normally\n * touch runLock directly. The\n * refactor moves that into the projectHandlers setter chain so the\n * route layer just calls a single hook.\n */\n abortRunLock: () => void;\n /** True while the leader agent owns the shared run lock. */\n isRunActive: () => boolean;\n /** Read-only reference to the live WS clients map. */\n getClients(): Map<WebSocket, ConnectedClient>;\n}\n/**\n * Services + WS-subsystem handlers, bootstrapped once. Immutable for\n * the duration of a session (the mutable ones live in `WebuiMutableState`).\n */\nexport interface WebuiDeps {\n trustBoundary: import('@wrongstack/core/security').TrustBoundary;\n agent: Agent;\n context: Context;\n container: Container;\n toolRegistry: ToolRegistry;\n modelsRegistry: ModelsRegistry;\n providerRegistry: ProviderRegistry;\n provider: Provider;\n mcpRegistry: MCPRegistry;\n vault: SecretVault;\n globalConfigPath: string;\n /** Active profile settings config; globalConfigPath is bootstrap metadata only. */\n profileConfigPath: string;\n /** Per-project layout \u2014 expose only the bits the route layer touches. */\n wpaths: { globalRoot: string; globalSkills: string; projectSessions: string };\n configStore: ConfigStore;\n tokenCounter: DefaultTokenCounter;\n permissionPolicy: PermissionPolicy;\n pendingConfirms: Map<string, PendingConfirm>;\n pipelines: AgentPipelines;\n logger: Logger;\n memoryStore: MemoryPort;\n modeStore: DefaultModeStore;\n skillLoader: SkillLoader | undefined;\n skillInstaller: SkillInstaller | undefined;\n customModeStore: CustomModeStore;\n compactor: Compactor;\n autoCompactor: AutoCompactionMiddleware | undefined;\n events: EventBus;\n wsHost: string;\n requireToken: boolean;\n publicUrl: string | undefined;\n publicWsUrl: string | undefined;\n wsPort: number;\n httpPort: number;\n wssPrimary: WebSocketServer;\n wssSecondary: WebSocketServer | null;\n /** Per-feature WS handlers (goal, specs, sdd-board, sdd-wizard, \u2026). */\n goalHandler: GoalWebSocketHandler;\n specsHandler: SpecsWebSocketHandler;\n sddBoardHandler: SddBoardWebSocketHandler;\n sddWizardHandler: SddWizardWebSocketHandler;\n worktreeHandler: WorktreeWebSocketHandler;\n collabHandler: CollaborationWebSocketHandler;\n terminalHandler: TerminalWebSocketHandler;\n /** Brain monitoring + last-20 decision log. */\n brain: ObservableBrainArbiter;\n brainSettings: { maxAutoRisk: BrainAutoRisk };\n /** Live-editable Brain config owner (brain.config.get/set). */\n brainRuntime: BrainRuntime;\n brainLog: Array<{ at: number; kind: string; question: string; outcome: string }>;\n}\n\n/**\n * Closures the routes call back into `startWebUI` for. These weren't\n * worth lifting into `WebuiMutableState` because they need write access\n * to internals (config persistence, autofill, \u2026) that only the boot\n * context has. The route layer treats them as opaque side-effects and\n * delegates without storing state of its own.\n */\nexport interface WebuiCallbacks {\n sessionStartPayload: () => Promise<{\n sessionId: string;\n model: string;\n provider: string;\n maxContext: number;\n inputCost: number;\n outputCost: number;\n cacheReadCost: number;\n projectName: string;\n projectRoot: string;\n cwd: string;\n mode: string;\n contextMode: string;\n }>;\n /** Reserve an explicitly selected session before its writer is opened. */\n claimSession: (sessionId: string, target?: SessionIdentityTarget) => Promise<() => Promise<void>>;\n /** Rebind session-scoped todo persistence before a new todo snapshot is installed. */\n onBeforeSessionTodosReplaced: (sessionId: string, sessionsDir: string) => Promise<void>;\n /** Re-point registry and HQ identity after a writer swap. */\n onSessionSwapped: (sessionId: string, target?: SessionIdentityTarget) => Promise<void>;\n /** Re-build the AutoCompaction middleware denominator on model switch. */\n updateAutoCompactionMaxContext: (\n newProvider: Provider,\n providerId?: string,\n providerCfg?: ProviderConfig | undefined,\n ) => Promise<void>;\n /** Unified, serialized helper for active-profile config mutations. */\n updateGlobalConfig: (\n mutate: (config: Record<string, unknown>) => void,\n errorLabel: string,\n ) => Promise<void>;\n /** Persist the durable subset of context.meta prefs to config.json. */\n persistPrefsToConfig: (payload: Record<string, unknown>) => Promise<void>;\n /** Snapshot of every pref the standalone server exposes. */\n prefSnapshot: () => Record<string, unknown>;\n}\n\nexport interface AllRoutes {\n providerRoutes: ProviderRouteHandlers;\n sessionRoutes: SessionRouteHandlers;\n projectRoutes: ProjectRouteHandlers;\n modeRoutes: ModeRouteHandlers;\n prefsRoutes: PrefsRouteHandlers;\n autonomyRoutes: AutonomyRouteHandlers;\n shellGitRoutes: ShellGitRouteHandlers;\n mailboxRoutes: MailboxRouteHandlers;\n mcpRoutes: McpRouteHandlers;\n brainRoutes: BrainRouteHandlers;\n goalRoutes: GoalRouteHandlers;\n specsRoutes: SpecsRouteHandlers;\n sddBoardRoutes: SddBoardRouteHandlers;\n sddWizardRoutes: SddWizardRouteHandlers;\n}\n\n/**\n * Build the 13 route records referenced by `handleProviderRoute`,\n * `handleSessionRoute`, \u2026 `handleSddWizardRoute`. The construction is a\n * direct lift from `startWebUI`; behaviour is unchanged.\n */\nexport function buildRoutes(\n state: WebuiMutableState,\n deps: WebuiDeps,\n cb: WebuiCallbacks,\n): AllRoutes {\n // ---- Provider/Key management helpers (extracted to provider-handlers.ts) ----\n const providerHandlers = createProviderHandlers({\n profileConfigPath: deps.profileConfigPath,\n vault: deps.vault,\n getConfigWriteLock: state.getConfigWriteLock,\n setConfigWriteLock: state.setConfigWriteLock,\n broadcast: (msg) => broadcast(state.getClients(), msg),\n clients: state.getClients(),\n modelsRegistry: deps.modelsRegistry,\n hasActiveModel: () => Boolean(state.getConfig().model),\n onProvidersLoaded: (providers) => {\n state.setConfig(patchConfig(state.getConfig(), { providers }));\n },\n applyModelSwitch: applyModelSwitchCore,\n });\n\n // Apply a provider+model switch to the live session: sync config, rebuild the\n // provider, refresh the auto-compaction denominator, persist, and broadcast a\n // fresh session.start. Shared by the `model.switch` handler and the\n // adopt-on-first-add path. Throws on provider-construction failure.\n async function applyModelSwitchCore(newProvider: string, newModel: string): Promise<void> {\n await deps.context.runModelTransition(async () => {\n const cur = state.getConfig();\n const newCfg = patchConfig(cur, { provider: newProvider, model: newModel });\n const providerCfg: ProviderConfig = newCfg.providers?.[newProvider] ?? { type: newProvider };\n const built = deps.providerRegistry.has(newProvider)\n ? deps.providerRegistry.create({ ...providerCfg, type: newProvider } as never)\n : makeProviderFromConfig(newProvider, providerCfg);\n // Overlay the target model's catalog facts. A freshly constructed provider\n // only has the wire-family baseline, so without this the session keeps the\n // previous model's context window and loses `maxOutput` entirely.\n const newProv = deps.modelsRegistry\n ? await withCatalogCapabilities(deps.modelsRegistry, newProvider, built, {\n ...providerCfg,\n type: newProvider,\n model: newModel,\n })\n : built;\n // Persist only after the target provider has been constructed. A failed\n // build must leave both the live session and durable selection untouched.\n await cb.updateGlobalConfig((config) => {\n config.provider = newProvider;\n config.model = newModel;\n }, 'model.switch');\n\n state.setConfig(newCfg);\n deps.configStore.update({ provider: newProvider, model: newModel });\n deps.context.model = newModel;\n deps.context.provider = newProv;\n // Capability refresh is best-effort after the atomic live swap. A catalog\n // outage must not report the switch as failed after it already committed.\n await cb.updateAutoCompactionMaxContext(newProv, newProvider, providerCfg).catch((error) => {\n deps.logger.warn(`model.switch capability refresh failed: ${String(error)}`);\n });\n\n broadcast(state.getClients(), {\n type: 'session.start',\n payload: await cb.sessionStartPayload(),\n });\n });\n }\n\n const modelOperations = createModelOperations({\n context: deps.context,\n memoryStore: deps.memoryStore,\n modelsRegistry: deps.modelsRegistry,\n getConfig: state.getConfig,\n getLiveProviderId: () => state.getConfig().provider ?? '',\n buildProvider: (providerId, providerConfig) =>\n deps.providerRegistry.has(providerId)\n ? deps.providerRegistry.create({ ...providerConfig, type: providerId } as never)\n : makeProviderFromConfig(providerId, providerConfig),\n applyModelSwitch: applyModelSwitchCore,\n isRunActive: state.isRunActive,\n send,\n broadcast: (message) => broadcast(state.getClients(), message),\n log: (message) => console.warn(message),\n });\n\n const providerRoutes: ProviderRouteHandlers = {\n providerHandlers,\n listProviders: (ws) => providerHandlers.handleProvidersList(ws),\n listSavedProviders: (ws) => providerHandlers.handleProvidersSaved(ws),\n listProviderModels: (ws, msg) =>\n providerHandlers.handleProviderModels(\n ws,\n (msg as { payload: { providerId: string } }).payload.providerId,\n ),\n searchProviderModels: (ws, query, limit) =>\n providerHandlers.handleProviderModelsSearch(ws, query, limit),\n switchModel: (ws, msg) => modelOperations.switchModel(ws, msg.payload),\n adoptDefaultProviderIfUnset: providerHandlers.adoptDefaultProviderIfUnset,\n refineModel: (ws, msg) =>\n modelOperations.refineModel(\n ws,\n msg.payload as import('./model-operations.js').ModelRefinePayload,\n ),\n };\n\n const sessionRoutes: SessionRouteHandlers = createSessionHandlers({\n config: state.getConfig(),\n clients: state.getClients(),\n context: deps.context,\n events: deps.events,\n toolRegistry: deps.toolRegistry,\n compactor: deps.compactor,\n customModeStore: deps.customModeStore,\n tokenCounter: deps.tokenCounter,\n getProjectRoot: state.getProjectRoot,\n getSession: state.getSession,\n getSessionStore: state.getSessionStore,\n sessionsDir: deps.wpaths.projectSessions,\n setSession: state.setSession,\n setSessionStartedAt: state.setSessionStartedAt,\n claimSession: cb.claimSession,\n onBeforeSessionTodosReplaced: cb.onBeforeSessionTodosReplaced,\n onSessionSwapped: cb.onSessionSwapped,\n abortActiveRun: state.abortRunLock,\n isRunActive: state.isRunActive,\n sessionStartPayload: cb.sessionStartPayload,\n });\n\n const projectRoutes: ProjectRouteHandlers = createProjectHandlers({\n globalConfigPath: deps.globalConfigPath,\n wpaths: deps.wpaths as never,\n clients: state.getClients(),\n context: deps.context,\n tokenCounter: deps.tokenCounter,\n config: state.getConfig(),\n getConfig: state.getConfig,\n getProjectRoot: state.getProjectRoot,\n getSession: state.getSession,\n setProjectRoot: state.setProjectRoot,\n setWorkingDir: state.setWorkingDir,\n setSession: state.setSession,\n setSessionStore: state.setSessionStore,\n setSessionStartedAt: state.setSessionStartedAt,\n abortRunLock: state.abortRunLock,\n onBeforeSessionTodosReplaced: cb.onBeforeSessionTodosReplaced,\n onSessionSwapped: cb.onSessionSwapped,\n sessionStartPayload: cb.sessionStartPayload,\n });\n\n const modeRoutes: ModeRouteHandlers = createModeHandlers({\n modeStore: deps.modeStore,\n memoryStore: deps.memoryStore,\n skillLoader: deps.skillLoader,\n modelCapabilities: (() => state.getModelCapabilities()) as never,\n context: deps.context,\n toolRegistry: deps.toolRegistry,\n config: state.getConfig(),\n getConfig: state.getConfig,\n projectRoot: state.getProjectRoot(),\n globalRoot: deps.wpaths.globalRoot,\n clients: state.getClients(),\n setModeId: state.setModeId,\n sessionStartPayload: cb.sessionStartPayload,\n });\n\n const prefsContext: PrefsHandlerContext = {\n meta: deps.context.meta,\n snapshot: cb.prefSnapshot,\n persist: cb.persistPrefsToConfig,\n pendingConfirms: deps.pendingConfirms,\n configStore: deps.configStore,\n setYolo: (enabled) =>\n (deps.permissionPolicy as { setYolo?: (value: boolean) => void }).setYolo?.(enabled),\n applyConfigPrefs: (payload) => {\n const config = state.getConfig();\n const features = (config.features ?? {}) as unknown as Record<string, unknown>;\n if (typeof payload['featureMcp'] === 'boolean') features['mcp'] = payload['featureMcp'];\n if (typeof payload['featurePlugins'] === 'boolean')\n features['plugins'] = payload['featurePlugins'];\n if (typeof payload['featureMemory'] === 'boolean')\n features['memory'] = payload['featureMemory'];\n if (typeof payload['featureSkills'] === 'boolean')\n features['skills'] = payload['featureSkills'];\n if (typeof payload['featureModelsRegistry'] === 'boolean')\n features['modelsRegistry'] = payload['featureModelsRegistry'];\n config.features = features as never;\n if (Array.isArray(payload['fallbackModels']))\n config.fallbackModels = payload['fallbackModels'] as string[];\n if (\n payload['fallbackProfiles'] &&\n typeof payload['fallbackProfiles'] === 'object' &&\n !Array.isArray(payload['fallbackProfiles'])\n ) {\n config.fallbackProfiles = payload['fallbackProfiles'] as Record<string, string[]>;\n }\n if (Array.isArray(payload['favoriteModels']))\n config.favoriteModels = payload['favoriteModels'] as string[];\n if (typeof payload['favoriteModelsOnly'] === 'boolean')\n config.favoriteModelsOnly = payload['favoriteModelsOnly'];\n if (Array.isArray(payload['modelAvailabilitySchedule']))\n config.modelAvailabilitySchedule = payload[\n 'modelAvailabilitySchedule'\n ] as import('@wrongstack/core/models').ModelBlackoutRule[];\n if (\n payload['modelMatrix'] &&\n typeof payload['modelMatrix'] === 'object' &&\n !Array.isArray(payload['modelMatrix'])\n ) {\n config.modelMatrix = payload['modelMatrix'] as NonNullable<typeof config.modelMatrix>;\n }\n if (typeof payload['fallbackAuto'] === 'boolean')\n config.fallbackAuto = payload['fallbackAuto'];\n },\n setAutoCompact: (enabled) => {\n deps.pipelines.contextWindow.remove('AutoCompaction', { optional: true });\n if (enabled && deps.autoCompactor) {\n deps.pipelines.contextWindow.use({\n name: 'AutoCompaction',\n handler: deps.autoCompactor.handler(),\n });\n }\n },\n setLogLevel: (level) => {\n (deps.logger as { level: string }).level = level;\n },\n send,\n broadcast: (message) => broadcast(state.getClients(), message),\n };\n const doctorConfigHandler = (ws: WebSocket, apply: boolean) =>\n handleConfigDoctor(ws, apply, {\n profileConfigPath: deps.profileConfigPath,\n vault: deps.vault,\n updateConfig: cb.updateGlobalConfig,\n applyRuntimeConfig: (next) => {\n state.setConfig(next);\n deps.configStore.update(next);\n },\n });\n const prefsRoutes = createPrefsRouteHandlers(prefsContext, doctorConfigHandler);\n const autonomyRoutes = createAutonomyRouteHandlers(prefsContext);\n\n const shellGitRoutes: ShellGitRouteHandlers = {\n gitInfo: async (ws) => {\n await handleGitInfo(ws, state.getProjectRoot());\n },\n gitChanges: async (ws) => {\n await handleGitChanges(ws, state.getProjectRoot());\n },\n gitDiff: async (ws, msg) => {\n const parsed = validateGitDiffPayload(msg.payload);\n if (!parsed.ok) {\n sendResult(ws, false, parsed.message);\n return;\n }\n await handleGitDiff(ws, state.getProjectRoot(), parsed.value.path);\n },\n shellOpen: async (ws, msg) => {\n const parsed = validateShellOpenPayload(msg.payload);\n if (!parsed.ok) {\n sendResult(ws, false, parsed.message);\n return;\n }\n // Normalize the wire-format target ('file'|'terminal') to the\n // handler contract ('terminal'|'file-manager').\n const normalizedTarget: ShellOpenTarget = normalizeShellOpenTarget(parsed.value.target);\n const authorization = await authorizeWebUIAction(\n deps.trustBoundary,\n {\n capability: normalizedTarget === 'terminal' ? 'process.spawn' : 'filesystem.open-native',\n subject: {\n kind: 'path',\n id: parsed.value.path,\n attributes: { target: normalizedTarget },\n },\n risk: 'elevated',\n cwd: state.getProjectRoot(),\n metadata: { transport: 'websocket' },\n },\n deps.logger,\n );\n if (!authorization.allowed) {\n sendResult(ws, false, `Shell action denied: ${authorization.reason}`);\n return;\n }\n const result: ShellOpenResult = await handleShellOpen(\n { path: parsed.value.path, target: normalizedTarget },\n deps.logger,\n { projectRoot: state.getProjectRoot() },\n );\n sendResult(ws, result.success, result.message);\n },\n };\n\n const mailboxRoutes = createMailboxRouteHandlers({\n getProjectRoot: state.getProjectRoot,\n getGlobalRoot: () => path.dirname(deps.globalConfigPath),\n events: deps.events,\n });\n\n // ---- MCP route (handleMcpRoute) ----\n // Issue #31 follow-on (after #118 PR 0 baseline, #119 prefs extraction).\n // Each callback delegates to the matching handleMcpXxx in mcp-handlers.ts\n // \u2014 that module already owns the WS-message logic, this is just the\n // chain-of-responsibility wiring. The 10 cases were pure delegations\n // inside the residual switch before this PR; now they're an explicit\n // sibling in the chain.\n const mcpRoutes: McpRouteHandlers = {\n list: (ws, msg) => handleMcpList(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n add: (ws, msg) => handleMcpAdd(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n update: (ws, msg) => handleMcpUpdate(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n remove: (ws, msg) => handleMcpRemove(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n enable: (ws, msg) => handleMcpEnable(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n disable: (ws, msg) => handleMcpDisable(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n sleep: (ws, msg) => handleMcpSleep(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n wake: (ws, msg) => handleMcpWake(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n restart: (ws, msg) => handleMcpRestart(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n discover: (ws, msg) => handleMcpDiscover(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n resources: (ws, msg) => handleMcpResources(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n prompts: (ws, msg) => handleMcpPrompts(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n resourceRead: (ws, msg) =>\n handleMcpResourceRead(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n promptGet: (ws, msg) => handleMcpPromptGet(ws, msg, deps.profileConfigPath, deps.mcpRegistry),\n };\n\n const brainContext: BrainHandlerContext = {\n send,\n brainSettings: deps.brainSettings,\n brainRuntime: deps.brainRuntime,\n getBrainLog: () => deps.brainLog,\n resolveArbiter: () => deps.brain,\n getSessionId: () => deps.context.session?.id,\n };\n const brainRoutes: BrainRouteHandlers = {\n status: (ws) => handleBrainStatus(brainContext, ws),\n risk: (ws, msg) =>\n handleBrainRisk(\n brainContext,\n ws,\n (msg.payload as { level?: string } | undefined)?.level ?? '',\n ),\n ask: (ws, msg) =>\n handleBrainAsk(\n brainContext,\n ws,\n (msg.payload as { question?: string } | undefined)?.question,\n ),\n configGet: (ws) => handleBrainConfigGet(brainContext, ws),\n configSet: (ws, msg) => handleBrainConfigSet(brainContext, ws, msg.payload),\n };\n\n const goalRoutes: GoalRouteHandlers = {\n handleMessage: (ws, msg) => deps.goalHandler.handleMessage(ws, msg),\n };\n\n const specsRoutes: SpecsRouteHandlers = {\n handleMessage: (msg) => deps.specsHandler.handleMessage(msg),\n };\n\n const sddBoardRoutes: SddBoardRouteHandlers = {\n handleMessage: (msg) => deps.sddBoardHandler.handleMessage(msg),\n };\n\n const sddWizardRoutes: SddWizardRouteHandlers = {\n handleMessage: (msg) => deps.sddWizardHandler.handleMessage(msg),\n };\n\n return {\n providerRoutes,\n sessionRoutes,\n projectRoutes,\n modeRoutes,\n prefsRoutes,\n autonomyRoutes,\n shellGitRoutes,\n mailboxRoutes,\n mcpRoutes,\n brainRoutes,\n goalRoutes,\n specsRoutes,\n sddBoardRoutes,\n sddWizardRoutes,\n };\n}\n", "import { type Context, DefaultSystemPromptBuilder } from '@wrongstack/core/agent';\nimport type { DefaultModeStore } from '@wrongstack/core/models';\nimport type { ToolRegistry } from '@wrongstack/core/registry';\nimport type { Config, MemoryPort, SkillLoader } from '@wrongstack/core/types';\nimport { resolveWstackPaths } from '@wrongstack/core/utils';\nimport type { WebSocket } from 'ws';\nimport { createModeRouteHandlers } from './mode-routes.js';\nimport type { ConnectedClient } from './types.js';\nimport { broadcast, send } from './ws-utils.js';\n\ntype SessionStartPayload = {\n sessionId: string;\n model: string;\n provider: string;\n maxContext: number;\n inputCost: number;\n outputCost: number;\n cacheReadCost: number;\n projectName: string;\n projectRoot: string;\n cwd: string;\n mode: string;\n contextMode: string;\n};\ntype ModelCapabilities = NonNullable<\n ConstructorParameters<typeof DefaultSystemPromptBuilder>[0]\n>['modelCapabilities'];\n\nexport interface ModeHandlersContext {\n modeStore: DefaultModeStore;\n memoryStore: MemoryPort;\n skillLoader: SkillLoader | undefined;\n modelCapabilities: ModelCapabilities;\n context: Context;\n toolRegistry: ToolRegistry;\n config: Pick<Config, 'provider' | 'model' | 'systemPrompt'>;\n getConfig?: () => Pick<Config, 'provider' | 'model' | 'systemPrompt'>;\n projectRoot: string;\n globalRoot: string;\n clients: Map<WebSocket, ConnectedClient>;\n setModeId: (id: string) => void;\n sessionStartPayload: () => Promise<SessionStartPayload>;\n}\n\nexport function createModeHandlers(context: ModeHandlersContext) {\n return createModeRouteHandlers({\n modeStore: context.modeStore,\n getSession: () => context.context.session,\n applyModeId: context.setModeId,\n send,\n afterSwitch: async (id) => {\n const modePrompt =\n id === 'default' ? '' : ((await context.modeStore.getMode(id))?.prompt ?? '');\n const paths = resolveWstackPaths({\n projectRoot: context.projectRoot,\n globalRoot: context.globalRoot,\n });\n const config = context.getConfig?.() ?? context.config;\n const builder = new DefaultSystemPromptBuilder({\n memoryStore: context.memoryStore,\n injectMemory: false,\n skillLoader: context.skillLoader,\n modeStore: context.modeStore,\n modeId: id,\n modePrompt,\n modelCapabilities: context.modelCapabilities,\n instructionPaths: {\n globalDir: paths.globalInstructions,\n projectDir: paths.inProjectInstructions,\n systemVariant: config.systemPrompt?.variant,\n },\n });\n context.context.systemPrompt = await builder.build({\n cwd: context.projectRoot,\n projectRoot: context.projectRoot,\n tools: context.toolRegistry.list(),\n provider: config.provider,\n model: config.model,\n });\n broadcast(context.clients, {\n type: 'session.start',\n payload: { ...(await context.sessionStartPayload()) },\n });\n },\n });\n}\n", "/**\n * Server lifecycle helpers for the standalone WebUI server.\n *\n * Phase 1e of the god-module split: the port resolution, WS auth/server\n * creation, event arming, session-start payload builder, HTTP server\n * startup, and graceful shutdown registration all moved here from\n * `start-webui.ts` so the orchestrator reads as connect-the-dots.\n *\n * Each function is a pure construction step \u2014 no behaviour change. The\n * WS/HTTP/shutdown wiring that used to be inline (~370 lines) now lives\n * behind four focused entry points.\n */\nimport * as path from 'node:path';\nimport { createRequire } from 'node:module';\nimport { fileURLToPath } from 'node:url';\nimport type { Config, ModelsRegistry } from '@wrongstack/core/types';\nimport { WebSocketServer, type WebSocket } from 'ws';\nimport { verifyClient as verifyWsClient } from './ws-auth.js';\nimport { envFlag, resolveAuthToken } from './ws-utils.js';\nimport { findFreePort } from './port-utils.js';\nimport { createHttpServer } from './http-server.js';\nimport { registerShutdownHandlers } from './lifecycle.js';\nimport { setupEvents, type FileWatcherMetrics } from './setup-events.js';\nimport { getCostRates } from './usage-cost.js';\nimport { resolveProviderModelMetadata } from './model-catalog.js';\nimport type { ConnectedClient } from './types.js';\nimport { toErrorMessage } from '@wrongstack/core/utils';\nimport { protocolAdvertisement } from '../protocol/index.js';\n\n// \u2500\u2500 Port resolution \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface ResolvedPorts {\n wsHost: string;\n httpPort: number;\n publicUrl: string | undefined;\n publicWsUrl: string | undefined;\n requireToken: boolean;\n}\n\n/**\n * Resolve bind host, HTTP port, public URLs, and the token-required flag\n * from CLI opts + env vars. The WS server shares the HTTP port (single\n * port design), so only one port is resolved. Auto-advances past taken\n * ports unless `WEBUI_STRICT_PORT` is set.\n */\nexport async function resolvePorts(opts: {\n surface?: 'webui' | 'simpleui' | undefined;\n wsHost?: string | undefined;\n httpPort?: number | undefined;\n webuiPort?: number | undefined;\n port?: number | undefined;\n publicUrl?: string | undefined;\n publicWsUrl?: string | undefined;\n requireToken?: boolean | undefined;\n}): Promise<ResolvedPorts> {\n const surface = opts.surface ?? 'webui';\n const surfaceDefaults = surface === 'simpleui'\n ? { http: 3466 }\n : { http: 3456 };\n const wsHost = opts.wsHost ?? process.env['WEBUI_HOST'] ?? process.env['WS_HOST'] ?? '127.0.0.1';\n const requestedHttpPort =\n opts.httpPort ?? opts.webuiPort ?? opts.port ??\n Number.parseInt(process.env['WEBUI_PORT'] ?? process.env['PORT'] ?? String(surfaceDefaults.http), 10);\n const publicUrl = opts.publicUrl ?? process.env['WEBUI_PUBLIC_URL'];\n const publicWsUrl = opts.publicWsUrl ?? process.env['WEBUI_PUBLIC_WS_URL'];\n const requireToken = opts.requireToken ?? envFlag('WEBUI_REQUIRE_TOKEN');\n\n const strictPort =\n process.env['WEBUI_STRICT_PORT'] === '1' || process.env['WEBUI_STRICT_PORT'] === 'true';\n let httpPort = requestedHttpPort;\n if (!strictPort) {\n httpPort = await findFreePort(wsHost, requestedHttpPort);\n if (httpPort !== requestedHttpPort) {\n console.warn(JSON.stringify({ level: 'warn', event: 'webui.port_reassigned', protocol: 'HTTP', requested: requestedHttpPort, assigned: httpPort, timestamp: new Date().toISOString() }));\n }\n }\n return { wsHost, httpPort, publicUrl, publicWsUrl, requireToken };\n}\n\n// \u2500\u2500 Session start payload \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface SessionStartPayloadGetters {\n getConfig(): Config;\n getSessionId(): string;\n getProjectRoot(): string;\n getWorkingDir(): string;\n getModeId(): string;\n getContextMode(): string;\n getNeedsSetup(): boolean;\n modelsRegistry: ModelsRegistry;\n}\n\n/**\n * Build a factory that produces the rich session.start payload from current\n * runtime state. Reads live values through getters so post-/new, post-resume,\n * and post-model.switch all broadcast the same shape.\n */\nexport function createSessionStartPayload(g: SessionStartPayloadGetters): () => Promise<{\n sessionId: string;\n model: string;\n provider: string;\n maxContext: number;\n inputCost: number;\n outputCost: number;\n cacheReadCost: number;\n projectName: string;\n projectRoot: string;\n cwd: string;\n mode: string;\n contextMode: string;\n protocolVersion: number;\n protocolCapabilities: string[];\n needsSetup?: boolean | undefined;\n}> {\n return async () => {\n const config = g.getConfig();\n let maxContext = 0;\n let inputCost = 0;\n let outputCost = 0;\n let cacheReadCost = 0;\n try {\n const m = await resolveProviderModelMetadata(\n g.modelsRegistry,\n config.provider,\n config.model,\n config.providers?.[config.provider],\n );\n maxContext = m?.capabilities?.maxContext ?? 0;\n if (!maxContext) {\n try {\n const provider = await (g.modelsRegistry as {\n getProvider(id: string): Promise<{ models: Array<{ id: string; limit?: { context?: number } }> } | undefined>;\n }).getProvider(config.provider);\n const rawModel = provider?.models.find((mod) => mod.id === config.model);\n maxContext = rawModel?.limit?.context ?? 0;\n } catch {\n /* best-effort */\n }\n }\n const rates = getCostRates(m);\n inputCost = rates.input;\n outputCost = rates.output;\n cacheReadCost = rates.cacheRead;\n } catch {\n // best-effort\n }\n const projectRoot = g.getProjectRoot();\n const result: {\n sessionId: string; model: string; provider: string; maxContext: number;\n inputCost: number; outputCost: number; cacheReadCost: number;\n projectName: string; projectRoot: string; cwd: string; mode: string; contextMode: string;\n protocolVersion: number; protocolCapabilities: string[];\n needsSetup?: boolean | undefined;\n } = {\n sessionId: g.getSessionId(),\n model: config.model,\n provider: config.provider,\n maxContext,\n inputCost,\n outputCost,\n cacheReadCost,\n projectName: path.basename(projectRoot) || projectRoot,\n projectRoot,\n cwd: g.getWorkingDir(),\n mode: g.getModeId(),\n contextMode: g.getContextMode(),\n ...protocolAdvertisement(),\n };\n if (g.getNeedsSetup()) result.needsSetup = true;\n return result;\n };\n}\n\n// \u2500\u2500 WebSocket servers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface WsServerResult {\n wssPrimary: WebSocketServer;\n wssSecondary: WebSocketServer | null;\n wsToken: string;\n clients: Map<WebSocket, ConnectedClient>;\n}\n\n/**\n * Attach a WebSocket server to an HTTP server (shared-port design).\n * Creates the primary WS server attached to the given HTTP server.\n * IPv6 loopback coverage is provided by the HTTP server's dual-stack\n * listen (see start-webui.ts); no separate WS secondary is created.\n * Returns the WS server, the resolved auth token, and the clients map.\n */\nexport function createWsServers(\n httpServer: import('node:http').Server,\n ports: ResolvedPorts,\n accessToken: string | undefined,\n): WsServerResult {\n const wsToken = resolveAuthToken(accessToken);\n console.log('[WebUI] WS auth token ready');\n const publicHostnames = [ports.publicUrl, ports.publicWsUrl]\n .map((value) => {\n if (!value) return undefined;\n try { return new URL(value).hostname; } catch { return undefined; }\n })\n .filter((value): value is string => Boolean(value));\n\n const verifyClient = (info: {\n origin: string; secure: boolean; req: import('node:http').IncomingMessage;\n }) =>\n verifyWsClient({\n origin: info.origin,\n url: info.req.url ?? '',\n hostHeader: info.req.headers.host,\n remoteAddress: info.req.socket.remoteAddress,\n cookieHeader: info.req.headers.cookie,\n wsHost: ports.wsHost,\n expectedToken: wsToken,\n requireToken: ports.requireToken,\n allowedHostnames: publicHostnames,\n allowBrowserUrlToken: Boolean(ports.publicWsUrl),\n });\n\n // 20 MiB to leave headroom for image attachments (base64-inflated) in\n // user_message payloads. Keep in sync with the CLI webui-server's\n // maxPayload \u2014 both servers speak the same protocol.\n const WS_MAX_PAYLOAD = 20 * 1024 * 1024;\n const wssPrimary = new WebSocketServer({\n server: httpServer, verifyClient, maxPayload: WS_MAX_PAYLOAD,\n // Send a ping every 15s to keep idle connections alive. Without this,\n // network equipment (routers, proxies, NAT gateways) may drop idle TCP\n // connections, causing the browser to see a close event and show the\n // \"reconnecting\" banner. The browser responds with a pong automatically\n // (the WebSocket API handles this at the transport level).\n pingInterval: 15_000,\n // Wait 5s for a pong before considering the connection dead. A client\n // that hasn't responded to 3 consecutive pings in a row (45s total\n // quiet) is almost certainly unreachable \u2014 close the socket so the\n // client can reconnect cleanly rather than hanging indefinitely.\n pingTimeout: 5_000,\n } as ConstructorParameters<typeof WebSocketServer>[0]);\n // IPv6 loopback secondary: when binding to 127.0.0.1, we also listen on\n // [::1] so Chrome/Edge on Windows (which resolve localhost to IPv6 first)\n // can connect without ECONNREFUSED. The HTTP server handles this via\n // dual-stack listen \u2014 see start-webui.ts.\n const wssSecondary = null;\n const clients = new Map<WebSocket, ConnectedClient>();\n return { wssPrimary, wssSecondary, wsToken, clients };\n}\n\n// \u2500\u2500 Event arming + WS error handlers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Wire setupEvents (the once-only event\u2192WS-broadcast bridge) behind a\n * listening-callback guard, and attach WS server error handlers. Returns\n * the dispose + fleet-broadcast functions.\n */\nexport function armEvents(\n wssPrimary: WebSocketServer,\n wssSecondary: WebSocketServer | null,\n wsHost: string,\n httpPort: number,\n setupInput: Parameters<typeof setupEvents>[0],\n watcherMetrics: FileWatcherMetrics,\n): { arm: (label: string) => void; getDispose: () => (() => void) | null; getFleetBroadcast: () => (() => Promise<void>) | null } {\n let eventsArmed = false;\n let disposeEvents: (() => void) | null = null;\n let fleetBroadcast: (() => Promise<void>) | null = null;\n\n const arm = (label: string): void => {\n if (eventsArmed) return;\n eventsArmed = true;\n console.log(`[WebUI] Backend ready (${label})`);\n disposeEvents = setupEvents({ ...setupInput, watcherMetrics, onFleetBroadcaster: (fn) => { fleetBroadcast = fn; } });\n };\n\n wssPrimary.on('listening', () => arm(`${wsHost}:${httpPort}`));\n wssPrimary.on('error', (err) => {\n console.error(JSON.stringify({ level: 'error', event: 'webui.ws_server_error', host: wsHost, message: toErrorMessage(err), timestamp: new Date().toISOString() }));\n });\n if (wssSecondary) {\n wssSecondary.on('listening', () => arm(`::1:${httpPort}`));\n wssSecondary.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EAFNOSUPPORT' || err.code === 'EADDRNOTAVAIL') {\n console.warn(JSON.stringify({ level: 'warn', event: 'webui.ipv6_unavailable', code: err.code, message: err.message, timestamp: new Date().toISOString() }));\n } else {\n console.error(JSON.stringify({ level: 'error', event: 'webui.ws_server_error', host: '::1', message: err.message, timestamp: new Date().toISOString() }));\n }\n });\n }\n return {\n arm,\n getDispose: () => disposeEvents,\n getFleetBroadcast: () => fleetBroadcast,\n };\n}\n\n// \u2500\u2500 HTTP server + shutdown \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Resolve the directory containing the built WebUI frontend assets.\n *\n * The standalone webui-server package does not bundle the React frontend;\n * it lives in the separate `@wrongstack/webui` package. Callers can pass an\n * explicit `distDir`; when they don't, we try to resolve the frontend package\n * relative to the server entry that is asking. This lets the standalone\n * standalone server serve the webui assets when both packages are installed,\n * while also allowing embedded callers (e.g. the desktop app) to pass an exact\n * path so they don't depend on module-resolution layout.\n */\nfunction resolveWebuiDistDir(fromUrl: string, explicitDistDir?: string | undefined): string {\n if (explicitDistDir) return path.resolve(explicitDistDir);\n try {\n const requireFromHere = createRequire(fromUrl);\n const serverEntry = requireFromHere.resolve('@wrongstack/webui');\n return path.dirname(serverEntry); // .../dist\n } catch {\n // Legacy fallback: assume the webui dist is co-located with the server\n // runtime (the pre-extraction layout). This path is wrong for the\n // extracted @wrongstack/webui-server package, but keeping it preserves\n // any bespoke/test setups that still lay out files that way.\n return path.resolve(path.dirname(fileURLToPath(fromUrl)), '..', '..', 'dist');\n }\n}\n\nexport function startHttpServer(opts: {\n wsHost: string;\n httpPort: number;\n wsToken: string;\n publicWsUrl: string | undefined;\n publicUrl: string | undefined;\n requireToken: boolean;\n globalRoot: string;\n globalConfigPath: string;\n projectRoot: string;\n openBrowser: boolean;\n watcherMetrics: FileWatcherMetrics;\n onFleetPing: () => void;\n onTechStackEvent?: ((event: import('./techstack-handlers.js').TechStackEvent) => void) | undefined;\n /** Live provider access for TechStack's LLM research stage. */\n getLlm?:\n | (() => { provider: import('@wrongstack/core/types').Provider; model: string } | undefined)\n | undefined;\n executePackageOperation?: import('./techstack-handlers.js').TechStackHandlerDeps['executePackageOperation'];\n distDir?: string | undefined;\n}): import('node:http').Server {\n const httpServer = createHttpServer({\n host: opts.wsHost,\n port: opts.httpPort,\n distDir: resolveWebuiDistDir(import.meta.url, opts.distDir),\n publicWsUrl: opts.publicWsUrl,\n globalRoot: opts.globalRoot,\n apiToken: opts.wsToken,\n requireToken: opts.requireToken,\n watcherMetrics: opts.watcherMetrics,\n onFleetPing: opts.onFleetPing,\n onTechStackEvent: opts.onTechStackEvent,\n getLlm: opts.getLlm,\n executePackageOperation: opts.executePackageOperation,\n projectRoot: opts.projectRoot,\n });\n return httpServer;\n}\n\ninterface ShutdownDeps {\n flushSession: () => Promise<void>;\n clients: () => IterableIterator<WebSocket>;\n servers: Array<import('node:http').Server | WebSocketServer>;\n onShutdown: () => Promise<void> | void;\n}\n\nexport function registerShutdown(deps: ShutdownDeps): void {\n registerShutdownHandlers({\n flushSession: deps.flushSession,\n clients: deps.clients,\n servers: deps.servers,\n onShutdown: deps.onShutdown,\n });\n}\n"],
5
- "mappings": "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A,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACpEO,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,2BAA2B;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC3DO,IAAM,iCAAiC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,qCAAqC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACvDO,IAAM,oCAAoC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,qCAAqC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACjFO,IAAM,iCAAiC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,iCAAiC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACpEO,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,2BAA2B;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,kCAAkC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC5DO,IAAM,iCAAiC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA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",
6
- "names": ["path", "cache", "error", "isRecord", "AUTONOMY_VALUES", "isRecord", "AUTONOMY_VALUES", "name", "path", "sendResult", "name", "sendResult", "access", "error", "fs", "path", "deps", "path", "name", "toolName", "tail", "s", "path", "isInside", "error", "text", "fs", "path", "fs", "path", "ToolValidationError", "name", "fs", "path", "relative", "stat", "ToolValidationError", "fs", "path", "atomicWrite", "name", "name", "fs", "path", "atomicWrite", "sessionPayload", "current", "error", "isRecord", "path", "text", "name", "error", "createChronicleProjectAccess", "resolveWstackPaths", "error", "access", "atomicWrite", "fs", "path", "load", "save", "broadcast", "resolve", "path", "reply", "readFile", "join", "resolveWstackPaths", "broadcast", "readFile", "toErrorMessage", "resolve", "error", "sendResult", "result", "toErrorMessage", "execFile", "resolve", "error", "sendResult", "error", "resolve", "error", "fs", "path", "getIndexState", "deps", "path", "resolve", "deps", "text", "toolName", "DefaultSessionStore", "DefaultSessionReader", "resolveWstackPaths", "tail", "readJsonBody", "resolve", "getSharedProjectMailbox", "mailboxSessionTag", "fs", "path", "record", "stat", "text", "fs", "path", "randomUUID", "sendJson", "deps", "error", "Buffer", "name", "deps", "error", "getIndexState", "path", "fs", "atomicWrite", "record", "caps", "name", "cache", "ok", "randomUUID", "randomUUID", "error", "listBoards", "updateTask", "recordKanbanVerificationEvidence", "activityContext", "findTask", "recordKanbanVerificationEvidence", "activityContext", "listBoards", "activityContext", "updateTask", "findTask", "name", "getServerKanbanStore", "fs", "atomicWrite", "deps", "current", "atomicWrite", "deps", "deps", "sendResult", "error", "errorMessage", "name", "text", "ToolValidationError", "toErrorMessage", "sendResult", "error", "toErrorMessage", "sendResult", "error", "toErrorMessage", "text", "getProcessRegistry", "ToolValidationError", "resolve", "spawn", "path", "deps", "resolved", "error", "resolve", "spawn", "path", "os", "deps", "deps", "broadcast", "sessionPayload", "text", "crypto", "path", "getSharedProjectMailbox", "resolveProjectDir", "deps", "toErrorMessage", "sendResult", "deserializeTaskGraph", "createBoard", "getBoard", "listBoards", "syncBoardFromTaskGraph", "deps", "broadcast", "tags", "boardId", "current", "getBoard", "getKanbanQueueHealth", "listBoards", "reconcileKanbanBoard", "recoverStaleTaskAssignments", "deps", "snapshot", "current", "error", "fs", "path", "decryptConfigSecrets", "atomicWrite", "FORBIDDEN_PROTO_KEYS", "deps", "getProcessRegistry", "randomUUID", "getProcessRegistry", "sendResult", "fs", "path", "DefaultSessionStore", "toErrorMessage", "wstackGlobalRoot", "fs", "path", "resolveWstackPaths", "sendResult", "error", "name", "stat", "resolveWstackPaths", "toErrorMessage", "normalize", "name", "fs", "ConfigError", "atomicWrite", "decryptConfigSecrets", "encryptConfigSecrets", "deps", "name", "error", "reply", "toErrorMessage", "repairToolUseAdjacency", "path", "name", "currentSessionId", "currentSessionId", "sessionPayload", "requestedSessionId", "current", "repairToolUseAdjacency", "name", "error", "toErrorMessage", "DefaultSessionStore", "wstackGlobalRoot", "makeProviderFromConfig", "text", "name", "shutdownCodebaseIndexServer", "deps", "shutdownCodebaseIndexServer", "error", "sendResult", "fs", "path", "spawn", "relative", "deps", "send", "sendResult", "error", "text", "current", "makeProviderFromConfig", "path", "expectDefined", "fs", "decryptConfigSecrets", "encryptConfigSecrets", "atomicWrite", "resolve", "deps", "loadSavedProviders", "saveProviders", "normalizeKeys", "writeKeysBack", "maskedKey", "listBoards", "listBoards", "path", "ToolValidationError", "WorktreeManager", "SddBoardStore", "deps", "WorktreeManager", "SddBoardStore", "name", "ToolValidationError", "deriveTitle", "deps", "error", "text", "path", "deps", "broadcast", "name", "broadcast", "sessionPayload", "currentSessionId", "sessionPayload", "current", "fsWatch", "fs", "path", "path", "relative", "deps", "broadcast", "DEBOUNCE_MS", "fsWatch", "fs", "path", "deps", "broadcast", "deps", "broadcast", "sessionPayload", "loadTasks", "loadPlan", "load", "SpecStore", "TaskGraphStore", "SpecStore", "TaskGraphStore", "deps", "randomUUID", "http", "path", "getSharedProjectMailbox", "resolveProjectDir", "createCompatibilityTrustBoundary", "DEFAULT_CONTEXT_WINDOW_MODE_ID", "expectDefined", "sessionScopedPath", "toErrorMessage", "wstackGlobalRoot", "makeProviderFromConfig", "join", "getSharedProjectMailbox", "TOKENS", "resolveContextWindowPolicy", "toErrorMessage", "spawn", "existsSync", "dirname", "join", "resolveProjectDir", "wstackGlobalRoot", "require", "resolve", "createRequire", "createCompatibilityTrustBoundary", "toErrorMessage", "createRequire", "createCompatibilityTrustBoundary", "toErrorMessage", "join", "resolve", "sep", "toErrorMessage", "WorktreeManager", "cleanupStaleSddWorktrees", "resolve", "join", "sep", "WorktreeManager", "toErrorMessage", "cleanupStaleSddWorktrees", "text", "resolveContextWindowPolicy", "toErrorMessage", "TOKENS", "join", "getSharedProjectMailbox", "path", "deps", "path", "sessionPayload", "current", "sendResult", "createRequire", "path", "getSharedProjectMailbox", "TOKENS", "DefaultSessionStore", "getSessionRegistry", "resolveContextWindowPolicy", "sessionScopedPath", "toErrorMessage", "fs", "path", "cache", "expectDefined", "toErrorMessage", "makeProviderFromConfig", "provider", "path", "WebSocket", "errorMessage", "stop", "toErrorMessage", "TOKENS", "name", "DefaultSessionStore", "getSessionRegistry", "createRequire", "getSharedProjectMailbox", "resolveContextWindowPolicy", "sessionScopedPath", "path", "makeProviderFromConfig", "DefaultSystemPromptBuilder", "resolveWstackPaths", "resolveWstackPaths", "DefaultSystemPromptBuilder", "deps", "makeProviderFromConfig", "error", "sendResult", "path", "path", "createRequire", "toErrorMessage", "verifyClient", "toErrorMessage", "requireFromHere", "createRequire", "deps", "sessionScopedPath", "error", "updateGlobalConfig", "expectDefined", "prefSnapshot", "persistPrefsToConfig", "createCompatibilityTrustBoundary", "DEFAULT_CONTEXT_WINDOW_MODE_ID", "randomUUID", "output", "resolve", "head", "deps", "hydrateSessionKanban", "makeProviderFromConfig", "toErrorMessage", "getSharedProjectMailbox", "resolveProjectDir", "wstackGlobalRoot"]
7
- }