elanous 0.2.10 → 0.2.12

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 (615) 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/-6XrAoD3eU7NyMHAE4xPS/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1147-466ec15afacc1a65.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1394-ee3795b112907122.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
  8. package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/3869-3cd46526879f454c.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
  18. package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
  19. package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
  24. package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/7277-0b2fc7c16ba2d64b.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/7758-0b018a9e4fc56200.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8605-0259994816604c49.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
  47. package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/9920-5cfdc5e8fd209825.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-cb169620945d1952.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cefe8169e36cf62a.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/board/page-d2e35228bc497119.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-5c05b0da4bc1392c.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/app/bots/page-e0ccdb576812b523.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/chat/page-813c4a52c9d05ca8.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/consult/page-4731f2c215358937.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/control/page-a022b257950f39e6.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/design-check/page-a2ffc717e04b8b0a.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/editor/page-b59ee4e70fc18fcf.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/exec/page-a67e11ba962337b5.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/field/page-c172dabd796eb7a3.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-1efd0cb9e0ed9d13.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/intake/page-d5dc7ff69a37b4cf.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/layout-e71c84189e8c683e.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/live/page-1d6a533ce5a6efcb.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/market/page-dfca9b7d2de0b135.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-793fa536b3a6ef37.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/morning/page-6dd3bfbbde2a5c2c.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/not-found-490653e8d4cc8852.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/observatory/page-77447356baad75d2.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-29e961191f6057df.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-c822f55b884d9104.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fa4ccfc432424e52.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/outputs/page-6d604227e1664b71.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/page-9c7e8f744a765daf.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/reflection/page-4048543b4b7ad5e0.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4c3a3126abed551a.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/sessions/page-64b0aecb1ca75e75.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4292d0149020e8a7.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/settings/page-db14d0be7f1c460c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-e5d8072cd7cfef73.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-9547b5cec7cf76bf.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/share/page-e6dcb83265530636.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/showroom/page-45248f08d6aecae5.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/app/tasks/page-2cddeb9e2aeedc55.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/app/term/page-e297866051595d81.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/app/today/page-baba2e047872fb0f.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/app/trace/page-e895da4ec9cac345.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/app/vault/page-4344faf20216233b.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-698bb29f11864b89.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/app/workflows/page-bd6a6dc1ddc273f2.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2e9e2fb01c9da1c9.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d62ceb13411ebba4.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/128fb7fb670b2fbf.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 -1
  152. package/apps/pwa/out/ops/seats/index.txt +22 -22
  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 -1
  178. package/apps/pwa/out/today/index.txt +23 -23
  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/context/nightly-condense.yaml +21 -0
  192. package/graphs/context/recipes.yaml +12 -0
  193. package/graphs/demo/inside-seed.yaml +20 -0
  194. package/graphs/demo/recipes.yaml +12 -0
  195. package/graphs/drafts/draft-cleanup.yaml +19 -0
  196. package/graphs/drafts/recipes.yaml +23 -0
  197. package/graphs/intake/intake-daily.yaml +2 -1
  198. package/graphs/ops/recipes.yaml +3 -0
  199. package/graphs/ops/secret-exposure.yaml +24 -0
  200. package/graphs/release/recipes.yaml +3 -0
  201. package/graphs/release/release-loop.yaml +4 -1
  202. package/graphs/video/explainer-line.yaml +2 -2
  203. package/package.json +2 -1
  204. package/plugins/card-followup/examples/sample-card.png +0 -0
  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/context-hooks/claude-stop.sh +4 -0
  216. package/scripts/context-hooks/emit.ts +24 -0
  217. package/scripts/context-hooks/post-tool-use.sh +4 -0
  218. package/scripts/coord-channel-watch.sh +12 -0
  219. package/scripts/coord-requests-bridge.ts +143 -0
  220. package/scripts/field-feed/lib.ts +4 -0
  221. package/scripts/fleet/node-setup.sh +20 -3
  222. package/scripts/homebrew-formula-bump.ts +69 -0
  223. package/scripts/lib/telegram-inject-args.ts +31 -0
  224. package/scripts/marketing/measure-site-numbers.ts +169 -0
  225. package/scripts/measure-gate-shards.ts +309 -0
  226. package/scripts/measure-pod-memory-by-goal.ts +130 -0
  227. package/scripts/mission-request-judge.ts +31 -1
  228. package/scripts/morning-report.ts +2 -2
  229. package/scripts/opportunity-scan.ts +1 -1
  230. package/scripts/release-loop/auto-approve-node.ts +21 -4
  231. package/scripts/release-loop/checklist-gate-node.ts +2 -1
  232. package/scripts/release-loop/cut-branch.ts +84 -0
  233. package/scripts/release-loop/gate-node.ts +22 -15
  234. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  235. package/scripts/release-loop/node-verdict.ts +3 -3
  236. package/scripts/release-loop/ops-upgrade-node.ts +47 -6
  237. package/scripts/release-loop/publish-node.ts +4 -1
  238. package/scripts/release-loop/tui-node-checks.ts +42 -0
  239. package/scripts/release-loop/tui-sim-node.ts +32 -8
  240. package/scripts/release-loop/unattended-release.ts +5 -3
  241. package/scripts/release-loop/version-node.ts +74 -13
  242. package/scripts/signal-digest-cycle.ts +2 -7
  243. package/scripts/signal-digest-photo.ts +11 -0
  244. package/scripts/tech1-public-measure.ts +94 -0
  245. package/scripts/telegram-inject.ts +14 -6
  246. package/scripts/test-diet/node.ts +1 -1
  247. package/scripts/test-diet/remeasure-list.ts +112 -0
  248. package/scripts/tui-regress.ts +2 -2
  249. package/scripts/ux/demo-rehearsal.ts +247 -0
  250. package/scripts/ux/demo-seed.ts +108 -0
  251. package/scripts/ux/lib/rehearsal-verdict.ts +80 -0
  252. package/skills/diagram-master/SKILL.md +366 -0
  253. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  254. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  255. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  256. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  257. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  258. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  259. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  260. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  261. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  262. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  263. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  264. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  265. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  266. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  267. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  268. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  269. package/skills/diagram-master/references/examples/README.md +69 -0
  270. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  271. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  272. package/skills/diagram-master/references/pyproject.toml +16 -0
  273. package/skills/diagram-master/references/quality-checklist.md +33 -0
  274. package/skills/diagram-master/references/routing-guide.md +164 -0
  275. package/skills/diagram-master/references/uv.lock +1356 -0
  276. package/skills/google-workspace/SKILL.md +33 -0
  277. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  278. package/skills/grill-me/SKILL.md +1 -1
  279. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  280. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  281. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  282. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  283. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  284. package/skills/omni-crawl/SKILL.md +21 -11
  285. package/skills/omni-crawl/scripts/main.ts +6 -6
  286. package/skills/omni-crawl/src/router.ts +3 -3
  287. package/skills/omni-digest/SKILL.md +17 -9
  288. package/skills/omni-digest/digest.md +2 -2
  289. package/skills/omni-digest/src/fetch.ts +30 -3
  290. package/skills/pitch-deck/SKILL.md +2 -2
  291. package/skills/pitch-deck/template.html +2 -2
  292. package/skills/youtube-master/SKILL.md +163 -0
  293. package/skills/youtube-master/package-lock.json +558 -0
  294. package/skills/youtube-master/package.json +13 -0
  295. package/skills/youtube-master/references/study-note-template.md +124 -0
  296. package/skills/youtube-master/scripts/main.ts +435 -0
  297. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  298. package/skills/youtube-master/src/audio.ts +63 -0
  299. package/skills/youtube-master/src/domain-staging.ts +50 -0
  300. package/skills/youtube-master/src/env.ts +36 -0
  301. package/skills/youtube-master/src/obsidian.ts +155 -0
  302. package/skills/youtube-master/src/router.ts +110 -0
  303. package/skills/youtube-master/src/stt.ts +199 -0
  304. package/skills/youtube-master/src/study-note.ts +175 -0
  305. package/skills/youtube-master/src/summarize.ts +358 -0
  306. package/skills/youtube-master/src/transcript.ts +76 -0
  307. package/skills/youtube-master/src/types.ts +91 -0
  308. package/skills/youtube-master/src/util.ts +93 -0
  309. package/skills/youtube-master/src/youtube.ts +70 -0
  310. package/skills/youtube-master/tsconfig.json +13 -0
  311. package/src/acp/server.ts +5 -2
  312. package/src/agent-mission/driver.ts +215 -23
  313. package/src/agent-mission/pty-decision.ts +71 -0
  314. package/src/agent-mission/review-loop.ts +30 -0
  315. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  316. package/src/autopilot/pty-control-loop.ts +4 -1
  317. package/src/autopilot/tool-registry.ts +2 -0
  318. package/src/boot/daemon-prompt-turn.ts +5 -0
  319. package/src/boot/daemon-runtime.ts +9 -3
  320. package/src/boot/daemon-tools/web-search.ts +3 -0
  321. package/src/card-followup/core.ts +109 -0
  322. package/src/chat/index.ts +2 -0
  323. package/src/cli/drive-input-jail.ts +101 -0
  324. package/src/cli/hooks-cli.ts +17 -3
  325. package/src/cli/make-cli.ts +43 -0
  326. package/src/cli/persona-cli.ts +98 -9
  327. package/src/cli/plugin-cli.ts +31 -22
  328. package/src/cli/pod-cli.ts +36 -9
  329. package/src/cli/pod-memory-advice.ts +35 -0
  330. package/src/cli/pr-cli.ts +51 -15
  331. package/src/cli/pty-drive-cli.ts +41 -7
  332. package/src/cli/pty-drive-verdict.ts +40 -0
  333. package/src/cli/release-cli.ts +63 -10
  334. package/src/cli/setup-cli.ts +43 -1
  335. package/src/cli/skills-cli.ts +17 -1
  336. package/src/context-bus/claude-hooks-install.ts +10 -0
  337. package/src/context-bus/context-now-surfaces.ts +65 -0
  338. package/src/context-bus/context-now.ts +104 -0
  339. package/src/context-bus/coord-events.ts +2 -2
  340. package/src/context-bus/external-events.ts +52 -0
  341. package/src/context-bus/long-term-memory.ts +108 -0
  342. package/src/context-bus/nightly-condense.ts +153 -0
  343. package/src/context-bus/session-events.ts +35 -0
  344. package/src/dashboard/dashboard-status-lines.ts +2 -0
  345. package/src/dashboard/index.ts +17 -4
  346. package/src/dashboard/slash-runtime/dashboard-handlers.ts +31 -1
  347. package/src/decisions/decision-cards.ts +10 -3
  348. package/src/decisions/decision-ledger.ts +13 -5
  349. package/src/discord/sprint21-runtime.ts +5 -1
  350. package/src/discord-self-message.ts +32 -0
  351. package/src/discord-slash-wire.ts +5 -1
  352. package/src/discord.ts +17 -1
  353. package/src/domains/core-tools.ts +3 -2
  354. package/src/domains/outbound-alert.ts +105 -32
  355. package/src/domains/outbound-log-probe.ts +8 -0
  356. package/src/domains/telegram-kind-route.ts +51 -13
  357. package/src/exec-requests/default-outputs.ts +25 -0
  358. package/src/exec-requests/planner.ts +10 -2
  359. package/src/exec-requests/runner.ts +20 -6
  360. package/src/exec-requests/store.ts +3 -0
  361. package/src/execution-loop/launch-gate.ts +109 -0
  362. package/src/field/field-reel.ts +5 -1
  363. package/src/field-note/index.ts +201 -0
  364. package/src/field-note/telegram.ts +142 -0
  365. package/src/field-note/transcribe.ts +248 -0
  366. package/src/graph-kinds/registry.ts +3 -3
  367. package/src/graph-runner/graph-cli.ts +61 -1
  368. package/src/graph-runner/graph-grow-llm.ts +47 -0
  369. package/src/graph-runner/graph-grow.ts +50 -0
  370. package/src/graph-runner/runner.ts +329 -33
  371. package/src/grok/agent-search.ts +8 -2
  372. package/src/guardian/secret-exposure-scan.ts +101 -0
  373. package/src/harness/harness-cli-command.ts +375 -13
  374. package/src/harness/harness-pod-dispatch.ts +43 -23
  375. package/src/harness/harness-seams.ts +38 -4
  376. package/src/harness/harness-stop.ts +23 -4
  377. package/src/harness/launch-registry.ts +91 -0
  378. package/src/harness/process-garbage.ts +5 -3
  379. package/src/hooks/consult-intake.ts +153 -0
  380. package/src/hooks/dispatch.ts +82 -0
  381. package/src/hooks/expose.ts +254 -0
  382. package/src/hooks/github-shadow.ts +108 -0
  383. package/src/hooks/providers.ts +71 -5
  384. package/src/hooks/queue.ts +1 -1
  385. package/src/hooks/receiver.ts +94 -16
  386. package/src/index.ts +76 -14
  387. package/src/intake-plane/categorize.ts +18 -46
  388. package/src/intake-plane/discord-seat-work.ts +38 -2
  389. package/src/intake-plane/front-route-classifier.ts +33 -39
  390. package/src/intake-plane/persona-answer.ts +30 -0
  391. package/src/intake-plane/runtime-callables.ts +8 -1
  392. package/src/intake-plane/telegram-seat-work.ts +36 -2
  393. package/src/intake-plane/wish-card.ts +33 -0
  394. package/src/intake-plane/wish-folder.ts +67 -0
  395. package/src/intent-gate/gate.ts +30 -10
  396. package/src/live/detail-switch.ts +5 -0
  397. package/src/llm/difficulty.ts +57 -0
  398. package/src/llm/judge-layer.ts +101 -0
  399. package/src/llm/mission-router.ts +33 -19
  400. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  401. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  402. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  403. package/src/loops/contract/loop-agent.schema.json +138 -0
  404. package/src/loops/contract/validate.ts +64 -0
  405. package/src/loops/registry.ts +20 -6
  406. package/src/market/signed-index.ts +4 -0
  407. package/src/maturity/bot-command-maturity.ts +45 -0
  408. package/src/maturity/feature-maturity.ts +27 -4
  409. package/src/model-tier/index.ts +2 -2
  410. package/src/model-tier/tier-resolver.ts +20 -20
  411. package/src/model-tier/types.ts +6 -6
  412. package/src/mss/logging/log-store.ts +15 -0
  413. package/src/nexus/api/config-model-tier.ts +5 -4
  414. package/src/nexus/api/fabric-plans.ts +53 -0
  415. package/src/nexus/api/harness-api.ts +5 -1
  416. package/src/nexus/api/health.ts +2 -0
  417. package/src/nexus/api/http-server.ts +67 -8
  418. package/src/nexus/api/inside-events.ts +226 -0
  419. package/src/nexus/api/meta-api.ts +21 -8
  420. package/src/nexus/api/missions.ts +6 -1
  421. package/src/nexus/api/ops-seats.ts +33 -0
  422. package/src/nexus/api/outbound-report.ts +40 -7
  423. package/src/nexus/api/outputs-route.ts +44 -0
  424. package/src/nexus/api/personas.ts +95 -53
  425. package/src/nexus/api/seat-requests.ts +44 -2
  426. package/src/nexus/api/sessions-store.ts +17 -38
  427. package/src/nexus/api/sub-seat-charters.ts +34 -0
  428. package/src/nexus/api/tabs-mutations.ts +3 -1
  429. package/src/nexus/api/task-cards-api.ts +19 -0
  430. package/src/nexus/api/trace.ts +18 -6
  431. package/src/nexus/api/workflow-history.ts +88 -0
  432. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  433. package/src/nexus/api/workflows.ts +132 -6
  434. package/src/nexus/index.ts +2 -0
  435. package/src/nexus/kinds/webterm.ts +2 -1
  436. package/src/nexus/outbound/delivery-ledger.ts +17 -8
  437. package/src/nexus/outbound/router.ts +8 -3
  438. package/src/nexus/webterm/pty.ts +6 -2
  439. package/src/onboarding/cli-auth-status.ts +80 -0
  440. package/src/onboarding/voice-ai.ts +3 -3
  441. package/src/org/seat-budget.ts +48 -0
  442. package/src/org/stall-escalation.ts +63 -0
  443. package/src/outputs/ledger.ts +120 -0
  444. package/src/persona/persona-todo.ts +79 -0
  445. package/src/persona/presets.ts +123 -2
  446. package/src/persona/team-set.ts +155 -0
  447. package/src/plugins/install/plugin-install.ts +14 -0
  448. package/src/plugins/maker/market-bundle.ts +110 -0
  449. package/src/plugins/maker/plugin-maker.ts +254 -11
  450. package/src/plugins/maker/wizard-generate.ts +103 -0
  451. package/src/pod-lease/admission.ts +150 -0
  452. package/src/pod-lease/dependency-state.ts +85 -0
  453. package/src/pod-lease/host-lease.ts +127 -0
  454. package/src/project/project-suggestion.ts +16 -0
  455. package/src/project/session-context.ts +24 -0
  456. package/src/release-loop/checklist.ts +17 -5
  457. package/src/release-loop/feature-store.ts +29 -13
  458. package/src/release-loop/landed-but-yellow.ts +48 -0
  459. package/src/release-loop/next-md-merge.ts +58 -0
  460. package/src/release-loop/release-note.ts +59 -4
  461. package/src/seat-dispatch/seat-ask.ts +130 -0
  462. package/src/seat-dispatch/seat-questions.ts +100 -0
  463. package/src/seat-loop/seat-loop.ts +709 -29
  464. package/src/seat-loop/seat-report.ts +37 -2
  465. package/src/self-dev/dev-cli.ts +4 -1
  466. package/src/self-dev/dev-pipeline.ts +37 -1
  467. package/src/self-dev/draft-sweep.ts +79 -40
  468. package/src/self-dev/draft-triage-rules.ts +62 -7
  469. package/src/self-dev/fabric-plan-core.ts +297 -0
  470. package/src/self-dev/orchestrate.ts +36 -4
  471. package/src/self-dev/release-path-guard.ts +62 -0
  472. package/src/self-dev/shard-aggregate.ts +230 -0
  473. package/src/self-dev/shard-placement.ts +60 -0
  474. package/src/self-dev/shard-plan.ts +48 -0
  475. package/src/self-dev/shard-pod-run.ts +77 -0
  476. package/src/self-dev/shard-run.ts +105 -0
  477. package/src/self-implement/budget-gate.ts +29 -12
  478. package/src/self-implement/gate-baseline.ts +1 -1
  479. package/src/self-implement/gate-candidate-ranking.ts +60 -0
  480. package/src/self-implement/gate-cli.ts +40 -1
  481. package/src/self-implement/gate-scope.ts +44 -13
  482. package/src/self-implement/graph-variant.ts +171 -0
  483. package/src/self-implement/harness-policy-gates.ts +1 -1
  484. package/src/self-implement/headless-elanous-driver.ts +27 -3
  485. package/src/self-implement/host-regate.ts +22 -1
  486. package/src/self-implement/importer-test-index.ts +2 -1
  487. package/src/self-implement/l8-merge-queue.ts +130 -0
  488. package/src/self-implement/orchestrator.ts +257 -9
  489. package/src/self-implement/route-consumer-test-index.ts +122 -0
  490. package/src/self-implement/seams.ts +72 -11
  491. package/src/self-implement/test-seams.ts +2 -0
  492. package/src/self-implement/uncommitted-work.ts +59 -0
  493. package/src/session/index.ts +36 -13
  494. package/src/skills/gift-install.ts +215 -0
  495. package/src/skills/tools/web-search.ts +4 -1
  496. package/src/steward/launch.ts +42 -26
  497. package/src/steward/steward-cards.ts +17 -9
  498. package/src/steward/triage.ts +46 -14
  499. package/src/task-cards/card-cli.ts +25 -1
  500. package/src/task-orchestrator/mission.ts +5 -0
  501. package/src/task-orchestrator/store.ts +12 -3
  502. package/src/task-orchestrator/surfaces/pod-command-job.ts +43 -17
  503. package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
  504. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  505. package/src/task-orchestrator/surfaces/self-implement-pod.ts +222 -40
  506. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  507. package/src/task-orchestrator/types.ts +2 -0
  508. package/src/telegram-card-followup.ts +16 -96
  509. package/src/telegram-commands.ts +31 -1
  510. package/src/telegram-project-command.ts +145 -0
  511. package/src/telegram-report.ts +21 -17
  512. package/src/telegram.ts +61 -8
  513. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  514. package/src/user-config.ts +110 -24
  515. package/src/version/packed-revision.json +1 -1
  516. package/src/web-search/grok.ts +7 -1
  517. package/src/web-search/index.ts +28 -1
  518. package/src/web-search/provider.ts +4 -0
  519. package/src/web-search/x-intent.ts +5 -0
  520. package/src/workflow-runtime/executor.ts +277 -47
  521. package/src/workflow-runtime/index.ts +1 -0
  522. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  523. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  524. package/src/workflow-runtime/schema.ts +79 -4
  525. package/src/workflow-runtime/types.ts +35 -4
  526. package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  536. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  537. package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
  556. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  614. package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
  615. /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → -6XrAoD3eU7NyMHAE4xPS}/_ssgManifest.js +0 -0
@@ -1,15 +1,19 @@
1
1
  import { debug } from '../debug/log.js';
2
2
  import { readFileSync } from 'node:fs';
3
- import { userConfigPath } from '../user-config.js';
3
+ import { getUserConfig, parseEventsConfig, userConfigPath, type EventsConfig } from '../user-config.js';
4
+ import { dispatchHook, type HookWake } from './dispatch.js';
4
5
  import { getSecretAsync } from '../nexus/config/secrets/index.js';
5
6
  import { HookQueue, type QueuedHook } from './queue.js';
7
+ import { recordGithubShadow } from './github-shadow.js';
6
8
  import { toExternalTask, verifyWebhook, type HookProvider } from './providers.js';
7
9
  import { drainReports, handleReportPost, ReportLimiter, ReportQueue, type ReceivedReport } from './error-report.js';
10
+ import { ConsultLimiter, ConsultQueue, drainConsults, handleConsultPost, type QueuedConsult } from './consult-intake.js';
8
11
  import { effectiveInstanceRoot } from '../instance/resolve.js';
9
12
 
10
13
  export interface HookSecrets {
11
14
  linear?: string;
12
15
  asana?: string;
16
+ github?: string;
13
17
  saveAsana?: (secret: string) => Promise<void>;
14
18
  }
15
19
  export interface HookReceiverOptions {
@@ -20,8 +24,17 @@ export interface HookReceiverOptions {
20
24
  now?: () => number;
21
25
  root?: string;
22
26
  retryBaseMs?: number;
27
+ events?: EventsConfig;
28
+ wakeSeat?: HookWake;
23
29
  /** ER2 — forward one queued error report to the Primary; default = POST /v1/reports/ingest over the tailnet. */
24
30
  forwardReport?: (item: ReceivedReport) => Promise<boolean>;
31
+ /** CS1 — forward a queued consultation to the Primary's consult ledger. */
32
+ forwardConsult?: (item: QueuedConsult) => Promise<boolean>;
33
+ /** CS1 — the public consult route is a write path from the open internet, so it stays closed (404) until
34
+ * `hooks.consult.enabled === true` in user config (대표 decision D-20261003-09). Tests pass it directly. */
35
+ consultEnabled?: boolean;
36
+ /** GET-only public metadata lookup; failure forces human review. */
37
+ githubFetch?: typeof fetch;
25
38
  }
26
39
 
27
40
  /** `/v1/tasks` lives on the Primary's nexus API, not on the control plane — so the address is its own setting. */
@@ -33,37 +46,79 @@ export function hooksPrimaryUrl(config: { hooks?: { primaryUrl?: unknown } }): U
33
46
  return url;
34
47
  }
35
48
 
36
- async function forwardToPrimary(event: QueuedHook): Promise<Response> {
49
+ async function forwardReportToPrimary(item: ReceivedReport): Promise<boolean> {
37
50
  const config = JSON.parse(readFileSync(userConfigPath(), 'utf8')) as { hooks?: { primaryTokenRef?: string; primaryUrl?: unknown } };
38
51
  const ref = config.hooks?.primaryTokenRef;
39
52
  if (!ref) throw new Error('primary token reference missing');
40
53
  const token = await getSecretAsync(ref);
41
54
  if (!token) throw new Error('primary token missing');
42
- return fetch(new URL('/v1/tasks', hooksPrimaryUrl(config)), {
43
- method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${token}`,
44
- 'x-elanous-trace-id': `${event.provider}:${event.eventId}` },
45
- body: JSON.stringify({ ...event.task, eventId: `${event.provider}:${event.eventId}` }), signal: AbortSignal.timeout(10_000),
55
+ const response = await fetch(new URL('/v1/reports/ingest', hooksPrimaryUrl(config)), {
56
+ method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
57
+ body: JSON.stringify(item), signal: AbortSignal.timeout(10_000),
46
58
  });
59
+ return response.ok;
47
60
  }
48
61
 
49
- async function forwardReportToPrimary(item: ReceivedReport): Promise<boolean> {
62
+ async function forwardConsultToPrimary(item: QueuedConsult): Promise<boolean> {
50
63
  const config = JSON.parse(readFileSync(userConfigPath(), 'utf8')) as { hooks?: { primaryTokenRef?: string; primaryUrl?: unknown } };
51
64
  const ref = config.hooks?.primaryTokenRef;
52
65
  if (!ref) throw new Error('primary token reference missing');
53
66
  const token = await getSecretAsync(ref);
54
67
  if (!token) throw new Error('primary token missing');
55
- const response = await fetch(new URL('/v1/reports/ingest', hooksPrimaryUrl(config)), {
68
+ const response = await fetch(new URL('/v1/consult-requests', hooksPrimaryUrl(config)), {
56
69
  method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
57
- body: JSON.stringify(item), signal: AbortSignal.timeout(10_000),
70
+ body: JSON.stringify(item.consult), signal: AbortSignal.timeout(10_000),
58
71
  });
59
72
  return response.ok;
60
73
  }
61
74
 
75
+ /** Raw read like the report forwarder: only an explicit `hooks.consult.enabled: true` opens the route. */
76
+ function consultRouteEnabled(): boolean {
77
+ try {
78
+ const config = JSON.parse(readFileSync(userConfigPath(), 'utf8')) as { hooks?: { consult?: { enabled?: unknown } } };
79
+ return config.hooks?.consult?.enabled === true;
80
+ } catch {
81
+ return false;
82
+ }
83
+ }
84
+
85
+ function consultOrigin(origin: string | null): string | null {
86
+ if (!origin) return null;
87
+ try {
88
+ const url = new URL(origin);
89
+ if (url.protocol !== 'https:' || url.origin !== origin) return null;
90
+ return url.hostname === 'elanous.ai' || url.hostname === 'www.elanous.ai' ||
91
+ /^[a-z0-9-]+\.vercel\.app$/i.test(url.hostname) ? origin : null;
92
+ } catch { return null; }
93
+ }
94
+
62
95
  export function startHookReceiver(options: HookReceiverOptions): { url: string; stop: () => void; queue: HookQueue } {
63
96
  const queue = new HookQueue(options.root);
64
97
  const reportQueue = new ReportQueue(options.root ?? effectiveInstanceRoot(), (event, data) => debug.log('hooks.reports', event, data));
65
98
  const reportLimiter = new ReportLimiter(options.now ?? Date.now);
66
99
  const forwardReport = options.forwardReport ?? forwardReportToPrimary;
100
+ const consultEnabled = options.consultEnabled ?? consultRouteEnabled();
101
+ debug.log('hooks.consult', consultEnabled ? 'route-open' : 'route-closed', {});
102
+ const consultQueue = new ConsultQueue(options.root ?? effectiveInstanceRoot(), (_event, data) =>
103
+ debug.log('hooks.consult', 'rejected', { reason: 'expired', ...data }));
104
+ const consultLimiter = new ConsultLimiter(options.now ?? Date.now);
105
+ const forwardConsult = options.forwardConsult ?? forwardConsultToPrimary;
106
+ let consultFailures = 0;
107
+ let consultNextAt = 0;
108
+ let consultsDraining = false;
109
+ async function drainConsultQueue(): Promise<void> {
110
+ if (stopped || consultsDraining || Date.now() < consultNextAt) return;
111
+ consultsDraining = true;
112
+ try {
113
+ const result = await drainConsults(consultQueue, forwardConsult, (options.now ?? Date.now)());
114
+ if (result.delivered) debug.log('hooks.consult', 'forwarded', { queued: consultQueue.count(), delivered: result.delivered });
115
+ if (result.failed) {
116
+ consultFailures++;
117
+ consultNextAt = Date.now() + Math.min(300_000, Math.max(1, options.retryBaseMs ?? 1000) * 2 ** Math.min(consultFailures - 1, 20));
118
+ debug.log('hooks.consult', 'forward-failed', { queued: consultQueue.count(), reason: 'delivery-failed' });
119
+ } else consultFailures = 0;
120
+ } finally { consultsDraining = false; }
121
+ }
67
122
  let reportFailures = 0;
68
123
  let reportNextAt = 0;
69
124
  let reportsDraining = false;
@@ -81,7 +136,12 @@ export function startHookReceiver(options: HookReceiverOptions): { url: string;
81
136
  } finally { reportsDraining = false; }
82
137
  }
83
138
  const now = options.now ?? Date.now;
84
- const forward = options.forward ?? forwardToPrimary;
139
+ const events = options.events ?? getUserConfig().events ?? parseEventsConfig(undefined);
140
+ // L14: public-repository intake events take the shadow ledger path; every other event keeps the seat dispatch path.
141
+ const dispatch = options.forward ?? ((event: QueuedHook) => dispatchHook(event, options.root ?? effectiveInstanceRoot(), events, options.wakeSeat).then(() => 204));
142
+ const forward = (event: QueuedHook) => event.provider === 'github' && event.task.github
143
+ ? recordGithubShadow(event, options.root ?? effectiveInstanceRoot(), options.githubFetch).then(() => 204)
144
+ : dispatch(event);
85
145
  const attempts = new Map<string, { next: number; failures: number }>();
86
146
  const pending = new Set<string>();
87
147
  let stopped = false;
@@ -112,19 +172,35 @@ export function startHookReceiver(options: HookReceiverOptions): { url: string;
112
172
  }
113
173
  } finally {
114
174
  void drainReportQueue();
175
+ void drainConsultQueue();
115
176
  draining = false;
116
177
  if (!stopped) timer = setTimeout(() => { void drain(); }, Math.min(1000, options.retryBaseMs ?? 1000));
117
178
  }
118
179
  }
119
180
  const server = Bun.serve({ hostname: options.host ?? '127.0.0.1', port: options.port,
120
- async fetch(request) {
181
+ async fetch(request, server) {
121
182
  const url = new URL(request.url);
122
183
  if (request.method === 'GET' && url.pathname === '/hooks/health')
123
184
  return Response.json({ ok: true, queued: queue.count(), reportsQueued: reportQueue.count() });
124
185
  if (request.method === 'POST' && url.pathname === '/v1/reports')
125
186
  return handleReportPost(request, { limiter: reportLimiter, queue: reportQueue, ...(options.now ? { now: options.now } : {}),
126
187
  log: (event, data) => debug.log('hooks.reports', event, data), wake: () => { reportNextAt = 0; void drainReportQueue(); } });
127
- if (request.method !== 'POST' || !/^\/hooks\/(linear|asana)$/.test(url.pathname)) return new Response('Not Found', { status: 404 });
188
+ if (consultEnabled && url.pathname === '/v1/consult' && (request.method === 'POST' || request.method === 'OPTIONS')) {
189
+ const origin = consultOrigin(request.headers.get('origin'));
190
+ if (!origin) {
191
+ debug.log('hooks.consult', 'rejected', { reason: 'origin' });
192
+ return Response.json({ error: 'forbidden' }, { status: 403 });
193
+ }
194
+ const headers = { 'Access-Control-Allow-Origin': origin, Vary: 'Origin',
195
+ 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type' };
196
+ if (request.method === 'OPTIONS') return new Response(null, { status: 204, headers });
197
+ const response = await handleConsultPost(request, { limiter: consultLimiter, queue: consultQueue, ...(options.now ? { now: options.now } : {}),
198
+ ip: server.requestIP(request)?.address ?? 'unknown',
199
+ log: (event, data) => debug.log('hooks.consult', event, data), wake: () => { consultNextAt = 0; void drainConsultQueue(); } });
200
+ for (const [key, value] of Object.entries(headers)) response.headers.set(key, value);
201
+ return response;
202
+ }
203
+ if (request.method !== 'POST' || !/^\/hooks\/(linear|asana|github)$/.test(url.pathname)) return new Response('Not Found', { status: 404 });
128
204
  const provider = url.pathname.slice('/hooks/'.length) as HookProvider;
129
205
  const reject = (reason: string) => {
130
206
  debug.log('hooks.receiver', 'rejected', { provider, reason });
@@ -150,13 +226,15 @@ export function startHookReceiver(options: HookReceiverOptions): { url: string;
150
226
  debug.log('hooks.receiver', 'ignored', { provider, kind: verified.ignored });
151
227
  return new Response(null, { status: 200 });
152
228
  }
153
- if (provider === 'linear') {
229
+ if (provider === 'linear' || provider === 'github') {
154
230
  const eventId = verified.eventIds[0]!;
155
- queue.enqueue({ provider, eventId, task: toExternalTask(provider, { ...(verified.body as object), eventId }) });
231
+ const body = verified.body as { type?: string; action: string; githubEvent?: string };
232
+ const kind = provider === 'linear' ? `${body.type}:${body.action}` : `${body.githubEvent}:${body.action}`;
233
+ queue.enqueue({ provider, eventId, kind, task: toExternalTask(provider, { ...body, eventId }) });
156
234
  } else {
157
235
  const body = verified.body as { events: unknown[] };
158
- const tasks = body.events.map(event => toExternalTask(provider, { event, task: (event as { task?: unknown }).task }));
159
- for (const task of tasks) queue.enqueue({ provider, eventId: task.eventId, task });
236
+ const tasks = body.events.map(event => ({ event: event as { action?: string }, task: toExternalTask(provider, { event, task: (event as { task?: unknown }).task }) }));
237
+ for (const { event, task } of tasks) queue.enqueue({ provider, eventId: task.eventId, kind: `task:${event.action ?? 'unknown'}`, task });
160
238
  }
161
239
  if (!draining) {
162
240
  if (timer) clearTimeout(timer);
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ import { LOGS_SINCE_OPTION, registerLogsCommands } from './cli/logs-cli.js';
9
9
  import { registerDocsCommands } from './cli/docs-cli.js';
10
10
  import { registerA2ACommands } from './cli/a2a-cli.js';
11
11
  import { registerPluginCommands } from './cli/plugin-cli.js';
12
+ import { registerMakeCommand } from './cli/make-cli.js';
12
13
  import { registerConnectCommand, registerSkillsCommands } from './cli/skills-cli.js';
13
14
  import { registerImportCommand } from './cli/import-cli.js';
14
15
  import { registerPersonaCommands } from './cli/persona-cli.js';
@@ -873,8 +874,10 @@ seatCmd.command('loop').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
873
874
  .option('--json', 'JSON 출력')
874
875
  .action(async (opts: { seat: string; once: boolean; json?: boolean }) => {
875
876
  try {
876
- const { runSeatLoopOnce } = await import('./seat-loop/seat-loop.js');
877
- const result = await runSeatLoopOnce(opts.seat);
877
+ // V3 F5: without the sink, the seat loop's judgment lines (seat.loop) never reach the log store when cron runs it.
878
+ await (await import('./domains/standalone-log-sink.js')).registerStandaloneLogSink('seat-loop');
879
+ const { runSeatLoopTurn } = await import('./seat-loop/seat-loop.js');
880
+ const result = await runSeatLoopTurn(opts.seat);
878
881
  if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
879
882
  else console.log(`seat loop ${opts.seat}: ${result.status}${'runId' in result && result.runId ? ` ${result.runId}` : ''}`);
880
883
  } catch (error) { console.error(`seat loop: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
@@ -913,6 +916,7 @@ registerCardCommand(program);
913
916
  registerLaunchHeadCommands(program);
914
917
  registerA2ACommands(program);
915
918
  registerPluginCommands(program);
919
+ registerMakeCommand(program);
916
920
  registerSkillsCommands(program);
917
921
  registerConnectCommand(program);
918
922
  registerImportCommand(program);
@@ -3024,6 +3028,48 @@ const harnessOrchestrateCmd = registerHarnessOrchestrateCapabilityOptions(
3024
3028
  await runHarnessOrchestrateExecution(plan, parts);
3025
3029
  });
3026
3030
 
3031
+ const contextCmd = program.command('context').description('외부 에이전트 맥락 이벤트');
3032
+ contextCmd.command('hooks').description('Claude Code 맥락 훅 설정').command('install')
3033
+ .requiredOption('--print', '설정 조각만 출력하고 설정 파일은 수정하지 않음')
3034
+ .action(async () => {
3035
+ const { claudeHooksSettings } = await import('./context-bus/claude-hooks-install.js');
3036
+ console.log(claudeHooksSettings(REPOSITORY_ROOT));
3037
+ });
3038
+ contextCmd.command('emit [sessionKind]')
3039
+ .description('외부 에이전트 세션 이벤트: emit <kind> --seat <자리> --text <한 줄> [--ref <PR|칸>]')
3040
+ .option('--seat <seat>', 'OP|TC|MK|UX')
3041
+ .option('--text <line>', '한 줄 이벤트')
3042
+ .option('--ref <PR|cell>', '연결 PR 또는 칸')
3043
+ .option('--kind <kind>', '기존 Claude Code 훅 이벤트 종류')
3044
+ .option('--summary <line>', '기존 훅 한 줄 요약')
3045
+ .option('--source <link>', '기존 훅 출처 링크')
3046
+ .action(async (sessionKind: string | undefined, opts: { seat?: string; text?: string; ref?: string; kind?: string; summary?: string; source?: string }) => {
3047
+ try {
3048
+ if (sessionKind !== undefined) {
3049
+ if (opts.seat === undefined || opts.text === undefined || opts.kind !== undefined || opts.summary !== undefined || opts.source !== undefined) {
3050
+ throw new Error('context emit <kind> requires --seat and --text (not hook options)');
3051
+ }
3052
+ const { emitSessionEvent, SESSION_EVENT_KINDS } = await import('./context-bus/session-events.js');
3053
+ if (!SESSION_EVENT_KINDS.includes(sessionKind as import('./context-bus/session-events.js').SessionEventKind)) {
3054
+ throw new Error(`unknown context session kind: ${sessionKind}`);
3055
+ }
3056
+ emitSessionEvent({ kind: sessionKind as import('./context-bus/session-events.js').SessionEventKind,
3057
+ seat: opts.seat, text: opts.text, ...(opts.ref === undefined ? {} : { ref: opts.ref }) });
3058
+ } else {
3059
+ if (opts.seat !== undefined || opts.text !== undefined || opts.ref !== undefined || !opts.kind || opts.summary === undefined || opts.source === undefined) {
3060
+ throw new Error('context emit hook requires --kind, --summary and --source');
3061
+ }
3062
+ if (!['claimed', 'done', 'asked', 'guide-changed'].includes(opts.kind)) throw new Error(`unknown context hook kind: ${opts.kind}`);
3063
+ const { recordExternalEvent } = await import('./context-bus/external-events.js');
3064
+ recordExternalEvent({ origin: 'claude-code', kind: opts.kind as import('./context-bus/external-events.js').ContextHookKind,
3065
+ summary: opts.summary, source: opts.source });
3066
+ }
3067
+ } catch (error) {
3068
+ console.error(`context emit: ${error instanceof Error ? error.message : String(error)}`);
3069
+ process.exitCode = 2;
3070
+ }
3071
+ });
3072
+
3027
3073
  const coordCmd = program.command('coord').description('조율 채널 맥락 원장');
3028
3074
  coordCmd.command('event').command('record')
3029
3075
  .requiredOption('--seat <ID>', '발신 자리')
@@ -3975,11 +4021,12 @@ selfCmd
3975
4021
  .option('--changed', '변경 파일 범위 게이트임을 명시한다')
3976
4022
  .option('--base <ref>', '커밋됐지만 PR 없는 변경의 비교 기준(ref...HEAD)')
3977
4023
  .option('--pr <number>', '열린 PR 번호에서 gh pr view files로 변경 파일을 읽는다')
3978
- .action((opts: { changed?: boolean; base?: string; pr?: string }) => {
3979
- if (!opts.changed) { ui.error('self gate requires --changed'); process.exitCode = 2; return; }
4024
+ .option('--shards [number]', '메모리 예산에 맞춰 시험을 별도 프로세스로 분할한다 (기본 2)')
4025
+ .action((opts: { changed?: boolean; base?: string; pr?: string; shards?: string | boolean }) => {
4026
+ if (!opts.changed && opts.shards === undefined) { ui.error('self gate requires --changed or --shards'); process.exitCode = 2; return; }
3980
4027
  try {
3981
4028
  const { runSelfGateCli } = require('./self-implement/gate-cli.js') as typeof import('./self-implement/gate-cli.js');
3982
- const result = runSelfGateCli(process.cwd(), { base: opts.base, pr: opts.pr });
4029
+ const result = runSelfGateCli(process.cwd(), { base: opts.base, pr: opts.pr, shards: opts.shards === undefined ? undefined : opts.shards === true ? 2 : Number(opts.shards) });
3983
4030
  console.log(result.lines.join('\n'));
3984
4031
  process.exitCode = result.exitCode;
3985
4032
  } catch (error) {
@@ -4011,7 +4058,8 @@ selfCmd
4011
4058
  // runSelfImplement(내부 SelfImplement 툴과 동일 코어)를 감싼다: fork→worktree→헤드리스 goal-loop
4012
4059
  // (+클린빌드 앵커)→gate(bun test)→PR(HITL). PR-open 은 --open-pr(명시 승인)일 때만·기본 fail-closed.
4013
4060
  selfCmd
4014
- .command('implement <feature...>')
4061
+ .command('implement [feature...]')
4062
+ .option('--feature-file <path>', 'feature 문면을 파일에서 읽는다 (문면을 argv 에 싣지 않음)')
4015
4063
  .description('자율 구현(self-build) — feature 를 격리 worktree 에서 goal-loop + 클린빌드 앵커로 끝까지 구현하고 gate(bun test) 통과까지. --config-dir 의 provider 로 모델 선택(gemma 등). PR-open 은 --open-pr(HITL 명시승인)일 때만. 수분 소요.')
4016
4064
  .option('--base <branch>', 'PR base 브랜치(생략 시 provider 기본)')
4017
4065
  .option('--no-draft', 'non-draft PR (기본 draft)')
@@ -4029,8 +4077,11 @@ selfCmd
4029
4077
  .option('--no-supervise', '⛔ 런 슈퍼바이저를 «끈다»(대표 2026-08-22: ***기본 ON***) — 켜져 있으면 실행이 끝나면 실패를 «트리아지»해서 다시 걸 수 있으면 스스로 재개한다(끝까지). 정지 사유는 converged|needs-human|max-rounds|no-progress 로 각각 «다른 값». 관측=elanous logs --category self-dev.supervisor')
4030
4078
  .option('--supervise-rounds <n>', '슈퍼바이저 재개 라운드 상한 (기본 3 · 끄려면 --no-supervise)')
4031
4079
  .option('--json', '구조화 출력 {stage, ok, branch, worktree, prUrl?, merged?}')
4032
- .action(async (parts: string[], opts: { base?: string; draft?: boolean; openPr?: boolean; autoMerge?: boolean; autoReview?: boolean; maxWait?: string; json?: boolean; plan?: boolean; enhance?: boolean; ground?: boolean; observeOnly?: boolean }) => {
4033
- const feature = parts.join(' ').trim();
4080
+ .action(async (parts: string[], opts: { featureFile?: string; base?: string; draft?: boolean; openPr?: boolean; autoMerge?: boolean; autoReview?: boolean; maxWait?: string; json?: boolean; plan?: boolean; enhance?: boolean; ground?: boolean; observeOnly?: boolean }) => {
4081
+ if (opts.featureFile && parts.length > 0) { ui.error('--feature-file 과 위치 인자 feature 는 함께 줄 수 없다'); process.exit(2); }
4082
+ let feature: string;
4083
+ try { feature = (opts.featureFile ? readFileSync(opts.featureFile, 'utf8') : parts.join(' ')).trim(); }
4084
+ catch (error) { ui.error(`--feature-file 읽기 실패: ${String(error)}`); process.exit(2); return; }
4034
4085
  if (!feature) { ui.error('feature 필요: elanous self implement "<무엇을 구현할지>"'); process.exit(2); }
4035
4086
  // Retired entry points must fail before run identity or log-sink setup creates observable execution state.
4036
4087
  if (opts.plan) { ui.error('self implement --plan is retired and rejected'); process.exit(1); return; }
@@ -4128,8 +4179,14 @@ export function setSelfOrchestrateSpawnForTesting(spawn: typeof selfOrchestrateS
4128
4179
  selfOrchestrateSpawnForTesting = spawn;
4129
4180
  }
4130
4181
 
4182
+ export function readSelfOrchestrateGoals(parts: string[], goalFiles: readonly string[] = []): { request: string; goals: string[] } {
4183
+ const fileGoals = goalFiles.map((path) => readFileSync(path, 'utf8'));
4184
+ return { request: [...parts, ...fileGoals].join(' '), goals: [...splitOrchestrateGoalTexts(parts), ...fileGoals] };
4185
+ }
4186
+
4131
4187
  const selfOrchestrateCmd = selfCmd
4132
4188
  .command('orchestrate [goals...]')
4189
+ .option('--goal-file <path>', '골 문면을 파일에서 읽는다 (반복 가능)', (value: string, acc: string[]) => [...acc, value], [] as string[])
4133
4190
  .description('병렬 self-dev — 여러 goal 을 각자 격리 worktree self-implement 서브프로세스로 동시성캡 병렬 실행. goal 은 `;;` 로 구분(또는 각 인자 1 goal). --concurrency 로 동시 잡 수(기본 2).')
4134
4191
  .option('--concurrency <n>', '동시 실행 잡 수 (기본 2)')
4135
4192
  .option('--auto-merge', '각 잡: 리뷰 clean 시 자동 병합(각 self-implement 에 --auto-merge 전달·리뷰노드 경유)')
@@ -4138,7 +4195,7 @@ const selfOrchestrateCmd = selfCmd
4138
4195
  .option('--base <branch>', '각 잡 PR base 브랜치')
4139
4196
  .option('--decompose', 'S2 — goal 1개를 LLM 으로 의존성 서브-DAG(위상 병렬 + hot-file 직렬)로 분해 후 실행')
4140
4197
  .addOption(new Option('--pod-skill-env', 'pod: 필수 스킬(설정 pod-skills.txt)의 키(.env)를 이 런의 Secret 으로 넘긴다 — 명시 opt-in(유료 크레딧) · 이미지엔 안 들어간다').hideHelp())
4141
- .addOption(new Option('--pod-pool <spec>', 'pod 풀 — 컨텍스트[@ssh호스트][:상한] 을 쉼표로, 앞이 우선(예 pool-node-b@node-b:12,pool-node-c@node-c:3) · 없으면 ELANOUS_POD_POOL · 그것도 없으면 현재 컨텍스트 하나').hideHelp())
4198
+ .addOption(new Option('--pod-pool <spec>', 'pod 풀 — 컨텍스트[@ssh호스트][:상한][#k3d-레지스트리:포트] 쉼표, 앞이 우선(예 pool-node-b@node-b:12#k3d-elanous-registry:5051,pool-node-c@node-c:3#k3d-elanous-registry:5052) · 없으면 ELANOUS_POD_POOL · 그것도 없으면 현재 컨텍스트 하나').hideHelp())
4142
4199
  .addOption(new Option('--reduce', '끝에 PR 을 연 조각들을 통합 브랜치 하나로 모아(게이트 한 번) PR 하나 — `--open-pr` 과 짝 · `--auto-merge` 와는 함께 못 쓴다(elanous self reduce)').hideHelp())
4143
4200
  .option('--substrate <kind>', '실행 칸: local(기본 · 격리 워크트리) | pod(k8s Job · docker/harness 이미지 · MANUAL-pods-for-elanous-ops-and-dev)')
4144
4201
  .option('--pod-account <name>', 'pod: codex 계정(~/.elanous/auth.json openai-codex:<name> · refresh 제외 사본) · 없으면 브로커가 Job 마다 잔량 많은 계정을 돌려 준다')
@@ -4146,11 +4203,14 @@ const selfOrchestrateCmd = selfCmd
4146
4203
  .option('--pod-pass-env <keys>', 'pod: 호스트 env 에서 Pod 로 넘길 키(쉼표) — 예 OPENROUTER_API_KEY,ANTHROPIC_API_KEY(벤치마크 과금 경로)')
4147
4204
  .option('--bench-arms <spec>', 'pod 벤치마크: 골 1개를 팔마다 «라벨 한 줄만 다르게» 복제해 동시에 — "id=provider[:model][@KEY+KEY];…" (예 codex=openai-codex;or-kimi=openrouter:openrouter/moonshotai/kimi-k3@OPENROUTER_API_KEY) · --auto-merge 거부 · RFC fleet 슈퍼바이저 §A3')
4148
4205
  .option('--help-all', '모든 orchestrate 옵션 표시')
4149
- .action(function (this: Command, parts: string[], opts: { concurrency?: string; autoMerge?: boolean; autoReview?: boolean; openPr?: boolean; base?: string; teardown?: boolean; resume?: string; board?: boolean; decompose?: boolean; fabricDecompose?: boolean; maxTasks?: string; supervise?: boolean; superviseRounds?: string; json?: boolean }) {
4206
+ .action(function (this: Command, parts: string[], opts: { goalFile?: string[]; concurrency?: string; autoMerge?: boolean; autoReview?: boolean; openPr?: boolean; base?: string; teardown?: boolean; resume?: string; board?: boolean; decompose?: boolean; fabricDecompose?: boolean; maxTasks?: string; supervise?: boolean; superviseRounds?: string; json?: boolean }) {
4150
4207
  return (async () => {
4151
- // goal 분리: 단일 인자에 `;;` 가 있으면 그걸로 split, 아니면 각 positional = 1 goal.
4152
- const joined = parts.join(' ');
4153
- let goalTexts = splitOrchestrateGoalTexts(parts);
4208
+ // 위치 인자는 종전처럼 분리하고 파일 입력은 파일당 한 골이다.
4209
+ let inputGoals: ReturnType<typeof readSelfOrchestrateGoals>;
4210
+ try { inputGoals = readSelfOrchestrateGoals(parts, opts.goalFile); }
4211
+ catch (error) { ui.error(`--goal-file 읽기 실패: ${String(error)}`); process.exit(2); return; }
4212
+ const joined = inputGoals.request;
4213
+ let goalTexts = inputGoals.goals;
4154
4214
  if ((opts as { reduce?: boolean }).reduce && opts.autoMerge) { ui.error('--reduce 는 --auto-merge 와 함께 못 쓴다 — 조각을 하나씩 main 에 병합하는 것과 하나로 모으는 것은 반대다(--open-pr 과 짝)'); process.exit(2); }
4155
4215
  // ☸️ 벤치 팔 — 골 1개를 팔마다 라벨 한 줄만 다르게(A/B 매뉴얼 ②) · pod 전용 · 자동 머지 금지(한 팔이 머지되면 다른 팔의 밑 땅이 바뀐다).
4156
4216
  const benchSpec = (opts as { benchArms?: string }).benchArms;
@@ -6298,7 +6358,7 @@ const selfDevCmd = program
6298
6358
  // `drive --help` 에도 그대로 보이고 자식이 그것을 계약으로 읽는다.
6299
6359
  // ⇒ 별칭을 없애지 않는다([[RFC-two-command-convergence-dev-and-pty-2026-07-28]] §6-2 = 층이 다르니
6300
6360
  // `drive` 는 프리미티브로 **유지**한다) — 대신 **도움말이 그 갈림을 먼저 말하게** 한다.
6301
- .description('⛔ `drive` 별칭으로 부르면 옵션은 여덟뿐 (--goal · --attach · --max-steps · --poll-ms · --model · --cwd · --worktree · --json) — `--attach <ref>` 는 이미 있는 PTY 를 몬다(생략하면 셸 명령을 새로 띄운다). 나머지는 전부 `dev` 전용이고 `drive` 에서는 거부된다. dev 와 drive 는 한 명령이라 이 도움말을 공유하므로, 아래 목록은 `dev` 기준이다. ⚠️ 실험 — 통합 self-dev 파이프라인 runDevPipeline. --backend self(디폴트·elanous-chat 자체구현)|codex/claude/gemini/grok(외부). --transport pty(디폴트·worktree·--branch 필수)|acp(cwd 세션·U6·capability 미검증). 미배선 조합은 NotYetUnified 명시 거부. ★self 는 무인 완결이 기본(PR 개설→auto-review 라벨→리뷰 clean 시 병합) — 끄려면 --no-open-pr/--no-auto-review/--no-auto-merge. 관측=elanous logs --category dev-pipeline · 상세=docs/manual/MANUAL-frontdoor-selfdev-dogfood-mechanism-2026-07-25.md')
6361
+ .description('⛔ `drive` 별칭으로 부르면 옵션은 아홉뿐 (--goal · --attach · --max-steps · --poll-ms · --model · --cwd · --worktree · --json · --jail-home) — `--attach <ref>` 는 이미 있는 PTY 를 몬다(생략하면 셸 명령을 새로 띄운다). 나머지는 전부 `dev` 전용이고 `drive` 에서는 거부된다. dev 와 drive 는 한 명령이라 이 도움말을 공유하므로, 아래 목록은 `dev` 기준이다. ⚠️ 실험 — 통합 self-dev 파이프라인 runDevPipeline. --backend self(디폴트·elanous-chat 자체구현)|codex/claude/gemini/grok(외부). --transport pty(디폴트·worktree·--branch 필수)|acp(cwd 세션·U6·capability 미검증). 미배선 조합은 NotYetUnified 명시 거부. ★self 는 무인 완결이 기본(PR 개설→auto-review 라벨→리뷰 clean 시 병합) — 끄려면 --no-open-pr/--no-auto-review/--no-auto-merge. 관측=elanous logs --category dev-pipeline · 상세=docs/manual/MANUAL-frontdoor-selfdev-dogfood-mechanism-2026-07-25.md')
6302
6362
  .option('--file <path>', 'input 파일(verbatim 바이트·<text...> 대신)')
6303
6363
  // ⭐ 대표 2026-08-11 — 발사 절차 «넷»을 한 명령으로. ask 파일을 주면 ⑴저작 → ⑵열린 PR ⊕ ⑶도는 런 검사 → ⑷발사.
6304
6364
  // ⛔ 걸리면 «이름을 대며» 멈춘다(조용히 진행하지 않는다). 우회는 --force-preflight 이고 그 사실이 관측에 남는다.
@@ -6324,6 +6384,7 @@ const selfDevCmd = program
6324
6384
  .option('-n, --max-steps <n>', 'elanous 또는 셸 drive: 최대 제어 스텝(기본 30)')
6325
6385
  .option('-p, --poll-ms <ms>', 'elanous 또는 셸 drive: 제어 스텝 간 폴 간격(ms·0 허용·기본 800)')
6326
6386
  .option('--attach <ref>', 'drive: 이미 있는 PTY 를 몬다(생략하면 셸 명령을 새로 띄운다·pty auto 와 같은 루프)')
6387
+ .option('--jail-home <dir>', 'drive: DRIVE-JAIL — 두뇌 입력에 이 디렉터리 밖 경로가 있으면 PTY 로 보내지 않는다')
6327
6388
  .option('-m, --model <id>', 'elanous 또는 셸 drive: 제어 brain LLM 모델(기본 config)')
6328
6389
  .option('--observe-only', 'elanous: child boot부터 SelfImplement 호출을 기록만 한다')
6329
6390
  .option('--isolated-root <path>', 'elanous: child config/state 격리 루트(설정 실패 시 fail-closed)')
@@ -6620,6 +6681,7 @@ const selfDevCmd = program
6620
6681
  ...(devOpts.worktree === true ? { worktree: true } : {}),
6621
6682
  ...(opts.json === true ? { json: true } : {}),
6622
6683
  attach: devOpts.attach,
6684
+ ...(devOpts.jailHome ? { jailHome: devOpts.jailHome } : {}),
6623
6685
  }, {
6624
6686
  exit: ((code: number): never => {
6625
6687
  completionGuard.conclude();
@@ -25,6 +25,7 @@ import type {
25
25
  } from './enrich.js';
26
26
  import { summariseContext } from './enrich.js';
27
27
  import { buildResponseFormatHeader } from './prompt-format.js';
28
+ import { judge } from '../llm/judge-layer.js';
28
29
 
29
30
  // ──────────────────── Closed sets ──────────────────────────────────────
30
31
 
@@ -69,7 +70,7 @@ export interface CategorizeResult {
69
70
  }
70
71
 
71
72
  export interface CategorizeCallable {
72
- (args: { prompt: string; signal?: AbortSignal }): Promise<{
73
+ (args: { prompt: string; signal?: AbortSignal; provider?: string; model?: string }): Promise<{
73
74
  text: string;
74
75
  promptTokens?: number;
75
76
  completionTokens?: number;
@@ -219,26 +220,6 @@ export function buildCategorizePrompt(decomposition: EnrichedDecomposition): str
219
220
 
220
221
  // ──────────────────── Parse + coerce ──────────────────────────────────
221
222
 
222
- function extractJsonBlock(text: string): unknown | null {
223
- const trimmed = text.trim();
224
- const fence = trimmed.match(/```(?:json)?\n([\s\S]*?)```/);
225
- const candidate = fence ? fence[1]! : trimmed;
226
- try {
227
- return JSON.parse(candidate);
228
- } catch {
229
- const open = candidate.indexOf('{');
230
- const close = candidate.lastIndexOf('}');
231
- if (open >= 0 && close > open) {
232
- try {
233
- return JSON.parse(candidate.slice(open, close + 1));
234
- } catch {
235
- return null;
236
- }
237
- }
238
- return null;
239
- }
240
- }
241
-
242
223
  function coerceConfidence(v: unknown): 'high' | 'medium' | 'low' {
243
224
  if (v === 'high' || v === 'medium' || v === 'low') return v;
244
225
  return 'medium';
@@ -306,27 +287,18 @@ export async function categorizeDecomposition(
306
287
 
307
288
  const prompt = buildCategorizePrompt(decomposition);
308
289
 
309
- let raw;
310
- try {
311
- raw = await opts.callable({ prompt, signal: opts.signal });
312
- } catch (err) {
313
- if (opts.strict) {
314
- throw new CategorizeError(
315
- 'LLM_CALL_FAILED',
316
- err instanceof Error ? err.message : String(err),
317
- );
318
- }
319
- return {
320
- categorizations: Object.fromEntries(tasks.map((t) => [t.key, fallbackRow(t.key)])),
321
- fallback: true,
322
- };
323
- }
324
-
325
- const parsed = extractJsonBlock(raw.text);
326
- const coerced = parsed ? coerceCategorizations(parsed, validKeys) : null;
327
- if (coerced === null) {
290
+ const decision = await judge({
291
+ site: 'intake.categorize', prompt, signal: opts.signal,
292
+ call: ({ prompt, signal, provider, model }) => opts.callable({ prompt, signal, provider, model }),
293
+ schema: (parsed) => coerceCategorizations(parsed, validKeys),
294
+ });
295
+ if (!decision.ok) {
328
296
  if (opts.strict) {
329
- throw new CategorizeError('PARSE_FAILED', 'no usable categorizations', raw.text);
297
+ if (decision.reason === 'call') {
298
+ throw new CategorizeError('LLM_CALL_FAILED',
299
+ decision.error instanceof Error ? decision.error.message : String(decision.error));
300
+ }
301
+ throw new CategorizeError('PARSE_FAILED', 'no usable categorizations', decision.rawText);
330
302
  }
331
303
  return {
332
304
  categorizations: Object.fromEntries(tasks.map((t) => [t.key, fallbackRow(t.key)])),
@@ -336,7 +308,7 @@ export async function categorizeDecomposition(
336
308
 
337
309
  // Backfill any missing tasks with the fallback shape so callers can
338
310
  // index by key without null checks.
339
- const filled: Record<string, TaskCategorization> = { ...coerced };
311
+ const filled: Record<string, TaskCategorization> = { ...decision.value };
340
312
  for (const t of tasks) {
341
313
  if (!filled[t.key]) filled[t.key] = fallbackRow(t.key);
342
314
  }
@@ -344,10 +316,10 @@ export async function categorizeDecomposition(
344
316
  categorizations: filled,
345
317
  fallback: false,
346
318
  usage: {
347
- promptTokens: raw.promptTokens,
348
- completionTokens: raw.completionTokens,
349
- costUsd: raw.costUsd,
350
- modelId: raw.modelId,
319
+ promptTokens: decision.reply.promptTokens,
320
+ completionTokens: decision.reply.completionTokens,
321
+ costUsd: decision.reply.costUsd,
322
+ modelId: decision.reply.modelId,
351
323
  },
352
324
  };
353
325
  }
@@ -1,11 +1,15 @@
1
1
  import { debug } from '../debug/log.js';
2
2
  import { discordDecisionOwner } from '../decisions/discord-decision-cards.js';
3
3
  import { canonicalSeatId } from '../msg/msg-store.js';
4
+ import { awaitGlobalPersonaLoad, getGlobalPersonaRegistry } from '../persona/global-registry.js';
5
+ import type { PersonaSource } from '../persona/mention-parser.js';
4
6
  import { dispatchCeoTask, type CeoCommandDeps } from '../seat-dispatch/ceo-commands.js';
5
7
  import { ceoTaskDeps, classifyCeoIntent } from '../seat-dispatch/ceo-intent.js';
8
+ import { askSeat, parseSeatAsk, type SeatAskDeps } from '../seat-dispatch/seat-ask.js';
6
9
  import { parseSeatAddress, resolveSeat } from '../seat-address/seat-address.js';
7
10
  import { getUserConfig, type UserConfig } from '../user-config.js';
8
11
  import { answerAsSeat } from './seat-answer.js';
12
+ import { answerAsPersona, resolvePersonaAddress, type PersonaAnswerDeps } from './persona-answer.js';
9
13
  import {
10
14
  submitIntakeWork,
11
15
  type SubmitIntakeWorkDeps,
@@ -23,8 +27,12 @@ export interface DiscordSeatWorkDeps extends SubmitIntakeWorkDeps {
23
27
  submit?: typeof submitIntakeWork;
24
28
  config?: UserConfig;
25
29
  answer?: typeof answerAsSeat;
30
+ personaSource?: PersonaSource;
31
+ personaAnswer?: typeof answerAsPersona;
32
+ personaAnswerDeps?: PersonaAnswerDeps;
26
33
  dispatch?: typeof dispatchCeoTask;
27
34
  commandDeps?: CeoCommandDeps;
35
+ askDeps?: SeatAskDeps;
28
36
  }
29
37
 
30
38
  /** Addressed work preserves graph intake except for one owner's private seat request. */
@@ -44,7 +52,15 @@ export async function handleDiscordSeatWork(
44
52
  debug.log('seat.dispatch', 'intent', { seat, intent: 'task', via: 'discord', outcome: result.channel });
45
53
  return result.reply;
46
54
  };
47
- const address = parseSeatAddress(text);
55
+ if (parseSeatAsk(text)) {
56
+ const auth = owner();
57
+ if (!auth) return null;
58
+ if (!deps.askDeps) throw new Error('seat ask delivery unavailable');
59
+ return askSeat(text, { channel: 'discord', channelId: msg.channelId, messageId: msg.messageId,
60
+ ...(msg.threadId ? { threadId: msg.threadId } : {}) },
61
+ deps.commandDeps ?? ceoTaskDeps(auth.cfg, auth.id), deps.askDeps);
62
+ }
63
+ const address = parseSeatAddress(text.replace(/^(@[A-Za-z][A-Za-z0-9_-]*(?:,@?[A-Za-z][A-Za-z0-9_-]*)*)/, (prefix) => prefix.replaceAll(',@', ',')));
48
64
  if (!address) {
49
65
  if (!text.trim() || /^\s*[/@@]/.test(text)) return null;
50
66
  const auth = owner();
@@ -57,11 +73,31 @@ export async function handleDiscordSeatWork(
57
73
  }
58
74
 
59
75
  const seats = address.seats.map((name) => ({ name, seat: resolveSeat(name) }));
60
- const unknown = seats.filter(({ seat }) => !seat).map(({ name }) => `@${name}`);
76
+ const hasUnresolved = seats.some(({ seat }) => !seat);
77
+ const auth = hasUnresolved ? owner() : null;
78
+ if (hasUnresolved && auth && !deps.personaSource) await awaitGlobalPersonaLoad();
79
+ const source = hasUnresolved && auth ? (deps.personaSource ?? getGlobalPersonaRegistry()) : null;
80
+ const addressed = seats.map(({ name, seat }) => ({
81
+ name, seat, persona: !seat && source ? resolvePersonaAddress(name, source) : null,
82
+ }));
83
+ const unknown = addressed.filter(({ seat, persona }) => !seat && (!persona || !auth)).map(({ name }) => `@${name}`);
61
84
  if (unknown.length) return `어느 좌석을 말씀하시나요? ${unknown.join(', ')}은(는) 등록된 좌석이 아닙니다. 좌석을 확인해 다시 보내 주세요.`;
85
+ const personas = addressed.filter(({ persona }) => persona);
86
+ if (personas.length && addressed.length !== 1) {
87
+ debug.log('persona.address', 'rejected', { reason: 'mixed', via: 'discord' });
88
+ return '페르소나는 한 번에 하나만 부를 수 있습니다';
89
+ }
62
90
  const body = address.body.trim();
63
91
  if (!body) return '어떤 일을 맡길까요? 좌석 주소 뒤에 요청 내용을 적어 다시 보내 주세요.';
64
92
 
93
+ if (personas.length === 1 && personas[0]?.persona) {
94
+ const { name, persona } = personas[0];
95
+ debug.log('persona.address', 'resolved', { name, personaId: persona.personaId, via: 'discord' });
96
+ const answer = await (deps.personaAnswer ?? answerAsPersona)(persona, body, deps.personaAnswerDeps);
97
+ debug.log('persona.address', 'answered', { personaId: persona.personaId, via: 'discord' });
98
+ return answer;
99
+ }
100
+
65
101
  if (seats.length === 1 && seats[0]?.seat) {
66
102
  const auth = owner();
67
103
  const seatId = canonicalSeatId(seats[0].seat.id);