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
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "outDir": "dist",
10
+ "rootDir": "."
11
+ },
12
+ "include": ["src/**/*.ts", "scripts/**/*.ts"]
13
+ }
package/src/acp/server.ts CHANGED
@@ -241,6 +241,8 @@ export interface AcpServerOptions {
241
241
  /** ACP standalone entry: require session cwd or an explicit boot default. */
242
242
  requireSessionToolCwd?: boolean;
243
243
  bootToolCwd?: string;
244
+ /** Optional PTY factory for the web terminal; production uses PreviewTerminal. */
245
+ createWebTerminal?: (opts: ConstructorParameters<typeof import('../preview/terminal.js').PreviewTerminal>[0]) => import('../preview/terminal.js').PreviewTerminal;
244
246
  /** Test seam for exercising stdio EOF with controlled byte streams. */
245
247
  stdioInput?: ReadableStream<Uint8Array>;
246
248
  stdioOutput?: WritableStream<Uint8Array>;
@@ -2190,7 +2192,8 @@ function wireAcpConnection(
2190
2192
  throw new Error('terminal/spawn: sessionId required');
2191
2193
  }
2192
2194
  const tid = resolveAcpTerminalId(p.terminalId);
2193
- const cwd = typeof p.cwd === 'string' && p.cwd.length > 0 ? p.cwd : process.cwd();
2195
+ const cwd = typeof p.cwd === 'string' && p.cwd.length > 0 ? p.cwd
2196
+ : (await import('../project/session-context.js')).resolveSessionProjectContext(p.sessionId)?.cwd ?? process.cwd();
2194
2197
  const cols = typeof p.cols === 'number' && p.cols > 0 ? p.cols : 80;
2195
2198
  const rows = typeof p.rows === 'number' && p.rows > 0 ? p.rows : 24;
2196
2199
 
@@ -2234,7 +2237,7 @@ function wireAcpConnection(
2234
2237
  }
2235
2238
 
2236
2239
  const { PreviewTerminal } = await import('../preview/terminal.js');
2237
- const pt = new PreviewTerminal({
2240
+ const pt = (opts.createWebTerminal ?? ((terminalOpts) => new PreviewTerminal(terminalOpts)))({
2238
2241
  cols, rows, cwd,
2239
2242
  // Web-terminal child shell renders inside the PWA's xterm.js,
2240
2243
  // which implements the xterm-256color terminfo. When the daemon
@@ -20,8 +20,12 @@ import { configuredWorktreeRoot } from '../user-config.js';
20
20
  import { worktreeHasChanges, commitWorktree, changedFiles } from '../self-implement/seams.js';
21
21
  import { streamLLM, type LLMMessage } from '../llm.js';
22
22
  import { debug } from '../debug/log.js';
23
+ import { emitPtyDecision, type DecisionInput } from './pty-decision.js';
24
+ import { observeExternalEvent } from '../context-bus/external-events.js';
25
+ import { emitSessionEvent, type SessionEventInput } from '../context-bus/session-events.js';
23
26
  import { emitDecision } from '../live/detail-switch.js';
24
27
  import { resolvePtyWebAddress } from '../cli/pty-web-address.js';
28
+ import { verdictForFinalPtyScreen } from '../cli/pty-drive-verdict.js';
25
29
  import { reemitPtyUsage } from '../budget/pty-usage-reemit.js';
26
30
  import { classifyAuthError } from '../oauth/codex.js';
27
31
  import type { FallbackStep } from '../oauth/fallback-chain.js';
@@ -449,6 +453,8 @@ export interface AgentMissionSpec {
449
453
  evidence: EvidenceMode;
450
454
  /** RFC 최대 라운드(기본 16). */
451
455
  maxRounds?: number;
456
+ /** 화면 무변화 회복 문턱(ms, 기본 45초). */
457
+ recoverAfterMs?: number;
452
458
  /** 완료 시 자동 commit(기본 true). */
453
459
  commit?: boolean;
454
460
  /** 스크린 캡처 저장 디렉토리. */
@@ -522,6 +528,8 @@ export interface AgentMissionDeps {
522
528
  createWorktree?: typeof createWorktree;
523
529
  recordWorktreeProvenance?: typeof recordHarnessWorktreeProvenance;
524
530
  runControlLoop?: typeof runPtyControlLoop;
531
+ /** Capture decisions in tests without replacing the process-wide debug logger. */
532
+ emitPtyDecision?: typeof emitPtyDecision;
525
533
  /** Inject controller responses while keeping the production control loop. */
526
534
  controlStream?: StreamLLMFn;
527
535
  resolvePtyWebAddress?: typeof resolvePtyWebAddress;
@@ -534,6 +542,12 @@ export interface AgentMissionDeps {
534
542
  checkEvidence?: typeof checkEvidence;
535
543
  commitWorktree?: typeof commitWorktree;
536
544
  dispatchOpenPullRequest?: typeof dispatchOpenPullRequest;
545
+ /** Optional context-journal sink for isolated missions. */
546
+ emitContextEvent?: (input: SessionEventInput) => void;
547
+ /** Internal continuation retains the original mission's context-event owner. */
548
+ contextEventRun?: boolean;
549
+ /** Carries a PR number back to the outer mission's context event. */
550
+ onMissionPrNumber?: (number: number) => void;
537
551
  terminateProcessTree?: typeof terminateMissionProcessTree;
538
552
  repoStatus?: (repo: string) => string | Promise<string>;
539
553
  emitDecision?: typeof emitDecision;
@@ -830,18 +844,37 @@ export interface MissionControlBrainOpts {
830
844
  readonly handoffEnabled?: boolean;
831
845
  /** Screen-grounded brain summary for the next backend, never the raw PTY screen. */
832
846
  readonly onSummary?: (summary: string) => void;
847
+ readonly onDecision?: (text: string, reply?: { question: string; answer: string }) => void;
848
+ readonly recoverAfterMs?: number;
849
+ readonly initialCommand?: string;
850
+ readonly onRecover?: (blocked: string, action: string) => void;
833
851
  }
834
852
 
835
853
  /** 기존 5-action mission 판단을 canonical PTY control-loop 결정으로 축소한다. search는 이 경계에서만
836
854
  * 부작용(context 기록)을 끝내고, child에는 context를 읽고 계속하라는 단일 input만 전달한다. */
837
- export function createMissionControlBrain(opts: MissionControlBrainOpts): RunSupervisor {
855
+ export type MissionControlBrain = RunSupervisor & {
856
+ /** Report whether the last returned input was accepted by the PTY; recovery stages and events commit only on acceptance. */
857
+ readonly onInputResult: (text: string, accepted: boolean) => void;
858
+ };
859
+
860
+ export function createMissionControlBrain(opts: MissionControlBrainOpts): MissionControlBrain {
838
861
  const history: string[] = [];
839
862
  const backendName = (opts.backend ?? codexBackend).name;
840
863
  // ★ P4 dedup(제한적 재시도·리뷰) — (layer:spec)별 시도횟수. 성공 시 영구 차단, 실패는 최대 2회까지
841
864
  // 허용(일시 네트워크/프로세스 오류는 재시도, 지속 실패는 루프 차단).
842
865
  const provisionAttempts = new Map<string, number>();
843
866
  const PROVISION_MAX_ATTEMPTS = 2;
844
- return createLlmControlBrain({
867
+ const recoverAfterMs = opts.recoverAfterMs ?? 45_000;
868
+ if (!Number.isFinite(recoverAfterMs) || recoverAfterMs <= 0) throw new Error('recoverAfterMs must be positive');
869
+ let lastScreen: string | undefined;
870
+ let repeatedQuestion = 0;
871
+ let lastQuestion: string | undefined;
872
+ let recoveryStage = 0;
873
+ let pendingReplayBlocked: string | undefined;
874
+ // The recovery input returned by the last decide(); committed (stage advance + event) only when the PTY accepts it.
875
+ let pendingRecovery: { blocked: string; action: string; text: string; replay?: boolean } | undefined;
876
+ let lastCommand = opts.initialCommand ?? opts.mission;
877
+ const llmBrain = createLlmControlBrain({
845
878
  goal: opts.mission,
846
879
  stream: opts.stream,
847
880
  maxTokens: 500,
@@ -855,7 +888,7 @@ export function createMissionControlBrain(opts: MissionControlBrainOpts): RunSup
855
888
  행동(action):
856
889
  - "wait": ${backendName} 가 아직 작업 중(도구 실행/생성)이면 대기.
857
890
  - "verify": ${backendName} 가 MISSION-COMPLETE/완료를 주장하면 증거 게이트(내가 실행)로 검증. 완료주장 시 이걸 우선.
858
- - "send": ${backendName} 가 멈추거나 계속 진행이 필요하면 짧고 명확한 지시(text).
891
+ - "send": ${backendName} 가 멈추거나 계속 진행이 필요하면 짧고 명확한 지시(text). 화면의 질문에 직접 답하는 경우에만 reason 을 Answering question: <화면의 질문 원문> 으로 기록하라. 다른 send 의 reason 은 종전처럼 행동 이유를 적어라.
859
892
  - "search": ${backendName} 가 정보/라이브러리/문법/외부자원에 막혔으면 omni-crawl 로 조사(query). ⭐외부 힌트 없이 스스로 판단.
860
893
  ${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/claude/elanous), mission(다음 지시), carry(diff/summary 선택). carry=summary 면 reason 에 화면에서 확인한 리뷰 지적을 구체적으로 요약하라(다음 backend 에 전달된다). claude 리뷰 뒤 지적은 codex 에 summary 로 되돌려라. elanous 는 증거 게이트와 PR.
861
894
  - "ask-human": 화면에 로그인 URL/장치 코드가 보이면 reason, url/code(보이는 것만). 토큰·자격파일을 열지 마라.` : ''}${opts.provision ? `
@@ -873,10 +906,19 @@ ${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/c
873
906
  history.push(`s${obs.step}:${decision.action}`);
874
907
  debug.log('agent-mission', 'brain', { step: obs.step, action: decision.action,
875
908
  ...(decision.action === 'ask-human' ? {} : { reason: decision.reason.slice(0, 120) }) });
909
+ // A '?' on screen alone does not establish that this send answered it. Only an
910
+ // explicit question citation in the brain's reason can attribute the reply.
911
+ const citedQuestion = /^Answering question:\s*(.+\?)\s*$/i.exec(decision.reason)?.[1]?.trim();
912
+ const question = citedQuestion && classifierFrameLines(obs.screen).find((line) => line === citedQuestion);
913
+ opts.onDecision?.(`step ${obs.step}: ${decision.action}${decision.action === 'ask-human' ? '' : ` — ${decision.reason || decision.text || decision.query || ''}`}`,
914
+ decision.action === 'send' && decision.text?.trim() && question ? { question, answer: decision.text } : undefined);
876
915
  if (decision.reason && decision.action !== 'ask-human') opts.onSummary?.(decision.reason.slice(0, 2000));
877
916
  if (decision.action === 'handoff' && decision.to && decision.mission) return { action: 'handoff', to: decision.to, mission: decision.mission, ...(decision.carry ? { carry: decision.carry } : {}) };
878
917
  if (decision.action === 'ask-human') return { action: 'ask-human', reason: decision.reason, ...(decision.url ? { url: decision.url } : {}), ...(decision.code ? { code: decision.code } : {}) };
879
- if (decision.action === 'send') return { action: 'input', text: `${decision.text || 'continue'}\r` };
918
+ if (decision.action === 'send') {
919
+ lastCommand = decision.text || 'continue';
920
+ return { action: 'input', text: `${lastCommand}\r` };
921
+ }
880
922
  if (decision.action === 'verify' || decision.action === 'done') return { action: 'done', reason: decision.reason || 'agent completed' };
881
923
  if (decision.action === 'search') {
882
924
  await opts.search(decision.query || opts.mission.slice(0, 120), obs.step);
@@ -911,6 +953,57 @@ ${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/c
911
953
  return { action: 'wait' };
912
954
  },
913
955
  });
956
+ return {
957
+ onInputResult: (text, accepted) => {
958
+ const recovery = pendingRecovery;
959
+ // Only the input this brain returned settles its recovery step (a trust answer in between does not).
960
+ if (!recovery || recovery.text !== text) return;
961
+ pendingRecovery = undefined;
962
+ if (!accepted) return;
963
+ if (recovery.replay) { pendingReplayBlocked = undefined; opts.onRecover?.(recovery.blocked, recovery.action); return; }
964
+ recoveryStage += 1;
965
+ if (recovery.action === 'Ctrl-C and replay previous command') pendingReplayBlocked = recovery.blocked;
966
+ else opts.onRecover?.(recovery.blocked, recovery.action);
967
+ },
968
+ decide: async (obs, signal) => {
969
+ pendingRecovery = undefined;
970
+ if (signal?.aborted) return { action: 'wait' };
971
+ const lines = classifierFrameLines(obs.screen);
972
+ // Only the active bottom line can be a repeated prompt; a question left in
973
+ // scrollback while new work appears is not a request for input.
974
+ const tail = lines.at(-1);
975
+ const question = tail && /\?(?:\s*\[[^\]\r\n]+\])?\s*$/.test(tail) ? tail : undefined;
976
+ const screenChanged = lastScreen !== undefined && obs.screen !== lastScreen;
977
+ if (screenChanged) recoveryStage = 0;
978
+ repeatedQuestion = question ? (!screenChanged && question === lastQuestion ? repeatedQuestion + 1 : 1) : 0;
979
+ lastQuestion = question;
980
+ lastScreen = obs.screen;
981
+ if (pendingReplayBlocked !== undefined) {
982
+ // Ctrl-C consumes its own step; replay on the next observation even when the
983
+ // interrupted child keeps redrawing a non-prompt screen. A rejected replay is retried.
984
+ const text = `${lastCommand}\r`;
985
+ pendingRecovery = { blocked: pendingReplayBlocked, action: 'Ctrl-C and replay previous command', text, replay: true };
986
+ return { action: 'input', text };
987
+ }
988
+ const blocked = repeatedQuestion >= 3 ? `same question repeated three times: ${question}`
989
+ : (obs.sameScreenMs ?? 0) >= recoverAfterMs ? `screen unchanged for ${obs.sameScreenMs}ms` : undefined;
990
+ if (blocked && opts.evidenceReady()) return { action: 'done', reason: 'Evidence ready on stalled screen' };
991
+ if (blocked && !signal?.aborted) {
992
+ const action = ['Enter', 'Esc', 'Ctrl-C and replay previous command', 'Human needed'] as const;
993
+ const next = action[Math.min(recoveryStage, 3)]!;
994
+ if (next !== 'Human needed') {
995
+ const text = next === 'Enter' ? '\r' : next === 'Esc' ? '\x1b' : '\x03';
996
+ pendingRecovery = { blocked, action: next, text };
997
+ return { action: 'input', text };
998
+ }
999
+ recoveryStage += 1;
1000
+ opts.onRecover?.(blocked, next);
1001
+ const summary = lines.slice(-3).join(' | ').slice(0, 240) || '(empty screen)';
1002
+ return { action: 'no-progress', terminal: true, reason: `사람 필요 · 마지막 화면 요약: ${summary}` };
1003
+ }
1004
+ return llmBrain.decide(obs, signal);
1005
+ },
1006
+ };
914
1007
  }
915
1008
 
916
1009
  /**
@@ -974,6 +1067,7 @@ export function makeMissionObserveStep(deps: {
974
1067
  bus: ChannelBus;
975
1068
  ident: { ptyId: string; instance: string; runId?: string };
976
1069
  now?: () => number;
1070
+ onPublishedFrame?: (obs: ControlObservation) => void;
977
1071
  }): (obs: ControlObservation, decision: ControlDecision) => Promise<void> {
978
1072
  const now = deps.now ?? ((): number => Date.now());
979
1073
  let lastFrameState: FrameState | null = null;
@@ -1008,6 +1102,7 @@ export function makeMissionObserveStep(deps: {
1008
1102
  ...(deps.ident.runId ? { runId: deps.ident.runId } : {}),
1009
1103
  ...(pngRef ? { pngRef } : {}),
1010
1104
  });
1105
+ deps.onPublishedFrame?.(obs);
1011
1106
  // capture 는 원 semantics 유지 — 예외 전파(증거/전사 계약 불변).
1012
1107
  await deps.capture(`s${obs.step}-${decision.action}`);
1013
1108
  };
@@ -1260,6 +1355,21 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
1260
1355
  } finally { signal?.removeEventListener('abort', stopWaiting); }
1261
1356
  }
1262
1357
  const startedAt = Date.now();
1358
+ const contextOwner = !deps.contextEventRun;
1359
+ const contextRunId = contextOwner ? ensureRunId() : undefined;
1360
+ let contextPrNumber: number | undefined;
1361
+ const emitContext = (kind: 'task-claimed' | 'task-done', detail: string): void => {
1362
+ if (!contextOwner) return;
1363
+ try {
1364
+ (deps.emitContextEvent ?? emitSessionEvent)({ kind, seat: 'TC', text: `Agent mission ${detail}: ${spec.mission.split(/\r?\n/, 1)[0]}`,
1365
+ ref: `runId=${contextRunId}${contextPrNumber === undefined ? '' : ` PR=#${contextPrNumber}`}` });
1366
+ } catch (error) {
1367
+ try { debug.log('agent-mission', 'context-event-failed', { kind, runId: contextRunId, error: String(error) }, { level: 'warn' }); } catch { /* fail-soft */ }
1368
+ }
1369
+ };
1370
+ emitContext('task-claimed', 'claimed');
1371
+ let result: AgentMissionResult | undefined;
1372
+ try {
1263
1373
  const initialFiles = workdir && spec.evidence.kind === 'doc' ? initialEvidenceFiles(workdir, spec.evidence) : undefined;
1264
1374
  let handle: PtyHandle | undefined;
1265
1375
  let childPid: number | undefined;
@@ -1293,10 +1403,12 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
1293
1403
  });
1294
1404
  signal?.addEventListener('abort', abort, { once: true });
1295
1405
  if (signal?.aborted) abort();
1296
- let result: AgentMissionResult;
1297
1406
  try {
1298
1407
  if (cancelled) await aborted;
1299
- const body = runAgentMissionBody(spec, { ...deps, onControlActive: (pending) => {
1408
+ const body = runAgentMissionBody(spec, { ...deps, contextEventRun: true, onMissionPrNumber: (number) => {
1409
+ contextPrNumber = number;
1410
+ try { deps.onMissionPrNumber?.(number); } catch { /* context propagation never changes a mission result */ }
1411
+ }, onControlActive: (pending) => {
1300
1412
  activeSettled = false;
1301
1413
  activeControl = pending.then(() => { activeSettled = true; }, () => { activeSettled = true; });
1302
1414
  }, onControlPending: (pending) => {
@@ -1364,10 +1476,12 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
1364
1476
  if (paths.length) {
1365
1477
  debug.log('agent-mission', 'outside-write', { workdir, pids: [], reason: paths.join(', ') });
1366
1478
  (deps.emitDecision ?? emitDecision)({ kind: 'ESCALATE', what: '작업 폴더 밖 쓰기', reason: paths.join(', '), purpose: '사람이 확인한다', target: 'human' });
1367
- return { ...result, ok: false, reason: 'outside-write', paths, committed: false };
1479
+ result = { ...result, ok: false, reason: 'outside-write', paths, committed: false };
1480
+ return result;
1368
1481
  }
1369
1482
  }
1370
1483
  return result;
1484
+ } finally { emitContext('task-done', result?.ok ? 'completed' : 'ended'); }
1371
1485
  }
1372
1486
 
1373
1487
  async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDeps, startedAt: number, initialFiles?: ReadonlyMap<string, string>): Promise<AgentMissionResult> {
@@ -1574,9 +1688,19 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1574
1688
  if (deps.isMissionAborted?.()) { offLive(); throw new Error('MISSION_ABORTED'); }
1575
1689
  try { h = spawnPty(ptyOpts); }
1576
1690
  catch (error) { offLive(); throw error; }
1577
- deps.onPtyStarted?.(h, () => { if (liveTimer) clearInterval(liveTimer); offLive(); });
1578
- if (deps.isMissionAborted?.()) return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
1579
- rounds: 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' };
1691
+ if (backend.name === 'codex') observeExternalEvent({ origin: 'codex-agent-mission', kind: 'started',
1692
+ summary: 'Codex agent mission started', source: `elanous://agent-mission/${encodeURIComponent(runId)}/${encodeURIComponent(h.id)}` });
1693
+ let contextFinished = false;
1694
+ const finishContext = (ok: boolean): void => {
1695
+ if (contextFinished || backend.name !== 'codex') return;
1696
+ contextFinished = true;
1697
+ observeExternalEvent({ origin: 'codex-agent-mission', kind: 'finished',
1698
+ summary: `Codex agent mission ${ok ? 'completed' : 'failed'}`,
1699
+ source: `elanous://agent-mission/${encodeURIComponent(runId)}/${encodeURIComponent(h.id)}` });
1700
+ };
1701
+ deps.onPtyStarted?.(h, () => { if (liveTimer) clearInterval(liveTimer); offLive(); finishContext(false); });
1702
+ if (deps.isMissionAborted?.()) { finishContext(false); return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
1703
+ rounds: 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' }; }
1580
1704
  const executorRef = buildExecutorPtyRef({
1581
1705
  ptyId: h.id,
1582
1706
  backend: backend.name,
@@ -1589,6 +1713,12 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1589
1713
  process.stderr.write(`[agent-mission] pty=${h.id} watch=${webAddress.webUrl ?? `(web unavailable: ${webAddress.pwaUnavailableReason ?? 'not-resolved'})`}\n`);
1590
1714
  debug.log('agent-mission', 'pty-link', { id: h.id, webUrl: webAddress.webUrl, webUrlSource: webAddress.webUrlSource });
1591
1715
 
1716
+ const decisionIdentity = { missionId: runId, sessionId: runId, terminalId: h.id, agent: backend.name };
1717
+ const decisionEvent = (event: Omit<DecisionInput, keyof typeof decisionIdentity>): void => {
1718
+ try { (deps.emitPtyDecision ?? emitPtyDecision)({ ...decisionIdentity, ...event } as DecisionInput); }
1719
+ catch { /* Observation must not change mission control or handoff. */ }
1720
+ };
1721
+
1592
1722
  // ⭐P2 arbiter: the child is accessMode='auto' (brain-owned), so the driver —
1593
1723
  // the autonomous brain — must write as 'agent' or the arbiter denies it. This
1594
1724
  // makes "protected autonomy" real: a human attaching mid-mission (read) can't
@@ -1615,6 +1745,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1615
1745
  : 'AGENT_YIELDED: PTY 제어가 사람에게 이양됨(takeover) — 자율 미션 중단');
1616
1746
  }
1617
1747
  h['write'](s, 'agent');
1748
+ decisionEvent({ step: 'input', text: s === '\r' ? 'Sent Enter' : `Sent ${s.startsWith('\x1b') ? 'key' : 'text'}: ${s.startsWith('\x1b') ? 'navigation' : s}` });
1618
1749
  };
1619
1750
 
1620
1751
  let seq = 0;
@@ -1638,7 +1769,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1638
1769
  if (liveChunks % 20 === 0) debug.log('agent-mission', 'live', { chunks: liveChunks, tail: s.slice(-80).replace(/\s+/g, ' ') });
1639
1770
  }).catch(() => { /* noop */ });
1640
1771
  }, 800);
1641
- const stopLive = (): void => { if (liveTimer) clearInterval(liveTimer); offLive(); };
1772
+ const stopLive = (ok = false): void => { if (liveTimer) clearInterval(liveTimer); offLive(); if (ok) finishContext(true); };
1773
+ try {
1642
1774
 
1643
1775
  // ready + trust — backend 별 신뢰/권한 프롬프트 처리(codex=1, 이후 백엔드는 자체 handler).
1644
1776
  await (deps.awaitMission ? deps.awaitMission(waitForQuiet(h, 1500, 20000)) : waitForQuiet(h, 1500, 20000));
@@ -1648,7 +1780,11 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1648
1780
  // A trust menu can need more than one key (claude: ↓ to «Yes», then Enter) — answer until it is gone, at most 3 times.
1649
1781
  // 🩸 09-29: one pass sent only ↓, the mission text went into the menu and its Enter confirmed «Yes» instead of
1650
1782
  // submitting the mission, which then sat unsent in the input box.
1651
- for (let pass = 0; pass < 3 && backend.handleTrust?.(screen, (s) => drive(s)); pass++) {
1783
+ for (let pass = 0; pass < 3 && backend.handleTrust?.(screen, (s) => {
1784
+ drive(s);
1785
+ // Moving the selection is only input; the trust question is answered when the choice is confirmed.
1786
+ if (s === '\r') decisionEvent({ step: 'answer', text: 'Answered folder trust prompt', detail: { question: 'Trust this folder?', answer: 'Confirm selected choice' } });
1787
+ }); pass++) {
1652
1788
  debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled', pass });
1653
1789
  const trusted = (async () => { await waitForQuiet(h, 1500, 15000); return capture('trusted'); })();
1654
1790
  screen = await (deps.awaitMission ? deps.awaitMission(trusted) : trusted);
@@ -1744,6 +1880,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1744
1880
  if (deps.isMissionAborted?.()) throw new Error('MISSION_ABORTED');
1745
1881
  // 미션 전송 — 인핸싱/기억으로 가공됐으면(멀티라인) 파일로 떨궈 read 지시(TUI 멀티라인 위험·verbatim 보존).
1746
1882
  // 원문 그대로면(단문) 타이핑.
1883
+ let submittedCommand = spec.mission;
1884
+ const submittedInputs: string[] = [];
1747
1885
  if (missionText !== spec.mission) {
1748
1886
  const pf = join(wt.path, '.mission-prompt.md');
1749
1887
  try { writeFileSync(pf, missionText); } catch { /* noop */ }
@@ -1751,9 +1889,12 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1751
1889
  ? '.mission-prompt.md 파일을 읽고 그 안의 미션을 완수하라. [elanous 인핸싱]의 커버리지 체크리스트 모든 항목을 산출물에 빠짐없이 반영하고(요약·일반화 금지), 완료하면 MISSION-COMPLETE 라고 답하라.'
1752
1890
  : '.mission-prompt.md 파일을 읽고 그 안의 미션을 완수하라(원문 그대로·[elanous 기억]은 참조 컨텍스트). 완료하면 MISSION-COMPLETE 라고 답하라.';
1753
1891
  debug.log('agent-mission', 'mission-send', { via: 'file', file: '.mission-prompt.md', chars: missionText.length, enhanced: enhanceActive });
1892
+ submittedCommand = note;
1893
+ submittedInputs.push(note);
1754
1894
  drive(note); await sleep(800); drive('\r');
1755
1895
  } else {
1756
1896
  debug.log('agent-mission', 'mission-send', { via: 'type', chars: spec.mission.length });
1897
+ submittedInputs.push(spec.mission);
1757
1898
  drive(spec.mission); await sleep(800); drive('\r');
1758
1899
  }
1759
1900
 
@@ -1761,13 +1902,21 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1761
1902
  let controllerSummary = deps.previousSummary ?? '';
1762
1903
  let reviewSummary = '';
1763
1904
  let coverageRetries = enhanceActive && checklist.length ? 2 : 0;
1905
+ let pendingAnswer: { text: string; question: string; answer: string } | undefined;
1764
1906
  const search = createMissionSearch({ worktree: wt.path, omniPath });
1765
1907
  const brain = createMissionControlBrain({
1766
1908
  mission: spec.mission,
1767
1909
  backend,
1768
1910
  stream: deps.controlStream,
1769
1911
  handoffEnabled: true,
1912
+ recoverAfterMs: spec.recoverAfterMs,
1913
+ initialCommand: submittedCommand,
1914
+ onRecover: (blocked, action) => { decisionEvent({ step: 'recover', text: action, detail: { blocked, action } }); },
1770
1915
  onSummary: (summary) => { controllerSummary = summary; },
1916
+ onDecision: (text, reply) => {
1917
+ pendingAnswer = reply ? { text: `${reply.answer || 'continue'}\r`, ...reply } : undefined;
1918
+ decisionEvent({ step: 'judge', text });
1919
+ },
1771
1920
  evidenceReady: () => spec.chain && spec.chain.length > 1 ? true : verifyEvidence(wt.path, spec.evidence).ok,
1772
1921
  search: async (query, step) => {
1773
1922
  usedOmni = true;
@@ -1784,9 +1933,14 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1784
1933
  // before asking the LLM — otherwise the mission text is typed into the prompt and the run stalls.
1785
1934
  const trustAwareBrain: RunSupervisor = {
1786
1935
  decide: (obs, signal) => {
1936
+ decisionEvent({ step: 'read', text: `step ${obs.step} (${obs.state}): ${classifierFrameLines(obs.screen).at(-1) ?? 'empty screen'}` });
1937
+ pendingAnswer = undefined;
1787
1938
  let answer: string | undefined;
1788
1939
  if (backend.handleTrust?.(obs.screen, (bytes) => { answer = bytes; }) && answer !== undefined) {
1789
1940
  debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled-in-loop', step: obs.step });
1941
+ decisionEvent({ step: 'judge', text: `step ${obs.step}: trust prompt` });
1942
+ // Only the confirming Enter answers the trust question; a navigation key stays an input event.
1943
+ if (answer === '\r') pendingAnswer = { text: answer, question: 'Trust this folder?', answer: 'Confirm selected choice' };
1790
1944
  emitDecision({ kind: 'ROUTE', what: `${backend.name} 폴더 신뢰 화면 → 계속`, reason: '시작 뒤 늦게 뜬 신뢰 확인', purpose: '미션을 이어 간다', target: backend.name, phase: 'implement' });
1791
1945
  return { action: 'input', text: answer };
1792
1946
  }
@@ -1845,7 +1999,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1845
1999
  handoffPrSkipped = true;
1846
2000
  debug.log('agent-mission', 'handoff-pr-skipped', { reason: 'origin-not-github' });
1847
2001
  } else {
1848
- (deps.dispatchOpenPullRequest ?? dispatchOpenPullRequest)({ title: `agent-mission: ${spec.branch}`, body: deps.originalMission ?? spec.mission, head: spec.branch, base: spec.base ?? 'main' }, { cwd: worktree });
2002
+ const opened = (deps.dispatchOpenPullRequest ?? dispatchOpenPullRequest)({ title: `agent-mission: ${spec.branch}`, body: deps.originalMission ?? spec.mission, head: spec.branch, base: spec.base ?? 'main' }, { cwd: worktree });
2003
+ if (opened.number !== null) deps.onMissionPrNumber?.(opened.number);
1849
2004
  }
1850
2005
  gatedHandoff = true;
1851
2006
  },
@@ -1879,15 +2034,37 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1879
2034
  (d) => debug.log('agent-mission.observe', 'progress', { surfaceId: d.surfaceId, state: d.state, summary: d.summary, unknownInput: d.unknownInput, frame: d.frameCount, runId: d.runId }),
1880
2035
  () => {
1881
2036
  const handleDeps = controlDepsForHandle(h);
2037
+ const inject = backend.name === 'claude' ? submitSeparately(handleDeps.inject) : handleDeps.inject;
1882
2038
  const pending = (deps.runControlLoop ?? runPtyControlLoop)(trustAwareBrain, {
1883
2039
  ...handleDeps,
1884
- ...(backend.name === 'claude' ? { inject: submitSeparately(handleDeps.inject) } : {}),
2040
+ inject: (text) => {
2041
+ const reply = pendingAnswer?.text === text ? pendingAnswer : undefined;
2042
+ pendingAnswer = undefined;
2043
+ const accepted = inject(text);
2044
+ if (accepted) {
2045
+ submittedInputs.push(text);
2046
+ decisionEvent({ step: 'input', text: `Sent ${text.startsWith('\x1b') ? 'key' : 'text'}: ${text.startsWith('\x1b') ? 'navigation' : text}` });
2047
+ }
2048
+ // Recovery stages and recover events are committed only after the PTY accepted the input.
2049
+ brain.onInputResult(text, accepted);
2050
+ if (accepted) {
2051
+ if (reply) decisionEvent({ step: 'answer', text: 'Answered agent question', detail: { question: reply.question, answer: reply.answer } });
2052
+ }
2053
+ return accepted;
2054
+ },
2055
+ injectKey: handleDeps.injectKey && ((name, repeat) => {
2056
+ const accepted = handleDeps.injectKey!(name, repeat);
2057
+ if (accepted) decisionEvent({ step: 'input', text: `Pressed ${name}${repeat ? ` ×${repeat}` : ''}`, detail: { keys: name } });
2058
+ return accepted;
2059
+ }),
1885
2060
  ...(deps.isMissionAborted ? {
1886
2061
  controlStance: () => deps.isMissionAborted!() ? 'unknown' as const : probeControlStance(h, 'agent', (e) =>
1887
2062
  debug.log('agent-mission', 'hascontrol-error', { id: h.id, error: (e as Error)?.message ?? String(e) })),
1888
2063
  } : {}),
1889
2064
  awaitOwnership: { maxWaitMs: AGENT_MISSION_TAKEOVER_WAIT_MS },
1890
2065
  settle: async () => {
2066
+ // A frozen screen goes quiet after 6 s, so stall recovery is still observed; work that keeps
2067
+ // drawing output keeps the original 360 s settle and round budget.
1891
2068
  const quiet = waitForQuiet(h, 6000, 360000);
1892
2069
  await (deps.awaitMission ? deps.awaitMission(quiet) : quiet);
1893
2070
  },
@@ -1903,7 +2080,11 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1903
2080
  }
1904
2081
  }
1905
2082
  },
1906
- verifyDone: spec.chain && spec.chain.length > 1 ? async () => ({ ok: true as const }) : verifyDone,
2083
+ verifyDone: spec.chain && spec.chain.length > 1 ? async () => ({ ok: true as const }) : async (obs) => {
2084
+ const verdict = await verifyDone(obs);
2085
+ if (!verdict.ok) decisionEvent({ step: 'recover', text: 'Evidence check requires another attempt', detail: { blocked: verdict.retry, action: 'Retry after fixing evidence' } });
2086
+ return verdict;
2087
+ },
1907
2088
  handoff: async (decision, obs) => {
1908
2089
  try {
1909
2090
  if (spec.chain && decision.to !== spec.chain[1]) throw new Error(`chain order violation: expected ${spec.chain[1] ?? 'completion'}, got ${decision.to}`);
@@ -1916,12 +2097,13 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1916
2097
  askHuman: async (decision) => {
1917
2098
  try {
1918
2099
  await waitForHumanLogin(decision, handoffOps);
2100
+ decisionEvent({ step: 'answer', text: 'Human login question resolved', detail: { question: decision.reason, answer: 'Login completed' } });
1919
2101
  } catch (error) {
1920
2102
  transitionFailure = error instanceof Error ? error.message : String(error);
1921
2103
  throw error;
1922
2104
  }
1923
2105
  },
1924
- }, { maxSteps: maxRounds });
2106
+ }, { maxSteps: maxRounds, stuckLimit: maxRounds + 1 });
1925
2107
  deps.onControlActive?.(pending);
1926
2108
  return pending;
1927
2109
  },
@@ -1954,7 +2136,9 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1954
2136
  }
1955
2137
  // A gate/PR handoff only counts as success when the control loop itself did not end in error.
1956
2138
  if (gatedHandoff && control.termination.kind !== 'error') {
1957
- stopLive();
2139
+ // The gate hands off a branch, not a file: record what is known instead of mislabeling the worktree directory.
2140
+ decisionEvent({ step: 'done', text: 'Mission handoff gate completed', detail: { result: { kind: 'text', ref: `branch ${wt.branch}` } } });
2141
+ stopLive(true);
1958
2142
  try { h.kill(); } catch { /* noop */ }
1959
2143
  return { ok: true, worktree: wt.path, branch: wt.branch, rounds: control.steps, evidencePath: wt.path, committed: true, usedOmniCrawl: usedOmni,
1960
2144
  ...(handoffPrSkipped ? { pr: 'skipped' as const, reason: 'origin-not-github' as const } : {}),
@@ -1985,6 +2169,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1985
2169
  maxFallbackDescents: runtimeFallback.maxDescents,
1986
2170
  });
1987
2171
  if (nextBackend && !deps.isMissionAborted?.()) {
2172
+ decisionEvent({ step: 'recover', text: `Switching ${backend.name} to ${nextBackend.name}`, detail: { blocked: control.termination.message, action: `Retry with ${nextBackend.name}` } });
1988
2173
  const nextStep: FallbackStep = nextBackend.name === 'grok' ? 'grok' : 'codex-rotate';
1989
2174
  stopLive();
1990
2175
  if (h.pid) await (deps.terminateProcessTree ?? terminateMissionProcessTree)(h.pid);
@@ -2011,24 +2196,31 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
2011
2196
  if (deps.isMissionAborted?.()) return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
2012
2197
  rounds: round, evidencePath: null, committed: false, usedOmniCrawl: usedOmni, detail: 'aborted' };
2013
2198
  const finalEv = verifyEvidence(wt.path, spec.evidence);
2014
- const evidencePath = finalEv.ok ? finalEv.path : null;
2199
+ const finalScreen = await h.renderScreen();
2200
+ const driveVerdict = verdictForFinalPtyScreen({ screen: finalScreen, inputHistory: submittedInputs, exitCode: h.exitCode ?? null });
2201
+ debug.log('agent-mission', 'drive-verdict', { kind: driveVerdict.kind, reason: driveVerdict.reason.slice(0, 200) });
2202
+ const recoverExhausted = control.termination.kind === 'stuck' && control.termination.reason.startsWith('사람 필요');
2203
+ const accepted = finalEv.ok && !recoverExhausted && driveVerdict.kind !== 'done-but-failed';
2204
+ const evidencePath = accepted ? finalEv.path : null;
2015
2205
  let committed = false;
2016
- if (!deps.isMissionAborted?.() && !spec.workdir && finalEv.ok && (spec.commit ?? true)) {
2206
+ if (!deps.isMissionAborted?.() && !spec.workdir && accepted && (spec.commit ?? true)) {
2017
2207
  const c = (deps.commitWorktree ?? commitWorktree)(wt.path, `chore(agent-mission): ${spec.branch} — ${backend.name}-in-elanous PTY RFC 산출`);
2018
2208
  committed = c.ok;
2019
2209
  debug.log('agent-mission', 'commit', { ok: c.ok, out: c.out.slice(0, 120) });
2020
2210
  }
2021
- debug.log('agent-mission', 'result', { ok: finalEv.ok, rounds: round, evidencePath, committed, usedOmni });
2022
- stopLive();
2211
+ debug.log('agent-mission', 'result', { ok: accepted, rounds: round, evidencePath, committed, usedOmni });
2212
+ decisionEvent({ step: 'done', text: accepted ? 'Mission evidence accepted' : 'Mission ended without sufficient evidence', detail: { result: { kind: evidencePath ? 'file' : 'text', ref: evidencePath ?? (control.termination.kind === 'error' ? control.termination.message : recoverExhausted ? control.termination.reason : 'evidence unavailable') } } });
2213
+ stopLive(accepted);
2023
2214
  if (h.pid) await terminateMissionProcessTree(h.pid);
2024
2215
  try { h.kill(); } catch { /* noop */ }
2025
2216
 
2026
2217
  return {
2027
- ok: finalEv.ok, worktree: wt.path, branch: wt.branch, rounds: round,
2218
+ ok: accepted, worktree: wt.path, branch: wt.branch, rounds: round,
2028
2219
  evidencePath, committed, usedOmniCrawl: usedOmni,
2029
2220
  ptyId: h.id, webUrl: webAddress.webUrl,
2030
- detail: done ? '완료(증거 충족)' : (finalEv.ok ? '증거 충족(루프 종료)' : '미완(증거 부족)'),
2221
+ detail: recoverExhausted ? control.termination.reason : driveVerdict.kind === 'done-but-failed' ? `미완(DRIVE-OK: ${driveVerdict.reason})` : done ? '완료(증거 충족)' : (finalEv.ok ? '증거 충족(루프 종료)' : '미완(증거 부족)'),
2031
2222
  };
2223
+ } finally { stopLive(); finishContext(false); }
2032
2224
  }
2033
2225
 
2034
2226
  /** @deprecated codex 특정 이름 — runAgentMission 을 쓰라(codex 는 기본 backend). */
@@ -0,0 +1,71 @@
1
+ import { debug } from '../debug/log.js';
2
+
3
+ type Identity = {
4
+ ts: string;
5
+ missionId: string;
6
+ seq: number;
7
+ sessionId: string;
8
+ terminalId: string;
9
+ agent: string;
10
+ text: string;
11
+ };
12
+ type Detail = { keys?: string; row?: number };
13
+
14
+ export type PtyDecision = Identity & (
15
+ | { step: 'read' | 'judge' | 'input'; detail?: Detail }
16
+ | { step: 'answer'; detail: Detail & { question: string; answer: string } }
17
+ | { step: 'recover'; detail: Detail & { blocked: string; action: string } }
18
+ | { step: 'done'; detail: Detail & { result: { kind: 'pr' | 'file' | 'text'; ref: string } } }
19
+ );
20
+
21
+ export type DecisionInput = Omit<Identity, 'ts' | 'seq'> & (
22
+ | { step: 'read' | 'judge' | 'input'; detail?: Detail }
23
+ | { step: 'answer'; detail: Detail & { question: string; answer: string } }
24
+ | { step: 'recover'; detail: Detail & { blocked: string; action: string } }
25
+ | { step: 'done'; detail: Detail & { result: { kind: 'pr' | 'file' | 'text'; ref: string } } }
26
+ );
27
+
28
+ const missionStreams = new Map<string, { alias: string; seq: number }>();
29
+ export const PTY_DECISION_TEXT_MAX = 240;
30
+
31
+ function safe(value: string): string {
32
+ const masked = value
33
+ .replace(/\bBearer\s+(?:"[^"]*"|'[^']*'|[^\s"'<>]+)/gi, 'Bearer [redacted]')
34
+ .replace(/\b([a-z0-9_]*(?:token|key(?:[_-]?id)?|secret|password|authorization)\s*[:=]\s*)(?:"[^"]*"|'[^']*'|[^\s"'<>]+)/gi, '$1[redacted]')
35
+ .replace(/\b(?:sk-[a-z0-9_-]+|gh[pousr]_[a-z0-9_]+|github_pat_[a-z0-9_]+|AIza[a-z0-9_-]+|xox[baprs]-[a-z0-9-]+)\b/gi, '[redacted]')
36
+ .replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, '[redacted]')
37
+ .replace(/[\x00-\x1f\x7f-\x9f]/g, ' ')
38
+ .trim();
39
+ const clipped = masked.slice(0, PTY_DECISION_TEXT_MAX);
40
+ return clipped.replace(/[\uD800-\uDBFF]$/, '') || '[redacted]';
41
+ }
42
+
43
+ /** The only emission point for the inside-PTY decision stream. Never log unsanitized input. */
44
+ export function emitPtyDecision(input: DecisionInput, log: typeof debug.log = (category, event, data) => debug.log(category, event, data)): PtyDecision {
45
+ let stream = missionStreams.get(input.missionId);
46
+ if (!stream) {
47
+ stream = { alias: `mission-${missionStreams.size + 1}`, seq: -1 };
48
+ missionStreams.set(input.missionId, stream);
49
+ }
50
+ stream.seq += 1;
51
+ const base = {
52
+ ts: new Date().toISOString(),
53
+ missionId: stream.alias,
54
+ seq: stream.seq,
55
+ sessionId: safe(input.sessionId),
56
+ terminalId: safe(input.terminalId),
57
+ agent: safe(input.agent),
58
+ text: safe(input.text),
59
+ };
60
+ const common = input.detail ? {
61
+ ...(input.detail.keys !== undefined ? { keys: safe(input.detail.keys) } : {}),
62
+ ...(input.detail.row !== undefined ? { row: input.detail.row } : {}),
63
+ } : {};
64
+ let decision: PtyDecision;
65
+ if (input.step === 'answer') decision = { ...base, step: input.step, detail: { ...common, question: safe(input.detail.question), answer: safe(input.detail.answer) } };
66
+ else if (input.step === 'recover') decision = { ...base, step: input.step, detail: { ...common, blocked: safe(input.detail.blocked), action: safe(input.detail.action) } };
67
+ else if (input.step === 'done') decision = { ...base, step: input.step, detail: { ...common, result: { kind: input.detail.result.kind, ref: safe(input.detail.result.ref) } } };
68
+ else decision = { ...base, step: input.step, ...(input.detail ? { detail: common } : {}) };
69
+ log('pty.decision', decision.step, decision);
70
+ return decision;
71
+ }