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
@@ -125,6 +125,8 @@ export interface CoreTurnCallbacks {
125
125
  * `src/core-turn/` never imports from dashboard / chat / tui /
126
126
  * display — the headless guard test enforces this structurally. */
127
127
  export interface CoreTurnContext {
128
+ /** Caller-owned identity for correlating this turn's research and debug events. */
129
+ runId?: string;
128
130
  /** Identifier for the hosting session. Piped through for future
129
131
  * correlation; the turn logic does not branch on it. */
130
132
  sessionId: string;
@@ -149,6 +151,8 @@ export interface CoreTurnContext {
149
151
  /** Optional provider request-size hook. Only providers with a measured
150
152
  * serializer consume it; all others retain their existing request path. */
151
153
  requestSizeGuard?: LLMOpts['requestSizeGuard'];
154
+ /** Optional per-turn reasoning effort; high/xhigh/max also opts into the default deep Bloom frame. */
155
+ reasoningEffort?: LLMOpts['reasoningEffort'];
152
156
  /** Tool catalog the model may call this turn. Empty array means
153
157
  * "text-only" — the loop delegates to plain `streamLLM`. */
154
158
  tools: LLMToolSpec[];
@@ -89,6 +89,8 @@ export interface AcpChatHandlers {
89
89
  /** Append streamed assistant text. Caller accumulates + redraws.
90
90
  * Receives each chunk exactly as the ACP agent emits it. */
91
91
  appendChunk: (delta: string) => void;
92
+ /** Replace the current streamed assistant answer with its authoritative final text. */
93
+ replaceText?: (fullText: string) => void;
92
94
  /** A goal iteration ended; fold only that interim reply in the visible pane. */
93
95
  foldGoalInterim?: (text: string) => void;
94
96
  /** Called once per tool_call event with a rendered label like
@@ -441,6 +443,14 @@ export class DashboardAcpChat {
441
443
  }
442
444
  const c = update.content;
443
445
  if (c.type === 'text') {
446
+ const meta = (update as typeof update & { _meta?: { elanous?: { textOperation?: unknown } } })._meta;
447
+ if (meta?.elanous?.textOperation === 'replace') {
448
+ this.closeStreamBuffer(sess, 'flush');
449
+ if (handlers.replaceText) handlers.replaceText(c.text);
450
+ else handlers.appendChunk(c.text);
451
+ handlers.redraw?.();
452
+ return;
453
+ }
444
454
  this.routeText(sess, c.text, handlers);
445
455
  }
446
456
  return;
@@ -1,9 +1,110 @@
1
1
  import type { PendingTaskNotification } from '../agent/task-notification.js';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { mkdirSync, writeFileSync } from 'node:fs';
4
+ import { basename, isAbsolute, join, relative, sep } from 'node:path';
2
5
  import { debug } from '../debug/log.js';
3
6
  import { redactMissionResultPath, type StartedClassicMissionCliJob } from './mission-cli-consumer.js';
7
+ import type { ClassicSidetabMissionResult } from './classic-sidetab-mission.js';
4
8
 
5
9
  export type ClassicMissionNotificationEnqueue = (notification: PendingTaskNotification) => void;
6
10
  export const CLASSIC_SIDETAB_MISSION_LABEL = 'sidetab mission';
11
+ const CLASSIC_SIDETAB_PAIR_TIMEOUT_MS = 60 * 60 * 1_000;
12
+ export interface ClassicSidetabMissionPairCompletionResult {
13
+ codex: ClassicSidetabMissionResult;
14
+ claude: ClassicSidetabMissionResult;
15
+ status: 'done' | 'error';
16
+ finishedAt: number;
17
+ }
18
+ type ClassicSidetabPairOutcome = ClassicSidetabMissionResult;
19
+ interface ClassicSidetabMissionPairJob {
20
+ missionId?: string;
21
+ taskId: string;
22
+ parentSessionId?: string;
23
+ startedAt: number;
24
+ mission: string;
25
+ workspaceDir: string;
26
+ completion: Promise<ClassicSidetabPairOutcome>;
27
+ }
28
+
29
+ function safeFilePart(value: string): string {
30
+ return value.replace(/[^a-zA-Z0-9_-]/g, '-').slice(0, 80) || 'pair';
31
+ }
32
+
33
+ function resultFileLabel(workspaceDir: string, result: ClassicSidetabPairOutcome): string {
34
+ if (!result.path) return '없음';
35
+ const rel = relative(workspaceDir, result.path);
36
+ return rel && !isAbsolute(rel) && rel !== '..' && !rel.startsWith(`..${sep}`) ? rel : basename(result.path);
37
+ }
38
+
39
+ function buildPairSynthesis(
40
+ pair: { codex: ClassicSidetabMissionPairJob; claude: ClassicSidetabMissionPairJob },
41
+ codex: ClassicSidetabPairOutcome,
42
+ claude: ClassicSidetabPairOutcome,
43
+ ): string {
44
+ const rows = [
45
+ { agent: 'Codex', job: pair.codex, result: codex },
46
+ { agent: 'Claude Code', job: pair.claude, result: claude },
47
+ ];
48
+ const cell = (value: string): string => value.replace(/[\r\n]+/g, ' ').trim().replaceAll('\\', '&#92;').replaceAll('|', '&#124;');
49
+ const table = rows.map(({ agent, job, result }) => {
50
+ const accepted = result.ok && Boolean(result.content?.trim());
51
+ const decision = accepted
52
+ ? '채택 — 별도 기여로 보존; 두 결과 간 우열을 임의 판정하지 않음'
53
+ : `미채택 — ${result.error ?? (result.ok ? '빈 결과' : '실패')}`;
54
+ const task = job.mission.length > 240 ? `${job.mission.slice(0, 240)}…` : job.mission;
55
+ return `| ${cell(agent)} | ${cell(task)} | ${cell(resultFileLabel(job.workspaceDir, result))} | ${accepted ? '성공' : '실패/빈 결과'} | ${cell(decision)} |`;
56
+ }).join('\n');
57
+ const contributions = rows.flatMap(({ agent, result }) => {
58
+ const content = result.ok ? result.content?.trim() : '';
59
+ if (!content) return [];
60
+ return [`## ${agent} 기여`, redactMissionResultPath(content, result.path)];
61
+ });
62
+ return [
63
+ '# Codex + Claude mission pair synthesis', '',
64
+ `- Codex mission: ${pair.codex.missionId ?? 'unavailable'}`,
65
+ `- Claude mission: ${pair.claude.missionId ?? 'unavailable'}`, '',
66
+ '## 비교·채택 표', '',
67
+ '| 손 | 맡은 작업 | 결과 파일 | 판정 | 채택 근거 |',
68
+ '|---|---|---|---|---|', table, '',
69
+ '채택 기준: 성공하고 비어 있지 않은 결과를 각자 독립 기여로 보존한다. 두 손의 답이 서로 다른 작업 분담에서 나온 경우 품질 순위를 추정하지 않으며, 실패·빈 결과는 채택하지 않고 사유를 남긴다.', '',
70
+ ...contributions.flatMap((section) => [section, '']),
71
+ ].join('\n').trimEnd() + '\n';
72
+ }
73
+
74
+ function persistPairSynthesis(
75
+ pair: { codex: ClassicSidetabMissionPairJob; claude: ClassicSidetabMissionPairJob },
76
+ taskId: string,
77
+ codex: ClassicSidetabPairOutcome,
78
+ claude: ClassicSidetabPairOutcome,
79
+ ): string {
80
+ if (typeof pair.codex.workspaceDir !== 'string' || !pair.codex.workspaceDir.trim()
81
+ || pair.codex.workspaceDir !== pair.claude.workspaceDir) {
82
+ throw new Error('pair members must share a workspace to persist one synthesis artifact');
83
+ }
84
+ const dir = join(pair.codex.workspaceDir, '.elanous', 'mission-results');
85
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
86
+ const path = join(dir, `classic-pair-synthesis-${safeFilePart(taskId)}-${randomUUID()}.md`);
87
+ writeFileSync(path, buildPairSynthesis(pair, codex, claude), { encoding: 'utf8', mode: 0o600, flag: 'wx' });
88
+ return path;
89
+ }
90
+
91
+ function compactPairNotification(status: 'done' | 'error', body: string, id: string): string {
92
+ const clean = (value: string): string => value.replace(/[\u0000-\u001f\u007f]/g, ' ').replace(/\s+/g, ' ').trim();
93
+ const payload = { status, body: clean(body), id: clean(id).slice(0, 80) || 'pair' };
94
+ let serialized = JSON.stringify(payload);
95
+ while (serialized.length > 500 && payload.body.length > 0) {
96
+ payload.body = payload.body.slice(0, -1);
97
+ serialized = JSON.stringify(payload);
98
+ }
99
+ return serialized;
100
+ }
101
+
102
+ function pairFailurePreview(name: string, result: ClassicSidetabPairOutcome): string {
103
+ const value = result.ok ? result.content?.trim() ?? '' : result.error ?? 'no result returned';
104
+ const redacted = redactMissionResultPath(value, result.path);
105
+ const clean = redacted.replace(/[\u0000-\u001f\u007f]/g, ' ').replace(/\s+/g, ' ').trim();
106
+ return `${name}: ${clean.slice(0, 110)}${clean.length > 110 ? '…' : ''}`;
107
+ }
7
108
 
8
109
  /** Deliver one eventual sidetab result through the parent's existing task-notification input path. */
9
110
  export function enqueueClassicSidetabMissionCompletion(
@@ -56,3 +157,94 @@ export function enqueueClassicSidetabMissionCompletion(
56
157
  });
57
158
  });
58
159
  }
160
+
161
+ /** Deliver a single combined parent notification after both parallel agents finish. */
162
+ export function enqueueClassicSidetabMissionPairCompletion(
163
+ pair: { codex: ClassicSidetabMissionPairJob; claude: ClassicSidetabMissionPairJob },
164
+ enqueue: ClassicMissionNotificationEnqueue,
165
+ now: () => number = Date.now,
166
+ options: { timeoutMs?: number; onTimeout?: () => void; onComplete?: (result: ClassicSidetabMissionPairCompletionResult) => void } = {},
167
+ ): Promise<ClassicSidetabMissionPairCompletionResult> {
168
+ const taskId = pair.codex.taskId;
169
+ const startedAt = Math.min(pair.codex.startedAt, pair.claude.startedAt);
170
+ const timeoutMs = options.timeoutMs ?? CLASSIC_SIDETAB_PAIR_TIMEOUT_MS;
171
+ let timeout: ReturnType<typeof setTimeout> | undefined;
172
+ const timedOut = new Promise<[ClassicSidetabPairOutcome, ClassicSidetabPairOutcome]>((resolve) => {
173
+ timeout = setTimeout(() => {
174
+ try { options.onTimeout?.(); } catch { /* timeout cleanup cannot suppress the receipt */ }
175
+ const failure = (member: string): ClassicSidetabPairOutcome => ({ ok: false, status: 'failed', error: `${member} sidetab mission exceeded the one-hour safety timeout` });
176
+ resolve([failure('Codex'), failure('Claude')]);
177
+ }, Math.max(1, timeoutMs));
178
+ });
179
+ const rejected = (name: string) => (error: unknown): ClassicSidetabPairOutcome => ({
180
+ ok: false,
181
+ status: 'failed',
182
+ error: `${name} sidetab mission rejected: ${error instanceof Error ? error.message : String(error)}`,
183
+ });
184
+ return Promise.race([
185
+ Promise.all([pair.codex.completion.catch(rejected('Codex')), pair.claude.completion.catch(rejected('Claude'))]),
186
+ timedOut,
187
+ ]).then(([codex, claude]) => {
188
+ const finishedAt = now();
189
+ const bothSucceeded = codex.ok && claude.ok && Boolean(codex.content?.trim()) && Boolean(claude.content?.trim());
190
+ let synthesisPath: string | undefined;
191
+ let synthesisError: string | undefined;
192
+ try { synthesisPath = persistPairSynthesis(pair, taskId, codex, claude); }
193
+ catch (error) {
194
+ synthesisError = error instanceof Error ? error.message : String(error);
195
+ debug.log('classic-sidetab.mission-pair', 'synthesis-write-failed', { taskId, reason: synthesisError }, { level: 'warn' });
196
+ }
197
+ const ok = bothSucceeded && Boolean(synthesisPath);
198
+ const result: ClassicSidetabMissionPairCompletionResult = {
199
+ codex, claude, status: ok ? 'done' : 'error', finishedAt,
200
+ };
201
+ try { options.onComplete?.(result); }
202
+ catch { debug.log('classic-sidetab.mission-pair', 'completion-callback-failed', { taskId, retry: false }); }
203
+ const summary = synthesisPath
204
+ ? bothSucceeded ? 'Both missions completed. Full comparison attached.' : 'Pair completed with failures. Full comparison attached.'
205
+ : `Synthesis save failed; ${pairFailurePreview('Codex', codex)}; ${pairFailurePreview('Claude', claude)}`;
206
+ const output = compactPairNotification(ok ? 'done' : 'error', summary, pair.codex.missionId ?? pair.claude.missionId ?? taskId);
207
+ try {
208
+ enqueue({
209
+ taskId,
210
+ ...(pair.codex.parentSessionId ? { parentSessionId: pair.codex.parentSessionId } : {}),
211
+ agentName: 'Codex + Claude',
212
+ label: CLASSIC_SIDETAB_MISSION_LABEL,
213
+ state: ok ? 'done' : 'error',
214
+ output,
215
+ truncated: !synthesisPath,
216
+ ...(synthesisPath ? { resultPath: synthesisPath } : {}),
217
+ durationMs: Math.max(0, finishedAt - startedAt),
218
+ finishedAt,
219
+ });
220
+ } catch {
221
+ debug.log('classic-sidetab.mission-pair', 'completion-enqueue-failed', { taskId, retry: false });
222
+ }
223
+ return result;
224
+ }).catch(() => {
225
+ const finishedAt = now();
226
+ const failure = (error: string): ClassicSidetabMissionResult => ({ ok: false, status: 'failed', error });
227
+ const result: ClassicSidetabMissionPairCompletionResult = {
228
+ codex: failure('Codex/Claude pair failed before results were available'),
229
+ claude: failure('Codex/Claude pair failed before results were available'),
230
+ status: 'error', finishedAt,
231
+ };
232
+ try { options.onComplete?.(result); } catch { debug.log('classic-sidetab.mission-pair', 'completion-callback-failed', { taskId, retry: false }); }
233
+ try {
234
+ enqueue({
235
+ taskId,
236
+ ...(pair.codex.parentSessionId ? { parentSessionId: pair.codex.parentSessionId } : {}),
237
+ agentName: 'Codex + Claude',
238
+ label: CLASSIC_SIDETAB_MISSION_LABEL,
239
+ state: 'error',
240
+ output: compactPairNotification('error', 'Concurrent Codex/Claude missions failed before results were available', pair.codex.missionId ?? pair.claude.missionId ?? taskId),
241
+ truncated: false,
242
+ durationMs: Math.max(0, finishedAt - startedAt),
243
+ finishedAt,
244
+ });
245
+ } catch {
246
+ debug.log('classic-sidetab.mission-pair', 'completion-enqueue-failed', { taskId, retry: false });
247
+ }
248
+ return result;
249
+ }).finally(() => { if (timeout) clearTimeout(timeout); });
250
+ }
@@ -0,0 +1,82 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import type { ClassicSidetabMissionPairResult, ClassicSidetabMissionPairSessionRegistry, ClassicSidetabMissionResult, ClassicSidetabMissionDispatchContext } from './classic-sidetab-mission.js';
3
+ import { enqueueClassicSidetabMissionPairCompletion, type ClassicMissionNotificationEnqueue, type ClassicSidetabMissionPairCompletionResult } from './classic-sidetab-mission-job.js';
4
+
5
+ interface ClassicSidetabPairSession {
6
+ id: string;
7
+ cwd: string;
8
+ }
9
+
10
+ export interface StartClassicSidetabMissionPairDeps<Session extends ClassicSidetabPairSession> {
11
+ agent: 'codex' | 'claude';
12
+ mission: string;
13
+ parallelMission: string;
14
+ context?: ClassicSidetabMissionDispatchContext;
15
+ spawnVisible: (agent: 'codex' | 'claude', missionId: string, attemptId: string) => Session | null;
16
+ runVisible: (agent: 'codex' | 'claude', prompt: string, session: Session | null, missionId?: string) => Promise<ClassicSidetabMissionResult>;
17
+ registry: ClassicSidetabMissionPairSessionRegistry;
18
+ hasSession: (sessionId: string) => boolean;
19
+ killSession: (sessionId: string) => void;
20
+ enqueue: ClassicMissionNotificationEnqueue;
21
+ now?: () => number;
22
+ createId?: () => string;
23
+ timeoutMs?: number;
24
+ onComplete?: (result: ClassicSidetabMissionPairCompletionResult) => void;
25
+ }
26
+
27
+ /** Production seam: start both visible PTYs, bind IDs/cancellation, and deliver one parent-linked completion receipt. */
28
+ export function startClassicSidetabMissionPair<Session extends ClassicSidetabPairSession>(
29
+ deps: StartClassicSidetabMissionPairDeps<Session>,
30
+ ): { result: ClassicSidetabMissionPairResult; completion: Promise<ClassicSidetabMissionPairCompletionResult> } {
31
+ // Keep Codex as the last-opened PTY regardless of which mission prompt is
32
+ // primary. The dashboard closes each popup after spawn, detaching its modal
33
+ // while preserving the session in the sidetab registry. On the tested
34
+ // Codex-first demo path, opening Codex last avoids a missed follow-up
35
+ // completion marker; this is a sequencing workaround, not a fix for
36
+ // background PTY marker detection (tracked by SIDETAB-MARKER-BACKGROUND-DETECT).
37
+ const createId = deps.createId ?? randomUUID;
38
+ const codexMissionId = createId();
39
+ const claudeMissionId = createId();
40
+ const codexAttemptId = createId();
41
+ const claudeAttemptId = createId();
42
+ const claudeSession = deps.spawnVisible('claude', claudeMissionId, claudeAttemptId);
43
+ const codexSession = deps.spawnVisible('codex', codexMissionId, codexAttemptId);
44
+ const missionIds = [codexSession ? codexMissionId : undefined, claudeSession ? claudeMissionId : undefined].filter((id): id is string => Boolean(id));
45
+ const activeCodexMissionId = codexSession ? codexMissionId : undefined;
46
+ const activeClaudeMissionId = claudeSession ? claudeMissionId : undefined;
47
+ const sessionIds = [codexSession?.id, claudeSession?.id].filter((id): id is string => Boolean(id));
48
+ deps.registry.register(missionIds, sessionIds);
49
+
50
+ const codexPrompt = deps.agent === 'codex' ? deps.mission : deps.parallelMission;
51
+ const claudePrompt = deps.agent === 'claude' ? deps.mission : deps.parallelMission;
52
+ const startedAt = (deps.now ?? Date.now)();
53
+ const codexCompletion = deps.runVisible('codex', codexPrompt, codexSession, activeCodexMissionId);
54
+ const claudeCompletion = deps.runVisible('claude', claudePrompt, claudeSession, activeClaudeMissionId);
55
+ // callId is the parent tool invocation identity; falling back to a mission id
56
+ // preserves queue uniqueness for embedders that do not expose a call id.
57
+ const taskId = deps.context?.callId || activeCodexMissionId || activeClaudeMissionId || createId();
58
+ const workspaceDir = codexSession?.cwd ?? claudeSession?.cwd ?? '';
59
+ const completion = missionIds.length
60
+ ? enqueueClassicSidetabMissionPairCompletion({
61
+ codex: { missionId: activeCodexMissionId, taskId, parentSessionId: deps.context?.parentSessionId, startedAt, mission: codexPrompt, workspaceDir, completion: codexCompletion },
62
+ claude: { missionId: activeClaudeMissionId, taskId, parentSessionId: deps.context?.parentSessionId, startedAt, mission: claudePrompt, workspaceDir, completion: claudeCompletion },
63
+ }, deps.enqueue, deps.now, {
64
+ timeoutMs: deps.timeoutMs,
65
+ onTimeout: () => { for (const sessionId of sessionIds) if (deps.hasSession(sessionId)) deps.killSession(sessionId); },
66
+ ...(deps.onComplete ? { onComplete: deps.onComplete } : {}),
67
+ }).finally(() => deps.registry.clear(missionIds))
68
+ : Promise.resolve<ClassicSidetabMissionPairCompletionResult>({
69
+ codex: { ok: false, status: 'failed' as const, error: 'Codex sidetab PTY could not start' },
70
+ claude: { ok: false, status: 'failed' as const, error: 'Claude sidetab PTY could not start' },
71
+ status: 'error' as const, finishedAt: (deps.now ?? Date.now)(),
72
+ });
73
+
74
+ return {
75
+ result: {
76
+ pairId: `${activeCodexMissionId ?? 'codex-unavailable'}+${activeClaudeMissionId ?? 'claude-unavailable'}`,
77
+ codex: codexSession ? { ok: true, status: 'running', path: '', interactionId: activeCodexMissionId } : { ok: false, status: 'failed', error: 'Codex sidetab PTY could not start' },
78
+ claude: claudeSession ? { ok: true, status: 'running', path: '', interactionId: activeClaudeMissionId } : { ok: false, status: 'failed', error: 'Claude sidetab PTY could not start' },
79
+ },
80
+ completion,
81
+ };
82
+ }
@@ -0,0 +1,242 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { mkdirSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { debug } from '../debug/log.js';
5
+ import type { ClassicSidetabMissionDispatchContext, ClassicSidetabMissionPairSessionRegistry, ClassicSidetabMissionResult } from './classic-sidetab-mission.js';
6
+ import { redactMissionResultPath } from './mission-cli-consumer.js';
7
+ import type { ClassicMissionNotificationEnqueue } from './classic-sidetab-mission-job.js';
8
+
9
+ export type ClassicMissionAgent = 'codex' | 'claude' | 'grok';
10
+
11
+ interface TrioSession { id: string; cwd: string }
12
+ interface MissionOutcome extends ClassicSidetabMissionResult { content?: string }
13
+ const MAX_FINAL_SCREEN_CHARS = 4_000;
14
+
15
+ export interface StartClassicSidetabMissionTrioDeps<Session extends TrioSession> {
16
+ mission: string;
17
+ context?: ClassicSidetabMissionDispatchContext;
18
+ checkGrokAuth: () => { ok: boolean; reason?: string } | Promise<{ ok: boolean; reason?: string }>;
19
+ spawnVisible: (agent: ClassicMissionAgent, missionId: string, attemptId: string) => Session | null;
20
+ runVisible: (agent: ClassicMissionAgent, mission: string, session: Session | null, missionId?: string) => Promise<MissionOutcome>;
21
+ registry: ClassicSidetabMissionPairSessionRegistry;
22
+ hasSession: (sessionId: string) => boolean;
23
+ killSession: (sessionId: string) => void;
24
+ enqueue: ClassicMissionNotificationEnqueue;
25
+ now?: () => number;
26
+ createId?: () => string;
27
+ timeoutMs?: number;
28
+ }
29
+
30
+ export interface ClassicSidetabMissionTrioStart {
31
+ trioId: string;
32
+ members: Record<ClassicMissionAgent, ClassicSidetabMissionResult>;
33
+ grokFallback?: string;
34
+ }
35
+
36
+ const DEFAULT_TIMEOUT_MS = 60 * 60 * 1_000;
37
+ const MAX_ANSWER_CHARS = 8_000;
38
+
39
+ function markdownCell(value: string | undefined): string {
40
+ return (value ?? '—').replaceAll('|', '\\|').replace(/\r?\n/g, '<br>');
41
+ }
42
+
43
+ function fenced(value: string): string {
44
+ const longest = Math.max(0, ...[...value.matchAll(/`+/g)].map((match) => match[0].length));
45
+ const fence = '`'.repeat(Math.max(3, longest + 1));
46
+ return `${fence}text\n${value}\n${fence}`;
47
+ }
48
+
49
+ function renderTrioSynthesis(mission: string, results: Record<ClassicMissionAgent, MissionOutcome>): string {
50
+ const agents: ClassicMissionAgent[] = ['codex', 'claude', 'grok'];
51
+ const rows = agents.map((agent) => {
52
+ const result = results[agent];
53
+ return `| ${agent} | ${markdownCell(mission)} | ${markdownCell(result.path)} | ${result.ok ? '완료' : markdownCell(result.error ?? result.status ?? '실패')} | |`;
54
+ });
55
+ const candidates = agents.map((agent) => {
56
+ const result = results[agent];
57
+ return [`### ${agent}`, `- 결과 경로: ${result.path ?? '없음'}`, `- 상태: ${result.ok ? '완료' : result.error ?? result.status ?? '실패'}`, '', result.content?.trim() ? fenced(result.content.trim()) : '_결과 내용 없음_'].join('\n');
58
+ });
59
+ return [
60
+ '# Sidetab mission synthesis record',
61
+ '',
62
+ '## 요청',
63
+ fenced(mission),
64
+ '',
65
+ '## 손별 귀속',
66
+ '| 손 | 맡은 일 | 결과 파일 | 결과 상태 | 채택 여부 |',
67
+ '| --- | --- | --- | --- | --- |',
68
+ ...rows,
69
+ '',
70
+ '## 후보 결과',
71
+ ...candidates,
72
+ '',
73
+ '## 채택 결과',
74
+ '_최종 채택문은 알림을 받은 부모 응답에서 작성한다. 성공 후보가 있으면 이 후보들만 근거로 채택하고, 성공 후보가 하나면 그 결과를 그대로 채택한다._',
75
+ '',
76
+ '## 채택 근거',
77
+ '_후보별 상태와 원문은 위 표에 기록했다. 실패한 손은 채택 근거에서 제외한다._',
78
+ '',
79
+ ].join('\n');
80
+ }
81
+
82
+ function persistTrioSynthesis(cwd: string, trioId: string, mission: string, results: Record<ClassicMissionAgent, MissionOutcome>): string {
83
+ const safeId = trioId.replace(/[^a-zA-Z0-9._-]/g, '-').slice(0, 120) || randomUUID();
84
+ const dir = join(cwd, '.elanous', 'mission-results');
85
+ mkdirSync(dir, { recursive: true });
86
+ const path = join(dir, `classic-trio-synthesis-${safeId}.md`);
87
+ writeFileSync(path, renderTrioSynthesis(mission, results), { encoding: 'utf8', flag: 'wx', mode: 0o600 });
88
+ return path;
89
+ }
90
+
91
+ /** Starts three visible PTYs with one verbatim goal; an unavailable Grok degrades to Codex + Claude. */
92
+ export async function startClassicSidetabMissionTrio<Session extends TrioSession>(
93
+ deps: StartClassicSidetabMissionTrioDeps<Session>,
94
+ ): Promise<{ result: ClassicSidetabMissionTrioStart; completion: Promise<void> }> {
95
+ const createId = deps.createId ?? randomUUID;
96
+ const now = deps.now ?? Date.now;
97
+ const startedAt = now();
98
+ // Start the first hand before the bounded subscribed-access probe. The
99
+ // probe may need a network round-trip, but must not consume the whole
100
+ // 30-second three-hand startup budget before any visible work begins.
101
+ const ids = new Map<ClassicMissionAgent, string>();
102
+ const sessions = new Map<ClassicMissionAgent, Session | null>();
103
+ const agents: ClassicMissionAgent[] = [];
104
+ const spawn = (agent: ClassicMissionAgent): Session | null => {
105
+ const missionId = createId();
106
+ ids.set(agent, missionId);
107
+ agents.push(agent);
108
+ const session = deps.spawnVisible(agent, missionId, createId());
109
+ if (!session) {
110
+ ids.delete(agent);
111
+ agents.pop();
112
+ return null;
113
+ }
114
+ sessions.set(agent, session);
115
+ return session;
116
+ };
117
+ spawn('claude');
118
+ spawn('codex');
119
+ const grokAuth = await deps.checkGrokAuth();
120
+ let grokFallback = grokAuth.ok ? undefined : grokAuth.reason ?? 'Grok login unavailable';
121
+ if (grokAuth.ok && !spawn('grok')) {
122
+ grokFallback = 'Grok sidetab PTY could not start';
123
+ }
124
+ const sessionIds = [...sessions.values()].flatMap((session) => session ? [session.id] : []);
125
+ const missionIds = [...ids.values()];
126
+ deps.registry.register(missionIds, sessionIds);
127
+ const outcomes = new Map<ClassicMissionAgent, Promise<MissionOutcome>>();
128
+ const completedOutcomes = new Map<ClassicMissionAgent, MissionOutcome>();
129
+ for (const agent of agents) {
130
+ const session = sessions.get(agent) ?? null;
131
+ if (agent === 'grok' && !session) continue;
132
+ const outcome = Promise.resolve().then(() => deps.runVisible(agent, deps.mission, session, ids.get(agent))).catch((error): MissionOutcome => ({
133
+ ok: false, status: 'failed', error: error instanceof Error ? error.message : String(error),
134
+ }));
135
+ outcomes.set(agent, outcome.then((result) => { completedOutcomes.set(agent, result); return result; }));
136
+ }
137
+ const members: Record<ClassicMissionAgent, ClassicSidetabMissionResult> = {
138
+ codex: sessions.get('codex') ? { ok: true, status: 'running', interactionId: ids.get('codex') } : { ok: false, status: 'failed', error: 'Codex sidetab PTY could not start' },
139
+ claude: sessions.get('claude') ? { ok: true, status: 'running', interactionId: ids.get('claude') } : { ok: false, status: 'failed', error: 'Claude sidetab PTY could not start' },
140
+ grok: sessions.get('grok') ? { ok: true, status: 'running', interactionId: ids.get('grok') } : { ok: false, status: 'failed', error: grokFallback ?? 'Grok sidetab PTY could not start' },
141
+ };
142
+ const taskId = deps.context?.callId || ids.get('codex') || ids.get('claude') || createId();
143
+ const timeoutMs = Math.max(1, deps.timeoutMs ?? DEFAULT_TIMEOUT_MS);
144
+ let timeout: ReturnType<typeof setTimeout> | undefined;
145
+ const timedOut = new Promise<void>((resolve) => {
146
+ timeout = setTimeout(() => {
147
+ for (const sessionId of sessionIds) if (deps.hasSession(sessionId)) deps.killSession(sessionId);
148
+ resolve();
149
+ }, timeoutMs);
150
+ });
151
+ const settled = Promise.all([...outcomes].map(async ([agent, promise]) => [agent, await promise] as const));
152
+ const completion = Promise.race([settled.then((results) => ({ didTimeout: false, results })), timedOut.then(() => ({ didTimeout: true, results: [...completedOutcomes.entries()] as const }))]).then(({ didTimeout, results }) => {
153
+ const finishedAt = now();
154
+ const all: Record<ClassicMissionAgent, MissionOutcome> = {
155
+ codex: { ...members.codex, ...(members.codex.status === 'running' ? { error: undefined } : {}) },
156
+ claude: { ...members.claude, ...(members.claude.status === 'running' ? { error: undefined } : {}) },
157
+ grok: { ...members.grok, ...(members.grok.status === 'running' ? { error: undefined } : {}) },
158
+ };
159
+ for (const [agent, outcome] of results) all[agent] = outcome;
160
+ let synthesisPath: string | undefined;
161
+ let synthesisError: string | undefined;
162
+ const artifactCwd = [...sessions.values()].find((session): session is Session => Boolean(session))?.cwd;
163
+ if (artifactCwd) {
164
+ try {
165
+ const trioId = `trio-${ids.get('codex') ?? ids.get('claude') ?? createId()}`;
166
+ synthesisPath = persistTrioSynthesis(artifactCwd, trioId, deps.mission, all);
167
+ debug.log('classic-sidetab.mission-trio', 'synthesis-record-written', {
168
+ taskId,
169
+ trioId,
170
+ resultPath: synthesisPath,
171
+ candidateCount: Object.values(all).filter((result) => Boolean(result.path || result.content)).length,
172
+ });
173
+ } catch (error) {
174
+ synthesisError = error instanceof Error ? error.message : String(error);
175
+ }
176
+ } else {
177
+ synthesisError = 'no sidetab workspace was available for the synthesis record';
178
+ }
179
+ const timeoutReason = didTimeout ? 'mission exceeded the configured safety timeout' : undefined;
180
+ const answer = (agent: ClassicMissionAgent): string => {
181
+ const result = all[agent];
182
+ const screen = result.finalScreen?.trim();
183
+ const screenRecord = screen ? `\n\n${agent} final raw PTY screen:\n${screen.length > MAX_FINAL_SCREEN_CHARS ? `${screen.slice(-MAX_FINAL_SCREEN_CHARS)}\n[screen tail truncated]` : screen}` : '';
184
+ const initial = result.initialScreen?.trim();
185
+ const initialRecord = initial ? `\n\n${agent} first PTY snapshot:\n${initial.length > 1_200 ? `${initial.slice(-1_200)}\n[first screen tail truncated]` : initial}` : '';
186
+ if (timeoutReason && result.status === 'running') return `${agent}: ${timeoutReason}${initialRecord}${screenRecord}`;
187
+ if (!result.ok) return `${agent}: ${result.error ?? 'failed; no answer returned'}${initialRecord}${screenRecord}`;
188
+ const content = result.content?.trim();
189
+ if (!content) return `${agent}: completed without an answer${screenRecord}`;
190
+ const safe = redactMissionResultPath(content, result.path);
191
+ return `${agent} candidate:\n${safe.length > MAX_ANSWER_CHARS ? `${safe.slice(0, MAX_ANSWER_CHARS)}\n[answer truncated]` : safe}${initialRecord}${screenRecord}`;
192
+ };
193
+ const grokFailed = Boolean(grokFallback) || !all.grok.ok;
194
+ // When Grok cannot start, the run is explicitly a two-hand fallback;
195
+ // do not count the unstarted Grok hand as missing coverage or a failure.
196
+ const expectedAgents = grokFallback ? (['codex', 'claude'] as const) : (['codex', 'claude', 'grok'] as const);
197
+ const candidateAgents = expectedAgents.filter((agent) => all[agent].ok && Boolean(all[agent].content?.trim()));
198
+ const failedMembers = expectedAgents
199
+ .filter((agent) => !candidateAgents.includes(agent))
200
+ .map((agent) => ({
201
+ agent,
202
+ reason: timeoutReason && all[agent].status === 'running'
203
+ ? timeoutReason
204
+ : all[agent].error ?? (all[agent].ok ? 'completed without an answer' : all[agent].status ?? 'failed'),
205
+ }));
206
+ // A completed notification with at least one candidate lets the parent
207
+ // synthesize/adopt the available work. `coverage` describes partial runs;
208
+ // state and JSON status intentionally share the same done/error value.
209
+ const notificationStatus = candidateAgents.length > 0 ? 'done' : 'error';
210
+ const coverage = candidateAgents.length === 0 ? 'none' : candidateAgents.length === expectedAgents.length ? 'complete' : 'partial';
211
+ const body = [
212
+ `Three-hand comparison · same goal · ${grokFailed ? `Grok unavailable; continued with Codex + Claude (${all.grok.error ?? 'failed'})` : 'Codex + Claude + Grok results'}`,
213
+ `Coverage: ${coverage}; successful candidates: ${candidateAgents.length ? candidateAgents.join(', ') : 'none'}; failed members: ${failedMembers.length ? failedMembers.map(({ agent, reason }) => `${agent} (${reason})`).join('; ') : 'none'}.`,
214
+ synthesisPath ? `Synthesis record: ${synthesisPath}` : `Synthesis record unavailable: ${synthesisError ?? 'unknown write failure'}`,
215
+ candidateAgents.length > 0
216
+ ? 'Adopt or synthesize the final answer from the successful candidates only. If exactly one candidate succeeded, adopt it directly. Name failed members and never imply they succeeded.'
217
+ : 'No candidate succeeded; explicitly report that no result can be adopted.',
218
+ '', answer('codex'), '', answer('claude'), '', answer('grok'), '',
219
+ candidateAgents.length > 0 ? 'Present a non-empty adopted result and a short reason.' : 'Leave the adopted result explicitly unavailable; do not fabricate one.',
220
+ ].join('\n');
221
+ try {
222
+ deps.enqueue({
223
+ taskId,
224
+ ...(deps.context?.parentSessionId ? { parentSessionId: deps.context.parentSessionId } : {}),
225
+ agentName: grokFailed ? 'Codex + Claude (Grok fallback)' : 'Codex + Claude + Grok',
226
+ label: 'sidetab mission comparison',
227
+ state: notificationStatus,
228
+ output: JSON.stringify({ status: notificationStatus, coverage, successfulMembers: candidateAgents, failedMembers, body, artifacts: synthesisPath ? [synthesisPath] : [], id: ids.get('codex') ?? ids.get('claude') ?? taskId, grokFallback: grokFailed ? all.grok.error : undefined }),
229
+ ...(synthesisPath ? { resultPath: synthesisPath } : {}),
230
+ truncated: body.includes('[answer truncated]'),
231
+ durationMs: Math.max(0, finishedAt - startedAt),
232
+ finishedAt,
233
+ });
234
+ } catch { /* notification delivery cannot interrupt the missions */ }
235
+ }).finally(() => {
236
+ if (timeout) clearTimeout(timeout);
237
+ for (const sessionId of sessionIds) if (deps.hasSession(sessionId)) deps.killSession(sessionId);
238
+ deps.registry.clear(missionIds);
239
+ });
240
+
241
+ return { result: { trioId: `trio-${ids.get('codex') ?? ids.get('claude') ?? createId()}`, members, ...(grokFallback ? { grokFallback } : {}) }, completion };
242
+ }