elanous 0.2.0 → 0.2.4

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 (1174) hide show
  1. package/.env.example +6 -0
  2. package/README.md +16 -14
  3. package/apps/pwa/out/404/index.html +1 -1
  4. package/apps/pwa/out/404.html +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1191-7b13a24117a689fa.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/2375-3fcae5186c64fe6b.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/2415.ed6428ff334c7ce2.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +25 -0
  17. package/apps/pwa/out/_next/static/chunks/{2a79f15a-2013e4d421d6df88.js → 2ea96958-e8c7e112de50b067.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/319-d37df1b6e0cbeff4.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +5 -0
  20. package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6804.8ed6ab492bc5fc0a.js → 4323.c5dfb6f503304775.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/4836-3c93795ab834381e.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{320-d7013ec072863e5e.js → 5080-1613752891fcadb4.js} +4 -4
  26. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/6062-73e68343a9814f6a.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/6090-1bd6077591603947.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/7457-f5cb1cc8db9f7453.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/8046cadf-211ca3c0e00f2b72.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8067-f74bf14d67ad98f1.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8142-011e1f474efb8b33.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8519-0059d82bdb4812bf.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/9740-52467f244755917f.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/9804-64c02c3c127d5014.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/app/approvals/page-21c3261af6ab377c.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-1991445b8ea86274.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/board/page-4ebfaee2369fe248.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/botlab/page-9fa879ebf5959096.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/bots/page-ca7c3cc305c3285a.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/chat/page-9951930add3d2051.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/control/page-4472ddf1e2458e69.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/app/design-check/page-4de08d4b766f134b.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/editor/page-7a975e2b9db1dfb7.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/intake/page-49270714ef35bb96.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/layout-33fbdf353e2a5982.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/live/page-259f122e2dd64317.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/market/page-65b82726753658e1.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-4b8df3748dc06285.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/morning/page-112f7e477bda77fd.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/not-found-542a5c0006da637c.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/observatory/page-63ffb347831262ea.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/page-98e4e359d97263b4.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/reflection/page-97e24ac675ce576e.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ac6391f26391d89d.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f45c9d45ffc43bd.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-36995b9cb5d98218.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/settings/page-0c795b577988d63f.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-b4311e2f71c6735a.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/setup/page-eb2381074df20dba.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/share/page-b01336e64eba01ae.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/showroom/page-7af7f21c1f2858ef.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/tasks/page-a98ecd364586c89b.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/term/page-57f0502dfbfa089b.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/trace/page-3467d2e1abd8a14a.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/vault/page-7842ca23d53ba682.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-ae9ac882912b0198.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/workflows/page-3a0d72e3f783bcef.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/workspace/page-f3b39fe8358c2a97.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-5a22af3181ac2afb.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/main-app-1457627bb302a22c.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +1 -0
  92. package/apps/pwa/out/_next/static/css/e66b7f5efc8df3f3.css +1 -0
  93. package/apps/pwa/out/_next/static/zoQX5iTvXOsIvCjxCe1Ji/_buildManifest.js +1 -0
  94. package/apps/pwa/out/approvals/index.html +1 -0
  95. package/apps/pwa/out/approvals/index.txt +30 -0
  96. package/apps/pwa/out/autopilot/index.html +1 -1
  97. package/apps/pwa/out/autopilot/index.txt +27 -26
  98. package/apps/pwa/out/board/index.html +1 -0
  99. package/apps/pwa/out/board/index.txt +30 -0
  100. package/apps/pwa/out/botlab/index.html +1 -1
  101. package/apps/pwa/out/botlab/index.txt +24 -23
  102. package/apps/pwa/out/bots/index.html +1 -1
  103. package/apps/pwa/out/bots/index.txt +24 -23
  104. package/apps/pwa/out/chat/index.html +1 -2
  105. package/apps/pwa/out/chat/index.txt +24 -23
  106. package/apps/pwa/out/control/index.html +1 -1
  107. package/apps/pwa/out/control/index.txt +27 -26
  108. package/apps/pwa/out/design-check/index.html +1 -1
  109. package/apps/pwa/out/design-check/index.txt +27 -26
  110. package/apps/pwa/out/editor/index.html +1 -0
  111. package/apps/pwa/out/editor/index.txt +31 -0
  112. package/apps/pwa/out/healthz +1 -1
  113. package/apps/pwa/out/index.html +1 -1
  114. package/apps/pwa/out/index.txt +24 -23
  115. package/apps/pwa/out/intake/index.html +1 -1
  116. package/apps/pwa/out/intake/index.txt +27 -26
  117. package/apps/pwa/out/live/index.html +1 -0
  118. package/apps/pwa/out/live/index.txt +30 -0
  119. package/apps/pwa/out/market/index.html +1 -0
  120. package/apps/pwa/out/market/index.txt +27 -0
  121. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  122. package/apps/pwa/out/missions/placeholder/index.txt +24 -23
  123. package/apps/pwa/out/morning/index.html +1 -1
  124. package/apps/pwa/out/morning/index.txt +27 -26
  125. package/apps/pwa/out/observatory/index.html +1 -1
  126. package/apps/pwa/out/observatory/index.txt +27 -26
  127. package/apps/pwa/out/reflection/index.html +1 -1
  128. package/apps/pwa/out/reflection/index.txt +25 -24
  129. package/apps/pwa/out/scheduler/index.html +1 -1
  130. package/apps/pwa/out/scheduler/index.txt +27 -26
  131. package/apps/pwa/out/sessions/index.html +1 -1
  132. package/apps/pwa/out/sessions/index.txt +24 -23
  133. package/apps/pwa/out/settings/devices/index.html +1 -1
  134. package/apps/pwa/out/settings/devices/index.txt +27 -26
  135. package/apps/pwa/out/settings/index.html +1 -1
  136. package/apps/pwa/out/settings/index.txt +27 -26
  137. package/apps/pwa/out/setup/done/index.html +1 -1
  138. package/apps/pwa/out/setup/done/index.txt +27 -26
  139. package/apps/pwa/out/setup/index.html +1 -1
  140. package/apps/pwa/out/setup/index.txt +27 -26
  141. package/apps/pwa/out/share/index.html +1 -1
  142. package/apps/pwa/out/share/index.txt +27 -26
  143. package/apps/pwa/out/showroom/index.html +1 -1
  144. package/apps/pwa/out/showroom/index.txt +24 -23
  145. package/apps/pwa/out/tasks/index.html +1 -1
  146. package/apps/pwa/out/tasks/index.txt +27 -26
  147. package/apps/pwa/out/term/index.html +1 -1
  148. package/apps/pwa/out/term/index.txt +27 -26
  149. package/apps/pwa/out/trace/index.html +1 -0
  150. package/apps/pwa/out/trace/index.txt +30 -0
  151. package/apps/pwa/out/vault/index.html +1 -1
  152. package/apps/pwa/out/vault/index.txt +27 -26
  153. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  154. package/apps/pwa/out/workflows/chat-ui/index.txt +27 -26
  155. package/apps/pwa/out/workflows/index.html +1 -1
  156. package/apps/pwa/out/workflows/index.txt +27 -27
  157. package/apps/pwa/out/workspace/index.html +1 -1
  158. package/apps/pwa/out/workspace/index.txt +27 -26
  159. package/apps/pwa/out/worktrees/index.html +1 -1
  160. package/apps/pwa/out/worktrees/index.txt +27 -26
  161. package/catalog/resources.yaml +8 -11
  162. package/docs/design/systems/LICENSE +201 -0
  163. package/docs/design/systems/NOTICE.md +29 -0
  164. package/docs/design/systems/SOURCE.json +291 -0
  165. package/docs/design/systems/application/DESIGN.md +71 -0
  166. package/docs/design/systems/application/manifest.json +54 -0
  167. package/docs/design/systems/application/tokens.css +63 -0
  168. package/docs/design/systems/artistic/DESIGN.md +71 -0
  169. package/docs/design/systems/artistic/manifest.json +54 -0
  170. package/docs/design/systems/artistic/tokens.css +63 -0
  171. package/docs/design/systems/bento/DESIGN.md +71 -0
  172. package/docs/design/systems/bento/manifest.json +54 -0
  173. package/docs/design/systems/bento/tokens.css +63 -0
  174. package/docs/design/systems/bold/DESIGN.md +71 -0
  175. package/docs/design/systems/bold/manifest.json +54 -0
  176. package/docs/design/systems/bold/tokens.css +63 -0
  177. package/docs/design/systems/brutalism/DESIGN.md +71 -0
  178. package/docs/design/systems/brutalism/manifest.json +54 -0
  179. package/docs/design/systems/brutalism/tokens.css +63 -0
  180. package/docs/design/systems/cafe/DESIGN.md +71 -0
  181. package/docs/design/systems/cafe/manifest.json +54 -0
  182. package/docs/design/systems/cafe/tokens.css +63 -0
  183. package/docs/design/systems/claymorphism/DESIGN.md +71 -0
  184. package/docs/design/systems/claymorphism/manifest.json +54 -0
  185. package/docs/design/systems/claymorphism/tokens.css +63 -0
  186. package/docs/design/systems/clean/DESIGN.md +71 -0
  187. package/docs/design/systems/clean/manifest.json +54 -0
  188. package/docs/design/systems/clean/tokens.css +63 -0
  189. package/docs/design/systems/colorful/DESIGN.md +71 -0
  190. package/docs/design/systems/colorful/manifest.json +54 -0
  191. package/docs/design/systems/colorful/tokens.css +63 -0
  192. package/docs/design/systems/contemporary/DESIGN.md +71 -0
  193. package/docs/design/systems/contemporary/manifest.json +54 -0
  194. package/docs/design/systems/contemporary/tokens.css +63 -0
  195. package/docs/design/systems/corporate/DESIGN.md +71 -0
  196. package/docs/design/systems/corporate/manifest.json +54 -0
  197. package/docs/design/systems/corporate/tokens.css +63 -0
  198. package/docs/design/systems/cosmic/DESIGN.md +71 -0
  199. package/docs/design/systems/cosmic/manifest.json +54 -0
  200. package/docs/design/systems/cosmic/tokens.css +63 -0
  201. package/docs/design/systems/creative/DESIGN.md +71 -0
  202. package/docs/design/systems/creative/manifest.json +54 -0
  203. package/docs/design/systems/creative/tokens.css +63 -0
  204. package/docs/design/systems/dashboard/DESIGN.md +71 -0
  205. package/docs/design/systems/dashboard/manifest.json +54 -0
  206. package/docs/design/systems/dashboard/tokens.css +63 -0
  207. package/docs/design/systems/default/DESIGN.md +62 -0
  208. package/docs/design/systems/default/manifest.json +69 -0
  209. package/docs/design/systems/default/tokens.css +200 -0
  210. package/docs/design/systems/dithered/DESIGN.md +71 -0
  211. package/docs/design/systems/dithered/manifest.json +54 -0
  212. package/docs/design/systems/dithered/tokens.css +63 -0
  213. package/docs/design/systems/doodle/DESIGN.md +71 -0
  214. package/docs/design/systems/doodle/manifest.json +54 -0
  215. package/docs/design/systems/doodle/tokens.css +63 -0
  216. package/docs/design/systems/dramatic/DESIGN.md +71 -0
  217. package/docs/design/systems/dramatic/manifest.json +54 -0
  218. package/docs/design/systems/dramatic/tokens.css +63 -0
  219. package/docs/design/systems/editorial/DESIGN.md +71 -0
  220. package/docs/design/systems/editorial/manifest.json +54 -0
  221. package/docs/design/systems/editorial/tokens.css +63 -0
  222. package/docs/design/systems/elegant/DESIGN.md +71 -0
  223. package/docs/design/systems/elegant/manifest.json +54 -0
  224. package/docs/design/systems/elegant/tokens.css +63 -0
  225. package/docs/design/systems/energetic/DESIGN.md +72 -0
  226. package/docs/design/systems/energetic/manifest.json +54 -0
  227. package/docs/design/systems/energetic/tokens.css +63 -0
  228. package/docs/design/systems/enterprise/DESIGN.md +71 -0
  229. package/docs/design/systems/enterprise/manifest.json +54 -0
  230. package/docs/design/systems/enterprise/tokens.css +63 -0
  231. package/docs/design/systems/expressive/DESIGN.md +71 -0
  232. package/docs/design/systems/expressive/manifest.json +54 -0
  233. package/docs/design/systems/expressive/tokens.css +63 -0
  234. package/docs/design/systems/fantasy/DESIGN.md +71 -0
  235. package/docs/design/systems/fantasy/manifest.json +54 -0
  236. package/docs/design/systems/fantasy/tokens.css +63 -0
  237. package/docs/design/systems/flat/DESIGN.md +71 -0
  238. package/docs/design/systems/flat/manifest.json +54 -0
  239. package/docs/design/systems/flat/tokens.css +63 -0
  240. package/docs/design/systems/friendly/DESIGN.md +71 -0
  241. package/docs/design/systems/friendly/manifest.json +54 -0
  242. package/docs/design/systems/friendly/tokens.css +63 -0
  243. package/docs/design/systems/glassmorphism/DESIGN.md +71 -0
  244. package/docs/design/systems/glassmorphism/manifest.json +54 -0
  245. package/docs/design/systems/glassmorphism/tokens.css +63 -0
  246. package/docs/design/systems/gradient/DESIGN.md +71 -0
  247. package/docs/design/systems/gradient/manifest.json +54 -0
  248. package/docs/design/systems/gradient/tokens.css +63 -0
  249. package/docs/design/systems/luxury/DESIGN.md +71 -0
  250. package/docs/design/systems/luxury/manifest.json +54 -0
  251. package/docs/design/systems/luxury/tokens.css +63 -0
  252. package/docs/design/systems/minimal/DESIGN.md +71 -0
  253. package/docs/design/systems/minimal/manifest.json +54 -0
  254. package/docs/design/systems/minimal/tokens.css +63 -0
  255. package/docs/design/systems/modern/DESIGN.md +71 -0
  256. package/docs/design/systems/modern/manifest.json +54 -0
  257. package/docs/design/systems/modern/tokens.css +63 -0
  258. package/docs/design/systems/mono/DESIGN.md +71 -0
  259. package/docs/design/systems/mono/manifest.json +54 -0
  260. package/docs/design/systems/mono/tokens.css +63 -0
  261. package/docs/design/systems/neobrutalism/DESIGN.md +71 -0
  262. package/docs/design/systems/neobrutalism/manifest.json +54 -0
  263. package/docs/design/systems/neobrutalism/tokens.css +63 -0
  264. package/docs/design/systems/neon/DESIGN.md +71 -0
  265. package/docs/design/systems/neon/manifest.json +54 -0
  266. package/docs/design/systems/neon/tokens.css +63 -0
  267. package/docs/design/systems/neumorphism/DESIGN.md +71 -0
  268. package/docs/design/systems/neumorphism/manifest.json +54 -0
  269. package/docs/design/systems/neumorphism/tokens.css +63 -0
  270. package/docs/design/systems/paper/DESIGN.md +71 -0
  271. package/docs/design/systems/paper/manifest.json +54 -0
  272. package/docs/design/systems/paper/tokens.css +63 -0
  273. package/docs/design/systems/perspective/DESIGN.md +71 -0
  274. package/docs/design/systems/perspective/manifest.json +54 -0
  275. package/docs/design/systems/perspective/tokens.css +63 -0
  276. package/docs/design/systems/premium/DESIGN.md +71 -0
  277. package/docs/design/systems/premium/manifest.json +54 -0
  278. package/docs/design/systems/premium/tokens.css +63 -0
  279. package/docs/design/systems/professional/DESIGN.md +71 -0
  280. package/docs/design/systems/professional/manifest.json +54 -0
  281. package/docs/design/systems/professional/tokens.css +63 -0
  282. package/docs/design/systems/publication/DESIGN.md +71 -0
  283. package/docs/design/systems/publication/manifest.json +54 -0
  284. package/docs/design/systems/publication/tokens.css +63 -0
  285. package/docs/design/systems/refined/DESIGN.md +71 -0
  286. package/docs/design/systems/refined/manifest.json +54 -0
  287. package/docs/design/systems/refined/tokens.css +63 -0
  288. package/docs/design/systems/retro/DESIGN.md +71 -0
  289. package/docs/design/systems/retro/manifest.json +54 -0
  290. package/docs/design/systems/retro/tokens.css +63 -0
  291. package/docs/design/systems/shadcn/DESIGN.md +71 -0
  292. package/docs/design/systems/shadcn/manifest.json +54 -0
  293. package/docs/design/systems/shadcn/tokens.css +255 -0
  294. package/docs/design/systems/simple/DESIGN.md +71 -0
  295. package/docs/design/systems/simple/manifest.json +54 -0
  296. package/docs/design/systems/simple/tokens.css +63 -0
  297. package/docs/design/systems/skeumorphism/DESIGN.md +71 -0
  298. package/docs/design/systems/skeumorphism/manifest.json +54 -0
  299. package/docs/design/systems/skeumorphism/tokens.css +63 -0
  300. package/docs/design/systems/sleek/DESIGN.md +71 -0
  301. package/docs/design/systems/sleek/manifest.json +54 -0
  302. package/docs/design/systems/sleek/tokens.css +63 -0
  303. package/docs/design/systems/spacious/DESIGN.md +71 -0
  304. package/docs/design/systems/spacious/manifest.json +54 -0
  305. package/docs/design/systems/spacious/tokens.css +63 -0
  306. package/docs/design/systems/storytelling/DESIGN.md +71 -0
  307. package/docs/design/systems/storytelling/manifest.json +54 -0
  308. package/docs/design/systems/storytelling/tokens.css +63 -0
  309. package/docs/design/systems/tom-modern/DESIGN.md +361 -0
  310. package/docs/design/systems/tom-modern/manifest.json +16 -0
  311. package/docs/design/systems/tom-modern/tokens.css +99 -0
  312. package/docs/design/systems/vibrant/DESIGN.md +71 -0
  313. package/docs/design/systems/vibrant/manifest.json +54 -0
  314. package/docs/design/systems/vibrant/tokens.css +63 -0
  315. package/docs/design/systems/vintage/DESIGN.md +71 -0
  316. package/docs/design/systems/vintage/manifest.json +54 -0
  317. package/docs/design/systems/vintage/tokens.css +63 -0
  318. package/docs/design/systems/warm-editorial/DESIGN.md +65 -0
  319. package/docs/design/systems/warm-editorial/manifest.json +54 -0
  320. package/docs/design/systems/warm-editorial/tokens.css +63 -0
  321. package/docs/goal-context/01-goal-authoring-checks.md +18 -0
  322. package/docs/goal-context/steward-directives-2026-09-28.md +44 -0
  323. package/graphs/catalog/catalog.yaml +615 -0
  324. package/graphs/default-loop.yaml +1 -1
  325. package/graphs/document-loop.yaml +1 -1
  326. package/graphs/examples/stale-draft-digest/digest.ts +26 -0
  327. package/graphs/examples/stale-draft-digest/recipes.yaml +8 -0
  328. package/graphs/examples/stale-draft-digest/stale-draft-digest.yaml +22 -0
  329. package/graphs/heal/heal-loop.yaml +155 -0
  330. package/graphs/heal/recipes.yaml +19 -0
  331. package/graphs/implement-loop.yaml +2 -2
  332. package/graphs/intake/intake-daily.yaml +55 -0
  333. package/graphs/intake/recipes.yaml +16 -0
  334. package/graphs/landing/landing-heal.yaml +22 -0
  335. package/graphs/landing/recipes.yaml +8 -0
  336. package/graphs/launch/launch-head.yaml +66 -0
  337. package/graphs/launch/recipes.yaml +8 -0
  338. package/graphs/operate-loop.yaml +1 -1
  339. package/graphs/ops/docs-publish.yaml +31 -0
  340. package/graphs/ops/recipes.yaml +8 -0
  341. package/graphs/release/recipes.yaml +38 -0
  342. package/graphs/release/release-loop.yaml +40 -0
  343. package/graphs/research-loop.yaml +1 -1
  344. package/graphs/steward/recipes.yaml +12 -0
  345. package/graphs/steward/steward.yaml +45 -0
  346. package/graphs/video/broll-line.yaml +54 -0
  347. package/package.json +7 -5
  348. package/plugins/job-coach/.agents/plugins/marketplace.json +12 -0
  349. package/plugins/job-coach/.codex-plugin/plugin.json +6 -0
  350. package/plugins/job-coach/.mcp.json +9 -0
  351. package/plugins/job-coach/README.md +20 -0
  352. package/plugins/job-coach/connectors/ncs/server.ts +89 -0
  353. package/plugins/job-coach/examples/interview-sample.md +11 -0
  354. package/plugins/job-coach/graphs/course-links.ts +46 -0
  355. package/plugins/job-coach/graphs/recipes.yaml +18 -0
  356. package/plugins/job-coach/graphs/report.yaml +20 -0
  357. package/plugins/job-coach/graphs/run-step.ts +108 -0
  358. package/plugins/job-coach/plugin.json +13 -0
  359. package/plugins/job-coach/plugin.ts +6 -0
  360. package/plugins/job-coach/skills/career-report/SKILL.md +6 -0
  361. package/plugins/job-coach/skills/interview-to-profile/SKILL.md +6 -0
  362. package/plugins/job-coach/skills/run-report/SKILL.md +15 -0
  363. package/scripts/backup/elanous-backup.sh +139 -13
  364. package/scripts/backup/elanous-restore.sh +122 -0
  365. package/scripts/ci-daemon-port-gate.ts +164 -0
  366. package/scripts/ci-typecheck-changed.ts +15 -1
  367. package/scripts/cli-json-exit-scan.ts +126 -0
  368. package/scripts/codex-quota-alert-format.ts +52 -0
  369. package/scripts/codex-quota-alert.ts +63 -13
  370. package/scripts/continuation-dogfood.ts +2 -1
  371. package/scripts/coord-channel-watch.sh +5 -5
  372. package/scripts/coord-tracks.json +5 -4
  373. package/scripts/cron-run.ts +37 -16
  374. package/scripts/daemon-port-baseline.txt +9 -0
  375. package/scripts/design/extract-corpus-bench.ts +469 -0
  376. package/scripts/design/extract-corpus-score.ts +510 -0
  377. package/scripts/design/vendor-open-design-systems.ts +100 -0
  378. package/scripts/docs-lint.ts +1 -1
  379. package/scripts/fleet/node-setup.sh +38 -4
  380. package/scripts/heal/run-role.ts +328 -0
  381. package/scripts/install-role-watch.sh +95 -0
  382. package/scripts/install.ps1 +11 -1
  383. package/scripts/install.sh +81 -9
  384. package/scripts/isolation-hardcode-baseline.txt +1 -1
  385. package/scripts/landing-heal/must-fix-match.ts +37 -0
  386. package/scripts/landing-heal/run-mission.ts +101 -0
  387. package/scripts/lib/pwa-scenarios/acp-replay.ts +79 -0
  388. package/scripts/lib/pwa-scenarios/cdp-driver.ts +67 -0
  389. package/scripts/lib/pwa-scenarios/runner.ts +200 -0
  390. package/scripts/lib/pwa-scenarios/scenarios.ts +202 -0
  391. package/scripts/market/db-check.ts +212 -0
  392. package/scripts/market-posture-cycle.ts +63 -4
  393. package/scripts/nightly-docops.ts +1 -1
  394. package/scripts/ops/channel-bot-token-migrate.ts +146 -0
  395. package/scripts/ops-health-check.ts +15 -3
  396. package/scripts/pty-scenarios/run.ts +272 -0
  397. package/scripts/public-leak-baseline.txt +0 -7
  398. package/scripts/publish-internal-dist.ts +119 -0
  399. package/scripts/pwa-scenarios.ts +106 -0
  400. package/scripts/rebrand-elanous.ts +1 -1
  401. package/scripts/release-loop/cutoff.ts +139 -0
  402. package/scripts/release-loop/docs-land-node.ts +65 -0
  403. package/scripts/release-loop/docs-node.ts +172 -0
  404. package/scripts/release-loop/gate-diff.ts +29 -0
  405. package/scripts/release-loop/gate-node.ts +353 -0
  406. package/scripts/release-loop/node-verdict.ts +85 -0
  407. package/scripts/release-loop/prepare-node.ts +31 -0
  408. package/scripts/release-loop/publish-node.ts +57 -0
  409. package/scripts/release-loop/pwa-node-verdict.ts +45 -0
  410. package/scripts/release-loop/pwa-scenarios-node.ts +140 -0
  411. package/scripts/release-loop/release-docs.ts +102 -0
  412. package/scripts/release-loop/tui-node-checks.ts +29 -0
  413. package/scripts/release-loop/tui-sim-node.ts +113 -0
  414. package/scripts/release-loop/upgrade-node.ts +25 -0
  415. package/scripts/release-loop/verify-node.ts +21 -0
  416. package/scripts/release-loop/version-node.ts +147 -0
  417. package/scripts/release-upgrade-check.sh +53 -0
  418. package/scripts/se-mission-prepare.ts +9 -15
  419. package/scripts/test-deterministic.ts +2 -1
  420. package/scripts/uninstall.sh +10 -3
  421. package/scripts/video-broll-line.ts +89 -0
  422. package/scripts/waitlist-daily-digest.ts +108 -0
  423. package/scripts/window-landings.sh +1 -1
  424. package/skills/motion-broll/LICENSE +25 -0
  425. package/skills/motion-broll/SKILL.md +150 -0
  426. package/skills/motion-broll/SOURCE.md +6 -0
  427. package/skills/motion-broll/engine/base.css +19 -0
  428. package/skills/motion-broll/engine/beats.js +11 -0
  429. package/skills/motion-broll/engine/build.py +21 -0
  430. package/skills/motion-broll/engine/fonts/Geist-Variable.woff2 +0 -0
  431. package/skills/motion-broll/engine/fonts/GeistMono-Medium.woff2 +0 -0
  432. package/skills/motion-broll/engine/fonts/OFL-Geist.txt +92 -0
  433. package/skills/motion-broll/engine/motion.js +146 -0
  434. package/skills/motion-broll/engine/render.js +22 -0
  435. package/skills/motion-broll/examples/opus-aoe2/01-opus-drop.html +41 -0
  436. package/skills/motion-broll/examples/opus-aoe2/02-pip-builds.html +110 -0
  437. package/skills/motion-broll/examples/opus-aoe2/03-effort-slider.html +38 -0
  438. package/skills/motion-broll/examples/opus-aoe2/04-master-prompt.html +56 -0
  439. package/skills/motion-broll/examples/opus-aoe2/05-low-vs-max.html +49 -0
  440. package/skills/motion-broll/examples/opus-aoe2/06-chapter.html +18 -0
  441. package/skills/motion-broll/examples/opus-aoe2/plan.json +14 -0
  442. package/skills/motion-broll/reference/engine-api.md +106 -0
  443. package/skills/motion-broll/scripts/composite.py +14 -0
  444. package/skills/motion-broll/scripts/inspect_video.py +34 -0
  445. package/skills/motion-broll/scripts/make_pages.py +34 -0
  446. package/skills/motion-broll/scripts/setup.sh +16 -0
  447. package/skills/motion-broll/scripts/words.py +13 -0
  448. package/skills/motion-broll/templates/compare.html +135 -0
  449. package/skills/motion-broll/templates/viewer.html +97 -0
  450. package/skills/omni-digest/SKILL.md +260 -0
  451. package/skills/omni-digest/digest.md +197 -0
  452. package/skills/omni-digest/docs/diagrams/noncode-terminal-promotion-path-2026-08-13.mmd +32 -0
  453. package/skills/omni-digest/package-lock.json +558 -0
  454. package/skills/omni-digest/package.json +13 -0
  455. package/skills/omni-digest/scripts/main.ts +404 -0
  456. package/skills/omni-digest/src/delegate.ts +34 -0
  457. package/skills/omni-digest/src/detect.ts +46 -0
  458. package/skills/omni-digest/src/diagram.ts +72 -0
  459. package/skills/omni-digest/src/domain-staging.ts +50 -0
  460. package/skills/omni-digest/src/env.ts +38 -0
  461. package/skills/omni-digest/src/fetch.ts +237 -0
  462. package/skills/omni-digest/src/media.ts +180 -0
  463. package/skills/omni-digest/src/obsidian.ts +69 -0
  464. package/skills/omni-digest/src/ocr.ts +149 -0
  465. package/skills/omni-digest/src/router.ts +60 -0
  466. package/skills/omni-digest/src/summarize.ts +87 -0
  467. package/skills/omni-digest/src/types.ts +124 -0
  468. package/skills/omni-digest/src/util.ts +34 -0
  469. package/skills/omni-digest/src/visual.ts +129 -0
  470. package/skills/omni-digest/src/x-api.ts +151 -0
  471. package/skills/omni-digest/tsconfig.json +13 -0
  472. package/src/a2a/agent-card.ts +29 -0
  473. package/src/a2a/server.ts +173 -0
  474. package/src/acp/auto-persist.ts +3 -6
  475. package/src/acp/backend-registry.ts +6 -10
  476. package/src/acp/channel-browser-shell.ts +1 -535
  477. package/src/acp/client.ts +106 -36
  478. package/src/acp/fs-roots.ts +20 -4
  479. package/src/acp/obsidian-tags.ts +6 -3
  480. package/src/acp/server.ts +189 -32
  481. package/src/agent/pty-binding.ts +1 -1
  482. package/src/agent/spawn-embodied-agent-in-vw.ts +5 -336
  483. package/src/agent/subagent-callable.ts +39 -1
  484. package/src/agent-mission/browser-login.ts +241 -0
  485. package/src/agent-mission/capabilities-cli.ts +33 -0
  486. package/src/agent-mission/capability-matrix.ts +31 -0
  487. package/src/agent-mission/capability-readers.ts +79 -0
  488. package/src/agent-mission/capability-types.ts +15 -0
  489. package/src/agent-mission/claude-headless.ts +131 -0
  490. package/src/agent-mission/claude-subscription.ts +57 -0
  491. package/src/agent-mission/doc-guided-install.ts +185 -0
  492. package/src/agent-mission/driver.ts +821 -69
  493. package/src/agent-mission/env-profile.ts +68 -0
  494. package/src/agent-mission/handoff.ts +128 -0
  495. package/src/agent-mission/in-agent-plugin.ts +311 -0
  496. package/src/agent-mission/mission-cli.ts +19 -1
  497. package/src/agent-mission/parse.ts +9 -4
  498. package/src/agent-mission/pr-review-watch.ts +62 -13
  499. package/src/agent-mission/resource-ladder.ts +187 -0
  500. package/src/agent-mission/tool-install.ts +249 -0
  501. package/src/agent-mission/tool-ladder.ts +37 -0
  502. package/src/agent-room/room-builder.ts +6 -600
  503. package/src/agent-substrate/review-intent.ts +43 -1
  504. package/src/auth/scope.ts +8 -4
  505. package/src/auth/temp-tokens.ts +131 -0
  506. package/src/auto-research/obsidian-bridge.ts +2 -0
  507. package/src/autopilot/build/integrity-gate.ts +27 -4
  508. package/src/autopilot/build/isolated-instance.ts +2 -1
  509. package/src/autopilot/build/llm-conflict-merge.ts +27 -0
  510. package/src/autopilot/llm-control-brain.ts +54 -12
  511. package/src/autopilot/mission-engine.ts +15 -1
  512. package/src/autopilot/mission-notify.ts +4 -2
  513. package/src/autopilot/mission-origin.ts +5 -5
  514. package/src/autopilot/mission-phase-track.ts +52 -0
  515. package/src/autopilot/mission-tool.ts +1 -1
  516. package/src/autopilot/pty-control-loop.ts +94 -2
  517. package/src/autopilot/track-agent.ts +138 -0
  518. package/src/autopilot/track-courier.ts +153 -0
  519. package/src/boot/acp-server.ts +16 -2
  520. package/src/boot/check-same-origin.ts +19 -5
  521. package/src/boot/daemon-multi-llm-runtime.ts +14 -8
  522. package/src/boot/daemon-prompt-turn.ts +2 -0
  523. package/src/boot/daemon-runtime.ts +36 -14
  524. package/src/boot/daemon-tools/index.ts +16 -0
  525. package/src/boot/daemon-tools/self-implement.ts +4 -0
  526. package/src/boot/daemon-tools/types.ts +3 -0
  527. package/src/browser-cdp/chrome-flags.ts +7 -0
  528. package/src/browser-cdp/client.ts +2 -0
  529. package/src/browser-pane/mount.ts +1 -246
  530. package/src/budget/codex-reset-credit-state.ts +15 -0
  531. package/src/budget/fetchers/codex.ts +2 -1
  532. package/src/budget/run-usage-rollup.ts +11 -4
  533. package/src/budget/unified-usage.ts +2 -1
  534. package/src/capture/tui-self-report.ts +10 -0
  535. package/src/channel-bot-token.ts +126 -0
  536. package/src/chat/index.ts +21 -45
  537. package/src/chat/input-text-key.ts +2 -2
  538. package/src/chat/mode/manual.ts +2 -4
  539. package/src/chat/pickers/state.ts +10 -27
  540. package/src/chat/search/modal.ts +14 -2
  541. package/src/chat/tool-render/types.ts +1 -1
  542. package/src/chat/turn-typeahead.ts +2 -1
  543. package/src/chat/wrap.ts +6 -8
  544. package/src/cli/__fixtures__/agent-help-before/agent.txt +18 -0
  545. package/src/cli/__fixtures__/agent-help-before/registry.txt +13 -0
  546. package/src/cli/__fixtures__/agent-help-before/root.txt +100 -0
  547. package/src/cli/__fixtures__/agent-help-before/tier.txt +15 -0
  548. package/src/cli/a2a-cli.ts +52 -0
  549. package/src/cli/agent-cli.ts +721 -0
  550. package/src/cli/autopilot-cli.ts +739 -0
  551. package/src/cli/bg-launch.ts +20 -4
  552. package/src/cli/claude-plugin-setup.ts +199 -0
  553. package/src/cli/config-test-sync.ts +94 -10
  554. package/src/cli/connector-cli.ts +204 -0
  555. package/src/cli/control-cli.ts +220 -0
  556. package/src/cli/control-join-cli.ts +142 -0
  557. package/src/cli/docs-cli.ts +38 -0
  558. package/src/cli/doctor-cli.ts +225 -26
  559. package/src/cli/doctor-distro.ts +17 -1
  560. package/src/cli/doctor-fix.ts +145 -17
  561. package/src/cli/doctor-llm-assist.ts +71 -0
  562. package/src/cli/doctor-private-files.ts +66 -0
  563. package/src/cli/doctor-readiness.ts +8 -5
  564. package/src/cli/fleet-cli.ts +63 -0
  565. package/src/cli/g6a-registration-probe.ts +16 -0
  566. package/src/cli/git-install-plan.ts +51 -0
  567. package/src/cli/hooks-cli.ts +44 -0
  568. package/src/cli/ingest-token-cli.ts +21 -0
  569. package/src/cli/intake-cli.ts +416 -0
  570. package/src/cli/labels-cli.ts +74 -0
  571. package/src/cli/leader-cli.ts +10 -159
  572. package/src/cli/live-cli.ts +48 -0
  573. package/src/cli/llm-detect-cli.ts +130 -0
  574. package/src/cli/logs-cli.ts +231 -7
  575. package/src/cli/machine-cli.ts +38 -0
  576. package/src/cli/mcp-call.ts +43 -13
  577. package/src/cli/mcp-gateway-cli.ts +90 -0
  578. package/src/cli/mcp-login.ts +116 -8
  579. package/src/cli/mcp-reload.ts +20 -3
  580. package/src/cli/nexus-dist.ts +18 -13
  581. package/src/cli/nexus-ios-bind.ts +20 -7
  582. package/src/cli/ops-cli.ts +225 -0
  583. package/src/cli/plugin-cli.ts +103 -0
  584. package/src/cli/pod-cli.ts +83 -0
  585. package/src/cli/port-lease-local.ts +124 -0
  586. package/src/cli/pr-cli.ts +12 -1
  587. package/src/cli/provider-cli.ts +720 -0
  588. package/src/cli/pty-record-cli.ts +63 -0
  589. package/src/cli/pty-takeover-cli.ts +57 -40
  590. package/src/cli/pty-web-address.ts +52 -0
  591. package/src/cli/publish-cli.ts +44 -0
  592. package/src/cli/pwa-build.ts +18 -12
  593. package/src/cli/pwa-dev.ts +13 -8
  594. package/src/cli/pwa-registry.ts +6 -0
  595. package/src/cli/pwa-share.ts +65 -22
  596. package/src/cli/pwa-show.ts +20 -4
  597. package/src/cli/pwa-start.ts +99 -27
  598. package/src/cli/pwa-test.ts +201 -96
  599. package/src/cli/release-cli.ts +90 -7
  600. package/src/cli/remotes-cli.ts +20 -1
  601. package/src/cli/remotes.ts +2 -1
  602. package/src/cli/repo-cli.ts +315 -36
  603. package/src/cli/research-cli.ts +66 -0
  604. package/src/cli/role-cli.ts +320 -0
  605. package/src/cli/schedule-cli.ts +246 -0
  606. package/src/cli/self-update.ts +98 -10
  607. package/src/cli/setup-cli.ts +64 -2
  608. package/src/cli/shadow-cli.ts +188 -0
  609. package/src/cli/share-auto-mount.ts +12 -8
  610. package/src/cli/start-cli.ts +221 -0
  611. package/src/cli/stdout-flush.ts +8 -0
  612. package/src/cli/storage-cli.ts +334 -0
  613. package/src/cli/tailscale-serve.ts +34 -19
  614. package/src/cli/tasks-cli.ts +176 -0
  615. package/src/cli/test-state-dir-flag.ts +1 -1
  616. package/src/cli/usage-cli.ts +15 -4
  617. package/src/cli/where-cli.ts +22 -55
  618. package/src/code-edit/diff-render.ts +6 -32
  619. package/src/code-edit/source-delta-browser.ts +0 -1
  620. package/src/codex/models.ts +1 -1
  621. package/src/config.ts +8 -13
  622. package/src/connectors/event-ledger.ts +41 -0
  623. package/src/connectors/linear-projector.ts +88 -0
  624. package/src/connectors/linear.ts +143 -0
  625. package/src/connectors/types.ts +19 -0
  626. package/src/control-plane/lease-holder.ts +41 -0
  627. package/src/control-plane/ledger.ts +146 -0
  628. package/src/control-plane/light-member.ts +164 -0
  629. package/src/control-plane/member-tokens.ts +88 -0
  630. package/src/control-plane/member.ts +159 -0
  631. package/src/control-plane/port-lease-heartbeat.ts +101 -0
  632. package/src/control-plane/ports.ts +40 -0
  633. package/src/control-plane/primary.ts +169 -0
  634. package/src/control-plane/server.ts +216 -0
  635. package/src/dashboard/acp-boot.ts +11 -38
  636. package/src/dashboard/assistant-render-state-runtime.ts +2 -2
  637. package/src/dashboard/assistant-sample-runtime.ts +2 -2
  638. package/src/dashboard/auto-compact-runtime.ts +11 -16
  639. package/src/dashboard/browser-help-runtime.ts +2 -3
  640. package/src/dashboard/chat/acp-chat.ts +2 -5
  641. package/src/dashboard/code-edit-post-turn-runtime.ts +1 -2
  642. package/src/dashboard/compact-surface-assembly.ts +0 -14
  643. package/src/dashboard/compact-surface-dispatch.ts +1 -38
  644. package/src/dashboard/compact-surface-inventory.ts +0 -8
  645. package/src/dashboard/compact-surface-runtime.ts +0 -14
  646. package/src/dashboard/context-menu-provider-boot.ts +0 -9
  647. package/src/dashboard/context-window-runtime-boot.ts +0 -37
  648. package/src/dashboard/index.ts +278 -2558
  649. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +0 -6
  650. package/src/dashboard/input/chat-main-slash-command.ts +2 -2
  651. package/src/dashboard/input/dashboard-priority-key-route.ts +1 -43
  652. package/src/dashboard/input/mouse-modal-surface-runtime.ts +1 -5
  653. package/src/dashboard/input/mouse-wiring.ts +2 -3
  654. package/src/dashboard/layout-display-runtime-registration.ts +0 -10
  655. package/src/dashboard/modals/pane-multi.ts +1 -1
  656. package/src/dashboard/replay-preview.ts +1 -1
  657. package/src/dashboard/runtime/approvers.ts +0 -1
  658. package/src/dashboard/runtime/state-snapshot.ts +0 -90
  659. package/src/dashboard/scenario-runtime-boot.ts +16 -16
  660. package/src/dashboard/slash-runtime/dashboard-handlers.ts +134 -1456
  661. package/src/dashboard/slash-runtime/design-pick.ts +96 -0
  662. package/src/dashboard/slash-runtime/help-from-registry.ts +77 -0
  663. package/src/dashboard/surface-registry-wiring.ts +2 -15
  664. package/src/dashboard/turn-message-runtime.ts +0 -4
  665. package/src/dashboard/turn-preamble.ts +1 -1
  666. package/src/dashboard/turn-stream-formatter.ts +2 -2
  667. package/src/dashboard/turn-stream-runtime.ts +2 -2
  668. package/src/dashboard-pane-context-menu.ts +0 -14
  669. package/src/debug/log.ts +7 -0
  670. package/src/decide/boundary-shadow.ts +131 -0
  671. package/src/design/apply-direction.ts +209 -0
  672. package/src/design/css-root-tokens.ts +89 -0
  673. package/src/design/custom-system-create.ts +230 -0
  674. package/src/design/design-directions.ts +61 -41
  675. package/src/design/design-gate.ts +241 -0
  676. package/src/design/design-library.ts +57 -0
  677. package/src/design/design-previews.ts +138 -0
  678. package/src/design/design-systems.ts +61 -0
  679. package/src/design/lint-artifact-run.ts +46 -6
  680. package/src/design/lint-artifact.ts +5 -1
  681. package/src/design/open-design-client.ts +247 -0
  682. package/src/design/system-from-extract.ts +767 -0
  683. package/src/design/system-schema.ts +123 -0
  684. package/src/discord-slash-wire.ts +2 -1
  685. package/src/discord-test-runner.ts +2 -1
  686. package/src/discord-voice-wire.ts +2 -1
  687. package/src/discord.ts +1 -1
  688. package/src/dispatch/opportunistic-launcher.ts +24 -1
  689. package/src/domains/ops-status.ts +35 -2
  690. package/src/domains/outbound-alert.ts +16 -4
  691. package/src/domains/repeated-failure.ts +89 -0
  692. package/src/domains/schedule-manage-tool.ts +28 -8
  693. package/src/domains/schedule-migrate.ts +22 -4
  694. package/src/domains/schedule-registry.ts +88 -33
  695. package/src/domains/schedule-runs.ts +132 -0
  696. package/src/domains/schedule-state.ts +152 -0
  697. package/src/element-registry/address.ts +1 -3
  698. package/src/git-fs/gh-cli.ts +47 -17
  699. package/src/git-fs/retry.ts +1 -0
  700. package/src/git-fs/runner.ts +1 -0
  701. package/src/git-fs/worktree.ts +6 -5
  702. package/src/github/pr-labels.ts +68 -0
  703. package/src/graph-kinds/plugin-nodes.ts +60 -0
  704. package/src/graph-kinds/registry.ts +118 -0
  705. package/src/graph-runner/graph-cli.ts +103 -0
  706. package/src/graph-runner/graph-notify.ts +220 -0
  707. package/src/graph-runner/graph-tick.ts +119 -0
  708. package/src/graph-runner/release-manifest.ts +93 -0
  709. package/src/graph-runner/runner.ts +457 -0
  710. package/src/grok/credential.ts +158 -5
  711. package/src/grounding/ensure-grounding.ts +131 -0
  712. package/src/grounding/mirror-export.ts +89 -0
  713. package/src/grounding/mirror-manifest.ts +252 -0
  714. package/src/grounding/sources-cli.ts +209 -0
  715. package/src/grounding/sources.ts +333 -0
  716. package/src/grounding/token.ts +115 -0
  717. package/src/harness/harness-cli-command.ts +352 -19
  718. package/src/harness/harness-pod-dispatch.ts +110 -0
  719. package/src/harness/harness-stop.ts +131 -0
  720. package/src/harness/harness-substrate-default.ts +40 -0
  721. package/src/harness/harness-worktrees.ts +1 -1
  722. package/src/harness/harness-write-boundary.ts +2 -0
  723. package/src/harness/llm-decompose.ts +2 -1
  724. package/src/harness/self-send-decide.ts +224 -0
  725. package/src/harness/shell-relay.ts +5 -0
  726. package/src/hooks/providers.ts +77 -0
  727. package/src/hooks/queue.ts +73 -0
  728. package/src/hooks/receiver.ts +133 -0
  729. package/src/index.ts +666 -3406
  730. package/src/input-core/dispatcher.ts +1 -1
  731. package/src/input-core/drag-esc-interceptor.ts +1 -1
  732. package/src/instance/current.ts +5 -5
  733. package/src/instance/leader.ts +10 -326
  734. package/src/instance/nexus-run-refusal.ts +27 -92
  735. package/src/instance/project-local-exclude.ts +27 -0
  736. package/src/instance/resolve.ts +40 -175
  737. package/src/intake-plane/capture.ts +14 -1
  738. package/src/intake-plane/check.ts +34 -14
  739. package/src/intake-plane/collect-github.ts +258 -0
  740. package/src/intake-plane/collect-pod.ts +100 -0
  741. package/src/intake-plane/collect-telegram-saved.ts +86 -0
  742. package/src/intake-plane/digest.ts +102 -0
  743. package/src/intake-plane/enrich-plugins.ts +1 -1
  744. package/src/intake-plane/front-classifier.ts +56 -0
  745. package/src/intake-plane/front-route-classifier.ts +80 -0
  746. package/src/intake-plane/front-route-rules.ts +152 -0
  747. package/src/intake-plane/grounding-docs.ts +185 -0
  748. package/src/intake-plane/harness-target.ts +20 -0
  749. package/src/intake-plane/intake-to-tasks.ts +303 -0
  750. package/src/intake-plane/items.ts +247 -0
  751. package/src/intake-plane/link-ledger.ts +27 -0
  752. package/src/intake-plane/route.ts +104 -0
  753. package/src/intake-plane/runtime-callables.ts +3 -1
  754. package/src/intake-plane/sketch-ledger.ts +34 -0
  755. package/src/intake-plane/slash.ts +30 -2
  756. package/src/intake-plane/submit-intake-work.ts +160 -0
  757. package/src/intake-plane/telegram-work.ts +56 -0
  758. package/src/iul/sidebar-shell.ts +0 -165
  759. package/src/launch-head/capability-check.ts +162 -0
  760. package/src/launch-head/launch-head-cli.ts +242 -0
  761. package/src/launch-head/load-balance.ts +81 -0
  762. package/src/live/detail-switch.ts +175 -0
  763. package/src/llm/provider-detect.ts +247 -0
  764. package/src/llm/provider-probe.ts +57 -0
  765. package/src/llm.ts +55 -23
  766. package/src/log-entry.ts +1 -1
  767. package/src/log-pane/attachment-popup.ts +1 -2
  768. package/src/loops/loop-cli.ts +37 -0
  769. package/src/loops/registry.ts +174 -0
  770. package/src/market/official-keys.ts +5 -0
  771. package/src/market/publish.ts +273 -0
  772. package/src/market/signed-index.ts +156 -0
  773. package/src/market/tgz.ts +121 -0
  774. package/src/mcp/client.ts +1 -1
  775. package/src/mcp/mcp-oauth.ts +40 -5
  776. package/src/mcp/server.ts +75 -7
  777. package/src/mcp-gateway/gateway.ts +128 -0
  778. package/src/mcp-gateway/pat-store.ts +124 -0
  779. package/src/mss/logging/log-store.ts +91 -2
  780. package/src/mss/logging/scoped-level.ts +5 -9
  781. package/src/native-tool-catalog.ts +64 -343
  782. package/src/nexus/api/connect-info.ts +23 -25
  783. package/src/nexus/api/context-url.ts +1 -1
  784. package/src/nexus/api/design-check.ts +90 -59
  785. package/src/nexus/api/design-previews-route.ts +182 -0
  786. package/src/nexus/api/design-system-create-route.ts +123 -0
  787. package/src/nexus/api/graph-kinds.ts +69 -0
  788. package/src/nexus/api/graphs-api.ts +221 -0
  789. package/src/nexus/api/harness-api.ts +31 -2
  790. package/src/nexus/api/health.ts +15 -0
  791. package/src/nexus/api/http-server.ts +274 -43
  792. package/src/nexus/api/image-generate.ts +3 -0
  793. package/src/nexus/api/ingest-token.ts +175 -0
  794. package/src/nexus/api/intake-ledger-api.ts +54 -0
  795. package/src/nexus/api/intake-route.ts +111 -0
  796. package/src/nexus/api/json-response.ts +33 -0
  797. package/src/nexus/api/live-detail.ts +47 -0
  798. package/src/nexus/api/live-shipped.ts +78 -0
  799. package/src/nexus/api/log-fabric.ts +33 -2
  800. package/src/nexus/api/markdown-publish.ts +3 -2
  801. package/src/nexus/api/mcp-http.ts +14 -9
  802. package/src/nexus/api/mcp-oauth-hint.ts +30 -0
  803. package/src/nexus/api/mcp-public-allowlist.ts +33 -0
  804. package/src/nexus/api/merge-approvals-gate.ts +79 -0
  805. package/src/nexus/api/merge-approvals.ts +306 -0
  806. package/src/nexus/api/meta-api.ts +4 -0
  807. package/src/nexus/api/next-fluent-wiring.ts +7 -9
  808. package/src/nexus/api/plugins-market.ts +125 -0
  809. package/src/nexus/api/pod-credential-api.ts +133 -0
  810. package/src/nexus/api/public-routes.ts +80 -0
  811. package/src/nexus/api/rest-route-paths.ts +15 -0
  812. package/src/nexus/api/schedules-action.ts +12 -3
  813. package/src/nexus/api/schedules-read.ts +228 -0
  814. package/src/nexus/api/sessions-store.ts +8 -2
  815. package/src/nexus/api/setup-answer-priority.ts +130 -0
  816. package/src/nexus/api/setup-channel-bot.ts +56 -0
  817. package/src/nexus/api/setup-child-llm.ts +228 -0
  818. package/src/nexus/api/setup-obsidian-skills.ts +93 -0
  819. package/src/nexus/api/task-cards-api.ts +34 -0
  820. package/src/nexus/api/tasks-create.ts +136 -0
  821. package/src/nexus/api/telegram-trigger-bot.ts +3 -3
  822. package/src/nexus/api/terminals.ts +204 -18
  823. package/src/nexus/api/trace.ts +354 -0
  824. package/src/nexus/api/vault-api.ts +140 -7
  825. package/src/nexus/api/worktrees.ts +18 -2
  826. package/src/nexus/boot/register-mcp-clients.ts +38 -4
  827. package/src/nexus/daemon-endpoint.ts +85 -0
  828. package/src/nexus/default-port.ts +1 -0
  829. package/src/nexus/index.ts +329 -111
  830. package/src/nexus/onboarding/pwa-share-prompt.ts +31 -8
  831. package/src/nexus/onboarding/tailscale-probe.ts +9 -1
  832. package/src/nexus/setup-status.ts +58 -0
  833. package/src/nexus/supervisor/lock.ts +8 -0
  834. package/src/nexus/webterm/pty.ts +15 -0
  835. package/src/oauth/codex-account-rotation.ts +122 -16
  836. package/src/oauth/codex-account-store.ts +88 -19
  837. package/src/oauth/codex-quota-policy.ts +55 -0
  838. package/src/oauth/store.ts +28 -25
  839. package/src/obsidian/default-vault.ts +17 -0
  840. package/src/obsidian/vault-write-guard.ts +46 -0
  841. package/src/onboarding/help/llm.md +2 -2
  842. package/src/onboarding.ts +2 -2
  843. package/src/panes/alt-skip-predicate.ts +4 -3
  844. package/src/panes/external-terminal-pane.ts +3 -4
  845. package/src/panes/factory.ts +1 -18
  846. package/src/panes/index.ts +1 -5
  847. package/src/panes/pane-cycle.ts +1 -1
  848. package/src/panes/types.ts +1 -1
  849. package/src/platform/env-literal.ts +4 -0
  850. package/src/plugin-hooks/dispatcher.ts +10 -4
  851. package/src/plugins/core/host.ts +94 -4
  852. package/src/plugins/core/manifest.ts +104 -7
  853. package/src/plugins/install/market-fetch.ts +249 -0
  854. package/src/plugins/install/plugin-install.ts +387 -0
  855. package/src/policy/claude-subscription-guard.ts +25 -0
  856. package/src/preview/terminal.ts +24 -1
  857. package/src/preview-pane/mount.ts +1 -142
  858. package/src/prompt/references.ts +4 -51
  859. package/src/pty-shell/pty-control-ipc.ts +57 -3
  860. package/src/pty-shell/pty-mouse.ts +75 -0
  861. package/src/pty-shell/pty-recording.ts +108 -0
  862. package/src/pty-shell/registry.ts +53 -3
  863. package/src/python/resolve-python.ts +1 -1
  864. package/src/release-loop/manifest.ts +65 -0
  865. package/src/release-loop/release-note.ts +174 -0
  866. package/src/roles/lease-cas.ts +52 -0
  867. package/src/roles/machine-name.ts +48 -0
  868. package/src/roles/machine-profile.ts +65 -0
  869. package/src/roles/role-lease-read.ts +81 -0
  870. package/src/roles/role-lease.ts +63 -0
  871. package/src/roles/role-watch.ts +69 -0
  872. package/src/self-dev/ask-launch-flow.ts +39 -22
  873. package/src/self-dev/ask-launch-io.ts +1 -1
  874. package/src/self-dev/dev-cli.ts +250 -139
  875. package/src/self-dev/dev-pipeline.ts +80 -8
  876. package/src/self-dev/draft-sweep.ts +231 -0
  877. package/src/self-dev/draft-triage-rules.ts +42 -0
  878. package/src/self-dev/entrance-baseline.ts +156 -4
  879. package/src/self-dev/fabric-decompose-adapter.ts +10 -0
  880. package/src/self-dev/launch-preflight.ts +1 -1
  881. package/src/self-dev/orchestrate.ts +297 -20
  882. package/src/self-dev/repair-signals.ts +6 -0
  883. package/src/self-dev/run-store.ts +20 -5
  884. package/src/self-dev/run-supervisor.ts +43 -3
  885. package/src/self-implement/abandoned-classification.ts +15 -1
  886. package/src/self-implement/blocked-draft-policy.ts +6 -0
  887. package/src/self-implement/budget-gate.ts +236 -0
  888. package/src/self-implement/child-llm-preference.ts +84 -0
  889. package/src/self-implement/decision-events.ts +57 -0
  890. package/src/self-implement/decision-signal-press.ts +5 -2
  891. package/src/self-implement/dependency-change-gate.ts +90 -0
  892. package/src/self-implement/gate-baseline.ts +32 -1
  893. package/src/self-implement/gate-cli.ts +29 -7
  894. package/src/self-implement/gate-scope.ts +7 -1
  895. package/src/self-implement/goal-author-decompose.ts +22 -4
  896. package/src/self-implement/goal-author.ts +23 -2
  897. package/src/self-implement/goal-boundary.ts +65 -0
  898. package/src/self-implement/goal-clarification-escalation.ts +1 -0
  899. package/src/self-implement/goal-documents-dir.ts +6 -1
  900. package/src/self-implement/goal-execution-records.ts +58 -0
  901. package/src/self-implement/goal-run-store.ts +42 -24
  902. package/src/self-implement/graph-authority.ts +13 -28
  903. package/src/self-implement/graph-catalog.ts +48 -0
  904. package/src/self-implement/graph-run-contract.ts +127 -0
  905. package/src/self-implement/graph-templates.ts +14 -7
  906. package/src/self-implement/graph-yaml.ts +35 -6
  907. package/src/self-implement/harness-policy-gates.ts +42 -0
  908. package/src/self-implement/headless-elanous-driver.ts +30 -6
  909. package/src/self-implement/heal-triage.ts +229 -0
  910. package/src/self-implement/host-regate.ts +240 -0
  911. package/src/self-implement/non-git-consent.ts +23 -0
  912. package/src/self-implement/orchestrator.ts +481 -132
  913. package/src/self-implement/pipeline-shape.ts +1 -1
  914. package/src/self-implement/pr-evidence-artifact.ts +6 -19
  915. package/src/self-implement/prior-draft-findings.ts +128 -0
  916. package/src/self-implement/pwa-import-graph.ts +65 -0
  917. package/src/self-implement/repo-provision.ts +18 -21
  918. package/src/self-implement/report-origin.ts +39 -0
  919. package/src/self-implement/rework-policy.ts +21 -0
  920. package/src/self-implement/run-ledger-compact.ts +438 -0
  921. package/src/self-implement/run-ledger.ts +212 -29
  922. package/src/self-implement/run-report.ts +24 -0
  923. package/src/self-implement/run-status-mapping.ts +2 -0
  924. package/src/self-implement/running-runs.ts +112 -14
  925. package/src/self-implement/scoped-typecheck-config.ts +49 -0
  926. package/src/self-implement/seams.ts +203 -38
  927. package/src/self-implement/self-implement-cli.ts +17 -2
  928. package/src/self-implement/shadow-repo.ts +350 -0
  929. package/src/self-implement/supervision-vocabulary.ts +7 -0
  930. package/src/shell-runner/dispatch.ts +3 -0
  931. package/src/shell-runner/index.ts +0 -7
  932. package/src/skills/runner.ts +0 -69
  933. package/src/skills/tools/agent-room-slash.ts +2 -1
  934. package/src/skills/tools/agent-room.ts +8 -140
  935. package/src/skills/tools/agent.ts +5 -3
  936. package/src/skills/tools/context.ts +5 -140
  937. package/src/skills/tools/control.ts +4 -188
  938. package/src/skills/tools/dashboard-slash.ts +3 -11
  939. package/src/skills/tools/dashboard-state.ts +3 -5
  940. package/src/skills/tools/dev-harness.ts +3 -2
  941. package/src/skills/tools/omni-search.ts +29 -1
  942. package/src/skills/tools/shell.ts +11 -29
  943. package/src/skills/tools/spawn-coding-agent-headless.ts +6 -9
  944. package/src/ssh/ssh-picker-modal.ts +1 -1
  945. package/src/steward/directive.ts +99 -0
  946. package/src/steward/triage.ts +203 -0
  947. package/src/storage/cli-bin.ts +67 -0
  948. package/src/storage/object-store-visibility.ts +169 -0
  949. package/src/storage/object-store.ts +452 -0
  950. package/src/storage/s3.ts +53 -10
  951. package/src/storage/storage-detect.ts +337 -0
  952. package/src/surface/address.ts +3 -5
  953. package/src/surface/index.ts +0 -6
  954. package/src/surface/llm-tools.ts +1 -2
  955. package/src/surface/shell-runner-boot.ts +4 -89
  956. package/src/task-cards/card-cli.ts +64 -0
  957. package/src/task-cards/card-store.ts +241 -0
  958. package/src/task-orchestrator/boot.ts +27 -1
  959. package/src/task-orchestrator/dispatcher.ts +49 -7
  960. package/src/task-orchestrator/external-fingerprint.ts +10 -0
  961. package/src/task-orchestrator/external-policy.ts +86 -0
  962. package/src/task-orchestrator/feedback-loop.ts +4 -2
  963. package/src/task-orchestrator/graph.ts +18 -1
  964. package/src/task-orchestrator/runtimes/create.ts +128 -0
  965. package/src/task-orchestrator/store.ts +78 -18
  966. package/src/task-orchestrator/surface-registry.ts +5 -2
  967. package/src/task-orchestrator/surfaces/external-exec.ts +180 -0
  968. package/src/task-orchestrator/surfaces/idea-approval-pr.ts +118 -0
  969. package/src/task-orchestrator/surfaces/index.ts +4 -3
  970. package/src/task-orchestrator/surfaces/pod-account-broker.ts +60 -5
  971. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +136 -0
  972. package/src/task-orchestrator/surfaces/pod-command-job.ts +348 -0
  973. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +177 -0
  974. package/src/task-orchestrator/surfaces/pod-pool.ts +128 -12
  975. package/src/task-orchestrator/surfaces/pod-skills.ts +11 -3
  976. package/src/task-orchestrator/surfaces/pod-source-bundle.ts +132 -0
  977. package/src/task-orchestrator/surfaces/pod-source-receive.ts +91 -0
  978. package/src/task-orchestrator/surfaces/pod-source-spec.ts +77 -0
  979. package/src/task-orchestrator/surfaces/self-implement-pod.ts +782 -41
  980. package/src/task-orchestrator/surfaces/self-implement.ts +8 -1
  981. package/src/task-orchestrator/tox-loop.ts +204 -0
  982. package/src/task-orchestrator/types.ts +21 -1
  983. package/src/telegram-commands.ts +8 -0
  984. package/src/telegram-report.ts +2 -1
  985. package/src/telegram-run.ts +18 -5
  986. package/src/telegram.ts +92 -22
  987. package/src/tool-runtime/acp-session-runtime.ts +28 -7
  988. package/src/tool-runtime/agent-runtime.ts +1 -0
  989. package/src/tool-runtime/context-runtime.ts +18 -35
  990. package/src/tool-runtime/control-runtime.ts +8 -21
  991. package/src/tool-runtime/dashboard-state-runtime.ts +1 -5
  992. package/src/tool-runtime/elanous-asana-runtimes.ts +205 -0
  993. package/src/tool-runtime/elanous-control-runtimes.ts +16 -2
  994. package/src/tool-runtime/elanous-task-submit-runtime.ts +124 -0
  995. package/src/tool-runtime/index.ts +4 -1
  996. package/src/tool-runtime/scenario-runtimes.ts +22 -21
  997. package/src/tool-runtime/scenario-target-mount.ts +6 -32
  998. package/src/tool-runtime/types.ts +8 -0
  999. package/src/tui/chat/attachment-summary.ts +4 -4
  1000. package/src/tui-client/headless-core-guard.ts +0 -1
  1001. package/src/tui.ts +8 -5
  1002. package/src/typecheck-ratchet.ts +15 -0
  1003. package/src/ui/hover-presenter.ts +3 -7
  1004. package/src/user-config.ts +427 -190
  1005. package/src/version/code-revision.ts +33 -8
  1006. package/src/version/packed-revision.json +1 -1
  1007. package/src/video-pipeline/broll-agent.ts +102 -0
  1008. package/src/video-pipeline/recipes/broll.ts +263 -0
  1009. package/src/video-pipeline/walk-line.ts +2 -1
  1010. package/src/views/scratch-image-size.ts +10 -0
  1011. package/src/voice/channel-adapters/pwa-voice-adapter.ts +2 -18
  1012. package/src/voice/channel-adapters/telegram-voice-adapter.ts +1 -6
  1013. package/src/voice/voice-tts-singleton.ts +46 -8
  1014. package/src/web-push/vapid-keys.ts +1 -1
  1015. package/src/web-search/index.ts +5 -5
  1016. package/src/web-terminal/preview-tap-registry.ts +152 -43
  1017. package/src/workflow-runtime/executor.ts +18 -22
  1018. package/src/workflow-runtime/node-catalog.ts +20 -1
  1019. package/src/workflow-runtime/nodes/bash.ts +1 -0
  1020. package/src/workflow-runtime/nodes/task.ts +74 -0
  1021. package/src/workflow-runtime/nodes/triggers.ts +24 -1
  1022. package/src/workflow-runtime/plugin-kind-node.ts +138 -0
  1023. package/src/workflow-runtime/schema.ts +98 -2
  1024. package/src/workflow-runtime/triggers/webhook-router.ts +43 -3
  1025. package/src/workflow-runtime/triggers/webhook-source.ts +19 -1
  1026. package/src/workflow-runtime/types.ts +74 -4
  1027. package/apps/pwa/out/_next/static/Ksn99fVf2HUWhSyV1-FC8/_buildManifest.js +0 -1
  1028. package/apps/pwa/out/_next/static/chunks/1176-4943bd83b00e53a2.js +0 -25
  1029. package/apps/pwa/out/_next/static/chunks/1380-9c652e1002032c86.js +0 -1
  1030. package/apps/pwa/out/_next/static/chunks/1863-2ea170dfec26b88b.js +0 -1
  1031. package/apps/pwa/out/_next/static/chunks/2091-2d6b7f4f16300f83.js +0 -1
  1032. package/apps/pwa/out/_next/static/chunks/2347-366617ec73babe3b.js +0 -1
  1033. package/apps/pwa/out/_next/static/chunks/2598.814f64e3268634e7.js +0 -1
  1034. package/apps/pwa/out/_next/static/chunks/3089-e60cc8f5d35ee239.js +0 -1
  1035. package/apps/pwa/out/_next/static/chunks/3158-c77ed9ea34f9cc9f.js +0 -1
  1036. package/apps/pwa/out/_next/static/chunks/3607-f0b5c5ee18fcf56a.js +0 -1
  1037. package/apps/pwa/out/_next/static/chunks/3659-05b2d5d971b42dbc.js +0 -1
  1038. package/apps/pwa/out/_next/static/chunks/3736-b6a7bfdcb8f56ec6.js +0 -1
  1039. package/apps/pwa/out/_next/static/chunks/3839-eebf298e89a7bb77.js +0 -1
  1040. package/apps/pwa/out/_next/static/chunks/4012.832a2824b978e7ee.js +0 -5
  1041. package/apps/pwa/out/_next/static/chunks/4706-d85d7f3345f3ff91.js +0 -1
  1042. package/apps/pwa/out/_next/static/chunks/526-17a6a2e0e6dc4498.js +0 -1
  1043. package/apps/pwa/out/_next/static/chunks/5508-676ac75f2757ad40.js +0 -1
  1044. package/apps/pwa/out/_next/static/chunks/5583-8a0317f4b8e68db9.js +0 -1
  1045. package/apps/pwa/out/_next/static/chunks/5927.8378481a12cc8044.js +0 -1
  1046. package/apps/pwa/out/_next/static/chunks/6258-b58f722b10e8d31d.js +0 -1
  1047. package/apps/pwa/out/_next/static/chunks/6820-32fd097e6186fdc9.js +0 -1
  1048. package/apps/pwa/out/_next/static/chunks/6852-983db7ca958634b7.js +0 -1
  1049. package/apps/pwa/out/_next/static/chunks/7235-e583e4a015e159b9.js +0 -1
  1050. package/apps/pwa/out/_next/static/chunks/7482-7b417330b24a996a.js +0 -1
  1051. package/apps/pwa/out/_next/static/chunks/7701-99b7d4dedb955bf8.js +0 -1
  1052. package/apps/pwa/out/_next/static/chunks/77f1928d-bd3777589042d3ea.js +0 -1
  1053. package/apps/pwa/out/_next/static/chunks/8366-36956cafc5e33614.js +0 -1
  1054. package/apps/pwa/out/_next/static/chunks/8370-23d0de995be666f8.js +0 -1
  1055. package/apps/pwa/out/_next/static/chunks/8617-307421f3b0e8b2a2.js +0 -1
  1056. package/apps/pwa/out/_next/static/chunks/8837-e45de46a9fedf1f5.js +0 -1
  1057. package/apps/pwa/out/_next/static/chunks/9058-0e8055a5ea3ebdd6.js +0 -1
  1058. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-84b84eca12acada4.js +0 -1
  1059. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-1f23568c29e88f7a.js +0 -1
  1060. package/apps/pwa/out/_next/static/chunks/app/botlab/page-bf6fc9aafd6135a7.js +0 -1
  1061. package/apps/pwa/out/_next/static/chunks/app/bots/page-3f8539ae4b719d2e.js +0 -1
  1062. package/apps/pwa/out/_next/static/chunks/app/chat/page-d2900febb74ecf32.js +0 -1
  1063. package/apps/pwa/out/_next/static/chunks/app/control/page-e82dec647dd79c36.js +0 -1
  1064. package/apps/pwa/out/_next/static/chunks/app/dashboard/page-096ec743a8ee955a.js +0 -1
  1065. package/apps/pwa/out/_next/static/chunks/app/design-check/page-255c2ceded4b3493.js +0 -1
  1066. package/apps/pwa/out/_next/static/chunks/app/healthz/route-84b84eca12acada4.js +0 -1
  1067. package/apps/pwa/out/_next/static/chunks/app/intake/page-2db61b2f9efba61f.js +0 -1
  1068. package/apps/pwa/out/_next/static/chunks/app/layout-e11ee17f221aaa9b.js +0 -1
  1069. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e075974e029ce4c4.js +0 -1
  1070. package/apps/pwa/out/_next/static/chunks/app/morning/page-ec5b68a9af3366a0.js +0 -1
  1071. package/apps/pwa/out/_next/static/chunks/app/not-found-986c177afb4adae6.js +0 -1
  1072. package/apps/pwa/out/_next/static/chunks/app/observatory/page-a72781461af2f2a3.js +0 -1
  1073. package/apps/pwa/out/_next/static/chunks/app/page-92781cbaafc487ad.js +0 -1
  1074. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2c14d2a1f2930f33.js +0 -1
  1075. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-22ee4bf8070b2b4d.js +0 -1
  1076. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9c06e4a8297942a8.js +0 -1
  1077. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d0cd32f6d373798f.js +0 -1
  1078. package/apps/pwa/out/_next/static/chunks/app/settings/page-0c1642018d87ebb8.js +0 -1
  1079. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-93e5e97d614df487.js +0 -1
  1080. package/apps/pwa/out/_next/static/chunks/app/setup/layout-84b84eca12acada4.js +0 -1
  1081. package/apps/pwa/out/_next/static/chunks/app/setup/page-b1ce871940d7393e.js +0 -1
  1082. package/apps/pwa/out/_next/static/chunks/app/share/page-ae154addf345febe.js +0 -1
  1083. package/apps/pwa/out/_next/static/chunks/app/showroom/page-90af3aa813d2053c.js +0 -1
  1084. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f3f962fda428a738.js +0 -1
  1085. package/apps/pwa/out/_next/static/chunks/app/term/page-1c1f7cc1d5def06d.js +0 -1
  1086. package/apps/pwa/out/_next/static/chunks/app/vault/page-09d4cbdaaacf06c1.js +0 -1
  1087. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e877b8e8ca90b27f.js +0 -1
  1088. package/apps/pwa/out/_next/static/chunks/app/workflows/page-71d902f463dea526.js +0 -1
  1089. package/apps/pwa/out/_next/static/chunks/app/workspace/page-40ea576cefa25fe6.js +0 -1
  1090. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a56a3f178c3831f6.js +0 -1
  1091. package/apps/pwa/out/_next/static/chunks/bcc499d1-804a270d878e0842.js +0 -1
  1092. package/apps/pwa/out/_next/static/chunks/framework-b25b7c5501c59b6d.js +0 -1
  1093. package/apps/pwa/out/_next/static/chunks/main-a9ec9da43387afff.js +0 -1
  1094. package/apps/pwa/out/_next/static/chunks/main-app-aa2c05954aaa6754.js +0 -1
  1095. package/apps/pwa/out/_next/static/chunks/pages/_app-bb3768fb4b84aebb.js +0 -1
  1096. package/apps/pwa/out/_next/static/chunks/pages/_error-2820ba75b87b2f5e.js +0 -1
  1097. package/apps/pwa/out/_next/static/chunks/webpack-58c73b145f189b1c.js +0 -1
  1098. package/apps/pwa/out/_next/static/css/effec8adf767aa75.css +0 -1
  1099. package/apps/pwa/out/dashboard/index.html +0 -1
  1100. package/apps/pwa/out/dashboard/index.txt +0 -26
  1101. package/src/acp/resident-shell.ts +0 -244
  1102. package/src/agent/spawn-local-llm-in-vw.ts +0 -240
  1103. package/src/dashboard/agent-spawn-tools-boot.ts +0 -14
  1104. package/src/dashboard/dock-picker-inventory.ts +0 -41
  1105. package/src/dashboard/goal-plan-hud-bridge.ts +0 -112
  1106. package/src/dashboard/hud-mirror.ts +0 -207
  1107. package/src/dashboard/input/mouse-dock-runtime.ts +0 -156
  1108. package/src/dashboard/input/mouse-hover-runtime.ts +0 -46
  1109. package/src/dashboard/input/mouse-pill-context-runtime.ts +0 -74
  1110. package/src/dashboard/input/mouse-workspace-restore-runtime.ts +0 -64
  1111. package/src/dashboard/input/scratch-actions.ts +0 -36
  1112. package/src/dashboard/input/virtual-window-key-router.ts +0 -24
  1113. package/src/dashboard/rich-scratch-viewers.ts +0 -77
  1114. package/src/dashboard/scratch-slash-runtime.ts +0 -36
  1115. package/src/dashboard/scratch-state-runtime.ts +0 -42
  1116. package/src/dashboard/scratch-widget-runtime.ts +0 -37
  1117. package/src/dashboard/sim-shell.ts +0 -313
  1118. package/src/dashboard/virtual-window-control-runtime.ts +0 -57
  1119. package/src/dashboard/virtual-window-help-runtime.ts +0 -113
  1120. package/src/dashboard/virtual-window-input-runtime.ts +0 -99
  1121. package/src/dashboard/virtual-window-mutation-runtime.ts +0 -102
  1122. package/src/dashboard/virtual-window-split-runtime.ts +0 -70
  1123. package/src/dashboard/vw-popup-openers.ts +0 -126
  1124. package/src/dashboard/window-picker-popup.ts +0 -74
  1125. package/src/dashboard/window-slash-runtime.ts +0 -108
  1126. package/src/dashboard/windowing/companion-slash.ts +0 -78
  1127. package/src/dashboard/windowing/fast-switch.ts +0 -138
  1128. package/src/dashboard/windowing/lifecycle.ts +0 -185
  1129. package/src/dashboard/windowing/virtual-windows.ts +0 -259
  1130. package/src/dashboard/windowing/visibility-chord.ts +0 -77
  1131. package/src/iul/resident-vw.ts +0 -55
  1132. package/src/panes/content-adapter.ts +0 -162
  1133. package/src/prompt/vw-reference.ts +0 -153
  1134. package/src/shell-runner/external-terminal-pane.ts +0 -157
  1135. package/src/sim/resident-vw.ts +0 -48
  1136. package/src/skills/tools/spawn-coding-agent-vw.ts +0 -181
  1137. package/src/skills/tools/virtual-windows.ts +0 -632
  1138. package/src/surface/adapters/window-surface-adapter.ts +0 -141
  1139. package/src/tool-runtime/layout-runtimes.ts +0 -81
  1140. package/src/tool-runtime/scenario-window-mount.ts +0 -207
  1141. package/src/views/ui-mode.ts +0 -100
  1142. package/src/virtual-window-context-menu.ts +0 -97
  1143. package/src/virtual-windows/addressing.ts +0 -195
  1144. package/src/virtual-windows/benchmark-preset.ts +0 -119
  1145. package/src/virtual-windows/event-bus.ts +0 -202
  1146. package/src/virtual-windows/layout/apply-planner.ts +0 -189
  1147. package/src/virtual-windows/layout/index.ts +0 -68
  1148. package/src/virtual-windows/layout/layout-commands.ts +0 -186
  1149. package/src/virtual-windows/layout/layout-tools.ts +0 -262
  1150. package/src/virtual-windows/layout/persistence.ts +0 -219
  1151. package/src/virtual-windows/layout/presets.ts +0 -114
  1152. package/src/virtual-windows/layout/restore-planner.ts +0 -223
  1153. package/src/virtual-windows/layout/serializer.ts +0 -197
  1154. package/src/virtual-windows/layout/tree.ts +0 -147
  1155. package/src/virtual-windows/layout/types.ts +0 -63
  1156. package/src/virtual-windows/layout-tree.ts +0 -389
  1157. package/src/virtual-windows/navigation.ts +0 -251
  1158. package/src/virtual-windows/pane-capture.ts +0 -142
  1159. package/src/virtual-windows/pane-content.ts +0 -611
  1160. package/src/virtual-windows/pane-spawner.ts +0 -278
  1161. package/src/virtual-windows/pty-tail-content.ts +0 -291
  1162. package/src/virtual-windows/resident-window.ts +0 -59
  1163. package/src/virtual-windows/secondary-action.ts +0 -25
  1164. package/src/virtual-windows/terminal-slot-content.ts +0 -165
  1165. package/src/virtual-windows/virtual-window.ts +0 -1301
  1166. package/src/virtual-windows/vw-local-input-target-popup.ts +0 -110
  1167. package/src/virtual-windows/vw-rename-modal.ts +0 -77
  1168. package/src/virtual-windows/vw-selector-popup.ts +0 -177
  1169. package/src/virtual-windows/window-registry.ts +0 -519
  1170. package/src/voice/channel-adapters/discord-voice-adapter.ts +0 -202
  1171. package/src/voice/voice-pwa-dispatch.ts +0 -245
  1172. package/src/window-picker-modal.ts +0 -135
  1173. /package/apps/pwa/out/_next/static/{Ksn99fVf2HUWhSyV1-FC8 → zoQX5iTvXOsIvCjxCe1Ji}/_ssgManifest.js +0 -0
  1174. /package/src/dashboard/{companion-slash-runtime.ts → companion-messages-runtime.ts} +0 -0
@@ -7,10 +7,11 @@
7
7
  // - 막히면 omni-crawl 자율 검색 → worktree 파일로 떨궈 codex 에 read 지시(TUI 멀티라인 회피)
8
8
  // - 증거 게이트(doc 존재 / tsc 0 / test pass)로 완료 판정 후 commit
9
9
  // 재사용: startPty(Bun 네이티브 PTY)·createWorktree·streamLLM·worktreeHasChanges·commitWorktree.
10
- import { execFileSync, spawnSync } from 'node:child_process';
10
+ import { execFileSync, spawnSync, spawn as spawnChild } from 'node:child_process';
11
11
  import { homedir } from 'node:os';
12
- import { existsSync, writeFileSync, mkdirSync, readdirSync, readFileSync, statSync } from 'node:fs';
13
- import { join } from 'node:path';
12
+ import { existsSync, writeFileSync, mkdirSync, readdirSync, readFileSync, statSync, readlinkSync, realpathSync, lstatSync } from 'node:fs';
13
+ import { createHash } from 'node:crypto';
14
+ import { join, relative, resolve, isAbsolute, sep } from 'node:path';
14
15
  import { startPty, mintPtyId, onPtyEvent, type PtyHandle, type StartOpts } from '../pty-shell/registry.js';
15
16
  import { withChildPtyIdentity } from '../agent/pty-identity.js';
16
17
  import { NESTED_AGENT_ENV_BLOCKLIST } from '../agent/nested-agent-env.js';
@@ -19,6 +20,8 @@ import { configuredWorktreeRoot } from '../user-config.js';
19
20
  import { worktreeHasChanges, commitWorktree, changedFiles } from '../self-implement/seams.js';
20
21
  import { streamLLM, type LLMMessage } from '../llm.js';
21
22
  import { debug } from '../debug/log.js';
23
+ import { emitDecision } from '../live/detail-switch.js';
24
+ import { resolvePtyWebAddress } from '../cli/pty-web-address.js';
22
25
  import { reemitPtyUsage } from '../budget/pty-usage-reemit.js';
23
26
  import { classifyAuthError } from '../oauth/codex.js';
24
27
  import type { FallbackStep } from '../oauth/fallback-chain.js';
@@ -29,10 +32,15 @@ import { createLlmControlBrain, type StreamLLMFn } from '../autopilot/llm-contro
29
32
  import { buildExecutorPtyRef, execSurfaceId } from '../self-implement/executor-contract.js';
30
33
  import { runWithControlObserve } from '../capture/control-observe-adapter.js';
31
34
  import { buildMissionProvision, sanitizeForPtyInput, type ProvisionRequest, type ProvisionResult } from './provision.js';
35
+ import { checkClaudeSubscription } from './claude-subscription.js';
36
+ import { handoffMission, waitForHumanLogin, type HandoffOperations } from './handoff.js';
37
+ import { runClaudeHeadless } from './claude-headless.js';
38
+ import { installPluginInsideAgent, type PluginRequest, type PluginDeps } from './in-agent-plugin.js';
32
39
  import { ensureRunId } from '../harness/harness-space.js';
33
40
  import { recordHarnessWorktreeProvenance } from '../harness/harness-worktree-add.js';
34
41
  import { resolveInstanceName } from '../instance-identity.js';
35
42
  import { getChannelBus } from '../terminal-matrix/index.js';
43
+ import { envLiteral } from '../platform/env-literal.js';
36
44
  import { publishSelfReportFrame } from '../capture/self-report-frame.js';
37
45
  import { buildExecutorSelfReportFrame } from '../self-implement/executor-frame.js';
38
46
  import { classifierFrameLines, classifyFrameState, type FrameState } from '../capture/frame-state-detect.js';
@@ -47,6 +55,52 @@ import type { IngestionEntry } from '../agent-substrate/execution/ingestion-poli
47
55
 
48
56
  const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
49
57
 
58
+ /** Terminate the PTY process and every descendant found before signalling it. */
59
+ export async function terminateMissionProcessTree(rootPid: number, deps: {
60
+ processTable?: () => string;
61
+ signal?: (pid: number, signal: NodeJS.Signals | 0) => void;
62
+ wait?: (ms: number) => Promise<void>;
63
+ } = {}): Promise<number[]> {
64
+ if (!Number.isSafeInteger(rootPid) || rootPid <= 0) return [];
65
+ const signal = deps.signal ?? ((pid, sig) => process.kill(pid, sig));
66
+ const processTable = deps.processTable ?? (() => execFileSync('ps', ['-eo', 'pid=,ppid='], { encoding: 'utf8' }));
67
+ const children = new Map<number, number[]>();
68
+ try {
69
+ for (const line of processTable().split('\n')) {
70
+ const match = line.trim().match(/^(\d+)\s+(\d+)$/);
71
+ if (!match) continue;
72
+ const pid = Number(match[1]);
73
+ const ppid = Number(match[2]);
74
+ if (!Number.isSafeInteger(pid) || !Number.isSafeInteger(ppid)) continue;
75
+ const siblings = children.get(ppid) ?? [];
76
+ siblings.push(pid);
77
+ children.set(ppid, siblings);
78
+ }
79
+ } catch (error) {
80
+ debug.log('agent-mission', 'process-tree-snapshot-failed', { rootPid, error: String(error) }, { level: 'warn' });
81
+ }
82
+ const visited = new Set<number>();
83
+ const order: number[] = [];
84
+ const collect = (pid: number): void => {
85
+ if (visited.has(pid)) return;
86
+ visited.add(pid);
87
+ for (const child of children.get(pid) ?? []) collect(child);
88
+ order.push(pid);
89
+ };
90
+ collect(rootPid);
91
+ for (const pid of order) {
92
+ try { signal(pid, 'SIGTERM'); } catch { /* The process may already have exited. */ }
93
+ }
94
+ await (deps.wait ?? sleep)(2000);
95
+ for (const pid of order) {
96
+ try {
97
+ signal(pid, 0);
98
+ signal(pid, 'SIGKILL');
99
+ } catch { /* The process has exited or is no longer accessible. */ }
100
+ }
101
+ return order;
102
+ }
103
+
50
104
  /** Bounded classifier-compatible screen tail retained with each screen observation. */
51
105
  export const SCREEN_LOG_TAIL_MAX_LINES = 10;
52
106
  /** Maximum code points retained for each logged screen-tail line. */
@@ -119,15 +173,45 @@ export const codexBackend: AgentBackend = {
119
173
  // ⚠️ "알려진 경로"까지의 보장 — CLI 가 새 과금 env 를 추가하면 추적 필요(flag/scrub drift 는 테스트로 감시).
120
174
 
121
175
  /** claude Code 백엔드 — --dangerously-skip-permissions(권한 자동)·구독(oauth) 모드.
122
- * scrub: API 키 + 대체 인증 토큰(ANTHROPIC_AUTH_TOKEN) + 프로바이더 스위치(Bedrock/Vertex) → oauth 로 좁힘.
123
- * CLAUDE_CODE_USE_BEDROCK/VERTEX 가 unset 이면 AWS/GCP creds 가 있어도 그 경로로 라우팅되지 않는다. */
176
+ * scrub: API 키 + 대체 인증 토큰(ANTHROPIC_AUTH_TOKEN) + 프로바이더 스위치(Bedrock/Vertex/Foundry) → oauth 로 좁힘.
177
+ * CLAUDE_CODE_USE_BEDROCK/VERTEX/FOUNDRY 가 unset 이면 다른 provider 의 creds 가 있어도 그 경로로 라우팅되지 않는다. */
124
178
  export const claudeBackend: AgentBackend = {
125
179
  name: 'claude',
126
180
  cmd: 'claude',
127
181
  args: ['--dangerously-skip-permissions'],
128
- scrubEnv: ['ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN', 'CLAUDE_CODE_USE_BEDROCK', 'CLAUDE_CODE_USE_VERTEX'],
182
+ // CLAUDE_CODE_OAUTH_TOKEN: a launching Claude Code session exports its own token; the child must use the
183
+ // machine's stored login, never the parent session's (09-29 🅞: status read `oauth_token` → «api-key» · 대표 R2).
184
+ scrubEnv: ['ANTHROPIC_API_KEY', 'ANTHROPIC_AUTH_TOKEN', 'CLAUDE_CODE_OAUTH_TOKEN', 'CLAUDE_CODE_USE_BEDROCK', 'CLAUDE_CODE_USE_VERTEX', 'CLAUDE_CODE_USE_FOUNDRY'],
185
+ // 🩸 09-29 S6: new worktree → «Accessing workspace … ❯ No, exit / Yes, I trust this folder». The default is «No», so
186
+ // the brain spent all 16 steps on this screen. Move to «Yes» (↓) then confirm (Enter) on the next observation —
187
+ // the worktree is an isolated tree elanous created (same reasoning as agy).
188
+ handleTrust: (screen, write) => {
189
+ const choice = claudeTrustChoice(screen);
190
+ if (choice === 'no-selected') { write('\x1b[B'); return true; }
191
+ if (choice === 'yes-selected') { write('\r'); return true; }
192
+ return false;
193
+ },
129
194
  };
130
195
 
196
+ /** claude reads «text + Enter» arriving in one chunk as a paste, so the Enter becomes a newline and nothing is sent
197
+ * (09-29 실물: three brain inputs piled up in the input box). Send the text, then Enter on its own a moment later. */
198
+ export function submitSeparately(inject: (text: string) => boolean, delay: (fn: () => void) => void = (fn) => { setTimeout(fn, 250); }): (text: string) => boolean {
199
+ return (text) => {
200
+ if (text.length < 2 || !/\r$/.test(text)) return inject(text);
201
+ if (!inject(text.slice(0, -1))) return false;
202
+ delay(() => { inject('\r'); });
203
+ return true;
204
+ };
205
+ }
206
+
207
+ /** claude 첫 화면의 폴더 신뢰 메뉴 — 어느 줄이 선택돼 있나(기본 선택 = «No, exit»). */
208
+ export function claudeTrustChoice(screen: string): 'no-selected' | 'yes-selected' | null {
209
+ if (!/Yes, I trust this folder/.test(screen) || !/(?:Accessing workspace|Quick safety check)/.test(screen)) return null;
210
+ if (/^\s*[❯>]\s*(?:\d+\.\s*)?Yes, I trust this folder/m.test(screen)) return 'yes-selected';
211
+ if (/^\s*[❯>]\s*(?:\d+\.\s*)?No, exit/m.test(screen)) return 'no-selected';
212
+ return null;
213
+ }
214
+
131
215
  /** gemini 백엔드 — ⭐ 실행체는 **Antigravity CLI(`agy`)** 다(대표 2026-08-18 결정).
132
216
  *
133
217
  * ⛔⭐⭐⭐ 왜 `gemini` 가 아닌가 — ***그 CLI 는 «죽었다»***(2026-08-19 라이브 실측):
@@ -153,8 +237,20 @@ export const geminiBackend: AgentBackend = {
153
237
  cmd: 'agy',
154
238
  args: ['--dangerously-skip-permissions'],
155
239
  scrubEnv: ['GEMINI_API_KEY', 'GOOGLE_API_KEY', 'GOOGLE_GENAI_USE_VERTEXAI', 'GOOGLE_APPLICATION_CREDENTIALS'],
240
+ // 🩸 09-27(agy 1.2.12): 새 워크트리마다 «Do you trust the contents of this project?» 메뉴가 먼저 뜨고 첫 줄이
241
+ // «> Yes, I trust this folder» 다. 처리가 없어 미션 문장이 이 메뉴로 들어가 사라졌고, 두뇌가 약 10분 뒤에야
242
+ // 다시 보냈다(탐침 run 06:03 → 06:13). 기본 선택(신뢰)을 Enter 로 고른다 — 워크트리는 elanous 가 만든 격리 트리다.
243
+ handleTrust: (screen, write) => {
244
+ if (agyNeedsTrust(screen)) { write('\r'); return true; }
245
+ return false;
246
+ },
156
247
  };
157
248
 
249
+ /** agy 첫 화면의 폴더 신뢰 메뉴(기본 선택 = 신뢰). */
250
+ export function agyNeedsTrust(screen: string): boolean {
251
+ return /Do you trust the contents of this project\?/.test(screen) && /Yes, I trust this folder/.test(screen);
252
+ }
253
+
158
254
  /** xAI grok Build CLI 백엔드 — --always-approve(전툴 자동승인)·구독(grok login) 모드.
159
255
  * scrub: XAI/GROK API 키 전부 → 남는 인증 = ~/.grok/auth.json(grok login oauth).
160
256
  * ⚠️ 바이너리는 xAI install.sh 가 ~/.grok/bin/grok 에 둔다 — cron/launchd 최소 PATH 에선 ensure-bin-path
@@ -339,8 +435,12 @@ export interface AgentMissionSpec {
339
435
  mission: string;
340
436
  /** repo 루트(기본: CWD 에서 resolveMainRepoRoot). */
341
437
  repo?: string;
342
- /** 새 worktree 브랜치명. */
343
- branch: string;
438
+ /** 새 worktree 브랜치명. workdir 모드에서는 관측 라벨(선택). */
439
+ branch?: string;
440
+ /** 저장소 worktree 대신 직접 실행할 비-git 작업 폴더. */
441
+ workdir?: string;
442
+ /** 호출자의 벽시계 마감/취소 신호. */
443
+ signal?: AbortSignal;
344
444
  /** 분기 base(기본 HEAD). 이전 미션 산출 위에 쌓으려면 그 브랜치명. */
345
445
  base?: string;
346
446
  /** 완료 증거 판정. */
@@ -355,6 +455,12 @@ export interface AgentMissionSpec {
355
455
  omniCrawlPath?: string;
356
456
  /** 구동할 에이전트 backend(기본 codexBackend). claude/gemini/grok 확장점. */
357
457
  agent?: AgentBackend;
458
+ /** Claude CLI 비대화형 stream-json 실행. 다른 backend 에서는 거부. */
459
+ headless?: boolean;
460
+ /** Install in the agent's own UI before sending the mission. */
461
+ plugin?: Pick<PluginRequest, 'plugin' | 'marketplace'>;
462
+ /** Explicit backend sequence; transitions use the same handoff coordinator as brain decisions. */
463
+ chain?: readonly ('codex' | 'claude' | 'elanous')[];
358
464
  /**
359
465
  * ★ elanous 내부 프롬프트 인핸싱(가산·anti-drift) — 원문 verbatim 보존 + 커버리지 체크리스트 부착.
360
466
  * 명시 override(undefined 면 entry 정책이 결정: elanous-apparatus→ON·external-verbatim→OFF·§6e capability 구동).
@@ -389,12 +495,16 @@ export type CodexMissionSpec = AgentMissionSpec;
389
495
  export interface AgentMissionResult {
390
496
  ok: boolean;
391
497
  worktree: string;
392
- branch: string;
498
+ branch: string | null;
499
+ reason?: 'aborted' | 'outside-write';
500
+ paths?: string[];
393
501
  rounds: number;
394
502
  evidencePath: string | null;
395
503
  committed: boolean;
396
504
  usedOmniCrawl: boolean;
397
505
  detail: string;
506
+ ptyId?: string;
507
+ webUrl?: string | null;
398
508
  }
399
509
  /** @deprecated codex 특정 이름 — AgentMissionResult 을 쓰라. */
400
510
  export type CodexMissionResult = AgentMissionResult;
@@ -405,10 +515,37 @@ export interface AgentMissionDeps {
405
515
  createWorktree?: typeof createWorktree;
406
516
  recordWorktreeProvenance?: typeof recordHarnessWorktreeProvenance;
407
517
  runControlLoop?: typeof runPtyControlLoop;
518
+ /** Inject controller responses while keeping the production control loop. */
519
+ controlStream?: StreamLLMFn;
520
+ resolvePtyWebAddress?: typeof resolvePtyWebAddress;
408
521
  resolveRunFallback?: (input: { currentStep: FallbackStep; currentCredentialRateLimited: true }) => { action: string; backend?: string };
409
522
  /** 재귀 재시도 사이에만 전달되는 런 로컬 폴백 진행 상태. */
410
523
  runtimeFallback?: RuntimeFallbackContext;
411
524
  reemitPtyUsage?: typeof reemitPtyUsage;
525
+ checkClaudeSubscription?: typeof checkClaudeSubscription;
526
+ runClaudeHeadless?: typeof runClaudeHeadless;
527
+ checkEvidence?: typeof checkEvidence;
528
+ commitWorktree?: typeof commitWorktree;
529
+ terminateProcessTree?: typeof terminateMissionProcessTree;
530
+ repoStatus?: (repo: string) => string | Promise<string>;
531
+ emitDecision?: typeof emitDecision;
532
+ onPtyStarted?: (handle: PtyHandle, stop: () => void) => void;
533
+ onHeadlessStarted?: (pid: number, kill: () => void) => void;
534
+ isMissionAborted?: () => boolean;
535
+ awaitMission?: <T>(pending: Promise<T>) => Promise<T>;
536
+ onControlPending?: (pending: Promise<unknown>) => void;
537
+ onControlActive?: (pending: Promise<unknown>) => void;
538
+ /** Upper bound for waiting on control stages after cancel (default 10s). */
539
+ cancelDrainMs?: number;
540
+ handoffOperations?: Partial<HandoffOperations>;
541
+ /** Internal continuation: retain this exact worktree rather than calling createWorktree again. */
542
+ handoffWorktree?: { path: string; branch: string; base: string };
543
+ originalMission?: string;
544
+ /** The last controller reason from the previous backend (not a PTY transcript). */
545
+ previousSummary?: string;
546
+ initialTsc?: ReturnType<typeof collectTscDiagnostics> | null;
547
+ installPlugin?: typeof installPluginInsideAgent;
548
+ pluginDeps?: PluginDeps;
412
549
  }
413
550
 
414
551
  const DEFAULT_OMNI = `${process.env.HOME}/.claude/skills/omni-crawl/scripts/main.ts`;
@@ -487,6 +624,13 @@ type EvidenceCheckDeps = {
487
624
  readonly executeTsc?: TscExecutor;
488
625
  readonly runTest?: (wt: string, testPath: string) => { ok: boolean; out: string };
489
626
  readonly hasChanges?: (wt: string) => boolean;
627
+ /** Worktree-relative paths this mission changed (uncommitted · untracked · committed since fork). */
628
+ readonly changedPaths?: (wt: string) => readonly string[];
629
+ /** Non-git mission: compare against the files present before execution, not only mtime. */
630
+ readonly startedAt?: number;
631
+ readonly initialFiles?: ReadonlyMap<string, string>;
632
+ /** test mode: whether the worktree is a TypeScript project (default: tsconfig.json exists). */
633
+ readonly hasTsconfig?: boolean;
490
634
  };
491
635
 
492
636
  export function checkEvidence(
@@ -501,8 +645,26 @@ export function checkEvidence(
501
645
  if (ev.kind === 'doc') {
502
646
  const dir = join(wt, ev.dirRel);
503
647
  if (!existsSync(dir)) return { ok: false, path: null, retry: `${ev.dirRel} 아래 문서가 아직 없다.` };
504
- const hit = readdirSync(dir).find((f) => ev.glob.test(f));
505
- return hit ? { ok: true, path: join(dir, hit) } : { ok: false, path: null, retry: `${ev.dirRel} 아래 대상 문서가 아직 없다.` };
648
+ // Only a document this mission wrote counts: a matching file that was already in the
649
+ // worktree (e.g. an old PLAN-*.md) passed round 0 without any work (🅞 09-27).
650
+ const changed = deps.startedAt === undefined ? (deps.changedPaths ?? changedFiles)(wt) : [];
651
+ const dirPrefix = `${ev.dirRel.replace(/\/+$/, '')}/`;
652
+ const isChanged = (f: string) => {
653
+ if (deps.startedAt !== undefined) {
654
+ try {
655
+ const stat = statSync(join(dir, f));
656
+ return stat.isFile() && stat.mtimeMs >= deps.startedAt
657
+ && (!deps.initialFiles || deps.initialFiles.get(f) !== fileFingerprint(join(dir, f)));
658
+ } catch { return false; }
659
+ }
660
+ return changed.some((c) => c === `${dirPrefix}${f}` || (c.endsWith('/') && `${dirPrefix}${f}`.startsWith(c)));
661
+ };
662
+ const matching = readdirSync(dir).filter((f) => ev.glob.test(f));
663
+ const hit = matching.find(isChanged);
664
+ if (hit) return { ok: true, path: join(dir, hit) };
665
+ return { ok: false, path: null, retry: matching.length
666
+ ? `${ev.dirRel} 아래 이름이 맞는 문서는 있지만 이번 미션이 쓴 것이 아니다 — 새로 작성하거나 고쳐라.`
667
+ : `${ev.dirRel} 아래 대상 문서가 아직 없다.` };
506
668
  }
507
669
  if (!hasChanges(wt)) return { ok: false, path: null, retry: '아직 변경사항이 없다. 실제 파일을 작성하라.' };
508
670
  if (ev.kind === 'tsc') {
@@ -516,7 +678,10 @@ export function checkEvidence(
516
678
  // 없으면 비파싱 원시 출력의 **끝** 1500자(out.slice(-1500))를 쓴다. output.slice(0,1500)(앞부분)로
517
679
  // 바꾸면 종전 문구와 어긋나 수용기준을 위반한다.
518
680
  if (ev.fileRel && !existsSync(join(wt, ev.fileRel))) return { ok: false, path: null, retry: `${ev.fileRel} 가 아직 없다.` };
519
- const tsc = executeTsc(wt);
681
+ // 🩸 09-29 S6(retry-demo): without a tsconfig.json tsc prints its help and exits 1, so a mission whose tests passed
682
+ // 2/2 was sent «tsc 실패» with the help text as the error. The test is the evidence the caller asked for — the
683
+ // tsc pre-check only applies to a TypeScript project.
684
+ const tsc: ReturnType<TscExecutor> = deps.hasTsconfig ?? existsSync(join(wt, 'tsconfig.json')) ? executeTsc(wt) : { ran: true, diagnostics: [] };
520
685
  if (!tsc.ran || tsc.diagnostics.length > 0) {
521
686
  const parsed = tsc.diagnostics.map((diagnostic) => diagnostic.line);
522
687
  const errors = parsed.slice(0, 25).join('\n') || (tsc.output ?? tsc.failure ?? '').slice(-1500);
@@ -652,6 +817,9 @@ export interface MissionControlBrainOpts {
652
817
  * 행동은 no-op(wait)로 폴백 = 무회귀. 반환 detail 을 자식에 input 으로 전달(설치됨/거부 안내). */
653
818
  readonly provision?: (req: ProvisionRequest) => Promise<ProvisionResult>;
654
819
  readonly stream?: StreamLLMFn;
820
+ readonly handoffEnabled?: boolean;
821
+ /** Screen-grounded brain summary for the next backend, never the raw PTY screen. */
822
+ readonly onSummary?: (summary: string) => void;
655
823
  }
656
824
 
657
825
  /** 기존 5-action mission 판단을 canonical PTY control-loop 결정으로 축소한다. search는 이 경계에서만
@@ -678,7 +846,9 @@ export function createMissionControlBrain(opts: MissionControlBrainOpts): RunSup
678
846
  - "wait": ${backendName} 가 아직 작업 중(도구 실행/생성)이면 대기.
679
847
  - "verify": ${backendName} 가 MISSION-COMPLETE/완료를 주장하면 증거 게이트(내가 실행)로 검증. 완료주장 시 이걸 우선.
680
848
  - "send": ${backendName} 가 멈추거나 계속 진행이 필요하면 짧고 명확한 지시(text).
681
- - "search": ${backendName} 가 정보/라이브러리/문법/외부자원에 막혔으면 omni-crawl 로 조사(query). ⭐외부 힌트 없이 스스로 판단.${opts.provision ? `
849
+ - "search": ${backendName} 가 정보/라이브러리/문법/외부자원에 막혔으면 omni-crawl 로 조사(query). ⭐외부 힌트 없이 스스로 판단.
850
+ ${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/claude/elanous), mission(다음 지시), carry(diff/summary 선택). carry=summary 면 reason 에 화면에서 확인한 리뷰 지적을 구체적으로 요약하라(다음 backend 에 전달된다). claude 리뷰 뒤 지적은 codex 에 summary 로 되돌려라. elanous 는 증거 게이트와 PR.
851
+ - "ask-human": 화면에 로그인 URL/장치 코드가 보이면 reason, url/code(보이는 것만). 토큰·자격파일을 열지 마라.` : ''}${opts.provision ? `
682
852
  - "provision": ${backendName} 가 **없는 Node 패키지**에 막혔으면(예: "Cannot find module 'X'"·"Module not found: X") 격리 worktree 에 자율 설치(spec=**npm 패키지명**, layer="pkg"). ⚠️Node 패키지만 — 파이썬/시스템 도구(pip·apt·brew)는 아직 미지원이니 provision 하지 말고 다른 방법(search·send)으로. 내가 설치 후 재시도를 지시한다.` : ''}
683
853
  증거상태: ${opts.evidenceReady() ? '충족(완료 가능)' : '아직'}.
684
854
  JSON 만: {"action":"...","text":"...","query":"...","spec":"...","layer":"pkg","reason":"..."}`;
@@ -691,7 +861,11 @@ export function createMissionControlBrain(opts: MissionControlBrainOpts): RunSup
691
861
  decisionFromRaw: async (raw, obs): Promise<ControlDecision> => {
692
862
  const decision = parseBrainDecision(raw);
693
863
  history.push(`s${obs.step}:${decision.action}`);
694
- debug.log('agent-mission', 'brain', { step: obs.step, action: decision.action, reason: decision.reason.slice(0, 120) });
864
+ debug.log('agent-mission', 'brain', { step: obs.step, action: decision.action,
865
+ ...(decision.action === 'ask-human' ? {} : { reason: decision.reason.slice(0, 120) }) });
866
+ if (decision.reason && decision.action !== 'ask-human') opts.onSummary?.(decision.reason.slice(0, 2000));
867
+ if (decision.action === 'handoff' && decision.to && decision.mission) return { action: 'handoff', to: decision.to, mission: decision.mission, ...(decision.carry ? { carry: decision.carry } : {}) };
868
+ if (decision.action === 'ask-human') return { action: 'ask-human', reason: decision.reason, ...(decision.url ? { url: decision.url } : {}), ...(decision.code ? { code: decision.code } : {}) };
695
869
  if (decision.action === 'send') return { action: 'input', text: `${decision.text || 'continue'}\r` };
696
870
  if (decision.action === 'verify' || decision.action === 'done') return { action: 'done', reason: decision.reason || 'agent completed' };
697
871
  if (decision.action === 'search') {
@@ -838,7 +1012,7 @@ export function buildMissionWorktreeRequest(
838
1012
  ctx: { repoRoot: string; worktreeRoot: string },
839
1013
  ): CreateWorktreeOpts {
840
1014
  return {
841
- repoRoot: ctx.repoRoot, branch: spec.branch, worktreeRoot: ctx.worktreeRoot, resetExisting: true,
1015
+ repoRoot: ctx.repoRoot, branch: spec.branch!, worktreeRoot: ctx.worktreeRoot, resetExisting: true,
842
1016
  ...(spec.base ? { base: spec.base } : {}),
843
1017
  ...(spec.reuseOwnedWorktree === true ? { reuseOwnedWorktree: true } : {}),
844
1018
  };
@@ -868,10 +1042,334 @@ export function recordMissionWorktreeProvenance(
868
1042
  }
869
1043
 
870
1044
  // ══════════════════ 메인 ══════════════════
1045
+ export const AGENT_MISSION_TAKEOVER_WAIT_MS = 1_800_000;
1046
+
1047
+ function containingGitRepo(dir: string): string | null {
1048
+ const probe = spawnSync('git', ['-C', dir, 'rev-parse', '--show-toplevel'], { encoding: 'utf8' });
1049
+ return probe.status === 0 && probe.stdout.trim() ? probe.stdout.trim() : null;
1050
+ }
1051
+
1052
+ function missionRepoStatus(repo: string): Promise<string> {
1053
+ return new Promise((resolve, reject) => {
1054
+ const child = spawnChild('git', ['status', '--porcelain', '-z', '--untracked-files=all'], { cwd: repo });
1055
+ let out = '', err = '';
1056
+ child.stdout.setEncoding('utf8').on('data', (chunk: string) => { out += chunk; });
1057
+ child.stderr.setEncoding('utf8').on('data', (chunk: string) => { err += chunk; });
1058
+ child.on('error', reject);
1059
+ child.on('close', (code) => code === 0 ? resolve(out) : reject(new Error(`git status failed (${code}): ${err}`)));
1060
+ });
1061
+ }
1062
+
1063
+ function statusEntries(status: string): Map<string, string> {
1064
+ const nulDelimited = status.includes('\0');
1065
+ const entries = nulDelimited ? status.split('\0') : status.split('\n');
1066
+ const paths = new Map<string, string>();
1067
+ for (let i = 0; i < entries.length; i++) {
1068
+ const entry = entries[i]!;
1069
+ if (!entry) continue;
1070
+ // Porcelain -z lists the source of a rename in the following entry; its path is literal.
1071
+ if (nulDelimited && /[RC]/.test(entry.slice(0, 2))) i++;
1072
+ const raw = nulDelimited ? entry.slice(3) : entry.slice(3).replace(/^.* -> /, '');
1073
+ if (raw) paths.set(raw, entry.slice(0, 2));
1074
+ }
1075
+ return paths;
1076
+ }
1077
+
1078
+ function insideWorkdir(repo: string, workdir: string, path: string): boolean {
1079
+ const root = realpathSync(repo);
1080
+ const folder = realpathSync(workdir);
1081
+ const candidate = resolve(root, path);
1082
+ const rel = relative(folder, candidate);
1083
+ return rel === '' || (rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
1084
+ }
1085
+
1086
+ function initialEvidenceFiles(workdir: string, evidence: Extract<EvidenceMode, { kind: 'doc' }>): Map<string, string> {
1087
+ const dir = join(workdir, evidence.dirRel);
1088
+ const files = new Map<string, string>();
1089
+ if (existsSync(dir)) for (const name of readdirSync(dir)) {
1090
+ if (!evidence.glob.test(name)) continue;
1091
+ const fingerprint = fileFingerprint(join(dir, name));
1092
+ if (fingerprint !== null) files.set(name, fingerprint);
1093
+ }
1094
+ return files;
1095
+ }
1096
+
1097
+ function fileFingerprint(path: string): string | null {
1098
+ try {
1099
+ const stat = statSync(path);
1100
+ if (!stat.isFile()) return null;
1101
+ return createHash('sha256').update(readFileSync(path)).digest('hex');
1102
+ } catch { return null; }
1103
+ }
1104
+
1105
+ function linkedTargetFingerprint(path: string, seen: Set<string> = new Set()): string | null {
1106
+ try {
1107
+ const real = realpathSync(path);
1108
+ // A link cycle is hashed as a marker; the content was already hashed on the first visit.
1109
+ if (seen.has(real)) return 'cycle';
1110
+ const stat = statSync(real);
1111
+ if (stat.isFile()) return fileFingerprint(real);
1112
+ if (!stat.isDirectory()) return null;
1113
+ seen.add(real);
1114
+ const hash = createHash('sha256');
1115
+ for (const entry of readdirSync(real, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
1116
+ const child = join(real, entry.name);
1117
+ // Follow nested links too: writing through `link/nested` changes the nested target, not the link text.
1118
+ const content = linkedTargetFingerprint(child, seen) ?? 'missing';
1119
+ hash.update(entry.name).update(entry.isSymbolicLink() ? `link:${readlinkSync(child)}:${content}` : content);
1120
+ }
1121
+ return hash.digest('hex');
1122
+ } catch { return null; }
1123
+ }
1124
+
1125
+ // Git control files change what git and its hooks execute. Objects, the index and refs churn during
1126
+ // ordinary reads and sibling worktrees, so they are not compared.
1127
+ const GIT_CONTROL_ENTRIES = ['config', 'config.worktree', 'hooks', 'info'];
1128
+
1129
+ function gitControlFingerprints(root: string, add: (label: string, hash: string | null) => void): void {
1130
+ const dotGit = join(root, '.git');
1131
+ const dirs: Array<{ dir: string; label: string }> = [];
1132
+ try {
1133
+ const stat = lstatSync(dotGit);
1134
+ if (stat.isDirectory()) dirs.push({ dir: dotGit, label: '.git' });
1135
+ else if (stat.isFile()) {
1136
+ add('.git', fileFingerprint(dotGit));
1137
+ const gitdir = /^gitdir:\s*(.+)$/m.exec(readFileSync(dotGit, 'utf8'))?.[1]?.trim();
1138
+ if (gitdir) {
1139
+ const dir = resolve(root, gitdir);
1140
+ dirs.push({ dir, label: '.git:gitdir' });
1141
+ const common = existsSync(join(dir, 'commondir')) ? readFileSync(join(dir, 'commondir'), 'utf8').trim() : '';
1142
+ if (common) dirs.push({ dir: resolve(dir, common), label: '.git:common' });
1143
+ }
1144
+ }
1145
+ } catch { return; }
1146
+ const walk = (absolute: string, label: string): void => {
1147
+ try {
1148
+ const stat = lstatSync(absolute);
1149
+ if (stat.isDirectory()) {
1150
+ for (const name of readdirSync(absolute).sort()) walk(join(absolute, name), `${label}/${name}`);
1151
+ } else add(label, stat.isSymbolicLink() ? `link:${readlinkSync(absolute)}:${linkedTargetFingerprint(absolute)}` : fileFingerprint(absolute));
1152
+ } catch { /* Absent control files are compared as absent. */ }
1153
+ };
1154
+ for (const { dir, label } of dirs) for (const name of GIT_CONTROL_ENTRIES) walk(join(dir, name), `${label}/${name}`);
1155
+ }
1156
+
1157
+ function externalLinks(dir: string, workdir: string, label: (path: string) => string): Map<string, string | null> {
1158
+ const links = new Map<string, string | null>();
1159
+ const folder = realpathSync(workdir);
1160
+ const visit = (current: string): void => {
1161
+ for (const entry of readdirSync(current, { withFileTypes: true })) {
1162
+ if (entry.name === '.git' && entry.isDirectory()) continue;
1163
+ const path = join(current, entry.name);
1164
+ if (entry.isDirectory()) visit(path);
1165
+ else if (entry.isSymbolicLink()) {
1166
+ try {
1167
+ const target = realpathSync(path);
1168
+ const rel = relative(folder, target);
1169
+ if (rel === '..' || rel.startsWith(`..${sep}`) || isAbsolute(rel)) {
1170
+ links.set(label(path), linkedTargetFingerprint(target));
1171
+ }
1172
+ } catch { /* A broken link cannot be used to write an existing target. */ }
1173
+ }
1174
+ }
1175
+ };
1176
+ visit(dir);
1177
+ return links;
1178
+ }
1179
+
1180
+ function repoFingerprints(repo: string, workdir: string, paths: readonly string[]): Map<string, string | null> {
1181
+ const fingerprints = new Map<string, string | null>();
1182
+ const root = realpathSync(repo);
1183
+ const folder = realpathSync(workdir);
1184
+ const inside = (absolute: string): boolean => {
1185
+ const rel = relative(folder, absolute);
1186
+ return rel === '' || (rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
1187
+ };
1188
+ const visit = (dir: string): void => {
1189
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
1190
+ if (dir === root && entry.name === '.git') continue;
1191
+ const absolute = join(dir, entry.name);
1192
+ if (inside(absolute)) continue;
1193
+ const path = relative(root, absolute);
1194
+ if (entry.isDirectory()) visit(absolute);
1195
+ else if (entry.isSymbolicLink()) {
1196
+ fingerprints.set(path, `link:${readlinkSync(absolute)}`);
1197
+ try {
1198
+ const target = realpathSync(absolute);
1199
+ if (!target.startsWith(`${root}${sep}`) && target !== root) {
1200
+ fingerprints.set(path, `link:${readlinkSync(absolute)}:${linkedTargetFingerprint(target)}`);
1201
+ }
1202
+ } catch { /* Broken link. */ }
1203
+ }
1204
+ else fingerprints.set(path, fileFingerprint(absolute));
1205
+ }
1206
+ };
1207
+ // Include ignored files as well as tracked/untracked paths: git status alone cannot see them.
1208
+ visit(root);
1209
+ gitControlFingerprints(root, (label, hash) => fingerprints.set(label, hash));
1210
+ for (const path of paths) {
1211
+ if (insideWorkdir(repo, workdir, path) || fingerprints.has(path)) continue;
1212
+ fingerprints.set(path, fileFingerprint(resolve(root, path)));
1213
+ }
1214
+ return fingerprints;
1215
+ }
1216
+
1217
+ /** Abort owns the PTY tree even while the control brain or an external tool is awaiting. */
871
1218
  export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMissionDeps = {}): Promise<AgentMissionResult> {
872
- const backend = spec.agent ?? resolveDefaultBackend();
1219
+ if (spec.signal?.aborted) {
1220
+ debug.log('agent-mission', 'aborted', { workdir: spec.workdir, pids: [], reason: 'aborted' });
1221
+ return { ok: false, reason: 'aborted', worktree: spec.workdir ?? '', branch: spec.workdir ? null : spec.branch ?? null,
1222
+ rounds: 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' };
1223
+ }
1224
+ if (spec.workdir && spec.evidence.kind !== 'doc') throw new Error('workdir 모드는 doc 증거만');
1225
+ const workdir = spec.workdir;
1226
+ const status = deps.repoStatus ?? missionRepoStatus;
1227
+ // Compare the repository that contains the workdir, not the launcher's cwd: a workdir outside any repository
1228
+ // (e.g. a media folder) must not be failed by unrelated writes in the launcher's tree, such as its own logs.
1229
+ const repo = workdir ? (spec.repo ?? containingGitRepo(workdir)) : null;
1230
+ if (workdir && !repo) debug.log('agent-mission', 'workdir-outside-repo', { workdir, pids: [], reason: 'links-only' });
1231
+ const signal = spec.signal;
1232
+ let before = '';
1233
+ let beforeFingerprints = new Map<string, string | null>();
1234
+ let beforeLinks = new Map<string, string | null>();
1235
+ if (workdir) {
1236
+ let stopWaiting!: () => void;
1237
+ const interrupted = new Promise<never>((_resolve, reject) => { stopWaiting = () => reject(new Error('MISSION_ABORTED')); });
1238
+ signal?.addEventListener('abort', stopWaiting, { once: true });
1239
+ try {
1240
+ if (repo) {
1241
+ before = await Promise.race([status(repo), interrupted]);
1242
+ beforeFingerprints = repoFingerprints(repo, workdir, [...statusEntries(before).keys()]);
1243
+ }
1244
+ beforeLinks = externalLinks(workdir, workdir, (path) => path);
1245
+ } catch (error) {
1246
+ if (!signal?.aborted) throw error;
1247
+ debug.log('agent-mission', 'aborted', { workdir, pids: [], reason: 'aborted' });
1248
+ return { ok: false, reason: 'aborted', worktree: workdir, branch: null,
1249
+ rounds: 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' };
1250
+ } finally { signal?.removeEventListener('abort', stopWaiting); }
1251
+ }
1252
+ const startedAt = Date.now();
1253
+ const initialFiles = workdir && spec.evidence.kind === 'doc' ? initialEvidenceFiles(workdir, spec.evidence) : undefined;
1254
+ let handle: PtyHandle | undefined;
1255
+ let childPid: number | undefined;
1256
+ let killChild: (() => void) | undefined;
1257
+ let stopPty: (() => void) | undefined;
1258
+ let abort!: () => void;
1259
+ let cancelled = false;
1260
+ let controlPending: Promise<unknown> | undefined;
1261
+ let controlSettled = false;
1262
+ let activeControl: Promise<unknown> | undefined;
1263
+ let activeSettled = false;
1264
+ const aborted = new Promise<never>((_resolve, reject) => {
1265
+ abort = () => {
1266
+ if (cancelled) return;
1267
+ cancelled = true;
1268
+ debug.log('agent-mission', 'aborted', { workdir, pids: childPid ? [childPid] : handle?.pid ? [handle.pid] : [], reason: 'aborted' });
1269
+ void (async () => {
1270
+ stopPty?.();
1271
+ const pid = childPid ?? handle?.pid;
1272
+ try {
1273
+ if (pid) {
1274
+ const pids = await (deps.terminateProcessTree ?? terminateMissionProcessTree)(pid);
1275
+ debug.log('agent-mission', 'tree-killed', { workdir, pids, reason: 'aborted' });
1276
+ }
1277
+ } finally {
1278
+ if (handle) try { handle.kill(); } catch { /* Already exited. */ }
1279
+ killChild?.();
1280
+ }
1281
+ })().then(() => reject(new Error('MISSION_ABORTED')), reject);
1282
+ };
1283
+ });
1284
+ signal?.addEventListener('abort', abort, { once: true });
1285
+ if (signal?.aborted) abort();
1286
+ let result: AgentMissionResult;
1287
+ try {
1288
+ if (cancelled) await aborted;
1289
+ const body = runAgentMissionBody(spec, { ...deps, onControlActive: (pending) => {
1290
+ activeSettled = false;
1291
+ activeControl = pending.then(() => { activeSettled = true; }, () => { activeSettled = true; });
1292
+ }, onControlPending: (pending) => {
1293
+ controlSettled = false;
1294
+ controlPending = pending.then(() => { controlSettled = true; }, () => { controlSettled = true; });
1295
+ }, awaitMission: (pending) => Promise.race([pending, aborted]), isMissionAborted: () => cancelled, onPtyStarted: (h, stop) => { handle = h; stopPty = stop; deps.onPtyStarted?.(h, stop); if (signal?.aborted) abort(); }, onHeadlessStarted: (pid, kill) => { childPid = pid; killChild = kill; deps.onHeadlessStarted?.(pid, kill); if (signal?.aborted) abort(); } }, startedAt, initialFiles);
1296
+ if (signal) {
1297
+ try { result = await Promise.race([body, aborted]); }
1298
+ catch (error) {
1299
+ if (cancelled) {
1300
+ // The tree is already terminated by abort; a stage not tied to cancellation (e.g. ownership wait)
1301
+ // must not hold the return forever, so the drain is bounded.
1302
+ const drain = (async () => {
1303
+ await body.catch(() => {});
1304
+ if (activeControl && !activeSettled) await activeControl;
1305
+ if (controlPending && !controlSettled) await controlPending;
1306
+ })();
1307
+ let timer: ReturnType<typeof setTimeout> | undefined;
1308
+ const drained = await Promise.race([drain.then(() => true), new Promise<false>((done) => { timer = setTimeout(() => done(false), deps.cancelDrainMs ?? 10_000); })]);
1309
+ clearTimeout(timer);
1310
+ if (!drained) debug.log('agent-mission', 'cancel-drain-timeout', { workdir, pids: childPid ? [childPid] : handle?.pid ? [handle.pid] : [], reason: 'aborted' });
1311
+ }
1312
+ throw error;
1313
+ }
1314
+ } else result = await body;
1315
+ if (cancelled) await aborted;
1316
+ } catch (error) {
1317
+ if (!cancelled) throw error;
1318
+ result = { ok: false, reason: 'aborted', worktree: workdir ?? '', branch: workdir ? null : spec.branch ?? null,
1319
+ rounds: 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' };
1320
+ } finally {
1321
+ signal?.removeEventListener('abort', abort);
1322
+ }
1323
+ if (workdir) {
1324
+ let after = '';
1325
+ if (repo) {
1326
+ let stopWaiting!: () => void;
1327
+ const interrupted = new Promise<never>((_resolve, reject) => { stopWaiting = () => reject(new Error('MISSION_ABORTED')); });
1328
+ signal?.addEventListener('abort', stopWaiting, { once: true });
1329
+ try { after = await Promise.race([status(repo), interrupted]); }
1330
+ catch (error) {
1331
+ if (!signal?.aborted) throw error;
1332
+ after = await status(repo);
1333
+ } finally { signal?.removeEventListener('abort', stopWaiting); }
1334
+ }
1335
+ // A cancel that lands during the final inspection still cancels the mission; it never reports success.
1336
+ if (signal?.aborted && result.reason !== 'aborted') {
1337
+ debug.log('agent-mission', 'aborted', { workdir, pids: [], reason: 'aborted-during-final-inspection' });
1338
+ result = { ...result, ok: false, reason: 'aborted', committed: false, detail: 'aborted' };
1339
+ }
1340
+ const afterEntries = statusEntries(after);
1341
+ const beforeEntries = statusEntries(before);
1342
+ const afterFingerprints = repo
1343
+ ? repoFingerprints(repo, workdir, [...new Set([...beforeFingerprints.keys(), ...afterEntries.keys()])])
1344
+ : new Map<string, string | null>();
1345
+ const paths = [...afterFingerprints].filter(([path, hash]) =>
1346
+ (beforeFingerprints.has(path) && beforeFingerprints.get(path) !== hash)
1347
+ || (!beforeFingerprints.has(path) && hash !== null)
1348
+ || (afterEntries.has(path) && beforeEntries.get(path) !== afterEntries.get(path)))
1349
+ .map(([path]) => path);
1350
+ for (const [link, hash] of externalLinks(workdir, workdir, (path) => path)) {
1351
+ if (beforeLinks.get(link) !== hash && !paths.includes(link)) paths.push(link);
1352
+ }
1353
+ paths.sort();
1354
+ if (paths.length) {
1355
+ debug.log('agent-mission', 'outside-write', { workdir, pids: [], reason: paths.join(', ') });
1356
+ (deps.emitDecision ?? emitDecision)({ kind: 'ESCALATE', what: '작업 폴더 밖 쓰기', reason: paths.join(', '), purpose: '사람이 확인한다', target: 'human' });
1357
+ return { ...result, ok: false, reason: 'outside-write', paths, committed: false };
1358
+ }
1359
+ }
1360
+ return result;
1361
+ }
1362
+
1363
+ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDeps, startedAt: number, initialFiles?: ReadonlyMap<string, string>): Promise<AgentMissionResult> {
1364
+ const backend = spec.agent ?? (spec.chain?.[0] && spec.chain[0] !== 'elanous' ? resolveBackend(spec.chain[0]) : resolveDefaultBackend());
1365
+ if (spec.chain && (spec.chain[0] !== backend.name || !['codex,claude,elanous', 'codex,claude,codex,elanous'].some((allowed) => allowed === spec.chain!.join(',') || (deps.handoffWorktree && allowed.endsWith(`,${spec.chain!.join(',')}`))))) throw new Error('invalid agent mission chain');
1366
+ if (spec.chain && spec.commit === false && spec.chain.includes('elanous')) throw new Error('elanous PR handoff requires commit authorization');
1367
+ if (spec.headless && spec.chain) throw new Error('--headless cannot run a PTY handoff chain');
1368
+ if (spec.headless && backend.name !== 'claude') throw new Error('--headless 는 --backend claude 전용입니다');
1369
+ if (spec.plugin && (spec.headless || (backend.name !== 'codex' && backend.name !== 'claude'))) throw new Error('--plugin 은 codex/claude PTY 전용입니다');
1370
+ if (spec.workdir && spec.chain) throw new Error('workdir 모드는 넘기기 사슬을 쓰지 않는다');
873
1371
  const runtimeFallback = deps.runtimeFallback ?? {
874
- fallbackEligible: spec.agent === undefined,
1372
+ fallbackEligible: spec.agent === undefined && !spec.chain,
875
1373
  attemptedSteps: new Set<FallbackStep>([backend.name === 'grok' ? 'grok' : 'codex-rotate']),
876
1374
  descents: 0,
877
1375
  maxDescents: backend.name === 'codex' ? 1 : 0,
@@ -880,6 +1378,7 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
880
1378
  const createMissionWorktree = deps.createWorktree ?? createWorktree;
881
1379
  const recordWorktreeProvenance = deps.recordWorktreeProvenance ?? recordHarnessWorktreeProvenance;
882
1380
  const repoRoot = spec.repo ?? resolveMainRepoRoot(process.cwd()) ?? process.cwd();
1381
+ if (!spec.workdir && !spec.branch) throw new Error('branch is required without workdir');
883
1382
  const maxRounds = spec.maxRounds ?? 16;
884
1383
  const omniPath = spec.omniCrawlPath ?? DEFAULT_OMNI;
885
1384
  const screensDir = spec.screensDir ?? join(process.env.TMPDIR || '/tmp', `agent-mission-${backend.name}-${spec.branch}`);
@@ -903,32 +1402,124 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
903
1402
  role: 'controller', executor: describeRole({ role: 'executor', executorKind: 'agent', agentBackend: backend.name }),
904
1403
  entry: missionEntry, capabilities: [...caps.active], enhanceActive,
905
1404
  });
906
- // ⭐ 이 자리는 «별칭»(createMissionWorktree)이라 소스 스캔이 못 찾았고 타입 검사가 찾았다
907
- // — 리뷰 3R must-fix ② 가 경고한 그 형태다(별칭·래퍼는 정규식으로 못 센다).
908
- const wt = createMissionWorktree(buildMissionWorktreeRequest(spec, { repoRoot, worktreeRoot: configuredWorktreeRoot() }));
909
- recordMissionWorktreeProvenance(wt.path, buildMissionWorktreeProvenance(spec.branch), recordWorktreeProvenance);
910
- debug.log('agent-mission', 'worktree', { path: wt.path, branch: wt.branch, base: wt.base });
911
- const baselineTsc = spec.evidence.kind === 'tsc' ? collectTscDiagnostics(wt.path) : null;
912
- const evidenceCheck: typeof checkEvidence = (worktree, evidence) => evidence.kind === 'tsc' && baselineTsc
913
- ? checkEvidence(worktree, evidence, { baseline: baselineTsc.diagnostics, executeTsc: baselineTsc.ran ? collectTscDiagnostics : () => baselineTsc })
914
- : checkEvidence(worktree, evidence);
915
-
916
1405
  // 구독 모드 — backend 지정 env 키 스크럽 후 강제 env까지 적용해 cmd·args·env를 순수 seam으로 구성한다.
917
1406
  // forcedEnv 이름의 후속 로깅은 이 착지의 의도적 경계이며, spawn에는 같은 seam의 env가 그대로 흐른다.
918
1407
  const spawnParams = resolveBackendSpawn(backend, process.env);
919
1408
  const env = spawnParams.env;
920
- env.TERM = 'xterm-256color';
921
- // ⭐run-identity — runId 를 spawn 前 확정해 child env(ELANOUS_RUN_ID 상속)와 executorRef 에 동일 배선한다.
922
- // spawn 後 mint 하면 child 는 자기 runId 를 모르고 ref 와도 상관이 끊긴다(K join 정합·review).
1409
+ if (backend.name === 'claude') {
1410
+ const status = (deps.checkClaudeSubscription ?? checkClaudeSubscription)({ env });
1411
+ debug.log('agent-mission.claude-subscription', 'status', {
1412
+ ok: status.ok, authMethod: status.authMethod, apiProvider: status.apiProvider, reason: status.reason,
1413
+ });
1414
+ if (!status.ok) {
1415
+ const action = status.reason === 'logged-out'
1416
+ ? 'Run `claude login` to authenticate a Claude subscription, then retry.'
1417
+ : status.reason === 'api-key'
1418
+ ? 'Claude is using API-key/provider authentication rather than a Claude subscription. Run `claude login` with a subscription account, then retry.'
1419
+ : 'Run `claude auth status --json` and check the Claude CLI/login, then retry.';
1420
+ return {
1421
+ ok: false, worktree: spec.workdir ?? '', branch: spec.branch ?? null, rounds: 0,
1422
+ evidencePath: null, committed: false, usedOmniCrawl: false,
1423
+ detail: `Claude subscription check failed (${status.reason}). ${action}`,
1424
+ };
1425
+ }
1426
+ }
1427
+ // ⭐ 이 자리는 «별칭»(createMissionWorktree)이라 소스 스캔이 못 찾았고 타입 검사가 찾았다
1428
+ // — 리뷰 3R must-fix ② 가 경고한 그 형태다(별칭·래퍼는 정규식으로 못 센다).
1429
+ if (deps.isMissionAborted?.()) throw new Error('MISSION_ABORTED');
1430
+ const wt = spec.workdir
1431
+ ? { path: spec.workdir, branch: spec.branch ?? null, base: null }
1432
+ : deps.handoffWorktree ?? createMissionWorktree(buildMissionWorktreeRequest(spec, { repoRoot, worktreeRoot: configuredWorktreeRoot() }));
1433
+ if (spec.workdir) debug.log('agent-mission', 'workdir-mode', { workdir: wt.path, pids: [], reason: 'non-git' });
1434
+ else {
1435
+ if (!deps.handoffWorktree) recordMissionWorktreeProvenance(wt.path, buildMissionWorktreeProvenance(spec.branch!), recordWorktreeProvenance);
1436
+ debug.log('agent-mission', 'worktree', { path: wt.path, branch: wt.branch, base: wt.base });
1437
+ }
1438
+ const baselineTsc = spec.evidence.kind === 'tsc' ? (deps.initialTsc ?? collectTscDiagnostics(wt.path)) : null;
1439
+ const evidenceCheck: typeof checkEvidence = (worktree, evidence) => evidence.kind === 'tsc' && baselineTsc
1440
+ ? checkEvidence(worktree, evidence, { baseline: baselineTsc.diagnostics, executeTsc: baselineTsc.ran ? collectTscDiagnostics : () => baselineTsc })
1441
+ : checkEvidence(worktree, evidence, spec.workdir ? { startedAt, initialFiles } : {});
1442
+ const verifyEvidence: typeof checkEvidence = spec.workdir ? evidenceCheck : deps.checkEvidence ?? evidenceCheck;
1443
+ // Resolve identity before either child path; both receive the same run ID through env.
1444
+ if (deps.isMissionAborted?.()) throw new Error('MISSION_ABORTED');
923
1445
  const runId = ensureRunId();
924
1446
  env.ELANOUS_RUN_ID = runId;
1447
+ if (spec.headless === true) {
1448
+ // The non-interactive child receives the mission on stdin, never via a PTY or argv.
1449
+ // Keep the same enhancement and additive memory policy as the interactive mission.
1450
+ let prompt = spec.mission;
1451
+ let checklist: string[] = [];
1452
+ if (enhanceActive) {
1453
+ const { enhancePrompt } = await import('../prompt-enhance/enhance.js');
1454
+ const enhanced = await enhancePrompt(spec.mission, {
1455
+ ...(spec.deliverableHint ? { deliverableHint: spec.deliverableHint } : {}),
1456
+ });
1457
+ prompt = enhanced.enhanced;
1458
+ checklist = enhanced.checklist;
1459
+ debug.log('agent-mission', 'enhance', {
1460
+ checklist: checklist.length, enhancedBy: enhanced.enhancedBy,
1461
+ origChars: enhanced.original.length, enhancedChars: prompt.length, verbatimPreserved: enhanced.verbatimPreserved,
1462
+ });
1463
+ }
1464
+ if (spec.memory !== false) {
1465
+ const { recallMemoryContext } = await import('../agent-substrate/execution/memory-context.js');
1466
+ const mem = await recallMemoryContext(spec.mission.slice(0, 300), { limit: 5 });
1467
+ if (mem) { prompt = `${prompt}\n\n${mem}`; debug.log('agent-mission', 'memory', { injected: true, chars: mem.length }); }
1468
+ else debug.log('agent-mission', 'memory', { injected: false });
1469
+ }
1470
+ if (deps.isMissionAborted?.()) throw new Error('MISSION_ABORTED');
1471
+ const headlessRun = (deps.runClaudeHeadless ?? runClaudeHeadless)({ cwd: wt.path, prompt, env: envLiteral(env), maxTurns: maxRounds, onSpawn: deps.onHeadlessStarted });
1472
+ const result = await (deps.awaitMission ? deps.awaitMission(headlessRun) : headlessRun);
1473
+ debug.log('agent-mission', 'headless-result', {
1474
+ ok: result.ok, reason: result.reason, exitCode: result.exitCode,
1475
+ sessionId: result.sessionId, numTurns: result.numTurns, toolEvents: result.toolEvents,
1476
+ malformedLines: result.malformedLines, durationMs: result.durationMs,
1477
+ });
1478
+ if (!result.ok) return {
1479
+ ok: false, worktree: wt.path, branch: wt.branch, rounds: result.numTurns ?? 0,
1480
+ evidencePath: null, committed: false, usedOmniCrawl: false,
1481
+ detail: `Claude headless failed (${result.reason}; exit ${result.exitCode ?? 'unknown'}). Check the Claude CLI and retry.`,
1482
+ };
1483
+ if (deps.isMissionAborted?.()) return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
1484
+ rounds: result.numTurns ?? 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' };
1485
+ const finalEv = verifyEvidence(wt.path, spec.evidence);
1486
+ if (!finalEv.ok) return {
1487
+ ok: false, worktree: wt.path, branch: wt.branch, rounds: result.numTurns ?? 0,
1488
+ evidencePath: null, committed: false, usedOmniCrawl: false,
1489
+ detail: `미완(증거 부족): ${finalEv.retry ?? '증거가 아직 부족하다.'}`,
1490
+ };
1491
+ if (checklist.length) {
1492
+ const { verifyCoverage } = await import('../prompt-enhance/coverage.js');
1493
+ const coverage = await verifyCoverage(gatherArtifactText(wt.path, finalEv.path), checklist, {});
1494
+ debug.log('agent-mission', 'coverage', { covered: coverage.covered.length, missing: coverage.missing.length,
1495
+ ratio: Number(coverage.ratio.toFixed(2)), method: coverage.method, coverageRetries: 0 });
1496
+ if (coverage.missing.length) debug.log('agent-mission', 'coverage-exhausted', { missing: coverage.missing.length });
1497
+ }
1498
+ let committed = false;
1499
+ if (!deps.isMissionAborted?.() && !spec.workdir && (spec.commit ?? true)) {
1500
+ const c = (deps.commitWorktree ?? commitWorktree)(wt.path, `chore(agent-mission): ${spec.branch} — claude-in-elanous headless 산출`);
1501
+ committed = c.ok;
1502
+ debug.log('agent-mission', 'commit', { ok: c.ok, out: c.out.slice(0, 120) });
1503
+ if (!c.ok) {
1504
+ debug.log('agent-mission', 'result', { ok: false, rounds: result.numTurns ?? 0, evidencePath: finalEv.path, committed: false, usedOmni: false });
1505
+ return { ok: false, worktree: wt.path, branch: wt.branch, rounds: result.numTurns ?? 0,
1506
+ evidencePath: finalEv.path, committed: false, usedOmniCrawl: false,
1507
+ detail: `미완(자동 커밋 실패): ${c.out.slice(0, 120)}` };
1508
+ }
1509
+ }
1510
+ debug.log('agent-mission', 'result', { ok: true, rounds: result.numTurns ?? 0, evidencePath: finalEv.path, committed, usedOmni: false });
1511
+ return { ok: true, worktree: wt.path, branch: wt.branch, rounds: result.numTurns ?? 0,
1512
+ evidencePath: finalEv.path, committed, usedOmniCrawl: false, detail: '완료(증거 충족)' };
1513
+ }
1514
+ env.TERM = 'xterm-256color';
1515
+ // ⭐run-identity — runId was resolved before either headless or PTY spawn.
925
1516
  debug.log('agent-mission', 'spawn', { agent: backend.name, cmd: `${spawnParams.cmd} ${spawnParams.args.join(' ')}`, scrubbed: backend.scrubEnv ?? [], nestedEnvRemovedCount: spawnParams.nestedEnvRemovedCount, runId });
926
1517
  // PTY 정체성 — kind(=backend)·nickname(goto 로 나중 접근)·accessMode='auto'(헤드리스 자율·brain 이 write 소유).
927
1518
  const ptyOpts = buildAgentMissionPtySpawnOptions({
928
1519
  backend,
929
1520
  spawn: { cmd: spawnParams.cmd, args: spawnParams.args, env, unsetEnv: spawnParams.unsetEnv },
930
1521
  workdir: wt.path,
931
- nickname: spec.nickname ?? spec.branch,
1522
+ nickname: spec.nickname ?? spec.branch ?? backend.name,
932
1523
  });
933
1524
  const childStartedAt = Date.now();
934
1525
  let liveDirty = false, liveChunks = 0;
@@ -970,8 +1561,12 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
970
1561
  }
971
1562
  });
972
1563
  let h: PtyHandle;
1564
+ if (deps.isMissionAborted?.()) { offLive(); throw new Error('MISSION_ABORTED'); }
973
1565
  try { h = spawnPty(ptyOpts); }
974
1566
  catch (error) { offLive(); throw error; }
1567
+ deps.onPtyStarted?.(h, () => { if (liveTimer) clearInterval(liveTimer); offLive(); });
1568
+ if (deps.isMissionAborted?.()) return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
1569
+ rounds: 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' };
975
1570
  const executorRef = buildExecutorPtyRef({
976
1571
  ptyId: h.id,
977
1572
  backend: backend.name,
@@ -980,6 +1575,9 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
980
1575
  instance: resolveInstanceName(),
981
1576
  });
982
1577
  debug.log('agent-mission', 'pty', { id: h.id, kind: h.kind, nickname: h.nickname, accessMode: h.accessMode, executorRef });
1578
+ const webAddress = (deps.resolvePtyWebAddress ?? resolvePtyWebAddress)(h.id);
1579
+ process.stderr.write(`[agent-mission] pty=${h.id} watch=${webAddress.webUrl ?? `(web unavailable: ${webAddress.pwaUnavailableReason ?? 'not-resolved'})`}\n`);
1580
+ debug.log('agent-mission', 'pty-link', { id: h.id, webUrl: webAddress.webUrl, webUrlSource: webAddress.webUrlSource });
983
1581
 
984
1582
  // ⭐P2 arbiter: the child is accessMode='auto' (brain-owned), so the driver —
985
1583
  // the autonomous brain — must write as 'agent' or the arbiter denies it. This
@@ -987,10 +1585,10 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
987
1585
  // inject unless they takeover (auto→write, needs 'open' policy). `h['write']`
988
1586
  // form so the drive helper isn't caught by the h.write→drive rewrite.
989
1587
  //
990
- // ⭐takeover 조율/셀프힐(review): 사람이 takeover 하면(auto→write) agent write 가 arbiter 에
991
- // 거부된다. 조용히 유실돼 미션이 헛도는 대신, drive 前 canWrite 로 감지해 미션을 깔끔히 중단
992
- // (사람이 제어를 가져갔으니 자율 구동 멈춤 = HITL 로 넘어감). 관측 남김.
1588
+ // 초기 미션 전송 중 소유권을 잃으면 write 를 시도하지 않는다. 제어 루프에 들어간 뒤의
1589
+ // takeover 는 awaitOwnership 으로 기다리며, 사람이 release 하면 미션을 재개한다.
993
1590
  const drive = (s: string): void => {
1591
+ if (deps.isMissionAborted?.()) return;
994
1592
  // ⭐공용 seam(P2b P-a′) — 판정은 `pty-control-stance` 한 곳. 집행(throw)은 종전 그대로다(무회귀).
995
1593
  const stance = probeControlStance(h, 'agent', (e) =>
996
1594
  debug.log('agent-mission', 'hascontrol-error', { id: h.id, error: (e as Error)?.message ?? String(e) }));
@@ -1033,11 +1631,30 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
1033
1631
  const stopLive = (): void => { if (liveTimer) clearInterval(liveTimer); offLive(); };
1034
1632
 
1035
1633
  // ready + trust — backend 별 신뢰/권한 프롬프트 처리(codex=1, 이후 백엔드는 자체 handler).
1036
- await waitForQuiet(h, 1500, 20000);
1037
- let screen = await capture('ready');
1038
- if (backend.handleTrust?.(screen, (s) => drive(s))) {
1039
- debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled' });
1040
- await waitForQuiet(h, 1500, 15000); screen = await capture('trusted');
1634
+ await (deps.awaitMission ? deps.awaitMission(waitForQuiet(h, 1500, 20000)) : waitForQuiet(h, 1500, 20000));
1635
+ if (deps.isMissionAborted?.()) throw new Error('MISSION_ABORTED');
1636
+ let screen = await (deps.awaitMission ? deps.awaitMission(capture('ready')) : capture('ready'));
1637
+ if (deps.isMissionAborted?.()) throw new Error('MISSION_ABORTED');
1638
+ // A trust menu can need more than one key (claude: ↓ to «Yes», then Enter) — answer until it is gone, at most 3 times.
1639
+ // 🩸 09-29: one pass sent only ↓, the mission text went into the menu and its Enter confirmed «Yes» instead of
1640
+ // submitting the mission, which then sat unsent in the input box.
1641
+ for (let pass = 0; pass < 3 && backend.handleTrust?.(screen, (s) => drive(s)); pass++) {
1642
+ debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled', pass });
1643
+ const trusted = (async () => { await waitForQuiet(h, 1500, 15000); return capture('trusted'); })();
1644
+ screen = await (deps.awaitMission ? deps.awaitMission(trusted) : trusted);
1645
+ }
1646
+
1647
+ if (spec.plugin) {
1648
+ const plugin = await (deps.installPlugin ?? installPluginInsideAgent)(
1649
+ { agent: backend.name as 'codex' | 'claude', ...spec.plugin }, h,
1650
+ { ...(backend.handleTrust ? { handleTrust: backend.handleTrust } : {}), ...deps.pluginDeps, write: drive },
1651
+ );
1652
+ if (plugin.outcome !== 'installed') {
1653
+ stopLive();
1654
+ try { h.kill(); } catch { /* already exited */ }
1655
+ return { ok: false, worktree: wt.path, branch: wt.branch, rounds: 0, evidencePath: null,
1656
+ committed: false, usedOmniCrawl: false, detail: `플러그인 설치 ESCALATE (${plugin.reason}) — 미션은 전송하지 않았다` };
1657
+ }
1041
1658
  }
1042
1659
 
1043
1660
  // ★ elanous 내부 인핸싱(opt-in) — 원문 verbatim 보존 + 커버리지 체크리스트 부착(anti-drift).
@@ -1066,6 +1683,8 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
1066
1683
  else debug.log('agent-mission', 'memory', { injected: false });
1067
1684
  }
1068
1685
 
1686
+ if (spec.plugin) missionText = `${missionText}\n\n설치된 ${spec.plugin.plugin} 플러그인에서 실제 스킬을 확인하고 ${spec.plugin.plugin}:<skill> 형식으로 해당 스킬을 사용하라.`;
1687
+ if (deps.isMissionAborted?.()) throw new Error('MISSION_ABORTED');
1069
1688
  // 미션 전송 — 인핸싱/기억으로 가공됐으면(멀티라인) 파일로 떨궈 read 지시(TUI 멀티라인 위험·verbatim 보존).
1070
1689
  // 원문 그대로면(단문) 타이핑.
1071
1690
  if (missionText !== spec.mission) {
@@ -1082,12 +1701,17 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
1082
1701
  }
1083
1702
 
1084
1703
  let usedOmni = false;
1704
+ let controllerSummary = deps.previousSummary ?? '';
1705
+ let reviewSummary = '';
1085
1706
  let coverageRetries = enhanceActive && checklist.length ? 2 : 0;
1086
1707
  const search = createMissionSearch({ worktree: wt.path, omniPath });
1087
1708
  const brain = createMissionControlBrain({
1088
1709
  mission: spec.mission,
1089
1710
  backend,
1090
- evidenceReady: () => evidenceCheck(wt.path, spec.evidence).ok,
1711
+ stream: deps.controlStream,
1712
+ handoffEnabled: true,
1713
+ onSummary: (summary) => { controllerSummary = summary; },
1714
+ evidenceReady: () => spec.chain && spec.chain.length > 1 ? true : verifyEvidence(wt.path, spec.evidence).ok,
1091
1715
  search: async (query, step) => {
1092
1716
  usedOmni = true;
1093
1717
  await search(query, step);
@@ -1098,12 +1722,64 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
1098
1722
  // buildMissionProvision 팩토리로 배선(wt.path→cwd 를 DI 로 행동검증 가능·소스 tripwire 불요).
1099
1723
  provision: buildMissionProvision(wt.path),
1100
1724
  });
1725
+ // A trust/permission prompt can appear after the first screen (09-29 S6: codex 0.157 showed «Folder access»
1726
+ // 70 s after launch, after the one-shot check). Answer it at every step with the backend's own bytes
1727
+ // before asking the LLM — otherwise the mission text is typed into the prompt and the run stalls.
1728
+ const trustAwareBrain: RunSupervisor = {
1729
+ decide: (obs, signal) => {
1730
+ let answer: string | undefined;
1731
+ if (backend.handleTrust?.(obs.screen, (bytes) => { answer = bytes; }) && answer !== undefined) {
1732
+ debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled-in-loop', step: obs.step });
1733
+ emitDecision({ kind: 'ROUTE', what: `${backend.name} 폴더 신뢰 화면 → 계속`, reason: '시작 뒤 늦게 뜬 신뢰 확인', purpose: '미션을 이어 간다', target: backend.name, phase: 'implement' });
1734
+ return { action: 'input', text: answer };
1735
+ }
1736
+ return brain.decide(obs, signal);
1737
+ },
1738
+ };
1739
+ let pendingHandoff: { to: 'codex' | 'claude'; mission: string; summary: string } | undefined;
1740
+ let gatedHandoff = false;
1741
+ let transitionFailure: string | undefined;
1742
+ const handoffOps: HandoffOperations = {
1743
+ start: async (to, mission) => { pendingHandoff = { to, mission, summary: controllerSummary }; },
1744
+ claudeLoggedIn: () => (deps.checkClaudeSubscription ?? checkClaudeSubscription)({ env: resolveBackendSpawn(claudeBackend, process.env).env }).ok,
1745
+ screen: () => h.renderScreen(),
1746
+ alive: () => h.isAlive(),
1747
+ login: async (worktree) => {
1748
+ const loginSpawn = resolveBackendSpawn(claudeBackend, process.env);
1749
+ const handle = spawnPty(buildAgentMissionPtySpawnOptions({
1750
+ backend: claudeBackend,
1751
+ spawn: { cmd: loginSpawn.cmd, args: ['login'], env: { ...loginSpawn.env, TERM: 'xterm-256color' }, unsetEnv: loginSpawn.unsetEnv },
1752
+ workdir: worktree,
1753
+ nickname: `${spec.branch}-login`,
1754
+ }));
1755
+ return { screen: () => handle.renderScreen(), alive: () => handle.isAlive(), close: () => handle.kill() };
1756
+ },
1757
+ sleep: async (ms) => { await sleep(ms); },
1758
+ notify: async (card) => {
1759
+ const { sendOutbound } = await import('../domains/outbound-alert.js');
1760
+ if (!sendOutbound([card.text, card.url, card.code].filter(Boolean).join('\n'), 'agent-mission')) {
1761
+ throw new Error('agent mission login card delivery failed');
1762
+ }
1763
+ },
1764
+ gateAndPr: async (worktree) => {
1765
+ if (spec.commit === false) throw new Error('elanous PR handoff requires commit authorization');
1766
+ const ev = (deps.checkEvidence ?? evidenceCheck)(worktree, spec.evidence);
1767
+ if (!ev.ok) throw new Error(`handoff evidence gate failed: ${ev.retry ?? 'missing evidence'}`);
1768
+ const commit = (deps.commitWorktree ?? commitWorktree)(worktree, `chore(agent-mission): ${spec.branch} handoff`);
1769
+ if (!commit.ok) throw new Error(`handoff commit failed: ${commit.out}`);
1770
+ execFileSync('git', ['push', '-u', 'origin', `HEAD:${spec.branch}`], { cwd: worktree, encoding: 'utf8', timeout: 120_000 });
1771
+ const { dispatchOpenPullRequest } = await import('../tool-runtime/git-pr-runtime.js');
1772
+ dispatchOpenPullRequest({ title: `agent-mission: ${spec.branch}`, body: deps.originalMission ?? spec.mission, head: spec.branch, base: spec.base ?? 'main' }, { cwd: worktree });
1773
+ gatedHandoff = true;
1774
+ },
1775
+ ...deps.handoffOperations,
1776
+ };
1101
1777
  const verifyDone = createMissionVerifyDone({
1102
1778
  worktree: wt.path,
1103
1779
  evidence: spec.evidence,
1104
1780
  checklist,
1105
1781
  coverageRetries,
1106
- checkEvidence: evidenceCheck,
1782
+ checkEvidence: verifyEvidence,
1107
1783
  });
1108
1784
  // ★ P3b-2 observe 어댑터(2026-07-25) — EMIT-side(makeMissionObserveStep)가 프레임 버스에 흘리는 executor
1109
1785
  // 화면을 **구조화 진행 다이제스트**(state+요약·throttle)로 압축해 observe 서피스(로그 패브릭)에 노출한다.
@@ -1114,24 +1790,97 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
1114
1790
  // ★ 동일 버스 인스턴스 보장(리뷰 should-fix) — observe 구독과 EMIT(makeMissionObserveStep)이 **같은** 버스를
1115
1791
  // 봐야 프레임이 흐른다. getChannelBus() 를 두 번 부르지 말고 지역 캐시로 구조적 보장.
1116
1792
  const bus = getChannelBus();
1117
- const control = await runWithControlObserve(
1793
+ const observeStep = makeMissionObserveStep({
1794
+ capture,
1795
+ renderPng: () => h.renderScreenPng(),
1796
+ bus,
1797
+ ident: { ptyId: h.id, instance: resolveInstanceName(), runId },
1798
+ });
1799
+ debug.log('agent-mission', 'takeover-wait', { id: h.id, maxWaitMs: AGENT_MISSION_TAKEOVER_WAIT_MS });
1800
+ const controlRun = runWithControlObserve(
1118
1801
  bus, execSurfaceId(h.id),
1119
1802
  (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 }),
1120
- () => (deps.runControlLoop ?? runPtyControlLoop)(brain, {
1121
- ...controlDepsForHandle(h),
1122
- settle: async () => { await waitForQuiet(h, 6000, 360000); },
1803
+ () => {
1804
+ const handleDeps = controlDepsForHandle(h);
1805
+ const pending = (deps.runControlLoop ?? runPtyControlLoop)(trustAwareBrain, {
1806
+ ...handleDeps,
1807
+ ...(backend.name === 'claude' ? { inject: submitSeparately(handleDeps.inject) } : {}),
1808
+ ...(deps.isMissionAborted ? {
1809
+ controlStance: () => deps.isMissionAborted!() ? 'unknown' as const : probeControlStance(h, 'agent', (e) =>
1810
+ debug.log('agent-mission', 'hascontrol-error', { id: h.id, error: (e as Error)?.message ?? String(e) })),
1811
+ } : {}),
1812
+ awaitOwnership: { maxWaitMs: AGENT_MISSION_TAKEOVER_WAIT_MS },
1813
+ settle: async () => {
1814
+ const quiet = waitForQuiet(h, 6000, 360000);
1815
+ await (deps.awaitMission ? deps.awaitMission(quiet) : quiet);
1816
+ },
1123
1817
  // ★ U5 — 제어스텝 관측: 프레임 버스 발행(PTY 감독 계열 통일 합류·headless #5379 와 동일 seam) + 화면 전사.
1124
1818
  // 발행 먼저·내부 fail-soft(관측이 미션 안 깸)·capture 는 예외 전파(원 semantics). 배선=makeMissionObserveStep.
1125
- onStep: makeMissionObserveStep({
1126
- capture,
1127
- renderPng: () => h.renderScreenPng(),
1128
- bus,
1129
- ident: { ptyId: h.id, instance: resolveInstanceName(), runId },
1130
- }),
1131
- verifyDone,
1132
- }, { maxSteps: maxRounds }),
1819
+ onStep: async (obs, decision) => {
1820
+ await observeStep(obs, decision);
1821
+ if (backend.name === 'claude') {
1822
+ // Keep only review findings, not authentication screens or a raw PTY transcript.
1823
+ const finding = obs.screen.match(/(?:review findings?|finding|issues?|지적|문제)\s*[::]\s*([^\r\n]+)/i)?.[1]?.trim();
1824
+ if (finding && !/login|log in|sign in|https?:\/\/|token|cookie|password|장치 코드|로그인/i.test(finding)) {
1825
+ reviewSummary = `${reviewSummary}\n${finding}`.trim().slice(-3500);
1826
+ }
1827
+ }
1828
+ },
1829
+ verifyDone: spec.chain && spec.chain.length > 1 ? async () => ({ ok: true as const }) : verifyDone,
1830
+ handoff: async (decision, obs) => {
1831
+ try {
1832
+ if (spec.chain && decision.to !== spec.chain[1]) throw new Error(`chain order violation: expected ${spec.chain[1] ?? 'completion'}, got ${decision.to}`);
1833
+ if (await handoffMission(decision, wt.path, handoffOps, reviewSummary || controllerSummary) === 'gated') gatedHandoff = true;
1834
+ } catch (error) {
1835
+ transitionFailure = error instanceof Error ? error.message : String(error);
1836
+ throw error;
1837
+ }
1838
+ },
1839
+ askHuman: async (decision) => {
1840
+ try {
1841
+ await waitForHumanLogin(decision, handoffOps);
1842
+ } catch (error) {
1843
+ transitionFailure = error instanceof Error ? error.message : String(error);
1844
+ throw error;
1845
+ }
1846
+ },
1847
+ }, { maxSteps: maxRounds });
1848
+ deps.onControlActive?.(pending);
1849
+ return pending;
1850
+ },
1133
1851
  { onSettled: (digestCount) => debug.log('agent-mission.observe', 'summary', { digestCount }), observeOpts: { expectRunId: runId } },
1134
1852
  );
1853
+ deps.onControlPending?.(controlRun);
1854
+ const control = await (deps.awaitMission ? deps.awaitMission(controlRun) : controlRun);
1855
+ if (deps.isMissionAborted?.()) throw new Error('MISSION_ABORTED');
1856
+ if (control.termination.kind === 'success' && !control.handoff && spec.chain && spec.chain.length > 1) {
1857
+ const to = spec.chain[1]!;
1858
+ try {
1859
+ if (await handoffMission({ action: 'handoff', to, mission: to === 'claude' ? 'Review changes and report findings; do not rewrite the original mission.' : to === 'codex' ? `Address the review findings and finish the original mission.\nOriginal mission:\n${deps.originalMission ?? spec.mission}` : deps.originalMission ?? spec.mission, carry: to === 'claude' ? 'diff' : 'summary' }, wt.path, handoffOps, reviewSummary || controllerSummary) === 'gated') gatedHandoff = true;
1860
+ } catch (error) {
1861
+ stopLive();
1862
+ try { h.kill(); } catch { /* noop */ }
1863
+ throw error;
1864
+ }
1865
+ }
1866
+ const nextChain = spec.chain?.slice(1);
1867
+ if (transitionFailure || (control.termination.kind !== 'success' && pendingHandoff)) {
1868
+ stopLive();
1869
+ try { h.kill(); } catch { /* noop */ }
1870
+ throw new Error(transitionFailure ?? 'handoff was requested but the PTY control loop did not finish successfully');
1871
+ }
1872
+ if (pendingHandoff) {
1873
+ stopLive();
1874
+ try { h.kill(); } catch { /* noop */ }
1875
+ const next = pendingHandoff;
1876
+ return runAgentMission({ ...spec, plugin: undefined, agent: resolveBackend(next.to), mission: next.mission, chain: nextChain && nextChain.length > 1 ? nextChain : undefined, enhance: false, memory: false }, { ...deps, handoffWorktree: { path: wt.path, branch: wt.branch!, base: wt.base! }, originalMission: deps.originalMission ?? spec.mission, previousSummary: next.summary, initialTsc: baselineTsc, runtimeFallback: { ...runtimeFallback, fallbackEligible: false } });
1877
+ }
1878
+ // A gate/PR handoff only counts as success when the control loop itself did not end in error.
1879
+ if (gatedHandoff && control.termination.kind !== 'error') {
1880
+ stopLive();
1881
+ try { h.kill(); } catch { /* noop */ }
1882
+ return { ok: true, worktree: wt.path, branch: wt.branch, rounds: control.steps, evidencePath: wt.path, committed: true, usedOmniCrawl: usedOmni, detail: '완료(증거 게이트·PR)' };
1883
+ }
1135
1884
  const done = control.termination.kind === 'success';
1136
1885
  const round = control.steps;
1137
1886
  if (control.termination.kind === 'error') {
@@ -1156,46 +1905,49 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
1156
1905
  descents: runtimeFallback.descents,
1157
1906
  maxFallbackDescents: runtimeFallback.maxDescents,
1158
1907
  });
1159
- if (nextBackend) {
1908
+ if (nextBackend && !deps.isMissionAborted?.()) {
1160
1909
  const nextStep: FallbackStep = nextBackend.name === 'grok' ? 'grok' : 'codex-rotate';
1161
1910
  stopLive();
1911
+ if (h.pid) await (deps.terminateProcessTree ?? terminateMissionProcessTree)(h.pid);
1162
1912
  try { h.kill(); } catch { /* noop */ }
1163
- return runAgentMission(
1164
- { ...spec, agent: nextBackend, reuseOwnedWorktree: true },
1165
- {
1166
- ...deps,
1167
- runtimeFallback: {
1168
- ...runtimeFallback,
1169
- attemptedSteps: new Set([...runtimeFallback.attemptedSteps, nextStep]),
1170
- descents: runtimeFallback.descents + 1,
1171
- },
1913
+ const nextSpec = { ...spec, agent: nextBackend, reuseOwnedWorktree: true };
1914
+ const nextDeps = {
1915
+ ...deps,
1916
+ runtimeFallback: {
1917
+ ...runtimeFallback,
1918
+ attemptedSteps: new Set([...runtimeFallback.attemptedSteps, nextStep]),
1919
+ descents: runtimeFallback.descents + 1,
1172
1920
  },
1173
- );
1921
+ };
1922
+ // Keep the original signal owner and outside-write baseline across a replacement PTY.
1923
+ return spec.signal || spec.workdir ? runAgentMissionBody(nextSpec, nextDeps, startedAt, initialFiles) : runAgentMission(nextSpec, nextDeps);
1174
1924
  }
1175
1925
  }
1176
1926
  debug.log('agent-mission', 'control-result', { termination: control.termination.kind, steps: control.steps });
1177
1927
  if (control.termination.kind === 'cancelled') {
1178
1928
  stopLive();
1179
- try { h.kill(); } catch { /* noop */ }
1180
1929
  throw new Error('AGENT_YIELDED: PTY 제어가 사람에게 이양됨(takeover) — 자율 미션 중단');
1181
1930
  }
1182
1931
 
1183
- const finalEv = evidenceCheck(wt.path, spec.evidence);
1932
+ if (deps.isMissionAborted?.()) return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
1933
+ rounds: round, evidencePath: null, committed: false, usedOmniCrawl: usedOmni, detail: 'aborted' };
1934
+ const finalEv = verifyEvidence(wt.path, spec.evidence);
1184
1935
  const evidencePath = finalEv.ok ? finalEv.path : null;
1185
1936
  let committed = false;
1186
- if (finalEv.ok && (spec.commit ?? true)) {
1187
- const c = commitWorktree(wt.path, `chore(agent-mission): ${spec.branch} — ${backend.name}-in-elanous PTY RFC 산출`);
1937
+ if (!deps.isMissionAborted?.() && !spec.workdir && finalEv.ok && (spec.commit ?? true)) {
1938
+ const c = (deps.commitWorktree ?? commitWorktree)(wt.path, `chore(agent-mission): ${spec.branch} — ${backend.name}-in-elanous PTY RFC 산출`);
1188
1939
  committed = c.ok;
1189
1940
  debug.log('agent-mission', 'commit', { ok: c.ok, out: c.out.slice(0, 120) });
1190
1941
  }
1191
1942
  debug.log('agent-mission', 'result', { ok: finalEv.ok, rounds: round, evidencePath, committed, usedOmni });
1192
1943
  stopLive();
1944
+ if (h.pid) await terminateMissionProcessTree(h.pid);
1193
1945
  try { h.kill(); } catch { /* noop */ }
1194
- await sleep(400);
1195
1946
 
1196
1947
  return {
1197
1948
  ok: finalEv.ok, worktree: wt.path, branch: wt.branch, rounds: round,
1198
1949
  evidencePath, committed, usedOmniCrawl: usedOmni,
1950
+ ptyId: h.id, webUrl: webAddress.webUrl,
1199
1951
  detail: done ? '완료(증거 충족)' : (finalEv.ok ? '증거 충족(루프 종료)' : '미완(증거 부족)'),
1200
1952
  };
1201
1953
  }