elanous 0.2.6 → 0.2.8

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 (517) hide show
  1. package/.env.example +10 -7
  2. package/README.md +4 -0
  3. package/apps/pwa/out/404/index.html +1 -1
  4. package/apps/pwa/out/404.html +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/{3995-bee512a7063036ce.js → 2375-cb6debea56cce4fb.js} +1 -1
  12. package/apps/pwa/out/_next/static/chunks/2415.ed6428ff334c7ce2.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +25 -0
  16. package/apps/pwa/out/_next/static/chunks/{8d0d9faf-97887ff99713b84e.js → 2ea96958-e8c7e112de50b067.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/{5329.8b7e4bca684b6eec.js → 3403.4bc97b4066945a94.js} +2 -2
  18. package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{7633.0654fe6ea259c1ee.js → 4323.c5dfb6f503304775.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/4836-3084c58c1725a40b.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{2984-977cfa339fcd65a5.js → 5080-1613752891fcadb4.js} +3 -3
  24. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{763-7d0e1913b5074e98.js → 5791-bb82743fa6299562.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/{4240-7153881b0b377306.js → 6062-73e68343a9814f6a.js} +1 -1
  27. package/apps/pwa/out/_next/static/chunks/6090-85a3f05f954e5697.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/6284-69db415193d5f8bd.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/7032-f4ef698518fba61c.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/{91ff6dda-3b33d42d20657429.js → 8046cadf-211ca3c0e00f2b72.js} +1 -1
  38. package/apps/pwa/out/_next/static/chunks/8067-d976b441a104ab74.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8519-5632377cce994f86.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8894-7317998f6cb97d8c.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/9454-a3e0953307216c58.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/9740-8f5ff96c522b5f55.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/app/approvals/page-9aa47b0bc6d570ff.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f4d2ecbbae6088d6.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/board/page-2053e49930c82748.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/botlab/page-d4b6df905f185055.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/bots/page-a70ba27c33003dd0.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/chat/page-186fc6952f027acc.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/consult/page-18166f885d831d3e.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/app/control/page-1c9d6cfe68b121c2.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/design-check/page-cbbe03c0da7b081a.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/editor/page-c108ff1fdb665c97.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/exec/page-147a328753d983e2.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/field/page-799395a9df7d95aa.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/intake/page-6a8158b71d1fe9d7.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/layout-9567560270857531.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/live/page-e7ed3d010153d818.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/market/page-c0c0d19d51342d3e.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2e002ad8faa43291.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/morning/page-b672e02e4bec8deb.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/not-found-1ba4a5d857276334.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/observatory/page-9db2226f38c542fb.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/page-70ee65f5f7a151dc.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/reflection/page-0bb8e43203efb23b.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-092e1bcf27d751cc.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/sessions/page-eb52580c4b75b905.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7464c1987dd76e6d.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/settings/page-e573437b0a1c728f.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-294300625e49e4d3.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/setup/page-085847b088675978.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/share/page-9fe9d38c36999eb4.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/showroom/page-d8ab4d1489223459.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/tasks/page-6141f67f531d8b6a.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/term/page-295a02b1026b8255.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/trace/page-1eb9a0e1e054209d.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/vault/page-82efa177a30f3741.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d0be51cec4f62606.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/app/workflows/page-2e367075ffdbc062.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/workspace/page-647ed2b66c1d49f1.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ba058c56e38f2792.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/main-app-6870f30ea99f8346.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/{webpack-37b8bf78a3c6eec5.js → webpack-e5bea36f183b25e6.js} +1 -1
  95. package/apps/pwa/out/_next/static/css/5ef72a618a8994f3.css +1 -0
  96. package/apps/pwa/out/_next/static/lywc8m_HDzH9MKSDQhyEj/_buildManifest.js +1 -0
  97. package/apps/pwa/out/approvals/index.html +1 -1
  98. package/apps/pwa/out/approvals/index.txt +22 -22
  99. package/apps/pwa/out/autopilot/index.html +1 -1
  100. package/apps/pwa/out/autopilot/index.txt +22 -22
  101. package/apps/pwa/out/board/index.html +1 -1
  102. package/apps/pwa/out/board/index.txt +22 -22
  103. package/apps/pwa/out/botlab/index.html +1 -1
  104. package/apps/pwa/out/botlab/index.txt +21 -21
  105. package/apps/pwa/out/bots/index.html +1 -1
  106. package/apps/pwa/out/bots/index.txt +21 -21
  107. package/apps/pwa/out/chat/index.html +1 -1
  108. package/apps/pwa/out/chat/index.txt +21 -21
  109. package/apps/pwa/out/consult/index.html +1 -0
  110. package/apps/pwa/out/consult/index.txt +32 -0
  111. package/apps/pwa/out/control/index.html +1 -1
  112. package/apps/pwa/out/control/index.txt +22 -22
  113. package/apps/pwa/out/design-check/index.html +1 -1
  114. package/apps/pwa/out/design-check/index.txt +22 -22
  115. package/apps/pwa/out/editor/index.html +1 -1
  116. package/apps/pwa/out/editor/index.txt +22 -22
  117. package/apps/pwa/out/exec/index.html +1 -0
  118. package/apps/pwa/out/exec/index.txt +32 -0
  119. package/apps/pwa/out/field/index.html +1 -0
  120. package/apps/pwa/out/field/index.txt +32 -0
  121. package/apps/pwa/out/healthz +1 -1
  122. package/apps/pwa/out/index.html +1 -1
  123. package/apps/pwa/out/index.txt +21 -21
  124. package/apps/pwa/out/intake/index.html +1 -1
  125. package/apps/pwa/out/intake/index.txt +22 -22
  126. package/apps/pwa/out/live/index.html +1 -1
  127. package/apps/pwa/out/live/index.txt +22 -22
  128. package/apps/pwa/out/market/index.html +1 -1
  129. package/apps/pwa/out/market/index.txt +21 -21
  130. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  131. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  132. package/apps/pwa/out/morning/index.html +1 -1
  133. package/apps/pwa/out/morning/index.txt +22 -22
  134. package/apps/pwa/out/observatory/index.html +1 -1
  135. package/apps/pwa/out/observatory/index.txt +22 -22
  136. package/apps/pwa/out/reflection/index.html +1 -1
  137. package/apps/pwa/out/reflection/index.txt +22 -22
  138. package/apps/pwa/out/scheduler/index.html +1 -1
  139. package/apps/pwa/out/scheduler/index.txt +22 -22
  140. package/apps/pwa/out/sessions/index.html +1 -1
  141. package/apps/pwa/out/sessions/index.txt +21 -21
  142. package/apps/pwa/out/settings/devices/index.html +1 -1
  143. package/apps/pwa/out/settings/devices/index.txt +22 -22
  144. package/apps/pwa/out/settings/index.html +1 -1
  145. package/apps/pwa/out/settings/index.txt +22 -22
  146. package/apps/pwa/out/setup/done/index.html +1 -1
  147. package/apps/pwa/out/setup/done/index.txt +22 -22
  148. package/apps/pwa/out/setup/index.html +1 -1
  149. package/apps/pwa/out/setup/index.txt +22 -22
  150. package/apps/pwa/out/share/index.html +1 -1
  151. package/apps/pwa/out/share/index.txt +22 -22
  152. package/apps/pwa/out/showroom/index.html +1 -1
  153. package/apps/pwa/out/showroom/index.txt +21 -21
  154. package/apps/pwa/out/tasks/index.html +1 -1
  155. package/apps/pwa/out/tasks/index.txt +22 -22
  156. package/apps/pwa/out/term/index.html +1 -1
  157. package/apps/pwa/out/term/index.txt +22 -22
  158. package/apps/pwa/out/trace/index.html +1 -1
  159. package/apps/pwa/out/trace/index.txt +22 -22
  160. package/apps/pwa/out/vault/index.html +1 -1
  161. package/apps/pwa/out/vault/index.txt +22 -22
  162. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  163. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  164. package/apps/pwa/out/workflows/index.html +1 -1
  165. package/apps/pwa/out/workflows/index.txt +22 -22
  166. package/apps/pwa/out/workspace/index.html +1 -1
  167. package/apps/pwa/out/workspace/index.txt +22 -22
  168. package/apps/pwa/out/worktrees/index.html +1 -1
  169. package/apps/pwa/out/worktrees/index.txt +22 -22
  170. package/bin/elanous.cjs +107 -0
  171. package/graphs/field/field-feed.yaml +24 -0
  172. package/graphs/field/recipes.yaml +12 -0
  173. package/graphs/landing/landing-heal.yaml +3 -1
  174. package/graphs/landing/recipes.yaml +3 -0
  175. package/graphs/release/recipes.yaml +10 -0
  176. package/graphs/release/release-loop.yaml +10 -3
  177. package/graphs/test-diet/recipes.yaml +9 -0
  178. package/graphs/test-diet/test-diet.yaml +22 -0
  179. package/package.json +6 -5
  180. package/persona-presets/_index.yaml +10 -0
  181. package/persona-presets/_schema.json +146 -0
  182. package/persona-presets/dana.yaml +26 -0
  183. package/persona-presets/haru.yaml +27 -0
  184. package/persona-presets/kai.yaml +27 -0
  185. package/persona-presets/leo.yaml +27 -0
  186. package/persona-presets/mira.yaml +30 -0
  187. package/persona-presets/nari.yaml +27 -0
  188. package/persona-presets/sora.yaml +27 -0
  189. package/persona-presets/yuna.yaml +27 -0
  190. package/plugins/card-followup/README.md +13 -4
  191. package/plugins/card-followup/graphs/card-followup.yaml +3 -1
  192. package/plugins/card-followup/graphs/recipes.yaml +5 -1
  193. package/plugins/card-followup/graphs/run-step.ts +122 -18
  194. package/plugins/card-followup/graphs/sales-strategy.ts +173 -0
  195. package/plugins/card-followup/plugin.json +1 -1
  196. package/plugins/doc-draft/README.md +13 -0
  197. package/plugins/doc-draft/examples/brief-sample.json +8 -0
  198. package/plugins/doc-draft/graphs/doc-draft.yaml +14 -0
  199. package/plugins/doc-draft/graphs/recipes.yaml +9 -0
  200. package/plugins/doc-draft/graphs/run-step.ts +113 -0
  201. package/plugins/doc-draft/plugin.json +24 -0
  202. package/plugins/geo-check/README.md +3 -1
  203. package/plugins/geo-check/graphs/run-step.ts +58 -13
  204. package/plugins/geo-check/plugin.json +1 -1
  205. package/plugins/job-coach/.codex-plugin/plugin.json +1 -1
  206. package/plugins/job-coach/README.md +1 -1
  207. package/plugins/job-coach/graphs/run-step.ts +2 -2
  208. package/plugins/job-coach/plugin.json +1 -1
  209. package/plugins/job-coach/plugin.ts +1 -1
  210. package/scripts/affinity/endcard.sh +3 -2
  211. package/scripts/affinity/reframe.sh +3 -1
  212. package/scripts/ci-public-export-leak-gate.ts +48 -0
  213. package/scripts/codex-quota-alert.ts +122 -258
  214. package/scripts/coord-tracks.json +4 -4
  215. package/scripts/field-feed/deliver-node.ts +57 -0
  216. package/scripts/field-feed/feed-node.ts +67 -0
  217. package/scripts/field-feed/lib.ts +164 -0
  218. package/scripts/field-feed/reel-node.ts +24 -0
  219. package/scripts/field-feed/start.ts +62 -0
  220. package/scripts/fixtures/vflow-sample.ndjson +6 -0
  221. package/scripts/install.sh +109 -21
  222. package/scripts/landing-heal/clean-checkout.ts +114 -0
  223. package/scripts/landing-heal/run-mission.ts +38 -3
  224. package/scripts/lib/pwa-scenarios/scenarios.ts +2 -1
  225. package/scripts/persona-presets/lint.ts +79 -0
  226. package/scripts/public-export.ts +8 -4
  227. package/scripts/release-loop/baseline-from-logs.ts +92 -0
  228. package/scripts/release-loop/checklist-gate-node.ts +2 -2
  229. package/scripts/release-loop/env-known-failures.ts +31 -0
  230. package/scripts/release-loop/gate-node.ts +108 -22
  231. package/scripts/release-loop/known-issues-node.ts +159 -0
  232. package/scripts/release-loop/npm-publish-node.ts +124 -0
  233. package/scripts/release-loop/ops-upgrade-node.ts +95 -0
  234. package/scripts/release-loop/publish-node.ts +23 -1
  235. package/scripts/release-loop/release-readiness.ts +58 -0
  236. package/scripts/release-loop/shard-plan.ts +17 -0
  237. package/scripts/release-loop/unattended-release.ts +93 -0
  238. package/scripts/storyboard/storyboard.ts +167 -0
  239. package/scripts/test-diet/lib.ts +88 -0
  240. package/scripts/test-diet/node.ts +102 -0
  241. package/scripts/ux/measure-first-text.ts +102 -0
  242. package/scripts/vflow-collect.ts +20 -7
  243. package/scripts/vflow-search.ts +73 -0
  244. package/scripts/video-free-line-test-walker.ts +36 -0
  245. package/scripts/video-pipeline.ts +2 -2
  246. package/skills/explainer-video/SKILL.md +12 -9
  247. package/skills/explainer-video/engine/build.mjs +1 -1
  248. package/skills/explainer-video/engine/reel.mjs +138 -31
  249. package/skills/explainer-video/engine/reel.sh +2 -1
  250. package/skills/explainer-video/examples/elanous-0.2.5/script.json +1 -1
  251. package/skills/grill-me/SKILL.md +1 -1
  252. package/skills/omni-digest/docs/diagrams/noncode-terminal-promotion-path-2026-08-13.mmd +1 -1
  253. package/src/a2a/server.ts +2 -0
  254. package/src/acp/auth-methods.ts +30 -0
  255. package/src/acp/elanous-aware-peers.ts +30 -0
  256. package/src/acp/server.ts +96 -20
  257. package/src/agent/monad-agent-turn.ts +25 -6
  258. package/src/agent/shared-app-tools.ts +5 -3
  259. package/src/agent-substrate/review-intent.ts +6 -2
  260. package/src/agent-substrate/shard-boundary-intent.ts +70 -0
  261. package/src/auth/github-app-token.ts +4 -1
  262. package/src/autopilot/track-agent-shadow.ts +151 -0
  263. package/src/autopilot/track-agent.ts +23 -3
  264. package/src/boot/acp-server-help.ts +16 -0
  265. package/src/boot/daemon-prompt-turn.ts +31 -10
  266. package/src/boot/daemon-tools/index.ts +7 -1
  267. package/src/budget/codex-credit-pace.ts +84 -0
  268. package/src/budget/codex-credit-plan.ts +154 -0
  269. package/src/budget/codex-reset-credit-state.ts +2 -0
  270. package/src/channel-import/detect.ts +191 -0
  271. package/src/channel-import/run.ts +111 -0
  272. package/src/chat/chat-cli.ts +4 -1
  273. package/src/chat/short-question.ts +40 -0
  274. package/src/cli/agent-cli.ts +24 -15
  275. package/src/cli/ask-bare.ts +42 -0
  276. package/src/cli/cli-user-error.ts +25 -0
  277. package/src/cli/codex-credit-plan-view.ts +25 -0
  278. package/src/cli/config-test-sync.ts +4 -0
  279. package/src/cli/decisions-cli.ts +13 -3
  280. package/src/cli/dependence-gauge.ts +237 -0
  281. package/src/cli/doctor-bundle.ts +128 -0
  282. package/src/cli/doctor-cli.ts +41 -1
  283. package/src/cli/doctor-local-llm.ts +95 -0
  284. package/src/cli/doctor-modes.ts +48 -0
  285. package/src/cli/import-cli.ts +60 -0
  286. package/src/cli/intake-cli.ts +12 -2
  287. package/src/cli/intake-source-cli.ts +58 -0
  288. package/src/cli/machine-cli.ts +23 -0
  289. package/src/cli/mcp-login.ts +13 -4
  290. package/src/cli/msg-cli.ts +137 -0
  291. package/src/cli/persona-cli.ts +116 -0
  292. package/src/cli/plugin-cli.ts +25 -0
  293. package/src/cli/pr-cli.ts +36 -0
  294. package/src/cli/provider-cli.ts +5 -0
  295. package/src/cli/release-cli.ts +50 -8
  296. package/src/cli/release-run-if-ready.ts +48 -0
  297. package/src/cli/setup-cli.ts +27 -6
  298. package/src/cli/setup-recommend.ts +8 -0
  299. package/src/cli/skills-cli.ts +173 -0
  300. package/src/cli/start-cli.ts +13 -4
  301. package/src/cli/usage-cli.ts +11 -1
  302. package/src/codex/setup.ts +37 -16
  303. package/src/dashboard/index.ts +18 -2
  304. package/src/dashboard/slash-runtime/dashboard-handlers.ts +2 -2
  305. package/src/dashboard/slash-runtime/help-from-registry.ts +4 -2
  306. package/src/decisions/decision-cards.ts +291 -0
  307. package/src/decisions/decision-ledger.ts +5 -2
  308. package/src/decisions/discord-decision-cards.ts +133 -0
  309. package/src/decisions/telegram-decision-cards.ts +100 -0
  310. package/src/directives/version-at.ts +77 -0
  311. package/src/discord.ts +73 -6
  312. package/src/domains/core-tools.ts +37 -14
  313. package/src/domains/outbound-alert.ts +94 -12
  314. package/src/domains/repeated-failure.ts +1 -1
  315. package/src/error-report/report.ts +200 -0
  316. package/src/exec-requests/planner.ts +146 -0
  317. package/src/exec-requests/runner.ts +378 -0
  318. package/src/exec-requests/store.ts +78 -0
  319. package/src/field/field-feed-auto.ts +48 -0
  320. package/src/field/field-media.ts +8 -3
  321. package/src/field/field-reel.ts +203 -0
  322. package/src/grok/credential.ts +7 -5
  323. package/src/harness/aside-run-status.ts +33 -0
  324. package/src/harness/browser-verify.ts +48 -17
  325. package/src/harness/harness-cli-command.ts +25 -3
  326. package/src/harness/image-load-state.ts +21 -0
  327. package/src/harness/process-garbage.ts +45 -0
  328. package/src/hooks/error-report.ts +210 -0
  329. package/src/hooks/receiver.ts +41 -1
  330. package/src/import/apply.ts +128 -0
  331. package/src/import/plan.ts +197 -0
  332. package/src/index.ts +168 -21
  333. package/src/input-core/text-entry.ts +13 -5
  334. package/src/instance/leader.ts +13 -1
  335. package/src/intake-plane/collect-github.ts +5 -3
  336. package/src/intake-plane/collect-telegram-saved.ts +15 -3
  337. package/src/intake-plane/discord-seat-work.ts +56 -0
  338. package/src/intake-plane/intake-sources.ts +202 -0
  339. package/src/intake-plane/items.ts +28 -12
  340. package/src/intake-plane/seat-answer.ts +96 -0
  341. package/src/intake-plane/seat-doc-route.ts +221 -0
  342. package/src/intake-plane/submit-intake-work.ts +9 -1
  343. package/src/intake-plane/telegram-seat-work.ts +72 -0
  344. package/src/llm/model-defaults.ts +24 -1
  345. package/src/llm.ts +5 -4
  346. package/src/machines/machine-ledger.ts +127 -0
  347. package/src/market/pack-internal-refs.ts +28 -0
  348. package/src/market/publish.ts +31 -4
  349. package/src/maturity/feature-maturity.ts +65 -0
  350. package/src/model-tier/turn-tier.ts +24 -0
  351. package/src/msg/msg-store.ts +149 -0
  352. package/src/native-tool-catalog.ts +2 -1
  353. package/src/nexus/api/chat-fast-path-config.ts +28 -0
  354. package/src/nexus/api/consult-requests.ts +128 -0
  355. package/src/nexus/api/discord-trigger-bot.ts +3 -0
  356. package/src/nexus/api/error-reports.ts +108 -0
  357. package/src/nexus/api/exec-requests.ts +51 -0
  358. package/src/nexus/api/field-uploads.ts +40 -3
  359. package/src/nexus/api/graph-approvals-feed.ts +140 -0
  360. package/src/nexus/api/graph-approvals.ts +71 -4
  361. package/src/nexus/api/http-server.ts +82 -8
  362. package/src/nexus/api/outbound-report.ts +7 -0
  363. package/src/nexus/api/running-runs-background.ts +68 -0
  364. package/src/nexus/api/running-runs-child.ts +6 -0
  365. package/src/nexus/api/seat-requests.ts +254 -0
  366. package/src/nexus/api/share-captures.ts +91 -0
  367. package/src/nexus/api/skill-problems.ts +56 -0
  368. package/src/nexus/api/terminals.ts +24 -8
  369. package/src/nexus/api/trace-run-scan.ts +37 -0
  370. package/src/nexus/api/trace.ts +19 -3
  371. package/src/nexus/index.ts +28 -1
  372. package/src/nexus/setup-status.ts +11 -7
  373. package/src/notify/llm-budget-alert.ts +16 -10
  374. package/src/oauth/browser-availability.ts +14 -0
  375. package/src/oauth/codex-account-rotation.ts +26 -4
  376. package/src/oauth/codex-account-store.ts +20 -2
  377. package/src/oauth/codex-browser-login.ts +173 -0
  378. package/src/oauth/codex-quota-policy.ts +16 -0
  379. package/src/oauth/codex.ts +4 -1
  380. package/src/oauth/fallback-chain.ts +5 -5
  381. package/src/oauth/store.ts +42 -5
  382. package/src/onboarding/continue-here.ts +34 -0
  383. package/src/onboarding/entry-hints.ts +8 -0
  384. package/src/onboarding/full-screen-io.ts +35 -3
  385. package/src/onboarding/help/skills.md +1 -1
  386. package/src/onboarding/non-interactive.ts +1 -0
  387. package/src/onboarding/subscription-hint.ts +27 -0
  388. package/src/onboarding/web-first.ts +90 -0
  389. package/src/onboarding.ts +287 -26
  390. package/src/persona/presets.ts +105 -0
  391. package/src/plugins/maker/node-install.ts +92 -0
  392. package/src/plugins/maker/node-maker.ts +139 -0
  393. package/src/plugins/maker/plugin-maker.ts +19 -7
  394. package/src/policy/llm-policy.ts +268 -0
  395. package/src/prompt-library/session-guidance.ts +7 -1
  396. package/src/prompt-library/universal-preamble.ts +2 -2
  397. package/src/relay/relay-cli.ts +20 -0
  398. package/src/relay/relay-server.ts +220 -0
  399. package/src/release-loop/checklist.ts +37 -13
  400. package/src/self-dev/decompose.ts +1 -0
  401. package/src/self-dev/dev-pipeline.ts +6 -3
  402. package/src/self-dev/orchestrate.ts +18 -11
  403. package/src/self-dev/run-record-mirror.ts +44 -0
  404. package/src/self-dev/run-store.ts +12 -3
  405. package/src/self-implement/harness-policy-gates.ts +4 -1
  406. package/src/self-implement/report-origin.ts +12 -1
  407. package/src/session/chat.ts +17 -5
  408. package/src/shell-env-bootstrap.ts +44 -7
  409. package/src/skills/connect-claude-plugin.ts +142 -0
  410. package/src/skills/connect.ts +70 -0
  411. package/src/skills/index.ts +29 -1
  412. package/src/skills/repair.ts +124 -0
  413. package/src/skills/runner.ts +11 -2
  414. package/src/skills/shared-agent-skill-roots.ts +25 -0
  415. package/src/skills/trigger-extract.ts +1 -1
  416. package/src/steward/failure-streak.ts +78 -0
  417. package/src/steward/steward-cards.ts +24 -0
  418. package/src/steward/triage-budget.ts +127 -0
  419. package/src/steward/triage-plan.ts +75 -0
  420. package/src/steward/triage.ts +244 -42
  421. package/src/task-cards/card-store.ts +1 -1
  422. package/src/task-orchestrator/surfaces/pod-command-job.ts +16 -8
  423. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +11 -5
  424. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +68 -0
  425. package/src/task-orchestrator/surfaces/self-implement-pod.ts +78 -4
  426. package/src/telegram-commands.ts +13 -0
  427. package/src/telegram.ts +72 -2
  428. package/src/tool-runtime/elanous-skills-list-runtime.ts +3 -3
  429. package/src/tool-runtime/self-cognition-runtimes.ts +160 -2
  430. package/src/user-config.ts +189 -15
  431. package/src/version/packed-revision.json +1 -1
  432. package/src/video-pipeline/recipes/character.ts +42 -5
  433. package/src/video-pipeline/recipes/ffmpeg.ts +1 -1
  434. package/src/video-pipeline/recipes/free-line.ts +16 -3
  435. package/src/video-pipeline/recipes/remote.ts +7 -1
  436. package/src/video-pipeline/vflow-reference.ts +109 -0
  437. package/apps/pwa/out/_next/static/chunks/1169-696263ac7af8c4d4.js +0 -1
  438. package/apps/pwa/out/_next/static/chunks/1883.c91a2648af4842fd.js +0 -1
  439. package/apps/pwa/out/_next/static/chunks/1947-9d64872eeb9cfdec.js +0 -1
  440. package/apps/pwa/out/_next/static/chunks/2808-dc06482994b40f70.js +0 -1
  441. package/apps/pwa/out/_next/static/chunks/3165-95515ca5f299a120.js +0 -1
  442. package/apps/pwa/out/_next/static/chunks/3190-e9282753e7ebde85.js +0 -1
  443. package/apps/pwa/out/_next/static/chunks/4259-99614149577e77cb.js +0 -1
  444. package/apps/pwa/out/_next/static/chunks/4283-329eabeaf233e6cd.js +0 -1
  445. package/apps/pwa/out/_next/static/chunks/4328-cb5058b1acc2de5e.js +0 -25
  446. package/apps/pwa/out/_next/static/chunks/4801-ecee6ef62b349b18.js +0 -1
  447. package/apps/pwa/out/_next/static/chunks/5110-8058791dd25a2e14.js +0 -1
  448. package/apps/pwa/out/_next/static/chunks/5330-c41e9670f594c38f.js +0 -1
  449. package/apps/pwa/out/_next/static/chunks/5423-e95fd125d1794349.js +0 -1
  450. package/apps/pwa/out/_next/static/chunks/5478-b5eae07dc79ea619.js +0 -1
  451. package/apps/pwa/out/_next/static/chunks/5787-96ee6642b9a661e5.js +0 -1
  452. package/apps/pwa/out/_next/static/chunks/6448-79d72368589f98bc.js +0 -1
  453. package/apps/pwa/out/_next/static/chunks/6522-9866c002b5531836.js +0 -1
  454. package/apps/pwa/out/_next/static/chunks/6729-b4a558b7aa891e0c.js +0 -1
  455. package/apps/pwa/out/_next/static/chunks/6969-cb03f9410b7d2e03.js +0 -1
  456. package/apps/pwa/out/_next/static/chunks/7007-3b9861091bb8dd21.js +0 -1
  457. package/apps/pwa/out/_next/static/chunks/7930-8dc7e20fc6fc19ca.js +0 -1
  458. package/apps/pwa/out/_next/static/chunks/8071-187edbc22a86741f.js +0 -1
  459. package/apps/pwa/out/_next/static/chunks/8198-d4101ad70cb9a579.js +0 -1
  460. package/apps/pwa/out/_next/static/chunks/8250.4a2c5553a07cdf47.js +0 -1
  461. package/apps/pwa/out/_next/static/chunks/8293-123b91e7b0330dc0.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/8296-d6d5d87dfa911d41.js +0 -1
  463. package/apps/pwa/out/_next/static/chunks/8305-603963c33ee8eec3.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/8612-4a0066f20951b8fd.js +0 -1
  465. package/apps/pwa/out/_next/static/chunks/9181-cf4e1b61c4783f92.js +0 -1
  466. package/apps/pwa/out/_next/static/chunks/9262-26c2ecbd5a67e4a2.js +0 -1
  467. package/apps/pwa/out/_next/static/chunks/9328-45abdebce4fbecb7.js +0 -1
  468. package/apps/pwa/out/_next/static/chunks/9355-dbc67205adf8745f.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/9763.255b90dd69875689.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/9933-66d31ec25c0231af.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-bd06fb55f4da0381.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4e586142da455a25.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-889ad5cddcf45b0d.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/app/board/page-47ba401d56572c27.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/app/botlab/page-0b54f9c83458e038.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/app/bots/page-4fcc296ef6c8ed90.js +0 -1
  477. package/apps/pwa/out/_next/static/chunks/app/chat/page-fe9fda494a87f4e5.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/app/control/page-f9642e25ce129590.js +0 -1
  479. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e1063e8ba5f3e2e7.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/app/editor/page-9d0df30027d8aa9d.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/app/healthz/route-bd06fb55f4da0381.js +0 -1
  482. package/apps/pwa/out/_next/static/chunks/app/intake/page-d97adf2c9455b8d0.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/app/layout-236b80d202110362.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/app/live/page-21a30f35f1a276ad.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/app/market/page-b1a5be357c4fa25d.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1705a60303f7f573.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/app/morning/page-76b337c11ad0e237.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/app/not-found-7c0f85fbb56f64c6.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/app/observatory/page-65ca16b20617b44d.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/app/page-e7f9b8fc29411c1d.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/app/reflection/page-92ea6213d1aeec04.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-a913a005aacb5476.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2d78804a40dfdef6.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-08a99148e780ac00.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/app/settings/page-deb674e7ed36f815.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-49f8de0534d192d7.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/app/setup/layout-bd06fb55f4da0381.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/app/setup/page-ba162a28d2176e18.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/app/share/page-1ff1a37b550ab41a.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/app/showroom/page-ccaa698f56c0fbdb.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/app/tasks/page-53b944082de1d7db.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/app/term/page-9b70adf1552789bf.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/app/trace/page-30d482aa63241fe8.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/app/vault/page-aecf786f54651d8a.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6ab9b62c7b6e08f2.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/app/workflows/page-08949735455e0c9a.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/app/workspace/page-a1479005234a46c2.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c3890e90bd232732.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/beb5cf10-9adcc10b83930090.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/framework-d68d41c88e05c801.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/main-app-11c63971b7a9593b.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/main-d09452353bd0d9cc.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/pages/_app-184d727cebeca767.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/pages/_error-21bbbbac99b720b1.js +0 -1
  515. package/apps/pwa/out/_next/static/css/eaa74e8bb2f62269.css +0 -1
  516. package/apps/pwa/out/_next/static/qMI0jnlZaBjjm4aIDYNGM/_buildManifest.js +0 -1
  517. /package/apps/pwa/out/_next/static/{qMI0jnlZaBjjm4aIDYNGM → lywc8m_HDzH9MKSDQhyEj}/_ssgManifest.js +0 -0
@@ -3,7 +3,9 @@ import { join } from 'node:path';
3
3
  import { debug } from '../../debug/log.js';
4
4
  import { decideGraphApproval, lastJsonObject, type GraphRunState } from '../../graph-runner/runner.js';
5
5
  import { effectiveInstanceRoot } from '../../instance/resolve.js';
6
+ import { getElanousConfigDir } from '../../elanous-config-dir.js';
6
7
  import { jsonResponse } from './json-response.js';
8
+ import { applyFeedEdit, feedFolderFor, isFeedPreviewMessage, mediaContentType, readFeedDraft, resolveFeedMedia, writeFeedDraft, type FeedDraft } from './graph-approvals-feed.js';
7
9
 
8
10
  export const GRAPH_APPROVALS_PATH = '/v1/graph-approvals';
9
11
  const SEGMENT = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
@@ -16,6 +18,8 @@ interface GraphApprovalItem {
16
18
  since: string;
17
19
  path: string[];
18
20
  recent: Array<{ nodeId: string; ok: boolean; outcome?: string; summary?: string }>;
21
+ /** EV10d — present only for a `{"kind":"feed-preview"}` approval whose run folder holds a valid draft. */
22
+ feed?: Omit<FeedDraft, 'folder'>;
19
23
  }
20
24
 
21
25
  /** One decision this daemon applied through `POST /v1/graph-approvals/:graphId/:runId`. */
@@ -72,6 +76,8 @@ interface GraphApprovalsDeps {
72
76
  * `tailscale serve` every tailnet peer (Pod included) arrives from loopback. */
73
77
  authReason?: (request: Request) => string | undefined;
74
78
  root?: string;
79
+ /** Config dir whose `field/<slug>` folders may hold feed drafts (EV10d). */
80
+ configDir?: string;
75
81
  }
76
82
 
77
83
  const DECISION_AUTH_REASONS = new Set(['bearer-match', 'temp-token', 'noauth']);
@@ -96,7 +102,16 @@ function undecided(state: GraphRunState, root: string): boolean {
96
102
  && Array.isArray(state.path) && !existsSync(join(root, 'graph-runs', state.graphId, `${state.runId}.json.${state.path.length}.decision.json`));
97
103
  }
98
104
 
99
- function list(root: string): GraphApprovalItem[] {
105
+ function feedFor(state: GraphRunState, configDir: string): Omit<FeedDraft, 'folder'> | undefined {
106
+ if (!isFeedPreviewMessage(state.pending?.message ?? '')) return undefined;
107
+ const folder = feedFolderFor(state, configDir);
108
+ const draft = folder ? readFeedDraft(folder) : null;
109
+ if (!draft) return undefined;
110
+ const { folder: _folder, ...rest } = draft;
111
+ return rest;
112
+ }
113
+
114
+ function list(root: string, configDir: string): GraphApprovalItem[] {
100
115
  const dir = join(root, 'graph-runs');
101
116
  let graphs: Dirent[];
102
117
  try { graphs = readdirSync(dir, { withFileTypes: true }); }
@@ -113,6 +128,7 @@ function list(root: string): GraphApprovalItem[] {
113
128
  const state = readRun(root, graph.name, runId);
114
129
  if (!state || !undecided(state, root) || !Array.isArray(state.nodes)) continue;
115
130
  const pending = state.pending!;
131
+ const feed = feedFor(state, configDir);
116
132
  items.push({
117
133
  graphId: state.graphId, runId: state.runId, nodeId: pending.nodeId, message: pending.message,
118
134
  since: pending.since, path: state.path,
@@ -124,6 +140,7 @@ function list(root: string): GraphApprovalItem[] {
124
140
  ...(typeof output?.summary === 'string' ? { summary: output.summary } : {}),
125
141
  };
126
142
  }),
143
+ ...(feed ? { feed } : {}),
127
144
  });
128
145
  }
129
146
  }
@@ -131,14 +148,17 @@ function list(root: string): GraphApprovalItem[] {
131
148
  }
132
149
 
133
150
  export async function handleGraphApprovals(req: Request, deps: GraphApprovalsDeps = {}): Promise<Response> {
134
- const pathname = new URL(req.url).pathname;
151
+ const url = new URL(req.url);
152
+ const pathname = url.pathname;
153
+ const sub = /^\/v1\/graph-approvals\/([^/]+)\/([^/]+)\/(feed-draft|media)$/.exec(pathname);
135
154
  const match = /^\/v1\/graph-approvals\/([^/]+)\/([^/]+)$/.exec(pathname);
136
- if (pathname !== GRAPH_APPROVALS_PATH && !match) return jsonResponse({ error: 'not-found' }, 404);
155
+ if (pathname !== GRAPH_APPROVALS_PATH && !match && !sub) return jsonResponse({ error: 'not-found' }, 404);
137
156
  if (!deps.authorize?.(req)) return jsonResponse({ error: 'unauthorized' }, 401);
157
+ if (sub) return handleFeed(req, url, sub[1]!, sub[2]!, sub[3] as 'feed-draft' | 'media', deps);
138
158
  if (pathname === GRAPH_APPROVALS_PATH) {
139
159
  if (req.method !== 'GET') return jsonResponse({ error: 'method-not-allowed' }, 405);
140
160
  // ⭐ `items` is unchanged; `decided` is additive (newest first) for other devices' cards.
141
- return jsonResponse({ items: list(deps.root ?? effectiveInstanceRoot()), decided: (deps.decisions ?? defaultDecisionRing).list() });
161
+ return jsonResponse({ items: list(deps.root ?? effectiveInstanceRoot(), deps.configDir ?? getElanousConfigDir()), decided: (deps.decisions ?? defaultDecisionRing).list() });
142
162
  }
143
163
  if (req.method !== 'POST') return jsonResponse({ error: 'method-not-allowed' }, 405);
144
164
  const authReason = deps.authReason?.(req);
@@ -172,3 +192,50 @@ export async function handleGraphApprovals(req: Request, deps: GraphApprovalsDep
172
192
  debug.log('approvals.graph', 'decided', { graphId, runId, nodeId, decision, by: `pwa:${authReason}` });
173
193
  return jsonResponse({ graphId, runId, decision });
174
194
  }
195
+
196
+ /** EV10d — `PUT …/:graphId/:runId/feed-draft` (사람 수정 저장) · `GET …/:graphId/:runId/media?path=` (초안 미디어). */
197
+ async function handleFeed(req: Request, url: URL, rawGraphId: string, rawRunId: string, kind: 'feed-draft' | 'media', deps: GraphApprovalsDeps): Promise<Response> {
198
+ let graphId: string;
199
+ let runId: string;
200
+ try { graphId = decodeURIComponent(rawGraphId); runId = decodeURIComponent(rawRunId); }
201
+ catch { return jsonResponse({ error: 'not-found' }, 404); }
202
+ if (!validSegment(graphId) || !validSegment(runId)) return jsonResponse({ error: 'not-found' }, 404);
203
+ const root = deps.root ?? effectiveInstanceRoot();
204
+ const state = readRun(root, graphId, runId);
205
+ const folder = state && isFeedPreviewMessage(state.pending?.message ?? '') ? feedFolderFor(state, deps.configDir ?? getElanousConfigDir()) : null;
206
+ if (!state || !folder) {
207
+ debug.log('approvals.feed', 'refused', { graphId, reason: 'not-feed' });
208
+ return jsonResponse({ error: 'not-found' }, 404);
209
+ }
210
+ if (kind === 'media') {
211
+ if (req.method !== 'GET') return jsonResponse({ error: 'method-not-allowed' }, 405);
212
+ const file = resolveFeedMedia(folder, url.searchParams.get('path') ?? '');
213
+ if (!file) {
214
+ debug.log('approvals.feed', 'refused', { graphId, reason: 'media-path' });
215
+ return jsonResponse({ error: 'not-found' }, 404);
216
+ }
217
+ debug.log('approvals.feed', 'media-served', { graphId });
218
+ return new Response(Bun.file(file), { headers: { 'content-type': mediaContentType(file), 'cache-control': 'private, max-age=60' } });
219
+ }
220
+ if (req.method !== 'PUT') return jsonResponse({ error: 'method-not-allowed' }, 405);
221
+ const authReason = deps.authReason?.(req);
222
+ if (!authReason || !DECISION_AUTH_REASONS.has(authReason)) {
223
+ debug.log('approvals.feed', 'refused', { graphId, reason: 'pairing-required' });
224
+ return jsonResponse({ error: 'pairing-required' }, 403);
225
+ }
226
+ if (!undecided(state, root)) return jsonResponse({ error: 'already-decided' }, 409);
227
+ const current = readFeedDraft(folder);
228
+ if (!current) return jsonResponse({ error: 'not-found' }, 404);
229
+ let body: unknown;
230
+ try { body = await req.json(); }
231
+ catch { return jsonResponse({ error: 'bad_request' }, 400); }
232
+ const result = applyFeedEdit(current, body);
233
+ if (!result.ok) {
234
+ debug.log('approvals.feed', 'refused', { graphId, reason: result.error });
235
+ return jsonResponse({ error: result.error }, 400);
236
+ }
237
+ writeFeedDraft(folder, result.draft);
238
+ debug.log('approvals.feed', 'draft-saved', { graphId, revision: result.draft.revision });
239
+ const { folder: _folder, ...feed } = result.draft;
240
+ return jsonResponse({ graphId, runId, feed });
241
+ }
@@ -15,6 +15,8 @@
15
15
  // Port policy (N1-2 decision): auto-pick from 31415 upward. Actual port
16
16
  // is recorded in runtime.json + printed in boot banner.
17
17
 
18
+ import { setInProcessOutbound } from '../../domains/outbound-alert.js';
19
+ import { getUserConfig } from '../../user-config.js';
18
20
  import type { TelegramEvent } from '../../workflow-runtime/triggers/telegram-source.js';
19
21
  import { spawnSync } from 'node:child_process';
20
22
  import { compareTokenConstTime } from '../../acp/transport/auth.js';
@@ -198,7 +200,11 @@ import { handleMcpResourceGet, MCP_RESOURCE_ROUTE_PATH } from './mcp-resource-ro
198
200
  import { APPROVALS_MERGES_PATH, DESIGN_DIRECTION_PATH, DESIGN_PREVIEW_PATH_PREFIX, DESIGN_PREVIEWS_PATH, DESIGN_SYSTEM_PATH, IPA_PATH_PREFIX, MANIFEST_PATH } from './rest-route-paths.js';
199
201
  import { handleMergeApprovals } from './merge-approvals.js';
200
202
  import { GRAPH_APPROVALS_PATH, handleGraphApprovals } from './graph-approvals.js';
201
- import { FIELD_SERVER_MAX_BODY_BYTES, FIELD_UPLOADS_PATH, handleFieldUploads } from './field-uploads.js';
203
+ import { handleExecRequests } from './exec-requests.js';
204
+ import { handleSeatRequests, SEAT_REQUESTS_PATH, type SeatRequestsDeps } from './seat-requests.js';
205
+ import { handleConsultRequests, CONSULT_REQUESTS_PATH, type ConsultRequestsDeps } from './consult-requests.js';
206
+ import { ExecRequestRunner } from '../../exec-requests/runner.js';
207
+ import { FIELD_SERVER_MAX_BODY_BYTES, FIELD_UPLOADS_PATH, FIELD_REEL_PATH, FIELD_REEL_FILE_PATH, handleFieldUploads } from './field-uploads.js';
202
208
  import { handleLiveDetail, LIVE_DETAIL_PATH } from './live-detail.js';
203
209
  import { handleLiveShipped, LIVE_SHIPPED_PATH } from './live-shipped.js';
204
210
  import { handleMcpWidgetCall, MCP_WIDGET_CALL_ROUTE_PATH, persistWidgetTurnToSessionStore } from './mcp-widget-call-route.js';
@@ -236,6 +242,7 @@ import {
236
242
  parseErrorsPath,
237
243
  } from './errors.js';
238
244
  import { handleChatBackendDetection } from './chat-backend-detection.js';
245
+ import { handleChatFastPathConfig } from './chat-fast-path-config.js';
239
246
  import { connectInfoTokenAllowed, handleConnectInfoGet, handleConnectTokenMint, type ConnectInfoCtx } from './connect-info.js';
240
247
  import { handleStaticAppRequest, pathMatchesStaticPrefix } from './static-app.js';
241
248
  import {
@@ -379,6 +386,8 @@ import {
379
386
  import { handleSessionTurnControl, SESSION_TURN_CONTROL_PATH } from '../../session/session-turn-control.js';
380
387
  import { authenticatePodCredential, handlePodGrokCredential, handlePodGithubCredential, POD_CREDENTIAL_GROK_PATH, POD_CREDENTIAL_GITHUB_PATH } from './pod-credential-api.js';
381
388
  import { handleOutboundReport } from './outbound-report.js';
389
+ import { handleErrorReportIngest } from './error-reports.js';
390
+ import { routeOutboundInProcess } from './outbound-report.js';
382
391
  import { handleSelfEvent } from './self-event.js';
383
392
  /** 매매 «실행»은 애드온이다(대표 09-20 결정 ③ · 별도 상용 저장소 · release/trading-export.yaml) — 공개 코어엔 없다.
384
393
  * 있으면 그 경로를 켜고, 없으면 501. 경로를 변수로 둬 공개본 타입 검사가 «모듈 없음»으로 막히지 않게 한다. */
@@ -446,6 +455,9 @@ export type NexusWsBridgeInit = Omit<WsBridgeOpts, 'hostname' | 'port'>;
446
455
  export interface NexusHttpServerOpts {
447
456
  /** Optional installer state root for isolated API consumers and tests. */
448
457
  pluginStateRoot?: string;
458
+ execRequests?: ExecRequestRunner;
459
+ seatRequests?: SeatRequestsDeps;
460
+ consultRequests?: ConsultRequestsDeps;
449
461
  state: NexusState;
450
462
  registry: TabRegistry;
451
463
  eventBus: NexusEventBus;
@@ -748,6 +760,10 @@ export function startNexusHttpServer(opts: NexusHttpServerOpts): NexusHttpServer
748
760
  ...(websocketHandler ? { websocket: websocketHandler } : {}),
749
761
  } as unknown as Parameters<typeof Bun.serve>[0];
750
762
  server = Bun.serve(fetchOpts);
763
+ // OB8 — this process now answers /v1/outbound itself; its own sendOutbound calls must not curl it.
764
+ setInProcessOutbound(routeOutboundInProcess);
765
+ // 데몬이 «실제로» 떴을 때만 재시작 복구(맡긴 일) — 주입된 러너(시험)는 건드리지 않는다.
766
+ if (!opts.execRequests) { try { execRequestRunner().reconcileInterrupted(); } catch { /* 복구 실패가 서버 기동을 막지 않는다 */ } }
751
767
  resolvedPort = port;
752
768
  break;
753
769
  } catch (err) {
@@ -770,6 +786,7 @@ export function startNexusHttpServer(opts: NexusHttpServerOpts): NexusHttpServer
770
786
  url,
771
787
  stop() {
772
788
  try { server!.stop(true); } catch { /* idempotent */ }
789
+ setInProcessOutbound(null);
773
790
  },
774
791
  };
775
792
  }
@@ -786,6 +803,13 @@ function isPortBusy(err: unknown): boolean {
786
803
  return /EADDRINUSE|address already in use/i.test(msg);
787
804
  }
788
805
 
806
+ let execRequestRunnerInstance: ExecRequestRunner | undefined;
807
+ /** 게으른 한 벌 — import 만으로는 만들지 않는다(재시작 복구가 import 에 묶이지 않게). */
808
+ function execRequestRunner(): ExecRequestRunner {
809
+ execRequestRunnerInstance ??= new ExecRequestRunner();
810
+ return execRequestRunnerInstance;
811
+ }
812
+
789
813
  export async function routeRequest(
790
814
  req: Request,
791
815
  opts: NexusHttpServerOpts,
@@ -834,21 +858,31 @@ export async function routeRequest(
834
858
  // Per-route checkAuth calls below stay in place.
835
859
  // OPTIONS is a CORS preflight and cannot carry Authorization; existing
836
860
  // handlers answer it themselves, so the gate does not swallow it.
837
- // A runtime-less tab mutation still needs authentication before the
838
- // dispatcher can return its 503. Do not enable this fallback for other paths.
839
- const runtimeLessTabMutation = !opts.metaApi && method !== 'GET' && method !== 'OPTIONS'
840
- && (pathname === '/v1/nexus/tabs' || pathname.startsWith('/v1/nexus/tabs/'));
861
+ // Without metaApi, only the owner bearer may reach these runtime-less
862
+ // meta-API stubs. All other private paths remain default-denied.
863
+ const runtimeLessMetaRoute = !opts.metaApi && (
864
+ (method !== 'GET' && method !== 'OPTIONS'
865
+ && (pathname === '/v1/nexus/tabs' || pathname.startsWith('/v1/nexus/tabs/')))
866
+ || (method === 'GET' && (
867
+ ['/v1/simulations', '/v1/tools', '/v1/intake', '/v1/sessions', '/v1/control-signals', '/v1/turns/last/screenshot'].includes(pathname)
868
+ || pathname.startsWith('/v1/recordings/')
869
+ ))
870
+ || (method === 'POST' && (
871
+ ['/v1/intake', '/v1/sessions/external', '/v1/control-signals', '/v1/prompt'].includes(pathname)
872
+ || pathname.startsWith('/v1/hitl/callback/')
873
+ ))
874
+ );
841
875
  if (
842
876
  method !== 'OPTIONS'
843
877
  && pathname.startsWith('/v1/')
844
878
  && !isPublicRoute(method, pathname, { setupMode: false })
845
879
  ) {
846
- const fallbackToken = runtimeLessTabMutation ? ensureAuthToken().token : undefined;
880
+ const fallbackToken = runtimeLessMetaRoute ? ensureAuthToken().token : undefined;
847
881
  const offered = req.headers.get('authorization');
848
882
  const fallbackAuthorized = fallbackToken !== undefined && offered?.startsWith('Bearer ') === true
849
883
  && compareTokenConstTime(offered.slice('Bearer '.length).trim(), fallbackToken);
850
884
  if (!(opts.metaApi ? checkAuth(req, opts.metaApi) : fallbackAuthorized)) {
851
- const name = method === 'POST' && pathname === '/v1/tasks' && opts.metaApi
885
+ const name = method === 'POST' && (pathname === '/v1/tasks' || pathname === '/v1/reports/ingest') && opts.metaApi
852
886
  ? matchIngestAuthorization(req)?.name
853
887
  : undefined;
854
888
  if (name === undefined) {
@@ -919,6 +953,25 @@ export async function routeRequest(
919
953
  });
920
954
  }
921
955
 
956
+ if (pathname === SEAT_REQUESTS_PATH) {
957
+ if (!opts.metaApi || !checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
958
+ return handleSeatRequests(req, opts.seatRequests);
959
+ }
960
+
961
+ if (pathname === CONSULT_REQUESTS_PATH) {
962
+ if (!opts.metaApi || !checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
963
+ return handleConsultRequests(req, opts.consultRequests);
964
+ }
965
+
966
+ if (pathname === '/v1/exec-requests' || pathname.startsWith('/v1/exec-requests/')) {
967
+ if (!opts.metaApi || !checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
968
+ if (/^\/v1\/exec-requests\/[^/]+\/files\//.test(pathname)) {
969
+ const credential = bearerCredential(req, opts.metaApi);
970
+ if (credential !== 'bearer-match' && credential !== 'temp-token') return jsonResponse({ error: 'unauthorized' }, 401);
971
+ }
972
+ return handleExecRequests(req, opts.execRequests ?? execRequestRunner());
973
+ }
974
+
922
975
  if (pathname === GRAPH_APPROVALS_PATH || pathname.startsWith(`${GRAPH_APPROVALS_PATH}/`)) {
923
976
  return handleGraphApprovals(req, {
924
977
  authorize: (request) => !!opts.metaApi && checkAuth(request, opts.metaApi),
@@ -926,9 +979,11 @@ export async function routeRequest(
926
979
  });
927
980
  }
928
981
  // 현장 업로드(owner 전용) — GET 목록 · POST 저장. 저장 규칙 정본 = src/field/field-media.ts.
929
- if (pathname === FIELD_UPLOADS_PATH && (method === 'GET' || method === 'POST')) {
982
+ if ((pathname === FIELD_UPLOADS_PATH && (method === 'GET' || method === 'POST'))
983
+ || ((pathname === FIELD_REEL_PATH || pathname === FIELD_REEL_FILE_PATH) && method === 'GET')) {
930
984
  return handleFieldUploads(req, {
931
985
  authorize: (request) => !!opts.metaApi && checkAuth(request, opts.metaApi),
986
+ configuredEvent: () => { try { return getUserConfig().telegram?.fieldDefaultEvent; } catch { return undefined; } },
932
987
  });
933
988
  }
934
989
  if (pathname === APPROVALS_MERGES_PATH || pathname.startsWith(`${APPROVALS_MERGES_PATH}/`)) {
@@ -1217,6 +1272,11 @@ export async function routeRequest(
1217
1272
  return handleGraphsValidatePost(req, opts.metaApi);
1218
1273
  }
1219
1274
 
1275
+ if (pathname === '/v1/config/chat-fast-path' && (method === 'GET' || method === 'PUT')) {
1276
+ if (!opts.metaApi || !checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
1277
+ return handleChatFastPathConfig(req);
1278
+ }
1279
+
1220
1280
  // Mutation routes (PR ι) — POST/PATCH/DELETE on /v1/nexus/tabs[/:id[/action]].
1221
1281
  // Templates POST handled here too (PR κ).
1222
1282
  // Config / secrets PUT/POST/DELETE here too (PR μ).
@@ -1250,6 +1310,8 @@ export async function routeRequest(
1250
1310
  if (!opts.metaApi) return jsonResponse({ error: 'meta-api-not-wired' }, 503);
1251
1311
  return handleTaskCreatePost(req, opts.metaApi);
1252
1312
  }
1313
+ // ER2 — error reports forwarded by the bot VM (ingest token · same as /v1/tasks).
1314
+ if (method === 'POST' && pathname === '/v1/reports/ingest') return handleErrorReportIngest(req);
1253
1315
  if (method === 'POST' && pathname.startsWith('/v1/tasks/') && pathname.endsWith('/approve')) {
1254
1316
  if (!opts.metaApi) return jsonResponse({ error: 'meta-api-not-wired' }, 503);
1255
1317
  let taskId: string;
@@ -1915,6 +1977,18 @@ export async function routeRequest(
1915
1977
  }
1916
1978
  // HANDOFF §4.2 follow-up — skill-side mirror of the workflow
1917
1979
  // router. Same regex → LLM cascade, applied to the skill index.
1980
+ // SK2 (PWA) — skills the index could not read: list ⊕ confirmed repair.
1981
+ if (pathname === '/v1/skills/problems' || pathname === '/v1/skills/problems/repair') {
1982
+ if (!opts.metaApi) return jsonResponse({ error: 'meta-api-not-wired' }, 503);
1983
+ const { handleSkillProblems } = await import('./skill-problems.js');
1984
+ return handleSkillProblems(req, opts.metaApi);
1985
+ }
1986
+ // SC1 (PWA · beta) — «공유용 캡처»: masked screen PNG in, metadata chunks stripped, stored under <configDir>/captures.
1987
+ if (pathname === '/v1/captures' || pathname.startsWith('/v1/captures/')) {
1988
+ if (!opts.metaApi) return jsonResponse({ error: 'meta-api-not-wired' }, 503);
1989
+ const { handleShareCaptures } = await import('./share-captures.js');
1990
+ return handleShareCaptures(req, opts.metaApi);
1991
+ }
1918
1992
  if (pathname === '/v1/skills/route' && method === 'POST') {
1919
1993
  if (!opts.metaApi) return jsonResponse({ error: 'meta-api-not-wired' }, 503);
1920
1994
  return handleSkillRoute(req, opts.metaApi);
@@ -44,6 +44,13 @@ function json(body: unknown, status: number): Response {
44
44
  });
45
45
  }
46
46
 
47
+ /** The daemon's own sendOutbound path (OB8) — what POST /v1/outbound does, without the HTTP self-call. */
48
+ export async function routeOutboundInProcess(text: string, kind: string): Promise<boolean> {
49
+ const result = await routeOutbound(getUserConfig(), { text, markdown: false, kind });
50
+ if (result.delivered) recordOutboundEvent(text, kind);
51
+ return result.delivered;
52
+ }
53
+
47
54
  /** POST /v1/outbound — fan one message out to the routed channels. */
48
55
  export async function handleOutboundReport(req: Request, metaApi: MetaApiOpts): Promise<Response> {
49
56
  if (!checkAuth(req, metaApi)) return json({ error: 'unauthorized' }, 401);
@@ -0,0 +1,68 @@
1
+ // The terminals list must answer at once and must never share the event loop with a ledger scan: the running-runs query
2
+ // reads every run ledger synchronously (~5k files · 0.9–1.8 s on 10-02), which froze typing in the web terminal while the
3
+ // PWA polled the list. This keeps the last result as a snapshot and refreshes it in a separate bun process, on demand.
4
+ import { join } from 'node:path';
5
+ import { debug } from '../../debug/log.js';
6
+ import type { RunningRunsResult } from '../../self-implement/running-runs.js';
7
+
8
+ export const RUNNING_RUNS_REFRESH_MS = 15_000;
9
+ /** A refresh that has not answered by then is abandoned; the next request starts another. */
10
+ export const RUNNING_RUNS_REFRESH_TIMEOUT_MS = 60_000;
11
+
12
+ export interface RunningRunsSnapshot {
13
+ /** Last result, or null before the first refresh finished (subjects then keep unknown assessments). */
14
+ readonly result: RunningRunsResult | null;
15
+ /** Milliseconds since `result` was computed; null when there is none. */
16
+ readonly ageMs: number | null;
17
+ }
18
+
19
+ /** Runs the query somewhere other than this event loop and resolves with its JSON output. */
20
+ export type RunningRunsRunner = (includeTest: boolean) => Promise<RunningRunsResult>;
21
+
22
+ export const RUNNING_RUNS_CHILD_SCRIPT = join(import.meta.dir, 'running-runs-child.ts');
23
+
24
+ /** Default runner: `bun running-runs-child.ts [--include-test]` — the child does the ledger I/O, we only parse its stdout. */
25
+ export const childProcessRunner: RunningRunsRunner = async (includeTest) => {
26
+ const proc = Bun.spawn([process.execPath, RUNNING_RUNS_CHILD_SCRIPT, ...(includeTest ? ['--include-test'] : [])], {
27
+ stdout: 'pipe', stderr: 'ignore', stdin: 'ignore', env: process.env,
28
+ });
29
+ const timer = setTimeout(() => proc.kill(), RUNNING_RUNS_REFRESH_TIMEOUT_MS);
30
+ try {
31
+ const [out, code] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
32
+ if (code !== 0) throw new Error(`running-runs child exit ${code}`);
33
+ return JSON.parse(out) as RunningRunsResult;
34
+ } finally { clearTimeout(timer); }
35
+ };
36
+
37
+ export interface RunningRunsBackground {
38
+ /** Never blocks: returns the last snapshot and starts a refresh when it is stale and none is in flight. */
39
+ snapshot(options: { includeTest?: boolean }): RunningRunsSnapshot;
40
+ }
41
+
42
+ export function createRunningRunsBackground(runner: RunningRunsRunner = childProcessRunner, now: () => number = Date.now, refreshMs = RUNNING_RUNS_REFRESH_MS): RunningRunsBackground {
43
+ const slots = new Map<boolean, { at: number; result: RunningRunsResult }>();
44
+ const flights = new Set<boolean>();
45
+ const refresh = (includeTest: boolean): void => {
46
+ if (flights.has(includeTest)) return;
47
+ flights.add(includeTest);
48
+ const started = now();
49
+ void runner(includeTest)
50
+ .then((result) => {
51
+ slots.set(includeTest, { at: now(), result });
52
+ debug.log('nexus.terminals', 'running-runs-refreshed', { includeTest, ms: now() - started });
53
+ })
54
+ .catch((error: unknown) => {
55
+ debug.log('nexus.terminals', 'running-runs-refresh-failed', { includeTest, reason: error instanceof Error ? error.message.slice(0, 80) : 'unknown' }, { level: 'warn' });
56
+ })
57
+ .finally(() => { flights.delete(includeTest); });
58
+ };
59
+ return {
60
+ snapshot(options) {
61
+ const includeTest = options.includeTest === true;
62
+ const slot = slots.get(includeTest);
63
+ const t = now();
64
+ if (!slot || t - slot.at >= refreshMs) refresh(includeTest);
65
+ return slot ? { result: slot.result, ageMs: t - slot.at } : { result: null, ageMs: null };
66
+ },
67
+ };
68
+ }
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bun
2
+ // Child of running-runs-background.ts: runs the running-runs query (all the ledger I/O) and prints the result as JSON.
3
+ import { queryRunningRuns } from '../../self-implement/running-runs.js';
4
+
5
+ const result = queryRunningRuns({ includeTest: process.argv.includes('--include-test'), caller: 'nexus.terminals' });
6
+ process.stdout.write(JSON.stringify(result));