elanous 0.2.41 → 0.2.43

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 (796) 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/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{2fe2c302.41b517f88d6fe502.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{385e4574.e9886ab32759eda3.js → 0ad6802e.ae7afb63fdcb4491.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/114.2b90424d1a3ce84c.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1151-5c2bb8f002ca2dd6.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1200.6a37c202f9f17e9a.js +226 -0
  9. package/apps/pwa/out/_next/static/chunks/1261-a616d5728e02e624.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1313-19f737e0222c4444.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1357.3bbef3976c37f94a.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1362-20adddfaf662b0fa.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/{6874.d5cf7eb8edb2cabe.js → 1406.a1dc2ab6f8449374.js} +2 -2
  14. package/apps/pwa/out/_next/static/chunks/1737-9491fc6ab29b9ec6.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1803-4f91a8e7dcaf042c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{5744.b9415e18ad623100.js → 1961.a81b12872c3e93a9.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/1970cf59.2d4d8ce5d6c81853.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/2073-ba274e00e4f9efb4.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/{5471.1e611302ed3a7c53.js → 2144.25b292396712196d.js} +2 -2
  21. package/apps/pwa/out/_next/static/chunks/{3230-49298c3b73ef2268.js → 2268-53861f339e0b65a2.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/{9834.63ab2bbc3153172e.js → 2312.0c8b61e22d3136d7.js} +1 -1
  23. package/apps/pwa/out/_next/static/chunks/{1800.f7ff51dc4978a958.js → 2573.387a707f6f9d720c.js} +2 -2
  24. package/apps/pwa/out/_next/static/chunks/273.f156eee28f11af77.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2873.d2140e5a82546401.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/{9048.212083de42d25be3.js → 3072.01338851ca21a6f7.js} +2 -2
  27. package/apps/pwa/out/_next/static/chunks/3091.a5a4143dea33d197.js +90 -0
  28. package/apps/pwa/out/_next/static/chunks/3095.dc44586a5f83b86d.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{2263.e09b6edea33bad2d.js → 3113.d7472bbc27d580c7.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/3228-9650b6447b6fa288.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/3402.44b565b314f2263c.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{addc2b32.8c4ff8f0aefe987d.js → 3557ac4a.c8931684475018ad.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/360.ae9f9f4c33c395e8.js +79 -0
  34. package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
  35. package/apps/pwa/out/_next/static/chunks/{a0a01613.6d1cca322238d7fe.js → 363bfab3.9623b9f89363541f.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/3694.e0099884345f0198.js +64 -0
  37. package/apps/pwa/out/_next/static/chunks/3744.54f87db52acfd1ab.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3903.3ef4656c67572764.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3935.16701e33f8982dc9.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3955.6922286237f2ac2b.js +24 -0
  41. package/apps/pwa/out/_next/static/chunks/3969.272ee7f9fd6c62e5.js +34 -0
  42. package/apps/pwa/out/_next/static/chunks/4199.ce86b281fd0a60b7.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4311-6dd3144002cc0c2d.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4426-2b230fad00c88930.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{530.d26346e18089640a.js → 4445.7990c76b3751a918.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4447-14c5161fa59166c7.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4856-b0b8075bba8c53f4.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4870-de370d65e73c0bb5.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4885-2c989165c4b29fad.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4894.fec2ca9e99caefa2.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/5093.8f04b7f8cb899a95.js +94 -0
  52. package/apps/pwa/out/_next/static/chunks/5122-2bb177cebf89e19a.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/5154.5f56dc3902e3d275.js +36 -0
  54. package/apps/pwa/out/_next/static/chunks/529.64ff7257180b2ac9.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5394.5dabeb0c62293a28.js +93 -0
  56. package/apps/pwa/out/_next/static/chunks/5461.08bf2404ff38ec85.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5474-22e08a85583209b2.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{1219.7e17964e0e7cd8e5.js → 5564.9e72532188f57586.js} +3 -3
  59. package/apps/pwa/out/_next/static/chunks/5567-265df39ed8fe9dcb.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5570-a94ae19811cb2046.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5574-b47c9ef2dceff1fd.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5628.6ddb2d5ffba4ff4c.js +309 -0
  63. package/apps/pwa/out/_next/static/chunks/5730.43d7ccc09988e646.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{1178.1aa9cad0e7695427.js → 5789.2da35c258292e1e5.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/{4133.2056bb4d78f621af.js → 5824.da9527b15a3221e5.js} +1 -1
  66. package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/{4527.a69f2894d1bc9f4a.js → 5930.8b4df3b46c32b05a.js} +1 -1
  68. package/apps/pwa/out/_next/static/chunks/5963-c4d8469c52a0828b.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/6001.ec4049ceb3c43418.js +27 -0
  70. package/apps/pwa/out/_next/static/chunks/6120-471f03db1e299c0c.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6175-41479e643aca1878.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6291.a2de4f9787637075.js +104 -0
  73. package/apps/pwa/out/_next/static/chunks/6400-6699907c3537436a.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/6428.1f4327d6ae5fdf9a.js +287 -0
  75. package/apps/pwa/out/_next/static/chunks/644.02cb026fa44bcd0a.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6466-6c87d60d3dd174fb.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{9507.7026657a2f47eb64.js → 6540.c7bef57ad8f90a87.js} +16 -16
  78. package/apps/pwa/out/_next/static/chunks/6773.d4264665ab31bec0.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6822.3c789f1a8443e774.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/{5574.f35accf4f132b29d.js → 6944.309f4e3ea54d1537.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/7261-8ff69d3b2ee671fd.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7266.084c6bbc70035140.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7271.5c0100e7320aa856.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7429-bf5731358c8f2f68.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7464.01f7a0ae1215fbe7.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7479.0fcad5f37eb64f0c.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7483.427a2fe2049e388d.js +148 -0
  88. package/apps/pwa/out/_next/static/chunks/7502-be74718178e13e56.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7530.0889722b19572065.js +24 -0
  90. package/apps/pwa/out/_next/static/chunks/7645.5b2ee3ad45c55ea3.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7788.7d1c79f1a8e18946.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7900.096f455c7c1efc53.js +77 -0
  93. package/apps/pwa/out/_next/static/chunks/7910-6f139bcafd238b9f.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7966.f71c8958d1637548.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{5947-135e26537d80a6b9.js → 8062-7cd0bcc7f01455ba.js} +3 -3
  96. package/apps/pwa/out/_next/static/chunks/8073.f6cf2f2c71aafbd0.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8201.190b94088980f430.js +74 -0
  98. package/apps/pwa/out/_next/static/chunks/8205.282ca4bb62d54a0a.js +62 -0
  99. package/apps/pwa/out/_next/static/chunks/8313-dfa1021bb58a46d6.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/837-81336ebaca8198a8.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8447.7963352ef5f71b76.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8574-868e8129525ef6d9.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8588.d1c6a2903727ce87.js +149 -0
  104. package/apps/pwa/out/_next/static/chunks/8637.90f92d5c8db4732c.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{2743.5d3f76948be32b34.js → 868.6e953be05bcf6dca.js} +2 -2
  106. package/apps/pwa/out/_next/static/chunks/8706-e1fe0309343a2273.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8749-06384cdfc4520add.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{5964-7e21164a8f2cf0ce.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/8967-7dfebf710c9dec9d.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{5159.115f1c2ca471386c.js → 8986.8e2e4efbfa655c59.js} +1 -1
  111. package/apps/pwa/out/_next/static/chunks/8997-3c564dbb3b58b055.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/923.2034d10ae91e9c20.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/943.39ae5e82f4f1893f.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9469.0500480de55fb205.js +32 -0
  116. package/apps/pwa/out/_next/static/chunks/9770.5f75bc6088b16109.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9810-2543267050e58b82.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9870.8419702475254745.js +8 -0
  119. package/apps/pwa/out/_next/static/chunks/9941-376d1b74d51b01a4.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9958.385434ab04241758.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{b2271e54.c1de3347976e90b0.js → aa57532f.510551854ff239b1.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-deea1450b17cb8dc.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-70985b904f8650ef.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a2e15e33e56a4353.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-fc72ce2db12d6ca9.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-be03e41f9436ebd9.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-35a35999382da3f2.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-3ff5b1e6ca88b848.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-a65101300a0ee5c1.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-3aca5b6d67dba511.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-45b8ab0a71e61314.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-53046e282d4cda8e.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-17809e60e8354c17.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-fd2442d347bf5898.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-e9d720d6fc082e21.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-6b8b4267bab0a677.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-deea1450b17cb8dc.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-8bcf6233ac7c17af.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-7cc25591cfc2126f.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-053e871f35c9beba.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-eff819f0c2d5e084.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-4d7e9d8db5274a87.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-2b2d8f5aa5f69ad4.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-0b8f92c5062e68b1.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1bd9d0fdac2ced3d.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-9ee28f7df07428ea.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-44b7a1ff468c6648.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-cbc6523711dc1b65.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-fdad47899c2695be.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-40f9e19149024298.js → page-79a8b5fee4c20871.js} +1 -1
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-03e8ac9606aeaffb.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-4cd55c55ec287e2f.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-db17b4305404161e.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-30041d848350fd02.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c540da022dbf86b0.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9399efc538da057f.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-a142dfb0331a05f5.js → page-ca2d09128c585ca4.js} +1 -1
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-0e2635aecd343038.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ef7f4399b6b7726e.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-deea1450b17cb8dc.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-caf530535b875468.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-eaa20c1543a5fd8e.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c541eb1b75120f61.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-ab5e213eda9479f4.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-0a815f34367b6db6.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-e858ba0ed9393b68.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-1638ee9dd6e0582f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-4cf5a399109391f2.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b4396321238798ec.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-cb72bfd21006781a.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6135d0242afbc434.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a1dccf907eddb856.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{53aeb4ee-51c92f8d683f5220.js → c7945435-b44d4dbe90ba0dcb.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/{2fdf2931.b431eee4fb468bc3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/{c0c1a699.0ba79f97005965d4.js → d96660fb.cbc21a2a88539dbb.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/ea514caa.05a24f78d9dffe5f.js +122 -0
  177. package/apps/pwa/out/_next/static/chunks/{83184dcd-0ee6247ff41eb3f2.js → fb7d20d5-6892502b6ee39ca6.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-e8a911e19b1be41f.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-7022f418fabba021.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-e5f15df755756a1e.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-4525f91e36940c9b.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-140f0e519c085b0f.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-8f22ef63dcb865b1.js +1 -0
  184. package/apps/pwa/out/_next/static/css/{b9d8151e48998417.css → 62c858ad53854f47.css} +1 -1
  185. package/apps/pwa/out/_next/static/css/d1f8bb401740a549.css +1 -0
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +23 -23
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +23 -23
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +23 -23
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +22 -22
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +22 -22
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +23 -23
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +22 -22
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +23 -23
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +23 -23
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +22 -22
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +23 -23
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +24 -25
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +23 -23
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +23 -23
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +22 -22
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +23 -23
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +23 -23
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +24 -25
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +24 -25
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +22 -22
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +22 -22
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +23 -23
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +23 -23
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +22 -22
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +22 -22
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +22 -22
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +23 -23
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +23 -23
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +22 -22
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +23 -23
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +23 -23
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +23 -23
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +23 -23
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +23 -23
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +22 -22
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +23 -23
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +23 -23
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +23 -23
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +23 -23
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +23 -23
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +23 -23
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +23 -23
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +23 -23
  279. package/catalog/external-commands.yaml +5 -3
  280. package/catalog/meta/catalogVersion.yaml +2 -1
  281. package/catalog/signing/catalog-signing-public.pem +3 -0
  282. package/docs/goal-context/04-mock-scenarios.md +13 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/heal/heal-loop.yaml +1 -0
  285. package/graphs/intake/intake-daily.yaml +16 -0
  286. package/graphs/intake/news-sources.yaml +1 -0
  287. package/graphs/intake/recipes.yaml +7 -0
  288. package/graphs/overlays/examples/research-runtime-empty-terminal.yaml +28 -0
  289. package/graphs/overlays/stop-heal-ladder.yaml +113 -0
  290. package/graphs/profiles/local.yaml +5 -0
  291. package/graphs/profiles/pod.yaml +4 -0
  292. package/graphs/units/verbs/recipes.yaml +11 -11
  293. package/graphs/work/research-report.yaml +10 -2
  294. package/package.json +6 -2
  295. package/plugins/demo-absorption-briefing/plugin.json +18 -0
  296. package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
  297. package/plugins/demo-browser-hand/plugin.json +13 -0
  298. package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
  299. package/plugins/demo-linear-secretary/plugin.json +15 -0
  300. package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
  301. package/plugins/demo-plugin-wizard/plugin.json +11 -0
  302. package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
  303. package/plugins/demo-research/plugin.json +16 -0
  304. package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
  305. package/plugins/demo-video-briefing/plugin.json +15 -0
  306. package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
  307. package/scripts/build-signed-catalog.ts +48 -0
  308. package/scripts/ci-typecheck-main-delta.sh +88 -0
  309. package/scripts/codex-fallback-live-probe.ts +1 -1
  310. package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
  311. package/scripts/demo/demo1104-stage.config.ts +21 -0
  312. package/scripts/demo/demo1104-stage.ts +316 -0
  313. package/scripts/goal-method-audit.ts +17 -1
  314. package/scripts/graph-units/land-enqueue.ts +90 -0
  315. package/scripts/heal/run-role.ts +99 -5
  316. package/scripts/hooks/codex-notify.sh +32 -0
  317. package/scripts/install.sh +10 -38
  318. package/scripts/land-global-checks.ts +6 -1
  319. package/scripts/landing-heal/land-plan.ts +57 -0
  320. package/scripts/lib/decompose-ab.ts +1 -0
  321. package/scripts/lib/fixtures/tui-regress/help-insufficient-commands.txt +15 -0
  322. package/scripts/lib/fixtures/tui-regress/help-live.txt +42 -0
  323. package/scripts/lib/fixtures/tui-regress/help-missing-keys.txt +21 -0
  324. package/scripts/lib/fixtures/tui-regress/help-original.txt +51 -0
  325. package/scripts/lib/fixtures/tui-regress/help-shifted-input.txt +26 -0
  326. package/scripts/lib/tui-regress-checks.ts +33 -13
  327. package/scripts/release-loop/auto-approve-node.ts +1 -1
  328. package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
  329. package/scripts/release-loop/gate-baseline-receipt.ts +47 -9
  330. package/scripts/release-loop/gate-image-pin.ts +81 -0
  331. package/scripts/release-loop/gate-method.ts +139 -0
  332. package/scripts/release-loop/gate-node-sim.ts +207 -0
  333. package/scripts/release-loop/gate-node.ts +463 -64
  334. package/scripts/release-loop/gate-pod-image-sticky-plan.ts +99 -0
  335. package/scripts/release-loop/gate-radius-live.ts +97 -13
  336. package/scripts/release-loop/gate-shard-dispatch.ts +43 -0
  337. package/scripts/release-loop/gate-traffic-mode.ts +151 -3
  338. package/scripts/release-loop/gate-train-receipts.ts +122 -0
  339. package/scripts/release-loop/node-verdict.ts +38 -25
  340. package/scripts/release-loop/preflight.ts +362 -8
  341. package/scripts/release-loop/resume-release.ts +83 -8
  342. package/scripts/release-loop/unattended-release.ts +20 -9
  343. package/scripts/rhythm/daily.ts +36 -4
  344. package/scripts/rhythm/linear-progress-sync.ts +298 -0
  345. package/scripts/ux-sim.ts +18 -1
  346. package/scripts/video-pipeline.ts +9 -1
  347. package/scripts/warm-pool-provider-config.ts +286 -0
  348. package/skills/omni-crawl/SKILL.md +5 -2
  349. package/skills/omni-crawl/scripts/main.ts +84 -23
  350. package/src/acp/agent-manager.ts +1 -0
  351. package/src/acp/codex-app-server-agent.ts +33 -0
  352. package/src/acp/codex-app-server-client.ts +153 -16
  353. package/src/acp/core-turn-bridge.ts +27 -9
  354. package/src/acp/event-router.ts +20 -1
  355. package/src/acp/server.ts +6 -0
  356. package/src/agent/registry.ts +2 -0
  357. package/src/agent/task-notification.ts +25 -5
  358. package/src/agent/types.ts +6 -0
  359. package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
  360. package/src/agent-mission/claude-headless.ts +4 -1
  361. package/src/agent-mission/codex-exec.ts +105 -0
  362. package/src/agent-mission/driver.ts +192 -11
  363. package/src/agent-mission/grok-auth-status.ts +47 -0
  364. package/src/agent-mission/hand-hooks.ts +101 -0
  365. package/src/agent-mission/mission-cli.ts +63 -4
  366. package/src/agent-mission/mission-hand-reply.ts +118 -0
  367. package/src/agent-mission/mission-line.ts +180 -0
  368. package/src/agent-mission/mission-out.ts +833 -0
  369. package/src/agent-mission/tool-install.ts +200 -3
  370. package/src/agent-substrate/context-strategy.ts +4 -4
  371. package/src/agent-substrate/self-review-cli.ts +178 -13
  372. package/src/agents/general-purpose.md +1 -1
  373. package/src/auto-research/research-turn.ts +211 -53
  374. package/src/autopilot/pr-manager.ts +69 -10
  375. package/src/autopilot/pty-control-loop.ts +2 -0
  376. package/src/boot/daemon-tools/self-implement.ts +3 -1
  377. package/src/boot/daemon-tools/web-search.ts +1 -2
  378. package/src/briefing/brief-items.ts +55 -11
  379. package/src/capture/tui-self-report.ts +22 -6
  380. package/src/chat/index.ts +1 -1
  381. package/src/cli/agent-cli.ts +2 -1
  382. package/src/cli/catalog-cli.ts +31 -0
  383. package/src/cli/connector-cli.ts +16 -0
  384. package/src/cli/doctor-fix.ts +2 -2
  385. package/src/cli/fixtures/review-loop-breaker/opwaiver-32646-1694ccc7a170.json +1 -0
  386. package/src/cli/fixtures/review-loop-breaker/opwaiver-32853-bd8f73595c83.json +1 -0
  387. package/src/cli/fixtures/review-loop-breaker/opwaiver-33097-1cc85900413c.json +1 -0
  388. package/src/cli/fixtures/review-loop-breaker/opwaiver-33106-972f31e4a3ca.json +1 -0
  389. package/src/cli/fixtures/review-loop-breaker/opwaiver-33113-3ab51f05968f.json +1 -0
  390. package/src/cli/fixtures/review-loop-breaker/pr-33097-1cc85900413c.json +1 -0
  391. package/src/cli/intake-source-cli.ts +44 -8
  392. package/src/cli/msg-cli.ts +32 -3
  393. package/src/cli/pr-cli.ts +21 -1
  394. package/src/cli/pr-land-heavy-remote.ts +75 -5
  395. package/src/cli/pr-land-overlap-evidence.ts +113 -2
  396. package/src/cli/pr-land-pod-shadow-job.ts +202 -4
  397. package/src/cli/pr-land-pod-shadow.ts +9 -2
  398. package/src/cli/release-checklist-read-cli.ts +57 -19
  399. package/src/cli/release-cli.ts +23 -3
  400. package/src/cli/research-cli.ts +13 -5
  401. package/src/cli/setup-cli.ts +166 -6
  402. package/src/cli/setup-keys.ts +187 -0
  403. package/src/cli/task-plugin-wizard-host.ts +114 -0
  404. package/src/cli/tasks-cli.ts +61 -9
  405. package/src/cli/tui-test-cli.ts +186 -0
  406. package/src/compact/auto.ts +8 -1
  407. package/src/config.ts +4 -2
  408. package/src/connectors/linear-daily-progress.ts +228 -0
  409. package/src/connectors/linear-projector.ts +34 -12
  410. package/src/connectors/linear.ts +151 -7
  411. package/src/control-plane/ledger.ts +52 -2
  412. package/src/control-plane/server.ts +16 -2
  413. package/src/core-turn/deep-turn-bloom.ts +67 -0
  414. package/src/core-turn/research-policy.ts +37 -0
  415. package/src/core-turn/run-core-turn.ts +606 -95
  416. package/src/core-turn/run-goal-loop.ts +18 -0
  417. package/src/core-turn/types.ts +4 -0
  418. package/src/dashboard/chat/acp-chat.ts +10 -0
  419. package/src/dashboard/classic-sidetab-mission-job.ts +161 -0
  420. package/src/dashboard/classic-sidetab-mission-pair.ts +81 -0
  421. package/src/dashboard/classic-sidetab-mission-trio.ts +219 -0
  422. package/src/dashboard/classic-sidetab-mission.ts +347 -0
  423. package/src/dashboard/index.ts +517 -18
  424. package/src/dashboard/input/agent-wake.ts +23 -1
  425. package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
  426. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +17 -0
  427. package/src/dashboard/mission-cli-consumer.ts +165 -0
  428. package/src/dashboard/plugin-wizard-runtime.ts +50 -0
  429. package/src/dashboard/plugin-wizard-tool.ts +55 -0
  430. package/src/dashboard/seat-boot-preamble.ts +171 -1
  431. package/src/dashboard/side-basic-runtime.ts +54 -1
  432. package/src/dashboard/sidetab-runtime.ts +90 -1
  433. package/src/dashboard/skill-catalog-preamble.ts +101 -0
  434. package/src/dashboard/skill-detection-runtime.ts +55 -15
  435. package/src/dashboard/slash-runtime/dashboard-handlers.ts +15 -0
  436. package/src/dashboard/terminal-popup-runtime.ts +6 -3
  437. package/src/dashboard/turn-preamble.ts +53 -15
  438. package/src/dashboard/turn-prompt-runtime.ts +4 -2
  439. package/src/decisions/linear-progress-summary.ts +78 -0
  440. package/src/decisions/linear-progress-sync.ts +152 -0
  441. package/src/domains/outbound-alert.ts +49 -11
  442. package/src/domains/telegram-kind-route.ts +16 -9
  443. package/src/graph-runner/arg-allowance.ts +13 -0
  444. package/src/graph-runner/graph-cli.ts +23 -7
  445. package/src/graph-runner/graph-run-api.ts +3 -1
  446. package/src/graph-runner/graph-tick.ts +10 -2
  447. package/src/graph-runner/runner.ts +86 -18
  448. package/src/graph-wizard/mission-compose.ts +407 -12
  449. package/src/grok/agent-search.ts +14 -4
  450. package/src/grok/credential.ts +28 -11
  451. package/src/harness/dispatch-backpressure.ts +54 -1
  452. package/src/harness/dispatch-shadow-compare.ts +74 -0
  453. package/src/harness/harness-cli-command.ts +11 -1
  454. package/src/harness/harness-pod-dispatch.ts +81 -15
  455. package/src/harness/harness-stop.ts +155 -11
  456. package/src/harness/skill-exec.ts +21 -9
  457. package/src/harness/skill-select.ts +1 -1
  458. package/src/hooks/error-report-cloud.ts +101 -0
  459. package/src/hooks/receiver.ts +29 -2
  460. package/src/index.ts +159 -13
  461. package/src/instance/spawn-elanous.ts +6 -4
  462. package/src/intake-plane/actions.ts +354 -0
  463. package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
  464. package/src/intake-plane/intake-sources.ts +78 -8
  465. package/src/intake-plane/items.ts +14 -4
  466. package/src/intake-plane/linear-mission-sync.ts +80 -0
  467. package/src/intake-plane/linear-secretary-runtime.ts +178 -0
  468. package/src/intake-plane/linear-wish.ts +227 -1
  469. package/src/life/life-cli.ts +168 -0
  470. package/src/life/life-kinds.ts +160 -0
  471. package/src/live-supply/budget-consumer.ts +78 -0
  472. package/src/live-supply/read.ts +3 -0
  473. package/src/live-supply/snapshot.ts +45 -0
  474. package/src/llm/provider-credentials.ts +8 -2
  475. package/src/llm.ts +168 -9
  476. package/src/loops/orchestrator/coordinator-shadow.ts +226 -0
  477. package/src/loops/orchestrator/tick.ts +13 -0
  478. package/src/maturity/feature-maturity.ts +4 -4
  479. package/src/msg/msg-sse-server.ts +3 -3
  480. package/src/msg/msg-store.ts +177 -19
  481. package/src/native-tool-catalog.ts +38 -4
  482. package/src/nexus/api/harness-traversal.ts +11 -0
  483. package/src/nexus/api/http-server.ts +37 -1
  484. package/src/nexus/api/mcp-public-allowlist.ts +2 -0
  485. package/src/nexus/index.ts +7 -2
  486. package/src/nexus/outbound/format.ts +9 -0
  487. package/src/nexus/outbound/router.ts +98 -13
  488. package/src/nexus/setup-status.ts +9 -0
  489. package/src/nexus/state/state.ts +3 -0
  490. package/src/oauth/codex-account-store.ts +20 -7
  491. package/src/oauth/codex-owner-mirror.ts +44 -0
  492. package/src/oauth/codex.ts +17 -2
  493. package/src/oauth/fallback-chain.ts +47 -17
  494. package/src/onboarding/first-run-doctor.ts +8 -1
  495. package/src/onboarding/first-run.ts +85 -26
  496. package/src/onboarding/key-setup.ts +103 -0
  497. package/src/onboarding/menu-answer.ts +13 -0
  498. package/src/onboarding/secret-prompt.ts +37 -0
  499. package/src/plugins/install/plugin-install.ts +59 -0
  500. package/src/pr-tool/census.ts +133 -2
  501. package/src/pty-shell/pty-control-ipc.ts +4 -1
  502. package/src/pty-shell/tui-run-state.ts +188 -2
  503. package/src/registry/catalog-server.ts +232 -0
  504. package/src/registry/loader.ts +45 -1
  505. package/src/registry/types.ts +1 -2
  506. package/src/release-loop/checklist-target-path-hint.ts +13 -0
  507. package/src/release-loop/checklist.ts +9 -1
  508. package/src/repl/index.ts +43 -2
  509. package/src/research/axis-fanout.ts +136 -16
  510. package/src/research/bloom-exemplars.ts +3 -1
  511. package/src/research/gap-followup.ts +13 -1
  512. package/src/research/plugin-discovery.ts +36 -14
  513. package/src/research-bridge/invoke.ts +22 -5
  514. package/src/research-bridge/types.ts +2 -0
  515. package/src/self-dev/ask-launch-flow.ts +72 -1
  516. package/src/self-dev/decompose.ts +119 -5
  517. package/src/self-dev/dev-cli.ts +4 -1
  518. package/src/self-dev/dev-pipeline.ts +5 -0
  519. package/src/self-dev/draft-residue.ts +64 -5
  520. package/src/self-dev/graph-front-nodes.ts +2 -1
  521. package/src/self-dev/graph-journey-route.ts +76 -21
  522. package/src/self-dev/launch-preflight-text.ts +5 -6
  523. package/src/self-dev/launch-preflight.ts +58 -0
  524. package/src/self-dev/orchestrate.ts +13 -3
  525. package/src/self-dev/review-provider-fallback.ts +9 -2
  526. package/src/self-dev/run-supervisor.ts +42 -4
  527. package/src/self-dev/run-types.ts +4 -0
  528. package/src/self-dev/shard-aggregate.ts +4 -0
  529. package/src/self-dev/shard-run.ts +36 -15
  530. package/src/self-implement/abandoned-classification.ts +12 -3
  531. package/src/self-implement/budget-gate.ts +7 -0
  532. package/src/self-implement/child-llm-preference.ts +10 -1
  533. package/src/self-implement/doctor-visit.ts +118 -8
  534. package/src/self-implement/elanous-tui-spawn.ts +3 -0
  535. package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
  536. package/src/self-implement/gate-artifacts.ts +2 -1
  537. package/src/self-implement/goal-author-cli.ts +4 -2
  538. package/src/self-implement/goal-author.ts +684 -7
  539. package/src/self-implement/graph-overlay-yaml.ts +37 -4
  540. package/src/self-implement/graph-overlay.ts +3 -1
  541. package/src/self-implement/graph-profile-yaml.ts +107 -0
  542. package/src/self-implement/graph-yaml.ts +26 -3
  543. package/src/self-implement/headless-elanous-driver.ts +31 -2
  544. package/src/self-implement/heal-intake.ts +112 -4
  545. package/src/self-implement/heal-triage.ts +20 -0
  546. package/src/self-implement/host-regate.ts +27 -4
  547. package/src/self-implement/merge-train.ts +5 -0
  548. package/src/self-implement/off-diff-evidence.ts +249 -5
  549. package/src/self-implement/orchestrator.ts +365 -25
  550. package/src/self-implement/regate-detail.ts +38 -1
  551. package/src/self-implement/rework-child-provider.ts +25 -0
  552. package/src/self-implement/run-chart.ts +122 -0
  553. package/src/self-implement/run-ledger.ts +162 -11
  554. package/src/self-implement/run-stop.ts +188 -4
  555. package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
  556. package/src/self-implement/stop-autoheal.ts +13 -0
  557. package/src/self-implement/tdd-evidence-tags.ts +9 -0
  558. package/src/self-implement/train-gate-receipt.ts +166 -0
  559. package/src/self-implement/train-gate-remote.ts +62 -18
  560. package/src/session/chat.ts +40 -4
  561. package/src/session/session-fanout.ts +2 -0
  562. package/src/session/streaming/acp-stream-sink.ts +2 -1
  563. package/src/session/streaming/chunk-producer.ts +6 -0
  564. package/src/session/streaming/stream-compositor.ts +3 -2
  565. package/src/session-runtime/index.ts +135 -5
  566. package/src/session-runtime/retry-policy.ts +1 -1
  567. package/src/session-runtime/tier-flip.ts +3 -3
  568. package/src/setup/llm-env-detect.ts +3 -0
  569. package/src/setup/service-key-catalog.ts +46 -0
  570. package/src/setup/service-keys.ts +241 -0
  571. package/src/sidetab-core/model.ts +19 -5
  572. package/src/sidetab-core/visible-agent-mission.ts +262 -0
  573. package/src/skills/name-match.ts +20 -0
  574. package/src/skills/tools/agent.ts +53 -6
  575. package/src/skills/tools/omni-search.ts +173 -13
  576. package/src/task-agent/parent-host.ts +10 -0
  577. package/src/task-agent/pod-distributor-entry.ts +3 -0
  578. package/src/task-agent/repair-outcomes.ts +65 -0
  579. package/src/task-agent/task-hand.ts +47 -7
  580. package/src/task-orchestrator/dispatcher.ts +14 -1
  581. package/src/task-orchestrator/linear-capture-events.ts +55 -0
  582. package/src/task-orchestrator/store.ts +16 -5
  583. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +4 -0
  584. package/src/task-orchestrator/surfaces/pod-distributor.ts +48 -0
  585. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +92 -1
  586. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +38 -1
  587. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
  588. package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +33 -6
  589. package/src/task-orchestrator/surfaces/pod-source-bundle.ts +45 -9
  590. package/src/task-orchestrator/surfaces/pod-source-receive.ts +178 -16
  591. package/src/task-orchestrator/surfaces/pod-source-spec.ts +3 -3
  592. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
  593. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +237 -41
  594. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +80 -3
  595. package/src/task-orchestrator/surfaces/self-implement-pod.ts +337 -51
  596. package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
  597. package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
  598. package/src/task-orchestrator/types.ts +14 -0
  599. package/src/telegram.ts +14 -16
  600. package/src/terminal/coding-agent.ts +14 -5
  601. package/src/terminal/session-registry.ts +1 -1
  602. package/src/tokens.ts +35 -2
  603. package/src/tool-hints/gate.ts +1 -0
  604. package/src/tool-runtime/agent-runtime.ts +2 -0
  605. package/src/tool-runtime/browser-hand-runtime.ts +381 -0
  606. package/src/tool-runtime/browser-runtime.ts +2 -1
  607. package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
  608. package/src/tool-runtime/elanous-linear-secretary-runtime.ts +57 -0
  609. package/src/tool-runtime/elanous-skills-list-runtime.ts +5 -1
  610. package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
  611. package/src/tool-runtime/index.ts +6 -0
  612. package/src/tool-runtime/skill-exec-runtime.ts +33 -13
  613. package/src/tool-runtime/types.ts +4 -0
  614. package/src/tui/entry.ts +38 -5
  615. package/src/tui/sidetab/attach.ts +177 -1
  616. package/src/tui/sidetab/herdr-portal.ts +225 -0
  617. package/src/tui-client/local-chat-turn.ts +26 -13
  618. package/src/tui.ts +22 -0
  619. package/src/user-config.ts +34 -9
  620. package/src/user-intent/types.ts +4 -3
  621. package/src/ux-sim/browser-hand.ts +165 -0
  622. package/src/ux-sim/draft-inventory-builder.ts +198 -0
  623. package/src/ux-sim/fake-browser-page.ts +81 -0
  624. package/src/ux-sim/fake-kubectl.ts +37 -3
  625. package/src/ux-sim/fake-linear-device.ts +31 -0
  626. package/src/ux-sim/fault-pool-cap.ts +11 -6
  627. package/src/ux-sim/graph-engine-sim.ts +47 -0
  628. package/src/ux-sim/linear-secretary.ts +216 -0
  629. package/src/ux-sim/mock-scenario-catalog.json +93 -0
  630. package/src/ux-sim/mock-scenario-catalog.ts +274 -0
  631. package/src/ux-sim/onboarding-first-run-device.ts +31 -21
  632. package/src/ux-sim/scenario.ts +185 -48
  633. package/src/ux-sim/service-key-setup.ts +50 -0
  634. package/src/ux-sim/term-slash-device.ts +74 -0
  635. package/src/ux-sim/turn-throw-sim.ts +31 -0
  636. package/src/version/packed-revision.json +1 -1
  637. package/src/voice/voice-tts-singleton.ts +18 -3
  638. package/src/web-search/exa.ts +77 -0
  639. package/src/web-search/grok.ts +5 -9
  640. package/src/web-search/index.ts +30 -9
  641. package/src/web-search/provider.ts +4 -1
  642. package/src/web-search/x-intent.ts +5 -0
  643. package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +0 -149
  644. package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +0 -36
  645. package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +0 -287
  647. package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +0 -90
  652. package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/1765.679b29625c8e88d4.js +0 -77
  654. package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +0 -32
  665. package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +0 -79
  667. package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +0 -74
  671. package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +0 -148
  681. package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +0 -226
  682. package/apps/pwa/out/_next/static/chunks/4667.97e31aa38c95c475.js +0 -309
  683. package/apps/pwa/out/_next/static/chunks/4702.4a4adc1f16d7c93b.js +0 -64
  684. package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +0 -94
  691. package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +0 -8
  693. package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +0 -24
  696. package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +0 -286
  699. package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +0 -27
  703. package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +0 -62
  705. package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +0 -24
  706. package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +0 -122
  708. package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/7191.fdc955f7d96064a4.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/8050-9b364bdef8f71927.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +0 -104
  720. package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +0 -93
  733. package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +0 -34
  738. package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/botlab/page-14949db884bfa672.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +0 -1
  794. package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
  795. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +0 -1
  796. /package/apps/pwa/out/_next/static/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
@@ -1092,7 +1092,15 @@ async function plan() {
1092
1092
  ovSelections = sel.selections.map((x) => ({ overlayId: x.overlayId, verdict: x.verdict, detail: x.detail }));
1093
1093
  if (sel.applied.length > 0) {
1094
1094
  const applied = applyGraphOverlays(decl.template, sel.applied);
1095
- if (applied.ok) ovPatches = applied.patches.map((x) => ({ overlayId: x.overlayId, node: x.node, field: x.field, before: (x as { before: unknown }).before, after: (x as { after: unknown }).after }));
1095
+ if (applied.ok) ovPatches = applied.patches.map((x) => {
1096
+ if (x.field === 'edge-rerouted') return {
1097
+ overlayId: x.overlayId, node: x.from, field: x.field, before: x.was, after: x.to,
1098
+ };
1099
+ if (x.field === 'node-added') return {
1100
+ overlayId: x.overlayId, node: x.node, field: x.field, before: null, after: x.kind,
1101
+ };
1102
+ return { overlayId: x.overlayId, node: x.node, field: x.field, before: x.before, after: x.after };
1103
+ });
1096
1104
  else ovError = `얹다가 거절됐다 — ${applied.rejections.map((r) => r.kind).join(', ')}`;
1097
1105
  }
1098
1106
  }
@@ -0,0 +1,286 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { chmodSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
3
+ import { dirname, isAbsolute, join } from 'node:path';
4
+ import { randomUUID } from 'node:crypto';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { userConfigPath } from '../src/user-config.js';
7
+ import type { WarmWorkerCandidate } from '../src/task-orchestrator/surfaces/pod-warm-worker-provider.js';
8
+
9
+ const TOKEN = /^[a-f0-9]{64}$/;
10
+ const SHA = /^[a-f0-9]{40}$/;
11
+ const DIGEST = /^sha256:[a-f0-9]{64}$/;
12
+ const LOCK_HASH = /^[a-f0-9]{64}$/;
13
+ const TIERS = new Set(['lite', 'standard']);
14
+
15
+ type JsonObject = Record<string, unknown>;
16
+
17
+ export interface WarmPoolProviderConfig {
18
+ candidates: WarmWorkerCandidate[];
19
+ poolTemplates: Array<{
20
+ host: string;
21
+ tier: 'lite' | 'standard';
22
+ spec: {
23
+ name: string;
24
+ namespace: string;
25
+ kubectlContext: string;
26
+ workerId: string;
27
+ image: string;
28
+ sourceUrl?: string;
29
+ sourceMirrorHostPath?: string;
30
+ nodeName: string;
31
+ cutSha: string;
32
+ key: { context: string; imageDigest: string; lockHash: string; architecture: string };
33
+ memoryLimit: '2Gi' | '16Gi';
34
+ hostProbeUrl: string;
35
+ prodProbeUrl: string;
36
+ };
37
+ }>;
38
+ profileConfig: { pod: { warmPoolProfile: string } };
39
+ controlUrl: string;
40
+ memberToken: string;
41
+ machineTokens: Record<string, string>;
42
+ }
43
+
44
+ export interface AssembleWarmPoolProviderConfigInput {
45
+ config: unknown;
46
+ controlUrl: string;
47
+ memberToken: string;
48
+ machineTokens: Record<string, string>;
49
+ }
50
+
51
+ /** Keep a deployment canary to one explicit worker instead of expanding its profile quota. */
52
+ export function selectSingleWarmPoolCandidate(config: WarmPoolProviderConfig, selection: string): WarmPoolProviderConfig {
53
+ const match = /^([a-zA-Z0-9][a-zA-Z0-9._-]*)\/(lite|standard)$/.exec(selection);
54
+ if (!match) throw new Error('--single-candidate must be HOST/lite or HOST/standard');
55
+ const [, host, tier] = match;
56
+ const template = config.poolTemplates.find(candidate => candidate.host === host && candidate.tier === tier);
57
+ if (!template) throw new Error(`warm pool template not found: ${host}/${tier}`);
58
+ const index = 1;
59
+ return {
60
+ ...config,
61
+ candidates: [{ host, tier: tier as 'lite' | 'standard', spec: {
62
+ ...template.spec,
63
+ name: `warm-${host}-${tier}-${index}`,
64
+ workerId: `${template.spec.workerId}-${tier}-${index}`,
65
+ } }],
66
+ poolTemplates: [],
67
+ };
68
+ }
69
+
70
+ function object(value: unknown, label: string): JsonObject {
71
+ if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`${label} is required`);
72
+ return value as JsonObject;
73
+ }
74
+
75
+ function text(value: unknown, label: string): string {
76
+ if (typeof value !== 'string' || !value.trim()) throw new Error(`${label} is required`);
77
+ return value.trim();
78
+ }
79
+
80
+ function token(value: unknown, label: string): string {
81
+ const parsed = text(value, label);
82
+ if (!TOKEN.test(parsed)) throw new Error(`${label} must be a 64-character hexadecimal token`);
83
+ return parsed;
84
+ }
85
+
86
+ function httpUrl(value: unknown, label: string, hostname?: string): string {
87
+ const parsed = text(value, label);
88
+ try {
89
+ const url = new URL(parsed);
90
+ if (url.protocol !== 'http:' || !url.port || url.username || url.password || url.search || url.hash
91
+ || (hostname !== undefined && url.hostname !== hostname)) throw new Error();
92
+ return url.href;
93
+ } catch { throw new Error(`${label} must be an http URL${hostname ? ` for ${hostname}` : ''}`); }
94
+ }
95
+
96
+ function controlUrl(value: unknown): string {
97
+ const parsed = text(value, 'controlUrl');
98
+ try {
99
+ const url = new URL(parsed);
100
+ const authority = /^(?:http|https):\/\/([^/?#]*)/i.exec(parsed)?.[1] ?? '';
101
+ const explicitPort = !authority.includes('\\') && /^(?:\[[^\]]+\]|[^:]+):\d+$/.test(authority);
102
+ if (!['http:', 'https:'].includes(url.protocol) || !explicitPort || authority.includes('@') || url.username || url.password
103
+ || parsed.includes('?') || parsed.includes('#') || url.search || url.hash)
104
+ throw new Error();
105
+ return url.href;
106
+ } catch { throw new Error('controlUrl must be an http or https URL with an explicit port'); }
107
+ }
108
+
109
+ function privateSource(pool: JsonObject): Pick<WarmPoolProviderConfig['poolTemplates'][number]['spec'], 'sourceUrl' | 'sourceMirrorHostPath'> {
110
+ const mirror = pool.sourceMirrorHostPath;
111
+ const source = pool.sourceUrl;
112
+ if (typeof mirror === 'string' && mirror.trim()) {
113
+ if (!isAbsolute(mirror) || mirror.trim() !== mirror) throw new Error('pod.warmPool.sourceMirrorHostPath must be an absolute normalized path');
114
+ return { sourceMirrorHostPath: mirror };
115
+ }
116
+ if (typeof source === 'string' && source.trim()) {
117
+ try {
118
+ const url = new URL(source);
119
+ if (url.protocol !== 'https:' || !url.hostname || url.username || url.password || url.search || url.hash) throw new Error();
120
+ return { sourceUrl: url.href };
121
+ } catch { throw new Error('pod.warmPool.sourceUrl must be a public https URL'); }
122
+ }
123
+ throw new Error('pod.warmPool.sourceMirrorHostPath or pod.warmPool.sourceUrl is required');
124
+ }
125
+
126
+ /** Convert canonical user config plus operator-supplied private credentials into the two provider loaders' shared format. */
127
+ export function assembleWarmPoolProviderConfig(input: AssembleWarmPoolProviderConfigInput): WarmPoolProviderConfig {
128
+ const root = object(input.config, 'config');
129
+ const pod = object(root.pod, 'pod');
130
+ const harness = object(root.harness, 'harness');
131
+ const profile = text(pod.warmPoolProfile, 'pod.warmPoolProfile');
132
+ const pool = object(pod.warmPool, 'pod.warmPool');
133
+ const cutSha = text(harness.imageCommit, 'harness.imageCommit');
134
+ if (!SHA.test(cutSha)) throw new Error('harness.imageCommit must be a 40-character commit SHA');
135
+ const kubectlContext = text(harness.podPool, 'harness.podPool');
136
+ const namespace = text(pool.namespace, 'pod.warmPool.namespace');
137
+ const imageRepository = text(pool.imageRepository, 'pod.warmPool.imageRepository').replace(/\/$/, '');
138
+ const imageDigest = text(pool.imageDigest, 'pod.warmPool.imageDigest');
139
+ if (!DIGEST.test(imageDigest)) throw new Error('pod.warmPool.imageDigest must be a sha256 digest');
140
+ const lockHash = text(pool.lockHash, 'pod.warmPool.lockHash');
141
+ if (!LOCK_HASH.test(lockHash)) throw new Error('pod.warmPool.lockHash must be a 64-character SHA-256');
142
+ const architecture = text(pool.architecture, 'pod.warmPool.architecture');
143
+ const hostProbeUrl = httpUrl(pool.hostProbeUrl, 'pod.warmPool.hostProbeUrl', 'host.orb.internal');
144
+ const prodProbeUrl = httpUrl(pool.prodProbeUrl, 'pod.warmPool.prodProbeUrl', 'core.elanous-prod');
145
+ const source = privateSource(pool);
146
+ const templates = pool.templates;
147
+ if (!Array.isArray(templates) || templates.length === 0) throw new Error('pod.warmPool.templates is required');
148
+ const seen = new Set<string>();
149
+ const machineTokens: Record<string, string> = {};
150
+ const poolTemplates = templates.map((raw, index) => {
151
+ const row = object(raw, `pod.warmPool.templates[${index}]`);
152
+ const host = text(row.host, `pod.warmPool.templates[${index}].host`);
153
+ const tier = text(row.tier, `pod.warmPool.templates[${index}].tier`);
154
+ if (!TIERS.has(tier)) throw new Error(`pod.warmPool.templates[${index}].tier must be lite or standard`);
155
+ const nodeName = text(row.nodeName, `pod.warmPool.templates[${index}].nodeName`);
156
+ const identity = `${host}/${tier}`;
157
+ if (seen.has(identity)) throw new Error(`duplicate pod.warmPool template ${identity}`);
158
+ seen.add(identity);
159
+ machineTokens[host] = token(input.machineTokens[host], `machine token for ${host}`);
160
+ return {
161
+ host,
162
+ tier: tier as 'lite' | 'standard',
163
+ spec: {
164
+ name: `warm-${host}-${tier}-template`, namespace, kubectlContext,
165
+ workerId: `warm-${host}-${cutSha.slice(0, 12)}`, image: `${imageRepository}@${imageDigest}`,
166
+ ...source, nodeName, cutSha,
167
+ key: { context: kubectlContext, imageDigest, lockHash, architecture },
168
+ memoryLimit: tier === 'lite' ? '2Gi' as const : '16Gi' as const,
169
+ hostProbeUrl, prodProbeUrl,
170
+ },
171
+ };
172
+ });
173
+ return { candidates: [], poolTemplates, profileConfig: { pod: { warmPoolProfile: profile } },
174
+ controlUrl: controlUrl(input.controlUrl), memberToken: token(input.memberToken, 'member token'), machineTokens };
175
+ }
176
+
177
+ /** Atomically replace the private provider config and repair permissions on an existing file. */
178
+ export function writeWarmPoolProviderConfig(path: string, config: WarmPoolProviderConfig): void {
179
+ if (!isAbsolute(path)) throw new Error('output path must be absolute');
180
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
181
+ const temporary = `${path}.${randomUUID()}.tmp`;
182
+ try {
183
+ writeFileSync(temporary, `${JSON.stringify(config, null, 2)}\n`, { encoding: 'utf8', flag: 'wx', mode: 0o600 });
184
+ renameSync(temporary, path);
185
+ chmodSync(path, 0o600);
186
+ } catch (error) {
187
+ try { unlinkSync(temporary); } catch { /* no temporary output */ }
188
+ throw error;
189
+ }
190
+ }
191
+
192
+ function redact(config: WarmPoolProviderConfig): unknown {
193
+ return { ...config, memberToken: '[redacted]', machineTokens: Object.fromEntries(Object.keys(config.machineTokens).map(host => [host, '[redacted]'])) };
194
+ }
195
+
196
+ function shellQuote(value: string): string { return `'${value.replaceAll("'", "'\\''")}'`; }
197
+
198
+ interface CliOptions {
199
+ configPath: string;
200
+ controlUrl: string;
201
+ memberTokenFile: string;
202
+ machineTokenFiles: Record<string, string>;
203
+ output: string;
204
+ dryRun: boolean;
205
+ serve: boolean;
206
+ singleCandidate?: string;
207
+ }
208
+
209
+ function parseArgs(argv: readonly string[]): CliOptions {
210
+ let configPath = userConfigPath(), controlUrl = '', memberTokenFile = '', output = '';
211
+ let dryRun = false, serve = false, singleCandidate: string | undefined;
212
+ const machineTokenFiles: Record<string, string> = {};
213
+ for (let index = 0; index < argv.length; index++) {
214
+ const arg = argv[index];
215
+ const next = () => {
216
+ const value = argv[++index];
217
+ if (!value) throw new Error(`missing value for ${arg}`);
218
+ return value;
219
+ };
220
+ if (arg === '--config') configPath = next();
221
+ else if (arg === '--control-url') controlUrl = next();
222
+ else if (arg === '--member-token-file') memberTokenFile = next();
223
+ else if (arg === '--machine-token') {
224
+ const [host, file, extra] = next().split('=');
225
+ if (!host || !file || extra !== undefined) throw new Error('--machine-token must be HOST=FILE');
226
+ machineTokenFiles[host] = file;
227
+ } else if (arg === '--output') output = next();
228
+ else if (arg === '--dry-run') dryRun = true;
229
+ else if (arg === '--serve') serve = true;
230
+ else if (arg === '--single-candidate') singleCandidate = next();
231
+ else throw new Error(`unknown argument: ${arg}`);
232
+ }
233
+ if (!isAbsolute(configPath) || !controlUrl || !isAbsolute(memberTokenFile))
234
+ throw new Error('usage: --config ABSOLUTE --control-url URL --member-token-file ABSOLUTE --machine-token HOST=ABSOLUTE [--output ABSOLUTE] [--single-candidate HOST/TIER] [--dry-run|--serve]');
235
+ if (Object.values(machineTokenFiles).some(file => !isAbsolute(file))) throw new Error('machine token files must be absolute');
236
+ if (dryRun && serve) throw new Error('--dry-run and --serve cannot be combined');
237
+ return { configPath, controlUrl, memberTokenFile, machineTokenFiles,
238
+ output: output || join(dirname(configPath), 'warm-pod-provider.json'), dryRun, serve, singleCandidate };
239
+ }
240
+
241
+ function readPrivateToken(path: string, label: string): string {
242
+ if (!isAbsolute(path)) throw new Error(`${label} path must be absolute`);
243
+ return token(readFileSync(path, 'utf8').trim(), label);
244
+ }
245
+
246
+ export async function runWarmPoolProviderConfig(argv: readonly string[]): Promise<void> {
247
+ const options = parseArgs(argv);
248
+ const config = JSON.parse(readFileSync(options.configPath, 'utf8')) as unknown;
249
+ const machineTokens = Object.fromEntries(Object.entries(options.machineTokenFiles)
250
+ .map(([host, path]) => [host, readPrivateToken(path, `machine token for ${host}`)]));
251
+ const assembled = assembleWarmPoolProviderConfig({ config, controlUrl: options.controlUrl,
252
+ memberToken: readPrivateToken(options.memberTokenFile, 'member token'), machineTokens });
253
+ const selected = options.singleCandidate ? selectSingleWarmPoolCandidate(assembled, options.singleCandidate) : assembled;
254
+ if (!options.dryRun) writeWarmPoolProviderConfig(options.output, selected);
255
+ process.stdout.write(`${JSON.stringify({ output: options.output, config: redact(selected),
256
+ ...(options.serve ? { serve: { command: `ELANOUS_WARM_POD_PROVIDER_CONFIG=${shellQuote(options.output)} bun src/task-orchestrator/surfaces/pod-warm-worker-provider.ts --serve` } } : {}) })}\n`);
257
+ if (!options.serve) return;
258
+ const provider = fileURLToPath(new URL('../src/task-orchestrator/surfaces/pod-warm-worker-provider.ts', import.meta.url));
259
+ const child = spawn(process.execPath, [provider, '--serve'], { stdio: 'inherit',
260
+ env: { ...process.env, ELANOUS_WARM_POD_PROVIDER_CONFIG: options.output } });
261
+ const forwardSignal = (signal: NodeJS.Signals) => { if (child.exitCode === null && child.signalCode === null) child.kill(signal); };
262
+ const forwardInterrupt = () => forwardSignal('SIGINT');
263
+ const forwardTerminate = () => forwardSignal('SIGTERM');
264
+ process.on('SIGINT', forwardInterrupt);
265
+ process.on('SIGTERM', forwardTerminate);
266
+ try {
267
+ await new Promise<void>((resolve, reject) => {
268
+ child.once('error', reject);
269
+ child.once('close', (code, signal) => {
270
+ process.exitCode = code ?? (signal === 'SIGINT' ? 130 : signal === 'SIGTERM' ? 143 : 2);
271
+ resolve();
272
+ });
273
+ });
274
+ } finally {
275
+ process.off('SIGINT', forwardInterrupt);
276
+ process.off('SIGTERM', forwardTerminate);
277
+ }
278
+ }
279
+
280
+ if (import.meta.main) {
281
+ try { await runWarmPoolProviderConfig(process.argv.slice(2)); }
282
+ catch (error) {
283
+ process.stderr.write(`warm-pool-provider-config: ${error instanceof Error ? error.message : String(error)}\n`);
284
+ process.exitCode = 2;
285
+ }
286
+ }
@@ -81,13 +81,16 @@ requires: []
81
81
  자체 합성 파이프라인 (Tavily Research 엔드포인트 미사용 — 콜당 15~250cr 폭탄 회피):
82
82
 
83
83
  ```
84
- 1) 다각도 tavily advanced ×3 (core/outlook/risk) 병렬 ~6cr ⚙️ OMNI_CRAWL_TAVILY=0 이면 ddg 무료 ×3 (0cr)
85
- 2) URL dedup → 상위 5개 firecrawl 풀스크랩 (캐시 2h) ~5cr
84
+ 1) 다각도 검색 ×3 (Tavily 사용 가능 시 Tavily, 키 없음/비활성 시 Firecrawl) 병렬
85
+ 런타임 0건/실패면 다음 유료 엔진, 두 검색축이 모두 비었을 때만 DDG 무료 최후 폴백
86
+ 2) URL dedup → 상위 5개 Firecrawl 풀스크랩 (캐시 2h)
86
87
  3) grok-community 1콜 (X+레딧 여론 각도) ~$0.05
87
88
  4) 기술 주제면 fc-dev 1콜 자동 가세 (looksTechnical 게이트) ~2cr
88
89
  → 통합 마크다운 (풀본문이 스니펫보다 dedup 우선 생존)
89
90
  ```
90
91
 
92
+ 각 각도 검색과 URL 스크랩은 엔진·단계별 경과 시간을 로그에 남긴다. Tavily 키가 없는 정상 경로는 Firecrawl 검색으로 세 각도를 채우며, DDG는 Tavily와 Firecrawl이 모두 없거나 0건일 때만 최후 폴백으로 호출한다.
93
+
91
94
  ## 실행
92
95
 
93
96
  이 스킬 폴더에서 실행합니다.
@@ -153,7 +153,7 @@ async function main(query: string) {
153
153
 
154
154
  // ── Deep research 파이프라인 (자체 합성 — Tavily Research 엔드포인트 미사용·비용 예측성) ──
155
155
  //
156
- // 1) 다각도 tavily advanced ×3 (사실/전망/리스크 각도) 병렬
156
+ // 1) 다각도 웹 검색 ×3 (Tavily 사용 가능 시 Tavily, 아니면 Firecrawl) 병렬
157
157
  // 2) URL dedup → 상위 K=5 를 firecrawl 풀스크랩 (maxAge 2h 캐시)
158
158
  // 3) grok-community 1콜 (X+레딧 여론 각도)
159
159
  // 카버당 비용: tavily ~6cr + firecrawl ~5cr + grok ~$0.03 — 예측 가능.
@@ -173,15 +173,11 @@ async function runDeep(query: string): Promise<CrawlResult[]> {
173
173
  const results: CrawlResult[] = [];
174
174
 
175
175
  // 1) 다각도 검색 + grok-community 동시 발사
176
- // ⛔⭐ 2026-08-06 (공식 결정) — tavily 각도 검색은 **기본 OFF**(deep 1회당 advanced ×3 ≈ 6cr 고정비).
177
- // 켜기: `.env` 또는 셸에 `OMNI_CRAWL_TAVILY=1`. 끄면 아래 `!gotTavily` 분기가 **이미 있는**
178
- // ddg 무료 각도 검색을 대신 돌린다(별도 배선 불필요).
176
+ // 키 부재·비활성뿐 아니라 Tavily/Firecrawl 런타임 공백도 다음 엔진으로 넘긴다.
177
+ // Tavily 부재 시 Firecrawl이 우선이며 DDG는 두 유료 검색축이 모두 비었을 때만 최후 폴백.
178
+ const angleEngines = deepAngleSearchOrder(tavilyEnabled() && tavilyAvailable(), firecrawlAvailable());
179
179
  const searchTasks: Array<Promise<CrawlResult | null>> = [
180
- ...(tavilyEnabled() ? angles.map(a =>
181
- searchTavily(a.q, { depth: 'advanced', maxResults: 5, chunksPerSource: 3, timeRange: flags['time-range'] })
182
- .then(r => ({ ...r, engine: `tavily:${a.label}` }))
183
- .catch(e => { console.log(` [deep] tavily(${a.label}) 실패: ${e.message?.slice(0, 80)}`); return null; }),
184
- ) : []),
180
+ ...angles.map(a => searchDeepAngle(a, angleEngines)),
185
181
  searchGrok({ query, mode: 'community' })
186
182
  .catch(e => { console.log(` [deep] grok-community 실패: ${e.message?.slice(0, 80)}`); return null; }),
187
183
  // 기술 주제면 개발자 인덱스 1콜 추가(실측 ~2cr) — 패시지가 곧 인용이라 풀스크랩 콜을 아낀다.
@@ -193,20 +189,11 @@ async function runDeep(query: string): Promise<CrawlResult[]> {
193
189
  const settled = await Promise.all(searchTasks);
194
190
  for (const r of settled) if (r) results.push(r as CrawlResult);
195
191
 
196
- // 1-b) tavily 축이 비면(기본 OFF · 키 없음 · 장애) ddg 무료가 각도 검색을 담당한다.
197
- const gotTavily = results.some(r => r.engine.startsWith('tavily') && r.totalItems > 0);
198
- if (!gotTavily) {
199
- console.log(' [deep] ddg 무료 티어로 각도 검색');
200
- const ddgResults = await Promise.all(angles.map(a =>
201
- searchDdg(a.q, { maxResults: 5 }).then(r => ({ ...r, engine: `ddg:${a.label}` })).catch(() => null)));
202
- for (const r of ddgResults) if (r && r.totalItems > 0) results.push(r as CrawlResult);
203
- }
204
-
205
192
  // 2) 검색 히트에서 상위 URL 추출 → firecrawl 풀스크랩 (병렬·캐시 2h)
206
193
  const seen = new Set<string>();
207
194
  const topUrls: string[] = [];
208
195
  for (const r of results) {
209
- if (!r.engine.startsWith('tavily') && !r.engine.startsWith('ddg')) continue;
196
+ if (!r.engine.startsWith('tavily') && !r.engine.startsWith('firecrawl') && !r.engine.startsWith('ddg')) continue;
210
197
  for (const it of r.items) {
211
198
  if (!it.url || seen.has(it.url)) continue;
212
199
  seen.add(it.url);
@@ -217,9 +204,21 @@ async function runDeep(query: string): Promise<CrawlResult[]> {
217
204
  }
218
205
  if (topUrls.length) {
219
206
  console.log(` [deep] 상위 ${topUrls.length}개 URL 풀스크랩 (firecrawl·캐시 2h)`);
220
- const scraped = await Promise.all(topUrls.map(u =>
221
- scrapeFirecrawl(u, { maxAge: 2 * 3600_000 }).catch(() => null),
222
- ));
207
+ const scraped = await Promise.all(topUrls.map(async u => {
208
+ const startedAt = Date.now();
209
+ try {
210
+ const result = await scrapeFirecrawl(u, { maxAge: 2 * 3600_000 });
211
+ if (!result) {
212
+ console.log(` [deep:firecrawl:scrape] ${u} · 실패 · ${Date.now() - startedAt}ms · 본문 없음`);
213
+ return null;
214
+ }
215
+ console.log(` [deep:firecrawl:scrape] ${u} · ${Date.now() - startedAt}ms · ${result.content.length}자`);
216
+ return result;
217
+ } catch (e: any) {
218
+ console.log(` [deep:firecrawl:scrape] ${u} · 실패 · ${Date.now() - startedAt}ms · ${e.message?.slice(0, 80)}`);
219
+ return null;
220
+ }
221
+ }));
223
222
  const items: CrawlItem[] = [];
224
223
  for (let i = 0; i < scraped.length; i++) {
225
224
  const s = scraped[i];
@@ -248,12 +247,54 @@ async function runDeep(query: string): Promise<CrawlResult[]> {
248
247
  if (s) items.push({ engine: 'fc-deep', query, url: missed[i], text: s.content.slice(0, 6000), metadata: { via: s.method, title: s.title } });
249
248
  }
250
249
  }
251
- if (items.length) results.push({ engine: 'deep-fullscrape', query, items, totalItems: items.length, costNote: `firecrawl ~${scraped.filter(Boolean).length}cr + 무료` });
250
+ if (items.length) {
251
+ console.log(` [deep:firecrawl:fullscrape] ${items.length}/${topUrls.length}건 본문 확보`);
252
+ results.push({ engine: 'deep-fullscrape', query, items, totalItems: items.length, costNote: `firecrawl ~${scraped.filter(Boolean).length}cr + 무료` });
253
+ } else {
254
+ console.log(` [deep:firecrawl:fullscrape] 0/${topUrls.length}건 본문 확보`);
255
+ }
252
256
  }
253
257
 
254
258
  return results;
255
259
  }
256
260
 
261
+ type DeepAngleEngine = 'tavily' | 'firecrawl' | 'ddg';
262
+
263
+ function deepAngleSearchOrder(tavilyReady: boolean, firecrawlReady: boolean): DeepAngleEngine[] {
264
+ return [
265
+ ...(tavilyReady ? ['tavily' as const] : []),
266
+ ...(firecrawlReady ? ['firecrawl' as const] : []),
267
+ 'ddg',
268
+ ];
269
+ }
270
+
271
+ function firecrawlTbsFromTimeRange(timeRange?: string): string | undefined {
272
+ if (!timeRange) return undefined;
273
+ return ({ day: 'qdr:d', week: 'qdr:w', month: 'qdr:m', year: 'qdr:y' } as Record<string, string>)[timeRange];
274
+ }
275
+
276
+ async function searchDeepAngle(
277
+ angle: { q: string; label: string },
278
+ engines: DeepAngleEngine[],
279
+ ): Promise<CrawlResult | null> {
280
+ for (const engine of engines) {
281
+ const startedAt = Date.now();
282
+ try {
283
+ const result = engine === 'tavily'
284
+ ? await searchTavily(angle.q, { depth: 'advanced', maxResults: 5, chunksPerSource: 3, timeRange: flags['time-range'] })
285
+ : engine === 'firecrawl'
286
+ ? await searchFirecrawl(angle.q, { limit: 5, tbs: firecrawlTbsFromTimeRange(flags['time-range']) })
287
+ : await searchDdg(angle.q, { maxResults: 5 });
288
+ const elapsedMs = Date.now() - startedAt;
289
+ console.log(` [deep:${engine}:${angle.label}] ${result.totalItems}건 · ${elapsedMs}ms`);
290
+ if (result.totalItems > 0) return { ...result, engine: `${engine}:${angle.label}` };
291
+ } catch (e: any) {
292
+ console.log(` [deep:${engine}:${angle.label}] 실패 · ${Date.now() - startedAt}ms · ${e.message?.slice(0, 80)}`);
293
+ }
294
+ }
295
+ return null;
296
+ }
297
+
257
298
  // ── 폴백 체인: tavily ↔ firecrawl → (최후) ddg 무료 (웹 검색 축 공백 방지) ──
258
299
  //
259
300
  // 원칙: 유료(tavily/firecrawl)가 1순위·기본. 유료가 공백/미가용일 때만 무료(ddg)로 강등.
@@ -494,6 +535,26 @@ function runSelfTest() {
494
535
  else { console.log(` FAIL: looksTechnical("${q}") expect ${expect}, got ${got}`); failed++; }
495
536
  }
496
537
 
538
+ const angleEngineCases: Array<[string, boolean, boolean, string]> = [
539
+ ['Tavily and Firecrawl ready', true, true, 'tavily,firecrawl,ddg'],
540
+ ['Tavily unavailable', false, true, 'firecrawl,ddg'],
541
+ ['Tavily disabled', false, true, 'firecrawl,ddg'],
542
+ ['both paid search engines unavailable', false, false, 'ddg'],
543
+ ];
544
+ for (const [label, tavilyReady, firecrawlReady, expected] of angleEngineCases) {
545
+ const got = deepAngleSearchOrder(tavilyReady, firecrawlReady).join(',');
546
+ if (got === expected) { console.log(` PASS: deep angle fallback ${label} → ${got}`); passed++; }
547
+ else { console.log(` FAIL: deep angle fallback ${label} expect ${expected}, got ${got}`); failed++; }
548
+ }
549
+ const tbsCases: Array<[string, string | undefined]> = [
550
+ ['day', 'qdr:d'], ['week', 'qdr:w'], ['month', 'qdr:m'], ['year', 'qdr:y'], ['unset', undefined],
551
+ ];
552
+ for (const [timeRange, expected] of tbsCases) {
553
+ const got = firecrawlTbsFromTimeRange(timeRange === 'unset' ? undefined : timeRange);
554
+ if (got === expected) { console.log(` PASS: Firecrawl time range ${timeRange} → ${got ?? 'unset'}`); passed++; }
555
+ else { console.log(` FAIL: Firecrawl time range ${timeRange} expect ${expected}, got ${got}`); failed++; }
556
+ }
557
+
497
558
  console.log(`\n결과: ${passed} passed, ${failed} failed`);
498
559
  if (failed > 0) process.exit(1);
499
560
  }
@@ -76,6 +76,7 @@ export class AcpAgentManager {
76
76
  agent = new CodexAppServerAgent({
77
77
  backendId,
78
78
  ...opts,
79
+ remoteSocketPath: process.env.ELANOUS_CODEX_REMOTE_SIDETAB_SOCKET || undefined,
79
80
  elicitationHandler: createAskUserElicitationHandler(),
80
81
  }) as unknown as AcpAgent;
81
82
  } else {
@@ -31,6 +31,7 @@
31
31
  import {
32
32
  CodexAppServerClient,
33
33
  spawnCodexAppServer,
34
+ spawnCodexRemoteTui,
34
35
  type SpawnCodexAppServerOpts,
35
36
  type SpawnedCodexAppServer,
36
37
  } from './codex-app-server-client.js';
@@ -713,6 +714,8 @@ export interface CodexAppServerAgentOpts {
713
714
  readonly codexBinary?: string;
714
715
  /** Session-scoped argv forwarded to `spawnCodexAppServer`. */
715
716
  readonly codexArgs?: readonly string[];
717
+ /** Explicit opt-in Codex remote side-tab Unix socket path. */
718
+ readonly remoteSocketPath?: string;
716
719
  readonly env?: Record<string, string>;
717
720
  readonly log?: (msg: string) => void;
718
721
  /** Called after a successful initialize with this backend's advertised capabilities.
@@ -770,6 +773,7 @@ export interface CodexAppServerAgentOpts {
770
773
  readonly _spawnFactory?: (
771
774
  opts: SpawnCodexAppServerOpts,
772
775
  ) => SpawnedCodexAppServer;
776
+ readonly _remoteTuiSpawnForTesting?: typeof spawnCodexRemoteTui;
773
777
  }
774
778
 
775
779
  export class CodexAppServerAgent {
@@ -777,12 +781,14 @@ export class CodexAppServerAgent {
777
781
  private readonly cwd?: string;
778
782
  private readonly codexBinary?: string;
779
783
  private readonly codexArgs?: readonly string[];
784
+ private readonly remoteSocketPath?: string;
780
785
  private readonly env?: Record<string, string>;
781
786
  private readonly log: (msg: string) => void;
782
787
  private readonly onCapabilities: ((capabilities: ElanousCapabilities) => void) | undefined;
783
788
 
784
789
  private client: CodexAppServerClient | null;
785
790
  private child: SpawnedCodexAppServer['child'] | null = null;
791
+ private remoteTuiChild: ReturnType<typeof spawnCodexRemoteTui> | null = null;
786
792
  private initialized = false;
787
793
 
788
794
  private readonly approvalAdapter: CodexApprovalAdapter;
@@ -877,12 +883,14 @@ export class CodexAppServerAgent {
877
883
  private readonly _spawnFactory:
878
884
  | ((opts: SpawnCodexAppServerOpts) => SpawnedCodexAppServer)
879
885
  | undefined;
886
+ private readonly _remoteTuiSpawnForTesting: typeof spawnCodexRemoteTui | undefined;
880
887
 
881
888
  constructor(opts: CodexAppServerAgentOpts) {
882
889
  this.backendId = opts.backendId;
883
890
  this.cwd = opts.cwd;
884
891
  this.codexBinary = opts.codexBinary;
885
892
  this.codexArgs = opts.codexArgs ? [...opts.codexArgs] : undefined;
893
+ this.remoteSocketPath = opts.remoteSocketPath;
886
894
  this.env = opts.env;
887
895
  this.log = opts.log ?? ((msg) => debug.log('acp.cxn.appserver.agent', msg));
888
896
  this.onCapabilities = opts.onCapabilities;
@@ -894,6 +902,7 @@ export class CodexAppServerAgent {
894
902
  this.imageTempDir = opts.imageTempDir ?? defaultImageTempDir();
895
903
  this._clientForTesting = opts._clientForTesting;
896
904
  this._spawnFactory = opts._spawnFactory;
905
+ this._remoteTuiSpawnForTesting = opts._remoteTuiSpawnForTesting;
897
906
  this.threadIndex = opts._threadIndexForTesting ?? globalCasThreadIndex();
898
907
  // M6 · idle hibernate config. Env override only applies when opts
899
908
  // didn't set it explicitly so tests can pin a value regardless of
@@ -979,6 +988,7 @@ export class CodexAppServerAgent {
979
988
  env: { ...rotatedCodexChildEnv(childEnv), ...(this.env ?? {}) },
980
989
  codexBinary,
981
990
  codexArgs: this.codexArgs,
991
+ remoteSocketPath: this.remoteSocketPath,
982
992
  };
983
993
  const spawned = spawnFn(spawnOpts);
984
994
  this.client = spawned.client;
@@ -1069,6 +1079,13 @@ export class CodexAppServerAgent {
1069
1079
  /* swallow */
1070
1080
  }
1071
1081
  }
1082
+ if (this.remoteTuiChild) {
1083
+ try {
1084
+ this.remoteTuiChild.kill('SIGTERM');
1085
+ } catch {
1086
+ /* swallow */
1087
+ }
1088
+ }
1072
1089
  if (this.child) {
1073
1090
  try {
1074
1091
  this.child.kill('SIGTERM');
@@ -1078,6 +1095,7 @@ export class CodexAppServerAgent {
1078
1095
  }
1079
1096
  this.client = null;
1080
1097
  this.child = null;
1098
+ this.remoteTuiChild = null;
1081
1099
  this.initialized = false;
1082
1100
  this.sessionToThread.clear();
1083
1101
  this.threadToSession.clear();
@@ -1110,6 +1128,7 @@ export class CodexAppServerAgent {
1110
1128
  * disabled. unref() so a CLI can still exit cleanly when the daemon
1111
1129
  * is the only thing keeping the loop alive. */
1112
1130
  private armIdleTimer(): void {
1131
+ if (this.remoteSocketPath) return;
1113
1132
  if (this.idleTimerHandle !== null) return;
1114
1133
  if (this.idleTimeoutMs <= 0) return;
1115
1134
  this.idleTimerHandle = setInterval(() => {
@@ -1328,6 +1347,20 @@ export class CodexAppServerAgent {
1328
1347
  // M6 · brand-new sessions are alive in the current daemon by
1329
1348
  // definition · no thread/resume needed before the first turn.
1330
1349
  this.currentDaemonSessions.add(sessionId);
1350
+ if (this.remoteSocketPath && !this.remoteTuiChild) {
1351
+ const explicitEnv = this.env ?? {};
1352
+ const tuiEnv = {
1353
+ ...rotatedCodexChildEnv({ ...process.env, ...explicitEnv }),
1354
+ ...explicitEnv,
1355
+ };
1356
+ const spawnRemoteTui = this._remoteTuiSpawnForTesting ?? spawnCodexRemoteTui;
1357
+ this.remoteTuiChild = spawnRemoteTui({
1358
+ codexBinary: this.codexBinary ?? resolvePreferredCodexBinary(),
1359
+ socketPath: this.remoteSocketPath,
1360
+ cwd: this.cwd,
1361
+ env: tuiEnv,
1362
+ });
1363
+ }
1331
1364
  debug.log('acp.client', 'session-new', { backendId: this.backendId, sessionId });
1332
1365
  return sessionId;
1333
1366
  }