elanous 0.2.10 → 0.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (584) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/Y4zKzL62sakG5momz3SoQ/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1394-556de6d71bbdb0fb.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
  7. package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/2310-7a59f043f6db207e.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/2548-6e316138d347cefe.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/3869-a39d1d9921e10d43.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
  19. package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
  20. package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
  25. package/apps/pwa/out/_next/static/chunks/507-5acd98bd6dab2d8a.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/5445-745eb795c5963d79.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
  31. package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/8605-ea5bee9dfae512c7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1dcdc58fc2de2454.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-6a061bd97f0b9398.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/board/page-cb95a7432c9ee744.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-b12b6d2f8d2d1aea.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/app/bots/page-b9efe868bfd36255.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/chat/page-7c97dcdfe2e37a60.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/consult/page-8fd36984f549270a.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/control/page-5721537ca8a3598c.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/design-check/page-b654240a572e4c48.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/editor/page-b9750abc897508c3.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/exec/page-4cd1de371f8ad048.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/field/page-d99f89657828421c.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/inside/page-50cb2a0eb15e6c83.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/intake/page-c8b1ccda6ba7ae98.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/layout-d6b1d156fb95e74b.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/live/page-2a9932ddb62d76bd.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/market/page-9688f5b4f1ff950f.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6b15dd6456c5df09.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/morning/page-35414e0a007b4082.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/not-found-e7a529e0507ac86c.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/observatory/page-e001823c35c9dd67.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-371423d1a573d64b.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4b764b125339ac17.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cdf8e4b01067bcf1.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a24072b35470157.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/page-94c82eb0ae5abb32.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/reflection/page-0be8d4b2ced75ba0.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d37cb0d52f9b6bd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/sessions/page-686da0df9bf23e5c.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4dc614f3ce043e63.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/settings/page-53f80edc6b8dc07c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-d02c782fc792e2af.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/app/setup/page-239c17b911b84e72.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/share/page-dc6a79fb003f746c.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/showroom/page-0fffb84cafdc9da6.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/app/tasks/page-1218753c82d585f6.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/app/term/page-4b5935e67531efb5.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/app/today/page-3285bc87caf1eaa5.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/app/trace/page-ad553b0e06505ecd.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/app/vault/page-fca096e3e860306f.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ebfa78f0d9885c3.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/app/workflows/page-3dc5f21f7e39622d.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/app/workspace/page-c6da2b468454532d.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-93bc70e36f595414.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → f48170cc-d05d28bf87a43bf4.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +1 -0
  105. package/apps/pwa/out/_next/static/css/543f56bcb1f79fca.css +1 -0
  106. package/apps/pwa/out/approvals/index.html +1 -1
  107. package/apps/pwa/out/approvals/index.txt +23 -23
  108. package/apps/pwa/out/autopilot/index.html +1 -1
  109. package/apps/pwa/out/autopilot/index.txt +23 -23
  110. package/apps/pwa/out/board/index.html +1 -1
  111. package/apps/pwa/out/board/index.txt +23 -23
  112. package/apps/pwa/out/botlab/index.html +1 -1
  113. package/apps/pwa/out/botlab/index.txt +22 -22
  114. package/apps/pwa/out/bots/index.html +1 -1
  115. package/apps/pwa/out/bots/index.txt +22 -22
  116. package/apps/pwa/out/chat/index.html +1 -1
  117. package/apps/pwa/out/chat/index.txt +22 -22
  118. package/apps/pwa/out/consult/index.html +1 -1
  119. package/apps/pwa/out/consult/index.txt +23 -23
  120. package/apps/pwa/out/control/index.html +1 -1
  121. package/apps/pwa/out/control/index.txt +23 -23
  122. package/apps/pwa/out/design-check/index.html +1 -1
  123. package/apps/pwa/out/design-check/index.txt +23 -23
  124. package/apps/pwa/out/editor/index.html +1 -1
  125. package/apps/pwa/out/editor/index.txt +23 -23
  126. package/apps/pwa/out/exec/index.html +1 -1
  127. package/apps/pwa/out/exec/index.txt +23 -23
  128. package/apps/pwa/out/field/index.html +1 -1
  129. package/apps/pwa/out/field/index.txt +23 -23
  130. package/apps/pwa/out/healthz +1 -1
  131. package/apps/pwa/out/index.html +1 -1
  132. package/apps/pwa/out/index.txt +22 -22
  133. package/apps/pwa/out/inside/index.html +1 -0
  134. package/apps/pwa/out/inside/index.txt +31 -0
  135. package/apps/pwa/out/intake/index.html +1 -1
  136. package/apps/pwa/out/intake/index.txt +23 -23
  137. package/apps/pwa/out/live/index.html +1 -1
  138. package/apps/pwa/out/live/index.txt +23 -23
  139. package/apps/pwa/out/market/index.html +1 -1
  140. package/apps/pwa/out/market/index.txt +22 -22
  141. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  142. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  143. package/apps/pwa/out/morning/index.html +1 -1
  144. package/apps/pwa/out/morning/index.txt +23 -23
  145. package/apps/pwa/out/observatory/index.html +1 -1
  146. package/apps/pwa/out/observatory/index.txt +23 -23
  147. package/apps/pwa/out/ops/checklist/index.html +1 -1
  148. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  149. package/apps/pwa/out/ops/release/index.html +1 -1
  150. package/apps/pwa/out/ops/release/index.txt +22 -22
  151. package/apps/pwa/out/ops/seats/index.html +1 -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/drafts/draft-cleanup.yaml +19 -0
  192. package/graphs/drafts/recipes.yaml +23 -0
  193. package/graphs/intake/intake-daily.yaml +2 -1
  194. package/graphs/ops/recipes.yaml +3 -0
  195. package/graphs/ops/secret-exposure.yaml +24 -0
  196. package/graphs/release/recipes.yaml +3 -0
  197. package/graphs/release/release-loop.yaml +4 -1
  198. package/graphs/video/explainer-line.yaml +2 -2
  199. package/package.json +2 -1
  200. package/plugins/elanous-hwp/README.md +25 -0
  201. package/plugins/elanous-hwp/cli.ts +22 -0
  202. package/plugins/elanous-hwp/converter.ts +237 -0
  203. package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
  204. package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
  205. package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
  206. package/plugins/elanous-hwp/plugin.json +16 -0
  207. package/plugins/elanous-hwp/plugin.ts +40 -0
  208. package/scripts/ci-public-export-leak-gate.ts +75 -14
  209. package/scripts/ci-public-leak-gate.ts +44 -9
  210. package/scripts/context-hooks/claude-stop.sh +4 -0
  211. package/scripts/context-hooks/emit.ts +24 -0
  212. package/scripts/context-hooks/post-tool-use.sh +4 -0
  213. package/scripts/coord-channel-watch.sh +12 -0
  214. package/scripts/coord-requests-bridge.ts +143 -0
  215. package/scripts/field-feed/lib.ts +4 -0
  216. package/scripts/fleet/node-setup.sh +20 -3
  217. package/scripts/homebrew-formula-bump.ts +69 -0
  218. package/scripts/marketing/measure-site-numbers.ts +169 -0
  219. package/scripts/measure-gate-shards.ts +309 -0
  220. package/scripts/mission-request-judge.ts +31 -1
  221. package/scripts/morning-report.ts +2 -2
  222. package/scripts/opportunity-scan.ts +1 -1
  223. package/scripts/release-loop/auto-approve-node.ts +21 -4
  224. package/scripts/release-loop/cut-branch.ts +84 -0
  225. package/scripts/release-loop/gate-node.ts +14 -13
  226. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  227. package/scripts/release-loop/node-verdict.ts +3 -3
  228. package/scripts/release-loop/tui-node-checks.ts +42 -0
  229. package/scripts/release-loop/tui-sim-node.ts +32 -8
  230. package/scripts/release-loop/unattended-release.ts +5 -3
  231. package/scripts/release-loop/version-node.ts +61 -10
  232. package/scripts/signal-digest-cycle.ts +2 -7
  233. package/scripts/signal-digest-photo.ts +11 -0
  234. package/scripts/tech1-public-measure.ts +94 -0
  235. package/scripts/test-diet/node.ts +1 -1
  236. package/scripts/tui-regress.ts +2 -2
  237. package/scripts/ux/demo-rehearsal.ts +243 -0
  238. package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
  239. package/skills/diagram-master/SKILL.md +366 -0
  240. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  241. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  242. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  243. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  244. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  245. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  246. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  247. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  248. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  249. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  250. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  251. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  252. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  253. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  254. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  255. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  256. package/skills/diagram-master/references/examples/README.md +69 -0
  257. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  258. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  259. package/skills/diagram-master/references/pyproject.toml +16 -0
  260. package/skills/diagram-master/references/quality-checklist.md +33 -0
  261. package/skills/diagram-master/references/routing-guide.md +164 -0
  262. package/skills/diagram-master/references/uv.lock +1356 -0
  263. package/skills/google-workspace/SKILL.md +33 -0
  264. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  265. package/skills/grill-me/SKILL.md +1 -1
  266. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  267. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  268. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  269. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  270. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  271. package/skills/omni-crawl/SKILL.md +21 -11
  272. package/skills/omni-crawl/scripts/main.ts +6 -6
  273. package/skills/omni-crawl/src/router.ts +3 -3
  274. package/skills/omni-digest/SKILL.md +17 -9
  275. package/skills/omni-digest/digest.md +2 -2
  276. package/skills/omni-digest/src/fetch.ts +30 -3
  277. package/skills/pitch-deck/SKILL.md +2 -2
  278. package/skills/pitch-deck/template.html +2 -2
  279. package/skills/youtube-master/SKILL.md +163 -0
  280. package/skills/youtube-master/package-lock.json +558 -0
  281. package/skills/youtube-master/package.json +13 -0
  282. package/skills/youtube-master/references/study-note-template.md +124 -0
  283. package/skills/youtube-master/scripts/main.ts +435 -0
  284. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  285. package/skills/youtube-master/src/audio.ts +63 -0
  286. package/skills/youtube-master/src/domain-staging.ts +50 -0
  287. package/skills/youtube-master/src/env.ts +36 -0
  288. package/skills/youtube-master/src/obsidian.ts +155 -0
  289. package/skills/youtube-master/src/router.ts +110 -0
  290. package/skills/youtube-master/src/stt.ts +199 -0
  291. package/skills/youtube-master/src/study-note.ts +175 -0
  292. package/skills/youtube-master/src/summarize.ts +358 -0
  293. package/skills/youtube-master/src/transcript.ts +76 -0
  294. package/skills/youtube-master/src/types.ts +91 -0
  295. package/skills/youtube-master/src/util.ts +93 -0
  296. package/skills/youtube-master/src/youtube.ts +70 -0
  297. package/skills/youtube-master/tsconfig.json +13 -0
  298. package/src/acp/server.ts +5 -2
  299. package/src/agent-mission/driver.ts +80 -10
  300. package/src/agent-mission/pty-decision.ts +71 -0
  301. package/src/agent-mission/review-loop.ts +30 -0
  302. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  303. package/src/autopilot/tool-registry.ts +2 -0
  304. package/src/boot/daemon-prompt-turn.ts +5 -0
  305. package/src/boot/daemon-runtime.ts +9 -3
  306. package/src/boot/daemon-tools/web-search.ts +3 -0
  307. package/src/card-followup/core.ts +109 -0
  308. package/src/chat/index.ts +1 -0
  309. package/src/cli/drive-input-jail.ts +101 -0
  310. package/src/cli/hooks-cli.ts +17 -3
  311. package/src/cli/make-cli.ts +43 -0
  312. package/src/cli/persona-cli.ts +90 -4
  313. package/src/cli/plugin-cli.ts +31 -22
  314. package/src/cli/pod-cli.ts +19 -9
  315. package/src/cli/pr-cli.ts +51 -15
  316. package/src/cli/pty-drive-cli.ts +41 -7
  317. package/src/cli/pty-drive-verdict.ts +40 -0
  318. package/src/cli/release-cli.ts +17 -4
  319. package/src/cli/setup-cli.ts +43 -1
  320. package/src/cli/skills-cli.ts +17 -1
  321. package/src/context-bus/claude-hooks-install.ts +10 -0
  322. package/src/context-bus/context-now-surfaces.ts +48 -0
  323. package/src/context-bus/context-now.ts +104 -0
  324. package/src/context-bus/coord-events.ts +2 -2
  325. package/src/context-bus/external-events.ts +52 -0
  326. package/src/context-bus/long-term-memory.ts +108 -0
  327. package/src/dashboard/index.ts +9 -4
  328. package/src/dashboard/slash-runtime/dashboard-handlers.ts +7 -1
  329. package/src/decisions/decision-cards.ts +10 -3
  330. package/src/decisions/decision-ledger.ts +13 -5
  331. package/src/discord/sprint21-runtime.ts +5 -1
  332. package/src/discord-self-message.ts +32 -0
  333. package/src/discord-slash-wire.ts +5 -1
  334. package/src/discord.ts +17 -1
  335. package/src/domains/core-tools.ts +3 -2
  336. package/src/domains/outbound-alert.ts +6 -1
  337. package/src/domains/telegram-kind-route.ts +51 -13
  338. package/src/exec-requests/default-outputs.ts +25 -0
  339. package/src/exec-requests/planner.ts +10 -2
  340. package/src/exec-requests/runner.ts +20 -6
  341. package/src/exec-requests/store.ts +3 -0
  342. package/src/execution-loop/launch-gate.ts +100 -0
  343. package/src/field/field-reel.ts +5 -1
  344. package/src/field-note/index.ts +201 -0
  345. package/src/field-note/transcribe.ts +248 -0
  346. package/src/graph-kinds/registry.ts +3 -3
  347. package/src/graph-runner/graph-cli.ts +61 -1
  348. package/src/graph-runner/graph-grow-llm.ts +37 -0
  349. package/src/graph-runner/graph-grow.ts +47 -0
  350. package/src/graph-runner/runner.ts +317 -25
  351. package/src/grok/agent-search.ts +8 -2
  352. package/src/guardian/secret-exposure-scan.ts +101 -0
  353. package/src/harness/harness-cli-command.ts +247 -7
  354. package/src/harness/harness-pod-dispatch.ts +43 -23
  355. package/src/harness/harness-seams.ts +38 -4
  356. package/src/harness/harness-stop.ts +23 -4
  357. package/src/harness/launch-registry.ts +91 -0
  358. package/src/harness/process-garbage.ts +5 -3
  359. package/src/hooks/dispatch.ts +82 -0
  360. package/src/hooks/expose.ts +254 -0
  361. package/src/hooks/github-shadow.ts +108 -0
  362. package/src/hooks/providers.ts +71 -5
  363. package/src/hooks/queue.ts +1 -1
  364. package/src/hooks/receiver.ts +21 -20
  365. package/src/index.ts +52 -14
  366. package/src/intake-plane/categorize.ts +18 -46
  367. package/src/intake-plane/discord-seat-work.ts +10 -0
  368. package/src/intake-plane/front-route-classifier.ts +33 -39
  369. package/src/intake-plane/persona-answer.ts +30 -0
  370. package/src/intake-plane/runtime-callables.ts +8 -1
  371. package/src/intake-plane/telegram-seat-work.ts +36 -2
  372. package/src/intake-plane/wish-folder.ts +67 -0
  373. package/src/intent-gate/gate.ts +30 -10
  374. package/src/live/detail-switch.ts +5 -0
  375. package/src/llm/difficulty.ts +57 -0
  376. package/src/llm/judge-layer.ts +101 -0
  377. package/src/llm/mission-router.ts +33 -19
  378. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  379. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  380. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  381. package/src/loops/contract/loop-agent.schema.json +138 -0
  382. package/src/loops/contract/validate.ts +64 -0
  383. package/src/loops/registry.ts +20 -6
  384. package/src/market/signed-index.ts +4 -0
  385. package/src/maturity/bot-command-maturity.ts +45 -0
  386. package/src/maturity/feature-maturity.ts +26 -4
  387. package/src/model-tier/index.ts +2 -2
  388. package/src/model-tier/tier-resolver.ts +20 -20
  389. package/src/model-tier/types.ts +6 -6
  390. package/src/mss/logging/log-store.ts +15 -0
  391. package/src/nexus/api/config-model-tier.ts +5 -4
  392. package/src/nexus/api/fabric-plans.ts +53 -0
  393. package/src/nexus/api/harness-api.ts +5 -1
  394. package/src/nexus/api/health.ts +2 -0
  395. package/src/nexus/api/http-server.ts +36 -0
  396. package/src/nexus/api/inside-events.ts +226 -0
  397. package/src/nexus/api/meta-api.ts +21 -8
  398. package/src/nexus/api/missions.ts +6 -1
  399. package/src/nexus/api/ops-seats.ts +33 -0
  400. package/src/nexus/api/outputs-route.ts +44 -0
  401. package/src/nexus/api/seat-requests.ts +44 -2
  402. package/src/nexus/api/sessions-store.ts +17 -38
  403. package/src/nexus/api/sub-seat-charters.ts +34 -0
  404. package/src/nexus/api/tabs-mutations.ts +3 -1
  405. package/src/nexus/api/trace.ts +18 -6
  406. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  407. package/src/nexus/api/workflows.ts +80 -6
  408. package/src/nexus/index.ts +2 -0
  409. package/src/nexus/kinds/webterm.ts +2 -1
  410. package/src/nexus/webterm/pty.ts +6 -2
  411. package/src/onboarding/cli-auth-status.ts +80 -0
  412. package/src/onboarding/voice-ai.ts +3 -3
  413. package/src/org/seat-budget.ts +48 -0
  414. package/src/org/stall-escalation.ts +63 -0
  415. package/src/outputs/ledger.ts +120 -0
  416. package/src/persona/persona-todo.ts +79 -0
  417. package/src/persona/presets.ts +116 -2
  418. package/src/persona/team-set.ts +155 -0
  419. package/src/plugins/install/plugin-install.ts +14 -0
  420. package/src/plugins/maker/market-bundle.ts +109 -0
  421. package/src/plugins/maker/plugin-maker.ts +254 -11
  422. package/src/plugins/maker/wizard-generate.ts +103 -0
  423. package/src/pod-lease/admission.ts +150 -0
  424. package/src/pod-lease/dependency-state.ts +85 -0
  425. package/src/pod-lease/host-lease.ts +127 -0
  426. package/src/project/project-suggestion.ts +16 -0
  427. package/src/project/session-context.ts +24 -0
  428. package/src/release-loop/checklist.ts +2 -2
  429. package/src/release-loop/feature-store.ts +5 -3
  430. package/src/release-loop/next-md-merge.ts +58 -0
  431. package/src/release-loop/release-note.ts +59 -4
  432. package/src/seat-dispatch/seat-ask.ts +130 -0
  433. package/src/seat-dispatch/seat-questions.ts +100 -0
  434. package/src/seat-loop/seat-loop.ts +548 -29
  435. package/src/seat-loop/seat-report.ts +37 -2
  436. package/src/self-dev/dev-cli.ts +4 -1
  437. package/src/self-dev/dev-pipeline.ts +37 -1
  438. package/src/self-dev/draft-sweep.ts +38 -33
  439. package/src/self-dev/draft-triage-rules.ts +8 -5
  440. package/src/self-dev/fabric-plan-core.ts +297 -0
  441. package/src/self-dev/orchestrate.ts +36 -4
  442. package/src/self-dev/release-path-guard.ts +62 -0
  443. package/src/self-dev/shard-aggregate.ts +230 -0
  444. package/src/self-dev/shard-placement.ts +60 -0
  445. package/src/self-dev/shard-plan.ts +48 -0
  446. package/src/self-dev/shard-pod-run.ts +77 -0
  447. package/src/self-dev/shard-run.ts +105 -0
  448. package/src/self-implement/gate-baseline.ts +1 -1
  449. package/src/self-implement/gate-cli.ts +40 -1
  450. package/src/self-implement/gate-scope.ts +37 -7
  451. package/src/self-implement/graph-variant.ts +171 -0
  452. package/src/self-implement/harness-policy-gates.ts +1 -1
  453. package/src/self-implement/headless-elanous-driver.ts +22 -3
  454. package/src/self-implement/host-regate.ts +22 -1
  455. package/src/self-implement/importer-test-index.ts +2 -1
  456. package/src/self-implement/l8-merge-queue.ts +130 -0
  457. package/src/self-implement/orchestrator.ts +242 -9
  458. package/src/self-implement/route-consumer-test-index.ts +122 -0
  459. package/src/self-implement/seams.ts +72 -11
  460. package/src/self-implement/test-seams.ts +1 -0
  461. package/src/self-implement/uncommitted-work.ts +59 -0
  462. package/src/session/index.ts +36 -13
  463. package/src/skills/gift-install.ts +215 -0
  464. package/src/skills/tools/web-search.ts +4 -1
  465. package/src/steward/launch.ts +42 -26
  466. package/src/steward/steward-cards.ts +17 -9
  467. package/src/steward/triage.ts +46 -14
  468. package/src/task-cards/card-cli.ts +25 -1
  469. package/src/task-orchestrator/mission.ts +5 -0
  470. package/src/task-orchestrator/store.ts +12 -3
  471. package/src/task-orchestrator/surfaces/pod-command-job.ts +29 -7
  472. package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
  473. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  474. package/src/task-orchestrator/surfaces/self-implement-pod.ts +214 -40
  475. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  476. package/src/task-orchestrator/types.ts +2 -0
  477. package/src/telegram-card-followup.ts +16 -96
  478. package/src/telegram-commands.ts +10 -1
  479. package/src/telegram-project-command.ts +71 -0
  480. package/src/telegram-report.ts +21 -17
  481. package/src/telegram.ts +29 -3
  482. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  483. package/src/user-config.ts +102 -20
  484. package/src/version/packed-revision.json +1 -1
  485. package/src/web-search/grok.ts +7 -1
  486. package/src/web-search/index.ts +28 -1
  487. package/src/web-search/provider.ts +4 -0
  488. package/src/web-search/x-intent.ts +5 -0
  489. package/src/workflow-runtime/executor.ts +277 -47
  490. package/src/workflow-runtime/index.ts +1 -0
  491. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  492. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  493. package/src/workflow-runtime/schema.ts +79 -4
  494. package/src/workflow-runtime/types.ts +35 -4
  495. package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  505. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  506. package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
  525. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  583. package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
  584. /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → Y4zKzL62sakG5momz3SoQ}/_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,6 +20,8 @@ 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';
23
25
  import { emitDecision } from '../live/detail-switch.js';
24
26
  import { resolvePtyWebAddress } from '../cli/pty-web-address.js';
25
27
  import { reemitPtyUsage } from '../budget/pty-usage-reemit.js';
@@ -522,6 +524,8 @@ export interface AgentMissionDeps {
522
524
  createWorktree?: typeof createWorktree;
523
525
  recordWorktreeProvenance?: typeof recordHarnessWorktreeProvenance;
524
526
  runControlLoop?: typeof runPtyControlLoop;
527
+ /** Capture decisions in tests without replacing the process-wide debug logger. */
528
+ emitPtyDecision?: typeof emitPtyDecision;
525
529
  /** Inject controller responses while keeping the production control loop. */
526
530
  controlStream?: StreamLLMFn;
527
531
  resolvePtyWebAddress?: typeof resolvePtyWebAddress;
@@ -830,6 +834,7 @@ export interface MissionControlBrainOpts {
830
834
  readonly handoffEnabled?: boolean;
831
835
  /** Screen-grounded brain summary for the next backend, never the raw PTY screen. */
832
836
  readonly onSummary?: (summary: string) => void;
837
+ readonly onDecision?: (text: string, reply?: { question: string; answer: string }) => void;
833
838
  }
834
839
 
835
840
  /** 기존 5-action mission 판단을 canonical PTY control-loop 결정으로 축소한다. search는 이 경계에서만
@@ -855,7 +860,7 @@ export function createMissionControlBrain(opts: MissionControlBrainOpts): RunSup
855
860
  행동(action):
856
861
  - "wait": ${backendName} 가 아직 작업 중(도구 실행/생성)이면 대기.
857
862
  - "verify": ${backendName} 가 MISSION-COMPLETE/완료를 주장하면 증거 게이트(내가 실행)로 검증. 완료주장 시 이걸 우선.
858
- - "send": ${backendName} 가 멈추거나 계속 진행이 필요하면 짧고 명확한 지시(text).
863
+ - "send": ${backendName} 가 멈추거나 계속 진행이 필요하면 짧고 명확한 지시(text). 화면의 질문에 직접 답하는 경우에만 reason 을 Answering question: <화면의 질문 원문> 으로 기록하라. 다른 send 의 reason 은 종전처럼 행동 이유를 적어라.
859
864
  - "search": ${backendName} 가 정보/라이브러리/문법/외부자원에 막혔으면 omni-crawl 로 조사(query). ⭐외부 힌트 없이 스스로 판단.
860
865
  ${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/claude/elanous), mission(다음 지시), carry(diff/summary 선택). carry=summary 면 reason 에 화면에서 확인한 리뷰 지적을 구체적으로 요약하라(다음 backend 에 전달된다). claude 리뷰 뒤 지적은 codex 에 summary 로 되돌려라. elanous 는 증거 게이트와 PR.
861
866
  - "ask-human": 화면에 로그인 URL/장치 코드가 보이면 reason, url/code(보이는 것만). 토큰·자격파일을 열지 마라.` : ''}${opts.provision ? `
@@ -873,6 +878,12 @@ ${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/c
873
878
  history.push(`s${obs.step}:${decision.action}`);
874
879
  debug.log('agent-mission', 'brain', { step: obs.step, action: decision.action,
875
880
  ...(decision.action === 'ask-human' ? {} : { reason: decision.reason.slice(0, 120) }) });
881
+ // A '?' on screen alone does not establish that this send answered it. Only an
882
+ // explicit question citation in the brain's reason can attribute the reply.
883
+ const citedQuestion = /^Answering question:\s*(.+\?)\s*$/i.exec(decision.reason)?.[1]?.trim();
884
+ const question = citedQuestion && classifierFrameLines(obs.screen).find((line) => line === citedQuestion);
885
+ opts.onDecision?.(`step ${obs.step}: ${decision.action}${decision.action === 'ask-human' ? '' : ` — ${decision.reason || decision.text || decision.query || ''}`}`,
886
+ decision.action === 'send' && decision.text?.trim() && question ? { question, answer: decision.text } : undefined);
876
887
  if (decision.reason && decision.action !== 'ask-human') opts.onSummary?.(decision.reason.slice(0, 2000));
877
888
  if (decision.action === 'handoff' && decision.to && decision.mission) return { action: 'handoff', to: decision.to, mission: decision.mission, ...(decision.carry ? { carry: decision.carry } : {}) };
878
889
  if (decision.action === 'ask-human') return { action: 'ask-human', reason: decision.reason, ...(decision.url ? { url: decision.url } : {}), ...(decision.code ? { code: decision.code } : {}) };
@@ -974,6 +985,7 @@ export function makeMissionObserveStep(deps: {
974
985
  bus: ChannelBus;
975
986
  ident: { ptyId: string; instance: string; runId?: string };
976
987
  now?: () => number;
988
+ onPublishedFrame?: (obs: ControlObservation) => void;
977
989
  }): (obs: ControlObservation, decision: ControlDecision) => Promise<void> {
978
990
  const now = deps.now ?? ((): number => Date.now());
979
991
  let lastFrameState: FrameState | null = null;
@@ -1008,6 +1020,7 @@ export function makeMissionObserveStep(deps: {
1008
1020
  ...(deps.ident.runId ? { runId: deps.ident.runId } : {}),
1009
1021
  ...(pngRef ? { pngRef } : {}),
1010
1022
  });
1023
+ deps.onPublishedFrame?.(obs);
1011
1024
  // capture 는 원 semantics 유지 — 예외 전파(증거/전사 계약 불변).
1012
1025
  await deps.capture(`s${obs.step}-${decision.action}`);
1013
1026
  };
@@ -1574,9 +1587,19 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1574
1587
  if (deps.isMissionAborted?.()) { offLive(); throw new Error('MISSION_ABORTED'); }
1575
1588
  try { h = spawnPty(ptyOpts); }
1576
1589
  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' };
1590
+ if (backend.name === 'codex') observeExternalEvent({ origin: 'codex-agent-mission', kind: 'started',
1591
+ summary: 'Codex agent mission started', source: `elanous://agent-mission/${encodeURIComponent(runId)}/${encodeURIComponent(h.id)}` });
1592
+ let contextFinished = false;
1593
+ const finishContext = (ok: boolean): void => {
1594
+ if (contextFinished || backend.name !== 'codex') return;
1595
+ contextFinished = true;
1596
+ observeExternalEvent({ origin: 'codex-agent-mission', kind: 'finished',
1597
+ summary: `Codex agent mission ${ok ? 'completed' : 'failed'}`,
1598
+ source: `elanous://agent-mission/${encodeURIComponent(runId)}/${encodeURIComponent(h.id)}` });
1599
+ };
1600
+ deps.onPtyStarted?.(h, () => { if (liveTimer) clearInterval(liveTimer); offLive(); finishContext(false); });
1601
+ if (deps.isMissionAborted?.()) { finishContext(false); return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
1602
+ rounds: 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' }; }
1580
1603
  const executorRef = buildExecutorPtyRef({
1581
1604
  ptyId: h.id,
1582
1605
  backend: backend.name,
@@ -1589,6 +1612,12 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1589
1612
  process.stderr.write(`[agent-mission] pty=${h.id} watch=${webAddress.webUrl ?? `(web unavailable: ${webAddress.pwaUnavailableReason ?? 'not-resolved'})`}\n`);
1590
1613
  debug.log('agent-mission', 'pty-link', { id: h.id, webUrl: webAddress.webUrl, webUrlSource: webAddress.webUrlSource });
1591
1614
 
1615
+ const decisionIdentity = { missionId: runId, sessionId: runId, terminalId: h.id, agent: backend.name };
1616
+ const decisionEvent = (event: Omit<DecisionInput, keyof typeof decisionIdentity>): void => {
1617
+ try { (deps.emitPtyDecision ?? emitPtyDecision)({ ...decisionIdentity, ...event } as DecisionInput); }
1618
+ catch { /* Observation must not change mission control or handoff. */ }
1619
+ };
1620
+
1592
1621
  // ⭐P2 arbiter: the child is accessMode='auto' (brain-owned), so the driver —
1593
1622
  // the autonomous brain — must write as 'agent' or the arbiter denies it. This
1594
1623
  // makes "protected autonomy" real: a human attaching mid-mission (read) can't
@@ -1615,6 +1644,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1615
1644
  : 'AGENT_YIELDED: PTY 제어가 사람에게 이양됨(takeover) — 자율 미션 중단');
1616
1645
  }
1617
1646
  h['write'](s, 'agent');
1647
+ decisionEvent({ step: 'input', text: s === '\r' ? 'Sent Enter' : `Sent ${s.startsWith('\x1b') ? 'key' : 'text'}: ${s.startsWith('\x1b') ? 'navigation' : s}` });
1618
1648
  };
1619
1649
 
1620
1650
  let seq = 0;
@@ -1638,7 +1668,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1638
1668
  if (liveChunks % 20 === 0) debug.log('agent-mission', 'live', { chunks: liveChunks, tail: s.slice(-80).replace(/\s+/g, ' ') });
1639
1669
  }).catch(() => { /* noop */ });
1640
1670
  }, 800);
1641
- const stopLive = (): void => { if (liveTimer) clearInterval(liveTimer); offLive(); };
1671
+ const stopLive = (ok = false): void => { if (liveTimer) clearInterval(liveTimer); offLive(); if (ok) finishContext(true); };
1672
+ try {
1642
1673
 
1643
1674
  // ready + trust — backend 별 신뢰/권한 프롬프트 처리(codex=1, 이후 백엔드는 자체 handler).
1644
1675
  await (deps.awaitMission ? deps.awaitMission(waitForQuiet(h, 1500, 20000)) : waitForQuiet(h, 1500, 20000));
@@ -1648,7 +1679,11 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1648
1679
  // A trust menu can need more than one key (claude: ↓ to «Yes», then Enter) — answer until it is gone, at most 3 times.
1649
1680
  // 🩸 09-29: one pass sent only ↓, the mission text went into the menu and its Enter confirmed «Yes» instead of
1650
1681
  // 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++) {
1682
+ for (let pass = 0; pass < 3 && backend.handleTrust?.(screen, (s) => {
1683
+ drive(s);
1684
+ // Moving the selection is only input; the trust question is answered when the choice is confirmed.
1685
+ if (s === '\r') decisionEvent({ step: 'answer', text: 'Answered folder trust prompt', detail: { question: 'Trust this folder?', answer: 'Confirm selected choice' } });
1686
+ }); pass++) {
1652
1687
  debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled', pass });
1653
1688
  const trusted = (async () => { await waitForQuiet(h, 1500, 15000); return capture('trusted'); })();
1654
1689
  screen = await (deps.awaitMission ? deps.awaitMission(trusted) : trusted);
@@ -1761,6 +1796,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1761
1796
  let controllerSummary = deps.previousSummary ?? '';
1762
1797
  let reviewSummary = '';
1763
1798
  let coverageRetries = enhanceActive && checklist.length ? 2 : 0;
1799
+ let pendingAnswer: { text: string; question: string; answer: string } | undefined;
1764
1800
  const search = createMissionSearch({ worktree: wt.path, omniPath });
1765
1801
  const brain = createMissionControlBrain({
1766
1802
  mission: spec.mission,
@@ -1768,6 +1804,10 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1768
1804
  stream: deps.controlStream,
1769
1805
  handoffEnabled: true,
1770
1806
  onSummary: (summary) => { controllerSummary = summary; },
1807
+ onDecision: (text, reply) => {
1808
+ pendingAnswer = reply ? { text: `${reply.answer || 'continue'}\r`, ...reply } : undefined;
1809
+ decisionEvent({ step: 'judge', text });
1810
+ },
1771
1811
  evidenceReady: () => spec.chain && spec.chain.length > 1 ? true : verifyEvidence(wt.path, spec.evidence).ok,
1772
1812
  search: async (query, step) => {
1773
1813
  usedOmni = true;
@@ -1784,9 +1824,13 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1784
1824
  // before asking the LLM — otherwise the mission text is typed into the prompt and the run stalls.
1785
1825
  const trustAwareBrain: RunSupervisor = {
1786
1826
  decide: (obs, signal) => {
1827
+ pendingAnswer = undefined;
1787
1828
  let answer: string | undefined;
1788
1829
  if (backend.handleTrust?.(obs.screen, (bytes) => { answer = bytes; }) && answer !== undefined) {
1789
1830
  debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled-in-loop', step: obs.step });
1831
+ decisionEvent({ step: 'judge', text: `step ${obs.step}: trust prompt` });
1832
+ // Only the confirming Enter answers the trust question; a navigation key stays an input event.
1833
+ if (answer === '\r') pendingAnswer = { text: answer, question: 'Trust this folder?', answer: 'Confirm selected choice' };
1790
1834
  emitDecision({ kind: 'ROUTE', what: `${backend.name} 폴더 신뢰 화면 → 계속`, reason: '시작 뒤 늦게 뜬 신뢰 확인', purpose: '미션을 이어 간다', target: backend.name, phase: 'implement' });
1791
1835
  return { action: 'input', text: answer };
1792
1836
  }
@@ -1872,6 +1916,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1872
1916
  renderPng: () => h.renderScreenPng(),
1873
1917
  bus,
1874
1918
  ident: { ptyId: h.id, instance: resolveInstanceName(), runId },
1919
+ onPublishedFrame: (obs) => decisionEvent({ step: 'read', text: `step ${obs.step} (${obs.state}): ${classifierFrameLines(obs.screen).at(-1) ?? 'empty screen'}` }),
1875
1920
  });
1876
1921
  debug.log('agent-mission', 'takeover-wait', { id: h.id, maxWaitMs: AGENT_MISSION_TAKEOVER_WAIT_MS });
1877
1922
  const controlRun = runWithControlObserve(
@@ -1879,9 +1924,24 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1879
1924
  (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
1925
  () => {
1881
1926
  const handleDeps = controlDepsForHandle(h);
1927
+ const inject = backend.name === 'claude' ? submitSeparately(handleDeps.inject) : handleDeps.inject;
1882
1928
  const pending = (deps.runControlLoop ?? runPtyControlLoop)(trustAwareBrain, {
1883
1929
  ...handleDeps,
1884
- ...(backend.name === 'claude' ? { inject: submitSeparately(handleDeps.inject) } : {}),
1930
+ inject: (text) => {
1931
+ const reply = pendingAnswer?.text === text ? pendingAnswer : undefined;
1932
+ pendingAnswer = undefined;
1933
+ const accepted = inject(text);
1934
+ if (accepted) {
1935
+ decisionEvent({ step: 'input', text: `Sent ${text.startsWith('\x1b') ? 'key' : 'text'}: ${text.startsWith('\x1b') ? 'navigation' : text}` });
1936
+ if (reply) decisionEvent({ step: 'answer', text: 'Answered agent question', detail: { question: reply.question, answer: reply.answer } });
1937
+ }
1938
+ return accepted;
1939
+ },
1940
+ injectKey: handleDeps.injectKey && ((name, repeat) => {
1941
+ const accepted = handleDeps.injectKey!(name, repeat);
1942
+ if (accepted) decisionEvent({ step: 'input', text: `Pressed ${name}${repeat ? ` ×${repeat}` : ''}`, detail: { keys: name } });
1943
+ return accepted;
1944
+ }),
1885
1945
  ...(deps.isMissionAborted ? {
1886
1946
  controlStance: () => deps.isMissionAborted!() ? 'unknown' as const : probeControlStance(h, 'agent', (e) =>
1887
1947
  debug.log('agent-mission', 'hascontrol-error', { id: h.id, error: (e as Error)?.message ?? String(e) })),
@@ -1903,7 +1963,11 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1903
1963
  }
1904
1964
  }
1905
1965
  },
1906
- verifyDone: spec.chain && spec.chain.length > 1 ? async () => ({ ok: true as const }) : verifyDone,
1966
+ verifyDone: spec.chain && spec.chain.length > 1 ? async () => ({ ok: true as const }) : async (obs) => {
1967
+ const verdict = await verifyDone(obs);
1968
+ if (!verdict.ok) decisionEvent({ step: 'recover', text: 'Evidence check requires another attempt', detail: { blocked: verdict.retry, action: 'Retry after fixing evidence' } });
1969
+ return verdict;
1970
+ },
1907
1971
  handoff: async (decision, obs) => {
1908
1972
  try {
1909
1973
  if (spec.chain && decision.to !== spec.chain[1]) throw new Error(`chain order violation: expected ${spec.chain[1] ?? 'completion'}, got ${decision.to}`);
@@ -1916,6 +1980,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1916
1980
  askHuman: async (decision) => {
1917
1981
  try {
1918
1982
  await waitForHumanLogin(decision, handoffOps);
1983
+ decisionEvent({ step: 'answer', text: 'Human login question resolved', detail: { question: decision.reason, answer: 'Login completed' } });
1919
1984
  } catch (error) {
1920
1985
  transitionFailure = error instanceof Error ? error.message : String(error);
1921
1986
  throw error;
@@ -1954,7 +2019,9 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1954
2019
  }
1955
2020
  // A gate/PR handoff only counts as success when the control loop itself did not end in error.
1956
2021
  if (gatedHandoff && control.termination.kind !== 'error') {
1957
- stopLive();
2022
+ // The gate hands off a branch, not a file: record what is known instead of mislabeling the worktree directory.
2023
+ decisionEvent({ step: 'done', text: 'Mission handoff gate completed', detail: { result: { kind: 'text', ref: `branch ${wt.branch}` } } });
2024
+ stopLive(true);
1958
2025
  try { h.kill(); } catch { /* noop */ }
1959
2026
  return { ok: true, worktree: wt.path, branch: wt.branch, rounds: control.steps, evidencePath: wt.path, committed: true, usedOmniCrawl: usedOmni,
1960
2027
  ...(handoffPrSkipped ? { pr: 'skipped' as const, reason: 'origin-not-github' as const } : {}),
@@ -1985,6 +2052,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1985
2052
  maxFallbackDescents: runtimeFallback.maxDescents,
1986
2053
  });
1987
2054
  if (nextBackend && !deps.isMissionAborted?.()) {
2055
+ decisionEvent({ step: 'recover', text: `Switching ${backend.name} to ${nextBackend.name}`, detail: { blocked: control.termination.message, action: `Retry with ${nextBackend.name}` } });
1988
2056
  const nextStep: FallbackStep = nextBackend.name === 'grok' ? 'grok' : 'codex-rotate';
1989
2057
  stopLive();
1990
2058
  if (h.pid) await (deps.terminateProcessTree ?? terminateMissionProcessTree)(h.pid);
@@ -2019,7 +2087,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
2019
2087
  debug.log('agent-mission', 'commit', { ok: c.ok, out: c.out.slice(0, 120) });
2020
2088
  }
2021
2089
  debug.log('agent-mission', 'result', { ok: finalEv.ok, rounds: round, evidencePath, committed, usedOmni });
2022
- stopLive();
2090
+ decisionEvent({ step: 'done', text: finalEv.ok ? 'Mission evidence accepted' : 'Mission ended without sufficient evidence', detail: { result: { kind: evidencePath ? 'file' : 'text', ref: evidencePath ?? (control.termination.kind === 'error' ? control.termination.message : 'evidence unavailable') } } });
2091
+ stopLive(finalEv.ok);
2023
2092
  if (h.pid) await terminateMissionProcessTree(h.pid);
2024
2093
  try { h.kill(); } catch { /* noop */ }
2025
2094
 
@@ -2029,6 +2098,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
2029
2098
  ptyId: h.id, webUrl: webAddress.webUrl,
2030
2099
  detail: done ? '완료(증거 충족)' : (finalEv.ok ? '증거 충족(루프 종료)' : '미완(증거 부족)'),
2031
2100
  };
2101
+ } finally { stopLive(); finishContext(false); }
2032
2102
  }
2033
2103
 
2034
2104
  /** @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 = debug.log): 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
+ }
@@ -11,6 +11,7 @@ import { runGitCommand } from '../git-fs/runner.js';
11
11
  import * as llm from '../llm.js';
12
12
  import type { LLMMessage } from '../llm.js';
13
13
  import { debug } from '../debug/log.js';
14
+ import { releasePathHold, releasePathHoldShouldPost, releasePathHoldComment, releasePathHoldCommentsArgs, releasePrFilePaths, RELEASE_PATH_LABEL } from '../self-dev/release-path-guard.js';
14
15
  import { runAgentMission, resolveBackend, type AgentMissionResult, type EvidenceMode } from './driver.js';
15
16
  import { judgeWithAcp, prepareJudgeDiff } from './acp-judge.js';
16
17
  import { verifyMergeAndMaybeRevert } from './merge-safety.js';
@@ -114,6 +115,31 @@ function gh(args: string[]): string {
114
115
  return execFileSync('gh', args, { encoding: 'utf8', timeout: 60000, maxBuffer: 20 * 1024 * 1024, env: process.env });
115
116
  }
116
117
 
118
+ /** Check every page of the PR file list immediately before an unattended review-loop merge. */
119
+ function holdReleasePathBeforeReviewMerge(pr: string, runGh: (args: string[]) => string): boolean {
120
+ let paths: string[];
121
+ try {
122
+ paths = releasePrFilePaths(JSON.parse(runGh(['api', '--paginate', '--slurp', '--method', 'GET', '-f', 'per_page=100', `repos/{owner}/{repo}/pulls/${pr}/files`])));
123
+ } catch (error) {
124
+ debug.log('self-dev.merge', 'release-path-inspection-failed', { pr, error: String(error) });
125
+ return true;
126
+ }
127
+ const path = releasePathHold(paths);
128
+ if (!path) return false;
129
+ debug.log('self-dev.merge', 'release-path-hold', { pr, path, label: RELEASE_PATH_LABEL, surface: 'review-loop' });
130
+ try {
131
+ const names: unknown = JSON.parse(runGh(['label', 'list', '--search', RELEASE_PATH_LABEL, '--json', 'name']));
132
+ if (!Array.isArray(names)) throw new Error('invalid label list');
133
+ if (!names.some((item: unknown) => !!item && typeof item === 'object' && 'name' in item && item.name === RELEASE_PATH_LABEL)) {
134
+ runGh(['label', 'create', RELEASE_PATH_LABEL, '--color', 'D93F0B', '--description', 'Release path requires OP approval']);
135
+ }
136
+ runGh(['pr', 'edit', pr, '--add-label', RELEASE_PATH_LABEL]);
137
+ } catch (error) { debug.log('self-dev.merge', 'release-path-annotation-failed', { pr, action: 'label', error: String(error) }); }
138
+ try { if (releasePathHoldShouldPost(() => JSON.parse(runGh(releasePathHoldCommentsArgs(pr))))) runGh(['pr', 'comment', pr, '--body', releasePathHoldComment(path)]); }
139
+ catch (error) { debug.log('self-dev.merge', 'release-path-annotation-failed', { pr, action: 'comment', error: String(error) }); }
140
+ return true;
141
+ }
142
+
117
143
  /** ★ G10 안전봉투 — 자율머지 직후 회귀검증(verifyMerge 시). 회귀면 revert PR 이 이미 생성됨(알림 포함) →
118
144
  * 원 PR 에 링크 코멘트만. fail-open(검증 오류는 머지를 막지 않음). */
119
145
  async function runMergeSafety(pr: string, opts: ReviewLoopOpts, depth: ReviewDepth): Promise<void> {
@@ -233,6 +259,7 @@ export async function judgeAndFinalize(
233
259
 
234
260
  if (j.verdict === 'merge') {
235
261
  if (opts.autoMerge) {
262
+ if (holdReleasePathBeforeReviewMerge(pr, runGh)) return { pr, branch, verdict: 'reinforce', asks, action: 'parked', reworkOk: true, pushed: lastPushed, rounds: round, detail: 'OP approval required: release-path hold or PR file inspection unavailable' };
236
263
  const approve = opts.approve ?? approvePr;
237
264
  const recordReviewOutcome = opts.recordReviewOutcome ?? recordOutcome;
238
265
  approve(pr, `2차 ACP 최종심판 MERGE (round ${round})`);
@@ -480,6 +507,9 @@ export async function runReviewLoop(pr: string, opts: ReviewLoopOpts = {}): Prom
480
507
  if (cls.verdict === 'ok') {
481
508
  // light: 1차 clean 으로 충분 → approve + 머지. heavy: 1차 ok 여도 2차 심판 머스트.
482
509
  if (!effectiveFinalJudge) {
510
+ if ((opts.autoMergeOnOk || opts.autoMerge) && holdReleasePathBeforeReviewMerge(pr, runGh)) {
511
+ return { pr, branch, verdict: 'ok', asks: [], action: 'parked', detail: 'OP approval required: release-path hold or PR file inspection unavailable' };
512
+ }
483
513
  approve(pr, `소작업(light)·1차 리뷰 clean`);
484
514
  let merged = false;
485
515
  if (opts.autoMergeOnOk || opts.autoMerge) {
@@ -9,6 +9,17 @@ import { join } from 'node:path';
9
9
  import { readFileSync, writeFileSync } from 'node:fs';
10
10
  import { runGitCommand } from '../../git-fs/runner.js';
11
11
  import { countTestDeclarations } from '../../self-implement/test-declarations.js';
12
+ import { NEXT_MD_PATH, resolveNextMdConflict } from '../../release-loop/next-md-merge.js';
13
+
14
+ function deterministicNextMd(git: MergeGitSeam, worktreePath: string, file: string): string | null {
15
+ try {
16
+ const resolved = resolveNextMdConflict(git.readIndexStage(worktreePath, 1, file), git.readIndexStage(worktreePath, 2, file), git.readIndexStage(worktreePath, 3, file));
17
+ void import('../../debug/log.js').then(({ debug }) => debug.log('self-dev.merge', 'next-md-deterministic', { resolved: resolved !== null })).catch(() => {});
18
+ return resolved;
19
+ } catch {
20
+ return null; // a stage is missing (added/deleted on one side) — the usual resolver decides
21
+ }
22
+ }
12
23
 
13
24
  /** 충돌 마커가 남아있나(LLM 이 해결 못 함 판별). ours/base/theirs 3-way 마커 모두. 순수. */
14
25
  export function hasConflictMarkers(s: string): boolean {
@@ -130,8 +141,8 @@ export interface MergeGitSeam {
130
141
  merge: (wt: string, mergeTarget: string) => { ok: boolean; conflict: boolean; stdout: string; errorDetail?: string };
131
142
  /** 충돌(unmerged) 파일 목록(worktree 상대 경로). */
132
143
  conflictedFiles: (wt: string) => string[];
133
- /** Reads an unmerged index stage (2=ours, 3=theirs) for a conflicted file. */
134
- readIndexStage: (wt: string, stage: 2 | 3, file: string) => string;
144
+ /** Reads an unmerged index stage (1=base, 2=ours, 3=theirs) for a conflicted file. */
145
+ readIndexStage: (wt: string, stage: 1 | 2 | 3, file: string) => string;
135
146
  readFile: (absPath: string) => string;
136
147
  writeFile: (absPath: string, content: string) => void;
137
148
  /** 해결된 파일 스테이징. */
@@ -193,7 +204,9 @@ export async function mergeMainWithLlmResolve(
193
204
  let merged: string;
194
205
  try {
195
206
  conflicted = git.readFile(abs);
196
- merged = await resolve(f, conflicted);
207
+ // release/next.md: concurrent landings each append a line — keep both without asking the LLM (REL7c).
208
+ const deterministic = f === NEXT_MD_PATH ? deterministicNextMd(git, worktreePath, f) : null;
209
+ merged = deterministic ?? await resolve(f, conflicted);
197
210
  } catch {
198
211
  git.abort(worktreePath); // LLM 예외 → base 유지
199
212
  return measuredOutcome({ status: 'conflict-unresolved', resolvedFiles });
@@ -266,4 +266,6 @@ export const AUTOPILOT_TOOL_IDS = [
266
266
  'memory_recall',
267
267
  'ops_status',
268
268
  'self_recall',
269
+ // CTX2 #23185 — 맥락 한 문(READ-ONLY 자기관측 원장에 더해졌다).
270
+ 'context_now',
269
271
  ] as const;
@@ -116,6 +116,8 @@ export async function runDaemonPromptTurn(opts: {
116
116
  * `--tool-cwd` / `ELANOUS_TOOL_CWD` to keep `/v1/prompt` and ACP WS
117
117
  * on the same path-guard boundary. */
118
118
  toolCwd?: string;
119
+ /** Per-turn project instructions; unlike the base system preamble these must survive subsequent turns. */
120
+ projectInstructions?: string;
119
121
  /** Phase 4 (WT-A-3b) — external abort signal. When provided and
120
122
  * fired, the internal AbortController fans the abort through to
121
123
  * `runCoreTurn` (LLM stream + tool dispatch). Callers without an
@@ -286,6 +288,9 @@ export async function runDaemonPromptTurn(opts: {
286
288
  if (fast && !isFirstTurn) {
287
289
  messages.unshift({ role: 'system', content: fastPathGuidance });
288
290
  }
291
+ if (!isFirstTurn && opts.projectInstructions) {
292
+ messages.unshift({ role: 'system', content: opts.projectInstructions });
293
+ }
289
294
  const result = await runCoreTurn({
290
295
  sessionId: request.sessionId,
291
296
  userText: request.userText,
@@ -53,6 +53,7 @@ import {
53
53
  import type { CoreTurnDispatchTool } from '../core-turn/index.js';
54
54
  import { elanousSelfAccessPrompt } from '../agent/self-ambient.js';
55
55
  import { createToolCwdResolver, type ToolCwdResolver } from './tool-cwd.js';
56
+ import { resolveSessionProjectContext } from '../project/session-context.js';
56
57
  import { debug } from '../debug/log.js';
57
58
 
58
59
  /** C4 (2026-07-12) — arm the non-detached-PTY kill ONCE per turn signal.
@@ -579,7 +580,9 @@ export function createDaemonRunTurn(
579
580
  // moved this out of an inline closure to fix the user-message
580
581
  // persistence bug uniformly across all daemon paths.
581
582
  getMessages: ({ sessionId, userText, promptBlocks, promptMeta }) => {
582
- const baseSystemPrompt = composeDaemonSystemPrompt(opts.systemPrompt, promptMeta, sessionId);
583
+ const projectInstructions = resolveSessionProjectContext(sessionId)?.instructions;
584
+ const baseSystemPrompt = [composeDaemonSystemPrompt(opts.systemPrompt, promptMeta, sessionId), projectInstructions]
585
+ .filter(Boolean).join('\n\n');
583
586
  // Image-pipeline followup #4 (2026-05-05) — append daemon webterm
584
587
  // context (current ACP sessionId + active terminal summary) to
585
588
  // the system prompt when the webterm surface is active. Helper
@@ -720,8 +723,11 @@ export function createDaemonRunTurn(
720
723
  });
721
724
  debugBridge.activate();
722
725
  }
723
- if (opts.acpSessionCwd) {
724
- const resolver = createToolCwdResolver({ tools: opts.tools ?? 'none', toolCwd: turnCtx.cwd });
726
+ const projectCwd = resolveSessionProjectContext(turnCtx.sessionId)?.cwd;
727
+ if (projectCwd || opts.acpSessionCwd) {
728
+ // An ACP session's explicit cwd wins; the project folder is only the default when none was given (IA3 review).
729
+ const explicitCwd = opts.acpSessionCwd && turnCtx.cwd ? turnCtx.cwd : undefined;
730
+ const resolver = createToolCwdResolver({ tools: opts.tools ?? 'none', toolCwd: explicitCwd ?? projectCwd ?? turnCtx.cwd });
725
731
  await turnToolCwd.run(resolver, () => inner(turnCtx));
726
732
  } else {
727
733
  await inner(turnCtx);
@@ -23,6 +23,8 @@ export interface DaemonWebSearchArgs {
23
23
  export interface DaemonWebSearchResult {
24
24
  query: string;
25
25
  providerName: string;
26
+ /** Absent for ordinary searches; signals whether X sources were actually cited. */
27
+ xSearch?: 'grok' | 'unavailable';
26
28
  hits: Array<{
27
29
  url: string;
28
30
  title: string;
@@ -90,6 +92,7 @@ export async function dispatchWebSearch(
90
92
  return {
91
93
  query,
92
94
  providerName: result.providerName,
95
+ ...(result.xSearch ? { xSearch: result.xSearch } : {}),
93
96
  hits: result.hits.map((h) => ({
94
97
  url: h.url,
95
98
  title: h.title,