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
@@ -0,0 +1,391 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { basename } from 'node:path';
3
+ import { awaitGlobalPersonaLoad, getGlobalPersonaRegistry } from '../persona/global-registry.js';
4
+ import { getSecretAsync } from '../nexus/config/secrets/index.js';
5
+ import { commentLinearIssue, createLinearAttachment, uploadLinearFile } from '../connectors/linear.js';
6
+ import { performBrowserAction, type BrowserActionDeps } from '../harness/browser-act.js';
7
+ import { decideActionBoundary } from '../harness/browser-act-boundary.js';
8
+ import { BROWSER_ACT_CATEGORY, BROWSER_ACT_EVENT } from '../harness/browser-act-step.js';
9
+ import type { BrowserActionResult } from '../harness/browser-act.js';
10
+ import { createCdpClientFromEndpoint } from '../browser-cdp/client.js';
11
+ import { orchestrationId } from '../grounding/ref-index.js';
12
+ import { debug } from '../debug/log.js';
13
+ import { requestConfirmation } from '../hitl/confirm.js';
14
+ import type { ToolRuntime, ToolRuntimeContext } from './types.js';
15
+ import { coordinateBrowserRoundtrip } from '../agent-mission/browser-roundtrip-coordinator.js';
16
+ import { appendRunLedgerEntry } from '../self-implement/run-ledger.js';
17
+ import { getHarnessRunId } from '../harness/harness-space.js';
18
+
19
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
20
+ const SELECTION_COMMENT = '이것도 반영';
21
+ const PAYWALL_PATTERN = /(paywall|subscribe\s?to\s?continue|subscription\srequired|유료\s?구독)/i;
22
+ const LOGIN_PATTERN = /(login\srequired|please\s+log\s?in|sign\s?in\s+to\s+continue|authentication\srequired|로그인\s*(이|가)?\s*필요|로그인\s*후\s*계속)/i;
23
+ const ASIDE_HAND_NODE_BRANCH = 'ASIDE-HAND-NODE·BROWSER-ROUNDTRIP-ASIDE' as const;
24
+ const PAGE_INSPECT_TIMEOUT_MS = 3_000;
25
+
26
+ export interface BrowserHandArgs {
27
+ url: string;
28
+ target: string;
29
+ armed: boolean;
30
+ linearSubtaskId: string;
31
+ persona?: string;
32
+ alternateUrl?: string;
33
+ includeThisToo?: boolean;
34
+ selection?: { text?: string; tab?: string };
35
+ }
36
+
37
+ export interface BrowserHandRepairNode extends Record<string, unknown> {
38
+ branch: typeof ASIDE_HAND_NODE_BRANCH;
39
+ orchestrationId: string;
40
+ blockedOn: string;
41
+ detourUrl: string;
42
+ outcome: 'detoured' | 'detour-failed';
43
+ graphEvent: {
44
+ seq: number;
45
+ ts: string;
46
+ type: 'node-added';
47
+ node: string;
48
+ kind: 'hand';
49
+ decider: 'browser-hand';
50
+ reason: string;
51
+ who: 'Elanous';
52
+ what: string;
53
+ missionId: string;
54
+ runId?: string;
55
+ };
56
+ }
57
+
58
+ export interface BrowserHandResult extends Record<string, unknown> {
59
+ ok: boolean;
60
+ output: string;
61
+ captureUrl?: string;
62
+ attachmentId?: string;
63
+ selectionReflected?: boolean;
64
+ blocked?: boolean;
65
+ detoured?: boolean;
66
+ repairNode?: BrowserHandRepairNode;
67
+ reason?: string;
68
+ }
69
+
70
+ export interface BrowserHandDeps {
71
+ browserAct?: (request: Parameters<typeof performBrowserAction>[0], deps?: BrowserActionDeps) => Promise<BrowserActionResult>;
72
+ browserActDeps?: BrowserActionDeps;
73
+ readCapture?: (path: string) => Promise<Buffer>;
74
+ getApiKey?: (name: string) => Promise<string | undefined>;
75
+ upload?: typeof uploadLinearFile;
76
+ attach?: typeof createLinearAttachment;
77
+ reflectSelection?: (input: { issueId: string; body: string }) => Promise<boolean>;
78
+ resolvePersona?: (id: string) => Promise<NonNullable<Parameters<typeof performBrowserAction>[0]['persona']> | undefined>;
79
+ /** Read-only inspection seam. A missing/unavailable observation is unknown, not unblocked. */
80
+ readPageText?: (url: string, port: number) => Promise<string | undefined>;
81
+ confirmHuman?: (input: { url: string; target: string }, ctx?: ToolRuntimeContext) => Promise<boolean>;
82
+ }
83
+
84
+ async function readPageTextWithCdp(url: string, port: number): Promise<string | undefined> {
85
+ let client: Awaited<ReturnType<typeof createCdpClientFromEndpoint>> | undefined;
86
+ try {
87
+ client = await createCdpClientFromEndpoint(port, { attachTimeoutMs: PAGE_INSPECT_TIMEOUT_MS, timeoutMs: PAGE_INSPECT_TIMEOUT_MS });
88
+ const page = await client.evaluate('({ href: location.href, text: document.body?.innerText ?? "" })');
89
+ if (!page || typeof page !== 'object' || !('href' in page) || !('text' in page)) return undefined;
90
+ const inspected = page as { href?: unknown; text?: unknown };
91
+ if (typeof inspected.href !== 'string' || typeof inspected.text !== 'string') return undefined;
92
+ const observedUrl = new URL(inspected.href);
93
+ const requestedUrl = new URL(url);
94
+ if (observedUrl.origin !== requestedUrl.origin || observedUrl.pathname !== requestedUrl.pathname || observedUrl.search !== requestedUrl.search) return undefined;
95
+ return inspected.text.slice(0, 20_000);
96
+ } catch {
97
+ return undefined;
98
+ } finally {
99
+ try { await client?.close(); } catch { /* attached browser remains user-owned */ }
100
+ }
101
+ }
102
+
103
+ function blockedKind(value: string | undefined): 'login' | 'paywall' | undefined {
104
+ if (!value) return undefined;
105
+ if (PAYWALL_PATTERN.test(value)) return 'paywall';
106
+ return LOGIN_PATTERN.test(value) ? 'login' : undefined;
107
+ }
108
+
109
+ function failureBlockKind(action: BrowserActionResult): 'login' | 'paywall' | undefined {
110
+ return action.ok ? undefined : blockedKind(action.error);
111
+ }
112
+
113
+ function recordRepairNode(node: BrowserHandRepairNode, deps: BrowserHandDeps): void {
114
+ try { debug.log('agent-mission', 'browser-repair-node', node); } catch { /* observability is fail-soft */ }
115
+ try { deps.browserActDeps?.observe?.('repair-node', node); } catch { /* observers must not alter the browser result */ }
116
+ const graphEvent = node.graphEvent;
117
+ if (!graphEvent.runId) return;
118
+ try {
119
+ // The external browser result and its one-retry repair decision become a real
120
+ // sequenced node-added row on the active research run, not just a debug event.
121
+ appendRunLedgerEntry({
122
+ timestamp: graphEvent.ts,
123
+ runId: graphEvent.runId,
124
+ event: graphEvent.type,
125
+ data: {
126
+ node: graphEvent.node,
127
+ kind: graphEvent.kind,
128
+ decider: graphEvent.decider,
129
+ reason: graphEvent.reason,
130
+ who: graphEvent.who,
131
+ what: graphEvent.what,
132
+ missionId: graphEvent.missionId,
133
+ orchestrationId: node.orchestrationId,
134
+ outcome: node.outcome,
135
+ blockedOn: node.blockedOn,
136
+ detourUrl: node.detourUrl,
137
+ },
138
+ });
139
+ debug.log('agent-mission', 'browser-repair-node-ledger-recorded', {
140
+ runId: graphEvent.runId, node: graphEvent.node, orchestrationId: node.orchestrationId,
141
+ });
142
+ } catch (error) {
143
+ try { debug.log('agent-mission', 'browser-repair-node-ledger-failed', {
144
+ runId: graphEvent.runId, node: graphEvent.node,
145
+ error: error instanceof Error ? error.message : String(error),
146
+ }, { level: 'warn' }); } catch { /* graph evidence must remain fail-soft */ }
147
+ }
148
+ }
149
+
150
+ function createRepairNode(input: {
151
+ block: 'login' | 'paywall';
152
+ sourceUrl: string;
153
+ detourUrl: string;
154
+ outcome: 'detoured' | 'detour-failed';
155
+ issueId: string;
156
+ deps: BrowserHandDeps;
157
+ }): BrowserHandRepairNode {
158
+ const runId = input.deps.browserActDeps?.getRunId?.() ?? undefined;
159
+ const orchestration = orchestrationId('aside-hand-node', runId ?? input.issueId);
160
+ const ts = new Date().toISOString();
161
+ const graphEvent = {
162
+ seq: 1 as const,
163
+ ts,
164
+ type: 'node-added' as const,
165
+ node: `browser-repair-${orchestration}`,
166
+ kind: 'hand' as const,
167
+ decider: 'browser-hand' as const,
168
+ reason: `${input.block} blocked source; one alternate source checked`,
169
+ who: 'Elanous' as const,
170
+ what: input.outcome === 'detoured' ? `Continue browser work from ${input.detourUrl}` : 'Stop after blocked browser source',
171
+ missionId: input.issueId,
172
+ ...(runId ? { runId } : {}),
173
+ };
174
+ return {
175
+ branch: ASIDE_HAND_NODE_BRANCH,
176
+ orchestrationId: orchestration,
177
+ blockedOn: `${input.block}:${input.sourceUrl}`,
178
+ detourUrl: input.detourUrl,
179
+ outcome: input.outcome,
180
+ graphEvent,
181
+ };
182
+ }
183
+
184
+ async function reflectSelectionWithLinearIssueTool(input: { issueId: string; body: string }, deps: BrowserHandDeps): Promise<boolean> {
185
+ const apiKey = await (deps.getApiKey ?? getSecretAsync)('connector.linear.apiKey');
186
+ if (!apiKey?.trim()) return false;
187
+ await commentLinearIssue({ apiKey, issueId: input.issueId, body: input.body });
188
+ return true;
189
+ }
190
+
191
+ async function loadPersona(id: string) {
192
+ await awaitGlobalPersonaLoad();
193
+ return getGlobalPersonaRegistry().get(id);
194
+ }
195
+
196
+ /** Attached-CDP browser action stays behind harness browser-act's armed, host and reversibility checks. */
197
+ export async function dispatchBrowserHand(args: BrowserHandArgs, _ctx?: ToolRuntimeContext, deps: BrowserHandDeps = {}): Promise<BrowserHandResult> {
198
+ const runId = _ctx?.runId || getHarnessRunId() || undefined;
199
+ const browserActDeps = {
200
+ ...deps.browserActDeps,
201
+ ...(_ctx?.runId
202
+ ? { getRunId: () => _ctx.runId! }
203
+ : deps.browserActDeps?.getRunId
204
+ ? {}
205
+ : { getRunId: () => runId ?? null }),
206
+ };
207
+ const url = args.url.trim();
208
+ const target = args.target.trim();
209
+ const issueId = args.linearSubtaskId.trim();
210
+ if (!args.armed) return { ok: false, reason: 'unarmed', output: '브라우저 조작은 사람의 명시적 armed 승인 뒤에만 실행합니다.' };
211
+ if (!url || !target || !UUID.test(issueId)) return { ok: false, reason: 'invalid-input', output: 'URL, CSS 대상, Linear 서브태스크 UUID가 필요합니다.' };
212
+ let parsed: URL;
213
+ try { parsed = new URL(url); } catch { return { ok: false, reason: 'invalid-url', output: '절대 URL이 필요합니다.' }; }
214
+ if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') return { ok: false, reason: 'invalid-url', output: 'http(s) URL만 허용합니다.' };
215
+ let humanApproved = false;
216
+ try {
217
+ if (deps.confirmHuman) humanApproved = await deps.confirmHuman({ url, target }, _ctx);
218
+ else humanApproved = (await requestConfirmation({
219
+ prompt: `Browser hand action on ${url}`,
220
+ detail: `Target: ${target}\nExplicit human approval is required before navigation or click.`,
221
+ ...(_ctx?.confirmChannels ? { channels: _ctx.confirmChannels } : {}),
222
+ onTimeout: () => false,
223
+ })).answer === true;
224
+ } catch { /* approval failure is denial */ }
225
+ if (!humanApproved) return { ok: false, reason: 'human-approval-required', output: '사람의 확인 승인을 받지 못해 브라우저를 조작하지 않았습니다.' };
226
+
227
+ if (!args.persona?.trim()) return { ok: false, reason: 'persona-required', output: '허용 호스트가 선언된 브라우저 페르소나가 필요합니다.' };
228
+ const persona = await (deps.resolvePersona ?? loadPersona)(args.persona);
229
+ if (!persona) return { ok: false, reason: 'persona-not-found', output: '브라우저 페르소나를 찾지 못했습니다.' };
230
+ if (!persona.actionHosts?.some(host => host.trim())) {
231
+ return { ok: false, reason: 'host-boundary-undeclared', output: '브라우저 페르소나에 허용 호스트가 선언되지 않아 이동을 시작하지 않았습니다.' };
232
+ }
233
+ const entryBoundary = decideActionBoundary({ hosts: persona.actionHosts, url, href: null });
234
+ if (!entryBoundary.allowed) return { ok: false, reason: 'host-boundary-blocked', output: `허용 호스트 경계가 시작 URL을 차단했습니다: ${entryBoundary.detail}` };
235
+ const pagePort = persona.browserPort ?? 9222;
236
+ const inspect = deps.readPageText ?? readPageTextWithCdp;
237
+ let actionUrl = url;
238
+ let blocked = false;
239
+ let detoured = false;
240
+ let repairNode: BrowserHandRepairNode | undefined;
241
+ let sourceText: string | undefined;
242
+ let capturedPath: string | undefined;
243
+ const runBrowserAction = async (actionUrl: string) => {
244
+ const observe = (event: string, data: Record<string, unknown>) => {
245
+ if (event === BROWSER_ACT_EVENT) {
246
+ const attachmentRef = data.attachmentRef;
247
+ if (typeof attachmentRef === 'string' && attachmentRef.trim()) capturedPath = attachmentRef;
248
+ }
249
+ (deps.browserActDeps?.observe ?? ((name, value) => debug.log(BROWSER_ACT_CATEGORY, name, value)))(event, data);
250
+ };
251
+ return (deps.browserAct ?? performBrowserAction)({
252
+ url: actionUrl, target, armed: true, entryPoint: 'tool-runtime/browser-hand', ...(persona ? { persona } : {}),
253
+ }, { ...browserActDeps, observe, reversibilityPolicy: 'navigation-only' });
254
+ };
255
+ try { sourceText = await inspect(url, pagePort); } catch { /* unavailable observation stays unknown */ }
256
+ let block = blockedKind(sourceText);
257
+ if (block) {
258
+ blocked = true;
259
+ const alternate = args.alternateUrl?.trim() ?? '';
260
+ let alternateAllowed = false;
261
+ let alternateParsed: URL | undefined;
262
+ try { alternateParsed = new URL(alternate); } catch { /* no valid fallback */ }
263
+ if (alternateParsed && ['http:', 'https:'].includes(alternateParsed.protocol)) {
264
+ const boundary = decideActionBoundary({ hosts: persona.actionHosts, url: alternate, href: null });
265
+ alternateAllowed = boundary.allowed;
266
+ }
267
+ let alternateText: string | undefined;
268
+ if (alternateAllowed) {
269
+ try { alternateText = await inspect(alternate, pagePort); } catch { /* unknown is allowed only after the source was verified blocked */ }
270
+ }
271
+ if (alternateAllowed && !blockedKind(alternateText)) {
272
+ actionUrl = alternate;
273
+ detoured = true;
274
+ }
275
+ if (!detoured) {
276
+ repairNode = createRepairNode({ block, sourceUrl: url, detourUrl: '', outcome: 'detour-failed', issueId, deps });
277
+ recordRepairNode(repairNode, deps);
278
+ return { ok: false, blocked, detoured, repairNode, reason: 'blocked-source-no-safe-alternate', output: '로그인·페이월이 관측됐지만 허용된 대체 출처를 확인하지 못해 브라우저 조작을 멈췄습니다.' };
279
+ }
280
+ }
281
+
282
+ let action = await runBrowserAction(actionUrl);
283
+ if (!action.ok && !blocked) {
284
+ block = failureBlockKind(action);
285
+ const alternate = args.alternateUrl?.trim() ?? '';
286
+ let alternateParsed: URL | undefined;
287
+ try { alternateParsed = new URL(alternate); } catch { /* no valid fallback */ }
288
+ let alternateText: string | undefined;
289
+ if (block && alternateParsed && ['http:', 'https:'].includes(alternateParsed.protocol)
290
+ && decideActionBoundary({ hosts: persona.actionHosts, url: alternate, href: null }).allowed) {
291
+ try { alternateText = await inspect(alternate, pagePort); } catch { /* unknown is allowed after an explicit login/paywall error */ }
292
+ }
293
+ if (block && alternateParsed && ['http:', 'https:'].includes(alternateParsed.protocol)
294
+ && decideActionBoundary({ hosts: persona.actionHosts, url: alternate, href: null }).allowed
295
+ && !blockedKind(alternateText)) {
296
+ blocked = true;
297
+ actionUrl = alternate;
298
+ action = await runBrowserAction(actionUrl);
299
+ detoured = true;
300
+ } else if (block) {
301
+ blocked = true;
302
+ }
303
+ if (block) {
304
+ repairNode = createRepairNode({ block, sourceUrl: url, detourUrl: detoured ? alternate : '', outcome: detoured && action.ok ? 'detoured' : 'detour-failed', issueId, deps });
305
+ recordRepairNode(repairNode, deps);
306
+ }
307
+ }
308
+ if (block && !repairNode) {
309
+ repairNode = createRepairNode({ block, sourceUrl: url, detourUrl: detoured ? actionUrl : '', outcome: detoured && action.ok ? 'detoured' : 'detour-failed', issueId, deps });
310
+ recordRepairNode(repairNode, deps);
311
+ }
312
+ if (!action.ok) return { ok: false, blocked, detoured, ...(repairNode ? { repairNode } : {}), reason: action.reason, output: `브라우저 작업이 안전 경계에서 중단되었습니다: ${action.reason}` };
313
+
314
+ let captureUrl: string | undefined;
315
+ let attachmentId: string | undefined;
316
+ const observedPath = (action.observed as unknown as { attachmentRef?: unknown } | undefined)?.attachmentRef;
317
+ const capturePath = capturedPath ?? (typeof observedPath === 'string' ? observedPath : undefined);
318
+ if (!capturePath || action.observed?.captureOutcome !== 'ok') {
319
+ return { ok: false, reason: 'capture-missing', output: '브라우저 동작은 끝났지만 캡처 증거가 없어 Linear 첨부 완료로 처리하지 않았습니다.' };
320
+ }
321
+ const apiKey = await (deps.getApiKey ?? getSecretAsync)('connector.linear.apiKey');
322
+ if (!apiKey?.trim()) return { ok: false, reason: 'linear-key-missing', output: '캡처는 생성했지만 Linear 키가 없어 서브태스크 첨부를 보류했습니다.' };
323
+ const bytes = await (deps.readCapture ?? (async path => readFile(path)))(capturePath);
324
+ captureUrl = await (deps.upload ?? uploadLinearFile)({ apiKey, filename: basename(capturePath), contentType: 'image/png', body: bytes });
325
+ attachmentId = await (deps.attach ?? createLinearAttachment)({ apiKey, issueId, title: '브라우저 캡처', url: captureUrl });
326
+
327
+ let selectionReflected = false;
328
+ if (args.includeThisToo === true) {
329
+ const text = args.selection?.text?.trim().slice(0, 3000) ?? '';
330
+ const tab = args.selection?.tab?.trim().slice(0, 500) ?? '';
331
+ if (!text && !tab) return { ok: false, reason: 'empty-selection', ...(captureUrl ? { captureUrl } : {}), ...(attachmentId ? { attachmentId } : {}), output: '선택 문장 또는 탭 정보가 없어 Linear 반영을 건너뛰었습니다.' };
332
+ try {
333
+ selectionReflected = deps.reflectSelection
334
+ ? await deps.reflectSelection({
335
+ issueId, body: `${SELECTION_COMMENT}: ${[tab, text].filter(Boolean).join(' — ')}`,
336
+ })
337
+ : await reflectSelectionWithLinearIssueTool({
338
+ issueId, body: `${SELECTION_COMMENT}: ${[tab, text].filter(Boolean).join(' — ')}`,
339
+ }, deps);
340
+ } catch {
341
+ return { ok: false, reason: 'linear-reflection-failed', ...(captureUrl ? { captureUrl } : {}), ...(attachmentId ? { attachmentId } : {}), output: '캡처는 첨부했지만 Linear 선택 반영에 실패했습니다.' };
342
+ }
343
+ if (!selectionReflected) return { ok: false, reason: 'linear-reflection-failed', ...(captureUrl ? { captureUrl } : {}), ...(attachmentId ? { attachmentId } : {}), output: '캡처는 첨부했지만 Linear 서브태스크 선택 반영이 실패했습니다.' };
344
+ }
345
+
346
+ return {
347
+ ok: true,
348
+ ...(captureUrl ? { captureUrl } : {}),
349
+ ...(attachmentId ? { attachmentId } : {}),
350
+ ...(args.includeThisToo === true ? { selectionReflected } : {}),
351
+ blocked,
352
+ detoured,
353
+ ...(repairNode ? { repairNode } : {}),
354
+ output: `브라우저 캡처를 Linear 서브태스크에 첨부했습니다${selectionReflected ? ' · 선택을 “이것도 반영”으로 기록했습니다' : ''}.`,
355
+ };
356
+ }
357
+
358
+ export const browserHandRuntime: ToolRuntime<BrowserHandArgs, BrowserHandResult> = {
359
+ id: 'browser_hand',
360
+ spec: {
361
+ name: 'BrowserHand',
362
+ description: '사람이 armed 승인한 브라우저 요소 하나를 기존 harness browser-act 안전 경로로 조작·캡처하고, 캡처와 명시적 “이것도 반영” 선택을 지정한 Linear 서브태스크에 기록합니다. 로그인·페이월이면 허용된 대체 출처로 한 번 우회하고 기존 그래프 갈래에 수리 노드를 기록합니다. 메일 발송은 없습니다.',
363
+ parameters: {
364
+ type: 'object',
365
+ properties: {
366
+ url: { type: 'string' }, target: { type: 'string', description: 'CSS selector of the element to click.' },
367
+ armed: { type: 'boolean', description: 'Must be true only after explicit human approval.' },
368
+ linearSubtaskId: { type: 'string', description: 'Linear issue UUID of the active subtask.' },
369
+ alternateUrl: { type: 'string', description: '로그인·페이월 시 1회만 이동할 대체 출처. persona actionHosts에 포함되어야 합니다.' },
370
+ persona: { type: 'string', description: '허용 호스트가 선언된 브라우저 페르소나 ID.' }, includeThisToo: { type: 'boolean' },
371
+ selection: { type: 'object', properties: { text: { type: 'string' }, tab: { type: 'string' } }, additionalProperties: false },
372
+ },
373
+ required: ['url', 'target', 'armed', 'linearSubtaskId', 'persona'], additionalProperties: false,
374
+ },
375
+ },
376
+ async run(args, ctx) {
377
+ const { result } = await coordinateBrowserRoundtrip({
378
+ url: args.url,
379
+ target: args.target,
380
+ armed: args.armed,
381
+ ...(args.persona ? { persona: args.persona } : {}),
382
+ ...(args.alternateUrl ? { alternateUrl: args.alternateUrl } : {}),
383
+ humanSelection: {
384
+ linearSubtaskId: args.linearSubtaskId,
385
+ ...(args.selection ? { selection: args.selection } : {}),
386
+ },
387
+ ...(args.includeThisToo === undefined ? {} : { includeThisToo: args.includeThisToo }),
388
+ }, {}, dispatchBrowserHand, ctx);
389
+ return result;
390
+ },
391
+ };
@@ -34,6 +34,7 @@ import { decideTypeAction } from '../harness/browser-act-type.js';
34
34
  import { requestConfirmation } from '../hitl/confirm.js';
35
35
  import type { TypeTarget } from '../harness/bot-type-request.js';
36
36
  import type { ToolRuntime, ToolRuntimeContext } from './types.js';
37
+ import { browserHandRuntime } from './browser-hand-runtime.js';
37
38
 
38
39
  // ─── Dependency injection ───────────────────────────────────────
39
40
 
@@ -49,9 +50,9 @@ export interface BrowserRuntimeDeps {
49
50
  observe?: BrowserActionObserver;
50
51
  }
51
52
 
52
- function observeBrowserAction(data: Record<string, unknown>): void {
53
+ function observeBrowserAction(data: Record<string, unknown>, explicitRunId?: string): void {
53
54
  try {
54
- const runId = getHarnessRunId() || null;
55
+ const runId = explicitRunId || getHarnessRunId() || null;
55
56
  (deps.observe ?? ((event, detail) => debug.log('harness.browser-action', event, detail)))('executed', {
56
57
  runId,
57
58
  sessionId: 'browser-runtime',
@@ -94,17 +95,20 @@ async function defaultCloseClient(): Promise<void> {
94
95
  singletonPromise = null;
95
96
  }
96
97
 
97
- let deps: BrowserRuntimeDeps = {
98
+ const DEFAULT_DEPS: BrowserRuntimeDeps = {
98
99
  getClient: defaultGetClient,
99
100
  closeClient: defaultCloseClient,
100
101
  };
102
+ let deps: BrowserRuntimeDeps = DEFAULT_DEPS;
101
103
  let attachedControlSignalBus: ReturnType<typeof defaultControlSignalBus> | null = null;
104
+ let detachBrowserControlSignalConsumer: (() => void) | null = null;
102
105
 
103
106
  function ensureBrowserControlSignalConsumer(): void {
104
107
  const bus = defaultControlSignalBus();
105
108
  if (attachedControlSignalBus === bus) return;
109
+ detachBrowserControlSignalConsumer?.();
106
110
  attachedControlSignalBus = bus;
107
- bus.subscribe(
111
+ detachBrowserControlSignalConsumer = bus.subscribe(
108
112
  { kind: 'browser-cdp-stop', minUrgency: 'quick-pass', surface: 'browser' },
109
113
  () => {
110
114
  void deps.closeClient?.();
@@ -116,6 +120,14 @@ export function setBrowserRuntimeDeps(next: Partial<BrowserRuntimeDeps>): void {
116
120
  deps = { ...deps, ...next };
117
121
  }
118
122
 
123
+ /** Reset dependency injection after a run-scoped observability test. */
124
+ export function _resetBrowserRuntimeDepsForTest(): void {
125
+ detachBrowserControlSignalConsumer?.();
126
+ detachBrowserControlSignalConsumer = null;
127
+ deps = DEFAULT_DEPS;
128
+ attachedControlSignalBus = null;
129
+ }
130
+
119
131
  export async function closeBrowserRuntime(): Promise<void> {
120
132
  if (deps.closeClient) await deps.closeClient();
121
133
  }
@@ -188,6 +200,7 @@ const MAX_NAV_TIMEOUT_MS = 60_000;
188
200
 
189
201
  export async function dispatchBrowserNavigate(args: BrowserNavigateArgs, ctx?: ToolRuntimeContext): Promise<BrowserNavigateResult> {
190
202
  ensureBrowserControlSignalConsumer();
203
+ const runId = ctx?.runId || getHarnessRunId() || undefined;
191
204
  const url = String(args.url ?? '').trim();
192
205
  const input = args.input;
193
206
  // Input is never an implicit side effect of navigation. Approval is scoped
@@ -214,7 +227,7 @@ export async function dispatchBrowserNavigate(args: BrowserNavigateArgs, ctx?: T
214
227
  if (!approved) return { output: '# BrowserNavigate: input not approved', finalUrl: '', title: '', loadMs: 0 };
215
228
  }
216
229
  if (!url) {
217
- observeBrowserAction({ action: 'navigate', url: '', target: 'url', ok: false, error: 'url is required' });
230
+ observeBrowserAction({ action: 'navigate', url: '', target: 'url', ok: false, error: 'url is required' }, runId);
218
231
  return { output: '# BrowserNavigate: error\nurl is required', finalUrl: '', title: '', loadMs: 0 };
219
232
  }
220
233
  const waitForLoad = args.waitForLoad !== false;
@@ -225,12 +238,12 @@ export async function dispatchBrowserNavigate(args: BrowserNavigateArgs, ctx?: T
225
238
  client = await deps.getClient();
226
239
  } catch (err) {
227
240
  const error = err instanceof Error ? err.message : String(err);
228
- observeBrowserAction({ action: 'navigate', url, target: url, ok: false, error });
241
+ observeBrowserAction({ action: 'navigate', url, target: url, ok: false, error }, runId);
229
242
  throw err;
230
243
  }
231
244
  if (!client) {
232
245
  const availability = getBrowserCdpAvailability();
233
- observeBrowserAction({ action: 'navigate', url, target: url, ok: false, error: 'chrome-unavailable' });
246
+ observeBrowserAction({ action: 'navigate', url, target: url, ok: false, error: 'chrome-unavailable' }, runId);
234
247
  return {
235
248
  output: `# BrowserNavigate: Chrome unavailable\n${availability.note}`,
236
249
  finalUrl: '',
@@ -263,7 +276,7 @@ export async function dispatchBrowserNavigate(args: BrowserNavigateArgs, ctx?: T
263
276
  await client.navigate(url);
264
277
  } catch (err) {
265
278
  const error = err instanceof Error ? err.message : String(err);
266
- observeBrowserAction({ action: 'navigate', url, target: url, ok: false, error, loadMs: Date.now() - started });
279
+ observeBrowserAction({ action: 'navigate', url, target: url, ok: false, error, loadMs: Date.now() - started }, runId);
267
280
  return {
268
281
  output: `# BrowserNavigate: error\n${error}`,
269
282
  finalUrl: url,
@@ -332,7 +345,7 @@ export async function dispatchBrowserNavigate(args: BrowserNavigateArgs, ctx?: T
332
345
  timedOut ? 'warning: load event timed out' : '',
333
346
  ].filter(Boolean).join('\n');
334
347
 
335
- observeBrowserAction({ action: 'navigate', url: finalUrl, target: url, ok: true, titleLength: title.length, loadMs, timedOut });
348
+ observeBrowserAction({ action: 'navigate', url: finalUrl, target: url, ok: true, titleLength: title.length, loadMs, timedOut }, runId);
336
349
  return { output, finalUrl, title, loadMs, timedOut: timedOut || undefined };
337
350
  }
338
351
 
@@ -404,8 +417,9 @@ function escapeForJs(s: string): string {
404
417
  return s.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
405
418
  }
406
419
 
407
- export async function dispatchBrowserRead(args: BrowserReadArgs): Promise<BrowserReadResult> {
420
+ export async function dispatchBrowserRead(args: BrowserReadArgs, ctx?: ToolRuntimeContext): Promise<BrowserReadResult> {
408
421
  ensureBrowserControlSignalConsumer();
422
+ const runId = ctx?.runId || getHarnessRunId() || undefined;
409
423
  const mode: BrowserReadMode = args.mode ?? 'text';
410
424
  const selector = typeof args.selector === 'string' ? args.selector.trim() : '';
411
425
  const maxChars = Math.min(
@@ -418,12 +432,12 @@ export async function dispatchBrowserRead(args: BrowserReadArgs): Promise<Browse
418
432
  client = await deps.getClient();
419
433
  } catch (err) {
420
434
  const error = err instanceof Error ? err.message : String(err);
421
- observeBrowserAction({ action: 'read', target: selector || 'document.body', mode, ok: false, error, attachmentRef: null, captureOutcome: mode === 'screenshot' ? 'error' : 'not-requested' });
435
+ observeBrowserAction({ action: 'read', target: selector || 'document.body', mode, ok: false, error, attachmentRef: null, captureOutcome: mode === 'screenshot' ? 'error' : 'not-requested' }, runId);
422
436
  throw err;
423
437
  }
424
438
  if (!client) {
425
439
  const availability = getBrowserCdpAvailability();
426
- observeBrowserAction({ action: 'read', target: selector || 'document.body', mode, ok: false, error: 'chrome-unavailable', attachmentRef: null, captureOutcome: mode === 'screenshot' ? 'unavailable' : 'not-requested' });
440
+ observeBrowserAction({ action: 'read', target: selector || 'document.body', mode, ok: false, error: 'chrome-unavailable', attachmentRef: null, captureOutcome: mode === 'screenshot' ? 'unavailable' : 'not-requested' }, runId);
427
441
  return {
428
442
  output: `# BrowserRead: Chrome unavailable\n${availability.note}`,
429
443
  mode,
@@ -434,7 +448,7 @@ export async function dispatchBrowserRead(args: BrowserReadArgs): Promise<Browse
434
448
  try {
435
449
  const png = await client.screenshot({ format: 'png' });
436
450
  const b64 = png.toString('base64');
437
- observeBrowserAction({ action: 'read', target: 'screenshot', mode, ok: true, bytes: png.byteLength, base64Length: b64.length, attachmentRef: null, captureOutcome: 'inline-base64' });
451
+ observeBrowserAction({ action: 'read', target: 'screenshot', mode, ok: true, bytes: png.byteLength, base64Length: b64.length, attachmentRef: null, captureOutcome: 'inline-base64' }, runId);
438
452
  return {
439
453
  output: `# BrowserRead: screenshot (${png.byteLength} bytes PNG, ${b64.length} chars base64)`,
440
454
  mode,
@@ -442,7 +456,7 @@ export async function dispatchBrowserRead(args: BrowserReadArgs): Promise<Browse
442
456
  };
443
457
  } catch (err) {
444
458
  const error = err instanceof Error ? err.message : String(err);
445
- observeBrowserAction({ action: 'read', target: 'screenshot', mode, ok: false, error, attachmentRef: null, captureOutcome: 'error' });
459
+ observeBrowserAction({ action: 'read', target: 'screenshot', mode, ok: false, error, attachmentRef: null, captureOutcome: 'error' }, runId);
446
460
  return {
447
461
  output: `# BrowserRead: screenshot error\n${error}`,
448
462
  mode,
@@ -461,7 +475,7 @@ export async function dispatchBrowserRead(args: BrowserReadArgs): Promise<Browse
461
475
  value = v == null ? '' : String(v);
462
476
  } catch (err) {
463
477
  const error = err instanceof Error ? err.message : String(err);
464
- observeBrowserAction({ action: 'read', target: selector || 'document.body', mode, ok: false, error, attachmentRef: null, captureOutcome: 'not-requested' });
478
+ observeBrowserAction({ action: 'read', target: selector || 'document.body', mode, ok: false, error, attachmentRef: null, captureOutcome: 'not-requested' }, runId);
465
479
  return {
466
480
  output: `# BrowserRead: evaluate error\n${error}`,
467
481
  mode,
@@ -471,7 +485,7 @@ export async function dispatchBrowserRead(args: BrowserReadArgs): Promise<Browse
471
485
  const truncated = value.length > maxChars;
472
486
  const out = truncated ? value.slice(0, maxChars) : value;
473
487
 
474
- observeBrowserAction({ action: 'read', target: selector || 'document.body', mode, ok: true, charLength: value.length, returnedChars: out.length, truncated, attachmentRef: null, captureOutcome: 'not-requested' });
488
+ observeBrowserAction({ action: 'read', target: selector || 'document.body', mode, ok: true, charLength: value.length, returnedChars: out.length, truncated, attachmentRef: null, captureOutcome: 'not-requested' }, runId);
475
489
  return {
476
490
  output: [
477
491
  `# BrowserRead (${mode}${selector ? ` · selector=${selector}` : ''})`,
@@ -489,11 +503,11 @@ export async function dispatchBrowserRead(args: BrowserReadArgs): Promise<Browse
489
503
  export const browserReadRuntime: ToolRuntime<BrowserReadArgs, BrowserReadResult> = {
490
504
  id: 'browser_read',
491
505
  spec: buildBrowserReadTool(),
492
- async run(req, _ctx: ToolRuntimeContext) {
493
- return dispatchBrowserRead(req);
506
+ async run(req, ctx: ToolRuntimeContext) {
507
+ return dispatchBrowserRead(req, ctx);
494
508
  },
495
509
  };
496
510
 
497
511
  // ─── Barrel ─────────────────────────────────────────────────────
498
512
 
499
- export const ALL_BROWSER_RUNTIMES = [browserNavigateRuntime, browserReadRuntime];
513
+ export const ALL_BROWSER_RUNTIMES = [browserNavigateRuntime, browserReadRuntime, browserHandRuntime];
@@ -0,0 +1,76 @@
1
+ import { debug } from '../debug/log.js';
2
+ import { commentLinearIssue, createLinearTeamIssue, moveLinearIssueToStateType } from '../connectors/linear.js';
3
+ import { getSecretAsync } from '../nexus/config/secrets/index.js';
4
+ import type { LLMToolSpec } from '../llm.js';
5
+ import type { ToolRuntime, ToolRuntimeContext } from './types.js';
6
+
7
+ export type ElanousLinearIssueArgs =
8
+ | { action: 'create'; teamKey: string; title: string; description?: string }
9
+ | { action: 'comment'; issueId: string; body: string }
10
+ | { action: 'complete'; issueId: string };
11
+ export interface ElanousLinearIssueResult extends Record<string, unknown> { ok: boolean; output: string }
12
+
13
+ type Deps = {
14
+ getApiKey?: (id: string) => Promise<string | undefined>;
15
+ create?: typeof createLinearTeamIssue;
16
+ comment?: typeof commentLinearIssue;
17
+ complete?: typeof moveLinearIssueToStateType;
18
+ fetch?: typeof fetch;
19
+ };
20
+
21
+ export function createElanousLinearIssueRuntime(deps: Deps = {}): ToolRuntime<ElanousLinearIssueArgs, ElanousLinearIssueResult> {
22
+ return {
23
+ id: 'elanous_linear_issue',
24
+ surfaces: ['tui', 'mcp'],
25
+ spec: {
26
+ name: 'elanous_linear_issue',
27
+ description: 'Perform one explicitly requested Linear issue action: create directly in a team without a project, add a comment, or mark an issue complete. Requires connector.linear.apiKey. Never use for an action the user did not request.',
28
+ parameters: {
29
+ type: 'object',
30
+ properties: {
31
+ action: { type: 'string', enum: ['create', 'comment', 'complete'] },
32
+ teamKey: { type: 'string', description: 'Required only for create; Linear team key, such as DEMO.' },
33
+ title: { type: 'string', description: 'Required only for create.' },
34
+ description: { type: 'string', description: 'Optional create description.' },
35
+ issueId: { type: 'string', description: 'Required for comment and complete.' },
36
+ body: { type: 'string', description: 'Required only for comment.' },
37
+ },
38
+ required: ['action'],
39
+ additionalProperties: false,
40
+ },
41
+ } satisfies LLMToolSpec,
42
+ async run(args: ElanousLinearIssueArgs, _ctx: ToolRuntimeContext): Promise<ElanousLinearIssueResult> {
43
+ const apiKey = await (deps.getApiKey ?? getSecretAsync)('connector.linear.apiKey');
44
+ if (!apiKey?.trim()) return { ok: false, output: 'Linear API key is missing; run elanous connector linear set-key' };
45
+ const fetch = deps.fetch ?? globalThis.fetch;
46
+ try {
47
+ if (args?.action === 'create') {
48
+ const teamKey = typeof args.teamKey === 'string' ? args.teamKey.trim() : '';
49
+ const title = typeof args.title === 'string' ? args.title.trim() : '';
50
+ if (!teamKey || !title) return { ok: false, output: 'Linear issue 생성에는 teamKey와 title이 필요합니다.' };
51
+ const issueId = await (deps.create ?? createLinearTeamIssue)({ apiKey, teamKey, title,
52
+ ...(typeof args.description === 'string' ? { description: args.description } : {}), fetch });
53
+ return { ok: true, output: `Linear 이슈를 생성했습니다: ${issueId}`, issueId };
54
+ }
55
+ const issueId = typeof args?.issueId === 'string' ? args.issueId.trim() : '';
56
+ if (!issueId) return { ok: false, output: 'Linear issueId가 필요합니다.' };
57
+ if (args.action === 'comment') {
58
+ const body = typeof args.body === 'string' ? args.body.trim() : '';
59
+ if (!body) return { ok: false, output: 'Linear 댓글 내용이 필요합니다.' };
60
+ await (deps.comment ?? commentLinearIssue)({ apiKey, issueId, body, fetch });
61
+ return { ok: true, output: `Linear 이슈에 댓글을 추가했습니다: ${issueId}`, issueId };
62
+ }
63
+ if (args.action === 'complete') {
64
+ await (deps.complete ?? moveLinearIssueToStateType)({ apiKey, issueId, type: 'completed', fetch });
65
+ return { ok: true, output: `Linear 이슈를 완료 상태로 바꿨습니다: ${issueId}`, issueId };
66
+ }
67
+ return { ok: false, output: '지원하지 않는 Linear 작업입니다.' };
68
+ } catch {
69
+ debug.log('tool.linear-issue', 'failed', { action: args?.action ?? 'unknown' });
70
+ return { ok: false, output: 'Linear 작업에 실패했습니다. 팀 키, 이슈 ID, 권한을 확인해 주세요.' };
71
+ }
72
+ },
73
+ };
74
+ }
75
+
76
+ export const elanousLinearIssueRuntime = createElanousLinearIssueRuntime();