elanous 0.2.9 → 0.2.11

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 (694) 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/Y4zKzL62sakG5momz3SoQ/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1394-556de6d71bbdb0fb.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
  7. package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/2310-7a59f043f6db207e.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/2548-6e316138d347cefe.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/3869-a39d1d9921e10d43.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
  19. package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
  20. package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
  25. package/apps/pwa/out/_next/static/chunks/507-5acd98bd6dab2d8a.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/5445-745eb795c5963d79.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/5845-e6c003ce8d5fd36a.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
  31. package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/8605-ea5bee9dfae512c7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1dcdc58fc2de2454.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-6a061bd97f0b9398.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/board/page-cb95a7432c9ee744.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-f972fc1c00a62e88.js → page-b12b6d2f8d2d1aea.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/app/bots/page-b9efe868bfd36255.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/chat/page-7c97dcdfe2e37a60.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/consult/page-8fd36984f549270a.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/control/page-5721537ca8a3598c.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/design-check/page-b654240a572e4c48.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/editor/page-b9750abc897508c3.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/exec/page-4cd1de371f8ad048.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/field/page-d99f89657828421c.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/inside/page-50cb2a0eb15e6c83.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/intake/page-c8b1ccda6ba7ae98.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/layout-d6b1d156fb95e74b.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/live/page-2a9932ddb62d76bd.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/market/page-9688f5b4f1ff950f.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6b15dd6456c5df09.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/morning/{page-adfbd2ba9598e59a.js → page-35414e0a007b4082.js} +1 -1
  72. package/apps/pwa/out/_next/static/chunks/app/not-found-e7a529e0507ac86c.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/observatory/page-e001823c35c9dd67.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-371423d1a573d64b.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4b764b125339ac17.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cdf8e4b01067bcf1.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a24072b35470157.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/page-94c82eb0ae5abb32.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/reflection/page-0be8d4b2ced75ba0.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d37cb0d52f9b6bd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/sessions/page-686da0df9bf23e5c.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4dc614f3ce043e63.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/settings/page-53f80edc6b8dc07c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-d02c782fc792e2af.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/app/setup/page-239c17b911b84e72.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/share/page-dc6a79fb003f746c.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/showroom/page-0fffb84cafdc9da6.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/app/tasks/page-1218753c82d585f6.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/app/term/page-4b5935e67531efb5.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/app/today/page-3285bc87caf1eaa5.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/app/trace/page-ad553b0e06505ecd.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/app/vault/page-fca096e3e860306f.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ebfa78f0d9885c3.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/app/workflows/page-3dc5f21f7e39622d.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/app/workspace/page-c6da2b468454532d.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-93bc70e36f595414.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → f48170cc-d05d28bf87a43bf4.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +1 -0
  105. package/apps/pwa/out/_next/static/css/543f56bcb1f79fca.css +1 -0
  106. package/apps/pwa/out/approvals/index.html +1 -1
  107. package/apps/pwa/out/approvals/index.txt +23 -23
  108. package/apps/pwa/out/autopilot/index.html +1 -1
  109. package/apps/pwa/out/autopilot/index.txt +23 -23
  110. package/apps/pwa/out/board/index.html +1 -1
  111. package/apps/pwa/out/board/index.txt +23 -23
  112. package/apps/pwa/out/botlab/index.html +1 -1
  113. package/apps/pwa/out/botlab/index.txt +22 -22
  114. package/apps/pwa/out/bots/index.html +1 -1
  115. package/apps/pwa/out/bots/index.txt +22 -22
  116. package/apps/pwa/out/chat/index.html +1 -1
  117. package/apps/pwa/out/chat/index.txt +22 -22
  118. package/apps/pwa/out/consult/index.html +1 -1
  119. package/apps/pwa/out/consult/index.txt +23 -23
  120. package/apps/pwa/out/control/index.html +1 -1
  121. package/apps/pwa/out/control/index.txt +23 -23
  122. package/apps/pwa/out/design-check/index.html +1 -1
  123. package/apps/pwa/out/design-check/index.txt +23 -23
  124. package/apps/pwa/out/editor/index.html +1 -1
  125. package/apps/pwa/out/editor/index.txt +23 -23
  126. package/apps/pwa/out/exec/index.html +1 -1
  127. package/apps/pwa/out/exec/index.txt +23 -23
  128. package/apps/pwa/out/field/index.html +1 -1
  129. package/apps/pwa/out/field/index.txt +23 -23
  130. package/apps/pwa/out/healthz +1 -1
  131. package/apps/pwa/out/index.html +1 -1
  132. package/apps/pwa/out/index.txt +22 -22
  133. package/apps/pwa/out/inside/index.html +1 -0
  134. package/apps/pwa/out/inside/index.txt +31 -0
  135. package/apps/pwa/out/intake/index.html +1 -1
  136. package/apps/pwa/out/intake/index.txt +23 -23
  137. package/apps/pwa/out/live/index.html +1 -1
  138. package/apps/pwa/out/live/index.txt +23 -23
  139. package/apps/pwa/out/market/index.html +1 -1
  140. package/apps/pwa/out/market/index.txt +22 -22
  141. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  142. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  143. package/apps/pwa/out/morning/index.html +1 -1
  144. package/apps/pwa/out/morning/index.txt +23 -23
  145. package/apps/pwa/out/observatory/index.html +1 -1
  146. package/apps/pwa/out/observatory/index.txt +23 -23
  147. package/apps/pwa/out/ops/checklist/index.html +1 -1
  148. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  149. package/apps/pwa/out/ops/release/index.html +1 -1
  150. package/apps/pwa/out/ops/release/index.txt +22 -22
  151. package/apps/pwa/out/ops/seats/index.html +1 -0
  152. package/apps/pwa/out/ops/seats/index.txt +30 -0
  153. package/apps/pwa/out/outputs/index.html +1 -0
  154. package/apps/pwa/out/outputs/index.txt +30 -0
  155. package/apps/pwa/out/reflection/index.html +1 -1
  156. package/apps/pwa/out/reflection/index.txt +23 -23
  157. package/apps/pwa/out/scheduler/index.html +1 -1
  158. package/apps/pwa/out/scheduler/index.txt +23 -23
  159. package/apps/pwa/out/sessions/index.html +1 -1
  160. package/apps/pwa/out/sessions/index.txt +22 -22
  161. package/apps/pwa/out/settings/devices/index.html +1 -1
  162. package/apps/pwa/out/settings/devices/index.txt +23 -23
  163. package/apps/pwa/out/settings/index.html +1 -1
  164. package/apps/pwa/out/settings/index.txt +23 -23
  165. package/apps/pwa/out/setup/done/index.html +1 -1
  166. package/apps/pwa/out/setup/done/index.txt +23 -23
  167. package/apps/pwa/out/setup/index.html +1 -1
  168. package/apps/pwa/out/setup/index.txt +23 -23
  169. package/apps/pwa/out/share/index.html +1 -1
  170. package/apps/pwa/out/share/index.txt +23 -23
  171. package/apps/pwa/out/showroom/index.html +1 -1
  172. package/apps/pwa/out/showroom/index.txt +22 -22
  173. package/apps/pwa/out/tasks/index.html +1 -1
  174. package/apps/pwa/out/tasks/index.txt +23 -23
  175. package/apps/pwa/out/term/index.html +1 -1
  176. package/apps/pwa/out/term/index.txt +23 -24
  177. package/apps/pwa/out/today/index.html +1 -0
  178. package/apps/pwa/out/today/index.txt +33 -0
  179. package/apps/pwa/out/trace/index.html +1 -1
  180. package/apps/pwa/out/trace/index.txt +23 -23
  181. package/apps/pwa/out/vault/index.html +1 -1
  182. package/apps/pwa/out/vault/index.txt +23 -23
  183. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  184. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  185. package/apps/pwa/out/workflows/index.html +1 -1
  186. package/apps/pwa/out/workflows/index.txt +23 -23
  187. package/apps/pwa/out/workspace/index.html +1 -1
  188. package/apps/pwa/out/workspace/index.txt +23 -24
  189. package/apps/pwa/out/worktrees/index.html +1 -1
  190. package/apps/pwa/out/worktrees/index.txt +23 -23
  191. package/graphs/drafts/draft-cleanup.yaml +19 -0
  192. package/graphs/drafts/recipes.yaml +23 -0
  193. package/graphs/field/field-feed.yaml +2 -0
  194. package/graphs/implement-loop.yaml +1 -1
  195. package/graphs/intake/intake-daily.yaml +2 -1
  196. package/graphs/ops/recipes.yaml +3 -0
  197. package/graphs/ops/secret-exposure.yaml +24 -0
  198. package/graphs/release/recipes.yaml +3 -0
  199. package/graphs/release/release-loop.yaml +4 -1
  200. package/graphs/video/explainer-line.yaml +2 -2
  201. package/package.json +2 -1
  202. package/plugins/card-followup/graphs/run-step.ts +48 -13
  203. package/plugins/doc-draft/graphs/doc-draft.yaml +3 -3
  204. package/plugins/doc-draft/graphs/run-step.ts +13 -6
  205. package/plugins/elanous-hwp/README.md +25 -0
  206. package/plugins/elanous-hwp/cli.ts +22 -0
  207. package/plugins/elanous-hwp/converter.ts +237 -0
  208. package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
  209. package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
  210. package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
  211. package/plugins/elanous-hwp/plugin.json +16 -0
  212. package/plugins/elanous-hwp/plugin.ts +40 -0
  213. package/scripts/ci-public-export-leak-gate.ts +75 -14
  214. package/scripts/ci-public-leak-gate.ts +44 -9
  215. package/scripts/ci-pwa-build-gate.ts +160 -0
  216. package/scripts/context-hooks/claude-stop.sh +4 -0
  217. package/scripts/context-hooks/emit.ts +24 -0
  218. package/scripts/context-hooks/post-tool-use.sh +4 -0
  219. package/scripts/coord-channel-watch.sh +54 -8
  220. package/scripts/coord-digest.ts +199 -0
  221. package/scripts/coord-post.sh +60 -3
  222. package/scripts/coord-requests-bridge.ts +143 -0
  223. package/scripts/field-feed/lib.ts +4 -0
  224. package/scripts/fleet/node-setup.sh +20 -3
  225. package/scripts/homebrew-formula-bump.ts +69 -0
  226. package/scripts/install.ps1 +68 -9
  227. package/scripts/install.sh +39 -12
  228. package/scripts/lib/pwa-scenarios/scenarios.ts +20 -0
  229. package/scripts/lib/tui-regress-checks.ts +146 -0
  230. package/scripts/marketing/measure-site-numbers.ts +169 -0
  231. package/scripts/measure-gate-shards.ts +309 -0
  232. package/scripts/memory-lifecycle-cycle.ts +2 -2
  233. package/scripts/mission-request-judge.ts +31 -1
  234. package/scripts/morning-report.ts +2 -2
  235. package/scripts/opportunity-scan.ts +1 -1
  236. package/scripts/ops-now-probe.ts +327 -0
  237. package/scripts/publish-internal-dist.ts +11 -1
  238. package/scripts/release-loop/auto-approve-node.ts +21 -4
  239. package/scripts/release-loop/cut-branch.ts +84 -0
  240. package/scripts/release-loop/cutoff.ts +19 -8
  241. package/scripts/release-loop/gate-node.ts +14 -13
  242. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  243. package/scripts/release-loop/node-verdict.ts +3 -3
  244. package/scripts/release-loop/ops-upgrade-node.ts +72 -16
  245. package/scripts/release-loop/release-readiness.ts +9 -0
  246. package/scripts/release-loop/tui-node-checks.ts +42 -0
  247. package/scripts/release-loop/tui-sim-node.ts +32 -8
  248. package/scripts/release-loop/unattended-release.ts +5 -3
  249. package/scripts/release-loop/version-node.ts +112 -13
  250. package/scripts/repo-watch-cycle.ts +1 -1
  251. package/scripts/retro-cycle.ts +2 -2
  252. package/scripts/schedule-health-report.ts +1 -1
  253. package/scripts/signal-digest-cycle.ts +2 -7
  254. package/scripts/signal-digest-photo.ts +11 -0
  255. package/scripts/storyboard/storyboard.ts +5 -161
  256. package/scripts/tech1-public-measure.ts +94 -0
  257. package/scripts/test-diet/lib.ts +30 -1
  258. package/scripts/test-diet/node.ts +83 -8
  259. package/scripts/test-timeout-audit.ts +114 -0
  260. package/scripts/tree-sync-alert.ts +1 -1
  261. package/scripts/tui-regress.ts +71 -0
  262. package/scripts/ux/demo-rehearsal.ts +243 -0
  263. package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
  264. package/scripts/waitlist-daily-digest.ts +1 -1
  265. package/skills/diagram-master/SKILL.md +366 -0
  266. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  267. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  268. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  269. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  270. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  271. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  272. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  273. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  274. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  275. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  276. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  277. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  278. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  279. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  280. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  281. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  282. package/skills/diagram-master/references/examples/README.md +69 -0
  283. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  284. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  285. package/skills/diagram-master/references/pyproject.toml +16 -0
  286. package/skills/diagram-master/references/quality-checklist.md +33 -0
  287. package/skills/diagram-master/references/routing-guide.md +164 -0
  288. package/skills/diagram-master/references/uv.lock +1356 -0
  289. package/skills/explainer-video/SKILL.md +4 -0
  290. package/skills/explainer-video/engine/reel.mjs +18 -13
  291. package/skills/explainer-video/engine/reel.sh +24 -5
  292. package/skills/explainer-video/engine/stitch.mjs +145 -0
  293. package/skills/google-workspace/SKILL.md +33 -0
  294. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  295. package/skills/grill-me/SKILL.md +1 -1
  296. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  297. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  298. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  299. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  300. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  301. package/skills/omni-crawl/SKILL.md +21 -11
  302. package/skills/omni-crawl/scripts/main.ts +6 -6
  303. package/skills/omni-crawl/src/router.ts +3 -3
  304. package/skills/omni-digest/SKILL.md +17 -9
  305. package/skills/omni-digest/digest.md +2 -2
  306. package/skills/omni-digest/src/fetch.ts +30 -3
  307. package/skills/pitch-deck/SKILL.md +36 -0
  308. package/skills/pitch-deck/template.html +80 -0
  309. package/skills/youtube-master/SKILL.md +163 -0
  310. package/skills/youtube-master/package-lock.json +558 -0
  311. package/skills/youtube-master/package.json +13 -0
  312. package/skills/youtube-master/references/study-note-template.md +124 -0
  313. package/skills/youtube-master/scripts/main.ts +435 -0
  314. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  315. package/skills/youtube-master/src/audio.ts +63 -0
  316. package/skills/youtube-master/src/domain-staging.ts +50 -0
  317. package/skills/youtube-master/src/env.ts +36 -0
  318. package/skills/youtube-master/src/obsidian.ts +155 -0
  319. package/skills/youtube-master/src/router.ts +110 -0
  320. package/skills/youtube-master/src/stt.ts +199 -0
  321. package/skills/youtube-master/src/study-note.ts +175 -0
  322. package/skills/youtube-master/src/summarize.ts +358 -0
  323. package/skills/youtube-master/src/transcript.ts +76 -0
  324. package/skills/youtube-master/src/types.ts +91 -0
  325. package/skills/youtube-master/src/util.ts +93 -0
  326. package/skills/youtube-master/src/youtube.ts +70 -0
  327. package/skills/youtube-master/tsconfig.json +13 -0
  328. package/src/acp/codex-approval-adapter.ts +9 -3
  329. package/src/acp/core-turn-bridge.ts +117 -18
  330. package/src/acp/fact-question.ts +11 -0
  331. package/src/acp/server.ts +53 -9
  332. package/src/acp/tool-approval.ts +126 -0
  333. package/src/acp/turn-runner.ts +36 -0
  334. package/src/agent/monad-agent-turn.ts +8 -0
  335. package/src/agent-mission/driver.ts +80 -10
  336. package/src/agent-mission/pty-decision.ts +71 -0
  337. package/src/agent-mission/review-loop.ts +30 -0
  338. package/src/ask-user-question/pending-questions.ts +25 -10
  339. package/src/ask-user-question/types.ts +9 -0
  340. package/src/auth/setup-link-tokens.ts +16 -5
  341. package/src/autopilot/build/integrity-gate.ts +12 -0
  342. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  343. package/src/autopilot/tool-registry.ts +2 -0
  344. package/src/boot/daemon-prompt-turn.ts +8 -0
  345. package/src/boot/daemon-runtime.ts +9 -3
  346. package/src/boot/daemon-tools/index.ts +8 -0
  347. package/src/boot/daemon-tools/types.ts +2 -0
  348. package/src/boot/daemon-tools/web-search.ts +4 -0
  349. package/src/card-followup/core.ts +109 -0
  350. package/src/chat/ctrl-c-in-input.ts +14 -0
  351. package/src/chat/index.ts +53 -0
  352. package/src/chat/pickers/state.ts +6 -2
  353. package/src/cli/agent-cli.ts +7 -0
  354. package/src/cli/decisions-cli.ts +25 -3
  355. package/src/cli/doctor-bundle-upload.ts +68 -0
  356. package/src/cli/doctor-cli.ts +38 -4
  357. package/src/cli/drive-input-jail.ts +101 -0
  358. package/src/cli/hooks-cli.ts +17 -3
  359. package/src/cli/make-cli.ts +43 -0
  360. package/src/cli/ops-cli.ts +20 -0
  361. package/src/cli/persona-cli.ts +90 -4
  362. package/src/cli/plugin-cli.ts +31 -22
  363. package/src/cli/pod-cli.ts +61 -2
  364. package/src/cli/pr-cli.ts +82 -17
  365. package/src/cli/pty-drive-cli.ts +41 -7
  366. package/src/cli/pty-drive-verdict.ts +40 -0
  367. package/src/cli/pwa-stop.ts +163 -13
  368. package/src/cli/pwa-test.ts +3 -0
  369. package/src/cli/release-cli.ts +80 -24
  370. package/src/cli/self-update.ts +14 -0
  371. package/src/cli/setup-cli.ts +43 -1
  372. package/src/cli/skills-cli.ts +17 -1
  373. package/src/cli/storyboard-cli.ts +37 -0
  374. package/src/cli/test-state-dir-flag.ts +11 -4
  375. package/src/connectors/linear.ts +146 -0
  376. package/src/context-bus/claude-hooks-install.ts +10 -0
  377. package/src/context-bus/context-now-surfaces.ts +48 -0
  378. package/src/context-bus/context-now.ts +104 -0
  379. package/src/context-bus/coord-events.ts +115 -0
  380. package/src/context-bus/external-events.ts +52 -0
  381. package/src/context-bus/long-term-memory.ts +108 -0
  382. package/src/dashboard/dashboard-boot-fixture.ts +23 -0
  383. package/src/dashboard/index.ts +63 -21
  384. package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -1
  385. package/src/dashboard/slash-runtime/help-from-registry.ts +43 -28
  386. package/src/decisions/decision-cards.ts +58 -3
  387. package/src/decisions/decision-ledger.ts +85 -6
  388. package/src/decisions/decision-linear-projection.ts +157 -0
  389. package/src/decisions/web-push-decision-cards.ts +50 -0
  390. package/src/directive/interpretation-card.ts +36 -0
  391. package/src/discord/sprint21-runtime.ts +5 -1
  392. package/src/discord-self-message.ts +32 -0
  393. package/src/discord-slash-wire.ts +5 -1
  394. package/src/discord.ts +19 -2
  395. package/src/domains/coo-admin-tool.ts +62 -0
  396. package/src/domains/core-tools.ts +13 -4
  397. package/src/domains/elanous-card.ts +29 -0
  398. package/src/domains/ops-facts-tool.ts +76 -0
  399. package/src/domains/outbound-alert.ts +46 -13
  400. package/src/domains/release-tool.ts +168 -0
  401. package/src/domains/telegram-kind-route.ts +65 -9
  402. package/src/exec-requests/default-outputs.ts +25 -0
  403. package/src/exec-requests/planner.ts +106 -28
  404. package/src/exec-requests/runner.ts +123 -12
  405. package/src/exec-requests/store.ts +11 -2
  406. package/src/execution-loop/launch-gate.ts +100 -0
  407. package/src/field/field-media.ts +10 -7
  408. package/src/field/field-reel.ts +19 -5
  409. package/src/field-note/index.ts +201 -0
  410. package/src/field-note/transcribe.ts +248 -0
  411. package/src/git-fs/worktree.ts +45 -6
  412. package/src/graph-kinds/registry.ts +3 -3
  413. package/src/graph-runner/graph-approval-card.ts +113 -0
  414. package/src/graph-runner/graph-cli.ts +189 -4
  415. package/src/graph-runner/graph-grow-llm.ts +37 -0
  416. package/src/graph-runner/graph-grow.ts +47 -0
  417. package/src/graph-runner/graph-notify.ts +25 -3
  418. package/src/graph-runner/runner.ts +453 -35
  419. package/src/grok/agent-search.ts +8 -2
  420. package/src/guardian/secret-exposure-scan.ts +101 -0
  421. package/src/harness/browser-verify.ts +25 -2
  422. package/src/harness/harness-cli-command.ts +478 -42
  423. package/src/harness/harness-incidents-writer.fixture.ts +24 -0
  424. package/src/harness/harness-incidents.ts +129 -0
  425. package/src/harness/harness-pod-dispatch.ts +43 -23
  426. package/src/harness/harness-seams.ts +38 -4
  427. package/src/harness/harness-stop.ts +75 -6
  428. package/src/harness/launch-registry.ts +91 -0
  429. package/src/harness/process-garbage.ts +5 -3
  430. package/src/hitl/clarification-policy.ts +3 -1
  431. package/src/hooks/dispatch.ts +82 -0
  432. package/src/hooks/expose.ts +254 -0
  433. package/src/hooks/github-shadow.ts +108 -0
  434. package/src/hooks/providers.ts +71 -5
  435. package/src/hooks/queue.ts +1 -1
  436. package/src/hooks/receiver.ts +21 -20
  437. package/src/index.ts +206 -49
  438. package/src/intake-plane/author-goals.ts +37 -4
  439. package/src/intake-plane/categorize.ts +18 -46
  440. package/src/intake-plane/check.ts +3 -0
  441. package/src/intake-plane/discord-seat-work.ts +57 -2
  442. package/src/intake-plane/front-route-classifier.ts +33 -39
  443. package/src/intake-plane/persona-answer.ts +30 -0
  444. package/src/intake-plane/runtime-callables.ts +8 -1
  445. package/src/intake-plane/seat-doc-route.ts +170 -6
  446. package/src/intake-plane/telegram-seat-work.ts +80 -4
  447. package/src/intake-plane/telegram-work.ts +1 -0
  448. package/src/intake-plane/wish-folder.ts +67 -0
  449. package/src/intent-gate/gate.ts +30 -10
  450. package/src/live/detail-switch.ts +5 -0
  451. package/src/llm/difficulty.ts +57 -0
  452. package/src/llm/judge-layer.ts +101 -0
  453. package/src/llm/mission-router.ts +33 -19
  454. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  455. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  456. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  457. package/src/loops/contract/loop-agent.schema.json +138 -0
  458. package/src/loops/contract/validate.ts +64 -0
  459. package/src/loops/registry.ts +20 -6
  460. package/src/market/signed-index.ts +4 -0
  461. package/src/maturity/bot-command-maturity.ts +45 -0
  462. package/src/maturity/cli-maturity.ts +34 -0
  463. package/src/maturity/feature-maturity.ts +120 -1
  464. package/src/maturity/tui-slash-maturity.ts +31 -0
  465. package/src/memory.ts +32 -4
  466. package/src/model-tier/index.ts +2 -2
  467. package/src/model-tier/tier-resolver.ts +20 -20
  468. package/src/model-tier/types.ts +6 -6
  469. package/src/mss/logging/log-store.ts +15 -0
  470. package/src/nexus/api/config-model-tier.ts +5 -4
  471. package/src/nexus/api/exec-requests.ts +33 -3
  472. package/src/nexus/api/fabric-plans.ts +53 -0
  473. package/src/nexus/api/harness-api.ts +5 -1
  474. package/src/nexus/api/health.ts +2 -0
  475. package/src/nexus/api/http-server.ts +89 -1
  476. package/src/nexus/api/inside-events.ts +226 -0
  477. package/src/nexus/api/meta-api.ts +32 -8
  478. package/src/nexus/api/missions.ts +6 -1
  479. package/src/nexus/api/ops-api.ts +10 -1
  480. package/src/nexus/api/ops-seats-sources.ts +37 -7
  481. package/src/nexus/api/ops-seats.ts +49 -6
  482. package/src/nexus/api/outputs-route.ts +44 -0
  483. package/src/nexus/api/seat-requests.ts +132 -10
  484. package/src/nexus/api/sessions-store.ts +42 -0
  485. package/src/nexus/api/setup-codex-login.ts +160 -0
  486. package/src/nexus/api/sub-seat-charters.ts +34 -0
  487. package/src/nexus/api/tabs-mutations.ts +3 -1
  488. package/src/nexus/api/trace.ts +18 -6
  489. package/src/nexus/api/usage-api.ts +102 -0
  490. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  491. package/src/nexus/api/workflows.ts +80 -6
  492. package/src/nexus/index.ts +47 -4
  493. package/src/nexus/kinds/webterm.ts +2 -1
  494. package/src/nexus/webterm/pty.ts +6 -2
  495. package/src/onboarding/cli-auth-status.ts +80 -0
  496. package/src/onboarding/first-run.ts +89 -0
  497. package/src/onboarding/lan-address.ts +45 -0
  498. package/src/onboarding/voice-ai.ts +3 -3
  499. package/src/onboarding/web-first.ts +119 -24
  500. package/src/onboarding.ts +4 -0
  501. package/src/ops-now/ops-now-refresh.ts +100 -0
  502. package/src/org/seat-budget.ts +48 -0
  503. package/src/org/stall-escalation.ts +63 -0
  504. package/src/outputs/ledger.ts +120 -0
  505. package/src/persona/persona-todo.ts +79 -0
  506. package/src/persona/presets.ts +116 -2
  507. package/src/persona/team-set.ts +155 -0
  508. package/src/plugins/install/plugin-install.ts +14 -0
  509. package/src/plugins/maker/market-bundle.ts +109 -0
  510. package/src/plugins/maker/plugin-maker.ts +254 -11
  511. package/src/plugins/maker/wizard-generate.ts +103 -0
  512. package/src/pod-lease/admission.ts +150 -0
  513. package/src/pod-lease/dependency-state.ts +85 -0
  514. package/src/pod-lease/host-lease.ts +127 -0
  515. package/src/project/project-store.ts +115 -0
  516. package/src/project/project-suggestion.ts +16 -0
  517. package/src/project/session-context.ts +24 -0
  518. package/src/release-loop/checklist.ts +79 -5
  519. package/src/release-loop/feature-store.ts +159 -24
  520. package/src/release-loop/next-md-merge.ts +58 -0
  521. package/src/release-loop/release-note.ts +59 -4
  522. package/src/release-loop/release-schedule.ts +53 -0
  523. package/src/repl/index.ts +7 -0
  524. package/src/seat-dispatch/ceo-commands.ts +41 -8
  525. package/src/seat-dispatch/ceo-intent.ts +38 -0
  526. package/src/seat-dispatch/seat-ask.ts +130 -0
  527. package/src/seat-dispatch/seat-questions.ts +100 -0
  528. package/src/seat-loop/seat-loop.ts +750 -0
  529. package/src/seat-loop/seat-report.ts +99 -0
  530. package/src/self-dev/decompose.ts +66 -11
  531. package/src/self-dev/dev-cli.ts +4 -1
  532. package/src/self-dev/dev-pipeline.ts +37 -1
  533. package/src/self-dev/draft-sweep.ts +38 -33
  534. package/src/self-dev/draft-triage-rules.ts +8 -5
  535. package/src/self-dev/fabric-plan-core.ts +297 -0
  536. package/src/self-dev/orchestrate.ts +36 -4
  537. package/src/self-dev/release-path-guard.ts +62 -0
  538. package/src/self-dev/run-store.ts +10 -1
  539. package/src/self-dev/shard-aggregate.ts +230 -0
  540. package/src/self-dev/shard-placement.ts +60 -0
  541. package/src/self-dev/shard-plan.ts +48 -0
  542. package/src/self-dev/shard-pod-run.ts +77 -0
  543. package/src/self-dev/shard-run.ts +105 -0
  544. package/src/self-implement/execution-clarification.ts +115 -0
  545. package/src/self-implement/gate-baseline.ts +1 -1
  546. package/src/self-implement/gate-cli.ts +46 -4
  547. package/src/self-implement/gate-scope.ts +37 -7
  548. package/src/self-implement/graph-variant.ts +171 -0
  549. package/src/self-implement/harness-policy-gates.ts +1 -1
  550. package/src/self-implement/headless-elanous-driver.ts +22 -3
  551. package/src/self-implement/host-regate.ts +22 -1
  552. package/src/self-implement/importer-test-index.ts +2 -1
  553. package/src/self-implement/l8-merge-queue.ts +130 -0
  554. package/src/self-implement/orchestrator.ts +279 -12
  555. package/src/self-implement/pipeline-shape.ts +1 -1
  556. package/src/self-implement/route-consumer-test-index.ts +122 -0
  557. package/src/self-implement/run-status-mapping.ts +5 -3
  558. package/src/self-implement/seams.ts +72 -11
  559. package/src/self-implement/test-seams.ts +1 -0
  560. package/src/self-implement/uncommitted-work.ts +59 -0
  561. package/src/session/chat.ts +2 -0
  562. package/src/session/index.ts +45 -13
  563. package/src/shell-env-bootstrap.ts +17 -0
  564. package/src/skills/gift-install.ts +215 -0
  565. package/src/skills/tools/web-search.ts +4 -1
  566. package/src/steward/directive.ts +51 -2
  567. package/src/steward/launch.ts +266 -0
  568. package/src/steward/outcome-notify.ts +115 -0
  569. package/src/steward/steward-cards.ts +25 -11
  570. package/src/steward/triage-plan.ts +32 -4
  571. package/src/steward/triage.ts +129 -13
  572. package/src/steward/working-backwards.ts +64 -0
  573. package/src/storyboard/storyboard.ts +141 -0
  574. package/src/task-cards/card-cli.ts +25 -1
  575. package/src/task-cards/card-store.ts +2 -2
  576. package/src/task-orchestrator/mission.ts +5 -0
  577. package/src/task-orchestrator/store.ts +12 -3
  578. package/src/task-orchestrator/surfaces/pod-command-job.ts +29 -7
  579. package/src/task-orchestrator/surfaces/pod-lease.ts +397 -0
  580. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  581. package/src/task-orchestrator/surfaces/self-implement-pod.ts +214 -40
  582. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  583. package/src/task-orchestrator/types.ts +2 -0
  584. package/src/telegram-card-followup.ts +153 -0
  585. package/src/telegram-commands.ts +10 -1
  586. package/src/telegram-project-command.ts +71 -0
  587. package/src/telegram-report.ts +29 -19
  588. package/src/telegram-run.ts +7 -0
  589. package/src/telegram.ts +58 -11
  590. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  591. package/src/tool-runtime/types.ts +4 -0
  592. package/src/tui-client/dashboard-session.ts +2 -0
  593. package/src/user-config.ts +216 -27
  594. package/src/version/packed-revision.json +1 -1
  595. package/src/web-push/notify-exec-request.ts +32 -0
  596. package/src/web-search/grok.ts +7 -1
  597. package/src/web-search/index.ts +28 -1
  598. package/src/web-search/provider.ts +4 -0
  599. package/src/web-search/x-intent.ts +5 -0
  600. package/src/workflow-runtime/executor.ts +277 -47
  601. package/src/workflow-runtime/index.ts +1 -0
  602. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  603. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  604. package/src/workflow-runtime/schema.ts +79 -4
  605. package/src/workflow-runtime/types.ts +35 -4
  606. package/apps/pwa/out/_next/static/bFI5EEwg7T6aG88ibX4Zq/_buildManifest.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  617. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  618. package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/5080-1613752891fcadb4.js +0 -10
  622. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6090-85a3f05f954e5697.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6284-69db415193d5f8bd.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7032-f4ef698518fba61c.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/8067-d976b441a104ab74.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/8519-5632377cce994f86.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8630-cdfc61e82c653ffc.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8894-e263b332208e3957.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/9454-139040d37c79dbc9.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/9740-8f5ff96c522b5f55.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fb7c2d458f32fcad.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-35e2713597dd24d1.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/board/page-918b656f064577ba.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/bots/page-5f30e00693527ebd.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/chat/page-7fbae173b3c103a7.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b4edcce364062ea.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/control/page-c5794f484c251f44.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1130d8eefcd87e76.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/editor/page-973996d584f008c1.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/exec/page-016e2bda04eecb1f.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/field/page-b4d6d9a3b56f2940.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/intake/page-ec49a466121233ba.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/layout-f72db356744ceade.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/live/page-a6fd9b50d1b85378.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/market/page-8b0402a46a749a3d.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-037f83e2a1edc8e2.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/not-found-46fedff57d4bec67.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/observatory/page-0cf318e9dcee2bbf.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-899b327cb8b6845c.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6c1e6ba743a29dfe.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/page-1a8e4807292f6b17.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/reflection/page-28deba6bcb834916.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-de68e2205794037d.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/sessions/page-c71c33a573230672.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-0df30e0c7e50148a.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/settings/page-4fc56790fe0d2682.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-59df2aebb38a7c1e.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/setup/page-4647be5dbcbd0795.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/share/page-e025892bda74b743.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/showroom/page-a0955de73b89f078.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/tasks/page-369846d2921af584.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/term/page-72cbc1c8cdd0f65d.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/trace/page-77b28bfb0996d5ea.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/vault/page-3220c4934f49c6c2.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-90670589b87abea8.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/workflows/page-7df9243ed021a4cc.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/workspace/page-4498c3853f4f688d.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-35bedde6d885f08f.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/main-app-6870f30ea99f8346.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  692. package/apps/pwa/out/_next/static/css/f92f63a5df0ba229.css +0 -1
  693. package/src/dashboard/turn-typeahead-echo.ts +0 -23
  694. /package/apps/pwa/out/_next/static/{bFI5EEwg7T6aG88ibX4Zq → Y4zKzL62sakG5momz3SoQ}/_ssgManifest.js +0 -0
@@ -15,7 +15,10 @@
15
15
  // In PR α `elanous nexus` is opt-in only; `elanous` continues to launch
16
16
  // the legacy dashboard.
17
17
 
18
+ import { getElanousConfigDir } from '../elanous-config-dir.js';
18
19
  import { hostname } from 'node:os';
20
+ import { request as httpRequest } from 'node:http';
21
+ import { isIP } from 'node:net';
19
22
  import { resolveToolCwd } from '../boot/tool-cwd.js';
20
23
  import { acquireNexusLock, NexusLockError, readNexusLock, findNexusLifecycleState } from './supervisor/lock.js';
21
24
  import { classifyNexusStatus, type NexusHttpHealth } from './status-line.js';
@@ -1267,6 +1270,7 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
1267
1270
  let coordinatorPushWatcher: { stop(): void } | undefined;
1268
1271
  // V2.2-3 (2026-05-12) — NEXUS-hosted Discord workflow trigger bot.
1269
1272
  // Wired below once the workflow daemon is constructed.
1273
+ let webPushDecisionTimer: ReturnType<typeof setInterval> | undefined;
1270
1274
  let workflowDiscordBot: NexusDiscordTriggerBotHandle | undefined;
1271
1275
  // V2.2-4 (2026-05-12) — NEXUS-hosted Telegram workflow trigger bot.
1272
1276
  let workflowTelegramBot: NexusTelegramTriggerBotHandle | undefined;
@@ -1945,10 +1949,12 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
1945
1949
  const tab = registry.get(tabId);
1946
1950
  if (!tab || tab.spec.kind !== 'webterm') return;
1947
1951
  const cwdMeta = (tab.spec.meta as { cwd?: string } | undefined)?.cwd;
1952
+ const projectSessionId = (tab.spec.meta as { sessionId?: string } | undefined)?.sessionId;
1948
1953
  const backendFactory = effectiveWebtermSpawn
1949
1954
  ? () => {
1950
1955
  const decided = resolveWebtermCwd({
1951
1956
  ...(cwdMeta ? { tabCwd: cwdMeta } : {}),
1957
+ ...(projectSessionId ? { sessionId: projectSessionId } : {}),
1952
1958
  ...(runtimeToolCwd ? { toolCwd: runtimeToolCwd } : {}),
1953
1959
  instance: resolveCurrentInstance(),
1954
1960
  processCwd: process.cwd(),
@@ -2108,7 +2114,9 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
2108
2114
  },
2109
2115
  } : {}),
2110
2116
  voiceAdapter,
2111
- ...buildNexusWsBridgeAuth(bearerToken),
2117
+ // The verifier reads the token envelope from the same config dir the boot token was written to
2118
+ // (ensureAuthToken) — default ~/.elanous would make an isolated daemon check the production envelope.
2119
+ ...buildNexusWsBridgeAuth(bearerToken, { configDir: getElanousConfigDir() }),
2112
2120
  };
2113
2121
 
2114
2122
  metaApiOpts = {
@@ -2729,6 +2737,28 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
2729
2737
  console.warn(`[nexus] workflow daemon boot skipped: ${msg}`);
2730
2738
  }
2731
2739
 
2740
+ // Decision cards use the same ledger and first-start baseline as the messaging transports.
2741
+ if ((getUserConfig().raw?.decisions as { cards?: unknown } | undefined)?.cards !== false && !isAutonomousRunContext()) {
2742
+ try {
2743
+ const { DecisionCardService } = await import('../decisions/decision-cards.js');
2744
+ const { webPushDecisionTransport } = await import('../decisions/web-push-decision-cards.js');
2745
+ const { listSubscriptions } = await import('../web-push/subscriptions.js');
2746
+ const { DecisionLedger } = await import('../decisions/decision-ledger.js');
2747
+ const ledger = new DecisionLedger();
2748
+ const service = new DecisionCardService({ transport: webPushDecisionTransport(ledger), ownerIds: [], ledger });
2749
+ await service.tick();
2750
+ webPushDecisionTimer = setInterval(() => {
2751
+ void service.tick().catch((error: unknown) => {
2752
+ debug.log('decisions.webpush', 'tick-failed', { reason: error instanceof Error ? error.message.slice(0, 80) : 'unknown' }, { level: 'warn' });
2753
+ });
2754
+ }, 20_000);
2755
+ webPushDecisionTimer.unref();
2756
+ debug.log('decisions.webpush', 'attached', { subscribers: listSubscriptions().length });
2757
+ } catch (error) {
2758
+ debug.log('decisions.webpush', 'attach-failed', { reason: error instanceof Error ? error.message.slice(0, 80) : 'unknown' }, { level: 'warn' });
2759
+ }
2760
+ }
2761
+
2732
2762
  // W7-후속 (2026-05-12) — Outbound substrate boot. Builds the
2733
2763
  // OutboundRouter + iOS push channel + token store from user-config
2734
2764
  // `notifications.apns.*`. The token store is passed to the http
@@ -3339,6 +3369,7 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
3339
3369
  console.warn(`[nexus] continuation scheduler stop failed: ${(err as Error).message}`);
3340
3370
  }
3341
3371
  }
3372
+ if (webPushDecisionTimer) { clearInterval(webPushDecisionTimer); webPushDecisionTimer = undefined; }
3342
3373
  // R5 — stop the dig-goal armer poller (no-op when never armed).
3343
3374
  if (digArmerHandle) { clearInterval(digArmerHandle); digArmerHandle = undefined; }
3344
3375
  if (replayArmerHandle) { clearInterval(replayArmerHandle); replayArmerHandle = undefined; }
@@ -3876,9 +3907,21 @@ async function probeNexusStatusHealth(runtime: NexusRuntimeMeta | null): Promise
3876
3907
  const healthUrl = new URL('http://localhost/v1/health');
3877
3908
  healthUrl.hostname = host.includes(':') && !host.startsWith('[') ? `[${host}]` : host;
3878
3909
  healthUrl.port = String(runtime.httpPort);
3879
- const response = await fetch(healthUrl.href, {
3880
- signal: AbortSignal.timeout(NEXUS_STATUS_HEALTH_TIMEOUT_MS),
3881
- });
3910
+ const signal = AbortSignal.timeout(NEXUS_STATUS_HEALTH_TIMEOUT_MS);
3911
+ if (healthUrl.hostname === 'localhost' || healthUrl.hostname === '[::1]'
3912
+ || (isIP(healthUrl.hostname) === 4 && healthUrl.hostname.startsWith('127.'))) {
3913
+ // Bun fetch inherits HTTP_PROXY even for loopback; node:http opens a direct socket.
3914
+ const ok = await new Promise<boolean>((resolve, reject) => {
3915
+ const req = httpRequest(healthUrl, { signal }, (response) => {
3916
+ response.resume();
3917
+ resolve(response.statusCode !== undefined && response.statusCode >= 200 && response.statusCode < 300);
3918
+ });
3919
+ req.on('error', reject);
3920
+ req.end();
3921
+ });
3922
+ return ok ? 'responsive' : 'silent';
3923
+ }
3924
+ const response = await fetch(healthUrl.href, { signal });
3882
3925
  return response.ok ? 'responsive' : 'silent';
3883
3926
  } catch {
3884
3927
  // The request could not complete, so retain unknown rather than infer listener silence.
@@ -24,6 +24,7 @@ export interface WebtermTabOpts {
24
24
  id?: string; // default: 'webterm:1'
25
25
  label?: string;
26
26
  cwd?: string;
27
+ sessionId?: string;
27
28
  }
28
29
 
29
30
  export const WEBTERM_KIND: TabKind = 'webterm';
@@ -34,7 +35,7 @@ export function createWebtermTabSpec(opts: WebtermTabOpts = {}): TabSpec {
34
35
  id,
35
36
  kind: WEBTERM_KIND,
36
37
  label: opts.label ?? id,
37
- ...(opts.cwd ? { meta: { cwd: opts.cwd } } : {}),
38
+ ...(opts.cwd || opts.sessionId ? { meta: { ...(opts.cwd ? { cwd: opts.cwd } : {}), ...(opts.sessionId ? { sessionId: opts.sessionId } : {}) } } : {}),
38
39
  };
39
40
  }
40
41
 
@@ -31,6 +31,7 @@ import { startPty as realStartPty, onPtyEvent as realOnPtyEvent } from '../../pt
31
31
  import type { StartOpts, PtyHandle, PtyEvent } from '../../pty-shell/registry.js';
32
32
 
33
33
  import { debug } from '../../debug/log.js';
34
+ import { resolveSessionProjectContext } from '../../project/session-context.js';
34
35
 
35
36
  // ── PtyBackend interface ─────────────────────────────────────────────
36
37
 
@@ -229,15 +230,18 @@ export function createRegistryBackend(
229
230
  }
230
231
 
231
232
  /** 웹 터미널 셸이 열릴 작업 디렉토리를 정한다(실행 맥락 SSOT: 맥락은 «한 번» 정해지고 인자로 내려간다).
232
- * 순서: 탭이 명시한 cwd → 데몬이 정한 tool cwd → (격리 우주면) 우주 뿌리 → 데몬 프로세스 cwd.
233
+ * 순서: 탭이 명시한 cwd → 대화 프로젝트 폴더 → 데몬 tool cwd → (격리 우주면) 우주 뿌리 → 프로세스 cwd.
233
234
  * ⛔ 격리(test) 우주에서 `process.cwd()` 로 떨어지면 셸이 «사람 작업 트리»에서 열린다(🅕 실측 2026-09-26). */
234
235
  export function resolveWebtermCwd(input: {
235
236
  tabCwd?: string;
237
+ sessionId?: string;
236
238
  toolCwd?: string;
237
239
  instance: { kind: 'prod' | 'test'; root: string };
238
240
  processCwd: string;
239
- }): { cwd: string; source: 'tab' | 'tool-cwd' | 'isolated-root' | 'process-cwd' } {
241
+ }): { cwd: string; source: 'tab' | 'project' | 'tool-cwd' | 'isolated-root' | 'process-cwd' } {
240
242
  if (input.tabCwd) return { cwd: input.tabCwd, source: 'tab' };
243
+ const projectCwd = resolveSessionProjectContext(input.sessionId)?.cwd;
244
+ if (projectCwd) return { cwd: projectCwd, source: 'project' };
241
245
  if (input.toolCwd) return { cwd: input.toolCwd, source: 'tool-cwd' };
242
246
  if (input.instance.kind === 'test') return { cwd: input.instance.root, source: 'isolated-root' };
243
247
  return { cwd: input.processCwd, source: 'process-cwd' };
@@ -0,0 +1,80 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { accessSync, constants, statSync } from 'node:fs';
3
+ import { delimiter, join } from 'node:path';
4
+
5
+ export type SkillCli = 'gh' | 'gws' | 'op' | 'himalaya';
6
+
7
+ export interface CliAuthStatus {
8
+ cli: SkillCli;
9
+ found: boolean;
10
+ authenticated: boolean;
11
+ skippedReason?: string;
12
+ }
13
+
14
+ export interface CliAuthStatusDeps {
15
+ path?: string;
16
+ findExecutable?: (name: SkillCli, path: string) => string | null;
17
+ runStatus?: (executable: string, args: readonly string[]) => { status: number | null; stdout?: string; error?: unknown };
18
+ }
19
+
20
+ const STATUS_COMMANDS: readonly { cli: SkillCli; args: readonly string[] }[] = [
21
+ { cli: 'gh', args: ['auth', 'status'] },
22
+ { cli: 'gws', args: ['auth', 'status'] },
23
+ { cli: 'op', args: ['whoami'] },
24
+ { cli: 'himalaya', args: ['account', 'check'] },
25
+ ];
26
+
27
+ function findOnPath(name: SkillCli, path: string): string | null {
28
+ for (const directory of path.split(delimiter).filter(Boolean)) {
29
+ const executable = join(directory, name);
30
+ try {
31
+ accessSync(executable, constants.X_OK);
32
+ if (statSync(executable).isFile()) return executable;
33
+ } catch { /* Try the next PATH entry. */ }
34
+ }
35
+ return null;
36
+ }
37
+
38
+ function runReadOnlyStatus(executable: string, args: readonly string[]) {
39
+ const result = spawnSync(executable, [...args], {
40
+ encoding: 'utf8', timeout: 5_000, maxBuffer: 64 * 1024,
41
+ stdio: ['ignore', 'pipe', 'ignore'],
42
+ });
43
+ return { status: result.status, stdout: result.stdout, error: result.error };
44
+ }
45
+
46
+ function gwsHasSession(stdout: string | undefined): boolean {
47
+ try {
48
+ const status: unknown = JSON.parse(stdout ?? '');
49
+ if (!status || typeof status !== 'object' || Array.isArray(status)) return false;
50
+ const auth = status as Record<string, unknown>;
51
+ return auth.token_valid === true;
52
+ } catch {
53
+ return false;
54
+ }
55
+ }
56
+
57
+ /** No credential-file reads, login calls, prompts, or token-bearing output leave this probe. */
58
+ export function detectSkillCliAuth(deps: CliAuthStatusDeps = {}): CliAuthStatus[] {
59
+ const path = deps.path ?? process.env.PATH ?? '';
60
+ const find = deps.findExecutable ?? findOnPath;
61
+ const run = deps.runStatus ?? runReadOnlyStatus;
62
+ return STATUS_COMMANDS.map(({ cli, args }) => {
63
+ let executable: string | null;
64
+ try { executable = find(cli, path); }
65
+ catch { executable = null; }
66
+ if (!executable) return { cli, found: false, authenticated: false, skippedReason: 'not on PATH' };
67
+ try {
68
+ const result = run(executable, args);
69
+ if (result.error || result.status === null) {
70
+ return { cli, found: true, authenticated: false, skippedReason: 'status check unavailable' };
71
+ }
72
+ if (result.status !== 0 || (cli === 'gws' && !gwsHasSession(result.stdout))) {
73
+ return { cli, found: true, authenticated: false, skippedReason: 'not authenticated' };
74
+ }
75
+ return { cli, found: true, authenticated: true };
76
+ } catch {
77
+ return { cli, found: true, authenticated: false, skippedReason: 'status check unavailable' };
78
+ }
79
+ });
80
+ }
@@ -0,0 +1,89 @@
1
+ import * as readline from 'node:readline/promises';
2
+ import { detectProviders, type DetectedProvider } from '../llm/provider-detect.js';
3
+ import { debug } from '../debug/log.js';
4
+ import { resolveProviderCredential } from '../llm/provider-credentials.js';
5
+ import {
6
+ getUserConfig, saveUserConfig, userConfigPath,
7
+ type LLMProviderName, type UserConfig,
8
+ } from '../user-config.js';
9
+
10
+ export interface FirstRunDeps {
11
+ config?: UserConfig;
12
+ path?: string;
13
+ detectProviders?: () => Promise<DetectedProvider[]>;
14
+ isTTY?: boolean;
15
+ chooseProvider?: () => Promise<LLMProviderName | null>;
16
+ print?: (message: string) => void;
17
+ saveConfig?: (config: UserConfig, path: string) => void;
18
+ }
19
+
20
+ async function chooseProvider(): Promise<LLMProviderName | null> {
21
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
22
+ try {
23
+ const answer = (await rl.question('Choose LLM (1 Codex, 2 Grok, 3 Claude; Enter to cancel): ')).trim();
24
+ return ({ '1': 'openai-codex', '2': 'grok', '3': 'anthropic' } as Record<string, LLMProviderName>)[answer] ?? null;
25
+ } finally {
26
+ rl.close();
27
+ }
28
+ }
29
+
30
+ export async function runFirstRun(deps: FirstRunDeps = {}): Promise<{
31
+ outcome: 'ready' | 'needs-llm' | 'cancelled'; provider?: string; inputs: number;
32
+ }> {
33
+ const path = deps.path ?? userConfigPath();
34
+ const cfg = deps.config ?? getUserConfig(path);
35
+ const print = deps.print ?? console.log;
36
+ let detected: DetectedProvider[] = [];
37
+ try { detected = await (deps.detectProviders ?? detectProviders)(); }
38
+ catch { /* Detection is advisory; a TTY can still choose. */ }
39
+ const subscriptions = detected.filter((d) => d.available && (d.auth === 'oauth' || d.auth === 'agent-cli'));
40
+ const providers = subscriptions.map((d) => d.provider);
41
+ const observe = (event: 'detected' | 'chosen' | 'ready' | 'needs-llm', inputs: number) =>
42
+ debug.log('onboarding.first-run', event, { providers, inputs });
43
+ observe('detected', 0);
44
+ // An incomplete onboarding marker does not mean the user's LLM is unconfigured.
45
+ // Keep an already usable provider, key and model rather than replacing them with a detected subscription.
46
+ const existing = cfg.llm.provider !== 'auto'
47
+ ? resolveProviderCredential({ provider: cfg.llm.provider, rotation: cfg.llm.rotation,
48
+ baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey })
49
+ : undefined;
50
+ const configured = existing && existing.source !== 'none'
51
+ ? cfg.llm.provider : undefined;
52
+ const picked = (['openai-codex', 'grok', 'claude-code', 'anthropic', 'gemini', 'openai', 'openrouter'] as const)
53
+ .find((name) => providers.includes(name));
54
+ let provider: LLMProviderName | null | undefined = configured ??
55
+ (picked === 'claude-code' ? 'anthropic' : picked as LLMProviderName | undefined);
56
+ let inputs = 0;
57
+ if (!provider) {
58
+ if ((deps.isTTY ?? process.stdin.isTTY) !== true) {
59
+ print('eln setup llm 으로 고르세요');
60
+ observe('needs-llm', 0);
61
+ return { outcome: 'needs-llm', inputs: 0 };
62
+ }
63
+ inputs = 1;
64
+ provider = await (deps.chooseProvider ?? chooseProvider)();
65
+ if (!provider) return { outcome: 'cancelled', inputs };
66
+ observe('chosen', inputs);
67
+ }
68
+ const credential = inputs === 1 || provider !== cfg.llm.provider
69
+ ? resolveProviderCredential({
70
+ provider, rotation: cfg.llm.rotation,
71
+ baseProvider: cfg.llm.provider, baseApiKey: cfg.llm.apiKey,
72
+ })
73
+ : undefined;
74
+ if (inputs === 1 && credential?.source === 'none') {
75
+ print('eln setup llm 으로 고르세요');
76
+ observe('needs-llm', inputs);
77
+ return { outcome: 'needs-llm', inputs };
78
+ }
79
+ (deps.saveConfig ?? saveUserConfig)({
80
+ ...cfg,
81
+ llm: { ...cfg.llm, provider,
82
+ ...(provider !== cfg.llm.provider ? { apiKey: credential?.apiKey, baseUrl: credential?.baseUrl, model: undefined } : {}),
83
+ ...(credential?.apiKey ? { apiKey: credential.apiKey } : {}),
84
+ ...(credential?.baseUrl ? { baseUrl: credential.baseUrl } : {}) },
85
+ onboarding: { ...cfg.onboarding, ready: true },
86
+ }, path);
87
+ observe('ready', inputs);
88
+ return { outcome: 'ready', provider, inputs };
89
+ }
@@ -0,0 +1,45 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { networkInterfaces } from 'node:os';
3
+
4
+ export function isPrivateIpv4(addr: string): boolean {
5
+ const parts = addr.split('.');
6
+ if (parts.length !== 4 || parts.some(part => !/^(0|[1-9]\d{0,2})$/.test(part) || Number(part) > 255)) return false;
7
+ const [a, b] = parts.map(Number);
8
+ return a === 10 || (a === 172 && b! >= 16 && b! <= 31) || (a === 192 && b === 168);
9
+ }
10
+
11
+ export function defaultRouteInterface(platform: NodeJS.Platform = process.platform): string | undefined {
12
+ try {
13
+ if (platform === 'darwin') {
14
+ return /^\s*interface:\s*(\S+)/m.exec(execFileSync('route', ['-n', 'get', 'default'], { encoding: 'utf8', timeout: 1000, stdio: ['ignore', 'pipe', 'ignore'] }))?.[1];
15
+ }
16
+ if (platform === 'linux') {
17
+ return /^default\s+.*?\bdev\s+(\S+)/m.exec(execFileSync('ip', ['route', 'show', 'default'], { encoding: 'utf8', timeout: 1000, stdio: ['ignore', 'pipe', 'ignore'] }))?.[1];
18
+ }
19
+ } catch { /* Route lookup is optional. */ }
20
+ return undefined;
21
+ }
22
+
23
+ export function pickLanAddress({ interfaces, defaultRouteInterface: route }: {
24
+ interfaces: ReturnType<typeof networkInterfaces>;
25
+ defaultRouteInterface?: string | (() => string | undefined);
26
+ }): string | null {
27
+ const candidates: { name: string; address: string }[] = [];
28
+ for (const [name, addresses] of Object.entries(interfaces)) {
29
+ for (const info of addresses ?? []) {
30
+ if (info.family === 'IPv4' && !info.internal && isPrivateIpv4(info.address)) {
31
+ candidates.push({ name, address: info.address });
32
+ }
33
+ }
34
+ }
35
+ if (candidates.length === 0) return null;
36
+ let preferred: string | undefined;
37
+ try { preferred = typeof route === 'function' ? route() : route ?? defaultRouteInterface(); } catch { /* Use sorted candidates. */ }
38
+ candidates.sort((a, b) => a.name.localeCompare(b.name) || a.address.localeCompare(b.address));
39
+ return (candidates.find(candidate => candidate.name === preferred) ?? candidates[0])?.address ?? null;
40
+ }
41
+
42
+ export function isLanReachableBind(httpHost: string | undefined): boolean {
43
+ const host = httpHost?.trim() ?? '';
44
+ return host === '' || host === '0.0.0.0' || host === '::' || host === '[::]' || isPrivateIpv4(host);
45
+ }
@@ -154,12 +154,12 @@ export async function askVoiceAI(
154
154
 
155
155
  if (mode === 'preset') {
156
156
  // Phase 2 catalog isn't shipped yet; the wizard records the intent
157
- // by keeping the user on Smart defaults but tagging persona='power'
157
+ // by keeping the user on Smart defaults but tagging profile='power'
158
158
  // so the auto-suggest hint in PWA opens the preset card directly.
159
159
  io.print(' (Preset catalog ships in Phase 2 · for now Smart defaults stay active.)');
160
160
  io.print(' elanous has noted your preference — preset hints will appear when ready.');
161
161
  return {
162
- modelTier: { persona: 'power' },
162
+ modelTier: { profile: 'power' },
163
163
  };
164
164
  }
165
165
 
@@ -175,7 +175,7 @@ export async function askVoiceAI(
175
175
 
176
176
  const answer: VoiceAIAnswer = {
177
177
  modelTier: {
178
- persona: 'custom',
178
+ profile: 'custom',
179
179
  voice: { stt: tier as ModelTier },
180
180
  },
181
181
  };
@@ -1,62 +1,150 @@
1
1
  import { spawnSync } from 'node:child_process';
2
+ import { hostname, networkInterfaces, userInfo } from 'node:os';
3
+ import { findNexusLifecycleState } from '../nexus/supervisor/lock.js';
4
+ import { isLanReachableBind, isPrivateIpv4, pickLanAddress } from './lan-address.js';
2
5
  import { isHeadlessEnv } from '../acp/codex-auth.js';
3
- import { runNexusShow, type NexusShowResult } from '../cli/nexus-show.js';
6
+ import { runBgLaunch, type BgLaunchResult } from '../cli/bg-launch.js';
7
+ import { joinRestHealthUrl, runNexusShow, type NexusShowResult } from '../cli/nexus-show.js';
8
+ import { issueSetupLinkToken } from '../auth/setup-link-tokens.js';
4
9
  import { debug } from '../debug/log.js';
5
10
  import { browserUnavailableReason } from '../oauth/browser-availability.js';
6
11
  import type { UserConfig } from '../user-config.js';
7
12
 
8
13
  export interface WebFirstSetupDeps {
9
14
  config: Pick<UserConfig, 'onboarding'>;
15
+ /** Whether a person is at a terminal (stdin TTY). Without one the web path only uses a daemon that is already up. */
10
16
  isTty?: boolean;
11
17
  terminal?: boolean;
18
+ startedAt?: number;
12
19
  showNexus?: () => Promise<NexusShowResult>;
20
+ startDaemon?: () => Promise<BgLaunchResult>;
21
+ probeHealth?: (url: string, timeoutMs: number) => Promise<boolean>;
13
22
  issueSetupLinkToken?: () => Promise<string | { token: string }>;
14
23
  renderQr?: (link: string) => string | undefined;
15
24
  openBrowser?: (link: string) => boolean;
16
25
  isHeadless?: () => boolean;
17
26
  browserEnv?: NodeJS.ProcessEnv;
18
27
  browserPlatform?: NodeJS.Platform;
28
+ httpHost?: () => string | undefined;
29
+ interfaces?: typeof networkInterfaces;
30
+ defaultRouteInterface?: () => string | undefined;
31
+ hostname?: typeof hostname;
32
+ username?: () => string;
19
33
  print?: (line: string) => void;
20
34
  }
21
35
 
36
+ const STARTUP_TIMEOUT_MS = 12_000;
37
+
38
+ async function probeHealth(url: string, timeoutMs: number): Promise<boolean> {
39
+ try {
40
+ const response = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });
41
+ return response.ok;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+
22
47
  function setupUrl(pwa: string, token: string): string {
23
48
  return `${pwa.replace(/\/app\/?$/, '').replace(/\/$/, '')}/setup#t=${encodeURIComponent(token)}`;
24
49
  }
25
50
 
26
51
  export async function runWebFirstSetup(deps: WebFirstSetupDeps): Promise<'link-shown' | 'fallback'> {
27
- const observe = (event: 'link-shown' | 'fallback', reason?: string, qr = false, browserOpened = false, remote: 'loopback' | 'tailnet' = 'loopback') => {
28
- try { debug.log('onboarding.web-first', event, { ...(reason ? { reason } : {}), qr, browserOpened, remote }); }
52
+ const startedAt = deps.startedAt ?? Date.now();
53
+ const print = deps.print ?? console.log;
54
+ const observe = (event: 'link-shown' | 'fallback', reason?: string, qr = false, browserOpened = false, remote: 'loopback' | 'tailnet' = 'loopback', ms?: number, lan?: 'shown' | 'loopback-bind' | 'no-address', ssh?: boolean) => {
55
+ try { debug.log('onboarding.web-first', event, { ...(reason ? { reason } : {}), qr, browserOpened, remote, ...(ms !== undefined ? { ms } : {}), ...(lan ? { lan, ssh } : {}) }); }
29
56
  catch { /* Observability must not block onboarding. */ }
30
57
  };
31
- if (deps.config.onboarding.webFirst !== true) { observe('fallback', 'disabled'); return 'fallback'; }
32
- if ((deps.isTty ?? (process.stdin.isTTY === true)) !== true) { observe('fallback', 'non-tty'); return 'fallback'; }
58
+ const fallback = (reason: string): 'fallback' => {
59
+ print(`웹 셋업을 사용할 수 없습니다 (${reason}). 터미널 설정으로 전환합니다.`);
60
+ observe('fallback', reason);
61
+ return 'fallback';
62
+ };
63
+ if (deps.config.onboarding.webFirst === false) { observe('fallback', 'disabled'); return 'fallback'; }
33
64
  if (deps.terminal) { observe('fallback', 'terminal'); return 'fallback'; }
34
65
 
35
- let shown: NexusShowResult;
36
- try {
37
- shown = await (deps.showNexus ?? (() => runNexusShow({ format: 'json', out: { log: () => {}, error: () => {} } })))();
38
- } catch { observe('fallback', 'daemon-unavailable'); return 'fallback'; }
39
- const running = shown.status === 'unregistered' || (shown.status === 'registered' && shown.instance?.alive === true);
40
- if (!running || !shown.urls?.pwa.loopback) { observe('fallback', 'daemon-unavailable'); return 'fallback'; }
66
+ const show = deps.showNexus ?? (() => runNexusShow({ format: 'json', out: { log: () => {}, error: () => {} } }));
67
+ let shown: NexusShowResult | undefined;
68
+ try { shown = await show(); } catch { /* A missing daemon may make inspection fail. */ }
69
+ const running = shown?.status === 'unregistered' || (shown?.status === 'registered' && shown.instance?.alive === true);
70
+ // A script, pipe or CI run never starts a daemon on its own: without a terminal the web path
71
+ // only uses a daemon that already answers health once. (install.sh runs first setup with
72
+ // stdin on /dev/tty, so the install → web path still starts one.)
73
+ if ((deps.isTty ?? (process.stdin.isTTY === true)) !== true) {
74
+ const rest = running ? shown?.urls?.rest.loopback : undefined;
75
+ const up = rest && shown?.urls?.pwa.loopback
76
+ ? await (deps.probeHealth ?? probeHealth)(joinRestHealthUrl(rest), 500) : false;
77
+ if (!up) { observe('fallback', 'non-tty'); return 'fallback'; }
78
+ }
79
+ const deadline = Date.now() + STARTUP_TIMEOUT_MS;
80
+ if (!running || !shown?.urls?.pwa.loopback) {
81
+ let launch: BgLaunchResult;
82
+ try {
83
+ launch = await (deps.startDaemon ?? (() => runBgLaunch({ out: { log: () => {}, error: () => {} } })))();
84
+ } catch { return fallback('daemon-start-failed'); }
85
+ if (launch.exitCode !== 0) return fallback('daemon-start-failed');
86
+ }
87
+
88
+ let healthy = false;
89
+ while (Date.now() < deadline) {
90
+ try {
91
+ shown = await show();
92
+ const live = shown.status === 'unregistered' || (shown.status === 'registered' && shown.instance?.alive === true);
93
+ if (live && shown.urls?.pwa.loopback && shown.urls.rest.loopback) {
94
+ const remaining = deadline - Date.now();
95
+ if (remaining > 0 && await (deps.probeHealth ?? probeHealth)(joinRestHealthUrl(shown.urls.rest.loopback), Math.min(remaining, 500))) {
96
+ healthy = true;
97
+ break;
98
+ }
99
+ }
100
+ } catch { /* A daemon may not have published its URLs yet. */ }
101
+ const remaining = deadline - Date.now();
102
+ if (remaining > 0) await Bun.sleep(Math.min(200, remaining));
103
+ }
104
+ if (!healthy) return fallback(running ? 'daemon-health-unavailable' : 'daemon-health-timeout');
105
+
106
+ if (!shown?.urls?.pwa.loopback) return fallback('daemon-unavailable');
41
107
 
42
108
  let token: string;
43
109
  try {
44
- const issue = deps.issueSetupLinkToken ?? (async () => {
45
- const modulePath = '../auth/setup-link-token.js';
46
- const mod = await import(modulePath) as { issueSetupLinkToken?: (options: Record<string, never>) => Promise<string | { token: string }> };
47
- if (typeof mod.issueSetupLinkToken !== 'function') throw new Error('issuer-missing');
48
- return mod.issueSetupLinkToken({});
49
- });
50
- const issued = await issue();
110
+ const issued = await (deps.issueSetupLinkToken ?? (() => Promise.resolve(issueSetupLinkToken({}))))();
51
111
  token = typeof issued === 'string' ? issued : issued?.token;
52
112
  if (!token) throw new Error('issuer-missing');
53
- } catch { observe('fallback', 'issuer-missing'); return 'fallback'; }
113
+ } catch { return fallback('issuer-missing'); }
54
114
 
55
- const print = deps.print ?? console.log;
56
115
  const link = setupUrl(shown.urls.pwa.loopback, token);
57
- const phoneLink = shown.urls.pwa.tailnet ? setupUrl(shown.urls.pwa.tailnet, token) : undefined;
116
+ const localUrl = new URL(shown.urls.pwa.loopback);
117
+ const port = localUrl.port || (localUrl.protocol === 'https:' ? '443' : '80');
118
+ let httpHost: string | undefined;
119
+ try { httpHost = (deps.httpHost ?? (() => findNexusLifecycleState()?.runtime?.httpHost))(); }
120
+ catch { /* Unknown bind must not produce a LAN link. */ }
121
+ const confirmedBind = typeof httpHost === 'string';
122
+ const reachable = confirmedBind && isLanReachableBind(httpHost);
123
+ let lanAddress: string | null = null;
124
+ if (reachable && httpHost !== undefined) {
125
+ if (isPrivateIpv4(httpHost.trim())) {
126
+ lanAddress = httpHost.trim();
127
+ } else {
128
+ try {
129
+ lanAddress = pickLanAddress({
130
+ interfaces: (deps.interfaces ?? networkInterfaces)(),
131
+ defaultRouteInterface: deps.defaultRouteInterface,
132
+ });
133
+ } catch { /* Optional LAN discovery must not block the local setup link. */ }
134
+ }
135
+ }
136
+ const lan: 'shown' | 'loopback-bind' | 'no-address' = !confirmedBind ? 'no-address' : !reachable ? 'loopback-bind' : lanAddress ? 'shown' : 'no-address';
137
+ const lanLink = lanAddress ? setupUrl(`http://${lanAddress}:${port}/app/`, token) : undefined;
138
+ const phoneLink = shown.urls.pwa.tailnet ? setupUrl(shown.urls.pwa.tailnet, token) : lanLink;
58
139
  print('브라우저에서 셋업을 이어가세요');
59
140
  print(link);
141
+ if (lanLink) {
142
+ print(`같은 와이파이의 폰이면: ${lanLink}`);
143
+ print('이 링크는 10분 안에 한 번만 열 수 있습니다');
144
+ } else if (lan === 'loopback-bind') {
145
+ print('같은 와이파이에서 열려면 `elanous nexus run` 을 루프백 없이 다시 띄우세요');
146
+ }
147
+ const linkShownMs = Date.now() - startedAt;
60
148
  let qr = false;
61
149
  if (phoneLink) {
62
150
  try {
@@ -66,14 +154,16 @@ export async function runWebFirstSetup(deps: WebFirstSetupDeps): Promise<'link-s
66
154
  }))(phoneLink);
67
155
  if (rendered) {
68
156
  print(rendered);
69
- print('같은 와이파이·tailnet 의 폰 카메라로 스캔하세요');
157
+ print(shown.urls.pwa.tailnet ? '같은 와이파이·tailnet 의 폰 카메라로 스캔하세요' : '같은 와이파이의 폰 카메라로 스캔하세요');
70
158
  qr = true;
71
159
  }
72
160
  } catch { /* QR is optional. */ }
73
161
  }
74
162
  print('터미널에서 하려면: `elanous setup --terminal`');
75
163
  let browserOpened = false;
76
- const why = browserUnavailableReason(deps.browserEnv ?? process.env, deps.browserPlatform ?? process.platform);
164
+ const env = deps.browserEnv ?? process.env;
165
+ const ssh = !!(env.SSH_CONNECTION || env.SSH_CLIENT || env.SSH_TTY);
166
+ const why = browserUnavailableReason(env, deps.browserPlatform ?? process.platform);
77
167
  if (why) {
78
168
  print(why);
79
169
  debug.log('browser.open', 'skipped', { reason: why.includes('ssh') ? 'ssh' : 'no-display' });
@@ -85,6 +175,11 @@ export async function runWebFirstSetup(deps: WebFirstSetupDeps): Promise<'link-s
85
175
  }))(link);
86
176
  } catch { /* The displayed link remains usable. */ }
87
177
  }
88
- observe('link-shown', undefined, qr, browserOpened, phoneLink ? 'tailnet' : 'loopback');
178
+ if (ssh) {
179
+ try {
180
+ print(`ssh -L ${port}:localhost:${port} ${(deps.username ?? (() => userInfo().username))()}@${(deps.hostname ?? hostname)()}`);
181
+ } catch { /* Optional SSH guidance must not block the setup link. */ }
182
+ }
183
+ observe('link-shown', undefined, qr, browserOpened, shown.urls.pwa.tailnet ? 'tailnet' : 'loopback', linkShownMs, lan, ssh);
89
184
  return 'link-shown';
90
185
  }
package/src/onboarding.ts CHANGED
@@ -1656,6 +1656,10 @@ export function needsOnboarding(cfg: UserConfig): boolean {
1656
1656
  return !cfg.onboarding.completed;
1657
1657
  }
1658
1658
 
1659
+ export function needsFirstRun(cfg: UserConfig): boolean {
1660
+ return !cfg.onboarding.completed && cfg.onboarding.ready !== true;
1661
+ }
1662
+
1659
1663
  /** γ (2026-04-28) · per-step wizard. Runs ONE of the 5 steps,
1660
1664
  * preserving every other field. Used by:
1661
1665
  *