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
@@ -266,4 +266,6 @@ export const AUTOPILOT_TOOL_IDS = [
266
266
  'memory_recall',
267
267
  'ops_status',
268
268
  'self_recall',
269
+ // CTX2 #23185 — 맥락 한 문(READ-ONLY 자기관측 원장에 더해졌다).
270
+ 'context_now',
269
271
  ] as const;
@@ -107,6 +107,8 @@ export async function runDaemonPromptTurn(opts: {
107
107
  surfaceResolutionReason?: SurfaceKindResolutionReason;
108
108
  /** Optional confirm channels for the triggering chat surface. */
109
109
  surfaceHitlChannels?: ConfirmChannel[];
110
+ /** Server-authenticated human owner for this request; absent for delegated or unverified callers. */
111
+ verifiedOwner?: { id: string };
110
112
  /** Optional structured-question channels for the triggering chat surface. */
111
113
  surfaceQuestionChannels?: QuestionChannel[];
112
114
  /** CWD for fs-bound tool dispatch (Read / Grep). Defaults to
@@ -114,6 +116,8 @@ export async function runDaemonPromptTurn(opts: {
114
116
  * `--tool-cwd` / `ELANOUS_TOOL_CWD` to keep `/v1/prompt` and ACP WS
115
117
  * on the same path-guard boundary. */
116
118
  toolCwd?: string;
119
+ /** Per-turn project instructions; unlike the base system preamble these must survive subsequent turns. */
120
+ projectInstructions?: string;
117
121
  /** Phase 4 (WT-A-3b) — external abort signal. When provided and
118
122
  * fired, the internal AbortController fans the abort through to
119
123
  * `runCoreTurn` (LLM stream + tool dispatch). Callers without an
@@ -226,6 +230,7 @@ export async function runDaemonPromptTurn(opts: {
226
230
  ...(request.source?.kind === 'daemon-api' && request.source.route === '/a2a'
227
231
  ? { requestOrigin: 'external-agent' as const } : {}),
228
232
  ...(request.userText ? { userText: request.userText } : {}),
233
+ ...(opts.verifiedOwner ? { verifiedOwner: opts.verifiedOwner } : {}),
229
234
  ...(opts.surface !== undefined || sourceResolution.surface !== 'unknown' ? { surface } : {}),
230
235
  ...(opts.surfaceHitlChannels ? { surfaceHitlChannels: opts.surfaceHitlChannels } : {}),
231
236
  ...(opts.surfaceQuestionChannels ? { surfaceQuestionChannels: opts.surfaceQuestionChannels } : {}),
@@ -283,6 +288,9 @@ export async function runDaemonPromptTurn(opts: {
283
288
  if (fast && !isFirstTurn) {
284
289
  messages.unshift({ role: 'system', content: fastPathGuidance });
285
290
  }
291
+ if (!isFirstTurn && opts.projectInstructions) {
292
+ messages.unshift({ role: 'system', content: opts.projectInstructions });
293
+ }
286
294
  const result = await runCoreTurn({
287
295
  sessionId: request.sessionId,
288
296
  userText: request.userText,
@@ -53,6 +53,7 @@ import {
53
53
  import type { CoreTurnDispatchTool } from '../core-turn/index.js';
54
54
  import { elanousSelfAccessPrompt } from '../agent/self-ambient.js';
55
55
  import { createToolCwdResolver, type ToolCwdResolver } from './tool-cwd.js';
56
+ import { resolveSessionProjectContext } from '../project/session-context.js';
56
57
  import { debug } from '../debug/log.js';
57
58
 
58
59
  /** C4 (2026-07-12) — arm the non-detached-PTY kill ONCE per turn signal.
@@ -579,7 +580,9 @@ export function createDaemonRunTurn(
579
580
  // moved this out of an inline closure to fix the user-message
580
581
  // persistence bug uniformly across all daemon paths.
581
582
  getMessages: ({ sessionId, userText, promptBlocks, promptMeta }) => {
582
- const baseSystemPrompt = composeDaemonSystemPrompt(opts.systemPrompt, promptMeta, sessionId);
583
+ const projectInstructions = resolveSessionProjectContext(sessionId)?.instructions;
584
+ const baseSystemPrompt = [composeDaemonSystemPrompt(opts.systemPrompt, promptMeta, sessionId), projectInstructions]
585
+ .filter(Boolean).join('\n\n');
583
586
  // Image-pipeline followup #4 (2026-05-05) — append daemon webterm
584
587
  // context (current ACP sessionId + active terminal summary) to
585
588
  // the system prompt when the webterm surface is active. Helper
@@ -720,8 +723,11 @@ export function createDaemonRunTurn(
720
723
  });
721
724
  debugBridge.activate();
722
725
  }
723
- if (opts.acpSessionCwd) {
724
- const resolver = createToolCwdResolver({ tools: opts.tools ?? 'none', toolCwd: turnCtx.cwd });
726
+ const projectCwd = resolveSessionProjectContext(turnCtx.sessionId)?.cwd;
727
+ if (projectCwd || opts.acpSessionCwd) {
728
+ // An ACP session's explicit cwd wins; the project folder is only the default when none was given (IA3 review).
729
+ const explicitCwd = opts.acpSessionCwd && turnCtx.cwd ? turnCtx.cwd : undefined;
730
+ const resolver = createToolCwdResolver({ tools: opts.tools ?? 'none', toolCwd: explicitCwd ?? projectCwd ?? turnCtx.cwd });
725
731
  await turnToolCwd.run(resolver, () => inner(turnCtx));
726
732
  } else {
727
733
  await inner(turnCtx);
@@ -16,6 +16,8 @@ import {
16
16
  dispatchBrowserRead,
17
17
  } from '../../tool-runtime/browser-runtime.js';
18
18
  import { askUserQuestionRuntime } from '../../tool-runtime/ask-user-question-runtime.js';
19
+ import { buildElanousHoldTool, buildPtyControlTool, dispatchElanousHold, dispatchPtyControl } from '../../tool-runtime/elanous-control-runtimes.js';
20
+ import { ptyAvailable } from '../../pty-shell/registry.js';
19
21
  import { dispatchToolByName, listToolRuntimes } from '../../tool-runtime/registry.js';
20
22
  import { ACP_SESSION_RUNTIMES } from '../../tool-runtime/acp-session-runtime.js';
21
23
  import { ClaudeSubscriptionNotAllowedError } from '../../policy/claude-subscription-guard.js';
@@ -340,6 +342,7 @@ export function toolSurface(kind: DaemonToolSurfaceKind, cfg?: import('../../use
340
342
  askUserQuestionRuntime.spec,
341
343
  ...ACP_SESSION_RUNTIMES.map((runtime) => runtime.spec),
342
344
  ...shared.specs, // L2 core + L3 finance(gated) — buildSharedAppTools 단일 출처(전 서피스 공용)
345
+ ...(ptyAvailable() ? [buildElanousHoldTool(), buildPtyControlTool()] : []),
343
346
  ];
344
347
 
345
348
  /** Shared dispatcher for chat-surface tools. Reused by 'chat' AND
@@ -392,11 +395,16 @@ export function toolSurface(kind: DaemonToolSurfaceKind, cfg?: import('../../use
392
395
  // L2 core + L3 finance(gated) — buildSharedAppTools 단일 dispatch · B5: 진행 한 줄(emitFeedback)·세션·호출 id 를 넘긴다.
393
396
  return shared.dispatch(name, args, {
394
397
  surface: 'tui',
398
+ ...(ctx.requestOrigin ? { requestOrigin: ctx.requestOrigin } : {}),
399
+ ...(ctx.verifiedOwner ? { verifiedOwner: ctx.verifiedOwner } : {}),
395
400
  ...(ctx.sessionId ? { sessionId: ctx.sessionId } : {}),
401
+ ...(ctx.surfaceHitlChannels ? { confirmChannels: ctx.surfaceHitlChannels } : {}),
396
402
  ...(ctx.toolCallId ? { toolCallId: ctx.toolCallId } : {}),
397
403
  ...(ctx.emitFeedback ? { emitFeedback: ctx.emitFeedback } : {}),
398
404
  });
399
405
  }
406
+ if (ptyAvailable() && name === 'ElanousHold') return dispatchElanousHold(args);
407
+ if (ptyAvailable() && name === 'PtyControl') return dispatchPtyControl(args);
400
408
  if (name === 'Bash') {
401
409
  // PLAN-ios-rich-dev-feedback-hydrate M3 (2026-05-13) — pass
402
410
  // sessionId + emitFeedback so dispatchBash emits tool.progress
@@ -61,6 +61,8 @@ export interface DaemonToolDispatchCtx {
61
61
  sessionId?: string;
62
62
  /** Trusted server-side classification of the current turn, never supplied as a tool argument. */
63
63
  requestOrigin?: RequestOrigin;
64
+ /** Owner principal verified at the server request boundary, not from input source metadata. */
65
+ verifiedOwner?: { id: string };
64
66
  /** Ingestion entry class. Omit for conservative external-verbatim fallback. */
65
67
  entry?: IngestionEntry;
66
68
  /** M5 PR 2 (PLAN-rich-dev-feedback-multi-surface · 2026-05-13) —
@@ -23,6 +23,8 @@ export interface DaemonWebSearchArgs {
23
23
  export interface DaemonWebSearchResult {
24
24
  query: string;
25
25
  providerName: string;
26
+ /** Absent for ordinary searches; signals whether X sources were actually cited. */
27
+ xSearch?: 'grok' | 'unavailable';
26
28
  hits: Array<{
27
29
  url: string;
28
30
  title: string;
@@ -41,6 +43,7 @@ export function buildWebSearchTool(): LLMToolSpec {
41
43
  'Search the public web via the daemon\'s configured provider (Grok / ' +
42
44
  'Firecrawl / etc.). When no key is available, falls back to keyless DuckDuckGo. ' +
43
45
  'Returns a ranked list of URLs + titles + snippets. ' +
46
+ 'For fact questions, answer directly from the snippets and URLs; read the full body only when insufficient. ' +
44
47
  'Pair with a follow-up Read or external WebFetch when the model needs ' +
45
48
  'the full article body.',
46
49
  parameters: {
@@ -89,6 +92,7 @@ export async function dispatchWebSearch(
89
92
  return {
90
93
  query,
91
94
  providerName: result.providerName,
95
+ ...(result.xSearch ? { xSearch: result.xSearch } : {}),
92
96
  hits: result.hits.map((h) => ({
93
97
  url: h.url,
94
98
  title: h.title,
@@ -0,0 +1,109 @@
1
+ import { chmodSync, mkdirSync, readFileSync, readdirSync } from 'node:fs';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { join, resolve } from 'node:path';
4
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
5
+ import { lastJsonObject, runGraph as defaultRunGraph, type GraphRunState } from '../graph-runner/runner.js';
6
+
7
+ const GRAPH = resolve(import.meta.dir, '../../plugins/card-followup/graphs/card-followup.yaml');
8
+ export type CardDetectDecision = 'card' | 'skip' | 'ambiguous';
9
+
10
+ export function cardShape(width?: number, height?: number): { decision: 'skip' | 'pass'; signal: string } {
11
+ if (!width || !height) return { decision: 'pass', signal: 'ratio:unknown' };
12
+ const ratio = Math.max(width, height) / Math.min(width, height);
13
+ if (ratio < 1.15) return { decision: 'skip', signal: 'ratio:square' };
14
+ if (ratio > 2.0) return { decision: 'skip', signal: 'ratio:screenshot' };
15
+ return { decision: 'pass', signal: `ratio:${ratio.toFixed(2)}` };
16
+ }
17
+ const EMAIL = /[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i;
18
+ const PHONE = /(?:\+?\d{1,3}[\s.-]?)?\(?\d{2,4}\)?[\s.-]?\d{3,4}[\s.-]?\d{4}/;
19
+ const WEB = /\b(?:https?:\/\/|www\.)\S+|\b[a-z0-9-]+\.(?:com|co\.kr|kr|io|ai|net|org)\b/i;
20
+ const TITLE = /대표|이사|팀장|부장|과장|실장|매니저|주식회사|\(주\)|\b(?:CEO|CTO|COO|CFO|Director|Manager|Founder|Inc|Ltd|Corp)\b/i;
21
+ export function cardText(ocr: string | null): { decision: CardDetectDecision; signal: string } {
22
+ if (ocr === null) return { decision: 'ambiguous', signal: 'ocr:unavailable' };
23
+ const chars = ocr.replace(/\s+/g, '').length;
24
+ if (chars < 15) return { decision: 'ambiguous', signal: 'ocr:chars<15' };
25
+ if (chars > 700) return { decision: 'skip', signal: 'ocr:document' };
26
+ const hits = ([['email', EMAIL], ['phone', PHONE], ['web', WEB], ['title', TITLE]] as const).filter(([, re]) => re.test(ocr)).map(([name]) => name);
27
+ const signal = `ocr:${hits.join(',') || 'none'}`;
28
+ if (hits.length >= 2) return { decision: 'card', signal };
29
+ return { decision: hits.length === 0 ? 'skip' : 'ambiguous', signal };
30
+ }
31
+ export function detectCard({ width, height, ocrText }: { width?: number; height?: number; ocrText: string | null }): { decision: CardDetectDecision; signal: string } {
32
+ const shape = cardShape(width, height);
33
+ return shape.decision === 'skip' ? { decision: 'skip', signal: shape.signal } : cardText(ocrText);
34
+ }
35
+
36
+ const obj = (value: unknown): Record<string, unknown> => value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
37
+ const text = (value: unknown): string => typeof value === 'string' ? value.trim() : '';
38
+ const line = (value: unknown): string => (typeof value === 'number' && Number.isFinite(value) ? String(value) : text(value)).replace(/[\r\n]+/g, ' ') || '—';
39
+
40
+ export class NotACardError extends Error {}
41
+ function isNotACard(state: GraphRunState): boolean {
42
+ if (state.status !== 'failed') return false;
43
+ const read = state.nodes.find((node) => node.nodeId === 'read-card');
44
+ if (!read || !read.ok) return false;
45
+ const output = lastJsonObject(read.output);
46
+ if (output?.outcome === 'ok' && output.card && typeof output.card === 'object') {
47
+ const card = obj(output.card);
48
+ return !['name', 'company', 'title', 'email', 'phone', 'url', 'linkedin'].some((field) => text(card[field]));
49
+ }
50
+ return output?.outcome === 'fail' && typeof output.reason === 'string'
51
+ && /\bnot a (?:business )?card\b|명함이?\s*아님|명함이?\s*아닙니다/i.test(output.reason);
52
+ }
53
+ function validateReport(report: Record<string, unknown>): void {
54
+ const card = obj(report.card), fit = obj(report.fit), approach = obj(report.approach);
55
+ const next = obj(report.nextAction), draft = obj(report.draft);
56
+ const score = fit.score;
57
+ if (report.sent !== false || !text(card.name) || !text(card.company)
58
+ || !(score === null || (typeof score === 'number' && Number.isFinite(score)))
59
+ || !text(fit.label) || !text(approach.problem) || !text(approach.proposal)
60
+ || !text(approach.channel) || !text(next.what) || !text(next.due)
61
+ || !text(draft.subject) || !text(draft.body)) {
62
+ throw new Error('incomplete or sent card report');
63
+ }
64
+ }
65
+
66
+ export async function runCardFollowup({ imagePath, ocrText, runGraph = defaultRunGraph, rootDir = effectiveInstanceRoot(), outDir, runId = randomUUID(), context }: {
67
+ imagePath: string;
68
+ ocrText: string | null;
69
+ runGraph?: typeof defaultRunGraph;
70
+ rootDir?: string;
71
+ outDir?: string;
72
+ runId?: string;
73
+ context?: string;
74
+ }): Promise<{ replies: [string, string, string]; followupPath?: string }> {
75
+ if (ocrText !== null && cardText(ocrText).decision !== 'card') throw new NotACardError('not a card');
76
+ const base = join(rootDir, 'graph-runs', 'card-followup');
77
+ const dir = outDir ?? join(base, runId);
78
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
79
+ chmodSync(base, 0o700);
80
+ chmodSync(dir, 0o700);
81
+ const statePath = join(base, `${runId}.json`);
82
+ const sealState = () => {
83
+ try { chmodSync(statePath, 0o600); } catch { /* runner may not have written state */ }
84
+ const contexts = `${statePath}.contexts`;
85
+ try {
86
+ chmodSync(contexts, 0o700);
87
+ for (const file of readdirSync(contexts)) chmodSync(join(contexts, file), 0o600);
88
+ } catch { /* no contexts yet */ }
89
+ };
90
+ try {
91
+ const state = await runGraph(GRAPH, { runId, deps: { root: rootDir }, input: {
92
+ image: imagePath, outDir: dir, ...(context ? { context } : {}),
93
+ } });
94
+ if (isNotACard(state)) throw new NotACardError('not a card');
95
+ if (state.status !== 'done') throw new Error('graph did not finish');
96
+ const report = obj(JSON.parse(readFileSync(join(dir, 'followup.json'), 'utf8')));
97
+ validateReport(report);
98
+ const card = obj(report.card), fit = obj(report.fit), approach = obj(report.approach);
99
+ const next = obj(report.nextAction), draft = obj(report.draft);
100
+ const summary = `① 요약\n${line(card.name)} · ${line(card.company)} · ${line(card.title)}\n타겟 판정: ${line(fit.score)} · ${line(fit.label)}`;
101
+ const strategy = `② 전략\n${[approach.problem, approach.proposal, approach.channel].map(line).join('\n')}\n다음 행동: ${line(next.what)} · ${line(next.due)}`;
102
+ const mail = `③ 팔로업 초안 (보내지 않았습니다)\n제목: ${line(draft.subject)}\n${text(draft.body)}`;
103
+ const followupPath = join(dir, 'followup.md');
104
+ readFileSync(followupPath);
105
+ return { replies: [summary, strategy, mail], followupPath };
106
+ } finally {
107
+ if (runGraph === defaultRunGraph) sealState();
108
+ }
109
+ }
@@ -0,0 +1,14 @@
1
+ /** U1a — how long an empty-input Ctrl+C stays armed (and its hint stays on screen). */
2
+ export const CTRL_C_ARM_MS = 2_000;
3
+
4
+ export function resolveCtrlCInInput({ text, now, armedAt }: {
5
+ text: string;
6
+ now: number;
7
+ armedAt: number | null;
8
+ }): { action: 'clear-input' | 'arm-exit' | 'exit'; armedAt: number | null; hint: string | null } {
9
+ if (text.length > 0) return { action: 'clear-input', armedAt: null, hint: null };
10
+ if (armedAt !== null && now >= armedAt && now - armedAt <= CTRL_C_ARM_MS) {
11
+ return { action: 'exit', armedAt: null, hint: null };
12
+ }
13
+ return { action: 'arm-exit', armedAt: now, hint: '한 번 더 누르면 나갑니다 · /quit' };
14
+ }
package/src/chat/index.ts CHANGED
@@ -19,6 +19,7 @@ import type { ModalSurface } from '../display/modal-stack.js';
19
19
  import type { ContentBlock } from '../llm.js';
20
20
  import { debug } from '../debug/log.js';
21
21
  import { matchTextInputGlobalAction } from './global-actions.js';
22
+ import { CTRL_C_ARM_MS, resolveCtrlCInInput } from './ctrl-c-in-input.js';
22
23
  import { isTextInputQuitChord } from './input-quit-chord.js';
23
24
  // P5 — leader-chord pass-through from input focus. chat.ts swallows
24
25
  // plain letters into its textarea buffer, so the resolver never sees
@@ -436,6 +437,7 @@ export const SLASH_COMMANDS: SlashCommand[] = [
436
437
  { name: 'model', aliases: ['m'], description: '모델 바꾸기 — /model <codex|terra|sol|luna|opus|sonnet|grok> (list + current when no arg). OpenAI 는 Codex(Responses API)만. effort 는 /reasoning.', subcommands: ['codex', 'terra', 'sol', 'luna', 'opus', 'sonnet', 'grok'] },
437
438
  { name: 'clear', aliases: ['cls'], description: '대화 기록 지우기' },
438
439
  { name: 'status', aliases: ['st'], description: '지금 상태 — 모델 · 연결 · 계정' },
440
+ { name: 'now', aliases: [], description: '현재 맥락과 출처 표 — /now [주제]' },
439
441
  { name: 'remaining', aliases: [], description: '계정별 남은 사용량' },
440
442
  { name: 'setup', aliases: [], description: '상세 설정 — /setup · /setup reset(다음 실행 때 마법사 다시)', subcommands: ['help', 'reset'] },
441
443
  { name: 'quit', aliases: ['q', 'exit'], description: '나가기' },
@@ -896,6 +898,10 @@ export async function textInput(opts: {
896
898
  let lastReportedLines = -1;
897
899
  let lineIdx = 0; // current line
898
900
  let colIdx = lines[0]!.length; // cursor at end of initial text
901
+ let ctrlCArmedAt: number | null = null;
902
+ let ctrlCHintTimer: ReturnType<typeof setTimeout> | null = null;
903
+ let ctrlCHint: string | null = null;
904
+ let ctrlCHintPainted = false;
899
905
 
900
906
  // KX2 — picker selection / navigation / async fetch caches live in
901
907
  // the shared state machine (chat-picker-state.ts). textInput keeps
@@ -1173,6 +1179,14 @@ export async function textInput(opts: {
1173
1179
  }
1174
1180
  prevDrawnLines = visibleLines;
1175
1181
 
1182
+ if (ctrlCHint) {
1183
+ writeTerminal(ansi.moveTo(row + 2, col) + '\x1b[2K' + C.muted(truncate(ctrlCHint, width)));
1184
+ ctrlCHintPainted = true;
1185
+ } else if (ctrlCHintPainted) {
1186
+ writeTerminal(ansi.moveTo(row + 2, col) + '\x1b[2K');
1187
+ ctrlCHintPainted = false;
1188
+ }
1189
+
1176
1190
  // Cursor — its buffer line is `lineIdx`; its screen row is the
1177
1191
  // bottom-anchored offset within the visible window. Critically,
1178
1192
  // `textBeforeCursor` reads from `lines[lineIdx]` (the buffer), not
@@ -1468,6 +1482,11 @@ export async function textInput(opts: {
1468
1482
  process.exit(0);
1469
1483
  }
1470
1484
 
1485
+ if (!(key.ctrl && (key.name === 'c' || key.name === 'ㅊ') && !key.shift && !key.alt)) {
1486
+ ctrlCArmedAt = null;
1487
+ ctrlCHint = null;
1488
+ }
1489
+
1471
1490
  // A bracketed-paste envelope is one atomic event. Handle it before
1472
1491
  // host routing so embedded newlines cannot reach a submit handler.
1473
1492
  if (key.name === 'paste') {
@@ -1571,6 +1590,40 @@ export async function textInput(opts: {
1571
1590
  continue;
1572
1591
  }
1573
1592
 
1593
+ if (key.ctrl && (key.name === 'c' || key.name === 'ㅊ') && !key.shift && !key.alt) {
1594
+ const text = lines.join('\n');
1595
+ const result = resolveCtrlCInInput({ text, now: Date.now(), armedAt: ctrlCArmedAt });
1596
+ debug.log('chat.input', 'ctrl-c', { action: result.action, length: text.length });
1597
+ ctrlCArmedAt = result.armedAt;
1598
+ ctrlCHint = result.hint;
1599
+ if (ctrlCHintTimer) clearTimeout(ctrlCHintTimer);
1600
+ ctrlCHintTimer = null;
1601
+ if (result.action === 'arm-exit') {
1602
+ // U1a — the hint promises «one more press exits» only while that is true.
1603
+ const armedAt = result.armedAt;
1604
+ ctrlCHintTimer = setTimeout(() => {
1605
+ ctrlCHintTimer = null;
1606
+ if (ctrlCArmedAt !== armedAt) return;
1607
+ ctrlCArmedAt = null;
1608
+ ctrlCHint = null;
1609
+ drawAll();
1610
+ }, CTRL_C_ARM_MS + 50);
1611
+ ctrlCHintTimer.unref?.();
1612
+ }
1613
+ if (result.action === 'exit') return submitBufferResult('/quit');
1614
+ if (result.action === 'clear-input') {
1615
+ lines = [''];
1616
+ lineIdx = 0;
1617
+ colIdx = 0;
1618
+ historyIdx = -1;
1619
+ savedCurrentInput = '';
1620
+ onUserBufferEdit();
1621
+ await picker.refresh(bufView());
1622
+ }
1623
+ drawAll();
1624
+ continue;
1625
+ }
1626
+
1574
1627
  const globalDispatcher = dispatchGlobalAction;
1575
1628
  const globalAction = globalDispatcher
1576
1629
  ? matchTextInputGlobalAction(key, {
@@ -33,6 +33,7 @@ import type {
33
33
  } from '../index.js';
34
34
  import { filterSlashCommands } from '../index.js';
35
35
  import { filterInputMatches } from '../../input/query-match.js';
36
+ import { readTuiSlashAudience, slashMaturity, slashVisibleFor } from '../../maturity/tui-slash-maturity.js';
36
37
 
37
38
  /** Read-only snapshot of the textInput buffer handed to state on
38
39
  * every public call. The state machine never mutates it; it only
@@ -234,8 +235,11 @@ export function createPickerState(deps: PickerDeps): PickerState {
234
235
  let currentAtItems: AtCandidate[] = [];
235
236
  let currentSkillItems: SkillCandidate[] = [];
236
237
 
237
- const filteredSlash = (buf: PickerBufferView): SlashCommand[] =>
238
- filterSlashCommands((buf.lines[0] ?? '').slice(1), deps.commands);
238
+ const filteredSlash = (buf: PickerBufferView): SlashCommand[] => {
239
+ const { role, showBeta } = readTuiSlashAudience();
240
+ return filterSlashCommands((buf.lines[0] ?? '').slice(1), deps.commands)
241
+ .filter((cmd) => (role === 'owner' && slashMaturity(cmd.name) === undefined) || slashVisibleFor(cmd.name, role, { showBeta }));
242
+ };
239
243
 
240
244
  const refreshArgs = async (buf: PickerBufferView): Promise<ArgSuggestion[]> => {
241
245
  const ctx = parseArgContext(buf, deps.commands);
@@ -3,6 +3,7 @@ import { resolve } from 'node:path';
3
3
  import { getUserConfig, reloadUserConfig } from '../user-config.js';
4
4
  import { handleOnboardingRefusal, needsOnboarding, runOnboarding } from '../onboarding.js';
5
5
  import { runTurn, ensureCliSession, sessionBudget } from '../session/chat.js';
6
+ import { suggestProjectForFolder } from '../project/project-store.js';
6
7
  import { NoLlmProviderAvailableError, noProviderAvailableMessage } from '../llm.js';
7
8
  import { resolveSessionId, getActiveSessionId, setActiveSessionId } from '../session/index.js';
8
9
  import { getHarnessSpace } from '../harness/harness-space.js';
@@ -433,6 +434,12 @@ export async function runChatTurnCli(opts: {
433
434
  }
434
435
  const session = ensureCliSession(opts.cfg, resolvedSessionIdHint);
435
436
  setActiveSessionId(session.id);
437
+ if (!opts.json && (!resolvedSessionIdHint || session.id !== resolvedSessionIdHint)) {
438
+ try {
439
+ const project = suggestProjectForFolder(process.cwd());
440
+ if (project) console.log(`Project suggestion: ${project.name} (${project.id})`);
441
+ } catch { /* suggestions must not interrupt a CLI conversation */ }
442
+ }
436
443
  const harnessSpace = getHarnessSpace();
437
444
  // Tag the debug log with this session id so every event in this
438
445
  // process attributes correctly. enrichDebugRecord picks up the
@@ -1,4 +1,5 @@
1
1
  import type { Command } from 'commander';
2
+ import { projectDecisionsToLinear } from '../decisions/decision-linear-projection.js';
2
3
  import { DecisionLedger, importDecisionMarkdown, type DecisionCategory, type DecisionLedgerOptions, type DecisionOption, type DecisionTrack, type DecisionEntry } from '../decisions/decision-ledger.js';
3
4
 
4
5
  const repeat = (value: string, values: string[]) => [...values, value];
@@ -49,22 +50,31 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
49
50
  const root = program.command('decisions').description('대표 결정 원장 · 로컬 전용');
50
51
  const emit = (value: unknown, json?: boolean, text?: string) => out.log(json ? JSON.stringify(value) : text ?? JSON.stringify(value));
51
52
  const fail = (action: () => void) => { try { action(); } catch (e) { throw new Error(`decisions: ${e instanceof Error ? e.message : String(e)}`); } };
53
+ root.command('linear-sync').description('열린 결정을 COO Linear 프로젝트에 투영하고 닫힌 결정을 동기화한다')
54
+ .option('--dry-run').option('--json')
55
+ .action(async (o: { dryRun?: boolean; json?: boolean }) => {
56
+ const result = await projectDecisionsToLinear({ stateDir: config.stateDir, dryRun: o.dryRun });
57
+ emit(result, o.json, result.reason ?? `생성 ${result.created} · 닫음 ${result.closed} · 건너뜀 ${result.skipped} · 실패 ${result.failed}${result.plan?.length ? `\n${result.plan.map(p => `${p.action} ${p.decisionId}${p.issue ? ` ${p.issue}` : ''}`).join('\n')}` : ''}`);
58
+ });
52
59
  root.command('raise').description('SCQA·선택지와 권고로 결정 항목을 올린다')
53
60
  .requiredOption('--title <text>').requiredOption('--category <category>')
54
61
  .requiredOption('--s <text>').requiredOption('--c <text>').option('--q <text>').option('--a <text>')
55
62
  .requiredOption('--option <key=label:consequence>', '선택지 (두 번 이상)', repeat, [] as string[])
56
63
  .option('--recommend <key>').option('--why <text>').option('--skip-recommend <reason>')
57
64
  .option('--track <track>').option('--agent <agent>').option('--session <id>')
65
+ .option('--resume-question <qid>').option('--run <runId>')
58
66
  .option('--ref <url>', '참조 (반복)', repeat, [] as string[])
59
67
  .option('--due <when>', '기한 — UTC ISO(2026-10-04T09:00:00Z) 또는 +Nh(지금부터 N시간) · 기한 2시간 전 텔레그램·디스코드로 다시 알린다')
60
68
  .option('--json')
61
- .action((o: { due?: string; title: string; category: DecisionCategory; s: string; c: string; q?: string; a?: string; option: string[]; recommend?: string; why?: string; skipRecommend?: string; track?: DecisionTrack; agent?: string; session?: string; ref: string[]; json?: boolean }) => fail(() => {
69
+ .action((o: { due?: string; title: string; category: DecisionCategory; s: string; c: string; q?: string; a?: string; option: string[]; recommend?: string; why?: string; skipRecommend?: string; track?: DecisionTrack; agent?: string; session?: string; resumeQuestion?: string; run?: string; ref: string[]; json?: boolean }) => fail(() => {
70
+ if (o.run !== undefined && o.resumeQuestion === undefined) throw new Error('--run requires --resume-question');
62
71
  if (o.skipRecommend !== undefined && (o.recommend !== undefined || o.why !== undefined)) throw new Error('choose recommendation or skip, not both');
63
72
  if (o.skipRecommend === undefined && (!o.recommend || !o.why)) throw new Error('--recommend and --why required, or --skip-recommend <reason>');
64
73
  const options: DecisionOption[] = o.option.map(parseOption);
65
74
  const entry = new DecisionLedger(config).raise({ title: o.title, category: o.category, scqa: { s: o.s, c: o.c, ...(o.q ? { q: o.q } : {}), ...(o.a ? { a: o.a } : {}) }, options,
66
75
  recommendation: o.skipRecommend !== undefined ? { skipped: true, reason: o.skipRecommend } : { option: o.recommend!, why: o.why! },
67
76
  raisedBy: { agent: agent(o.agent), ...(o.track ? { track: o.track } : {}), ...(o.session ? { session: o.session } : {}) }, ...(o.ref.length ? { refs: o.ref } : {}),
77
+ ...(o.resumeQuestion !== undefined ? { resume: { questionId: o.resumeQuestion, ...(o.run !== undefined ? { runId: o.run } : {}) } } : {}),
68
78
  ...(o.due ? { dueAt: dueAt(o.due) } : {}) });
69
79
  emit(entry, o.json, `올림: ${formatDecisionRow(entry)}`);
70
80
  }));
@@ -83,8 +93,20 @@ export function registerDecisionsCommands(program: Command, config: DecisionLedg
83
93
  if (o.auto && !o.delegation?.trim()) throw new Error('--auto requires --delegation');
84
94
  if (!o.auto && (o.delegation || o.track || o.agent)) throw new Error('delegation/track/agent require --auto');
85
95
  const by = o.auto ? { kind: 'auto' as const, agent: agent(o.agent), delegation: o.delegation!, ...(o.track ? { track: o.track } : {}) } : { kind: 'human' as const };
86
- const entry = new DecisionLedger(config).decide(id, choice, by, o.note);
87
- emit(entry, o.json, `결정: ${formatDecisionDetail(entry)}`);
96
+ const { entry, delivery } = new DecisionLedger(config).decideWithDelivery(id, choice, by, o.note);
97
+ if (delivery && !delivery.ok) {
98
+ // The decision is recorded; only the answer to the waiting run failed — say so and how to retry, never «success».
99
+ const hint = `⚠ 답 전달 실패(${delivery.questionId} · ${delivery.reason}) — 결정은 기록됐다 · 다시: elanous decisions retry-answer ${entry.id}`;
100
+ emit({ ...entry, delivery }, o.json, `결정: ${formatDecisionDetail(entry)}\n${hint}`);
101
+ process.exitCode = 3;
102
+ return;
103
+ }
104
+ emit(delivery ? { ...entry, delivery } : entry, o.json, `결정: ${formatDecisionDetail(entry)}`);
105
+ }));
106
+ root.command('retry-answer <id>').description('기록된 결정의 대기 질문 답 전달만 재시도한다').option('--json')
107
+ .action((id: string, o: { json?: boolean }) => fail(() => {
108
+ const entry = new DecisionLedger(config).retryAnswer(id);
109
+ emit(entry, o.json, `답 전달: ${entry.id} → ${entry.resume?.questionId}`);
88
110
  }));
89
111
  root.command('add-options <id>').description('선택지가 미기재된 과거 항목에 확인된 선택지를 추가')
90
112
  .requiredOption('--option <key=label:consequence>', '선택지 (두 번 이상)', repeat, [] as string[])
@@ -0,0 +1,68 @@
1
+ import { readFileSync, statSync } from 'node:fs';
2
+ import { debug } from '../debug/log.js';
3
+
4
+ export interface DoctorBundleUploadOptions {
5
+ path: string;
6
+ files: readonly string[];
7
+ uploadUrl?: string;
8
+ confirm: (message: string) => Promise<boolean>;
9
+ fetch: typeof globalThis.fetch;
10
+ yes?: boolean;
11
+ /** Present the inventory before either consent or transport; JSON callers can use stderr. */
12
+ announce?: (contents: string) => void;
13
+ /** Pass the size returned by buildDoctorBundle, if available. */
14
+ bytes?: number;
15
+ }
16
+
17
+ export interface DoctorBundleUploadResult {
18
+ path: string;
19
+ uploaded: boolean;
20
+ code?: string;
21
+ reason?: string;
22
+ exitCode: number;
23
+ message: string;
24
+ }
25
+
26
+ /** The bundle is local until both an HTTPS destination and affirmative consent exist. */
27
+ export async function uploadDoctorBundle({ path, files, uploadUrl, confirm, fetch, yes = false, bytes, announce = console.log }: DoctorBundleUploadOptions): Promise<DoctorBundleUploadResult> {
28
+ const size = bytes ?? (() => { try { return statSync(path).size; } catch { return undefined; } })();
29
+ const skipped = (reason: string, message: string): DoctorBundleUploadResult => {
30
+ debug.log('doctor.bundle', 'upload-skipped', { bytes: size, reason });
31
+ return { path, uploaded: false, reason, exitCode: 0, message };
32
+ };
33
+ if (!uploadUrl?.trim()) return skipped('no-recipient', `수신처가 아직 정해지지 않았습니다 — 파일을 지원에 직접 보내 주세요: ${path}`);
34
+ let destination: URL;
35
+ try {
36
+ destination = new URL(uploadUrl.trim());
37
+ if (destination.protocol !== 'https:' || !destination.hostname || destination.username || destination.password) throw new Error('invalid destination');
38
+ } catch {
39
+ return skipped('invalid-recipient', `수신처가 유효한 HTTPS 주소가 아닙니다 — 파일을 지원에 직접 보내 주세요: ${path}`);
40
+ }
41
+ const contents = `내용 목록 (${size === undefined ? '크기 확인 불가' : `${size} bytes`}):\n${files.map((file) => ` ${file}`).join('\n')}`;
42
+ announce(contents);
43
+ if (!yes) {
44
+ let agreed = false;
45
+ try { agreed = await confirm('올릴까요? (y/N) '); } catch { /* An unavailable prompt is a refusal. */ }
46
+ if (!agreed) {
47
+ debug.log('doctor.bundle', 'declined', { bytes: size, reason: 'consent-declined' });
48
+ return { path, uploaded: false, reason: 'consent-declined', exitCode: 0, message: `업로드하지 않았습니다: ${path}` };
49
+ }
50
+ }
51
+ const failed = (reason: string): DoctorBundleUploadResult => {
52
+ debug.log('doctor.bundle', 'upload-failed', { bytes: size, reason });
53
+ return { path, uploaded: false, reason, exitCode: 1, message: `업로드 실패 (${reason}) — 파일: ${path} — 다시 시도해 주세요.` };
54
+ };
55
+ try {
56
+ const response = await fetch(destination.href, {
57
+ method: 'POST', headers: { 'Content-Type': 'application/gzip' }, body: readFileSync(path), redirect: 'manual',
58
+ });
59
+ if (!response.ok) return failed(`HTTP ${response.status}`);
60
+ const data: unknown = await response.json();
61
+ const code = data && typeof data === 'object' && !Array.isArray(data) ? (data as { code?: unknown }).code : undefined;
62
+ if (typeof code !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/.test(code)) return failed('진단 코드 응답이 올바르지 않습니다');
63
+ debug.log('doctor.bundle', 'uploaded', { bytes: size, reason: 'success' });
64
+ return { path, uploaded: true, code, exitCode: 0, message: `진단 코드: ${code} — 이 코드만 지원에 알려 주세요` };
65
+ } catch {
66
+ return failed('네트워크 또는 파일 읽기 오류');
67
+ }
68
+ }
@@ -38,6 +38,7 @@ import { describeModes, formatModeLine, type DoctorMode } from './doctor-modes.j
38
38
  import { formatDoctorLocalLlm, probeDoctorLocalLlm, type DoctorLocalLlm } from './doctor-local-llm.js';
39
39
  import type { LlmInventory } from '../llm/local-manager/types.js';
40
40
  import { buildDoctorBundle } from './doctor-bundle.js';
41
+ import { uploadDoctorBundle } from './doctor-bundle-upload.js';
41
42
 
42
43
  function defaultCheckPythonEnv(): { status: 'ok' | 'fixable' | 'manual'; evidence: string; remedy?: string } {
43
44
  const c = checkPythonEnv(false);
@@ -193,6 +194,9 @@ export interface DoctorCliDeps extends DoctorOptions, Pick<DoctorFixDeps, 'home'
193
194
  adviceInteractive?: boolean;
194
195
  /** Local-manager inventory seam; default calls getInventory(). */
195
196
  localLlmInventory?: () => Promise<LlmInventory>;
197
+ /** Inject the upload transport and consent for isolated CLI tests. */
198
+ uploadFetch?: typeof globalThis.fetch;
199
+ confirmBundleUpload?: (message: string) => Promise<boolean>;
196
200
  }
197
201
 
198
202
  const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../..');
@@ -1217,15 +1221,21 @@ export function registerDoctorCommand(program: Command, deps: DoctorCliDeps = {}
1217
1221
  .option('--json', 'structured output')
1218
1222
  .option('--credentials', 'show per-credential details in human-readable output')
1219
1223
  .option('--bundle', 'write a redacted diagnostics archive for support')
1224
+ .option('--upload', 'send the bundle to diagnostics.uploadUrl after consent (requires --bundle)')
1220
1225
  .option('--out <dir>', 'output directory for --bundle')
1221
1226
  .option('--fix', 'show repairs; git installation asks on a TTY (other repairs require --yes)')
1222
1227
  .option('--advise', 'ask the configured LLM to rank catalog repairs (read-only advice)')
1223
- .option('--yes', 'apply planned doctor repairs (requires --fix)')
1228
+ .option('--yes', 'apply planned doctor repairs (--fix), or confirm bundle upload (--bundle --upload)')
1224
1229
  .option('--sudo', 'also run the planned sudo install lines — only where `sudo -n true` works (requires --fix --yes)')
1225
1230
  .option('--restart', 'restart the nexus service when it runs a different version than this installed copy, then verify it (requires --fix --yes · interrupts bots, terminals and running turns)')
1226
- .action(async (opts: { json?: boolean; credentials?: boolean; bundle?: boolean; out?: string; fix?: boolean; advise?: boolean; yes?: boolean; sudo?: boolean; restart?: boolean }) => {
1231
+ .action(async (opts: { json?: boolean; credentials?: boolean; bundle?: boolean; upload?: boolean; out?: string; fix?: boolean; advise?: boolean; yes?: boolean; sudo?: boolean; restart?: boolean }) => {
1232
+ if (opts.upload && !opts.bundle) {
1233
+ err.error('--upload requires --bundle');
1234
+ setExitCode(1);
1235
+ return;
1236
+ }
1227
1237
  if (opts.bundle) {
1228
- if (opts.fix || opts.advise || opts.yes || opts.sudo || opts.restart) {
1238
+ if (opts.fix || opts.advise || opts.sudo || opts.restart || (opts.yes && !opts.upload)) {
1229
1239
  err.error('--bundle cannot be combined with repair or advice options');
1230
1240
  setExitCode(1);
1231
1241
  return;
@@ -1235,7 +1245,31 @@ export function registerDoctorCommand(program: Command, deps: DoctorCliDeps = {}
1235
1245
  const doctorReport = runDoctor(deps);
1236
1246
  if (doctorReport.ok) doctorReport.localLlm = await probeDoctorLocalLlm(deps.localLlmInventory);
1237
1247
  const result = buildDoctorBundle({ outDir: opts.out ?? process.cwd(), doctorOptions: deps, doctorReport });
1238
- out.log(opts.json ? JSON.stringify(result) : [`Diagnostics: ${result.path} (${result.bytes} bytes)`, 'Contents:', ...result.files.map((file) => ` ${file}`)].join('\n'));
1248
+ if (opts.upload) {
1249
+ let uploadUrl: string | undefined;
1250
+ try { uploadUrl = (deps.userConfig ?? (deps.getUserConfig ?? getUserConfig)()).diagnostics?.uploadUrl; }
1251
+ catch {
1252
+ const reason = '설정을 읽을 수 없습니다';
1253
+ debug.log('doctor.bundle', 'upload-failed', { bytes: result.bytes, reason: 'config-read-failed' });
1254
+ if (opts.json) out.log(JSON.stringify({ path: result.path, uploaded: false, reason }));
1255
+ else err.error(`업로드 실패 (${reason}) — 파일: ${result.path} — 다시 시도해 주세요.`);
1256
+ setExitCode(1);
1257
+ return;
1258
+ }
1259
+ const uploaded = await uploadDoctorBundle({
1260
+ ...result,
1261
+ uploadUrl,
1262
+ yes: opts.yes,
1263
+ announce: (contents) => { if (opts.json) err.error(contents); else out.log(contents); },
1264
+ confirm: deps.confirmBundleUpload ?? ((message) => confirmDoctorAdvice(message, opts.json === true)),
1265
+ fetch: deps.uploadFetch ?? globalThis.fetch,
1266
+ });
1267
+ if (opts.json) out.log(JSON.stringify({ path: uploaded.path, uploaded: uploaded.uploaded, ...(uploaded.code ? { code: uploaded.code } : {}), ...(uploaded.reason ? { reason: uploaded.reason } : {}) }));
1268
+ else out.log(uploaded.message);
1269
+ if (uploaded.exitCode) setExitCode(uploaded.exitCode);
1270
+ } else {
1271
+ out.log(opts.json ? JSON.stringify(result) : [`Diagnostics: ${result.path} (${result.bytes} bytes)`, 'Contents:', ...result.files.map((file) => ` ${file}`)].join('\n'));
1272
+ }
1239
1273
  } catch {
1240
1274
  err.error('Could not create diagnostics archive.');
1241
1275
  setExitCode(1);