elanous 0.2.42 → 0.2.44

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 (764) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → HMXsxdy5MIIcHPMHv1wD4}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/08334415.f0e80896acbef722.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1032-78ba4f6391258cab.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1082-53f86a26e03d309d.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1109-7d0e264f6f2edbc7.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1124-7c26330402481143.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{2160.a097e7b138ae1c55.js → 118.2a89982fe4276880.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1244.6c435dbf1bf21d8a.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1252.9e665904d3aa3b1a.js +32 -0
  12. package/apps/pwa/out/_next/static/chunks/1266.a46cc33cb6a72d75.js +104 -0
  13. package/apps/pwa/out/_next/static/chunks/1306.967240ede9a0f757.js +24 -0
  14. package/apps/pwa/out/_next/static/chunks/1344.3b95f3bd1b77a3fe.js +94 -0
  15. package/apps/pwa/out/_next/static/chunks/{4043.6b91203436c9c86b.js → 1401.22dfe92640a2b1ac.js} +4 -4
  16. package/apps/pwa/out/_next/static/chunks/1431-f7c78bd5be21e011.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1451-cdd35a8a0b31834b.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{6632.0eac1c554f8f2ef3.js → 1694.18debfd77562e56d.js} +2 -2
  19. package/apps/pwa/out/_next/static/chunks/1708-f03d587b7a7545c8.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1775-fa7152bdeff6c95f.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/178-4da509cd7266672a.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/1850-522de4ee34957210.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/1876-c6f6e0ddcc76c6a1.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/1976.097066b072432242.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{3507.97e1977bc4d5fb0a.js → 1978.eeb60a606dc5deac.js} +2 -2
  26. package/apps/pwa/out/_next/static/chunks/2043.e233e3b5a3e790f5.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2150.71b94e3348107c83.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2158.ebc6fc5a10280ab7.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2216.802962c04f40a26e.js +64 -0
  30. package/apps/pwa/out/_next/static/chunks/2294.7890edcfa046c97d.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/235.c89aaae4bcd6233a.js +74 -0
  32. package/apps/pwa/out/_next/static/chunks/{5885.0a3e52c8faccec98.js → 239.de075467b5523469.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/249.ba7051590d603c8f.js +226 -0
  34. package/apps/pwa/out/_next/static/chunks/2571.a6ac4e26c8618403.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/2610.e149cd564a08913e.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/2705.9816f3c244f8b85f.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/2801.afeb8a4dae22f85f.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/2954.bbefc95d6b20e0d8.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/2e0f720a.a0697c08e3806a60.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3042.96ec235fe41c8d4e.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3097-8e358f158acef46b.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3205-93b1abe28b4fb16a.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3273.b4434f0dcae7eb29.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3311.9cbc43ea0c90d60c.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{1487.2f67b79444062da6.js → 3349.b5f09ee474d9533e.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/3503.a47a9755fb4d97b0.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/3506-5f429b3b7e1392b0.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/3843.bad404d008893291.js +77 -0
  49. package/apps/pwa/out/_next/static/chunks/3877-4b40e530b47e3bf9.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/435-ce2958253cf7de61.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4393.28fa5228d0eec217.js +149 -0
  52. package/apps/pwa/out/_next/static/chunks/4404.7281c847c6e10dfc.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/{8673-bab689a55f7e13b9.js → 4415-b9d6a90960920a4a.js} +3 -3
  54. package/apps/pwa/out/_next/static/chunks/447-5b304de1fe098f43.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/4484-8ebea83d431e6fae.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/{8262.ddc03e06b733f184.js → 4502.bdcc877abd437a05.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/4599-f95790fc5c65b8df.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{1262.e804feb8fd1acb8c.js → 46.57c783fa4884714f.js} +2 -2
  59. package/apps/pwa/out/_next/static/chunks/463-b9114e411f33728e.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/4659.a57d1f0c5d754cd2.js +36 -0
  61. package/apps/pwa/out/_next/static/chunks/4722-a847e7a28115035f.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/{1063.2fb8a9dc55c731f2.js → 4757.67c6d7473a038e78.js} +1 -1
  63. package/apps/pwa/out/_next/static/chunks/4874-c86f878ec4502ad3.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{6377.bc7df239edbff244.js → 4891.3f80ba517a3b2373.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/4998.810ca8833084caa9.js +62 -0
  66. package/apps/pwa/out/_next/static/chunks/4f98febc.ea5841d4d616bfb2.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/{3482.a9ae9d2ad6a5bd97.js → 5052.7dbb12a55d4f18f5.js} +1 -1
  68. package/apps/pwa/out/_next/static/chunks/5166-ca73b3e361085a6d.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/5180-039f4a18b07ad387.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/5232.5a2ce4daf7a9e11d.js +115 -0
  71. package/apps/pwa/out/_next/static/chunks/5439.3fec6dbce29ecb36.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/5612-074d9a5e00dfac6a.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/5675-01989d524a84c505.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/5751.af641a1adf5ec697.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/5758-c6cb98714d18ab0c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/578eded8.b582637306e16964.js +122 -0
  77. package/apps/pwa/out/_next/static/chunks/5790.5eb06a653ebd8571.js +34 -0
  78. package/apps/pwa/out/_next/static/chunks/5853-4033e5bd5afbe06b.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/5904.97d70bb7f46b2db7.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/{3347.f846266b5e5f3ede.js → 5989.7ecd362c5c44b747.js} +3 -3
  81. package/apps/pwa/out/_next/static/chunks/{73d2eb0e.4966ad55293c801a.js → 5a34fb2f.52f1b4e1baebb48a.js} +3 -3
  82. package/apps/pwa/out/_next/static/chunks/{7a98bc80.fa935989e829f9c2.js → 5a5078f8.2099200e5ea95e16.js} +1 -1
  83. package/apps/pwa/out/_next/static/chunks/6036-c302c34ff0b3d410.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/606.ef81c313381f4264.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/616.1af54a928b1ba704.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/6201.bc936f71f613a8e9.js +41 -0
  87. package/apps/pwa/out/_next/static/chunks/6204-fdc86e0e64c4f92d.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/{7411.9b4b8b747dc7b802.js → 6245.1182e007e9d230d9.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/{b450776b.3db34d8d965f82d3.js → 63699a35.17262e162bc514b2.js} +1 -1
  90. package/apps/pwa/out/_next/static/chunks/6420.494801a80030160c.js +27 -0
  91. package/apps/pwa/out/_next/static/chunks/{e8543907.5b040a5f22a0b0e5.js → 6549dad0.2740b25e51bf8f05.js} +1 -1
  92. package/apps/pwa/out/_next/static/chunks/{9427.96aa912ddb5801e0.js → 6881.9e7955847640c7fe.js} +17 -17
  93. package/apps/pwa/out/_next/static/chunks/6931.fcdfb94141e67b3d.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/6991-8e081c6ce38c0ba1.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7010.1bbd17a7f2b3e376.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7029.d1466acf55fae2ed.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7152-a123aa8e129c131f.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7455.196168fffac3b9c4.js +24 -0
  99. package/apps/pwa/out/_next/static/chunks/7638.6ca4770dd1129138.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/7649-f37d76260e5e2a5a.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/7679.32c40cdd14f20b4a.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/7751.04bfbd16b4c6cd0a.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/7864.b1ff31d4030b8994.js +148 -0
  104. package/apps/pwa/out/_next/static/chunks/7869-c47bd2c075c1fefa.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{8138.6c10b2a356d52fca.js → 8442.2f09ca969d631615.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8445.2738dbd59a78c78c.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8447.5510c439f9938c6d.js +286 -0
  108. package/apps/pwa/out/_next/static/chunks/{9415.69e4a21c60c7d2db.js → 8551.f762945c2cda2e95.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/8635-57a9d8d9db70f4f1.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/86961958-4b0689a5048f756b.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/8709.3c6019bb18f8554f.js +8 -0
  112. package/apps/pwa/out/_next/static/chunks/8759.c999528a0a907bf6.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{9a852a62-6192a6ea9346ced3.js → 87f498e5-0881de09f2e44707.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/8843.c3197f904c952b81.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/{3d0154af.5331fec737ffe8c3.js → 892fd990.456232f326cc39c2.js} +1 -1
  116. package/apps/pwa/out/_next/static/chunks/8965-135a2c9eaa2464cb.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/8971-8d3b9c96f8a6c958.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9059.c8598d96f8e5e9cd.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9115.90447ae198b84eae.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9147.d9b0a02e0babc9b4.js +93 -0
  121. package/apps/pwa/out/_next/static/chunks/9204-83075f4b70c61cdc.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9244-c32ef14b5dc72bdf.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/930.2a9a30f964350c66.js +90 -0
  124. package/apps/pwa/out/_next/static/chunks/9398.1f56e3f17795f43f.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/9527.3e5ad31c891c5fcb.js +79 -0
  126. package/apps/pwa/out/_next/static/chunks/9571-4ac933e774d1225c.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-9fc644de2d8edae3.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/approvals/page-0c9dace2db62bee8.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f5e65c3dc9d89f2a.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/board/page-2a9c19b9a140b7b1.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/botlab/page-61533ad92141adfb.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/bots/page-112004ced6fd0329.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/ceo/page-f733318c237a49d8.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/chat/page-51ea677d2d33bbc0.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/consult/page-428b41f2f9566e3c.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/control/page-1b29396ea90a61e5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/decisions/page-cf83ec613ac904bf.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/design-check/page-3f4c0ecbc284bb5f.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/editor/page-b63c322f54f70cc6.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/exec/page-fe328c4ee9aac6b4.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/field/page-bfb855c584f0fb98.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/healthz/route-9fc644de2d8edae3.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/inside/page-47b1710c110eabd7.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/intake/page-42895214458bc6d2.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/layout-d03de0ebd8366e23.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live/page-3ed6c47e4b1c61c2.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/live-run/page-ae653e9bf261c738.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/loops/page-23f3f0a0209c0ac4.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/market/page-88c691273aae66f9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e187ac52a95538b3.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/morning/page-6e45828daed1295e.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/not-found-edb5d7287bb46186.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4a7eaacd93c3f6a5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ca073d43d74cc84.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1e9fee67b1199436.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-df1283ea963c6816.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/outputs/page-19fcf8d8301ccd18.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/page-5ab699e0303bbb40.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7cde0d29756984c5.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-9d4c598e8ee22f7a.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/sessions/page-cc1609a71f44ec62.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7659a9a1345bfaa9.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/settings/page-0afef60ecc0c4af5.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-a3553949f8f34f5f.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/layout-9fc644de2d8edae3.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/setup/page-057a69702f3c67c7.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/share/page-c0f0e570f3f74c73.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/showroom/page-1825071ae34e3b89.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/tasks/page-6244e3e135d8ccfc.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/term/page-da787e8a10b8a82e.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/today/page-1316d32498e2be42.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/trace/page-4df94572e343de2e.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/vault/page-708969f7475e88c1.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-c58add08c919a1dc.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workflows/page-a24847f45e5d5bf9.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/workspace/page-acfec65a3a60e22e.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-3dfc598e6fbde245.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-c658a626118411b7.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-4c73685fd891445b.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-6310f7e5de7dd01d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-51c326bf48610be1.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-d0beadf754da59b0.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-acd243bfbf3f6732.js +1 -0
  184. package/apps/pwa/out/_next/static/css/d1f8bb401740a549.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/catalog/external-commands.yaml +5 -3
  279. package/catalog/meta/catalogVersion.yaml +2 -1
  280. package/catalog/signing/catalog-signing-public.pem +3 -0
  281. package/graphs/intake/intake-daily.yaml +16 -0
  282. package/graphs/intake/news-sources.yaml +1 -0
  283. package/graphs/intake/recipes.yaml +7 -0
  284. package/graphs/overlays/README.md +6 -0
  285. package/graphs/overlays/examples/research-runtime-empty-terminal.yaml +28 -0
  286. package/graphs/profiles/local.yaml +5 -0
  287. package/graphs/profiles/pod.yaml +4 -0
  288. package/graphs/release/release-loop.yaml +33 -17
  289. package/graphs/units/verbs/make-doc.yaml +1 -0
  290. package/package.json +6 -2
  291. package/plugins/demo-absorption-briefing/plugin.json +18 -0
  292. package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
  293. package/plugins/demo-browser-hand/plugin.json +13 -0
  294. package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
  295. package/plugins/demo-linear-secretary/plugin.json +15 -0
  296. package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
  297. package/plugins/demo-plugin-wizard/plugin.json +11 -0
  298. package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
  299. package/plugins/demo-research/plugin.json +16 -0
  300. package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
  301. package/plugins/demo-video-briefing/plugin.json +15 -0
  302. package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
  303. package/scripts/bench-metering-plan.ts +229 -0
  304. package/scripts/build-signed-catalog.ts +48 -0
  305. package/scripts/ci-typecheck-main-delta.sh +88 -0
  306. package/scripts/codex-fallback-live-probe.ts +1 -1
  307. package/scripts/demo/demo1104-parallel-host.ts +56 -0
  308. package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
  309. package/scripts/demo/demo1104-parallel.ts +72 -0
  310. package/scripts/demo/demo1104-stage.config.ts +21 -0
  311. package/scripts/demo/demo1104-stage.ts +316 -0
  312. package/scripts/goal-method-audit.ts +17 -1
  313. package/scripts/graph-units/land-enqueue.ts +90 -0
  314. package/scripts/hooks/codex-notify.sh +32 -0
  315. package/scripts/install.sh +10 -38
  316. package/scripts/landing-heal/land-plan.ts +57 -0
  317. package/scripts/public-leak-baseline.txt +0 -1
  318. package/scripts/release-loop/auto-approve-node.ts +1 -1
  319. package/scripts/release-loop/docs-node.ts +4 -2
  320. package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
  321. package/scripts/release-loop/gate-image-pin.ts +116 -2
  322. package/scripts/release-loop/gate-method.ts +139 -0
  323. package/scripts/release-loop/gate-node.ts +395 -43
  324. package/scripts/release-loop/gate-progress-sim.ts +73 -0
  325. package/scripts/release-loop/gate-traffic-mode.ts +151 -3
  326. package/scripts/release-loop/node-verdict.ts +38 -25
  327. package/scripts/release-loop/notes-repair.ts +18 -1
  328. package/scripts/release-loop/preflight.ts +544 -10
  329. package/scripts/release-loop/render-warm-control-manifest.ts +22 -0
  330. package/scripts/release-loop/resume-release.ts +9 -7
  331. package/scripts/release-loop/resume.ts +13 -4
  332. package/scripts/release-loop/unattended-release.ts +20 -9
  333. package/scripts/release-loop/warm-control-forward.ts +178 -0
  334. package/scripts/retro-cycle.ts +30 -8
  335. package/scripts/rhythm/daily.ts +39 -4
  336. package/scripts/rhythm/linear-progress-sync.ts +311 -0
  337. package/scripts/ux-sim.ts +7 -1
  338. package/scripts/video-pipeline.ts +9 -1
  339. package/scripts/warm-pool-provider-config.ts +35 -7
  340. package/src/acp/agent-manager.ts +1 -0
  341. package/src/acp/codex-app-server-agent.ts +33 -0
  342. package/src/acp/codex-app-server-client.ts +153 -16
  343. package/src/acp/core-turn-bridge.ts +17 -12
  344. package/src/acp/event-router.ts +20 -1
  345. package/src/acp/server.ts +6 -0
  346. package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
  347. package/src/agent-mission/claude-headless.ts +4 -1
  348. package/src/agent-mission/codex-exec.ts +105 -0
  349. package/src/agent-mission/driver.ts +192 -11
  350. package/src/agent-mission/grok-auth-status.ts +107 -0
  351. package/src/agent-mission/hand-hooks.ts +101 -0
  352. package/src/agent-mission/mission-cli.ts +56 -21
  353. package/src/agent-mission/mission-hand-reply.ts +118 -0
  354. package/src/agent-mission/mission-line.ts +180 -0
  355. package/src/agent-mission/mission-out.ts +256 -18
  356. package/src/agent-mission/tool-install.ts +122 -11
  357. package/src/agent-substrate/pr-reviewer.ts +147 -11
  358. package/src/agent-substrate/self-review-cli.ts +10 -2
  359. package/src/agents/general-purpose.md +1 -1
  360. package/src/auto-research/research-fanout.ts +221 -0
  361. package/src/auto-research/research-turn.ts +362 -31
  362. package/src/autopilot/mission-codebase-gate.ts +7 -3
  363. package/src/autopilot/pr-manager.ts +31 -3
  364. package/src/boot/daemon-tools/self-implement.ts +3 -1
  365. package/src/boot/daemon-tools/web-search.ts +1 -2
  366. package/src/briefing/brief-items.ts +55 -11
  367. package/src/cli/agent-cli.ts +2 -1
  368. package/src/cli/catalog-cli.ts +31 -0
  369. package/src/cli/connector-cli.ts +16 -0
  370. package/src/cli/control-cli.ts +15 -6
  371. package/src/cli/doctor-fix.ts +2 -2
  372. package/src/cli/intake-source-cli.ts +44 -8
  373. package/src/cli/log-event-names.ts +8 -0
  374. package/src/cli/msg-cli.ts +32 -3
  375. package/src/cli/pr-cli.ts +21 -1
  376. package/src/cli/pr-land-heavy-remote.ts +44 -6
  377. package/src/cli/pr-land-overlap-evidence.ts +13 -1
  378. package/src/cli/pr-land-pod-shadow-job.ts +143 -5
  379. package/src/cli/pr-land-pod-shadow.ts +9 -2
  380. package/src/cli/release-checklist-read-cli.ts +44 -16
  381. package/src/cli/release-cli.ts +23 -3
  382. package/src/cli/research-cli.ts +9 -0
  383. package/src/cli/setup-cli.ts +166 -6
  384. package/src/cli/setup-keys.ts +199 -0
  385. package/src/cli/task-plugin-wizard-host.ts +114 -0
  386. package/src/cli/tasks-cli.ts +54 -9
  387. package/src/cli/tui-test-cli.ts +190 -0
  388. package/src/config.ts +4 -2
  389. package/src/connectors/linear-daily-progress.ts +228 -0
  390. package/src/connectors/linear-projector.ts +34 -12
  391. package/src/connectors/linear.ts +151 -7
  392. package/src/control-plane/ledger.ts +42 -4
  393. package/src/control-plane/member-tokens.ts +25 -2
  394. package/src/control-plane/ports.ts +8 -3
  395. package/src/control-plane/server.ts +26 -5
  396. package/src/core-turn/deep-turn-bloom.ts +67 -0
  397. package/src/core-turn/research-policy.ts +43 -0
  398. package/src/core-turn/run-core-turn.ts +488 -51
  399. package/src/core-turn/types.ts +4 -0
  400. package/src/dashboard/chat/acp-chat.ts +10 -0
  401. package/src/dashboard/classic-sidetab-mission-job.ts +192 -0
  402. package/src/dashboard/classic-sidetab-mission-pair.ts +82 -0
  403. package/src/dashboard/classic-sidetab-mission-trio.ts +242 -0
  404. package/src/dashboard/classic-sidetab-mission.ts +169 -5
  405. package/src/dashboard/index.ts +387 -14
  406. package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
  407. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +8 -0
  408. package/src/dashboard/mission-cli-consumer.ts +20 -8
  409. package/src/dashboard/plugin-wizard-runtime.ts +50 -0
  410. package/src/dashboard/plugin-wizard-tool.ts +55 -0
  411. package/src/dashboard/sidetab-runtime.ts +3 -1
  412. package/src/dashboard/terminal-popup-runtime.ts +6 -3
  413. package/src/dashboard/visible-mission-diagnostics.ts +16 -0
  414. package/src/decisions/linear-progress-summary.ts +78 -0
  415. package/src/decisions/linear-progress-sync.ts +152 -0
  416. package/src/domains/outbound-alert.ts +49 -11
  417. package/src/domains/retro-cycle-observation.ts +43 -0
  418. package/src/domains/retro-cycle.ts +13 -2
  419. package/src/domains/retro-proposals.ts +92 -0
  420. package/src/domains/retro-report.ts +6 -1
  421. package/src/domains/telegram-kind-route.ts +16 -9
  422. package/src/graph-runner/arg-allowance.ts +13 -0
  423. package/src/graph-runner/graph-cli.ts +24 -1
  424. package/src/graph-runner/graph-grow-llm.ts +3 -1
  425. package/src/graph-runner/graph-run-api.ts +3 -1
  426. package/src/graph-runner/runner.ts +310 -46
  427. package/src/graph-wizard/mission-compose.ts +407 -12
  428. package/src/harness/dispatch-backpressure.ts +54 -1
  429. package/src/harness/dispatch-shadow-compare.ts +74 -0
  430. package/src/harness/harness-cli-command.ts +15 -3
  431. package/src/harness/harness-pod-dispatch.ts +3 -0
  432. package/src/harness/skill-exec.ts +21 -9
  433. package/src/harness/skill-select.ts +1 -1
  434. package/src/hooks/error-report-cloud.ts +101 -0
  435. package/src/hooks/receiver.ts +29 -2
  436. package/src/index.ts +129 -12
  437. package/src/intake-plane/actions.ts +354 -0
  438. package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
  439. package/src/intake-plane/intake-sources.ts +78 -8
  440. package/src/intake-plane/items.ts +14 -4
  441. package/src/intake-plane/linear-mission-sync.ts +80 -0
  442. package/src/intake-plane/linear-secretary-runtime.ts +178 -0
  443. package/src/intake-plane/linear-wish.ts +227 -1
  444. package/src/life/life-cli.ts +168 -0
  445. package/src/life/life-kinds.ts +160 -0
  446. package/src/live-supply/budget-consumer.ts +78 -0
  447. package/src/live-supply/read.ts +3 -0
  448. package/src/live-supply/snapshot.ts +45 -0
  449. package/src/llm/child-first-llm-observation.ts +112 -0
  450. package/src/llm/provider-credentials.ts +68 -6
  451. package/src/llm/provider-failure-evidence.ts +44 -0
  452. package/src/llm.ts +172 -12
  453. package/src/maturity/feature-maturity.ts +3 -3
  454. package/src/mcp/client.ts +7 -0
  455. package/src/mcp/proxy-runtime.ts +6 -1
  456. package/src/mcp/server.ts +54 -0
  457. package/src/msg/msg-sse-server.ts +3 -3
  458. package/src/msg/msg-store.ts +177 -19
  459. package/src/native-tool-catalog.ts +36 -2
  460. package/src/nexus/api/consult-requests.ts +18 -6
  461. package/src/nexus/api/discord-trigger-bot.ts +6 -6
  462. package/src/nexus/api/graphs-api.ts +4 -2
  463. package/src/nexus/api/grokbot-trigger-bot.ts +206 -0
  464. package/src/nexus/api/http-server.ts +37 -1
  465. package/src/nexus/api/mcp-public-allowlist.ts +2 -0
  466. package/src/nexus/api/telegram-trigger-bot.ts +6 -6
  467. package/src/nexus/boot/register-mcp-clients.ts +114 -8
  468. package/src/nexus/index.ts +22 -2
  469. package/src/nexus/outbound/format.ts +9 -0
  470. package/src/nexus/outbound/grokbot-adapter.ts +71 -0
  471. package/src/nexus/outbound/router.ts +121 -16
  472. package/src/nexus/setup-status.ts +9 -0
  473. package/src/nexus/state/state.ts +3 -0
  474. package/src/oauth/codex-account-store.ts +20 -7
  475. package/src/oauth/codex-owner-mirror.ts +81 -0
  476. package/src/oauth/codex.ts +17 -2
  477. package/src/oauth/fallback-chain.ts +47 -17
  478. package/src/onboarding/first-run-doctor.ts +8 -1
  479. package/src/onboarding/first-run.ts +126 -29
  480. package/src/onboarding/key-setup.ts +103 -0
  481. package/src/onboarding/menu-answer.ts +13 -0
  482. package/src/onboarding/secret-prompt.ts +37 -0
  483. package/src/plugins/install/plugin-install.ts +59 -0
  484. package/src/pr-tool/census.ts +130 -0
  485. package/src/preview/terminal.ts +22 -7
  486. package/src/prompt-enhance/enhance.ts +10 -0
  487. package/src/pty-shell/pty-control-ipc.ts +4 -1
  488. package/src/pty-shell/pty-write-provenance.ts +21 -3
  489. package/src/pty-shell/registry.ts +9 -2
  490. package/src/registry/catalog-server.ts +232 -0
  491. package/src/registry/loader.ts +45 -1
  492. package/src/registry/types.ts +1 -2
  493. package/src/release-loop/proposal-auto-place.ts +83 -0
  494. package/src/research/axis-fanout.ts +79 -29
  495. package/src/research/lenses/second-order.ts +312 -0
  496. package/src/self-dev/ask-launch-flow.ts +72 -1
  497. package/src/self-dev/dev-cli.ts +7 -2
  498. package/src/self-dev/dev-pipeline.ts +5 -0
  499. package/src/self-dev/draft-residue.ts +64 -5
  500. package/src/self-dev/draft-sweep.ts +31 -10
  501. package/src/self-dev/draft-triage-rules.ts +60 -3
  502. package/src/self-dev/graph-front-nodes.ts +2 -1
  503. package/src/self-dev/graph-journey-route.ts +76 -21
  504. package/src/self-dev/launch-preflight.ts +58 -0
  505. package/src/self-dev/orchestrate.ts +1 -1
  506. package/src/self-dev/run-supervisor.ts +152 -2
  507. package/src/self-dev/shard-aggregate.ts +4 -0
  508. package/src/self-dev/shard-run.ts +36 -15
  509. package/src/self-implement/abandoned-classification.ts +12 -3
  510. package/src/self-implement/budget-gate.ts +7 -0
  511. package/src/self-implement/child-llm-preference.ts +10 -1
  512. package/src/self-implement/doctor-visit.ts +30 -8
  513. package/src/self-implement/elanous-tui-spawn.ts +3 -0
  514. package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
  515. package/src/self-implement/gate-artifacts.ts +2 -1
  516. package/src/self-implement/goal-author-cli.ts +4 -2
  517. package/src/self-implement/goal-author.ts +549 -10
  518. package/src/self-implement/graph-overlay-yaml.ts +181 -4
  519. package/src/self-implement/graph-overlay.ts +3 -1
  520. package/src/self-implement/graph-profile-yaml.ts +107 -0
  521. package/src/self-implement/graph-yaml.ts +94 -5
  522. package/src/self-implement/off-diff-evidence.ts +249 -5
  523. package/src/self-implement/orchestrator.ts +298 -26
  524. package/src/self-implement/run-chart.ts +6 -3
  525. package/src/self-implement/run-ledger.ts +51 -1
  526. package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
  527. package/src/self-implement/tdd-evidence-tags.ts +9 -0
  528. package/src/self-implement/test-scenario-request.ts +37 -6
  529. package/src/self-implement/train-gate-receipt.ts +166 -0
  530. package/src/self-implement/train-gate-remote.ts +62 -18
  531. package/src/session/chat.ts +6 -4
  532. package/src/session/session-fanout.ts +2 -0
  533. package/src/session/streaming/acp-stream-sink.ts +2 -1
  534. package/src/session/streaming/chunk-producer.ts +6 -0
  535. package/src/session/streaming/stream-compositor.ts +3 -2
  536. package/src/session-runtime/index.ts +74 -6
  537. package/src/session-runtime/retry-policy.ts +1 -1
  538. package/src/setup/llm-env-detect.ts +3 -0
  539. package/src/setup/service-key-catalog.ts +46 -0
  540. package/src/setup/service-keys.ts +241 -0
  541. package/src/sidetab-core/model.ts +205 -10
  542. package/src/sidetab-core/visible-agent-mission-pair.ts +51 -0
  543. package/src/sidetab-core/visible-agent-mission.ts +182 -48
  544. package/src/skills/tools/agent.ts +23 -4
  545. package/src/skills/tools/omni-search.ts +127 -27
  546. package/src/task-agent/parent-host.ts +29 -1
  547. package/src/task-agent/recall-inject.ts +98 -0
  548. package/src/task-agent/repair-outcomes.ts +65 -0
  549. package/src/task-agent/task-hand.ts +46 -14
  550. package/src/task-orchestrator/dispatcher.ts +14 -1
  551. package/src/task-orchestrator/linear-capture-events.ts +55 -0
  552. package/src/task-orchestrator/store.ts +16 -5
  553. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +23 -1
  554. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +107 -1
  555. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
  556. package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +21 -9
  557. package/src/task-orchestrator/surfaces/pod-source-receive.ts +23 -11
  558. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
  559. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +1 -1
  560. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +467 -77
  561. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +45 -3
  562. package/src/task-orchestrator/surfaces/self-implement-pod.ts +210 -14
  563. package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
  564. package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
  565. package/src/task-orchestrator/types.ts +14 -0
  566. package/src/telegram.ts +14 -16
  567. package/src/terminal/coding-agent.ts +14 -5
  568. package/src/terminal/session-registry.ts +1 -1
  569. package/src/tool-hints/gate.ts +46 -14
  570. package/src/tool-hints/signals.ts +1 -1
  571. package/src/tool-hints/types.ts +2 -0
  572. package/src/tool-runtime/agent-runtime.ts +1 -0
  573. package/src/tool-runtime/browser-hand-runtime.ts +391 -0
  574. package/src/tool-runtime/browser-runtime.ts +33 -19
  575. package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
  576. package/src/tool-runtime/elanous-linear-secretary-runtime.ts +173 -0
  577. package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
  578. package/src/tool-runtime/index.ts +6 -0
  579. package/src/tool-runtime/types.ts +5 -0
  580. package/src/tui/entry.ts +51 -8
  581. package/src/tui/sidetab/attach.ts +252 -11
  582. package/src/tui/sidetab/herdr-portal.ts +225 -0
  583. package/src/tui/sidetab/list.ts +3 -2
  584. package/src/tui-client/next-dashboard-runtime.ts +52 -0
  585. package/src/user-config.ts +34 -9
  586. package/src/user-intent/types.ts +4 -3
  587. package/src/ux-sim/browser-hand.ts +165 -0
  588. package/src/ux-sim/draft-inventory-builder.ts +199 -0
  589. package/src/ux-sim/fake-browser-page.ts +81 -0
  590. package/src/ux-sim/fake-linear-device.ts +31 -0
  591. package/src/ux-sim/graph-engine-sim.ts +47 -0
  592. package/src/ux-sim/linear-secretary.ts +208 -0
  593. package/src/ux-sim/mock-scenario-catalog.json +81 -26
  594. package/src/ux-sim/mock-scenario-catalog.ts +175 -5
  595. package/src/ux-sim/onboarding-first-run-device.ts +31 -21
  596. package/src/ux-sim/release-sim-rig.ts +62 -18
  597. package/src/ux-sim/scenario.ts +70 -26
  598. package/src/ux-sim/service-key-setup.ts +113 -0
  599. package/src/ux-sim/term-slash-device.ts +74 -0
  600. package/src/ux-sim/turn-throw-sim.ts +31 -0
  601. package/src/version/packed-revision.json +1 -1
  602. package/src/web-search/exa.ts +77 -0
  603. package/src/web-search/index.ts +30 -9
  604. package/src/web-search/provider.ts +4 -1
  605. package/src/web-search/x-intent.ts +5 -0
  606. package/apps/pwa/out/_next/static/chunks/0244e5b5.6fc7670f8223d82d.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +0 -36
  608. package/apps/pwa/out/_next/static/chunks/1147-5196d19c222051b3.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/1319.b9b815ae0f181e06.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/1455-530ca16c7e71baff.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/1574.878c18ecc97b1bd4.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +0 -32
  614. package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/1945.7b54990d578c119b.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +0 -286
  620. package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +0 -34
  623. package/apps/pwa/out/_next/static/chunks/2456.b6de0e1c05f28843.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/2690.0521c738b7749931.js +0 -115
  629. package/apps/pwa/out/_next/static/chunks/2974.595d1e29d040cb6a.js +0 -64
  630. package/apps/pwa/out/_next/static/chunks/3207.a756c95e9ec8c3c8.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +0 -93
  632. package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +0 -41
  633. package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +0 -24
  635. package/apps/pwa/out/_next/static/chunks/3741.9cf76acaa2ee5298.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +0 -77
  641. package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/4276.336d76d858fcdf1b.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/4320.583cbab64db6be02.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/4770.769c9cd9c7034eba.js +0 -148
  647. package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +0 -74
  648. package/apps/pwa/out/_next/static/chunks/50061469.0326382241ef3b2d.js +0 -122
  649. package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +0 -149
  650. package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +0 -27
  652. package/apps/pwa/out/_next/static/chunks/53c73f84.373b6160adfa89a4.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/5431-72a1dbde59400691.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/5440-4236de26c5ea5856.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/6131.348b7d6bdcd267ce.js +0 -226
  664. package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +0 -90
  665. package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +0 -104
  671. package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +0 -94
  672. package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +0 -24
  679. package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +0 -8
  687. package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/8505.fd803c6c33b54cc3.js +0 -79
  689. package/apps/pwa/out/_next/static/chunks/8546-6f03f8ea34dd61d9.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/9211-330b6736a63d4cb3.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/9249.976f1e69a9d80754.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/9633.ce5bddc56784da72.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/9656-374232558fd528d0.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +0 -62
  705. package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0e3d7b9421b79dac.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/morning/page-0f291d3c8fd55a3a.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/term/page-bf067887b3307423.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +0 -1
  763. package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
  764. /package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → HMXsxdy5MIIcHPMHv1wD4}/_ssgManifest.js +0 -0
@@ -6,8 +6,14 @@ import type { Command } from 'commander';
6
6
  import { debug, redactSecretText } from '../debug/log.js';
7
7
  import type { AsyncLockHandle } from '../storage/file-lock.js';
8
8
  import { stateDirSourceForChild } from '../agent/identity-env.js';
9
+ import { createMissionLineStore, MissionLineHttpError, postMissionLineEvent, type MissionLineEvent, type MissionLineType } from './mission-line.js';
10
+ import type { LinearMissionLink } from '../intake-plane/linear-mission-sync.js';
9
11
 
10
12
  const MISSION_CONTEXT_ENV = 'ELANOUS_MISSION_CONTEXT';
13
+ const HAND_CHILD_ENV_KEYS = [
14
+ 'ELANOUS_MISSION_ID', 'ELANOUS_ATTEMPT_ID', 'ELANOUS_HAND_TOKEN', 'ELANOUS_HAND_ATTEMPT_ID',
15
+ 'ELANOUS_HAND_FINAL_LINE_ID', 'ELANOUS_HAND_AGENT', 'ELANOUS_HAND_RUN_ID', 'ELANOUS_HAND_PTY_ID',
16
+ ] as const;
11
17
 
12
18
  interface MissionContext { missionId: string; storeRoot: string }
13
19
 
@@ -21,17 +27,27 @@ function missionContextForEnv(env: NodeJS.ProcessEnv, missionId: string): Missio
21
27
  } catch { return undefined; }
22
28
  }
23
29
 
24
- function missionChildEnv(root: string, missionId: string, base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
30
+ export function missionChildEnv(root: string, missionId: string, base: NodeJS.ProcessEnv = process.env, line?: { token: string; attemptId: string; finalLineId: string; agent: 'codex' | 'claude'; nexusUrl?: string; runId?: string; ptyId?: string }): NodeJS.ProcessEnv {
25
31
  const storeRoot = resolve(root);
32
+ const childBase = { ...base };
33
+ for (const key of HAND_CHILD_ENV_KEYS) delete childBase[key];
26
34
  return {
27
- ...base,
35
+ ...childBase,
28
36
  ELANOUS_STATE_DIR: storeRoot,
29
37
  ELANOUS_STATE_DIR_SOURCE: stateDirSourceForChild(storeRoot, base),
38
+ ...(line ? { ELANOUS_MISSION_ID: missionId, ELANOUS_ATTEMPT_ID: line.attemptId,
39
+ ELANOUS_HAND_TOKEN: line.token, ELANOUS_HAND_ATTEMPT_ID: line.attemptId,
40
+ ELANOUS_HAND_FINAL_LINE_ID: line.finalLineId, ELANOUS_HAND_AGENT: line.agent,
41
+ ...(line.runId ? { ELANOUS_HAND_RUN_ID: line.runId, ELANOUS_RUN_ID: line.runId } : {}),
42
+ ...(line.ptyId ? { ELANOUS_HAND_PTY_ID: line.ptyId } : {}), ...(line.nexusUrl ? { ELANOUS_NEXUS_URL: line.nexusUrl } : {}) } : {}),
30
43
  [MISSION_CONTEXT_ENV]: JSON.stringify({ missionId, storeRoot }),
31
44
  };
32
45
  }
33
46
 
34
47
  export type MissionOutStatus = 'running' | 'completed' | 'cancelled' | 'failed' | 'timeout';
48
+ export class MissionReplyStateError extends Error {
49
+ constructor(readonly status: 404 | 409, message: string) { super(message); this.name = 'MissionReplyStateError'; }
50
+ }
35
51
  export interface MissionReplyEvent {
36
52
  type: 'mission.reply';
37
53
  missionId: string;
@@ -45,6 +61,18 @@ export interface MissionReplyEvent {
45
61
  scope?: string;
46
62
  stop?: boolean;
47
63
  priority?: string;
64
+ lineId?: string;
65
+ attemptId?: string;
66
+ runId?: string;
67
+ ptyId?: string;
68
+ replyTo?: number;
69
+ agent?: 'codex' | 'claude';
70
+ lineType?: 'progress' | 'final' | 'ask' | 'answer' | 'correct';
71
+ source?: string;
72
+ state?: string;
73
+ who?: string;
74
+ what?: string;
75
+ graphEvents?: Array<{ seq: number; ts: string; type: 'node-added'; node: string; kind: 'hand'; decider: 'mission-line'; reason: string; who: string; what: string; missionId: string }>;
48
76
  }
49
77
  export interface MissionReplyMessageFields {
50
78
  kind?: string;
@@ -53,6 +81,17 @@ export interface MissionReplyMessageFields {
53
81
  scope?: string;
54
82
  stop?: boolean;
55
83
  priority?: string;
84
+ lineId?: string;
85
+ attemptId?: string;
86
+ runId?: string;
87
+ ptyId?: string;
88
+ replyTo?: number;
89
+ agent?: 'codex' | 'claude';
90
+ lineType?: 'progress' | 'final' | 'ask' | 'answer' | 'correct';
91
+ source?: string;
92
+ state?: string;
93
+ who?: string;
94
+ what?: string;
56
95
  }
57
96
  export interface MissionOutRecord {
58
97
  missionId: string;
@@ -70,6 +109,8 @@ export interface MissionOutRecord {
70
109
  pendingFinalReply?: string;
71
110
  workerPid?: number;
72
111
  agentPid?: number;
112
+ /** Server-validated DEMO child issue; never populated from a reply payload. */
113
+ linearLink?: LinearMissionLink;
73
114
  }
74
115
  export interface MissionOutStoreDeps {
75
116
  now?: () => Date;
@@ -151,12 +192,22 @@ function validateReplyMessageFields(fields: MissionReplyMessageFields): MissionR
151
192
  const value = fields[key];
152
193
  if (value !== undefined && (typeof value !== 'string' || !value.trim())) throw new Error(`reply ${key} 는 비어 있지 않은 문자열이어야 합니다`);
153
194
  }
195
+ for (const key of ['attemptId', 'runId', 'ptyId', 'source', 'state', 'who', 'what', 'lineId'] as const) {
196
+ const value = fields[key];
197
+ if (value !== undefined && (typeof value !== 'string' || !value.trim())) throw new Error(`reply ${key} 는 비어 있지 않은 문자열이어야 합니다`);
198
+ }
199
+ if (fields.replyTo !== undefined && (!Number.isInteger(fields.replyTo) || fields.replyTo < 1)) throw new Error('reply replyTo 는 양의 정수여야 합니다');
200
+ if (fields.lineId !== undefined && !/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i.test(fields.lineId)) {
201
+ throw new Error('reply lineId 는 UUID 형식이어야 합니다');
202
+ }
203
+ if (fields.agent !== undefined && fields.agent !== 'codex' && fields.agent !== 'claude') throw new Error('reply agent 값이 올바르지 않습니다');
204
+ if (fields.lineType !== undefined && !['progress', 'final', 'ask', 'answer', 'correct'].includes(fields.lineType)) throw new Error('reply lineType 값이 올바르지 않습니다');
154
205
  if (fields.stop !== undefined && typeof fields.stop !== 'boolean') throw new Error('reply stop 은 boolean 이어야 합니다');
155
206
  if (fields.kind === 'correct' && (!fields.scope || fields.stop === undefined || !fields.priority)) {
156
207
  throw new Error('reply kind=correct 에는 scope, stop, priority 가 필요합니다');
157
208
  }
158
209
  // ask / answer / correct are reserved names. Unknown names remain accepted
159
- // as extension kinds; their behavior is intentionally deferred to 0.2.43.
210
+ // as extension kinds.
160
211
  return fields;
161
212
  }
162
213
 
@@ -166,6 +217,19 @@ function atomicJson(path: string, value: unknown): void {
166
217
  renameSync(temp, path);
167
218
  }
168
219
 
220
+ export async function waitForMissionAnswer(store: ReturnType<typeof createMissionOutStore>, missionId: string, ask: Pick<MissionReplyEvent, 'sequence' | 'deadline'>, defaults: string, deps: { now?: () => number; sleep?: (ms: number) => Promise<void> } = {}): Promise<{ text: string; usedDefault: boolean }> {
221
+ const now = deps.now ?? Date.now;
222
+ const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolveDelay) => setTimeout(resolveDelay, ms)));
223
+ const parsedDeadline = ask.deadline ? Date.parse(ask.deadline) : Number.NaN;
224
+ const deadline = Number.isFinite(parsedDeadline) ? parsedDeadline : now() + 2 * 60_000;
225
+ while (now() < deadline) {
226
+ const answer = store.replies(missionId).find((event) => event.kind === 'answer' && event.replyTo === ask.sequence);
227
+ if (answer) return { text: answer.text, usedDefault: false };
228
+ await sleep(Math.min(250, Math.max(1, deadline - now())));
229
+ }
230
+ return { text: defaults, usedDefault: true };
231
+ }
232
+
169
233
  export function createMissionOutStore(root: string, deps: MissionOutStoreDeps = {}) {
170
234
  const now = deps.now ?? (() => new Date());
171
235
  const withLock = async <T>(missionId: string, action: (lock: AsyncLockHandle) => T): Promise<T> => {
@@ -196,7 +260,7 @@ export function createMissionOutStore(root: string, deps: MissionOutStoreDeps =
196
260
  } catch { return []; }
197
261
  };
198
262
  return {
199
- create(input: { missionId?: string; agent: 'codex' | 'claude'; prompt: string; cwd: string; outputPath: string; targetOutputPath: string }): MissionOutRecord {
263
+ create(input: { missionId?: string; agent: 'codex' | 'claude'; prompt: string; cwd: string; outputPath: string; targetOutputPath: string; linearLink?: LinearMissionLink }): MissionOutRecord {
200
264
  const dir = join(root, 'agent-missions');
201
265
  mkdirSync(dir, { recursive: true, mode: 0o700 });
202
266
  const createdAt = now().toISOString();
@@ -218,13 +282,27 @@ export function createMissionOutStore(root: string, deps: MissionOutStoreDeps =
218
282
  if (!text.trim()) throw new Error('reply 본문이 비었습니다');
219
283
  const messageFields = validateReplyMessageFields(fields);
220
284
  return withLock(missionId, (lock) => {
285
+ const priorLine = messageFields.lineId
286
+ ? replies(missionId).find((event) => event.lineId === messageFields.lineId)
287
+ : undefined;
288
+ if (priorLine) return priorLine;
221
289
  const current = read(missionId);
222
- if (!current) throw new Error(`미션을 찾을 수 없습니다: ${missionId}`);
223
- if (current.status !== 'running') throw new Error(`미션이 실행 중이 아닙니다: ${current.status}`);
224
- if (current.doneReceived || replies(missionId).some((event) => event.done)) throw new Error('최종 답변이 이미 제출됐습니다');
290
+ if (!current) throw new MissionReplyStateError(404, `미션을 찾을 수 없습니다: ${missionId}`);
291
+ if (current.status !== 'running') throw new MissionReplyStateError(409, `미션이 실행 중이 아닙니다: ${current.status}`);
292
+ if (current.doneReceived || replies(missionId).some((event) => event.done)) throw new MissionReplyStateError(409, '최종 답변이 이미 제출됐습니다');
293
+ if (messageFields.kind === 'ask' && replies(missionId).filter((event) => event.kind === 'ask').length >= 3) {
294
+ throw new MissionReplyStateError(409, '미션당 ask 는 최대 3회입니다; 남은 정보로 진행하거나 다시 작성하세요');
295
+ }
296
+ const askDeadline = messageFields.kind === 'ask'
297
+ ? (messageFields.deadline ?? new Date(now().getTime() + 2 * 60_000).toISOString())
298
+ : undefined;
225
299
  const event: MissionReplyEvent = {
226
300
  type: 'mission.reply', missionId, sequence: replies(missionId).length + 1,
227
301
  text, done, createdAt: now().toISOString(), ...messageFields,
302
+ ...(askDeadline ? { deadline: askDeadline } : {}),
303
+ ...(replies(missionId).length === 0 && messageFields.who && messageFields.what ? {
304
+ graphEvents: [{ seq: 1, ts: now().toISOString(), type: 'node-added', node: `hand-${missionId}`, kind: 'hand', decider: 'mission-line', reason: 'hand mission line opened', who: messageFields.who, what: messageFields.what, missionId }],
305
+ } : {}),
228
306
  };
229
307
  if (!lock.stillHeld()) throw new Error('미션 상태 잠금을 잃어 reply 기록을 중단했습니다');
230
308
  appendFileSync(replyPath(root, missionId), `${JSON.stringify(event)}\n`, { encoding: 'utf8', mode: 0o600 });
@@ -339,7 +417,34 @@ export async function runMissionOutWorker(root: string, missionId: string, runAg
339
417
  if (!existsSync(record.outputPath) || statSync(record.outputPath).size === 0) throw new Error('결과 파일이 없어 미션을 실패 처리했습니다');
340
418
  const latest = store.read(missionId);
341
419
  if (!latest || latest.status !== 'running') return;
342
- if (!latest.doneReceived) await store.reply(missionId, readFileSync(record.outputPath, 'utf8'), true);
420
+ if (!latest.doneReceived) {
421
+ const finalText = readFileSync(record.outputPath, 'utf8');
422
+ const lineToken = process.env.ELANOUS_HAND_TOKEN?.trim();
423
+ const lineAttemptId = process.env.ELANOUS_HAND_ATTEMPT_ID?.trim();
424
+ const lineId = process.env.ELANOUS_HAND_FINAL_LINE_ID?.trim() || randomUUID();
425
+ const persistedFinal = lineAttemptId
426
+ ? store.replies(missionId).find((event) => event.done && event.attemptId === lineAttemptId)
427
+ : undefined;
428
+ if (persistedFinal) {
429
+ // NEXUS may have durably appended the final row but lost its HTTP
430
+ // response. Reuse that row; never append a second terminal event.
431
+ } else if (lineToken && lineAttemptId) {
432
+ try {
433
+ await postMissionLineEvent({ lineId, missionId, attemptId: lineAttemptId, agent: record.agent, type: 'final', source: 'mission-worker', text: finalText, state: 'completed' });
434
+ } catch (error) {
435
+ if (error instanceof MissionLineHttpError && error.status < 500) throw error;
436
+ // The local mission ledger is the durability boundary. NEXUS is an
437
+ // observation/transport edge; an unavailable daemon must not turn a
438
+ // valid output file into a lost final reply.
439
+ debug.log('agent-mission', 'line-ingress-fallback', { missionId, error: redactSecretText(String(error)) });
440
+ const racedFinal = store.replies(missionId).find((event) => event.lineId === lineId);
441
+ if (!racedFinal) await store.reply(missionId, finalText, true, {
442
+ lineId, attemptId: lineAttemptId, agent: record.agent, lineType: 'final', source: 'mission-worker', state: 'completed',
443
+ ...(store.replies(missionId).length === 0 ? { who: record.agent === 'claude' ? 'Claude' : 'Codex', what: record.prompt.replace(/\s+/g, ' ').trim().slice(0, 180) || 'hand mission' } : {}),
444
+ });
445
+ }
446
+ } else await store.reply(missionId, finalText, true);
447
+ }
343
448
  await store.complete(missionId);
344
449
  } catch (e) {
345
450
  const latest = store.read(missionId);
@@ -353,6 +458,11 @@ export async function runMissionOutWorker(root: string, missionId: string, runAg
353
458
  debug.log('agent-mission', 'terminal-write-failed', { missionId, error: redactSecretText(String(stateError)) }, { level: 'error' });
354
459
  }
355
460
  }
461
+ } finally {
462
+ // The attempt credential belongs to this worker job, including failure and
463
+ // cancellation paths. Revocation is idempotent when a final line already
464
+ // closed the token at the NEXUS ingress.
465
+ createMissionLineStore(root).revoke(missionId);
356
466
  }
357
467
  }
358
468
 
@@ -402,7 +512,7 @@ const missionUsage = {
402
512
  command: 'eln mission',
403
513
  commands: {
404
514
  run: {
405
- args: [], flags: ['--agent codex|claude', '--prompt <text>|--prompt-file <path>', '--out <path>', '--dry-run', '--output-format json'],
515
+ args: [], flags: ['--agent codex|claude', '--prompt <text>|--prompt-file <path>', '--out <path>', '--linear-issue-id <id>', '--dry-run', '--output-format json'],
406
516
  responseSchema: { type: 'object', required: ['id', 'missionId', 'status'], properties: { id: { type: 'string', format: 'uuid' }, missionId: { type: 'string', format: 'uuid' }, status: { const: 'running' }, artifacts: { type: 'array', items: { type: 'string' } } } },
407
517
  },
408
518
  status: {
@@ -410,7 +520,7 @@ const missionUsage = {
410
520
  responseSchema: { type: 'object', required: ['id', 'missionId', 'status', 'artifacts', 'replies'], properties: { id: { type: 'string', format: 'uuid' }, missionId: { type: 'string', format: 'uuid' }, status: { enum: ['running', 'done', 'cancelled', 'failed', 'timeout'] }, body: { type: 'string' }, artifacts: { type: 'array', items: { type: 'string' } }, replies: { type: 'array', items: { $ref: '#/events/mission.reply' } }, result: { type: 'string' }, lockStale: { type: 'boolean' }, error: { type: 'string' } } },
411
521
  },
412
522
  reply: {
413
- args: ['[missionId]', '[text|stdin]'], flags: ['--mission <missionId>', '--done', '--kind <kind>', '--defaults <text>', '--deadline <value>', '--scope <text>', '--[no-]stop', '--priority <value>'],
523
+ args: ['[missionId]', '[text|stdin]'], flags: ['--mission <missionId>', '--done', '--kind <kind>', '--defaults <text>', '--deadline <value>', '--reply-to <sequence>', '--scope <text>', '--[no-]stop', '--priority <value>'],
414
524
  responseSchema: { type: 'object', required: ['missionId', 'accepted', 'sequence', 'done'], properties: { missionId: { type: 'string', format: 'uuid' }, accepted: { const: true }, sequence: { type: 'integer', minimum: 1 }, done: { type: 'boolean' } } },
415
525
  },
416
526
  cancel: {
@@ -418,12 +528,14 @@ const missionUsage = {
418
528
  responseSchema: { type: 'object', required: ['missionId', 'status', 'cancelled'], properties: { missionId: { type: 'string', format: 'uuid' }, status: { enum: ['running', 'completed', 'cancelled', 'failed'] }, cancelled: { type: 'boolean' } } },
419
529
  },
420
530
  },
421
- events: { 'mission.reply': { type: 'object', required: ['type', 'missionId', 'sequence', 'text', 'done', 'createdAt'], properties: { type: { const: 'mission.reply' }, missionId: { type: 'string', format: 'uuid' }, sequence: { type: 'integer' }, text: { type: 'string' }, done: { type: 'boolean' }, createdAt: { type: 'string', format: 'date-time' }, kind: { type: 'string', description: 'Reserved kinds: ask, answer, correct. Unknown kinds are accepted as no-op extensions.' }, defaults: { type: 'string' }, deadline: { type: 'string' }, scope: { type: 'string' }, stop: { type: 'boolean' }, priority: { type: 'string' } } } },
531
+ events: { 'mission.reply': { type: 'object', required: ['type', 'missionId', 'sequence', 'text', 'done', 'createdAt'], properties: { type: { const: 'mission.reply' }, missionId: { type: 'string', format: 'uuid' }, sequence: { type: 'integer' }, replyTo: { type: 'integer', minimum: 1 }, runId: { type: 'string' }, ptyId: { type: 'string' }, text: { type: 'string' }, done: { type: 'boolean' }, createdAt: { type: 'string', format: 'date-time' }, kind: { type: 'string', description: 'Reserved kinds: ask, answer, correct.' }, defaults: { type: 'string' }, deadline: { type: 'string' }, scope: { type: 'string' }, stop: { type: 'boolean' }, priority: { type: 'string' } } } },
422
532
  replyContract: 'Use `eln --config-dir <storeRoot> mission reply --mission <missionId> <text> [--kind ask|answer|correct]` for replies and `eln --config-dir <storeRoot> mission reply --mission <missionId> --done <text>` for the final answer.',
423
533
  agentInstructionBlock: [
424
534
  'You can send durable progress and final answers to Elanous with `eln mission reply`.',
425
535
  'Use `eln --config-dir <storeRoot> mission reply --mission <missionId> "<message>"` for progress/questions.',
426
- 'Reserved message kinds: ask, answer, correct. Unknown kinds are accepted but have no special behavior.',
536
+ 'Ask for a decision with `--kind ask --defaults <fallback>`; include question and options in the text. An unanswered ask defaults after two minutes. Ask at most three times, then continue with available information or rewrite the task.',
537
+ 'Example: `eln --config-dir <storeRoot> mission reply --mission <missionId> --kind ask --defaults main "Which base should I use? Options: main or release/2.4."` blocks until HandReply or the deadline.',
538
+ 'For a correction, include --scope, --stop, and --priority; corrections require a bound child run and PTY.',
427
539
  'Finish with `eln --config-dir <storeRoot> mission reply --mission <missionId> --done "<final answer>"`.',
428
540
  'Use `eln --config-dir <storeRoot> mission status <missionId>` to inspect the interaction; do not return output file paths.',
429
541
  ].join('\n'),
@@ -436,6 +548,8 @@ export function registerMissionOutCommand(program: Command, deps: {
436
548
  write?: (text: string) => void;
437
549
  error?: (text: string) => void;
438
550
  startWorker?: (root: string, missionId: string) => number;
551
+ /** Test seam; production resolves the registered current NEXUS endpoint. */
552
+ resolveNexusUrl?: () => string | null;
439
553
  } = {}): Command {
440
554
  const write = deps.write ?? ((text) => process.stdout.write(text));
441
555
  const error = deps.error ?? ((text) => process.stderr.write(text));
@@ -452,6 +566,26 @@ export function registerMissionOutCommand(program: Command, deps: {
452
566
  const missionContext = missionContextForEnv(process.env, missionId);
453
567
  return missionContext ? observingStoreAt(missionContext.storeRoot) : storeAt(true);
454
568
  };
569
+ const syncAcceptedLinearReply = async (store: ReturnType<typeof createMissionOutStore>, missionId: string, event: MissionReplyEvent): Promise<void> => {
570
+ try {
571
+ const linkedMission = store.read(missionId);
572
+ if (!linkedMission?.linearLink) return;
573
+ const latestLine = (): { lineType: string; sequence: number } | undefined => store.replies(missionId)
574
+ .filter(reply => reply.lineType === 'progress' || reply.lineType === 'final')
575
+ .sort((a, b) => b.sequence - a.sequence)
576
+ .map(reply => ({ lineType: reply.lineType!, sequence: reply.sequence }))[0];
577
+ const missionContext = missionContextForEnv(process.env, missionId);
578
+ const lockRoot = missionContext?.storeRoot ?? await root();
579
+ const { syncLinearMissionProgress } = await import('../intake-plane/linear-mission-sync.js');
580
+ await syncLinearMissionProgress({
581
+ link: linkedMission.linearLink, lineType: event.lineType, sequence: event.sequence, latestLine: latestLine(),
582
+ }, { lockRoot, getLatestLine: async () => latestLine() });
583
+ } catch (error) {
584
+ debug.log('agent-mission', 'linear-progress-sync-setup-failed', {
585
+ missionId, error: redactSecretText(String(error)),
586
+ }, { level: 'warn' });
587
+ }
588
+ };
455
589
  const out = (opts: { json?: boolean; outputFormat?: string }, value: unknown): void => {
456
590
  write(opts.json || opts.outputFormat === 'json' ? `${JSON.stringify(value)}\n` : `${JSON.stringify(value, null, 2)}\n`);
457
591
  };
@@ -466,10 +600,11 @@ export function registerMissionOutCommand(program: Command, deps: {
466
600
  .option('--prompt <text>', 'Mission prompt')
467
601
  .option('--prompt-file <path>', 'Read the prompt from a UTF-8 file')
468
602
  .option('--out <path>', 'Internal result file required for fail-closed completion')
603
+ .option('--linear-issue-id <id>', 'Bind this mission to a verified DEMO subtask')
469
604
  .option('--dry-run', 'Resolve and print request without creating a job')
470
605
  .option('--json', 'Emit JSON')
471
606
  .option('--output-format <format>', 'text or json', 'text')
472
- .action(async (opts: { agent?: string; prompt?: string; promptFile?: string; out?: string; dryRun?: boolean; json?: boolean; outputFormat?: string; usage?: boolean }, command: Command) => {
607
+ .action(async (opts: { agent?: string; prompt?: string; promptFile?: string; out?: string; linearIssueId?: string; dryRun?: boolean; json?: boolean; outputFormat?: string; usage?: boolean }, command: Command) => {
473
608
  if (opts.usage || command.optsWithGlobals().usage) { out({ json: true }, missionUsage.commands.run); return; }
474
609
  if (!opts.agent) { error('--agent 는 필수입니다\n'); process.exitCode = 2; return; }
475
610
  if (!opts.out) { error('--out 은 필수입니다\n'); process.exitCode = 2; return; }
@@ -485,9 +620,29 @@ export function registerMissionOutCommand(program: Command, deps: {
485
620
  const store = await storeAt();
486
621
  let record: MissionOutRecord | undefined;
487
622
  try {
623
+ const linearLink = opts.linearIssueId
624
+ ? await (await import('../intake-plane/linear-mission-sync.js')).resolveDemoLinearMissionLink(opts.linearIssueId)
625
+ : undefined;
488
626
  const missionId = randomUUID();
489
627
  const outputPath = `${targetOutputPath}.eln-mission-${missionId}.tmp`;
490
- record = store.create({ missionId, agent: opts.agent as 'codex' | 'claude', prompt, cwd: process.cwd(), outputPath, targetOutputPath });
628
+ record = store.create({ missionId, agent: opts.agent as 'codex' | 'claude', prompt, cwd: process.cwd(), outputPath, targetOutputPath, ...(linearLink ? { linearLink } : {}) });
629
+ // Injected state roots are test fixtures: avoid discovering a global
630
+ // daemon whose state belongs to another instance. Production callers
631
+ // use effectiveInstanceRoot and resolve their registered NEXUS here.
632
+ const candidateNexusUrl = process.env.ELANOUS_NEXUS_URL?.trim() || deps.resolveNexusUrl?.()
633
+ || (deps.stateRoot ? null : (await import('../nexus/daemon-endpoint.js')).resolveDaemonEndpoint()?.baseUrl);
634
+ let nexusUrl: string | null = null;
635
+ if (candidateNexusUrl) {
636
+ try {
637
+ const parsed = new URL(candidateNexusUrl);
638
+ if (parsed.protocol === 'http:' || parsed.protocol === 'https:') nexusUrl = parsed.origin;
639
+ } catch { /* invalid NEXUS configuration cannot receive a mission token */ }
640
+ }
641
+ const handLine = nexusUrl ? createMissionLineStore(await root()).issue({
642
+ missionId, attemptId: randomUUID(), agent: record.agent,
643
+ who: record.agent === 'claude' ? 'Claude' : 'Codex',
644
+ what: prompt.replace(/\s+/g, ' ').trim().slice(0, 180) || 'hand mission',
645
+ }) : undefined;
491
646
  const { mkdirSync } = await import('node:fs');
492
647
  mkdirSync(dirname(targetOutputPath), { recursive: true });
493
648
  let workerPid: number;
@@ -498,7 +653,7 @@ export function registerMissionOutCommand(program: Command, deps: {
498
653
  if (!entry) throw new Error('CLI 엔트리 경로를 확인할 수 없습니다');
499
654
  const stateRoot = await root();
500
655
  const child = spawn(process.execPath, [entry, 'mission', '__worker', record.missionId], {
501
- cwd: record.cwd, detached: true, stdio: 'ignore', env: missionChildEnv(stateRoot, record.missionId),
656
+ cwd: record.cwd, detached: true, stdio: 'ignore', env: missionChildEnv(stateRoot, record.missionId, process.env, handLine && nexusUrl ? { ...handLine, agent: record.agent, nexusUrl } : undefined),
502
657
  });
503
658
  if (!child.pid) throw new Error('미션 워커 PID 생성 실패');
504
659
  child.unref();
@@ -553,8 +708,9 @@ export function registerMissionOutCommand(program: Command, deps: {
553
708
  .option('--scope <text>', 'Correction scope')
554
709
  .option('--[no-]stop', 'Correction stop request')
555
710
  .option('--priority <value>', 'Correction priority')
711
+ .option('--reply-to <sequence>', 'Ask sequence being answered/corrected')
556
712
  .option('--json', 'Emit JSON').option('--output-format <format>', 'text or json', 'text')
557
- .action(async (rawArgs: string[], opts: { mission?: string; done?: boolean; kind?: string; defaults?: string; deadline?: string; scope?: string; stop?: boolean; priority?: string; json?: boolean; outputFormat?: string; usage?: boolean }, command: Command) => {
713
+ .action(async (rawArgs: string[], opts: { mission?: string; done?: boolean; kind?: string; defaults?: string; deadline?: string; scope?: string; stop?: boolean; priority?: string; replyTo?: string; json?: boolean; outputFormat?: string; usage?: boolean }, command: Command) => {
558
714
  if (opts.usage || command.optsWithGlobals().usage) { out({ json: true }, missionUsage.commands.reply); return; }
559
715
  const args = [...rawArgs];
560
716
  const missionId = opts.mission?.trim() || args.shift();
@@ -562,7 +718,85 @@ export function registerMissionOutCommand(program: Command, deps: {
562
718
  let text = args.join(' ');
563
719
  if (!text.trim()) text = await (deps.readStdin ?? (async () => (await import('../cli/piped-stdin.js')).readPipedStdin()))();
564
720
  try {
565
- const event = await (await replyStoreAt(missionId)).reply(missionId, text, opts.done, {
721
+ if (opts.kind === 'ask' && !opts.defaults?.trim()) throw new Error('reply kind=ask 에는 --defaults 가 필요합니다');
722
+ const lineToken = process.env.ELANOUS_HAND_TOKEN?.trim();
723
+ const lineAttemptId = process.env.ELANOUS_HAND_ATTEMPT_ID?.trim();
724
+ const lineAgent = process.env.ELANOUS_HAND_AGENT === 'claude' ? 'claude' : process.env.ELANOUS_HAND_AGENT === 'codex' ? 'codex' : undefined;
725
+ if (lineToken && lineAttemptId && lineAgent) {
726
+ const replyTo = opts.replyTo === undefined ? undefined : Number(opts.replyTo);
727
+ if (opts.replyTo !== undefined && (!Number.isInteger(replyTo) || (replyTo ?? 0) < 1)) throw new Error('--reply-to 는 양의 정수여야 합니다');
728
+ if (opts.kind === 'correct' && (!opts.scope || opts.stop === undefined || !opts.priority)) {
729
+ throw new Error('reply kind=correct 에는 scope, stop, priority 가 필요합니다');
730
+ }
731
+ const lineId = randomUUID();
732
+ const lineType: NonNullable<MissionReplyMessageFields['lineType']> = opts.done
733
+ ? 'final'
734
+ : opts.kind === 'ask' || opts.kind === 'answer' || opts.kind === 'correct' ? opts.kind : 'progress';
735
+ const fields: MissionReplyMessageFields & { lineId: string; attemptId: string; agent: 'codex' | 'claude'; lineType: MissionLineType; source: string } = {
736
+ lineId,
737
+ attemptId: lineAttemptId, agent: lineAgent,
738
+ ...(process.env.ELANOUS_HAND_RUN_ID ? { runId: process.env.ELANOUS_HAND_RUN_ID } : {}),
739
+ ...(process.env.ELANOUS_HAND_PTY_ID ? { ptyId: process.env.ELANOUS_HAND_PTY_ID } : {}),
740
+ ...(replyTo ? { replyTo } : {}),
741
+ lineType,
742
+ source: 'mission-reply', ...(opts.done ? { state: 'completed' } : {}),
743
+ ...(opts.kind !== undefined ? { kind: opts.kind } : {}),
744
+ ...(opts.defaults !== undefined ? { defaults: opts.defaults } : {}),
745
+ ...(opts.deadline !== undefined ? { deadline: opts.deadline } : {}),
746
+ ...(opts.scope !== undefined ? { scope: opts.scope } : {}),
747
+ ...(opts.stop !== undefined ? { stop: opts.stop } : {}),
748
+ ...(opts.priority !== undefined ? { priority: opts.priority } : {}),
749
+ };
750
+ let event: MissionReplyEvent | MissionLineEvent;
751
+ try {
752
+ const lineEvent = await postMissionLineEvent({
753
+ lineId, missionId, attemptId: lineAttemptId, agent: lineAgent,
754
+ ...(process.env.ELANOUS_HAND_RUN_ID ? { runId: process.env.ELANOUS_HAND_RUN_ID } : {}),
755
+ ...(process.env.ELANOUS_HAND_PTY_ID ? { ptyId: process.env.ELANOUS_HAND_PTY_ID } : {}),
756
+ ...(replyTo ? { replyTo } : {}),
757
+ type: lineType, source: 'mission-reply', text, ...(opts.done ? { state: 'completed' } : {}),
758
+ ...(opts.kind !== undefined ? { kind: opts.kind } : {}),
759
+ ...(opts.defaults !== undefined ? { defaults: opts.defaults } : {}),
760
+ ...(opts.deadline !== undefined ? { deadline: opts.deadline } : {}),
761
+ ...(opts.scope !== undefined ? { scope: opts.scope } : {}),
762
+ ...(opts.stop !== undefined ? { stop: opts.stop } : {}),
763
+ ...(opts.priority !== undefined ? { priority: opts.priority } : {}),
764
+ });
765
+ event = {
766
+ type: 'mission.reply', missionId, sequence: lineEvent.sequence,
767
+ text: lineEvent.text, done: lineEvent.done, createdAt: lineEvent.createdAt,
768
+ ...fields,
769
+ ...(lineEvent.deadline ? { deadline: lineEvent.deadline } : {}),
770
+ };
771
+ } catch (error) {
772
+ if (error instanceof MissionLineHttpError && error.status < 500) throw error;
773
+ debug.log('agent-mission', 'line-ingress-fallback', { missionId, error: redactSecretText(String(error)) });
774
+ const replyStore = await replyStoreAt(missionId);
775
+ const persistedLine = replyStore.replies(missionId).find((reply) => reply.lineId === lineId);
776
+ if (persistedLine) event = persistedLine;
777
+ else {
778
+ const existingReplies = replyStore.replies(missionId);
779
+ const mission = replyStore.read(missionId);
780
+ event = await replyStore.reply(missionId, text, opts.done ?? false, {
781
+ ...fields,
782
+ ...(existingReplies.length === 0 && mission ? {
783
+ who: lineAgent === 'claude' ? 'Claude' : 'Codex',
784
+ what: mission.prompt.replace(/\s+/g, ' ').trim().slice(0, 180) || 'hand mission',
785
+ } : {}),
786
+ });
787
+ }
788
+ }
789
+ const linkedStore = await replyStoreAt(missionId);
790
+ await syncAcceptedLinearReply(linkedStore, missionId, event);
791
+ if (opts.kind === 'ask') {
792
+ const answerStore = await replyStoreAt(missionId);
793
+ const answer = await waitForMissionAnswer(answerStore, missionId, event, opts.defaults!);
794
+ out(opts, { missionId, accepted: true, sequence: event.sequence, done: event.done, answer: answer.text, usedDefault: answer.usedDefault });
795
+ } else out(opts, { missionId, accepted: true, sequence: event.sequence, done: event.done });
796
+ return;
797
+ }
798
+ const replyStore = await replyStoreAt(missionId);
799
+ const event = await replyStore.reply(missionId, text, opts.done ?? false, {
566
800
  ...(opts.kind !== undefined ? { kind: opts.kind } : {}),
567
801
  ...(opts.defaults !== undefined ? { defaults: opts.defaults } : {}),
568
802
  ...(opts.deadline !== undefined ? { deadline: opts.deadline } : {}),
@@ -570,7 +804,11 @@ export function registerMissionOutCommand(program: Command, deps: {
570
804
  ...(opts.stop !== undefined ? { stop: opts.stop } : {}),
571
805
  ...(opts.priority !== undefined ? { priority: opts.priority } : {}),
572
806
  });
573
- out(opts, { missionId, accepted: true, sequence: event.sequence, done: event.done });
807
+ await syncAcceptedLinearReply(replyStore, missionId, event);
808
+ if (opts.kind === 'ask') {
809
+ const answer = await waitForMissionAnswer(replyStore, missionId, event, opts.defaults!);
810
+ out(opts, { missionId, accepted: true, sequence: event.sequence, done: event.done, answer: answer.text, usedDefault: answer.usedDefault });
811
+ } else out(opts, { missionId, accepted: true, sequence: event.sequence, done: event.done });
574
812
  } catch (e) { error(`${String(e)}\n`); process.exitCode = 1; }
575
813
  });
576
814
 
@@ -1,4 +1,4 @@
1
- import { spawnSync } from 'node:child_process';
1
+ import { spawn, spawnSync, type ChildProcess } from 'node:child_process';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { existsSync, mkdtempSync, rmSync } from 'node:fs';
4
4
  import { tmpdir } from 'node:os';
@@ -33,20 +33,131 @@ export type AgentCliDetection = {
33
33
  agent: AgentCli;
34
34
  /** null means the executable/version probe could not establish installation state. */
35
35
  installed: boolean | null;
36
+ /** Sanitized semantic version only; raw CLI output is never exposed. */
37
+ version?: string;
36
38
  executable: 'present' | 'missing' | 'unknown';
37
39
  login: 'ready' | 'needed' | 'api-key' | 'unknown';
38
40
  message: string;
39
41
  };
40
42
 
43
+ /** The supported, non-privileged installer for each visible coding CLI. */
44
+ export const AGENT_CLI_INSTALLERS: Record<AgentCli, { command: string; args: string[]; display: string }> = {
45
+ codex: { command: 'npm', args: ['install', '-g', '@openai/codex@latest'], display: 'npm install -g @openai/codex@latest' },
46
+ claude: { command: 'npm', args: ['install', '-g', '@anthropic-ai/claude-code'], display: 'npm install -g @anthropic-ai/claude-code' },
47
+ };
48
+
49
+ export type AgentCliPreparation = {
50
+ ready: boolean;
51
+ detection: AgentCliDetection;
52
+ installation: 'not-needed' | 'declined' | 'installed' | 'failed';
53
+ message: string;
54
+ };
55
+
41
56
  type AgentCliRunner = (command: string, args: string[], options: {
42
57
  encoding: 'utf8'; timeout: number; env: Record<string, string>;
43
58
  }) => ReturnType<typeof spawnSync>;
44
59
 
45
- function verifiedAgentVersion(agent: AgentCli, raw: string): boolean {
60
+ export interface AgentCliPreparationDeps {
61
+ env?: Record<string, string | undefined>;
62
+ detect?: (agent: AgentCli, options: { env: Record<string, string | undefined>; runCli?: AgentCliRunner }) => AgentCliDetection;
63
+ runCli?: AgentCliRunner;
64
+ /** Must be an explicit user confirmation; no installer runs when it is absent or declines. */
65
+ confirmInstall?: (prompt: string) => boolean | Promise<boolean>;
66
+ /** Injection seam for tests. Production runs npm only after confirmInstall returns true. */
67
+ install?: (command: string, args: string[], options: { env: Record<string, string>; timeoutMs: number }) => { status: number | null; error?: { code?: string } | null } | Promise<{ status: number | null; error?: { code?: string } | null }>;
68
+ onStatus?: (line: string) => void;
69
+ }
70
+
71
+ function runAgentCliInstaller(command: string, args: string[], options: { env: Record<string, string>; timeoutMs: number }): Promise<{ status: number | null; error?: { code?: string } | null }> {
72
+ return new Promise((resolve) => {
73
+ const spawnInstaller = spawn as unknown as (file: string, args: string[], options: { env: Record<string, string>; stdio: 'ignore'; windowsHide: true }) => ChildProcess;
74
+ const child = spawnInstaller(command, args, { env: options.env, stdio: 'ignore', windowsHide: true });
75
+ let settled = false;
76
+ let timedOut = false;
77
+ let forceKill: ReturnType<typeof setTimeout> | undefined;
78
+ const timeout = setTimeout(() => {
79
+ timedOut = true;
80
+ child.kill('SIGTERM');
81
+ forceKill = setTimeout(() => child.kill('SIGKILL'), 2_000);
82
+ }, options.timeoutMs);
83
+ const finish = (result: { status: number | null; error?: { code?: string } | null }): void => {
84
+ if (settled) return;
85
+ settled = true;
86
+ clearTimeout(timeout);
87
+ if (forceKill) clearTimeout(forceKill);
88
+ resolve(result);
89
+ };
90
+ child.once('error', (error: Error & { code?: string }) => finish({ status: null, error }));
91
+ child.once('close', (status: number | null) => finish(timedOut
92
+ ? { status: null, error: { code: 'ETIMEDOUT' } }
93
+ : { status }));
94
+ });
95
+ }
96
+
97
+ function agentCliNotReadyMessage(detection: AgentCliDetection): string {
98
+ if (detection.installed === false) return `${detection.agent}: 설치되지 않음`;
99
+ if (detection.installed === null) return `${detection.agent}: 설치 상태 확인 불가`;
100
+ if (detection.login === 'api-key') return `${detection.agent}: API 키 인증은 감지했지만 구독 로그인이 필요합니다. ${detection.agent} login을 실행해 주세요`;
101
+ if (detection.login === 'needed') return `${detection.agent}: 로그인이 필요합니다. ${detection.agent} login을 실행해 주세요`;
102
+ return `${detection.agent}: 로그인 상태를 확인할 수 없습니다`;
103
+ }
104
+
105
+ /** Detect first, ask once before an official install, then re-detect before the caller launches. */
106
+ export async function prepareAgentCli(
107
+ agent: AgentCli,
108
+ deps: AgentCliPreparationDeps = {},
109
+ ): Promise<AgentCliPreparation> {
110
+ const env = deps.env ?? process.env;
111
+ const detect = deps.detect ?? detectAgentCli;
112
+ const detectOptions = { env, ...(deps.runCli ? { runCli: deps.runCli } : {}) };
113
+ const installer = AGENT_CLI_INSTALLERS[agent];
114
+ let detection = detect(agent, detectOptions);
115
+ deps.onStatus?.(detection.message);
116
+ if (detection.installed === true && detection.login === 'ready') {
117
+ return { ready: true, detection, installation: 'not-needed', message: detection.message };
118
+ }
119
+ if (detection.installed !== false) {
120
+ return { ready: false, detection, installation: 'not-needed', message: agentCliNotReadyMessage(detection) };
121
+ }
122
+ if (!deps.confirmInstall || !await deps.confirmInstall(`설치할까요? ${installer.display}`)) {
123
+ return { ready: false, detection, installation: 'declined', message: `${agent}: 설치를 건너뛰었습니다` };
124
+ }
125
+
126
+ const install = deps.install ?? runAgentCliInstaller;
127
+ let result: { status: number | null; error?: { code?: string } | null };
128
+ try {
129
+ const backend = agent === 'codex' ? codexBackend : claudeBackend;
130
+ result = await install(installer.command, [...installer.args], {
131
+ env: resolveBackendSpawn(backend, env).env,
132
+ timeoutMs: 300_000,
133
+ });
134
+ } catch {
135
+ return { ready: false, detection, installation: 'failed', message: `${agent}: 설치 명령을 실행하지 못했습니다` };
136
+ }
137
+ if (result.status !== 0) {
138
+ const detail = result.error?.code === 'ENOENT' ? 'npm을 찾을 수 없습니다' : '설치 명령이 성공하지 않았습니다';
139
+ return { ready: false, detection, installation: 'failed', message: `${agent}: ${detail}` };
140
+ }
141
+
142
+ detection = detect(agent, detectOptions);
143
+ deps.onStatus?.(detection.message);
144
+ if (detection.installed !== true) {
145
+ return { ready: false, detection, installation: 'failed', message: `${agent}: 설치 뒤 버전 확인에 실패했습니다` };
146
+ }
147
+ if (detection.login !== 'ready') {
148
+ return { ready: false, detection, installation: 'installed', message: agentCliNotReadyMessage(detection) };
149
+ }
150
+ return { ready: true, detection, installation: 'installed', message: detection.message };
151
+ }
152
+
153
+ function agentVersion(agent: AgentCli, raw: string): { version?: string } | undefined {
46
154
  const prefix = agent === 'claude' ? /^(?:Claude(?: Code)?\s+)?v?/i : /^(?:Codex(?:-CLI)?\s+)?v?/i;
47
155
  const versioned = raw.replace(prefix, '');
48
- // Probe output is untrusted: validate its shape but never return any part of it.
49
- return /^\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?(?: \(Claude Code\))?$/i.test(versioned);
156
+ // Probe output is untrusted: validate the semver shape but expose only a bounded numeric core.
157
+ const match = /^(\d+\.\d+\.\d+)(?:[-+][A-Za-z0-9.-]{1,40})?(?: \(Claude Code\))?$/i.exec(versioned);
158
+ if (!match) return undefined;
159
+ const parts = match[1]!.split('.');
160
+ return parts.every((part) => part.length <= 6) ? { version: match[1]! } : undefined;
50
161
  }
51
162
 
52
163
  function agentExecutableExists(command: string, env: Record<string, string>): boolean {
@@ -79,8 +190,8 @@ export function detectAgentCli(
79
190
  return { agent, installed: present ? null : false, executable: present ? 'unknown' : 'missing', login: 'unknown', message: present ? `${agent}: 실행 파일을 실행할 수 없어 상태 확인 불가` : `${agent}: 설치되지 않음` };
80
191
  }
81
192
  const rawVersion = `${versionResult.stdout ?? ''}\n${versionResult.stderr ?? ''}`.trim().split(/\r?\n/, 1)[0] ?? '';
82
- const versionVerified = versionResult.status === 0 && verifiedAgentVersion(agent, rawVersion);
83
- if (!versionVerified) {
193
+ const verifiedVersion = versionResult.status === 0 ? agentVersion(agent, rawVersion) : undefined;
194
+ if (!verifiedVersion) {
84
195
  const executable = versionResult.status === null || versionResult.error ? 'unknown' : 'present';
85
196
  return {
86
197
  agent, installed: null, executable, login: 'unknown',
@@ -103,13 +214,13 @@ export function detectAgentCli(
103
214
  } catch { /* Keep authentication unknown when the probe itself fails. */ }
104
215
  }
105
216
  const message = login === 'ready'
106
- ? `${agent}: 설치됨, 로그인 확인됨`
217
+ ? `${agent}: 설치됨${verifiedVersion.version ? ` v${verifiedVersion.version}` : ''} · 로그인 확인됨`
107
218
  : login === 'api-key'
108
- ? `${agent}: API 키 로그인됨 (구독 로그인 아님)`
219
+ ? `${agent}: 설치됨${verifiedVersion.version ? ` v${verifiedVersion.version}` : ''} · API 키 로그인됨 (구독 로그인 아님)`
109
220
  : login === 'needed'
110
- ? `${agent}: 설치됨, 로그인 필요`
111
- : `${agent}: 설치됨, 로그인 상태 확인 불가`;
112
- return { agent, installed: true, executable: 'present', login, message };
221
+ ? `${agent}: 설치됨${verifiedVersion.version ? ` v${verifiedVersion.version}` : ''} · 로그인 필요`
222
+ : `${agent}: 설치됨${verifiedVersion.version ? ` v${verifiedVersion.version}` : ''} · 로그인 상태 확인 불가`;
223
+ return { agent, installed: true, ...(verifiedVersion.version ? { version: verifiedVersion.version } : {}), executable: 'present', login, message };
113
224
  }
114
225
 
115
226
  function defaultExec(cmd: string[], opts: { stdin?: string; timeoutMs: number }): ExecResult {