elanous 0.2.8 → 0.2.10

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 (385) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/8067-87ce253ec2f23697.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/{5080-1613752891fcadb4.js → 8195-6fde3d7a39859206.js} +5 -5
  14. package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-d4b6df905f185055.js → page-54b32bd27726588d.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/app/chat/{page-186fc6952f027acc.js → page-f8116559c7424da7.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/app/design-check/{page-cbbe03c0da7b081a.js → page-54e1f966ab60a4dc.js} +1 -1
  27. package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/app/market/{page-c0c0d19d51342d3e.js → page-b31610deda76337b.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-2e002ad8faa43291.js → page-6cb0e1bbefe5fb3d.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-7464c1987dd76e6d.js → page-e168fa1030af0548.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/app/showroom/{page-d8ab4d1489223459.js → page-4fddc90b23feb215.js} +1 -1
  51. package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +1 -0
  61. package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +1 -0
  62. package/apps/pwa/out/approvals/index.html +1 -1
  63. package/apps/pwa/out/approvals/index.txt +30 -29
  64. package/apps/pwa/out/autopilot/index.html +1 -1
  65. package/apps/pwa/out/autopilot/index.txt +30 -29
  66. package/apps/pwa/out/board/index.html +1 -1
  67. package/apps/pwa/out/board/index.txt +30 -29
  68. package/apps/pwa/out/botlab/index.html +1 -1
  69. package/apps/pwa/out/botlab/index.txt +27 -26
  70. package/apps/pwa/out/bots/index.html +1 -1
  71. package/apps/pwa/out/bots/index.txt +27 -26
  72. package/apps/pwa/out/chat/index.html +1 -1
  73. package/apps/pwa/out/chat/index.txt +27 -26
  74. package/apps/pwa/out/consult/index.html +1 -1
  75. package/apps/pwa/out/consult/index.txt +30 -29
  76. package/apps/pwa/out/control/index.html +1 -1
  77. package/apps/pwa/out/control/index.txt +30 -29
  78. package/apps/pwa/out/design-check/index.html +1 -1
  79. package/apps/pwa/out/design-check/index.txt +30 -29
  80. package/apps/pwa/out/editor/index.html +1 -1
  81. package/apps/pwa/out/editor/index.txt +30 -29
  82. package/apps/pwa/out/exec/index.html +1 -1
  83. package/apps/pwa/out/exec/index.txt +30 -29
  84. package/apps/pwa/out/field/index.html +1 -1
  85. package/apps/pwa/out/field/index.txt +30 -29
  86. package/apps/pwa/out/healthz +1 -1
  87. package/apps/pwa/out/index.html +1 -1
  88. package/apps/pwa/out/index.txt +27 -26
  89. package/apps/pwa/out/intake/index.html +1 -1
  90. package/apps/pwa/out/intake/index.txt +30 -29
  91. package/apps/pwa/out/live/index.html +1 -1
  92. package/apps/pwa/out/live/index.txt +30 -29
  93. package/apps/pwa/out/market/index.html +1 -1
  94. package/apps/pwa/out/market/index.txt +27 -26
  95. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  96. package/apps/pwa/out/missions/placeholder/index.txt +27 -26
  97. package/apps/pwa/out/morning/index.html +1 -1
  98. package/apps/pwa/out/morning/index.txt +30 -29
  99. package/apps/pwa/out/observatory/index.html +1 -1
  100. package/apps/pwa/out/observatory/index.txt +30 -29
  101. package/apps/pwa/out/ops/checklist/index.html +1 -0
  102. package/apps/pwa/out/ops/checklist/index.txt +30 -0
  103. package/apps/pwa/out/ops/release/index.html +1 -0
  104. package/apps/pwa/out/ops/release/index.txt +30 -0
  105. package/apps/pwa/out/ops/seats/index.html +1 -0
  106. package/apps/pwa/out/ops/seats/index.txt +30 -0
  107. package/apps/pwa/out/reflection/index.html +1 -1
  108. package/apps/pwa/out/reflection/index.txt +28 -27
  109. package/apps/pwa/out/scheduler/index.html +1 -1
  110. package/apps/pwa/out/scheduler/index.txt +30 -29
  111. package/apps/pwa/out/sessions/index.html +1 -1
  112. package/apps/pwa/out/sessions/index.txt +27 -26
  113. package/apps/pwa/out/settings/devices/index.html +1 -1
  114. package/apps/pwa/out/settings/devices/index.txt +30 -29
  115. package/apps/pwa/out/settings/index.html +1 -1
  116. package/apps/pwa/out/settings/index.txt +30 -29
  117. package/apps/pwa/out/setup/done/index.html +1 -1
  118. package/apps/pwa/out/setup/done/index.txt +30 -29
  119. package/apps/pwa/out/setup/index.html +1 -1
  120. package/apps/pwa/out/setup/index.txt +30 -29
  121. package/apps/pwa/out/share/index.html +1 -1
  122. package/apps/pwa/out/share/index.txt +30 -29
  123. package/apps/pwa/out/showroom/index.html +1 -1
  124. package/apps/pwa/out/showroom/index.txt +27 -26
  125. package/apps/pwa/out/tasks/index.html +1 -1
  126. package/apps/pwa/out/tasks/index.txt +30 -29
  127. package/apps/pwa/out/term/index.html +1 -1
  128. package/apps/pwa/out/term/index.txt +30 -29
  129. package/apps/pwa/out/today/index.html +1 -0
  130. package/apps/pwa/out/today/index.txt +33 -0
  131. package/apps/pwa/out/trace/index.html +1 -1
  132. package/apps/pwa/out/trace/index.txt +30 -29
  133. package/apps/pwa/out/vault/index.html +1 -1
  134. package/apps/pwa/out/vault/index.txt +30 -29
  135. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  136. package/apps/pwa/out/workflows/chat-ui/index.txt +30 -29
  137. package/apps/pwa/out/workflows/index.html +1 -1
  138. package/apps/pwa/out/workflows/index.txt +30 -29
  139. package/apps/pwa/out/workspace/index.html +1 -1
  140. package/apps/pwa/out/workspace/index.txt +30 -29
  141. package/apps/pwa/out/worktrees/index.html +1 -1
  142. package/apps/pwa/out/worktrees/index.txt +30 -29
  143. package/graphs/field/field-feed.yaml +2 -0
  144. package/graphs/implement-loop.yaml +1 -1
  145. package/graphs/release/recipes.yaml +3 -0
  146. package/graphs/release/release-loop.yaml +3 -1
  147. package/graphs/test-diet/nightly-audit.yaml +18 -0
  148. package/graphs/test-diet/recipes.yaml +3 -0
  149. package/package.json +1 -1
  150. package/plugins/card-followup/graphs/run-step.ts +48 -13
  151. package/plugins/doc-draft/graphs/doc-draft.yaml +3 -3
  152. package/plugins/doc-draft/graphs/run-step.ts +14 -7
  153. package/scripts/ci-pwa-build-gate.ts +160 -0
  154. package/scripts/coord-channel-watch.sh +42 -8
  155. package/scripts/coord-digest.ts +199 -0
  156. package/scripts/coord-post.sh +60 -3
  157. package/scripts/install.ps1 +68 -9
  158. package/scripts/install.sh +39 -12
  159. package/scripts/lib/pwa-scenarios/scenarios.ts +20 -0
  160. package/scripts/lib/tui-regress-checks.ts +146 -0
  161. package/scripts/memory-lifecycle-cycle.ts +2 -2
  162. package/scripts/ops-now-probe.ts +327 -0
  163. package/scripts/publish-internal-dist.ts +11 -1
  164. package/scripts/release-loop/cutoff.ts +31 -2
  165. package/scripts/release-loop/export-check-node.ts +85 -0
  166. package/scripts/release-loop/gate-node.ts +18 -4
  167. package/scripts/release-loop/node-verdict.ts +8 -1
  168. package/scripts/release-loop/ops-upgrade-node.ts +72 -16
  169. package/scripts/release-loop/release-readiness.ts +9 -0
  170. package/scripts/release-loop/version-node.ts +58 -10
  171. package/scripts/repo-watch-cycle.ts +1 -1
  172. package/scripts/retro-cycle.ts +2 -2
  173. package/scripts/schedule-health-report.ts +1 -1
  174. package/scripts/storyboard/storyboard.ts +5 -161
  175. package/scripts/test-diet/lib.ts +31 -1
  176. package/scripts/test-diet/node.ts +134 -17
  177. package/scripts/test-timeout-audit.ts +114 -0
  178. package/scripts/tree-sync-alert.ts +1 -1
  179. package/scripts/tui-regress.ts +71 -0
  180. package/scripts/waitlist-daily-digest.ts +1 -1
  181. package/skills/explainer-video/SKILL.md +4 -0
  182. package/skills/explainer-video/engine/reel.mjs +18 -13
  183. package/skills/explainer-video/engine/reel.sh +24 -5
  184. package/skills/explainer-video/engine/stitch.mjs +145 -0
  185. package/skills/pitch-deck/SKILL.md +36 -0
  186. package/skills/pitch-deck/template.html +80 -0
  187. package/src/acp/codex-approval-adapter.ts +9 -3
  188. package/src/acp/core-turn-bridge.ts +117 -18
  189. package/src/acp/fact-question.ts +11 -0
  190. package/src/acp/server.ts +48 -7
  191. package/src/acp/tool-approval.ts +126 -0
  192. package/src/acp/turn-runner.ts +36 -0
  193. package/src/agent/monad-agent-turn.ts +8 -0
  194. package/src/ask-user-question/pending-questions.ts +25 -10
  195. package/src/ask-user-question/types.ts +9 -0
  196. package/src/auth/setup-link-tokens.fixture.ts +19 -0
  197. package/src/auth/setup-link-tokens.ts +164 -0
  198. package/src/autopilot/build/integrity-gate.ts +12 -0
  199. package/src/boot/daemon-prompt-turn.ts +3 -0
  200. package/src/boot/daemon-tools/index.ts +8 -0
  201. package/src/boot/daemon-tools/types.ts +2 -0
  202. package/src/boot/daemon-tools/web-search.ts +1 -0
  203. package/src/budget/unified-usage.ts +75 -0
  204. package/src/channel-bot-token.ts +37 -10
  205. package/src/chat/ctrl-c-in-input.ts +14 -0
  206. package/src/chat/index.ts +61 -9
  207. package/src/chat/pickers/state.ts +6 -2
  208. package/src/cli/agent-cli.ts +7 -0
  209. package/src/cli/decisions-cli.ts +25 -3
  210. package/src/cli/doctor-bundle-upload.ts +68 -0
  211. package/src/cli/doctor-cli.ts +38 -4
  212. package/src/cli/op-proxy-sync.ts +83 -0
  213. package/src/cli/ops-cli.ts +20 -0
  214. package/src/cli/pod-cli.ts +49 -0
  215. package/src/cli/pr-cli.ts +37 -4
  216. package/src/cli/pwa-stop.ts +163 -13
  217. package/src/cli/pwa-test.ts +3 -0
  218. package/src/cli/release-cli.ts +98 -15
  219. package/src/cli/self-update.ts +14 -0
  220. package/src/cli/storyboard-cli.ts +37 -0
  221. package/src/cli/test-state-dir-flag.ts +11 -4
  222. package/src/connectors/linear.ts +146 -0
  223. package/src/context-bus/coord-events.ts +115 -0
  224. package/src/dashboard/dashboard-boot-fixture.ts +23 -0
  225. package/src/dashboard/dashboard-status-lines.ts +45 -0
  226. package/src/dashboard/first-screen-band.ts +35 -0
  227. package/src/dashboard/index.ts +128 -34
  228. package/src/dashboard/provider-slash-runtime.ts +28 -11
  229. package/src/dashboard/slash-runtime/dashboard-handlers.ts +17 -0
  230. package/src/dashboard/slash-runtime/help-from-registry.ts +43 -28
  231. package/src/dashboard/turn-stream-formatter.ts +1 -1
  232. package/src/decisions/decision-cards.ts +50 -2
  233. package/src/decisions/decision-ledger.ts +75 -4
  234. package/src/decisions/decision-linear-projection.ts +157 -0
  235. package/src/decisions/web-push-decision-cards.ts +50 -0
  236. package/src/directive/interpretation-card.ts +36 -0
  237. package/src/discord.ts +2 -1
  238. package/src/domains/coo-admin-tool.ts +62 -0
  239. package/src/domains/core-tools.ts +11 -3
  240. package/src/domains/elanous-card.ts +29 -0
  241. package/src/domains/ops-facts-tool.ts +76 -0
  242. package/src/domains/outbound-alert.ts +41 -13
  243. package/src/domains/release-tool.ts +168 -0
  244. package/src/domains/telegram-kind-route.ts +19 -1
  245. package/src/exec-requests/planner.ts +98 -28
  246. package/src/exec-requests/runner.ts +107 -10
  247. package/src/exec-requests/store.ts +8 -2
  248. package/src/field/field-media.ts +10 -7
  249. package/src/field/field-reel.ts +14 -4
  250. package/src/git-fs/worktree.ts +45 -6
  251. package/src/graph-runner/graph-approval-card.ts +113 -0
  252. package/src/graph-runner/graph-cli.ts +129 -4
  253. package/src/graph-runner/graph-notify.ts +25 -3
  254. package/src/graph-runner/runner.ts +142 -16
  255. package/src/harness/browser-verify.ts +25 -2
  256. package/src/harness/harness-cli-command.ts +231 -35
  257. package/src/harness/harness-incidents-writer.fixture.ts +24 -0
  258. package/src/harness/harness-incidents.ts +129 -0
  259. package/src/harness/harness-stop.ts +53 -3
  260. package/src/hitl/clarification-policy.ts +3 -1
  261. package/src/index.ts +172 -41
  262. package/src/intake-plane/author-goals.ts +37 -4
  263. package/src/intake-plane/check.ts +3 -0
  264. package/src/intake-plane/discord-seat-work.ts +47 -2
  265. package/src/intake-plane/seat-doc-route.ts +170 -6
  266. package/src/intake-plane/telegram-seat-work.ts +44 -2
  267. package/src/intake-plane/telegram-work.ts +1 -0
  268. package/src/maturity/cli-maturity.ts +34 -0
  269. package/src/maturity/feature-maturity.ts +100 -1
  270. package/src/maturity/tui-slash-maturity.ts +31 -0
  271. package/src/memory.ts +32 -4
  272. package/src/nexus/api/exec-requests.ts +33 -3
  273. package/src/nexus/api/http-server.ts +73 -1
  274. package/src/nexus/api/meta-api.ts +38 -0
  275. package/src/nexus/api/operator.ts +61 -0
  276. package/src/nexus/api/ops-api.ts +148 -0
  277. package/src/nexus/api/ops-seats-sources.ts +95 -0
  278. package/src/nexus/api/ops-seats.ts +124 -0
  279. package/src/nexus/api/public-routes.ts +14 -1
  280. package/src/nexus/api/seat-requests.ts +88 -8
  281. package/src/nexus/api/sessions-store.ts +63 -0
  282. package/src/nexus/api/setup-claim.ts +21 -0
  283. package/src/nexus/api/setup-codex-login.ts +160 -0
  284. package/src/nexus/api/usage-api.ts +102 -0
  285. package/src/nexus/config/secrets/file-backend.ts +56 -18
  286. package/src/nexus/index.ts +45 -4
  287. package/src/onboarding/first-run-doctor.ts +54 -0
  288. package/src/onboarding/first-run.ts +89 -0
  289. package/src/onboarding/lan-address.ts +45 -0
  290. package/src/onboarding/web-first.ts +119 -24
  291. package/src/onboarding.ts +4 -0
  292. package/src/ops-now/ops-now-refresh.ts +100 -0
  293. package/src/project/project-store.ts +115 -0
  294. package/src/release-loop/checklist.ts +76 -61
  295. package/src/release-loop/feature-store.ts +460 -0
  296. package/src/release-loop/manifest.ts +59 -5
  297. package/src/release-loop/release-schedule.ts +53 -0
  298. package/src/repl/index.ts +7 -0
  299. package/src/seat-dispatch/ceo-commands.ts +98 -0
  300. package/src/seat-dispatch/ceo-intent.ts +38 -0
  301. package/src/seat-loop/seat-loop.ts +231 -0
  302. package/src/seat-loop/seat-report.ts +64 -0
  303. package/src/self-dev/decompose.ts +66 -11
  304. package/src/self-dev/run-store.ts +10 -1
  305. package/src/self-implement/execution-clarification.ts +115 -0
  306. package/src/self-implement/gate-cli.ts +6 -3
  307. package/src/self-implement/orchestrator.ts +37 -3
  308. package/src/self-implement/pipeline-shape.ts +1 -1
  309. package/src/self-implement/run-status-mapping.ts +5 -3
  310. package/src/session/chat.ts +2 -0
  311. package/src/session/index.ts +9 -0
  312. package/src/shell-env-bootstrap.ts +17 -0
  313. package/src/skills/tools/usage-slash.ts +8 -7
  314. package/src/steward/directive.ts +51 -2
  315. package/src/steward/launch.ts +250 -0
  316. package/src/steward/outcome-notify.ts +115 -0
  317. package/src/steward/steward-cards.ts +8 -2
  318. package/src/steward/triage-plan.ts +32 -4
  319. package/src/steward/triage.ts +93 -9
  320. package/src/steward/working-backwards.ts +64 -0
  321. package/src/storyboard/storyboard.ts +141 -0
  322. package/src/task-cards/card-store.ts +2 -2
  323. package/src/task-orchestrator/surfaces/pod-lease.ts +260 -0
  324. package/src/telegram-card-followup.ts +233 -0
  325. package/src/telegram-commands.ts +16 -0
  326. package/src/telegram-report.ts +15 -9
  327. package/src/telegram-run.ts +90 -13
  328. package/src/telegram.ts +29 -8
  329. package/src/thinking-line.ts +28 -20
  330. package/src/tool-runtime/types.ts +4 -0
  331. package/src/tui/chat/execution-badge.ts +1 -1
  332. package/src/tui-client/dashboard-session.ts +2 -0
  333. package/src/user-config.ts +118 -11
  334. package/src/ux-sim/turn-states.ts +1 -1
  335. package/src/version/packed-revision.json +1 -1
  336. package/src/web-push/notify-exec-request.ts +32 -0
  337. package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +0 -1
  338. package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +0 -1
  339. package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +0 -1
  340. package/apps/pwa/out/_next/static/chunks/4836-3084c58c1725a40b.js +0 -1
  341. package/apps/pwa/out/_next/static/chunks/6090-85a3f05f954e5697.js +0 -1
  342. package/apps/pwa/out/_next/static/chunks/6284-69db415193d5f8bd.js +0 -1
  343. package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +0 -1
  344. package/apps/pwa/out/_next/static/chunks/7032-f4ef698518fba61c.js +0 -1
  345. package/apps/pwa/out/_next/static/chunks/8067-d976b441a104ab74.js +0 -1
  346. package/apps/pwa/out/_next/static/chunks/8519-5632377cce994f86.js +0 -1
  347. package/apps/pwa/out/_next/static/chunks/8894-7317998f6cb97d8c.js +0 -1
  348. package/apps/pwa/out/_next/static/chunks/9454-a3e0953307216c58.js +0 -1
  349. package/apps/pwa/out/_next/static/chunks/9740-8f5ff96c522b5f55.js +0 -1
  350. package/apps/pwa/out/_next/static/chunks/app/approvals/page-9aa47b0bc6d570ff.js +0 -1
  351. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f4d2ecbbae6088d6.js +0 -1
  352. package/apps/pwa/out/_next/static/chunks/app/board/page-2053e49930c82748.js +0 -1
  353. package/apps/pwa/out/_next/static/chunks/app/bots/page-a70ba27c33003dd0.js +0 -1
  354. package/apps/pwa/out/_next/static/chunks/app/consult/page-18166f885d831d3e.js +0 -1
  355. package/apps/pwa/out/_next/static/chunks/app/control/page-1c9d6cfe68b121c2.js +0 -1
  356. package/apps/pwa/out/_next/static/chunks/app/editor/page-c108ff1fdb665c97.js +0 -1
  357. package/apps/pwa/out/_next/static/chunks/app/exec/page-147a328753d983e2.js +0 -1
  358. package/apps/pwa/out/_next/static/chunks/app/field/page-799395a9df7d95aa.js +0 -1
  359. package/apps/pwa/out/_next/static/chunks/app/intake/page-6a8158b71d1fe9d7.js +0 -1
  360. package/apps/pwa/out/_next/static/chunks/app/layout-9567560270857531.js +0 -1
  361. package/apps/pwa/out/_next/static/chunks/app/live/page-e7ed3d010153d818.js +0 -1
  362. package/apps/pwa/out/_next/static/chunks/app/morning/page-b672e02e4bec8deb.js +0 -1
  363. package/apps/pwa/out/_next/static/chunks/app/not-found-1ba4a5d857276334.js +0 -1
  364. package/apps/pwa/out/_next/static/chunks/app/observatory/page-9db2226f38c542fb.js +0 -1
  365. package/apps/pwa/out/_next/static/chunks/app/page-70ee65f5f7a151dc.js +0 -1
  366. package/apps/pwa/out/_next/static/chunks/app/reflection/page-0bb8e43203efb23b.js +0 -1
  367. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-092e1bcf27d751cc.js +0 -1
  368. package/apps/pwa/out/_next/static/chunks/app/sessions/page-eb52580c4b75b905.js +0 -1
  369. package/apps/pwa/out/_next/static/chunks/app/settings/page-e573437b0a1c728f.js +0 -1
  370. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-294300625e49e4d3.js +0 -1
  371. package/apps/pwa/out/_next/static/chunks/app/setup/page-085847b088675978.js +0 -1
  372. package/apps/pwa/out/_next/static/chunks/app/share/page-9fe9d38c36999eb4.js +0 -1
  373. package/apps/pwa/out/_next/static/chunks/app/tasks/page-6141f67f531d8b6a.js +0 -1
  374. package/apps/pwa/out/_next/static/chunks/app/term/page-295a02b1026b8255.js +0 -1
  375. package/apps/pwa/out/_next/static/chunks/app/trace/page-1eb9a0e1e054209d.js +0 -1
  376. package/apps/pwa/out/_next/static/chunks/app/vault/page-82efa177a30f3741.js +0 -1
  377. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d0be51cec4f62606.js +0 -1
  378. package/apps/pwa/out/_next/static/chunks/app/workflows/page-2e367075ffdbc062.js +0 -1
  379. package/apps/pwa/out/_next/static/chunks/app/workspace/page-647ed2b66c1d49f1.js +0 -1
  380. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ba058c56e38f2792.js +0 -1
  381. package/apps/pwa/out/_next/static/chunks/main-app-6870f30ea99f8346.js +0 -1
  382. package/apps/pwa/out/_next/static/css/5ef72a618a8994f3.css +0 -1
  383. package/apps/pwa/out/_next/static/lywc8m_HDzH9MKSDQhyEj/_buildManifest.js +0 -1
  384. package/src/dashboard/turn-typeahead-echo.ts +0 -23
  385. /package/apps/pwa/out/_next/static/{lywc8m_HDzH9MKSDQhyEj → 2DsiDfDCks44g1cPUMhiW}/_ssgManifest.js +0 -0
package/src/index.ts CHANGED
@@ -96,6 +96,7 @@ applyTestFlagFromArgv();
96
96
  applyConfigDirFlagFromArgv();
97
97
 
98
98
  import { Command, Option } from 'commander';
99
+ import { filterCliRootHelp } from './maturity/cli-maturity.js';
99
100
  import type { AdPipelinePlan, AdPipelineResult } from './ad-pipeline/run.js';
100
101
  import type { AcpPermissionApprover } from './acp/client.js';
101
102
  import { runGitCommand } from './git-fs/runner.js';
@@ -122,7 +123,7 @@ import { DEFAULT_REVIEW_BACKEND } from './agent-substrate/acp-reviewer.js';
122
123
  import type { ReviewResult } from './agent-substrate/pr-reviewer.js';
123
124
  import type { ReviewVerdict } from './agent-mission/review-loop.js';
124
125
  import type { SyncMode } from './types.js';
125
- import { runOnboarding, runOnboardingStep, runOnboardingNonInteractive, needsOnboarding, handleOnboardingRefusal, type OnboardingStepId } from './onboarding.js';
126
+ import { runOnboarding, runOnboardingStep, runOnboardingNonInteractive, needsOnboarding, needsFirstRun, handleOnboardingRefusal, type OnboardingStepId } from './onboarding.js';
126
127
  import {
127
128
  getUserConfig, reloadUserConfig, userConfigPath, saveUserConfig,
128
129
  backupUserConfig, backupConfigPath, addRotationEntry, type RotationEntry,
@@ -137,6 +138,7 @@ import {
137
138
  } from './session/index.js';
138
139
  import { requestSessionTurnControl } from './session/session-turn-control.js';
139
140
  import { ensureCliSession, sessionBudget } from './session/chat.js';
141
+ import { suggestProjectForFolder } from './project/project-store.js';
140
142
  import { botFromConfig, TelegramBot } from './telegram.js';
141
143
  import { acquireTelegramLock, TelegramLockError, defaultLockPath, safeReadLock } from './telegram-lock.js';
142
144
  import { basename, join as _joinPath, resolve } from 'node:path';
@@ -865,6 +867,29 @@ registerUsageCommand(program);
865
867
  registerLiveCommands(program);
866
868
  registerResearchCommand(program);
867
869
  registerReleaseCommands(program);
870
+ const seatCmd = program.command('seat').description('분배된 자리의 하루 루프와 보고');
871
+ seatCmd.command('loop').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
872
+ .requiredOption('--once', '한 번 실행')
873
+ .option('--json', 'JSON 출력')
874
+ .action(async (opts: { seat: string; once: boolean; json?: boolean }) => {
875
+ try {
876
+ const { runSeatLoopOnce } = await import('./seat-loop/seat-loop.js');
877
+ const result = await runSeatLoopOnce(opts.seat);
878
+ if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
879
+ else console.log(`seat loop ${opts.seat}: ${result.status}${'runId' in result && result.runId ? ` ${result.runId}` : ''}`);
880
+ } catch (error) { console.error(`seat loop: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
881
+ });
882
+ seatCmd.command('report').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
883
+ .option('--post', '설정된 채널에 게시')
884
+ .option('--json', 'JSON 출력')
885
+ .action(async (opts: { seat: string; post?: boolean; json?: boolean }) => {
886
+ try {
887
+ const { seatReport } = await import('./seat-loop/seat-report.js');
888
+ const result = await seatReport(opts.seat, { post: opts.post });
889
+ if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
890
+ else console.log(result.body);
891
+ } catch (error) { console.error(`seat report: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
892
+ });
868
893
  registerModelWatchCommand(program);
869
894
  registerDoctorCommand(program);
870
895
  // runCli() → main() → program.parseAsync() dispatches control serve and resources where|list.
@@ -986,6 +1011,18 @@ linearCmd.command('set-key').description('Read Linear API key from stdin and sto
986
1011
  catch { console.error('connector.linear.apiKey: could not save key'); process.exitCode = 1; }
987
1012
  });
988
1013
 
1014
+ const storyboardCmd = program.command('storyboard').description('스토리보드 정본 검사 · MD 생성');
1015
+ storyboardCmd.command('lint').description('스토리보드 검사').argument('[files...]').option('--json', 'JSON 출력')
1016
+ .action(async (paths: string[], opts: { json?: boolean }) => {
1017
+ const { runStoryboard } = await import('./cli/storyboard-cli.js');
1018
+ process.exitCode = runStoryboard('lint', paths, opts.json);
1019
+ });
1020
+ storyboardCmd.command('render').description('스토리보드 검사 후 MD 생성').argument('[files...]')
1021
+ .action(async (paths: string[]) => {
1022
+ const { runStoryboard } = await import('./cli/storyboard-cli.js');
1023
+ process.exitCode = runStoryboard('render', paths);
1024
+ });
1025
+
989
1026
  const pythonCmd = program.command('python').description('elanous 가 쓰는 파이썬(해석 · 점검 · elanous venv 셋업) — RFC-doctor-fix-build-toolchain-and-python-by-distro');
990
1027
  pythonCmd.command('where').description('어느 파이썬을 쓰나(ELANOUS_PYTHON > elanous venv > pyenv .python-version > PATH)').option('--json').option('--path', '경로만 한 줄(스크립트·스킬용)').action(async (o: { json?: boolean; path?: boolean }) => {
991
1028
  const { runPythonWhere } = await import('./cli/python-cli.js'); process.exitCode = runPythonWhere(console, o.json, o.path);
@@ -1050,7 +1087,8 @@ program
1050
1087
  .option(
1051
1088
  '--test',
1052
1089
  '격리 테스트 인스턴스로 실행 — cwd 의 git 트리(worktree 포함)에서 `<트리>/.elanous-test` 를 루트로 잡고 state·config 두 축을 함께 격리한다. config 사본이 없으면 자동 물질화. `--test=<dir>` 로 루트 직접 지정 가능(값 문법은 `=` 형태 하나 — 모호함 없음). ELANOUS_STATE_DIR/--config-dir 을 손으로 줄 필요가 없다.',
1053
- );
1090
+ )
1091
+ .option('--help-all', '시스템 명령을 제외한 모든 최상위 명령 표시');
1054
1092
  program.addHelpText('after', acpServerHelpText());
1055
1093
 
1056
1094
  program
@@ -2120,13 +2158,13 @@ harnessCmd
2120
2158
  .option('--json', 'JSON 출력')
2121
2159
  .option('--dry-run', '프로세스 후보만 보고 신호·Pod Job 삭제는 하지 않는다')
2122
2160
  .action(async (runId: string, opts: { context?: string[]; json?: boolean; dryRun?: boolean }) => {
2123
- const { stopHarnessRun, defaultHarnessStopDeps, formatHarnessStop } = await import('./harness/harness-stop.js');
2161
+ const { stopHarnessRun, defaultHarnessStopDeps, formatHarnessStop, AmbiguousHarnessStopRunIdError } = await import('./harness/harness-stop.js');
2124
2162
  try {
2125
2163
  const result = await stopHarnessRun(runId, defaultHarnessStopDeps(), opts.context, opts.dryRun === true);
2126
2164
  process.stdout.write(`${opts.json ? JSON.stringify(result) : formatHarnessStop(result)}\n`);
2127
2165
  } catch (error) {
2128
2166
  process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
2129
- process.exitCode = 2;
2167
+ process.exitCode = error instanceof AmbiguousHarnessStopRunIdError ? 1 : 2;
2130
2168
  }
2131
2169
  });
2132
2170
  harnessCmd
@@ -2556,11 +2594,18 @@ harnessCmd
2556
2594
  const { verifyDeployedPage, formatVerifyUrlReport } = await import('./harness/browser-verify.js');
2557
2595
  const { writeFileSync } = await import('node:fs');
2558
2596
  let shotWritten = false;
2597
+ let shotWriteError: string | undefined;
2559
2598
  const r = await verifyDeployedPage(url, {
2560
2599
  backend: opts.backend,
2561
2600
  ...(opts.port ? { port: Number(opts.port) } : {}),
2562
2601
  // ⛔ 「썼다」를 «셋»으로 — 안 시켰다 / 썼다 / 못 썼다. 뭉치면 없는 파일을 있다고 말한다.
2563
- ...(opts.shot ? { onScreenshot: (b: Buffer) => { writeFileSync(opts.shot!, b); shotWritten = true; } } : {}),
2602
+ ...(opts.shot ? { onScreenshot: (b: Buffer) => {
2603
+ try { writeFileSync(opts.shot!, b); shotWritten = true; }
2604
+ catch (error) {
2605
+ shotWriteError = error instanceof Error ? error.message : String(error);
2606
+ if (opts.backend === 'aside') throw error;
2607
+ }
2608
+ } } : {}),
2564
2609
  });
2565
2610
  if (r.skipped === 'no-cdp') {
2566
2611
  console.log(`⚠️ CDP 엔드포인트 없음(9222) — 검증 skip. browser-debug 스킬로 브라우저를 9222 에 먼저 띄우세요.`);
@@ -2571,8 +2616,11 @@ harnessCmd
2571
2616
  return;
2572
2617
  }
2573
2618
  const L = formatVerifyUrlReport(url, r, opts.shot === undefined ? undefined : { path: opts.shot, written: shotWritten });
2619
+ if (opts.shot && !shotWritten && !r.skipped) {
2620
+ L.push(` - 스크린샷을 ${opts.shot} 에 못 썼다 — ${shotWriteError ?? (r.unmeasured?.includes('screenshot') ? '스크린샷을 못 쟀다' : '스크린샷 데이터가 오지 않았다')}`);
2621
+ }
2574
2622
  console.log(L.join('\n'));
2575
- if (!r.ok) process.exitCode = 1;
2623
+ if (!r.ok || (opts.shot && !shotWritten && !r.skipped)) process.exitCode = 1;
2576
2624
  } catch (e: any) {
2577
2625
  ui.error(`harness verify-url 실패: ${String(e?.message ?? e).slice(0, 200)}`);
2578
2626
  process.exitCode = 1;
@@ -2976,6 +3024,28 @@ const harnessOrchestrateCmd = registerHarnessOrchestrateCapabilityOptions(
2976
3024
  await runHarnessOrchestrateExecution(plan, parts);
2977
3025
  });
2978
3026
 
3027
+ const coordCmd = program.command('coord').description('조율 채널 맥락 원장');
3028
+ coordCmd.command('event').command('record')
3029
+ .requiredOption('--seat <ID>', '발신 자리')
3030
+ .requiredOption('--header <line>', '채널 글 첫 줄')
3031
+ .option('--url <url>', '채널 코멘트 URL')
3032
+ .action(async (opts: { seat: string; header: string; url?: string }) => {
3033
+ const { parseCoordHeader, recordCoordEvent } = await import('./context-bus/coord-events.js');
3034
+ recordCoordEvent({ ...parseCoordHeader(opts.seat, opts.header), url: opts.url || null });
3035
+ });
3036
+ coordCmd.command('events')
3037
+ .option('--since <ISO|2h>', '조회 시작', '2h')
3038
+ .option('--seat <ID>', '발신 자리')
3039
+ .option('--json', 'JSON 출력')
3040
+ .action(async (opts: { since: string; seat?: string; json?: boolean }) => {
3041
+ const { listCoordEvents } = await import('./context-bus/coord-events.js');
3042
+ const relative = /^(\d+)h$/.exec(opts.since);
3043
+ const since = relative ? new Date(Date.now() - Number(relative[1]) * 3_600_000).toISOString() : new Date(opts.since).toISOString();
3044
+ const rows = listCoordEvents({ since, ...(opts.seat ? { seat: opts.seat } : {}) });
3045
+ if (opts.json) await writeStdoutJson(JSON.stringify(rows) + '\n');
3046
+ else for (const row of rows) console.log(`${row.at} [${row.refs.seat}] ${row.text}`);
3047
+ });
3048
+
2979
3049
  const selfCmd = program.command('self').description('Self-awareness memory — 외부 도구(Claude Code/Codex)가 구현/변경 이력을 elanous 기억에 주입·회상');
2980
3050
 
2981
3051
  // M12 Claude Code 의존도 계기판 — `elanous self dependence [--since] [--until] [--json]`(읽기만).
@@ -6498,8 +6568,21 @@ const selfDevCmd = program
6498
6568
  if (devAskSubstrate?.substrate === 'pod') {
6499
6569
  const { dispatchHarnessOnPod } = await import('./harness/harness-pod-dispatch.js');
6500
6570
  const { devAskPodDispatchInput } = await import('./harness/harness-substrate-default.js');
6501
- const status = await dispatchHarnessOnPod(devAskPodDispatchInput(opts, askAuthoredFile!, devAskSubstrate.pool!));
6502
- if (status !== 0) console.error('Pod 실행에 닿지 못했다 — 풀·컨텍스트·SSH 연결을 확인하거나 `--substrate local` 로 명시하라');
6571
+ const { classifyHarnessPodExit, harnessPodRunId, recordClassifiedHarnessPodExit, warnRecentIncidentBurst } = await import('./harness/harness-cli-command.js');
6572
+ warnRecentIncidentBurst();
6573
+ let podOutput = '';
6574
+ let podRunId: string | undefined;
6575
+ const status = await dispatchHarnessOnPod(devAskPodDispatchInput(opts, askAuthoredFile!, devAskSubstrate.pool!), {
6576
+ onOutput: (text) => {
6577
+ podRunId ??= harnessPodRunId(podOutput + text);
6578
+ podOutput = (podOutput + text).slice(-16_000);
6579
+ },
6580
+ });
6581
+ if (status !== 0) {
6582
+ const classified = classifyHarnessPodExit({ status }, podOutput, { ...(podRunId ? { runId: podRunId } : {}) });
6583
+ recordClassifiedHarnessPodExit(podRunId ?? harnessPodRunId(podOutput), classified.reason, status);
6584
+ for (const line of classified.lines) console.error(line);
6585
+ }
6503
6586
  completionGuard.conclude();
6504
6587
  process.exit(status);
6505
6588
  }
@@ -7499,6 +7582,10 @@ sessionCmd
7499
7582
  const s = ensureCliSession(cfg);
7500
7583
  setActiveSessionId(s.id);
7501
7584
  ui.info(`Created session ${s.id.slice(0, 8)} (marked active).`);
7585
+ try {
7586
+ const project = suggestProjectForFolder(process.cwd());
7587
+ if (project) ui.info(`Project suggestion: ${project.name} (${project.id})`);
7588
+ } catch { /* suggestions must not interrupt session creation */ }
7502
7589
  });
7503
7590
 
7504
7591
  sessionCmd
@@ -7929,7 +8016,7 @@ sessionCmd
7929
8016
  });
7930
8017
 
7931
8018
  async function runFirstSetupForCli(cfg: ReturnType<typeof getUserConfig>, announceFallback = false): Promise<boolean> {
7932
- if (cfg.onboarding.webFirst === true) {
8019
+ if (cfg.onboarding.webFirst !== false) {
7933
8020
  const { runWebFirstSetup } = await import('./onboarding/web-first.js');
7934
8021
  if (await runWebFirstSetup({ config: cfg }) === 'link-shown') return false;
7935
8022
  if (announceFallback) ui.info('No config yet — launching setup wizard first.');
@@ -7972,7 +8059,7 @@ program
7972
8059
  if (opts.tools) announceChatToolsCompatibility();
7973
8060
  const cfg = getUserConfig();
7974
8061
  if (needsOnboarding(cfg)) {
7975
- if (cfg.onboarding.webFirst !== true) ui.info('No config yet — launching setup wizard first.');
8062
+ if (cfg.onboarding.webFirst === false) ui.info('No config yet — launching setup wizard first.');
7976
8063
  if (!await runFirstSetupForCli(cfg, true)) return;
7977
8064
  }
7978
8065
  const refreshed = reloadUserConfig();
@@ -8039,7 +8126,7 @@ program
8039
8126
  }
8040
8127
  const cfg = getUserConfig();
8041
8128
  if (needsOnboarding(cfg)) {
8042
- if (cfg.onboarding.webFirst !== true) ui.info('No config yet — launching setup wizard first.');
8129
+ if (cfg.onboarding.webFirst === false) ui.info('No config yet — launching setup wizard first.');
8043
8130
  if (!await runFirstSetupForCli(cfg, true)) return;
8044
8131
  }
8045
8132
  const refreshed = reloadUserConfig();
@@ -9281,24 +9368,50 @@ const nexusRunCmd = nexusCmd
9281
9368
  process.once('exit', () => releaseTestPort(resolvedPort, process.pid));
9282
9369
  }
9283
9370
  const { runNexus } = await import('./nexus/index.js');
9284
- await runNexus({
9285
- headless: true,
9286
- tools: toolsKind ?? 'webterm',
9287
- autoMountShare: !bgChild,
9288
- // bg-launch child reads `--watch` from forwardArgs (set by
9289
- // runPwaStart). External !TTY launches (launchd / Docker /
9290
- // nohup) get watch only when the user explicitly didn't disable
9291
- // it — service-manager production posture stays watch-off.
9292
- ...((bgChild ? opts.watch === true : watchOn) ? { pwaWatch: true } : {}),
9293
- ...(opts.mcp === false ? { mcpEnabled: false } : {}),
9294
- ...(opts.auth === false ? { noAuth: true } : {}),
9295
- ...(opts.force ? { force: true } : {}),
9296
- ...(opts.dispatch ? { dispatch: true } : {}),
9297
- ...(opts.toolCwd ? { toolCwd: opts.toolCwd } : {}),
9298
- ...(opts.historyDir ? { historyDir: opts.historyDir } : {}),
9299
- ...(resolvedHttpHost ? { httpHost: resolvedHttpHost } : {}),
9300
- ...(resolvedPort !== undefined ? { httpStartPort: resolvedPort } : {}),
9301
- });
9371
+ // Only isolated daemons force exit after SIGINT cleanup; production and
9372
+ // SIGTERM keep their existing service-manager lifecycle contracts.
9373
+ const isolatedDaemon = (await import('./instance/current.js')).resolveCurrentInstance().kind === 'test';
9374
+ let stoppedBySigint = false;
9375
+ let cleanupTimer: ReturnType<typeof setTimeout> | undefined;
9376
+ const onStop = () => {
9377
+ if (!isolatedDaemon) return;
9378
+ stoppedBySigint = true;
9379
+ cleanupTimer = setTimeout(() => {
9380
+ console.error('elanous nexus: SIGINT cleanup exceeded 8s; exiting');
9381
+ process.exit(1);
9382
+ }, 8_000);
9383
+ };
9384
+ if (isolatedDaemon) process.once('SIGINT', onStop);
9385
+ try {
9386
+ await runNexus({
9387
+ headless: true,
9388
+ tools: toolsKind ?? 'webterm',
9389
+ autoMountShare: !bgChild,
9390
+ // bg-launch child reads `--watch` from forwardArgs (set by
9391
+ // runPwaStart). External !TTY launches (launchd / Docker /
9392
+ // nohup) get watch only when the user explicitly didn't disable
9393
+ // it — service-manager production posture stays watch-off.
9394
+ ...((bgChild ? opts.watch === true : watchOn) ? { pwaWatch: true } : {}),
9395
+ ...(opts.mcp === false ? { mcpEnabled: false } : {}),
9396
+ ...(opts.auth === false ? { noAuth: true } : {}),
9397
+ ...(opts.force ? { force: true } : {}),
9398
+ ...(opts.dispatch ? { dispatch: true } : {}),
9399
+ ...(opts.toolCwd ? { toolCwd: opts.toolCwd } : {}),
9400
+ ...(opts.historyDir ? { historyDir: opts.historyDir } : {}),
9401
+ ...(resolvedHttpHost ? { httpHost: resolvedHttpHost } : {}),
9402
+ ...(resolvedPort !== undefined ? { httpStartPort: resolvedPort } : {}),
9403
+ });
9404
+ } catch (error) {
9405
+ if (stoppedBySigint) {
9406
+ console.error(`elanous nexus: SIGINT cleanup failed: ${error instanceof Error ? error.message : String(error)}`);
9407
+ process.exit(1);
9408
+ }
9409
+ throw error;
9410
+ } finally {
9411
+ process.removeListener('SIGINT', onStop);
9412
+ if (cleanupTimer) clearTimeout(cleanupTimer);
9413
+ }
9414
+ if (stoppedBySigint) process.exit(0);
9302
9415
  return;
9303
9416
  }
9304
9417
 
@@ -10114,10 +10227,14 @@ tokenCmd
10114
10227
  .description('Rotate the ACP admin token')
10115
10228
  .option('--grace-ms <ms>', 'Previous-token grace period in milliseconds', (value: string) => Number(value))
10116
10229
  .option('--show-token', 'Print the complete new token')
10117
- .action(async (opts: { graceMs?: number; showToken?: boolean }) => {
10230
+ .option('--sync-op-proxy', 'Update the configured op proxy bearer over SSH after rotation')
10231
+ .action(async (opts: { graceMs?: number; showToken?: boolean; syncOpProxy?: boolean }) => {
10118
10232
  if (opts.graceMs !== undefined && (!Number.isFinite(opts.graceMs) || opts.graceMs < 0)) {
10119
10233
  throw new Error('--grace-ms must be a non-negative finite number');
10120
10234
  }
10235
+ if (opts.syncOpProxy && opts.showToken) {
10236
+ throw new Error('--sync-op-proxy cannot be combined with --show-token');
10237
+ }
10121
10238
  const [{ rotateAdminToken }, { getElanousConfigDir }] = await Promise.all([
10122
10239
  import('./auth/token-store.js'),
10123
10240
  import('./elanous-config-dir.js'),
@@ -10128,9 +10245,17 @@ tokenCmd
10128
10245
  });
10129
10246
  if (opts.showToken) {
10130
10247
  console.log(result.newActive);
10131
- return;
10132
- }
10133
- console.log(`ACP admin token rotated: length=${result.newActive.length} prefix=${result.newActive.slice(0, 4)}`);
10248
+ } else {
10249
+ console.log(opts.syncOpProxy
10250
+ ? `ACP admin token rotated: length=${result.newActive.length}`
10251
+ : `ACP admin token rotated: length=${result.newActive.length} prefix=${result.newActive.slice(0, 4)}`);
10252
+ }
10253
+ const { readOpProxyConfig, finishOpProxyRotation } = await import('./cli/op-proxy-sync.js');
10254
+ finishOpProxyRotation(readOpProxyConfig(), result.newActive, {
10255
+ sync: opts.syncOpProxy === true,
10256
+ tokenFile: `${getElanousConfigDir()}/acp-token`,
10257
+ ...(opts.showToken ? { out: (line: string) => console.error(line) } : {}),
10258
+ });
10134
10259
  });
10135
10260
 
10136
10261
  const acpCmd = program.command('acp').description('Agent Client Protocol — spawn ACP agents (claude-code, codex, gemini)');
@@ -10727,18 +10852,24 @@ async function main(): Promise<void> {
10727
10852
  program.error(`error: unknown command '${firstCommand}'`);
10728
10853
  return;
10729
10854
  }
10730
- await program.parseAsync(['node', 'elanous', ...args]);
10855
+ const showAll = args[0] === '--help-all';
10856
+ const role = getUserConfig().cli?.helpRole ?? 'owner';
10857
+ const { shown, hidden } = filterCliRootHelp(program.commands, role, showAll);
10858
+ debug.log('cli.maturity', 'help-filtered', { role, shown, hidden });
10859
+ await program.parseAsync(['node', 'elanous', ...(showAll ? ['--help'] : args)]);
10731
10860
  return;
10732
10861
  }
10733
10862
 
10734
- // First-run: trigger the onboarding wizard before dropping into the
10735
- // dashboard so we don't need to handle half-configured state in the
10736
- // TUI chrome. Subsequent launches skip straight to the dashboard.
10737
- // (Bare `elanous` always lands on the dashboard now, so the wizard just
10738
- // gates on config completeness — no entry-mode branch.)
10863
+ // Bare entry only requires an LLM; detailed setup stays behind `eln setup`.
10864
+ const firstRunStartedAt = Date.now();
10739
10865
  const cfg = getUserConfig();
10740
- if (needsOnboarding(cfg)) {
10741
- if (!await runFirstSetupForCli(cfg)) return;
10866
+ if (needsFirstRun(cfg)) {
10867
+ if (cfg.onboarding.webFirst !== false) {
10868
+ const { runWebFirstSetup } = await import('./onboarding/web-first.js');
10869
+ if (await runWebFirstSetup({ config: cfg, startedAt: firstRunStartedAt }) === 'link-shown') return;
10870
+ }
10871
+ const { runFirstRun } = await import('./onboarding/first-run.js');
10872
+ if ((await runFirstRun({ config: cfg })).outcome !== 'ready') return;
10742
10873
  }
10743
10874
 
10744
10875
  // Active-provider banner so users know WHICH model/auth is about to
@@ -2,7 +2,8 @@
2
2
  * intake check → 골 저작 연결. 판정 「없음」마다 기존 골 중복을 먼저 보고, 없으면 골 저작기로 골 문서를 쓰고 lint 한 뒤 멈춘다.
3
3
  * 하니스는 발사하지 않는다. 골: 내부 문서 `ASK-intake-check-authors-goals-for-gaps-2026-09-24`
4
4
  */
5
- import { existsSync, readdirSync, readFileSync } from 'node:fs';
5
+ import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
6
+ import { CardStore, taskCardsDir } from '../task-cards/card-store.js';
6
7
  import { join, relative } from 'node:path';
7
8
  import { debug } from '../debug/log.js';
8
9
  import { resolveGoalDocumentsDir } from '../self-implement/goal-documents-dir.js';
@@ -42,7 +43,22 @@ function defaultGoalDocs(root: string): { path: string; text: string }[] {
42
43
  .map((name) => ({ path: relative(root, join(dir, name)), text: readFileSync(join(dir, name), 'utf8') }));
43
44
  }
44
45
 
45
- function authorAsk(item: IntakeCheckItem): string {
46
+ function prfaqSignals(sourceRef: string | undefined, root: string): { source: string; signals: string[] } | undefined {
47
+ if (!sourceRef?.startsWith('linear:') || !existsSync(taskCardsDir(root))) return undefined;
48
+ const store = new CardStore(root);
49
+ try {
50
+ const cards = store.listCards();
51
+ const matches = cards.filter(row => row.goalId === sourceRef);
52
+ const card = matches.length === 1 ? matches[0] : undefined;
53
+ const section = [...(card?.sections ?? [])].reverse().find(row => row.key.startsWith('prfaq:'));
54
+ if (!section) return undefined;
55
+ const criteria = section.content.split('⑧ 판정 기준')[1]?.split('⑨')[0] ?? '';
56
+ const signals = criteria.split('\n').map(line => line.trim().replace(/^-\s*/, '')).filter(line => /^판정 신호: 조건 = .+; 관측 = .+; 기대 = .+\.$/.test(line)).slice(0, 2);
57
+ return signals.length ? { source: `${card!.goalId} / ${section.key}`, signals } : undefined;
58
+ } finally { store.close(); }
59
+ }
60
+
61
+ function authorAsk(item: IntakeCheckItem, evidence?: { source: string; signals: string[] }): string {
46
62
  // The first line leads the ask and `제목:` is the title the author forwards (parseAskProseTitle), so both are the fact.
47
63
  return [
48
64
  item.fact,
@@ -52,9 +68,23 @@ function authorAsk(item: IntakeCheckItem): string {
52
68
  '백틱 이름은 대조에 쓴 검색 표지일 뿐이다 — 그 문자열이 저장소에 생기는 것을 판정 신호로 삼지 말고, 사실이 말하는 동작을 판정 신호로 쓴다.',
53
69
  `대조 결과: ${item.current}`,
54
70
  ...(item.quotes.length > 0 ? [`출처 인용: ${item.quotes.join(' / ')}`] : []),
71
+ ...(evidence ? [`아래 판정 신호를 골 문서 ## 판정 신호에 원문 그대로 인용하라. 출처: 카드 ${evidence.source}`, ...evidence.signals] : []),
55
72
  ].join('\n');
56
73
  }
57
74
 
75
+ function appendPrfaqSignals(document: string, evidence: { source: string; signals: string[] }): string {
76
+ const section = /^## 판정 신호\s*$/m.exec(document);
77
+ if (!section) throw new Error('Authored goal has no ## 판정 신호 section');
78
+ const start = section.index + section[0].length;
79
+ const end = document.slice(start).search(/^## /m);
80
+ const boundary = end < 0 ? document.length : start + end;
81
+ const block = document.slice(start, boundary);
82
+ const missing = evidence.signals.filter(signal => !block.includes(signal));
83
+ const source = block.includes(`출처: 카드 ${evidence.source}`) ? '' : `출처: 카드 ${evidence.source}\n`;
84
+ if (!missing.length && !source) return document;
85
+ return document.slice(0, boundary) + `\n${source}${missing.map(signal => `- ${signal}`).join('\n')}\n` + document.slice(boundary);
86
+ }
87
+
58
88
  export async function authorIntakeGoals(
59
89
  items: readonly IntakeCheckItem[],
60
90
  deps: IntakeAuthorDeps,
@@ -84,8 +114,11 @@ export async function authorIntakeGoals(
84
114
  }
85
115
  authored++;
86
116
  try {
87
- const written = await deps.author(authorAsk(item), `intake check: ${opts.source}`);
88
- const lintErrors = deps.lintErrors(written.document);
117
+ const evidence = prfaqSignals(item.sourceRef, deps.root);
118
+ const written = await deps.author(authorAsk(item, evidence), `intake check: ${opts.source}`);
119
+ const document = evidence ? appendPrfaqSignals(written.document, evidence) : written.document;
120
+ if (document !== written.document) writeFileSync(join(deps.root, written.path), document);
121
+ const lintErrors = deps.lintErrors(document);
89
122
  outcomes.push({ fact: item.fact, status: 'authored', goalPath: written.path, lintErrors });
90
123
  } catch (error) {
91
124
  outcomes.push({ fact: item.fact, status: 'author-failed', reason: error instanceof Error ? error.message : String(error) });
@@ -63,6 +63,8 @@ export interface IntakeCheckEvidence {
63
63
 
64
64
  export interface IntakeCheckItem {
65
65
  readonly fact: string;
66
+ /** Source identity preserved from the supplied fact for card-backed goal evidence. */
67
+ readonly sourceRef?: string;
66
68
  readonly originalClaims?: readonly string[];
67
69
  readonly quotes: readonly string[];
68
70
  readonly verdict: IntakeCheckVerdict;
@@ -1415,6 +1417,7 @@ export function runIntakeCheck(
1415
1417
  const item: IntakeCheckItem = {
1416
1418
  ...judged,
1417
1419
  quotes: [quote],
1420
+ ...(fact.sourceRef ? { sourceRef: fact.sourceRef } : {}),
1418
1421
  ...(fact.originalClaim ? { originalClaims: [fact.originalClaim] } : {}),
1419
1422
  };
1420
1423
  merged.set(key, item);
@@ -1,4 +1,11 @@
1
+ import { debug } from '../debug/log.js';
2
+ import { discordDecisionOwner } from '../decisions/discord-decision-cards.js';
3
+ import { canonicalSeatId } from '../msg/msg-store.js';
4
+ import { dispatchCeoTask, type CeoCommandDeps } from '../seat-dispatch/ceo-commands.js';
5
+ import { ceoTaskDeps, classifyCeoIntent } from '../seat-dispatch/ceo-intent.js';
1
6
  import { parseSeatAddress, resolveSeat } from '../seat-address/seat-address.js';
7
+ import { getUserConfig, type UserConfig } from '../user-config.js';
8
+ import { answerAsSeat } from './seat-answer.js';
2
9
  import {
3
10
  submitIntakeWork,
4
11
  type SubmitIntakeWorkDeps,
@@ -7,21 +14,47 @@ import {
7
14
  export interface DiscordSeatWorkMessage {
8
15
  channelId: string;
9
16
  messageId: string;
17
+ userId?: string;
18
+ isDm?: boolean;
10
19
  threadId?: string;
11
20
  }
12
21
 
13
22
  export interface DiscordSeatWorkDeps extends SubmitIntakeWorkDeps {
14
23
  submit?: typeof submitIntakeWork;
24
+ config?: UserConfig;
25
+ answer?: typeof answerAsSeat;
26
+ dispatch?: typeof dispatchCeoTask;
27
+ commandDeps?: CeoCommandDeps;
15
28
  }
16
29
 
17
- /** Addressed Discord work goes through the graph intake door, not the chat turn. */
30
+ /** Addressed work preserves graph intake except for one owner's private seat request. */
18
31
  export async function handleDiscordSeatWork(
19
32
  text: string,
20
33
  msg: DiscordSeatWorkMessage,
21
34
  deps: DiscordSeatWorkDeps = {},
22
35
  ): Promise<string | null> {
36
+ const owner = (): { cfg: UserConfig; id: string } | null => {
37
+ if (!msg.isDm || !msg.userId) return null;
38
+ const cfg = deps.config ?? getUserConfig();
39
+ const id = discordDecisionOwner(cfg);
40
+ return id && id === msg.userId ? { cfg, id } : null;
41
+ };
42
+ const sendTask = async (seat: string, body: string, cfg: UserConfig, id: string): Promise<string> => {
43
+ const result = await (deps.dispatch ?? dispatchCeoTask)(seat, body, deps.commandDeps ?? ceoTaskDeps(cfg, id), { via: 'discord' });
44
+ debug.log('seat.dispatch', 'intent', { seat, intent: 'task', via: 'discord', outcome: result.channel });
45
+ return result.reply;
46
+ };
23
47
  const address = parseSeatAddress(text);
24
- if (!address) return null;
48
+ if (!address) {
49
+ if (!text.trim() || /^\s*[/@@]/.test(text)) return null;
50
+ const auth = owner();
51
+ const configured = (auth?.cfg.raw?.seatDispatch as { defaultSeat?: unknown } | undefined)?.defaultSeat;
52
+ if (typeof configured !== 'string' || classifyCeoIntent(text) !== 'task') return null;
53
+ const seat = resolveSeat(configured);
54
+ if (!seat) return null;
55
+ const id = canonicalSeatId(seat.id);
56
+ return ['OP', 'TC', 'MK', 'UX'].includes(id) ? sendTask(id, text, auth!.cfg, auth!.id) : null;
57
+ }
25
58
 
26
59
  const seats = address.seats.map((name) => ({ name, seat: resolveSeat(name) }));
27
60
  const unknown = seats.filter(({ seat }) => !seat).map(({ name }) => `@${name}`);
@@ -29,6 +62,18 @@ export async function handleDiscordSeatWork(
29
62
  const body = address.body.trim();
30
63
  if (!body) return '어떤 일을 맡길까요? 좌석 주소 뒤에 요청 내용을 적어 다시 보내 주세요.';
31
64
 
65
+ if (seats.length === 1 && seats[0]?.seat) {
66
+ const auth = owner();
67
+ const seatId = canonicalSeatId(seats[0].seat.id);
68
+ if (auth && ['OP', 'TC', 'MK', 'UX'].includes(seatId)) {
69
+ const intent = classifyCeoIntent(body);
70
+ if (intent === 'task') return sendTask(seatId, body, auth.cfg, auth.id);
71
+ const answer = await (deps.answer ?? answerAsSeat)(seats[0].name, body);
72
+ debug.log('seat.dispatch', 'intent', { seat: seatId, intent, via: 'discord', outcome: answer ? 'answered' : 'intake' });
73
+ if (answer) return answer.text;
74
+ }
75
+ }
76
+
32
77
  const reportTo = {
33
78
  channel: 'discord' as const,
34
79
  channelId: msg.channelId,