@chorus-aidlc/chorus 0.16.4 → 0.17.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 (435) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-build-manifest.json +420 -420
  3. package/.next/standalone/.next/app-path-routes-manifest.json +53 -53
  4. package/.next/standalone/.next/build-manifest.json +5 -5
  5. package/.next/standalone/.next/prerender-manifest.json +45 -45
  6. package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page.js +1 -1
  7. package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page.js +1 -1
  10. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page.js +1 -1
  12. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page_client-reference-manifest.js +1 -1
  13. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js +2 -2
  14. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page.js +2 -2
  17. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page.js +2 -2
  19. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js +2 -2
  21. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js +2 -2
  24. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page_client-reference-manifest.js +1 -1
  26. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page.js +1 -1
  27. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page.js +2 -2
  30. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page_client-reference-manifest.js +1 -1
  31. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js +1 -1
  32. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page_client-reference-manifest.js +1 -1
  34. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js +1 -1
  35. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/(dashboard)/projects/page.js +1 -1
  38. package/.next/standalone/.next/server/app/(dashboard)/projects/page.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/(dashboard)/projects/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/(dashboard)/settings/page.js +2 -2
  41. package/.next/standalone/.next/server/app/(dashboard)/settings/page.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
  43. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/_not-found.html +2 -2
  45. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  46. package/.next/standalone/.next/server/app/admin/companies/[uuid]/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/admin/companies/new/page_client-reference-manifest.js +1 -1
  48. package/.next/standalone/.next/server/app/admin/companies/new.html +2 -2
  49. package/.next/standalone/.next/server/app/admin/companies/new.rsc +1 -1
  50. package/.next/standalone/.next/server/app/admin/companies/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/admin/companies.html +2 -2
  52. package/.next/standalone/.next/server/app/admin/companies.rsc +1 -1
  53. package/.next/standalone/.next/server/app/admin/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/admin.html +2 -2
  55. package/.next/standalone/.next/server/app/admin.rsc +1 -1
  56. package/.next/standalone/.next/server/app/api/admin/companies/[uuid]/route_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app/api/admin/companies/route_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/api/admin/login/route_client-reference-manifest.js +1 -1
  59. package/.next/standalone/.next/server/app/api/admin/session/route_client-reference-manifest.js +1 -1
  60. package/.next/standalone/.next/server/app/api/agent-connections/route.js.nft.json +1 -1
  61. package/.next/standalone/.next/server/app/api/agent-connections/route_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/api/agents/[uuid]/route_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route.js +1 -1
  64. package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/api/agents/route_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/api/api-keys/[uuid]/route_client-reference-manifest.js +1 -1
  68. package/.next/standalone/.next/server/app/api/api-keys/route_client-reference-manifest.js +1 -1
  69. package/.next/standalone/.next/server/app/api/auth/callback/route_client-reference-manifest.js +1 -1
  70. package/.next/standalone/.next/server/app/api/auth/check-default/route_client-reference-manifest.js +1 -1
  71. package/.next/standalone/.next/server/app/api/auth/company-oidc/route_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/api/auth/default-login/route_client-reference-manifest.js +1 -1
  73. package/.next/standalone/.next/server/app/api/auth/identify/route_client-reference-manifest.js +1 -1
  74. package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
  75. package/.next/standalone/.next/server/app/api/auth/me/route_client-reference-manifest.js +1 -1
  76. package/.next/standalone/.next/server/app/api/auth/sync-token/route_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/api/comments/route.js +1 -1
  78. package/.next/standalone/.next/server/app/api/comments/route.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/api/comments/route_client-reference-manifest.js +1 -1
  80. package/.next/standalone/.next/server/app/api/daemon/connection-heartbeat/route.js.nft.json +1 -1
  81. package/.next/standalone/.next/server/app/api/daemon/connection-heartbeat/route_client-reference-manifest.js +1 -1
  82. package/.next/standalone/.next/server/app/api/daemon/control/route_client-reference-manifest.js +1 -1
  83. package/.next/standalone/.next/server/app/api/daemon/directory-request/report/route.js.nft.json +1 -1
  84. package/.next/standalone/.next/server/app/api/daemon/directory-request/report/route_client-reference-manifest.js +1 -1
  85. package/.next/standalone/.next/server/app/api/daemon/execution-state/route.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/api/daemon/execution-state/route_client-reference-manifest.js +1 -1
  87. package/.next/standalone/.next/server/app/api/daemon/executions/route.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/api/daemon/executions/route_client-reference-manifest.js +1 -1
  89. package/.next/standalone/.next/server/app/api/daemon/pending-turns/route.js +1 -1
  90. package/.next/standalone/.next/server/app/api/daemon/pending-turns/route.js.nft.json +1 -1
  91. package/.next/standalone/.next/server/app/api/daemon/pending-turns/route_client-reference-manifest.js +1 -1
  92. package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route.js.nft.json +1 -1
  93. package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route_client-reference-manifest.js +1 -1
  94. package/.next/standalone/.next/server/app/api/daemon/resume/route.js.nft.json +1 -1
  95. package/.next/standalone/.next/server/app/api/daemon/resume/route_client-reference-manifest.js +1 -1
  96. package/.next/standalone/.next/server/app/api/daemon/transcript/route.js +1 -1
  97. package/.next/standalone/.next/server/app/api/daemon/transcript/route.js.nft.json +1 -1
  98. package/.next/standalone/.next/server/app/api/daemon/transcript/route_client-reference-manifest.js +1 -1
  99. package/.next/standalone/.next/server/app/api/daemon/turn-advance/route.js +1 -1
  100. package/.next/standalone/.next/server/app/api/daemon/turn-advance/route.js.nft.json +1 -1
  101. package/.next/standalone/.next/server/app/api/daemon/turn-advance/route_client-reference-manifest.js +1 -1
  102. package/.next/standalone/.next/server/app/api/daemon-directory-requests/[uuid]/route.js.nft.json +1 -1
  103. package/.next/standalone/.next/server/app/api/daemon-directory-requests/[uuid]/route_client-reference-manifest.js +1 -1
  104. package/.next/standalone/.next/server/app/api/daemon-directory-requests/route.js.nft.json +1 -1
  105. package/.next/standalone/.next/server/app/api/daemon-directory-requests/route_client-reference-manifest.js +1 -1
  106. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route.js +1 -1
  107. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route.js.nft.json +1 -1
  108. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route_client-reference-manifest.js +1 -1
  109. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route.js +1 -1
  110. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route.js.nft.json +1 -1
  111. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route_client-reference-manifest.js +1 -1
  112. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route.js +1 -1
  113. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route_client-reference-manifest.js +1 -1
  115. package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route.js +1 -1
  116. package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route.js.nft.json +1 -1
  117. package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route_client-reference-manifest.js +1 -1
  118. package/.next/standalone/.next/server/app/api/daemon-sessions/route.js +1 -1
  119. package/.next/standalone/.next/server/app/api/daemon-sessions/route.js.nft.json +1 -1
  120. package/.next/standalone/.next/server/app/api/daemon-sessions/route_client-reference-manifest.js +1 -1
  121. package/.next/standalone/.next/server/app/api/documents/[uuid]/route_client-reference-manifest.js +1 -1
  122. package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route.js +1 -1
  123. package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route.js.nft.json +1 -1
  124. package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route_client-reference-manifest.js +1 -1
  125. package/.next/standalone/.next/server/app/api/events/notifications/route.js +1 -1
  126. package/.next/standalone/.next/server/app/api/events/notifications/route.js.nft.json +1 -1
  127. package/.next/standalone/.next/server/app/api/events/notifications/route_client-reference-manifest.js +1 -1
  128. package/.next/standalone/.next/server/app/api/events/route.js +1 -1
  129. package/.next/standalone/.next/server/app/api/events/route.js.nft.json +1 -1
  130. package/.next/standalone/.next/server/app/api/events/route_client-reference-manifest.js +1 -1
  131. package/.next/standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
  132. package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route.js +1 -1
  133. package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route.js.nft.json +1 -1
  134. package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route_client-reference-manifest.js +1 -1
  135. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route.js +1 -1
  136. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route.js.nft.json +1 -1
  137. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route_client-reference-manifest.js +1 -1
  138. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route.js +1 -1
  139. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route.js.nft.json +1 -1
  140. package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route_client-reference-manifest.js +1 -1
  141. package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route.js +1 -1
  142. package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route.js.nft.json +1 -1
  143. package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route_client-reference-manifest.js +1 -1
  144. package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route.js +1 -1
  145. package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route_client-reference-manifest.js +1 -1
  147. package/.next/standalone/.next/server/app/api/ideas/[uuid]/route.js +1 -1
  148. package/.next/standalone/.next/server/app/api/ideas/[uuid]/route.js.nft.json +1 -1
  149. package/.next/standalone/.next/server/app/api/ideas/[uuid]/route_client-reference-manifest.js +1 -1
  150. package/.next/standalone/.next/server/app/api/ideas/[uuid]/wake-preview/route.js.nft.json +1 -1
  151. package/.next/standalone/.next/server/app/api/ideas/[uuid]/wake-preview/route_client-reference-manifest.js +1 -1
  152. package/.next/standalone/.next/server/app/api/ideas/conversational/route.js +1 -1
  153. package/.next/standalone/.next/server/app/api/ideas/conversational/route.js.nft.json +1 -1
  154. package/.next/standalone/.next/server/app/api/ideas/conversational/route_client-reference-manifest.js +1 -1
  155. package/.next/standalone/.next/server/app/api/mcp/route.js +4 -4
  156. package/.next/standalone/.next/server/app/api/mcp/route.js.nft.json +1 -1
  157. package/.next/standalone/.next/server/app/api/mcp/route_client-reference-manifest.js +1 -1
  158. package/.next/standalone/.next/server/app/api/me/assignments/route.js +1 -1
  159. package/.next/standalone/.next/server/app/api/me/assignments/route.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/api/me/assignments/route_client-reference-manifest.js +1 -1
  161. package/.next/standalone/.next/server/app/api/mentionables/route.js +1 -1
  162. package/.next/standalone/.next/server/app/api/mentionables/route.js.nft.json +1 -1
  163. package/.next/standalone/.next/server/app/api/mentionables/route_client-reference-manifest.js +1 -1
  164. package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route.js +1 -1
  165. package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route.js.nft.json +1 -1
  166. package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route_client-reference-manifest.js +1 -1
  167. package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route.js +1 -1
  168. package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route.js.nft.json +1 -1
  169. package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route_client-reference-manifest.js +1 -1
  170. package/.next/standalone/.next/server/app/api/notifications/preferences/route.js +1 -1
  171. package/.next/standalone/.next/server/app/api/notifications/preferences/route.js.nft.json +1 -1
  172. package/.next/standalone/.next/server/app/api/notifications/preferences/route_client-reference-manifest.js +1 -1
  173. package/.next/standalone/.next/server/app/api/notifications/read-all/route.js +1 -1
  174. package/.next/standalone/.next/server/app/api/notifications/read-all/route.js.nft.json +1 -1
  175. package/.next/standalone/.next/server/app/api/notifications/read-all/route_client-reference-manifest.js +1 -1
  176. package/.next/standalone/.next/server/app/api/notifications/route.js +1 -1
  177. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  178. package/.next/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
  179. package/.next/standalone/.next/server/app/api/notifications/unread-count/route.js +1 -1
  180. package/.next/standalone/.next/server/app/api/notifications/unread-count/route.js.nft.json +1 -1
  181. package/.next/standalone/.next/server/app/api/notifications/unread-count/route_client-reference-manifest.js +1 -1
  182. package/.next/standalone/.next/server/app/api/project-groups/[uuid]/dashboard/route_client-reference-manifest.js +1 -1
  183. package/.next/standalone/.next/server/app/api/project-groups/[uuid]/route_client-reference-manifest.js +1 -1
  184. package/.next/standalone/.next/server/app/api/project-groups/route_client-reference-manifest.js +1 -1
  185. package/.next/standalone/.next/server/app/api/project-visits/pin/route_client-reference-manifest.js +1 -1
  186. package/.next/standalone/.next/server/app/api/project-visits/route_client-reference-manifest.js +1 -1
  187. package/.next/standalone/.next/server/app/api/project-visits/visit/route_client-reference-manifest.js +1 -1
  188. package/.next/standalone/.next/server/app/api/projects/[uuid]/activity/route_client-reference-manifest.js +1 -1
  189. package/.next/standalone/.next/server/app/api/projects/[uuid]/agent-cwds/route.js.nft.json +1 -1
  190. package/.next/standalone/.next/server/app/api/projects/[uuid]/agent-cwds/route_client-reference-manifest.js +1 -1
  191. package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route.js +1 -1
  192. package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route.js.nft.json +1 -1
  193. package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route_client-reference-manifest.js +1 -1
  194. package/.next/standalone/.next/server/app/api/projects/[uuid]/documents/route_client-reference-manifest.js +1 -1
  195. package/.next/standalone/.next/server/app/api/projects/[uuid]/group/route_client-reference-manifest.js +1 -1
  196. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route.js +1 -1
  197. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route.js.nft.json +1 -1
  198. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route_client-reference-manifest.js +1 -1
  199. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route.js +1 -1
  200. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route.js.nft.json +1 -1
  201. package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route_client-reference-manifest.js +1 -1
  202. package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/[proposalUuid]/validate/route_client-reference-manifest.js +1 -1
  203. package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/route_client-reference-manifest.js +1 -1
  204. package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/summary/route_client-reference-manifest.js +1 -1
  205. package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route.js +1 -1
  206. package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route.js.nft.json +1 -1
  207. package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route_client-reference-manifest.js +1 -1
  208. package/.next/standalone/.next/server/app/api/projects/[uuid]/route_client-reference-manifest.js +1 -1
  209. package/.next/standalone/.next/server/app/api/projects/[uuid]/stats/route_client-reference-manifest.js +1 -1
  210. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route.js +1 -1
  211. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route.js.nft.json +1 -1
  212. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route_client-reference-manifest.js +1 -1
  213. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route.js +1 -1
  214. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route.js.nft.json +1 -1
  215. package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route_client-reference-manifest.js +1 -1
  216. package/.next/standalone/.next/server/app/api/projects/agent-cwd-options/route.js.nft.json +1 -1
  217. package/.next/standalone/.next/server/app/api/projects/agent-cwd-options/route_client-reference-manifest.js +1 -1
  218. package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
  219. package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
  220. package/.next/standalone/.next/server/app/api/proposals/[uuid]/approve/route_client-reference-manifest.js +1 -1
  221. package/.next/standalone/.next/server/app/api/proposals/[uuid]/close/route_client-reference-manifest.js +1 -1
  222. package/.next/standalone/.next/server/app/api/proposals/[uuid]/reject/route_client-reference-manifest.js +1 -1
  223. package/.next/standalone/.next/server/app/api/proposals/[uuid]/revoke/route_client-reference-manifest.js +1 -1
  224. package/.next/standalone/.next/server/app/api/proposals/[uuid]/route_client-reference-manifest.js +1 -1
  225. package/.next/standalone/.next/server/app/api/references/[uuid]/route_client-reference-manifest.js +1 -1
  226. package/.next/standalone/.next/server/app/api/references/route_client-reference-manifest.js +1 -1
  227. package/.next/standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
  228. package/.next/standalone/.next/server/app/api/session/route_client-reference-manifest.js +1 -1
  229. package/.next/standalone/.next/server/app/api/sessions/[uuid]/route.js +1 -1
  230. package/.next/standalone/.next/server/app/api/sessions/[uuid]/route.js.nft.json +1 -1
  231. package/.next/standalone/.next/server/app/api/sessions/[uuid]/route_client-reference-manifest.js +1 -1
  232. package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route.js +1 -1
  233. package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route.js.nft.json +1 -1
  234. package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route_client-reference-manifest.js +1 -1
  235. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route.js +1 -1
  236. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route.js.nft.json +1 -1
  237. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route_client-reference-manifest.js +1 -1
  238. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route.js +1 -1
  239. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route.js.nft.json +1 -1
  240. package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route_client-reference-manifest.js +1 -1
  241. package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route.js +1 -1
  242. package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route.js.nft.json +1 -1
  243. package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route_client-reference-manifest.js +1 -1
  244. package/.next/standalone/.next/server/app/api/tasks/[uuid]/route.js +1 -1
  245. package/.next/standalone/.next/server/app/api/tasks/[uuid]/route.js.nft.json +1 -1
  246. package/.next/standalone/.next/server/app/api/tasks/[uuid]/route_client-reference-manifest.js +1 -1
  247. package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route.js +1 -1
  248. package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route.js.nft.json +1 -1
  249. package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route_client-reference-manifest.js +1 -1
  250. package/.next/standalone/.next/server/app/index.html +2 -2
  251. package/.next/standalone/.next/server/app/index.rsc +1 -1
  252. package/.next/standalone/.next/server/app/login/admin/page_client-reference-manifest.js +1 -1
  253. package/.next/standalone/.next/server/app/login/admin.html +2 -2
  254. package/.next/standalone/.next/server/app/login/admin.rsc +1 -1
  255. package/.next/standalone/.next/server/app/login/callback/page_client-reference-manifest.js +1 -1
  256. package/.next/standalone/.next/server/app/login/callback.html +2 -2
  257. package/.next/standalone/.next/server/app/login/callback.rsc +1 -1
  258. package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  259. package/.next/standalone/.next/server/app/login/pick-workspace/page_client-reference-manifest.js +1 -1
  260. package/.next/standalone/.next/server/app/login/pick-workspace.html +2 -2
  261. package/.next/standalone/.next/server/app/login/pick-workspace.rsc +1 -1
  262. package/.next/standalone/.next/server/app/login.html +2 -2
  263. package/.next/standalone/.next/server/app/login.rsc +1 -1
  264. package/.next/standalone/.next/server/app/onboarding/page.js +2 -2
  265. package/.next/standalone/.next/server/app/onboarding/page.js.nft.json +1 -1
  266. package/.next/standalone/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
  267. package/.next/standalone/.next/server/app/onboarding.html +2 -2
  268. package/.next/standalone/.next/server/app/onboarding.rsc +2 -2
  269. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  270. package/.next/standalone/.next/server/app/projects.html +2 -2
  271. package/.next/standalone/.next/server/app/projects.rsc +2 -2
  272. package/.next/standalone/.next/server/app/settings.html +2 -2
  273. package/.next/standalone/.next/server/app/settings.rsc +3 -3
  274. package/.next/standalone/.next/server/app-paths-manifest.json +53 -53
  275. package/.next/standalone/.next/server/chunks/{5205.js → 1114.js} +1 -1
  276. package/.next/standalone/.next/server/chunks/1318.js +1 -1
  277. package/.next/standalone/.next/server/chunks/1437.js +1 -0
  278. package/.next/standalone/.next/server/chunks/1559.js +2 -2
  279. package/.next/standalone/.next/server/chunks/2572.js +1 -1
  280. package/.next/standalone/.next/server/chunks/2961.js +1 -1
  281. package/.next/standalone/.next/server/chunks/{9793.js → 3045.js} +1 -1
  282. package/.next/standalone/.next/server/chunks/3831.js +37 -0
  283. package/.next/standalone/.next/server/chunks/4827.js +1 -1
  284. package/.next/standalone/.next/server/chunks/5245.js +1 -1
  285. package/.next/standalone/.next/server/chunks/{4394.js → 5706.js} +1 -1
  286. package/.next/standalone/.next/server/chunks/6113.js +1 -1
  287. package/.next/standalone/.next/server/chunks/6207.js +1 -1
  288. package/.next/standalone/.next/server/chunks/6515.js +2 -2
  289. package/.next/standalone/.next/server/chunks/679.js +1 -1
  290. package/.next/standalone/.next/server/chunks/7368.js +1 -1
  291. package/.next/standalone/.next/server/chunks/7530.js +1 -1
  292. package/.next/standalone/.next/server/chunks/8454.js +1 -1
  293. package/.next/standalone/.next/server/chunks/920.js +1 -1
  294. package/.next/standalone/.next/server/chunks/9213.js +1 -1
  295. package/.next/standalone/.next/server/chunks/9378.js +1 -1
  296. package/.next/standalone/.next/server/chunks/9449.js +1 -0
  297. package/.next/standalone/.next/server/chunks/9458.js +1 -0
  298. package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
  299. package/.next/standalone/.next/server/middleware-manifest.json +5 -5
  300. package/.next/standalone/.next/server/pages/404.html +2 -2
  301. package/.next/standalone/.next/server/pages/500.html +1 -1
  302. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  303. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  304. package/.next/standalone/.next/static/chunks/{11595.a6268c75ca8a2163.js → 11595.bbe40924d18958bf.js} +1 -1
  305. package/.next/standalone/.next/static/chunks/18139-e6ef4b5869593f8e.js +1 -0
  306. package/.next/standalone/.next/static/chunks/28856-ef2cb58fbd404ef9.js +1 -0
  307. package/.next/standalone/.next/static/chunks/{31308-fda6febfb2882a28.js → 31308-bb4a97b3f39c22dd.js} +1 -1
  308. package/.next/standalone/.next/static/chunks/{33456.16ff7edf00137539.js → 33456.5499eb8e892b110a.js} +1 -1
  309. package/.next/standalone/.next/static/chunks/{4860.9e06848eb531e667.js → 4860.be77046fb2b3a2bd.js} +1 -1
  310. package/.next/standalone/.next/static/chunks/66873-e3be53f41b3f2255.js +1 -0
  311. package/.next/standalone/.next/static/chunks/70303-aec3d52ad87602a3.js +1 -0
  312. package/.next/standalone/.next/static/chunks/76201-83b26515f85ce37c.js +1 -0
  313. package/.next/standalone/.next/static/chunks/78917-a8a8dff98857c045.js +1 -0
  314. package/.next/standalone/.next/static/chunks/97663-9c3ae4fd60b353db.js +1 -0
  315. package/.next/standalone/.next/static/chunks/{99373.81b79c91858f9099.js → 99373.111493dc260a2a04.js} +1 -1
  316. package/.next/standalone/.next/static/chunks/app/(dashboard)/{layout-b742c51c0a764daf.js → layout-40fe7d026c5a7c6d.js} +1 -1
  317. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/dashboard/page-87d4d0fe90fca28c.js +1 -0
  318. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-1206abaee85dc915.js +1 -0
  319. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/{page-425acbe9ade5fa83.js → page-474e494097c8945f.js} +1 -1
  320. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/graph/page-e902b19328092ccf.js +1 -0
  321. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-f273288c3530aa0f.js +1 -0
  322. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/new/page-6568a7b08bf9a54b.js +1 -0
  323. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/page-fbd3c27b68666234.js +1 -0
  324. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/{page-58b48aa0a11603c3.js → page-15bb6e1696668512.js} +1 -1
  325. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/{page-286faced32c6133f.js → page-2bea97214b1595cc.js} +1 -1
  326. package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-2bf7ceee62b574c7.js +1 -0
  327. package/.next/standalone/.next/static/chunks/app/onboarding/{page-5c82cf3abd856301.js → page-540da64d7ba16dc7.js} +1 -1
  328. package/.next/standalone/.next/static/chunks/{webpack-4d1cc14b13e247b6.js → webpack-7cbb3ba6792f1fb3.js} +1 -1
  329. package/.next/standalone/package.json +1 -1
  330. package/.next/standalone/public/chorus-plugin/.claude-plugin/plugin.json +1 -1
  331. package/.next/standalone/public/chorus-plugin/bin/chorus-api.sh +44 -1
  332. package/.next/standalone/public/chorus-plugin/bin/on-session-start.sh +4 -3
  333. package/.next/standalone/public/chorus-plugin/bin/tests/test-mcp-cli-delegation.sh +244 -0
  334. package/.next/standalone/public/chorus-plugin/skills/brainstorm/SKILL.md +1 -1
  335. package/.next/standalone/public/chorus-plugin/skills/chorus/SKILL.md +19 -1
  336. package/.next/standalone/public/chorus-plugin/skills/chorus-cli/SKILL.md +57 -0
  337. package/.next/standalone/public/chorus-plugin/skills/develop/SKILL.md +2 -2
  338. package/.next/standalone/public/chorus-plugin/skills/docs/SKILL.md +1 -1
  339. package/.next/standalone/public/chorus-plugin/skills/idea/SKILL.md +1 -1
  340. package/.next/standalone/public/chorus-plugin/skills/openspec-aware/SKILL.md +85 -42
  341. package/.next/standalone/public/chorus-plugin/skills/orchestrate/SKILL.md +1 -1
  342. package/.next/standalone/public/chorus-plugin/skills/proposal/SKILL.md +2 -2
  343. package/.next/standalone/public/chorus-plugin/skills/quick-dev/SKILL.md +1 -1
  344. package/.next/standalone/public/chorus-plugin/skills/review/SKILL.md +1 -1
  345. package/.next/standalone/public/chorus-plugin/skills/yolo/SKILL.md +3 -3
  346. package/.next/standalone/public/dsh-credentials.sh +20 -127
  347. package/.next/standalone/public/install-codex.sh +21 -406
  348. package/.next/standalone/public/install-kiro.sh +20 -344
  349. package/.next/standalone/public/install-opencode.sh +20 -275
  350. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-brainstorm/SKILL.md +1 -1
  351. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-cli/SKILL.md +57 -0
  352. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-develop/SKILL.md +2 -2
  353. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-docs/SKILL.md +1 -1
  354. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-idea/SKILL.md +1 -1
  355. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-openspec-aware/SKILL.md +85 -42
  356. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-orchestrate/SKILL.md +1 -1
  357. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-proposal/SKILL.md +2 -2
  358. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-quick-dev/SKILL.md +1 -1
  359. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-review/SKILL.md +1 -1
  360. package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-yolo/SKILL.md +3 -3
  361. package/.next/standalone/public/kiro-plugin/bin/chorus-api.sh +44 -1
  362. package/.next/standalone/public/kiro-plugin/bin/on-agent-spawn.sh +6 -4
  363. package/.next/standalone/public/kiro-plugin/manifest.txt +41 -0
  364. package/.next/standalone/public/skill/brainstorm-chorus/SKILL.md +1 -1
  365. package/.next/standalone/public/skill/chorus/SKILL.md +19 -1
  366. package/.next/standalone/public/skill/code-reviewer-chorus/SKILL.md +1 -1
  367. package/.next/standalone/public/skill/develop-chorus/SKILL.md +1 -1
  368. package/.next/standalone/public/skill/docs-chorus/SKILL.md +1 -1
  369. package/.next/standalone/public/skill/idea-chorus/SKILL.md +1 -1
  370. package/.next/standalone/public/skill/orchestrate-chorus/SKILL.md +1 -1
  371. package/.next/standalone/public/skill/proposal-chorus/SKILL.md +1 -1
  372. package/.next/standalone/public/skill/proposal-reviewer-chorus/SKILL.md +1 -1
  373. package/.next/standalone/public/skill/quick-dev-chorus/SKILL.md +1 -1
  374. package/.next/standalone/public/skill/review-chorus/SKILL.md +1 -1
  375. package/.next/standalone/public/skill/task-reviewer-chorus/SKILL.md +1 -1
  376. package/.next/standalone/public/skill/yolo-chorus/SKILL.md +1 -1
  377. package/.next/standalone/public/test-dsh-credentials.sh +22 -38
  378. package/.next/standalone/public/test-install-codex.sh +31 -79
  379. package/README.ja.md +2 -2
  380. package/README.ko.md +2 -2
  381. package/README.md +2 -2
  382. package/README.zh.md +2 -2
  383. package/chorus.mjs +35 -1
  384. package/cli/agent-backend-prompt.mjs +3 -2
  385. package/cli/agents.mjs +329 -0
  386. package/cli/chorus-client.mjs +69 -0
  387. package/cli/claude-spawner.mjs +4 -0
  388. package/cli/codex-spawner.mjs +11 -6
  389. package/cli/credentials.mjs +185 -3
  390. package/cli/daemon-agent.mjs +26 -2
  391. package/cli/daemon-config.mjs +27 -2
  392. package/cli/daemon-service.mjs +120 -33
  393. package/cli/daemon.mjs +128 -22
  394. package/cli/dsh-spawner.mjs +7 -0
  395. package/cli/init/adapters.mjs +137 -0
  396. package/cli/init/agent-type-map.mjs +60 -0
  397. package/cli/init/chorus-plugin-consts.mjs +16 -0
  398. package/cli/init/codex-mcp-config.mjs +183 -0
  399. package/cli/init/contracts.mjs +120 -0
  400. package/cli/init/detect.mjs +97 -0
  401. package/cli/init/file-template.mjs +248 -0
  402. package/cli/init/install-methods.mjs +508 -0
  403. package/cli/init/registry.mjs +74 -0
  404. package/cli/init/run-command.mjs +30 -0
  405. package/cli/init/select.mjs +111 -0
  406. package/cli/init/steps/credential-seed.mjs +751 -0
  407. package/cli/init/steps/daemon-setup.mjs +246 -0
  408. package/cli/init/steps/plugin-install.mjs +37 -0
  409. package/cli/init-args.mjs +137 -0
  410. package/cli/init.mjs +198 -0
  411. package/cli/kiro-spawner.mjs +4 -0
  412. package/cli/mcp-args.mjs +280 -0
  413. package/cli/mcp.mjs +164 -0
  414. package/cli/spawner-select.mjs +45 -2
  415. package/package.json +1 -1
  416. package/.next/standalone/.next/server/chunks/3594.js +0 -1
  417. package/.next/standalone/.next/server/chunks/5351.js +0 -33
  418. package/.next/standalone/.next/server/chunks/6667.js +0 -1
  419. package/.next/standalone/.next/server/chunks/6995.js +0 -1
  420. package/.next/standalone/.next/static/chunks/19887-b805e1dcee8c367b.js +0 -1
  421. package/.next/standalone/.next/static/chunks/29108-5a11eea003f4cc11.js +0 -1
  422. package/.next/standalone/.next/static/chunks/53073-a7ed20af6538a178.js +0 -1
  423. package/.next/standalone/.next/static/chunks/6603-e70ddeab6ad09c50.js +0 -1
  424. package/.next/standalone/.next/static/chunks/78917-1b59cbb806b3ecfc.js +0 -1
  425. package/.next/standalone/.next/static/chunks/82751-3e161e1d8dbda3ac.js +0 -1
  426. package/.next/standalone/.next/static/chunks/99366-425e9ef22e60e3e2.js +0 -1
  427. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/dashboard/page-f636e00c28f425ea.js +0 -1
  428. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-c004f1a194af7fa5.js +0 -1
  429. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/graph/page-fdd617457730a116.js +0 -1
  430. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-b9eb4e0692996657.js +0 -1
  431. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/new/page-d5b222f379b2e8ca.js +0 -1
  432. package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/page-0a6c2d0e1b68e0e4.js +0 -1
  433. package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-1507a761e67c2aa9.js +0 -1
  434. /package/.next/standalone/.next/static/{6sHDgeKioa0SJR1MAbcYG → 0spgxl3lP26Fl1otd1D7R}/_buildManifest.js +0 -0
  435. /package/.next/standalone/.next/static/{6sHDgeKioa0SJR1MAbcYG → 0spgxl3lP26Fl1otd1D7R}/_ssgManifest.js +0 -0
@@ -17,8 +17,18 @@ import { readFileSync } from "node:fs";
17
17
  import { loginFilePath } from "./credentials.mjs";
18
18
 
19
19
  /** The agent backends the daemon recognizes. Existing spawners cover claude-code,
20
- * codex, and kiro; dsh registration is the base contract for its bridge. */
21
- export const KNOWN_AGENTS = ["claude-code", "codex", "kiro", "dsh"];
20
+ * codex, and kiro; dsh registration is the base contract for its bridge.
21
+ *
22
+ * `offline` is a NON-wakeable classification, not a real backend: an agent whose
23
+ * key is parked in daemon.json purely so `chorus mcp` can proxy through it, while
24
+ * the daemon builds NO spawner and dispatches NO wake for it. It is accepted here
25
+ * (and by-name in agent-backend-prompt via this list) so an agents[] entry may set
26
+ * `agentType: "offline"` and pass resolveAgentConfigs' KNOWN_AGENTS validation. The
27
+ * fail-closed no-wake handling lives in spawner-select.mjs (selectSpawner returns
28
+ * an OfflineSpawner that refuses to spawn) — an offline value MUST NOT fall through
29
+ * to the claude-code default and wake it. `chorus agents add` maps every non-wakeable
30
+ * selected agent (opencode/openclaw/pi/dsh) to this classification. */
31
+ export const KNOWN_AGENTS = ["claude-code", "codex", "kiro", "dsh", "offline"];
22
32
 
23
33
  /** The default agent backend when neither --agent nor CHORUS_AGENT is set. */
24
34
  export const DEFAULT_AGENT = "claude-code";
@@ -35,6 +45,11 @@ export function backendCli(agentType) {
35
45
  if (agentType === "codex") return { name: "codex", envVar: "CHORUS_CODEX_PATH" };
36
46
  if (agentType === "kiro") return { name: "kiro-cli", envVar: "CHORUS_KIRO_PATH" };
37
47
  if (agentType === "dsh") return { name: "dsh-jsonrpc-agent", envVar: "CHORUS_DSH_PATH" };
48
+ // `offline` has no CLI to resolve — it is never woken (see backendClientType).
49
+ // The daemon does not probe a binary for it; this explicit descriptor keeps the
50
+ // return sensible if some banner path ever reads it (CHORUS_AGENT selects the
51
+ // backend), instead of mislabeling it as `claude`.
52
+ if (agentType === "offline") return { name: "offline", envVar: "CHORUS_AGENT" };
38
53
  return { name: "claude", envVar: "CHORUS_CLAUDE_PATH" };
39
54
  }
40
55
 
@@ -50,6 +65,15 @@ export function backendClientType(agentType) {
50
65
  if (agentType === "codex") return "codex";
51
66
  if (agentType === "kiro") return "kiro";
52
67
  if (agentType === "dsh") return "dsh";
68
+ // `offline` is a non-wakeable classification — the daemon SHALL NOT register it
69
+ // as a wakeable connection (daemon-multi-agent spec). It must therefore NOT
70
+ // fall through to the `claude_code` default (which would make an offline agent
71
+ // present as a wakeable claude_code connection). Return the distinct `offline`
72
+ // string: the runtime fan-out skips registering it at all, and this value is
73
+ // intentionally OUTSIDE the server's DAEMON_CLIENT_TYPES allowlist, so any
74
+ // future path that DID try to register it fails closed (server rejects) rather
75
+ // than silently registering it as claude_code.
76
+ if (agentType === "offline") return "offline";
53
77
  return "claude_code";
54
78
  }
55
79
 
@@ -306,13 +306,19 @@ function positiveInt(value) {
306
306
  * @typedef {Object} AgentConfig One fully-resolved agent runtime config.
307
307
  * @property {string} url Chorus server URL for this agent.
308
308
  * @property {string} apiKey This agent's `cho_` API key.
309
- * @property {string} agentType Backend: claude-code | codex | kiro | dsh.
309
+ * @property {string} agentType Backend: claude-code | codex | kiro | dsh | offline.
310
+ * @property {boolean} [daemonWake] Wake opt-in for a wakeable backend; only
311
+ * `false` disables (absent/true ⇒ woken).
310
312
  * @property {Array<string|undefined>} cwds Served paths (`undefined` ⇒ process cwd).
311
313
  * @property {"yolo"|"chorus"} permissionMode Woken-agent permission posture.
312
314
  * @property {number} maxConcurrency This agent's wake-queue cap.
313
315
  * @property {number} sigintTimeoutMs Interrupt escalation window (ms).
314
316
  * @property {string[]} browseRoots Directory-discovery allowlist.
315
317
  * @property {string} label Diagnostic label ("agent" or "agents[i]").
318
+ * @property {string} [agentUuid] This agent's Chorus UUID — exported to a
319
+ * woken session as CHORUS_AGENT_PROFILE so its
320
+ * hooks/skills resolve the key from daemon.json.
321
+ * @property {string} [agentName] This agent's Chorus display name (profile alias).
316
322
  */
317
323
 
318
324
  /**
@@ -365,6 +371,8 @@ export function resolveAgentConfigs(flags = {}, deps = {}) {
365
371
  sigintTimeoutMs: resolveSigintTimeoutMs(flags, deps),
366
372
  browseRoots: resolveBrowseRoots(flags, deps),
367
373
  label: "agent",
374
+ agentUuid: nonEmptyStr(file?.agentUuid),
375
+ agentName: nonEmptyStr(file?.agentName),
368
376
  },
369
377
  ];
370
378
  }
@@ -433,6 +441,23 @@ export function resolveAgentConfigs(flags = {}, deps = {}) {
433
441
  const browseRoots =
434
442
  entry.browseRoots !== undefined ? cleanCwdList(entry.browseRoots, home) : defaultBrowseRoots;
435
443
 
436
- return { url, apiKey, agentType, cwds, permissionMode, maxConcurrency, sigintTimeoutMs, browseRoots, label };
444
+ // daemonWake: per-agent opt-in for daemon waking (pass-through boolean). Only
445
+ // `=== false` disables waking; absent (undefined) or true ⇒ woken, so agent
446
+ // entries written before this field existed keep being woken. Orthogonal to
447
+ // agentType (offline is never woken regardless).
448
+ return {
449
+ url,
450
+ apiKey,
451
+ agentType,
452
+ cwds,
453
+ permissionMode,
454
+ maxConcurrency,
455
+ sigintTimeoutMs,
456
+ browseRoots,
457
+ daemonWake: entry.daemonWake,
458
+ label,
459
+ agentUuid: nonEmptyStr(entry.agentUuid),
460
+ agentName: nonEmptyStr(entry.agentName),
461
+ };
437
462
  });
438
463
  }
@@ -35,6 +35,9 @@ import { fileURLToPath } from "node:url";
35
35
  /** The systemd --user unit name (also the launchd label stem). */
36
36
  export const SERVICE_NAME = "chorus-daemon";
37
37
 
38
+ /** The macOS launchd LaunchAgent label. */
39
+ export const LAUNCHD_LABEL = "com.chorus.daemon";
40
+
38
41
  /** Default IO bundle — overridable per-call for tests (no real disk/process). */
39
42
  function defaultIO() {
40
43
  return {
@@ -232,25 +235,39 @@ function systemdQuoteArg(token) {
232
235
 
233
236
  /**
234
237
  * Detect whether a supervisor already manages the chorus daemon on this host.
235
- * Linux only (systemd --user); everything else reports `{ kind: "none" }`.
236
- * - kind: "systemd" with installed (unit file present, `is-enabled` not
237
- * "not-found") and active (`is-active` == "active").
238
- * - kind: "none" otherwise (or when systemctl is unavailable).
238
+ * - Linux kind: "systemd" (unit file present and/or `is-active` == "active").
239
+ * - macOS → kind: "launchd" (LaunchAgent plist present and/or `launchctl list
240
+ * <label>` reports it loaded).
241
+ * - kind: "none" otherwise (or when the service manager is unavailable).
239
242
  * Used by the lifecycle subcommands to decide whether to delegate.
240
243
  * @param {object} [io]
241
- * @returns {{ kind: "systemd", installed: boolean, active: boolean, unitPath: string } | { kind: "none" }}
244
+ * @returns {{ kind: "systemd", installed: boolean, active: boolean, unitPath: string }
245
+ * | { kind: "launchd", installed: boolean, active: boolean, label: string, plistPath: string }
246
+ * | { kind: "none" }}
242
247
  */
243
248
  export function detectSupervisor(io = defaultIO()) {
244
- if (io.platform !== "linux") return { kind: "none" };
245
- const unitPath = systemdUnitPath(io);
246
- const installed = safeExists(unitPath, io);
247
- // `is-active` is authoritative for "running under systemd right now". Query it
248
- // even when the unit file is absent: a transient/unit-less path still returns
249
- // non-active, and we never want to throw here.
250
- const activeRes = systemctlUser(["is-active", `${SERVICE_NAME}.service`], io);
251
- const active = (activeRes.stdout ?? "").trim() === "active";
252
- if (!installed && !active) return { kind: "none" };
253
- return { kind: "systemd", installed, active, unitPath };
249
+ if (io.platform === "linux") {
250
+ const unitPath = systemdUnitPath(io);
251
+ const installed = safeExists(unitPath, io);
252
+ // `is-active` is authoritative for "running under systemd right now". Query it
253
+ // even when the unit file is absent: a transient/unit-less path still returns
254
+ // non-active, and we never want to throw here.
255
+ const activeRes = systemctlUser(["is-active", `${SERVICE_NAME}.service`], io);
256
+ const active = (activeRes.stdout ?? "").trim() === "active";
257
+ if (!installed && !active) return { kind: "none" };
258
+ return { kind: "systemd", installed, active, unitPath };
259
+ }
260
+ if (io.platform === "darwin") {
261
+ const plistPath = launchdPlistPath(io);
262
+ const installed = safeExists(plistPath, io);
263
+ // `launchctl list <label>` exits 0 when the agent is loaded (prints its dict),
264
+ // non-zero otherwise. This is authoritative for "loaded right now".
265
+ const listRes = launchctl(["list", LAUNCHD_LABEL], io);
266
+ const active = listRes.status === 0;
267
+ if (!installed && !active) return { kind: "none" };
268
+ return { kind: "launchd", installed, active, label: LAUNCHD_LABEL, plistPath };
269
+ }
270
+ return { kind: "none" };
254
271
  }
255
272
 
256
273
  function safeExists(path, io) {
@@ -281,6 +298,44 @@ export function journalctlUser(args, io = defaultIO()) {
281
298
  }
282
299
  }
283
300
 
301
+ /** Run `launchctl <args>`, capturing output. Never throws. macOS only. */
302
+ export function launchctl(args, io = defaultIO()) {
303
+ try {
304
+ const r = io.spawnSync("launchctl", args, { encoding: "utf8" });
305
+ // spawnSync sets .error (and status null) when the binary is missing (ENOENT);
306
+ // surface that as a null status + the error message rather than throwing.
307
+ if (r?.error) {
308
+ return { status: null, stdout: r?.stdout ?? "", stderr: String(r.error.message ?? r.error) };
309
+ }
310
+ return { status: r?.status ?? null, stdout: r?.stdout ?? "", stderr: r?.stderr ?? "" };
311
+ } catch (err) {
312
+ return { status: null, stdout: "", stderr: err instanceof Error ? err.message : String(err) };
313
+ }
314
+ }
315
+
316
+ /**
317
+ * Classify whether THIS host supports installing a real boot-autostart daemon
318
+ * service, and via which supervisor. The single source of truth both
319
+ * `chorus daemon install` and the `chorus agents add` daemon-setup step consult so they
320
+ * cannot disagree about what "supported" means (add-chorus-init-daemon-setup).
321
+ * - "systemd" — Linux where `systemctl --user` is usable.
322
+ * - "launchd" — macOS (launchctl is always present).
323
+ * - "unsupported" — Linux without a usable systemctl, Windows, or anything else.
324
+ * Pure-ish: only probes `systemctl --user --version` on Linux (injected IO).
325
+ * @param {object} [io]
326
+ * @returns {"systemd" | "launchd" | "unsupported"}
327
+ */
328
+ export function autostartCapability(io = defaultIO()) {
329
+ if (io.platform === "darwin") return "launchd";
330
+ if (io.platform === "linux") {
331
+ // `systemctl --user` must be reachable — a container/minimal host may lack it,
332
+ // in which case there is no real boot service we can install.
333
+ const probe = systemctlUser(["--version"], io);
334
+ return probe.status === 0 ? "systemd" : "unsupported";
335
+ }
336
+ return "unsupported";
337
+ }
338
+
284
339
  /**
285
340
  * Install the systemd --user unit (Linux) or return the template to print
286
341
  * (macOS/Windows). On Linux: write the unit, `daemon-reload`, `enable --now`.
@@ -331,19 +386,39 @@ export function installService(spec, io = defaultIO()) {
331
386
  }
332
387
  }
333
388
  if (io.platform === "darwin") {
389
+ // Real launchd install (add-chorus-init-daemon-setup): write the LaunchAgent
390
+ // plist and `launchctl load -w` it so it starts now and at every login —
391
+ // no longer a printed-template-only posture.
334
392
  const plistPath = launchdPlistPath(io);
335
393
  const unitText = renderLaunchdPlist({ ...spec, home, logPath: join(home, ".chorus", "daemon.log") });
336
- return {
337
- platform: "darwin",
338
- installed: false,
339
- unitPath: plistPath,
340
- unitText,
341
- steps: [
342
- `Save the plist below to ${plistPath}`,
343
- `launchctl load -w ${plistPath}`,
344
- `Check: launchctl list | grep com.chorus.daemon`,
345
- ],
346
- };
394
+ const steps = [];
395
+ try {
396
+ io.mkdirSync(dirname(plistPath), { recursive: true });
397
+ // Back up an existing plist before overwrite (backup-before-overwrite
398
+ // convention, mirrors the init plugin-install step); best-effort.
399
+ if (safeExists(plistPath, io) && typeof io.readFileSync === "function") {
400
+ try {
401
+ io.writeFileSync(`${plistPath}.chorus-bak`, io.readFileSync(plistPath));
402
+ steps.push(`backed up existing plist ${plistPath}.chorus-bak`);
403
+ } catch {
404
+ // a failed backup must not block the (idempotent) re-install
405
+ }
406
+ }
407
+ // Unload any currently-loaded copy first so a re-install applies the new
408
+ // plist rather than leaving the old agent running (parallels the systemd
409
+ // restart). Best-effort — a not-loaded agent returns non-zero here.
410
+ launchctl(["unload", plistPath], io);
411
+ io.writeFileSync(plistPath, unitText, { mode: 0o644 });
412
+ steps.push(`wrote ${plistPath}`);
413
+ const load = launchctl(["load", "-w", plistPath], io);
414
+ if (load.status !== 0) {
415
+ return { platform: "darwin", installed: false, unitPath: plistPath, unitText, steps, error: `launchctl load -w failed: ${load.stderr.trim() || `exit ${load.status}`}` };
416
+ }
417
+ steps.push(`launchctl load -w ${plistPath}`);
418
+ return { platform: "darwin", installed: true, unitPath: plistPath, unitText, steps };
419
+ } catch (err) {
420
+ return { platform: "darwin", installed: false, unitPath: plistPath, unitText, steps, error: err instanceof Error ? err.message : String(err) };
421
+ }
347
422
  }
348
423
  // Windows / other: no first-class service model without native deps. Print the
349
424
  // foreground command an operator can wrap in their supervisor of choice.
@@ -398,18 +473,30 @@ export function uninstallService(io = defaultIO()) {
398
473
  return { platform: "linux", removed: existed || disable.status === 0, unitPath, steps };
399
474
  }
400
475
  if (io.platform === "darwin") {
476
+ // Real launchd uninstall (add-chorus-init-daemon-setup): unload the agent and
477
+ // remove the plist. Idempotent: tolerate an already-absent plist / not-loaded
478
+ // agent.
401
479
  const plistPath = launchdPlistPath(io);
402
- return {
403
- platform: "darwin",
404
- removed: false,
405
- unitPath: plistPath,
406
- steps: [`launchctl unload -w ${plistPath}`, `rm ${plistPath}`],
407
- };
480
+ const steps = [];
481
+ const existed = safeExists(plistPath, io);
482
+ // unload -w stops the agent and clears its "enabled" override; a not-loaded
483
+ // agent returns non-zero, which we tolerate.
484
+ const unload = launchctl(["unload", "-w", plistPath], io);
485
+ if (unload.status === 0) steps.push(`launchctl unload -w ${plistPath}`);
486
+ try {
487
+ if (existed) {
488
+ io.unlinkSync(plistPath);
489
+ steps.push(`removed ${plistPath}`);
490
+ }
491
+ } catch (err) {
492
+ return { platform: "darwin", removed: false, unitPath: plistPath, steps, error: err instanceof Error ? err.message : String(err) };
493
+ }
494
+ return { platform: "darwin", removed: existed, unitPath: plistPath, steps };
408
495
  }
409
496
  return {
410
497
  platform: "other",
411
498
  removed: false,
412
- steps: ["Automatic service uninstall is only supported on Linux (systemd). Remove the daemon from your supervisor manually."],
499
+ steps: ["Automatic service uninstall is only supported on Linux (systemd) and macOS (launchd). Remove the daemon from your supervisor manually."],
413
500
  };
414
501
  }
415
502
 
package/cli/daemon.mjs CHANGED
@@ -31,6 +31,7 @@ import {
31
31
  yoloWarningLine,
32
32
  } from "./daemon-permission-mode.mjs";
33
33
  import { resolveAgentType, backendClientType } from "./daemon-agent.mjs";
34
+ import { isWakeableAgentType } from "./init/agent-type-map.mjs";
34
35
  import { formatBanner, agentNotFoundWarningLine } from "./daemon-banner.mjs";
35
36
  import { ChorusClient, validateAndFetchIdentity } from "./chorus-client.mjs";
36
37
  import { SseListener } from "./sse-listener.mjs";
@@ -75,6 +76,7 @@ import {
75
76
  uninstallService,
76
77
  systemctlUser,
77
78
  journalctlUser,
79
+ launchctl,
78
80
  resolveServicePaths,
79
81
  SERVICE_NAME,
80
82
  } from "./daemon-service.mjs";
@@ -633,6 +635,27 @@ export function buildMultiAgentDaemon(agentConfigs, deps = {}) {
633
635
 
634
636
  const agents = agentConfigs
635
637
  .map((cfg, i) => {
638
+ // Offline agents are proxy-only: their key is parked in daemon.json solely so
639
+ // `chorus mcp` can act under that identity (it reads the file directly, not via
640
+ // this runtime). The daemon-multi-agent spec says the daemon SHALL NOT construct
641
+ // a spawner, dispatch wakes, OR register it as a wakeable connection. Building a
642
+ // runtime here would open an SSE stream that self-reports a connection — so we
643
+ // SKIP the offline agent entirely (no runtime, no connection, no self-report),
644
+ // which is what closes the T4-review registration gap. Returning null (kept in
645
+ // step with a build failure) preserves the original index `i` for the per-agent
646
+ // injected-dep alignment below (map keeps the index; the filter drops the null).
647
+ // Skip = not woken: an offline backend (can't be woken) OR a wakeable backend
648
+ // the operator opted out of (`daemonWake: false`). Both get the same proxy-only
649
+ // treatment (no runtime/SSE/connection); the key stays in daemon.json for
650
+ // `chorus mcp`. `daemonWake` absent/true ⇒ woken (back-compat with entries that
651
+ // predate the field).
652
+ if (cfg.agentType === "offline" || cfg.daemonWake === false) {
653
+ const why = cfg.agentType === "offline" ? "offline backend" : "daemon waking disabled (daemonWake:false)";
654
+ logger.info?.(
655
+ `[Chorus] agent ${cfg.label}: ${why} — proxy-only key, no wakeable connection registered`,
656
+ );
657
+ return null;
658
+ }
636
659
  // Per-agent deps: cfg fields drive the per-agent runtime; injectable fakes are
637
660
  // indexed per agent. `cwd` (singular) is cleared so a caller's single value can
638
661
  // never leak across agents — each agent's `cwds` is authoritative.
@@ -655,7 +678,13 @@ export function buildMultiAgentDaemon(agentConfigs, deps = {}) {
655
678
  : deps.makeSseListener,
656
679
  };
657
680
  try {
658
- return { cfg, daemon: build({ url: cfg.url, apiKey: cfg.apiKey }, agentDeps) };
681
+ return {
682
+ cfg,
683
+ daemon: build(
684
+ { url: cfg.url, apiKey: cfg.apiKey, agentUuid: cfg.agentUuid, agentName: cfg.agentName },
685
+ agentDeps,
686
+ ),
687
+ };
659
688
  } catch (err) {
660
689
  logger.error?.(
661
690
  `[Chorus] agent ${cfg.label}: failed to build runtime — skipping ` +
@@ -667,6 +696,33 @@ export function buildMultiAgentDaemon(agentConfigs, deps = {}) {
667
696
  .filter(Boolean);
668
697
 
669
698
  if (agents.length === 0) {
699
+ // Distinguish "all offline" (nothing wakeable to serve — not an error) from
700
+ // "every wakeable runtime threw" (a real build failure). An all-offline config
701
+ // is a legitimate proxy-only setup: return an idle no-op daemon so the process
702
+ // stays up (its offline keys remain available to `chorus mcp`) rather than
703
+ // crashing with a misleading "all runtimes failed" error.
704
+ const anyWakeable = agentConfigs.some(
705
+ (cfg) => isWakeableAgentType(cfg.agentType) && cfg.daemonWake !== false,
706
+ );
707
+ if (!anyWakeable) {
708
+ logger.warn?.(
709
+ "[Chorus] all configured agents are offline — no daemon-wakeable backend to serve. " +
710
+ "Offline keys remain in daemon.json for `chorus mcp`; the daemon has nothing to wake.",
711
+ );
712
+ return {
713
+ agents: [],
714
+ connections: [],
715
+ // No wakeable connection was registered, so there are no back-compat aliases.
716
+ waker: undefined,
717
+ router: undefined,
718
+ sseListener: undefined,
719
+ // Never settles: an idle daemon simply waits (it registered no connection, so
720
+ // it can never be "all-conflicted"). runDaemon keeps it alive on waitForever.
721
+ allConflict: new Promise(() => {}),
722
+ async start() {},
723
+ async stop() {},
724
+ };
725
+ }
670
726
  throw new Error("buildMultiAgentDaemon: all agent runtimes failed to build");
671
727
  }
672
728
 
@@ -783,6 +839,7 @@ export async function runDaemon(flags = {}, deps = {}) {
783
839
  uninstallService,
784
840
  systemctlUser,
785
841
  journalctlUser,
842
+ launchctl,
786
843
  resolveServicePaths: () => resolveServicePaths(env),
787
844
  };
788
845
  // The preflight dep bundle — built from the same seams runDaemon resolved, so
@@ -860,6 +917,11 @@ export async function runDaemon(flags = {}, deps = {}) {
860
917
  for (const cfg of agentConfigs) {
861
918
  try {
862
919
  const id = await validate({ url: cfg.url, apiKey: cfg.apiKey });
920
+ // The validated identity is authoritative for the CHORUS_AGENT_PROFILE the
921
+ // spawner exports — fill from it when daemon.json omitted the field
922
+ // (resolveAgentConfigs already normalized these to a trimmed string | undefined).
923
+ cfg.agentUuid = cfg.agentUuid ?? id.uuid;
924
+ cfg.agentName = cfg.agentName ?? id.name;
863
925
  okConfigs.push(cfg);
864
926
  log(
865
927
  `[Chorus] agent ${cfg.label}: ${id.name} (${id.uuid}) — ${cfg.agentType}, ` +
@@ -998,7 +1060,11 @@ export async function runDaemon(flags = {}, deps = {}) {
998
1060
  }
999
1061
  log(`[Chorus] browse roots: ${browseRoots.join(", ")} (discovery only; no connections created)`);
1000
1062
 
1001
- const daemon = build(creds, {
1063
+ const daemon = build(
1064
+ // Export this agent's identity as CHORUS_AGENT_PROFILE in the woken session
1065
+ // (the validated identity is authoritative; creds may already carry it).
1066
+ { ...creds, agentUuid: creds.agentUuid ?? identity.uuid, agentName: creds.agentName ?? identity.name },
1067
+ {
1002
1068
  logger: { info: log, warn: errLog, error: errLog },
1003
1069
  permissionMode,
1004
1070
  agentType,
@@ -1118,11 +1184,13 @@ export async function preflight(ctx) {
1118
1184
  /**
1119
1185
  * Dispatch a daemon lifecycle subcommand. Two families:
1120
1186
  * - install / uninstall — manage the boot-autostart supervisor service
1121
- * (systemd --user on Linux; a printed template on macOS/Windows).
1187
+ * (systemd --user on Linux; launchd LaunchAgent on macOS; a printed template
1188
+ * on Windows/other).
1122
1189
  * - status / stop / restart / logs — when a supervisor unit is installed and
1123
- * active, DELEGATE to it (systemctl / journalctl) so a supervised daemon is
1124
- * never misreported as "not running"; otherwise operate on the
1125
- * pidfile/logfile-managed `-d` background daemon exactly as before.
1190
+ * active, DELEGATE to it (systemctl / journalctl on Linux, launchctl on
1191
+ * macOS) so a supervised daemon is never misreported as "not running";
1192
+ * otherwise operate on the pidfile/logfile-managed `-d` background daemon
1193
+ * exactly as before.
1126
1194
  * Each reports clearly (no silent failure). `restart` performs
1127
1195
  * stop-then-detached-start on the pidfile path.
1128
1196
  * @returns {Promise<number>} exit code
@@ -1239,21 +1307,26 @@ export async function handleLifecycleAction(action, { log, errLog, lifecycle, se
1239
1307
  for (const s of r.steps) log(`[Chorus] ${s}`);
1240
1308
  log(`[Chorus] it will now start automatically at login. Manage it with:`);
1241
1309
  log(`[Chorus] chorus daemon status | stop | restart | logs`);
1242
- // A --user service only survives logout with lingering enabled; and a
1243
- // separately-started `chorus daemon -d` would hold the same paths and make
1244
- // this service exit-and-retry. Surface both so neither is a silent gotcha.
1245
- log(`[Chorus] to keep it running after you log out: loginctl enable-linger "$USER"`);
1246
- log(`[Chorus] if you previously ran 'chorus daemon -d', stop it first ('chorus daemon stop') so it doesn't hold the same paths.`);
1310
+ if (r.platform === "linux") {
1311
+ // A --user service only survives logout with lingering enabled; and a
1312
+ // separately-started `chorus daemon -d` would hold the same paths and make
1313
+ // this service exit-and-retry. Surface both so neither is a silent gotcha.
1314
+ log(`[Chorus] to keep it running after you log out: loginctl enable-linger "$USER"`);
1315
+ log(`[Chorus] if you previously ran 'chorus daemon -d', stop it first ('chorus daemon stop') so it doesn't hold the same paths.`);
1316
+ } else if (r.platform === "darwin") {
1317
+ log(`[Chorus] if you previously ran 'chorus daemon -d', stop it first ('chorus daemon stop') so it doesn't hold the same paths.`);
1318
+ }
1247
1319
  return 0;
1248
1320
  }
1249
- if (r.platform === "linux") {
1250
- // Linux install actually failed (write / systemctl error) — surface it.
1321
+ if (r.platform === "linux" || r.platform === "darwin") {
1322
+ // A real install (systemd/launchd) actually failed — surface it, never a
1323
+ // silent success or a misleading "not supported" message.
1251
1324
  errLog(`[Chorus] service install failed: ${r.error}`);
1252
1325
  for (const s of r.steps) errLog(`[Chorus] (did: ${s})`);
1253
1326
  return 1;
1254
1327
  }
1255
- // macOS / Windows: not auto-installed by design — print the template + steps.
1256
- log(`[Chorus] automatic install is Linux-only. To run the daemon as a service on this platform:`);
1328
+ // Windows / other: no first-class auto-install — print the template + steps.
1329
+ log(`[Chorus] automatic install is not supported on this platform. To run the daemon as a service:`);
1257
1330
  for (const s of r.steps) log(`[Chorus] ${s}`);
1258
1331
  log("");
1259
1332
  log(r.unitText);
@@ -1261,7 +1334,7 @@ export async function handleLifecycleAction(action, { log, errLog, lifecycle, se
1261
1334
  }
1262
1335
  if (action === "uninstall") {
1263
1336
  const r = svc.uninstallService();
1264
- if (r.platform === "linux") {
1337
+ if (r.platform === "linux" || r.platform === "darwin") {
1265
1338
  if (r.error) {
1266
1339
  errLog(`[Chorus] service uninstall failed: ${r.error}`);
1267
1340
  return 1;
@@ -1274,22 +1347,32 @@ export async function handleLifecycleAction(action, { log, errLog, lifecycle, se
1274
1347
  }
1275
1348
  return 0;
1276
1349
  }
1277
- log(`[Chorus] automatic uninstall is Linux-only. To remove the service on this platform:`);
1350
+ log(`[Chorus] automatic uninstall is not supported on this platform. To remove the service:`);
1278
1351
  for (const s of r.steps) log(`[Chorus] ${s}`);
1279
1352
  return 0;
1280
1353
  }
1281
1354
 
1282
1355
  // For the control verbs, prefer a live supervisor unit over the pidfile.
1356
+ // A supervisor is systemd (Linux) or launchd (macOS); both delegate the verbs
1357
+ // to their service manager so a supervised daemon is never misreported as "not
1358
+ // running" via the pidfile.
1283
1359
  const sup = svc.detectSupervisor();
1284
- const supervised = sup.kind === "systemd" && sup.installed;
1360
+ const systemd = sup.kind === "systemd" && sup.installed;
1361
+ const launchd = sup.kind === "launchd" && sup.installed;
1285
1362
 
1286
1363
  if (action === "status") {
1287
- if (supervised) {
1364
+ if (systemd) {
1288
1365
  log(`[Chorus] daemon is managed by systemd (${SERVICE_NAME}.service) — ${sup.active ? "active" : "installed but NOT active"}.`);
1289
1366
  const r = svc.systemctlUser(["status", "--no-pager", `${SERVICE_NAME}.service`]);
1290
1367
  if (r.stdout) log(r.stdout.trimEnd());
1291
1368
  return sup.active ? 0 : 1;
1292
1369
  }
1370
+ if (launchd) {
1371
+ log(`[Chorus] daemon is managed by launchd (${sup.label}) — ${sup.active ? "loaded" : "installed but NOT loaded"}.`);
1372
+ const r = svc.launchctl(["list", sup.label]);
1373
+ if (r.stdout) log(r.stdout.trimEnd());
1374
+ return sup.active ? 0 : 1;
1375
+ }
1293
1376
  const s = lifecycle.isRunning();
1294
1377
  if (s.running) log(`[Chorus] daemon is running (pid ${s.pid}).`);
1295
1378
  else if (s.stale) log(`[Chorus] daemon is NOT running (stale pidfile for pid ${s.pid}).`);
@@ -1297,7 +1380,7 @@ export async function handleLifecycleAction(action, { log, errLog, lifecycle, se
1297
1380
  return 0;
1298
1381
  }
1299
1382
  if (action === "logs") {
1300
- if (supervised) {
1383
+ if (systemd) {
1301
1384
  const r = svc.journalctlUser(["-u", `${SERVICE_NAME}.service`, "--no-pager", "-n", "200"]);
1302
1385
  if (r.status !== 0 && !r.stdout) {
1303
1386
  errLog(`[Chorus] could not read the service journal: ${r.stderr.trim() || `exit ${r.status}`}`);
@@ -1306,6 +1389,8 @@ export async function handleLifecycleAction(action, { log, errLog, lifecycle, se
1306
1389
  log(r.stdout.trimEnd());
1307
1390
  return 0;
1308
1391
  }
1392
+ // launchd (and the pidfile path) both log to ~/.chorus/daemon.log — the plist
1393
+ // routes stdout/stderr there — so the pidfile logfile reader serves both.
1309
1394
  const r = lifecycle.readLog();
1310
1395
  if (!r.ok) {
1311
1396
  errLog(`[Chorus] ${r.message}`);
@@ -1315,7 +1400,7 @@ export async function handleLifecycleAction(action, { log, errLog, lifecycle, se
1315
1400
  return 0;
1316
1401
  }
1317
1402
  if (action === "stop") {
1318
- if (supervised) {
1403
+ if (systemd) {
1319
1404
  const r = svc.systemctlUser(["stop", `${SERVICE_NAME}.service`]);
1320
1405
  if (r.status === 0) {
1321
1406
  log(`[Chorus] stopped the daemon service (systemctl --user stop ${SERVICE_NAME}.service).`);
@@ -1325,6 +1410,16 @@ export async function handleLifecycleAction(action, { log, errLog, lifecycle, se
1325
1410
  errLog(`[Chorus] failed to stop the service: ${r.stderr.trim() || `exit ${r.status}`}`);
1326
1411
  return 1;
1327
1412
  }
1413
+ if (launchd) {
1414
+ const r = svc.launchctl(["unload", sup.plistPath]);
1415
+ if (r.status === 0) {
1416
+ log(`[Chorus] stopped the daemon service (launchctl unload ${sup.plistPath}).`);
1417
+ log(`[Chorus] note: it will load again at next login. To disable: chorus daemon uninstall`);
1418
+ return 0;
1419
+ }
1420
+ errLog(`[Chorus] failed to stop the service: ${r.stderr.trim() || `exit ${r.status}`}`);
1421
+ return 1;
1422
+ }
1328
1423
  // --force: unconditional pidfile cleanup for stuck states the identity
1329
1424
  // probe cannot resolve. Threaded from the parsed client flags.
1330
1425
  const r = lifecycle.stopDaemon({ force: pfDeps?.flags?.force === true });
@@ -1336,7 +1431,7 @@ export async function handleLifecycleAction(action, { log, errLog, lifecycle, se
1336
1431
  return ok ? 0 : 1;
1337
1432
  }
1338
1433
  if (action === "restart") {
1339
- if (supervised) {
1434
+ if (systemd) {
1340
1435
  const r = svc.systemctlUser(["restart", `${SERVICE_NAME}.service`]);
1341
1436
  if (r.status === 0) {
1342
1437
  log(`[Chorus] restarted the daemon service (systemctl --user restart ${SERVICE_NAME}.service).`);
@@ -1345,6 +1440,17 @@ export async function handleLifecycleAction(action, { log, errLog, lifecycle, se
1345
1440
  errLog(`[Chorus] failed to restart the service: ${r.stderr.trim() || `exit ${r.status}`}`);
1346
1441
  return 1;
1347
1442
  }
1443
+ if (launchd) {
1444
+ // launchd has no atomic restart — unload then load the same plist.
1445
+ svc.launchctl(["unload", sup.plistPath]);
1446
+ const r = svc.launchctl(["load", sup.plistPath]);
1447
+ if (r.status === 0) {
1448
+ log(`[Chorus] restarted the daemon service (launchctl unload+load ${sup.plistPath}).`);
1449
+ return 0;
1450
+ }
1451
+ errLog(`[Chorus] failed to restart the service: ${r.stderr.trim() || `exit ${r.status}`}`);
1452
+ return 1;
1453
+ }
1348
1454
  const r = lifecycle.stopDaemon();
1349
1455
  log(`[Chorus] ${r.message}`);
1350
1456
  // Start a fresh detached instance regardless of whether one was running.
@@ -187,6 +187,13 @@ export class DshSpawner {
187
187
  };
188
188
  if (this.creds?.url) childEnv.CHORUS_URL = this.creds.url;
189
189
  if (this.creds?.apiKey) childEnv.CHORUS_API_KEY = this.creds.apiKey;
190
+ // Identity profile — the dsh doc-mirror wrapper passes this to `chorus mcp
191
+ // --agent` (resolving the key from ~/.chorus/daemon.json). dsh scrubs
192
+ // credential-shaped env from tool subprocesses; the profile is not a secret,
193
+ // and the wrapper also reads it from $DSH_HOME/.env, so url/apiKey remain the
194
+ // reliable fallback when it doesn't survive.
195
+ if (this.creds?.agentUuid || this.creds?.agentName)
196
+ childEnv.CHORUS_AGENT_PROFILE = this.creds.agentUuid || this.creds.agentName;
190
197
 
191
198
  const { command, argv } = resolveDshSpawnCommand(dshPath, this.platform, childEnv);
192
199
  let child;