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
package/src/repl/index.ts CHANGED
@@ -41,6 +41,8 @@ import {
41
41
  type UserConfig,
42
42
  } from '../user-config.js';
43
43
  import { setAmbientSessionId, debug } from '../debug/log.js';
44
+ import { buildInstalledSkillCatalogMessage, type InstalledSkillSummary } from '../dashboard/skill-catalog-preamble.js';
45
+ import { resolveModelContextWindow } from '../models/context-window.js';
44
46
  import { decideSigintAction } from './sigint.js';
45
47
  import { decideSessionStart, observeSessionStart } from '../session/session-start.js';
46
48
  import { buildReplayTurnsFromSession } from './replay.js';
@@ -275,13 +277,39 @@ export function buildReplSystemPrompt(ctx: {
275
277
  sessionId?: string | undefined;
276
278
  /** 시험·임베디드 호출부용 시임 — 기본은 실제 홈·msg 원장·process.env. */
277
279
  seatBootDeps?: SeatBootDeps | undefined;
280
+ /** Installed skill summaries are injectable for deterministic prompt tests. */
281
+ skillCatalog?: readonly InstalledSkillSummary[] | undefined;
282
+ skillCatalogContextWindow?: number | null | undefined;
278
283
  }): string | undefined {
279
284
  const base = ctx.enabledToolNames === undefined
280
285
  ? undefined
281
286
  : buildAgentSystemPrompt(ctx.cfg, ctx.enabledToolNames);
287
+ const skillToolsEnabled = ctx.enabledToolNames?.includes('skill_exec') === true
288
+ && ctx.enabledToolNames.includes('elanous_skills_list');
289
+ let skillCatalogText = '';
290
+ if (skillToolsEnabled) {
291
+ try {
292
+ const catalog = ctx.skillCatalog ?? (() => {
293
+ const skills = require('../skills/index.js') as typeof import('../skills/index.js');
294
+ return skills.applySkillFilter(skills.getSkillIndex(), ctx.cfg.skills)
295
+ .map(({ name, description }) => ({ name, description }));
296
+ })();
297
+ const built = buildInstalledSkillCatalogMessage(
298
+ catalog,
299
+ ctx.skillCatalogContextWindow ?? resolveModelContextWindow(ctx.cfg.llm.model),
300
+ );
301
+ skillCatalogText = built.message?.content ?? '';
302
+ debug.log('repl.skill-catalog', 'built', {
303
+ skillCount: built.skillCount, estimatedTokens: built.estimatedTokens,
304
+ budgetTokens: built.budgetTokens, mode: built.mode,
305
+ });
306
+ } catch (error) {
307
+ debug.log('repl.skill-catalog', 'failed', { reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
308
+ }
309
+ }
282
310
  const card = buildSeatBootCardText(ctx);
283
- if (card.length === 0) return base;
284
- return base === undefined || base.length === 0 ? card : `${base}\n\n${card}`;
311
+ const parts = [skillCatalogText, base ?? '', card].filter(part => part.length > 0);
312
+ return parts.length > 0 ? parts.join('\n\n') : undefined;
285
313
  }
286
314
 
287
315
  /** 자리 부트 카드 문면(system 메시지 0~1개를 이어 붙인 것). 자리가 아니면 ''. */
@@ -344,6 +372,7 @@ async function runOneTurn(
344
372
  nextTuiDelivery?: { pending: PendingTaskNotification[] },
345
373
  onJsonDelta?: (delta: string) => void,
346
374
  onJsonStatus?: (line: string) => void,
375
+ onJsonReplace?: (fullText: string) => void,
347
376
  ): Promise<{ reply: string; provider: string; model: string | null; durationMs: number; logPath: string | null }> {
348
377
  const startedAt = Date.now();
349
378
  const replyChunks: string[] = [];
@@ -374,6 +403,7 @@ async function runOneTurn(
374
403
  userConfig: cfg,
375
404
  sessionId,
376
405
  userText,
406
+ utteranceSurface: 'tui',
377
407
  systemPrompt,
378
408
  userImages: userImages.length > 0 ? userImages : undefined,
379
409
  ...(process.env.ELANOUS_TEST_FAKE_LLM === '1' && Number.isFinite(Number(process.env.ELANOUS_TEST_FAKE_LLM_IDLE_TIMEOUT_MS))
@@ -387,6 +417,14 @@ async function runOneTurn(
387
417
  }
388
418
  else process.stdout.write(d);
389
419
  },
420
+ onReplaceText: (fullText) => {
421
+ if (jsonOutput) {
422
+ replyChunks.splice(0, replyChunks.length, fullText);
423
+ onJsonReplace?.(fullText);
424
+ } else {
425
+ process.stdout.write(`\n\n [근거 반영된 답변]\n ${fullText}\n`);
426
+ }
427
+ },
390
428
  onStatusLine: (line) => { onJsonStatus?.(line); },
391
429
  tools: replToolSpecs,
392
430
  dispatchTool: tools?.dispatch,
@@ -795,6 +833,9 @@ export async function runRepl(opts: ReplOpts): Promise<number> {
795
833
  process.env.ELANOUS_NEXT_TUI_STREAM === '1' && typeof turn.id === 'string'
796
834
  ? (text) => { process.stdout.write(`${JSON.stringify({ event: 'status', turnId: turn.id, text })}\n`); }
797
835
  : undefined,
836
+ process.env.ELANOUS_NEXT_TUI_STREAM === '1' && typeof turn.id === 'string'
837
+ ? (text) => { process.stdout.write(`${JSON.stringify({ event: 'replace', turnId: turn.id, text })}\n`); }
838
+ : undefined,
798
839
  );
799
840
  } catch (error) {
800
841
  if (!backgroundBridge) throw error;
@@ -1,7 +1,16 @@
1
1
  // Research-only native fanout. The caller supplies Bloom's question ladder;
2
2
  // each axis gets its own direct tool call and evidence stays attributed to it.
3
3
  import type { BloomResearchQuestion, ResearchEvidenceEnvelope } from '../auto-research/question-ladder-contract.js';
4
- import type { WebSearchHit } from '../web-search/provider.js';
4
+ import { getAvailableResearchWebSearchProviders } from '../web-search/index.js';
5
+ import type { WebSearchHit, WebSearchProvider } from '../web-search/provider.js';
6
+ import { debug } from '../debug/log.js';
7
+
8
+ const RESEARCH_SEARCH_ENGINES = ['exa', 'firecrawl'] as const;
9
+ const RESEARCH_WEB_FALLBACK_IDS = ['exa', 'firecrawl'] as const;
10
+ const RESEARCH_EXA_TIMEOUT_MS = 4_500;
11
+ // Leave scheduler/logging headroom under the user-visible 15s aggregate cap.
12
+ export const RESEARCH_SEARCH_BUDGET_MS = 14_500;
13
+ const ENGINE_BREAKER_FAILURE_LIMIT = 2;
5
14
 
6
15
  export interface AxisToolCallPlan {
7
16
  questionId: string;
@@ -25,10 +34,124 @@ export interface AxisSearchResult {
25
34
  hits: AxisSearchHit[];
26
35
  errors: string[];
27
36
  }
28
- export type AxisSearch = (query: string) => Promise<AxisSearchHit[] | AxisSearchResult>;
37
+ export interface AxisSearchContext {
38
+ questionPrompt?: string;
39
+ requestedWindow?: string;
40
+ }
41
+ export type AxisSearch = (query: string, signal?: AbortSignal, context?: AxisSearchContext) => Promise<AxisSearchHit[] | AxisSearchResult>;
29
42
 
30
43
  export interface AxisFanoutDeps {
31
44
  search?: AxisSearch;
45
+ signal?: AbortSignal;
46
+ admitToolCall?: (toolName: 'OmniSearch') => boolean;
47
+ }
48
+
49
+ interface ProviderHealth {
50
+ failures: number;
51
+ open: boolean;
52
+ }
53
+
54
+ /** Build one bounded searcher per research prepass. Research uses only the
55
+ * sequential Exa → Firecrawl fallback; Grok is reserved for explicit X intent.
56
+ * Per-engine serialization lets a timeout open that engine's
57
+ * breaker before queued Bloom axes start. */
58
+ export function createResearchAxisSearcher(
59
+ availableProviders: readonly WebSearchProvider[] = getAvailableResearchWebSearchProviders(),
60
+ now: () => number = Date.now,
61
+ ): AxisSearch {
62
+ const webFallback = RESEARCH_WEB_FALLBACK_IDS.flatMap(id => availableProviders.filter(provider => provider.id === id));
63
+ const allowed = [...webFallback];
64
+ const health = new Map(allowed.map(provider => [provider.id, { failures: 0, open: false }]));
65
+ const deadline = now() + RESEARCH_SEARCH_BUDGET_MS;
66
+ const tails = new Map<string, Promise<void>>();
67
+
68
+ debug.log('research.search', 'provider-preflight', {
69
+ allowed: RESEARCH_SEARCH_ENGINES,
70
+ available: allowed.map(provider => provider.id),
71
+ excluded: availableProviders.filter(provider => !(RESEARCH_SEARCH_ENGINES as readonly string[]).includes(provider.id))
72
+ .map(provider => provider.id),
73
+ budgetMs: RESEARCH_SEARCH_BUDGET_MS,
74
+ });
75
+
76
+ const enqueue = <T>(providerId: string, run: () => Promise<T>): Promise<T> => {
77
+ const previous = tails.get(providerId) ?? Promise.resolve();
78
+ const current = previous.then(run, run);
79
+ tails.set(providerId, current.then(() => undefined, () => undefined));
80
+ return current;
81
+ };
82
+
83
+ return async (query, signal) => {
84
+ const hits: AxisSearchHit[] = [];
85
+ const errors: string[] = [];
86
+ const execute = async (provider: WebSearchProvider): Promise<boolean> => enqueue(provider.id, async () => {
87
+ const state = health.get(provider.id)!;
88
+ if (state.open) return false;
89
+ const remainingMs = deadline - now();
90
+ if (remainingMs <= 0) {
91
+ state.open = true;
92
+ errors.push(`${provider.id}: research search budget exhausted`);
93
+ return false;
94
+ }
95
+ const timeoutMs = provider.id === 'exa'
96
+ ? Math.min(RESEARCH_EXA_TIMEOUT_MS, remainingMs)
97
+ : remainingMs;
98
+ const startedAt = now();
99
+ try {
100
+ const controller = new AbortController();
101
+ const abortFromCaller = (): void => controller.abort(signal?.reason);
102
+ if (signal?.aborted) abortFromCaller();
103
+ else signal?.addEventListener('abort', abortFromCaller, { once: true });
104
+ let timer: ReturnType<typeof setTimeout> | undefined;
105
+ let result;
106
+ try {
107
+ result = await Promise.race([
108
+ provider.search({ query, limit: 5 }, controller.signal),
109
+ new Promise<never>((_, reject) => {
110
+ timer = setTimeout(() => {
111
+ controller.abort();
112
+ reject(new DOMException(`${provider.id} research search timed out after ${timeoutMs}ms`, 'TimeoutError'));
113
+ }, timeoutMs);
114
+ }),
115
+ ]);
116
+ } finally {
117
+ if (timer !== undefined) clearTimeout(timer);
118
+ signal?.removeEventListener('abort', abortFromCaller);
119
+ }
120
+ if (result.hits.length === 0) {
121
+ state.failures += 1;
122
+ if (state.failures >= ENGINE_BREAKER_FAILURE_LIMIT) state.open = true;
123
+ } else {
124
+ state.failures = 0;
125
+ hits.push(...result.hits.map(hit => ({ ...hit, engine: provider.id })));
126
+ }
127
+ debug.log('research.search', 'provider-complete', {
128
+ provider: provider.id, queryLength: query.length, hits: result.hits.length,
129
+ durationMs: now() - startedAt, breakerOpen: state.open,
130
+ });
131
+ return result.hits.length > 0;
132
+ } catch (error) {
133
+ const message = error instanceof Error ? error.message : String(error);
134
+ const timeout = error instanceof Error && /timeout|timed out|abort/i.test(`${error.name} ${error.message}`);
135
+ const quota = /quota|credit|rate.?limit|\b429\b|exhaust/i.test(message);
136
+ state.failures += 1;
137
+ if (timeout || quota || state.failures >= ENGINE_BREAKER_FAILURE_LIMIT) state.open = true;
138
+ errors.push(`${provider.id}: ${message}`);
139
+ debug.log('research.search', 'provider-failed', {
140
+ provider: provider.id, queryLength: query.length, durationMs: now() - startedAt,
141
+ timeout, quota, failures: state.failures, breakerOpen: state.open,
142
+ }, { level: 'warn' });
143
+ return false;
144
+ }
145
+ });
146
+ const runWebFallback = async (): Promise<void> => {
147
+ for (const provider of webFallback) {
148
+ if (!health.get(provider.id)?.open && await execute(provider)) return;
149
+ }
150
+ };
151
+ await runWebFallback();
152
+ if (hits.length === 0 && errors.length === 0) errors.push('no healthy Exa/Firecrawl research provider');
153
+ return { hits, errors };
154
+ };
32
155
  }
33
156
 
34
157
  /** Keep every query attached to the Bloom question that produced it. */
@@ -39,18 +162,6 @@ export function planAxisToolCalls(questions: readonly BloomResearchQuestion[]):
39
162
  .map(query => ({ questionId: question.id, tool: 'OmniSearch' as const, query })));
40
163
  }
41
164
 
42
- async function directOmniSearch(query: string): Promise<AxisSearchResult> {
43
- const { dispatchOmniSearch } = await import('../skills/tools/omni-search.js');
44
- const hits: AxisSearchHit[] = [];
45
- const result = await dispatchOmniSearch({ query }, { onSource: hit => { hits.push(hit); } });
46
- if (Object.keys(result.metadata.perEngine).length === 0) {
47
- throw new Error('no available web-search providers');
48
- }
49
- const errors = Object.entries(result.metadata.perEngine)
50
- .flatMap(([engine, info]) => info.error ? [`${engine}: ${info.error}`] : []);
51
- return { hits, errors };
52
- }
53
-
54
165
  function evidenceFromHit(question: BloomResearchQuestion, hit: AxisSearchHit): ResearchEvidenceEnvelope {
55
166
  const published = hit.publishedAt;
56
167
  const date = published !== undefined && Number.isFinite(published) && published > 0
@@ -89,8 +200,17 @@ export async function fanOutAxisEvidence(
89
200
  if (new Set(questions.map(question => question.id)).size !== questions.length) {
90
201
  throw new Error('research axis question IDs must be unique');
91
202
  }
92
- const search = deps.search ?? directOmniSearch;
93
- const settled = await Promise.allSettled(plan.map(call => search(call.query)));
203
+ const search = deps.search ?? createResearchAxisSearcher();
204
+ const settled = await Promise.allSettled(plan.map(call => {
205
+ if (deps.admitToolCall && !deps.admitToolCall('OmniSearch')) {
206
+ return Promise.resolve({ hits: [], errors: ['research tool budget reached'] } satisfies AxisSearchResult);
207
+ }
208
+ const question = questions.find(candidate => candidate.id === call.questionId)!;
209
+ return search(call.query, deps.signal, {
210
+ questionPrompt: question.prompt,
211
+ requestedWindow: question.requestedWindow,
212
+ });
213
+ }));
94
214
  const axes: AxisEvidenceGroup[] = questions.map(question => ({ questionId: question.id, evidence: [] }));
95
215
  const groups = new Map(axes.map(axis => [axis.questionId, axis]));
96
216
  const byQuestion = new Map(questions.map(question => [question.id, question]));
@@ -34,10 +34,12 @@ const BLOOM_BY_LEVEL = Object.fromEntries(COGNITIVE_BY_LEVEL.map((cognitive, ind
34
34
  return [index + 1, cell];
35
35
  })) as Record<BloomExemplarLevel, Bloom2D>;
36
36
 
37
- // Public source tree intentionally contains only two original exemplars.
37
+ // Public source tree intentionally contains a small set of original exemplars.
38
38
  const PUBLIC_EXEMPLARS: readonly BloomExemplar[] = [
39
39
  { domain: 'finance', level: 4, bloom: BLOOM_BY_LEVEL[4], question: '채권 금리 변화가 만기 구조와 발행자의 차환 위험에 어떤 경로로 연결되는가?' },
40
40
  { domain: 'finance', level: 5, bloom: BLOOM_BY_LEVEL[5], question: '현재 금리 전망을 반박할 수 있는 시장 지표와 그 신뢰도는 무엇인가?' },
41
+ { domain: 'technology', level: 4, bloom: BLOOM_BY_LEVEL[4], question: 'AI 데이터센터의 추론 처리량 증가가 GPU 전력밀도와 냉각 부하, 랙당 계통용량 요구에 어떤 경로로 이어지는가?' },
42
+ { domain: 'technology', level: 5, bloom: BLOOM_BY_LEVEL[5], question: 'AI 데이터센터 전력수요 전망을 반박할 수 있는 GPU 이용률·전력사용효율·계통접속 자료는 무엇이며 각 지표의 한계는 무엇인가?' },
41
43
  ];
42
44
 
43
45
  const DOMAIN_TERMS: Record<BloomExemplarDomain, readonly string[]> = {
@@ -18,6 +18,7 @@ export interface ResearchGapFollowupInput {
18
18
  request: string;
19
19
  questions: readonly BloomResearchQuestion[];
20
20
  evidence: readonly ResearchEvidenceEnvelope[];
21
+ signal?: AbortSignal;
21
22
  /** Optional remaining time supplied by the owning turn; omitted uses the fixed 2-minute cap. */
22
23
  remainingBudgetMs?: number;
23
24
  roundsUsed?: number;
@@ -128,6 +129,7 @@ export async function runGapFollowup(
128
129
  deps: ResearchGapFollowupDeps = {},
129
130
  ): Promise<ResearchGapFollowupResult> {
130
131
  const plan = planGapFollowup(input);
132
+ if (input.signal?.aborted) return { ...plan, followupEvidence: [], discoveryCards: [] };
131
133
  const startedAt = (deps.now ?? Date.now)();
132
134
  const deadline = startedAt + plan.timeBudgetMs;
133
135
  const discover = async (failedQuestions: ReadonlySet<string>): Promise<{ cards: string[]; evidence: ResearchEvidenceEnvelope[] }> => {
@@ -139,6 +141,9 @@ export async function runGapFollowup(
139
141
  const remainingMs = deadline - (deps.now ?? Date.now)();
140
142
  if (remainingMs <= 0) break;
141
143
  const controller = new AbortController();
144
+ const abortFromParent = () => controller.abort(input.signal?.reason);
145
+ input.signal?.addEventListener('abort', abortFromParent, { once: true });
146
+ if (input.signal?.aborted) abortFromParent();
142
147
  const timer = setTimeout(() => controller.abort(new Error('plugin discovery time budget exhausted')),
143
148
  Math.min(10_000, remainingMs));
144
149
  try {
@@ -158,7 +163,10 @@ export async function runGapFollowup(
158
163
  questionId: gap.questionId, reason: error instanceof Error ? error.message.slice(0, 160) : String(error).slice(0, 160),
159
164
  }, { level: 'warn' });
160
165
  }
161
- finally { clearTimeout(timer); }
166
+ finally {
167
+ clearTimeout(timer);
168
+ input.signal?.removeEventListener('abort', abortFromParent);
169
+ }
162
170
  }
163
171
  return { cards, evidence };
164
172
  };
@@ -168,6 +176,9 @@ export async function runGapFollowup(
168
176
  }
169
177
 
170
178
  const controller = new AbortController();
179
+ const abortFromParent = () => controller.abort(input.signal?.reason);
180
+ input.signal?.addEventListener('abort', abortFromParent, { once: true });
181
+ if (input.signal?.aborted) abortFromParent();
171
182
  const timer = setTimeout(() => controller.abort(new Error('research gap follow-up time budget exhausted')),
172
183
  Math.max(1, deadline - (deps.now ?? Date.now)()));
173
184
  try {
@@ -200,6 +211,7 @@ export async function runGapFollowup(
200
211
  return { ...plan, followupEvidence: [...outcomes, ...discovered.evidence], discoveryCards: discovered.cards };
201
212
  } finally {
202
213
  clearTimeout(timer);
214
+ input.signal?.removeEventListener('abort', abortFromParent);
203
215
  }
204
216
  }
205
217
 
@@ -136,15 +136,30 @@ function card(gap: string, candidates: readonly PluginDiscoveryCandidate[], inst
136
136
 
137
137
  /** One bounded, fail-soft discovery attempt for a research capability gap. */
138
138
  export async function discoverResearchPlugin(gapText: string, deps: PluginDiscoveryDeps = {}): Promise<PluginDiscoveryResult> {
139
+ const discoveryStartedAt = performance.now();
140
+ const log = deps.log ?? ((event: string, data: Record<string, unknown>) => debug.log('research.plugin-discovery', event, data));
141
+ const observe = (event: string, data: Record<string, unknown>): void => {
142
+ try { log(event, data); } catch { /* timing must not change discovery behavior */ }
143
+ };
144
+ observe('started', {});
145
+ const finish = (result: PluginDiscoveryResult): PluginDiscoveryResult => {
146
+ observe('completed', {
147
+ elapsedMs: Math.round((performance.now() - discoveryStartedAt) * 10) / 10,
148
+ outcome: result.outcome,
149
+ candidateCount: result.candidates.length,
150
+ installed: result.installed !== undefined,
151
+ });
152
+ return result;
153
+ };
139
154
  const gap = safeGap(gapText);
140
- if (!gap) return { candidates: [], card: 'Plugin discovery skipped: unsafe or empty gap.', outcome: 'invalid-gap' };
155
+ if (!gap) return finish({ candidates: [], card: 'Plugin discovery skipped: unsafe or empty gap.', outcome: 'invalid-gap' });
141
156
  const aborted = (): PluginDiscoveryResult => ({ candidates: [], card: 'Plugin discovery skipped: time budget exhausted.', outcome: 'create-suggestion' });
142
- if (deps.signal?.aborted) return aborted();
143
- const log = deps.log ?? ((event: string, data: Record<string, unknown>) => debug.log('research.plugin-discovery', event, data));
157
+ if (deps.signal?.aborted) return finish(aborted());
144
158
  const threshold = Number.isSafeInteger(deps.githubStarThreshold) && (deps.githubStarThreshold as number) > 0
145
159
  ? deps.githubStarThreshold as number : configuredStarThreshold();
146
160
  const candidates: PluginDiscoveryCandidate[] = [];
147
161
 
162
+ const marketStartedAt = performance.now();
148
163
  try {
149
164
  const market = await (deps.market ?? (() => ensureMarketIndex('elanous')))();
150
165
  // A signed index is the only built-in source with a verifiable install spec.
@@ -159,15 +174,19 @@ export async function discoverResearchPlugin(gapText: string, deps: PluginDiscov
159
174
  installSpec: `${entry.name}@elanous` });
160
175
  }
161
176
  }
162
- } catch { log('market-unavailable', { gap: gap.slice(0, 80) }); }
163
- if (deps.signal?.aborted) return aborted();
177
+ } catch { observe('market-unavailable', { gap: gap.slice(0, 80) }); }
178
+ finally {
179
+ observe('stage-complete', { stage: 'signed-market', elapsedMs: Math.round((performance.now() - marketStartedAt) * 10) / 10 });
180
+ }
181
+ if (deps.signal?.aborted) return finish(aborted());
164
182
 
183
+ const searchStartedAt = performance.now();
165
184
  try {
166
185
  const found = await (deps.search ?? ((query: string, signal?: AbortSignal) => discoverCapability(query,
167
186
  { layer: 'skill', limit: MAX_CANDIDATES, community: false, signal })))(gap, deps.signal);
168
- if (deps.signal?.aborted) return aborted();
187
+ if (deps.signal?.aborted) return finish(aborted());
169
188
  for (const hit of found.slice(0, MAX_CANDIDATES)) {
170
- if (deps.signal?.aborted) return aborted();
189
+ if (deps.signal?.aborted) return finish(aborted());
171
190
  let url: URL;
172
191
  try { url = new URL(hit.url); } catch { continue; }
173
192
  if (url.protocol !== 'https:' || url.username || url.password) continue;
@@ -186,8 +205,11 @@ export async function discoverResearchPlugin(gapText: string, deps: PluginDiscov
186
205
  ? { installSpec: `https://github.com/${repo!.owner}/${repo!.repo}.git#${github.sha}` } : {}),
187
206
  });
188
207
  }
189
- } catch { log('search-unavailable', { gap: gap.slice(0, 80) }); }
190
- if (deps.signal?.aborted) return aborted();
208
+ } catch { observe('search-unavailable', { gap: gap.slice(0, 80) }); }
209
+ finally {
210
+ observe('stage-complete', { stage: 'capability-search', elapsedMs: Math.round((performance.now() - searchStartedAt) * 10) / 10 });
211
+ }
212
+ if (deps.signal?.aborted) return finish(aborted());
191
213
 
192
214
  const deduped = candidates.filter((item, index) => candidates.findIndex(other => other.url === item.url && other.name === item.name) === index)
193
215
  .slice(0, MAX_CANDIDATES);
@@ -197,20 +219,20 @@ export async function discoverResearchPlugin(gapText: string, deps: PluginDiscov
197
219
  if (installable.length === 1) {
198
220
  const candidate = installable[0]!;
199
221
  try {
200
- if (deps.signal?.aborted) return aborted();
222
+ if (deps.signal?.aborted) return finish(aborted());
201
223
  const item = await (deps.install ?? defaultInstall)(candidate.installSpec!);
202
224
  const undo = `eln plugin remove ${item.name}`;
203
225
  installed = { name: item.name, path: item.path,
204
226
  notice: `Reason: missing research capability ${gap}; source: ${candidate.source}; permissions: ${candidate.permissions.join(', ') || 'none declared'}.`, undo };
205
- log('installed', { name: item.name, source: candidate.source, undo });
227
+ observe('installed', { name: item.name, source: candidate.source, undo });
206
228
  } catch (error) {
207
- log('install-refused', { name: candidate.name, reason: error instanceof Error ? error.message.slice(0, 120) : 'unknown' });
229
+ observe('install-refused', { name: candidate.name, reason: error instanceof Error ? error.message.slice(0, 120) : 'unknown' });
208
230
  }
209
231
  }
210
232
  const outcome: PluginDiscoveryResult['outcome'] = installed ? 'installed' : deduped.length ? 'proposed' : 'create-suggestion';
211
233
  const result = { candidates: deduped, installed, card: card(gap, deduped, installed), outcome };
212
- log(outcome, { gap: gap.slice(0, 80), count: deduped.length, installed: installed?.name });
213
- return result;
234
+ observe(outcome, { gap: gap.slice(0, 80), count: deduped.length, installed: installed?.name });
235
+ return finish(result);
214
236
  }
215
237
 
216
238
  /** Re-query through exactly one installed, declared read-only skill with no local-file or shell tools. */
@@ -14,7 +14,7 @@
14
14
  // isolation without standing up the LLM stack.
15
15
 
16
16
  import type { ExternalResearchResult, InvokeResearchOpts } from './types.js';
17
- import type { SkillManifest } from '../skills/runner.js';
17
+ import type { ExecuteSkillOpts, SkillManifest } from '../skills/runner.js';
18
18
  import type { BloomResearchQuestion } from '../auto-research/question-ladder-contract.js';
19
19
  import type { AxisFanoutDeps, AxisFanoutResult } from '../research/axis-fanout.js';
20
20
  import { recordResult } from './store.js';
@@ -76,8 +76,23 @@ export type ResearchInvoker = (
76
76
  args: string,
77
77
  onProgress?: (delta: string) => void,
78
78
  signal?: AbortSignal,
79
+ skillRootDir?: string,
79
80
  ) => Promise<ResearchInvocationOutcome>;
80
81
 
82
+ export type ResearchSkillExecutorForTest = (
83
+ manifest: SkillManifest,
84
+ args: string,
85
+ onProgress?: (delta: string) => void,
86
+ opts?: ExecuteSkillOpts,
87
+ ) => Promise<{ finalResponse: string }>;
88
+
89
+ let researchSkillExecutorForTest: ResearchSkillExecutorForTest | null = null;
90
+
91
+ /** Replace only skill execution in tests; manifest parsing still uses the real selected skill root. */
92
+ export function setResearchSkillExecutorForTest(executor: ResearchSkillExecutorForTest | null): void {
93
+ researchSkillExecutorForTest = executor;
94
+ }
95
+
81
96
  let invoker: ResearchInvoker | null = null;
82
97
 
83
98
  /** Register the production / test invoker. Pass null to revert to
@@ -103,19 +118,21 @@ async function defaultInvoker(
103
118
  args: string,
104
119
  onProgress?: (delta: string) => void,
105
120
  signal?: AbortSignal,
121
+ skillRootDir?: string,
106
122
  ): Promise<ResearchInvocationOutcome> {
107
123
  const { parseSkillMd, executeSkill } = await import('../skills/runner.js');
108
- const manifest = parseSkillMd(skillName);
124
+ const manifest = parseSkillMd(skillName, skillRootDir);
109
125
  if (!manifest) {
110
126
  return {
111
127
  output: '',
112
128
  ok: false,
113
- error: `skill "${skillName}" not found under ~/.claude/skills/`,
129
+ error: `skill "${skillName}" not found under ${skillRootDir ?? '~/.claude/skills'}/`,
114
130
  };
115
131
  }
116
132
  try {
117
133
  // ★ research 격리 — 파일-쓰기 도구 deny 주입(main 트리 오염 차단). Bash·검색도구는 유지.
118
- const result = await executeSkill(withResearchIsolation(manifest), args, (delta) => {
134
+ const run = researchSkillExecutorForTest ?? executeSkill;
135
+ const result = await run(withResearchIsolation(manifest), args, (delta) => {
119
136
  if (onProgress) onProgress(delta);
120
137
  }, { signal });
121
138
  return researchOutcomeFromSkillRun(result);
@@ -138,7 +155,7 @@ export async function invokeResearch(
138
155
  ): Promise<ExternalResearchResult> {
139
156
  const skillName = opts.skill || DEFAULT_SKILL;
140
157
  const startedAt = new Date();
141
- const outcome = await (invoker ?? defaultInvoker)(skillName, topic, opts.onProgress, opts.signal);
158
+ const outcome = await (invoker ?? defaultInvoker)(skillName, topic, opts.onProgress, opts.signal, opts.skillRootDir);
142
159
  const finishedAt = new Date();
143
160
  const result: ExternalResearchResult = {
144
161
  topic,
@@ -28,6 +28,8 @@ export interface ExternalResearchResult {
28
28
  export interface InvokeResearchOpts {
29
29
  /** Skill name override; default 'omni-crawl'. */
30
30
  skill?: string;
31
+ /** Root directory containing the selected catalog entry. */
32
+ skillRootDir?: string;
31
33
  /** Stream progress chunks back to the caller (e.g. dashboard chat
32
34
  * pane) so the user sees activity for long-running invocations. */
33
35
  onProgress?: (delta: string) => void;
@@ -29,8 +29,10 @@ import {
29
29
  renderConcurrentAuthoringNotice,
30
30
  renderLaunchPreflight,
31
31
  renderRepeatedBlockNotice,
32
+ renderSiblingContextLines,
32
33
  siblingTestPath,
33
34
  type AskPreflightDeps,
35
+ type SiblingContextCard,
34
36
  type LaunchPreflightResult,
35
37
  type PriorBlockSample,
36
38
  type RecentAuthoringSample,
@@ -245,6 +247,8 @@ export interface AskLaunchFlowInput {
245
247
  readonly goalType?: import('../self-implement/goal-author.js').GoalType;
246
248
  /** 런 식별자가 이미 있으면 앞단 관측을 그 키로 잇는다. 없으면 관측은 runId 없이 남는다. */
247
249
  readonly runId?: string;
250
+ /** CARD-TARGET-PATHS가 제공한 같은-경로 카드 관측. 발사 판정에는 쓰지 않는다. */
251
+ readonly cardsTouchingPaths?: readonly SiblingContextCard[];
248
252
  /** Explicit harness choice; false is distinct from omission. */
249
253
  readonly selfResolveClarifications?: boolean;
250
254
  }
@@ -258,6 +262,18 @@ export type AskLaunchFlowResult =
258
262
  /** ⑴ 저작에서 접지 예산(AUTHOR-TIMEBOX)을 넘겨 NOT-GROUNDED 로 끝났다 — 발사하지 «않는다». */
259
263
  | { readonly kind: 'stopped-by-timebox'; readonly goalFile: string };
260
264
 
265
+ /**
266
+ * A harness entry can be named inside a request whose operative instruction is
267
+ * explicitly read-only. Require both a read-only marker and a no-write marker;
268
+ * either alone is too broad (for example, implementing a read-only feature).
269
+ */
270
+ function isExplicitReadOnlyNoWriteRequest(text: string): boolean {
271
+ const normalized = text.normalize('NFKC').toLowerCase();
272
+ const readOnly = /(?:read[\s-]*only|readonly|읽기\s*전용|읽기만|파일\s*존재\s*여부만|상태만\s*확인)/u.test(normalized);
273
+ const noWrite = /(?:수정하지\s*마|변경하지\s*마|변경\s*금지|파일을?\s*만들지\s*마|쓰지\s*마|편집하지\s*마|no\s+(?:file\s+)?changes?|do\s+not\s+(?:edit|modify|write|create)|don't\s+(?:edit|modify|write|create)|without\s+(?:editing|modifying|writing)|\bcommit\b.{0,24}(?:하지\s*마|금지)|\bpush\b.{0,24}(?:하지\s*마|금지)|\bpr\b.{0,24}(?:하지\s*마|금지))/u.test(normalized);
274
+ return readOnly && noWrite;
275
+ }
276
+
261
277
  /** ⑴ AUTHOR-TIMEBOX NOT-GROUNDED — 결과 줄을 쓰고 흐름을 끊는 값. */
262
278
  export type AskLaunchFlowTimeboxStop = Extract<AskLaunchFlowResult, { kind: 'stopped-by-timebox' }>;
263
279
 
@@ -858,9 +874,23 @@ export async function runAskLaunchFlow(
858
874
  // ⛔ 이 목록은 «광고»다 — 실제 단계와 어긋나면 조회하는 사람이 없는 단계를 찾거나 있는 단계를 안 찾는다.
859
875
  // ⛔ 분해 단계는 «두 이름 중 하나»로 난다 — 켜졌으면 `…-decomposition`, 꺼졌으면 `…-decomposition-skipped`.
860
876
  // ⭐ 뒤엣것을 빼 두면 조회하는 사람이 「분해 관측이 0건이다」를 보고 «없어졌다»로 읽는다(실은 꺼진 것이다).
861
- steps: ['ask-start', 'ask-pre-preflight', 'ask-authored', 'ask-launching-tree', 'ask-preflight', 'ask-launch-decomposition', 'ask-launch-decomposition-skipped', 'ask-launch'],
877
+ steps: ['ask-start', 'ask-readonly-no-launch', 'ask-pre-preflight', 'ask-authored', 'ask-launching-tree', 'ask-preflight', 'ask-launch-decomposition', 'ask-launch-decomposition-skipped', 'ask-launch'],
862
878
  }, 'info');
863
879
 
880
+ if (isExplicitReadOnlyNoWriteRequest(input.askText)) {
881
+ deps.log('ask-readonly-no-launch', {
882
+ entrance: entrance.id,
883
+ surface: entrance.surface,
884
+ inputSource: input.inputSource,
885
+ runId: input.runId ?? process.env.ELANOUS_RUN_ID ?? null,
886
+ authoringSkipped: true,
887
+ launchSkipped: true,
888
+ completionModeSelected: false,
889
+ }, 'info');
890
+ deps.print('[ask] 읽기 전용·변경 금지 요청으로 판정해 구현·자동 병합을 시작하지 않았습니다. TUI 읽기 도구로 결과만 확인하세요.');
891
+ return { kind: 'stopped-before-authoring' };
892
+ }
893
+
864
894
  const launchPreflight = await runPrePreflight(input, deps);
865
895
  if (launchPreflight === false) return { kind: 'stopped-before-authoring' };
866
896
 
@@ -1036,6 +1066,47 @@ export async function runAskLaunchFlow(
1036
1066
  const preflight = decision.result;
1037
1067
  deps.print(renderLaunchPreflight(preflight, input.forceRequested && decision.shouldLaunch && preflight.blockers.length > 0, 'before-launch'));
1038
1068
  observeLaunchPreflight(deps, 'before-launch', decision);
1069
+ let siblingCards = input.cardsTouchingPaths;
1070
+ let siblingCardsUnmeasured = false;
1071
+ if (siblingCards === undefined && preflight.paths.length > 0) {
1072
+ try {
1073
+ // CARD-TARGET-PATHS is a read-only signal: production entrances use the shared task-card store when
1074
+ // no caller supplied a precomputed snapshot. The launch decision never depends on these matches.
1075
+ const taskHand = await import('../task-agent/task-hand.js');
1076
+ const state = taskHand.readTaskAgentState<{ tasks?: Record<string, import('../task-agent/task-hand.js').TaskCard> }>(taskHand.taskAgentStatePath());
1077
+ siblingCards = taskHand.cardsTouchingPaths(Object.values(state.tasks ?? {}), preflight.paths)
1078
+ .map(({ card, runId, paths }) => ({ cardId: card.id, ...(runId ? { runId } : {}), overlapPaths: paths }));
1079
+ } catch (error) {
1080
+ siblingCardsUnmeasured = true;
1081
+ try { debug.log('self-dev.ask', 'sibling-context-cards-unmeasured', { reason: error instanceof Error ? error.message : String(error) }); }
1082
+ catch { /* supplemental card context remains fail-soft */ }
1083
+ siblingCards = [];
1084
+ }
1085
+ }
1086
+ const siblingContextLines = renderSiblingContextLines(preflight, siblingCards);
1087
+ const recentLanded = preflight.warnings.filter((warning) => warning.kind === 'recent-change' && preflight.paths.includes(warning.name)).length;
1088
+ const siblingContextObservation = {
1089
+ liveRuns: preflight.warnings.filter((warning) => warning.kind === 'live-run').length,
1090
+ openPrs: preflight.warnings.filter((warning) => warning.kind === 'open-pr' || warning.kind === 'sibling-pr').length,
1091
+ recentLanded,
1092
+ unmeasured: siblingCardsUnmeasured || preflight.liveRuns.state === 'unknown' || preflight.openPrs.state === 'unknown' || preflight.recentChanges.state === 'unknown' || preflight.unreadableRuns > 0,
1093
+ };
1094
+ try { debug.log('self-dev.ask', 'sibling-context', siblingContextObservation); }
1095
+ catch { /* sibling context observation must not change launch */ }
1096
+ if (!sanitizeFailed && existsSync(goalFile)) {
1097
+ try {
1098
+ const document = deps.readFile(goalFile);
1099
+ const firstSection = document.search(/^## /mu);
1100
+ const header = siblingContextLines.join('\n');
1101
+ const beforeFirstSection = firstSection < 0 ? document : document.slice(0, firstSection).trimEnd();
1102
+ const contextualized = firstSection < 0
1103
+ ? `${header}\n\n${document}`
1104
+ : `${beforeFirstSection ? `${beforeFirstSection}\n` : ''}${header}\n형제가 같은 파일을 고친다 — 국소 변경만 · 무관 포맷 금지 · 자기 의도를 시험으로 고정\n\n${document.slice(firstSection)}`;
1105
+ (deps.writeGoalDocument ?? deps.writeFile)(goalFile, contextualized);
1106
+ } catch (error) {
1107
+ deps.print(`[ask] 형제 맥락 기록 못 남김 (${error instanceof Error ? error.message : String(error)})`);
1108
+ }
1109
+ }
1039
1110
  // ⛔ 자식 격리 worktree를 만들기 전, 이 흐름을 호출한 작업 트리에서만 센다.
1040
1111
  // 이 관측은 발사 판정의 입력이 아니다 — 의도적으로 옛 판에서 쏘는 경우도 있다.
1041
1112
  const invokerBehindDefaultBranch = deps.measureInvokerBehindDefaultBranch?.()