elanous 0.2.21 → 0.2.23

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 (780) hide show
  1. package/NOTICE +7 -0
  2. package/README.md +32 -22
  3. package/apps/pwa/out/404/index.html +1 -1
  4. package/apps/pwa/out/404.html +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{119fc678.6f591cdb84ca5791.js → 0673cc54.8e2ef1c23e49e190.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{a9f2b54d-40c16bd0efdb04b8.js → 0a09e062-34f747a17d8d8c2e.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/{f8626309.a4e5d362b1d55e59.js → 0e3acd34.d42b2ef87fdf4234.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +77 -0
  9. package/apps/pwa/out/_next/static/chunks/{7175-350f4ce2873bc038.js → 1325-dc3f3c21eb181cb4.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +34 -0
  11. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +24 -0
  12. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/{6767.8e6c5f6e744fcd9f.js → 1505.5826671109111e75.js} +2 -2
  14. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 1669-da843ed73aa301f5.js} +1 -1
  21. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +36 -0
  23. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +122 -0
  24. package/apps/pwa/out/_next/static/chunks/2528.0af5c0e1fad88df6.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +62 -0
  27. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/272-b23d2e92161d11fd.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{7899.597af4a9996c907f.js → 2721.bc9a8f36bd85c07a.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +149 -0
  35. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3961-fbef064c213b2b18.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +309 -0
  39. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{d70879db.c66c56a95a91efc6.js → 4c5e95ce.83e9b16add6fcd8c.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/{6158.566c890adc06a459.js → 5313.1697309c532b9856.js} +2 -2
  52. package/apps/pwa/out/_next/static/chunks/{79b78388.663188133449d707.js → 53746282.1be36038d1abd949.js} +1 -1
  53. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5578.ac963634373b28c6.js +286 -0
  56. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5967-c0a80f8ffe5d4050.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 5974.360f8441eb0ac1ec.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +74 -0
  64. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/6571-926ddf024a6ad5df.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +64 -0
  69. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/{9832.2ab2e818013574c7.js → 6702.ebbd165d5e4a4a14.js} +1 -1
  71. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +32 -0
  73. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +93 -0
  78. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 740.90b31555290236a9.js} +2 -2
  83. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +148 -0
  84. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +226 -0
  85. package/apps/pwa/out/_next/static/chunks/{9070.067c106528ec1ae6.js → 7518.49161e8f5814abdb.js} +1 -1
  86. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +27 -0
  87. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +115 -0
  90. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7905.b230b9d06cb4ad5d.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{8194.484f51e273d9abd2.js → 8264.00e434fbd02e9311.js} +16 -16
  97. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +8 -0
  99. package/apps/pwa/out/_next/static/chunks/{088d8e8a.8069543d082bec12.js → 83cfc5c8.349535543c1548b6.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +23 -0
  101. package/apps/pwa/out/_next/static/chunks/{1948.5f35b39eef222a94.js → 8438.ee7f0df3b3f6fcb4.js} +1 -1
  102. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/{4588.ad3364cb7fb97ada.js → 8532.a86e99acf9b761cb.js} +2 -2
  105. package/apps/pwa/out/_next/static/chunks/8569.b853a8daa8f31d12.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8925-2abfb48af477fb7f.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{88729267.9c6c000157c83f2f.js → 89849432.9eaa2f4c9c010965.js} +3 -3
  110. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +90 -0
  111. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +94 -0
  112. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +41 -0
  114. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +287 -0
  116. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +79 -0
  117. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{3522-1de1319d028ac89c.js → 9502-32c5dc22e8f120f5.js} +3 -3
  120. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +104 -0
  123. package/apps/pwa/out/_next/static/chunks/{7630.2b9a68659053ff4e.js → 9976.8f28864317639fe6.js} +16 -16
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d5341ac96203a983.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-0160ab83c8685a12.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-55c631c032dcc47e.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ad3bd8084048bee4.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-e6784759a2531031.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5c5d0e370f495ef6.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-c325e21543cd48a8.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/{page-111cabe4d1fd69ae.js → page-6168a7c43e6ef8f5.js} +1 -1
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-31417d3604154a6d.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-e9606dc0bdec9305.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-a648bc464c9dc754.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-25bb425afdb27541.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-32d72fdef1afe11a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-d27b794c8ba76bbb.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-2bd9ce9c020d02d4.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-a34096245e63b9f2.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-22170f4f00a15496.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/page-4cc66d22ca4ec502.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83b14c729fcea837.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-6e2781c523dad761.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-26dd415c8f13f341.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-ccdb83ed40c8d724.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-7ad3de8fa06fdea9.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-015c02c4fec4023e.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-6b0ae5b5c42f6d2f.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-786111f30b6f0969.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-48fb31810693c357.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e17cce5e2ed0fee.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-cb154acadb025414.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-16258e956ea93fc2.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-c2dd2b19c93f90ab.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f35dd1dd96ae87.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d3c007c8a0ddd7ee.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7837ce2aacb97b04.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-7350ee93f4fe1033.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-00723458575f2b19.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-745d9b6c015076f8.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-736d33c7414a8a1a.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-119be9a0444d2482.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-fa806c018833e332.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/page-c782041b5f5199ba.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-d431fbdea6ad93dd.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-0c056abff82b9891.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-242d668e4fbf72c4.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-847c3de6ca8a4416.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-81dd0d8ae923ed72.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-74e69ba2c8e970d4.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-70038f41ae7cf931.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/b4e12462-5fab4a813a63dadd.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → ce383d63.d2ede338788ed18e.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/{framework-5c169757551134ed.js → framework-b2763b10dc6b3836.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +1 -0
  184. package/apps/pwa/out/_next/static/css/5619d59e87eddf66.css +1 -0
  185. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +1 -0
  186. package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_buildManifest.js +1 -1
  187. package/apps/pwa/out/approvals/index.html +1 -1
  188. package/apps/pwa/out/approvals/index.txt +23 -23
  189. package/apps/pwa/out/autopilot/index.html +1 -1
  190. package/apps/pwa/out/autopilot/index.txt +23 -23
  191. package/apps/pwa/out/board/index.html +1 -1
  192. package/apps/pwa/out/board/index.txt +23 -23
  193. package/apps/pwa/out/botlab/index.html +1 -1
  194. package/apps/pwa/out/botlab/index.txt +22 -22
  195. package/apps/pwa/out/bots/index.html +1 -1
  196. package/apps/pwa/out/bots/index.txt +22 -22
  197. package/apps/pwa/out/ceo/index.html +1 -1
  198. package/apps/pwa/out/ceo/index.txt +23 -23
  199. package/apps/pwa/out/chat/index.html +1 -1
  200. package/apps/pwa/out/chat/index.txt +22 -22
  201. package/apps/pwa/out/consult/index.html +1 -1
  202. package/apps/pwa/out/consult/index.txt +23 -23
  203. package/apps/pwa/out/control/index.html +1 -1
  204. package/apps/pwa/out/control/index.txt +23 -23
  205. package/apps/pwa/out/decisions/index.html +1 -1
  206. package/apps/pwa/out/decisions/index.txt +22 -22
  207. package/apps/pwa/out/design-check/index.html +1 -1
  208. package/apps/pwa/out/design-check/index.txt +23 -23
  209. package/apps/pwa/out/editor/index.html +1 -1
  210. package/apps/pwa/out/editor/index.txt +24 -23
  211. package/apps/pwa/out/exec/index.html +1 -1
  212. package/apps/pwa/out/exec/index.txt +23 -23
  213. package/apps/pwa/out/field/index.html +1 -1
  214. package/apps/pwa/out/field/index.txt +23 -23
  215. package/apps/pwa/out/healthz +1 -1
  216. package/apps/pwa/out/index.html +1 -1
  217. package/apps/pwa/out/index.txt +22 -22
  218. package/apps/pwa/out/inside/index.html +1 -1
  219. package/apps/pwa/out/inside/index.txt +22 -22
  220. package/apps/pwa/out/intake/index.html +1 -1
  221. package/apps/pwa/out/intake/index.txt +23 -23
  222. package/apps/pwa/out/live/index.html +1 -1
  223. package/apps/pwa/out/live/index.txt +23 -23
  224. package/apps/pwa/out/live-run/index.html +1 -1
  225. package/apps/pwa/out/live-run/index.txt +24 -23
  226. package/apps/pwa/out/loops/index.html +1 -1
  227. package/apps/pwa/out/loops/index.txt +22 -22
  228. package/apps/pwa/out/market/index.html +1 -1
  229. package/apps/pwa/out/market/index.txt +22 -22
  230. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  231. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  232. package/apps/pwa/out/morning/index.html +1 -1
  233. package/apps/pwa/out/morning/index.txt +23 -23
  234. package/apps/pwa/out/observatory/index.html +1 -1
  235. package/apps/pwa/out/observatory/index.txt +23 -23
  236. package/apps/pwa/out/ops/checklist/index.html +1 -1
  237. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  238. package/apps/pwa/out/ops/release/index.html +1 -1
  239. package/apps/pwa/out/ops/release/index.txt +22 -22
  240. package/apps/pwa/out/ops/seats/index.html +1 -1
  241. package/apps/pwa/out/ops/seats/index.txt +22 -22
  242. package/apps/pwa/out/outputs/index.html +1 -1
  243. package/apps/pwa/out/outputs/index.txt +22 -22
  244. package/apps/pwa/out/reflection/index.html +1 -1
  245. package/apps/pwa/out/reflection/index.txt +23 -23
  246. package/apps/pwa/out/scheduler/index.html +1 -1
  247. package/apps/pwa/out/scheduler/index.txt +23 -23
  248. package/apps/pwa/out/sessions/index.html +1 -1
  249. package/apps/pwa/out/sessions/index.txt +22 -22
  250. package/apps/pwa/out/settings/devices/index.html +1 -1
  251. package/apps/pwa/out/settings/devices/index.txt +23 -23
  252. package/apps/pwa/out/settings/index.html +1 -1
  253. package/apps/pwa/out/settings/index.txt +23 -23
  254. package/apps/pwa/out/setup/done/index.html +1 -1
  255. package/apps/pwa/out/setup/done/index.txt +23 -23
  256. package/apps/pwa/out/setup/index.html +1 -1
  257. package/apps/pwa/out/setup/index.txt +23 -23
  258. package/apps/pwa/out/share/index.html +1 -1
  259. package/apps/pwa/out/share/index.txt +23 -23
  260. package/apps/pwa/out/showroom/index.html +1 -1
  261. package/apps/pwa/out/showroom/index.txt +22 -22
  262. package/apps/pwa/out/tasks/index.html +1 -1
  263. package/apps/pwa/out/tasks/index.txt +23 -23
  264. package/apps/pwa/out/term/index.html +1 -1
  265. package/apps/pwa/out/term/index.txt +23 -23
  266. package/apps/pwa/out/today/index.html +1 -1
  267. package/apps/pwa/out/today/index.txt +23 -23
  268. package/apps/pwa/out/trace/index.html +1 -1
  269. package/apps/pwa/out/trace/index.txt +23 -23
  270. package/apps/pwa/out/vault/index.html +1 -1
  271. package/apps/pwa/out/vault/index.txt +23 -23
  272. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  273. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  274. package/apps/pwa/out/workflows/index.html +1 -1
  275. package/apps/pwa/out/workflows/index.txt +23 -23
  276. package/apps/pwa/out/workspace/index.html +1 -1
  277. package/apps/pwa/out/workspace/index.txt +23 -23
  278. package/apps/pwa/out/worktrees/index.html +1 -1
  279. package/apps/pwa/out/worktrees/index.txt +23 -23
  280. package/catalog/models/anthropic/claude-haiku-5-5.yaml +32 -0
  281. package/catalog/models/anthropic/claude-opus-5-5.yaml +5 -0
  282. package/catalog/models/anthropic/claude-sonnet-5-5.yaml +31 -0
  283. package/catalog/models/anthropic/claude-sonnet-5.yaml +8 -2
  284. package/catalog/models/openai/gpt-6-astra.yaml +6 -0
  285. package/catalog/models/openai/gpt-6-luna.yaml +6 -0
  286. package/catalog/models/openai/gpt-6-sol.yaml +6 -0
  287. package/graphs/catalog/catalog.yaml +1 -1
  288. package/graphs/drafts/recipes.yaml +2 -2
  289. package/graphs/log-horizon/log-horizon-watch.yaml +25 -0
  290. package/graphs/log-horizon/recipes.yaml +3 -0
  291. package/graphs/release/recipes.yaml +1 -1
  292. package/graphs/release/release-loop.yaml +6 -2
  293. package/graphs/release-rehearsal/recipes.yaml +12 -0
  294. package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
  295. package/graphs/test-diet/recipes.yaml +3 -0
  296. package/graphs/test-diet/test-diet.yaml +3 -1
  297. package/package.json +4 -1
  298. package/scripts/bench-report.ts +82 -3
  299. package/scripts/ci-typecheck-changed.ts +10 -1
  300. package/scripts/f-session-monitor.ts +69 -0
  301. package/scripts/hq/hq-fence-wrapper.sh +148 -0
  302. package/scripts/hq/standby-snapshot.ts +7 -3
  303. package/scripts/knowledge-compress.ts +11 -0
  304. package/scripts/lib/typecheck-ratchet.ts +51 -0
  305. package/scripts/nightly-docops.ts +90 -3
  306. package/scripts/openai-relay-server.ts +5 -1
  307. package/scripts/release-loop/docs-node.ts +258 -43
  308. package/scripts/release-loop/gate-method.ts +59 -0
  309. package/scripts/release-loop/gate-node.ts +73 -7
  310. package/scripts/release-loop/gate-wall.ts +208 -0
  311. package/scripts/release-loop/known-issues-node.ts +53 -8
  312. package/scripts/release-loop/publish-at.ts +14 -0
  313. package/scripts/release-loop/publish-node.ts +17 -2
  314. package/scripts/release-loop/resume-release.ts +34 -4
  315. package/scripts/release-loop/resume.ts +53 -0
  316. package/scripts/release-loop/shard-plan.ts +3 -11
  317. package/scripts/release-loop/tui-node-checks.ts +22 -0
  318. package/scripts/release-loop/unattended-release.ts +8 -1
  319. package/scripts/research-coo-admin-dates.ts +39 -0
  320. package/scripts/rhythm/daily.ts +51 -2
  321. package/scripts/rhythm/weekly.ts +3 -2
  322. package/scripts/skills/public-check.ts +7 -2
  323. package/scripts/smart-merge/resync-shadow.ts +5 -3
  324. package/scripts/test-diet/lib.ts +81 -1
  325. package/scripts/test-diet/node.ts +48 -2
  326. package/scripts/tsc-main-safety-net.ts +189 -0
  327. package/scripts/usage-rollup.ts +8 -4
  328. package/scripts/verify-coo-admin-evidence.ts +83 -0
  329. package/src/acp/client.ts +4 -2
  330. package/src/acp/codex-plugins.ts +48 -6
  331. package/src/agent/monad-agent-turn.ts +67 -5
  332. package/src/agent/run-context.ts +14 -0
  333. package/src/agent/tool-profile.ts +28 -2
  334. package/src/agent-env/profile.ts +25 -5
  335. package/src/agent-mission/acp-judge.ts +8 -2
  336. package/src/agent-mission/capabilities-cli.ts +16 -1
  337. package/src/agent-mission/driver.ts +27 -13
  338. package/src/agent-mission/pr-review-watch.ts +6 -2
  339. package/src/agent-mission/review-loop.ts +33 -5
  340. package/src/agent-mission/supervisor-metrics.ts +17 -2
  341. package/src/agent-substrate/acp-reviewer.ts +25 -9
  342. package/src/agent-substrate/pr-reviewer.ts +175 -32
  343. package/src/agent-substrate/review-intent.ts +106 -5
  344. package/src/agent-substrate/self-review-cli.ts +111 -16
  345. package/src/agent-substrate/shard-boundary-intent.ts +92 -26
  346. package/src/ask-user-question/pending-questions.ts +8 -2
  347. package/src/autopilot/build/llm-conflict-merge.ts +238 -20
  348. package/src/autopilot/codebase-grounding.ts +44 -0
  349. package/src/autopilot/llm-control-brain.ts +13 -1
  350. package/src/autopilot/mission-codebase-gate.ts +8 -77
  351. package/src/autopilot/pr-manager.ts +30 -11
  352. package/src/away/release-watch.ts +47 -8
  353. package/src/boot/acp-server.ts +4 -7
  354. package/src/boot/acp-socket-path.ts +7 -0
  355. package/src/briefing/brief-items.ts +123 -22
  356. package/src/chat/index.ts +13 -3
  357. package/src/cli/agent-cli.ts +20 -0
  358. package/src/cli/brief-cli.ts +46 -22
  359. package/src/cli/cli-user-error.ts +9 -2
  360. package/src/cli/config-classify.ts +83 -0
  361. package/src/cli/control-cli.ts +14 -0
  362. package/src/cli/decisions-cli.ts +26 -16
  363. package/src/cli/log-event-names.ts +3 -0
  364. package/src/cli/logs-cli.ts +1 -0
  365. package/src/cli/logs-model-input.ts +1 -1
  366. package/src/cli/mcp-login.ts +111 -37
  367. package/src/cli/plugin-cli.ts +21 -1
  368. package/src/cli/pod-cli.ts +26 -0
  369. package/src/cli/pr-cli.ts +94 -9
  370. package/src/cli/pr-land-overlap-evidence.ts +131 -0
  371. package/src/cli/release-cli.ts +74 -15
  372. package/src/cli/self-update.ts +173 -10
  373. package/src/cli/skills-cli.ts +12 -3
  374. package/src/cli/tasks-cli.ts +241 -28
  375. package/src/connectors/types.ts +6 -6
  376. package/src/context-bus/context-first.ts +51 -2
  377. package/src/context-bus/context-now-surfaces.ts +29 -0
  378. package/src/context-bus/coord-events.ts +32 -4
  379. package/src/context-bus/long-term-memory.ts +26 -7
  380. package/src/context-bus/nightly-condense.ts +170 -21
  381. package/src/control/control-status.ts +87 -0
  382. package/src/control-plane/light-member.ts +5 -3
  383. package/src/control-plane/member.ts +172 -7
  384. package/src/core-turn/run-goal-loop.ts +108 -3
  385. package/src/dashboard/chat-fold.ts +20 -0
  386. package/src/dashboard/first-screen-band.ts +151 -1
  387. package/src/dashboard/index.ts +27 -5
  388. package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -3
  389. package/src/dashboard/stale-install-check.ts +13 -2
  390. package/src/dashboard/turn-stream-formatter.ts +25 -0
  391. package/src/debug/log-diet.ts +159 -0
  392. package/src/debug/log.ts +52 -17
  393. package/src/decisions/decision-cards.ts +20 -1
  394. package/src/decisions/decision-ledger.ts +11 -8
  395. package/src/decisions/web-push-decision-cards.ts +19 -3
  396. package/src/discord-self-message.ts +2 -2
  397. package/src/display/coordinator.ts +25 -2
  398. package/src/domains/coo-admin-dates.evidence.json +876 -0
  399. package/src/domains/coo-admin-tool.ts +75 -14
  400. package/src/domains/cron-match.ts +1 -0
  401. package/src/domains/ops-status.ts +53 -0
  402. package/src/domains/outbound-alert.ts +41 -7
  403. package/src/domains/release-tool.ts +119 -10
  404. package/src/domains/schedule-registry.ts +10 -7
  405. package/src/domains/schedule-runner.ts +1 -0
  406. package/src/elanous-config-dir.ts +2 -2
  407. package/src/elanous-daemon.ts +3 -3
  408. package/src/exec-requests/planner.ts +6 -0
  409. package/src/execution-loop/launch-gate.ts +1 -1
  410. package/src/expression/i18n/messages.en.ts +5 -0
  411. package/src/expression/i18n/messages.ja.ts +5 -0
  412. package/src/expression/i18n/messages.ko.ts +5 -0
  413. package/src/expression/i18n/messages.zh.ts +5 -0
  414. package/src/expression/i18n/types.ts +8 -0
  415. package/src/github/pr-labels.ts +1 -0
  416. package/src/graph-kinds/registry.ts +6 -6
  417. package/src/graph-runner/graph-cli.ts +34 -2
  418. package/src/graph-runner/graph-run-api.ts +7 -0
  419. package/src/graph-runner/graph-tick.ts +73 -12
  420. package/src/graph-runner/runner.ts +94 -13
  421. package/src/graph-unify/wf-to-graph.ts +79 -0
  422. package/src/graph-wizard/generate.ts +34 -2
  423. package/src/graph-wizard/steps.ts +13 -0
  424. package/src/harness/dispatch-backpressure.ts +259 -0
  425. package/src/harness/harness-cli-command.ts +227 -50
  426. package/src/harness/harness-queue.ts +58 -14
  427. package/src/harness/harness-seams.ts +2 -20
  428. package/src/harness/harness-substrate-default.ts +72 -1
  429. package/src/harness/launch-advice.ts +23 -0
  430. package/src/harness/nested-elanous-policy.ts +4 -2
  431. package/src/hq/fence-wrapper.ts +7 -0
  432. package/src/hq/hq.ts +33 -2
  433. package/src/hq/lease.ts +13 -0
  434. package/src/hq/seats.ts +114 -18
  435. package/src/index.ts +199 -71
  436. package/src/intake-plane/collect-github.ts +19 -1
  437. package/src/intake-plane/digest.ts +45 -20
  438. package/src/intake-plane/lens.ts +36 -8
  439. package/src/intelligence-map/model-alias.ts +6 -0
  440. package/src/intelligence-map/model-catalog.ts +41 -0
  441. package/src/knowledge/conclusion-compress.ts +93 -0
  442. package/src/knowledge/kgs/pack.ts +5 -2
  443. package/src/knowledge/kgs/sqlite-store.ts +15 -0
  444. package/src/knowledge/know-find.ts +9 -2
  445. package/src/knowledge/query.ts +20 -0
  446. package/src/knowledge/tools/knowledge-query.ts +20 -2
  447. package/src/knowledge/write.ts +234 -2
  448. package/src/llm/bedrock-provider.ts +175 -0
  449. package/src/llm/bedrock.ts +345 -0
  450. package/src/llm/provider-credentials.ts +3 -1
  451. package/src/llm.ts +332 -51
  452. package/src/loops/budget.ts +150 -0
  453. package/src/loops/neighbor-runtime.ts +88 -0
  454. package/src/loops/orchestrator/author-depth.ts +29 -11
  455. package/src/loops/orchestrator/overlap.ts +7 -1
  456. package/src/loops/orchestrator/resync-shadow.ts +1 -1
  457. package/src/loops/orchestrator/seat-share.ts +6 -49
  458. package/src/loops/orchestrator/tick.ts +35 -2
  459. package/src/loops/orchestrator/traffic.ts +6 -80
  460. package/src/loops/registry.ts +5 -0
  461. package/src/market/publish.ts +17 -1
  462. package/src/market/signed-index.ts +42 -0
  463. package/src/maturity/feature-maturity.ts +2 -1
  464. package/src/mcp/mcp-oauth.ts +136 -17
  465. package/src/model-tier/llm-tier-map.ts +48 -4
  466. package/src/models/prompts.ts +22 -1
  467. package/src/mss/logging/horizon-watch.ts +168 -0
  468. package/src/mss/logging/log-store.ts +204 -15
  469. package/src/mss/logging/redaction.ts +17 -0
  470. package/src/native-tool-catalog.ts +1 -1
  471. package/src/nexus/api/consult-requests.ts +7 -10
  472. package/src/nexus/api/discord-trigger-bot.ts +6 -3
  473. package/src/nexus/api/draft-metrics.ts +22 -8
  474. package/src/nexus/api/error-reports.ts +30 -8
  475. package/src/nexus/api/graph-peer-edit.ts +77 -0
  476. package/src/nexus/api/graph-wizard-api.ts +9 -1
  477. package/src/nexus/api/graphs-api.ts +145 -7
  478. package/src/nexus/api/http-server.ts +101 -8
  479. package/src/nexus/api/loop-resources.ts +42 -0
  480. package/src/nexus/api/outbound-report.ts +8 -3
  481. package/src/nexus/api/plugins-market.ts +24 -0
  482. package/src/nexus/api/telegram-trigger-bot.ts +6 -3
  483. package/src/nexus/index.ts +13 -2
  484. package/src/nexus/outbound/format.ts +2 -0
  485. package/src/nexus/outbound/router.ts +198 -13
  486. package/src/oauth/claude-pty-maturity.ts +24 -0
  487. package/src/oauth/codex-account-rotation.ts +16 -18
  488. package/src/oauth/codex-account-store.ts +134 -5
  489. package/src/oauth/fallback-chain.ts +50 -15
  490. package/src/onboarding.ts +2 -1
  491. package/src/plugins/adapters/claude-package.ts +4 -12
  492. package/src/plugins/core/capability-policy.ts +141 -0
  493. package/src/plugins/core/host.ts +21 -8
  494. package/src/plugins/core/manifest.ts +19 -2
  495. package/src/plugins/core/trust-store.ts +15 -0
  496. package/src/plugins/core/types.ts +12 -0
  497. package/src/plugins/install/market-fetch.ts +68 -16
  498. package/src/plugins/install/plugin-install.ts +187 -16
  499. package/src/plugins/maker/market-bundle.ts +9 -0
  500. package/src/plugins/maker/plugin-maker.ts +32 -21
  501. package/src/plugins/maker/wizard-generate.ts +87 -9
  502. package/src/policy/llm-policy.ts +24 -6
  503. package/src/process/pid-liveness.ts +1 -1
  504. package/src/prompt-cache/openai.ts +10 -6
  505. package/src/prompt-cache/openrouter.ts +94 -0
  506. package/src/prompt-enhance/enhance.ts +46 -5
  507. package/src/prompt-library/family-prompt-coverage.ts +1 -0
  508. package/src/prompt-library/universal-preamble.ts +2 -2
  509. package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
  510. package/src/registry/loader.ts +6 -1
  511. package/src/release-loop/checklist-board.ts +27 -0
  512. package/src/release-loop/checklist.ts +62 -9
  513. package/src/release-loop/feature-store.ts +3 -0
  514. package/src/release-loop/gate-shards.ts +48 -4
  515. package/src/release-loop/landed-to-green.ts +81 -0
  516. package/src/release-loop/light-rc.ts +11 -1
  517. package/src/release-loop/merged-pr-checklist.ts +10 -0
  518. package/src/release-loop/placement.ts +91 -22
  519. package/src/release-loop/rehearsal.ts +317 -0
  520. package/src/release-loop/release-schedule.ts +13 -1
  521. package/src/release-loop/rubric-types.ts +1 -0
  522. package/src/release-loop/rubric.ts +2 -2
  523. package/src/retro/daily.ts +23 -9
  524. package/src/seat-address/seat-address.ts +1 -0
  525. package/src/seat-loop/seat-loop.ts +208 -21
  526. package/src/seat-loop/seat-report.ts +29 -1
  527. package/src/seat-loop/traffic-signal.ts +44 -0
  528. package/src/self-dev/ask-launch-flow.ts +2 -2
  529. package/src/self-dev/dev-cli.ts +157 -11
  530. package/src/self-dev/dev-pipeline.ts +18 -1
  531. package/src/self-dev/draft-residue.ts +463 -0
  532. package/src/self-dev/draft-sweep.ts +195 -17
  533. package/src/self-dev/draft-triage-rules.ts +27 -1
  534. package/src/self-dev/launch-preflight-text.ts +549 -0
  535. package/src/self-dev/launch-preflight.ts +10 -545
  536. package/src/self-dev/orchestrate-cli.ts +57 -2
  537. package/src/self-dev/orchestrate-summary-line.ts +13 -0
  538. package/src/self-dev/orchestrate.ts +9 -133
  539. package/src/self-dev/review-provider-fallback.ts +179 -0
  540. package/src/self-dev/run-store.ts +1 -3
  541. package/src/self-dev/run-supervisor.ts +8 -23
  542. package/src/self-dev/run-types.ts +178 -0
  543. package/src/self-dev/shard-aggregate.ts +61 -13
  544. package/src/self-dev/shard-plan.ts +5 -1
  545. package/src/self-dev/shard-run.ts +23 -5
  546. package/src/self-dev/supervisor-verdict-edges.ts +2 -4
  547. package/src/self-implement/blocked-draft-policy.ts +3 -19
  548. package/src/self-implement/draft-on-stop-mode.ts +18 -0
  549. package/src/self-implement/follow-up-goals.ts +114 -38
  550. package/src/self-implement/gate-baseline-reap.ts +157 -0
  551. package/src/self-implement/gate-baseline.ts +78 -16
  552. package/src/self-implement/gate-cli.ts +12 -2
  553. package/src/self-implement/gate-remote.ts +17 -6
  554. package/src/self-implement/goal-author.ts +24 -4
  555. package/src/self-implement/goal-digest.ts +19 -0
  556. package/src/self-implement/graph-overlay-condition.ts +4 -0
  557. package/src/self-implement/harness-policy-gates.ts +7 -5
  558. package/src/self-implement/headless-elanous-driver.ts +11 -9
  559. package/src/self-implement/host-regate.ts +148 -43
  560. package/src/self-implement/l8-merge-queue.ts +147 -13
  561. package/src/self-implement/merge-train.ts +131 -0
  562. package/src/self-implement/off-diff-evidence.ts +9 -0
  563. package/src/self-implement/orchestrator.ts +201 -43
  564. package/src/self-implement/review-finding-recurrence.ts +28 -0
  565. package/src/self-implement/rework-policy.ts +2 -1
  566. package/src/self-implement/round-summary-card.ts +63 -0
  567. package/src/self-implement/run-ledger.ts +4 -3
  568. package/src/self-implement/run-step-projection.ts +147 -0
  569. package/src/self-implement/run-stop.ts +1 -1
  570. package/src/self-implement/seams.ts +41 -6
  571. package/src/self-implement/self-implement-cli.ts +6 -0
  572. package/src/self-implement/train-gate-remote.ts +158 -0
  573. package/src/session-runtime/index.ts +10 -1
  574. package/src/session-runtime/retry-api.ts +11 -1
  575. package/src/shell-env-bootstrap.ts +19 -4
  576. package/src/skills/gift-install.ts +119 -0
  577. package/src/skills/runner.ts +59 -2
  578. package/src/skills/skill-feedback.ts +31 -1
  579. package/src/skills/skill-tier.ts +1 -0
  580. package/src/smart-wizard/capability-index.ts +231 -0
  581. package/src/smart-wizard/rung.ts +74 -0
  582. package/src/steward/launch.ts +20 -9
  583. package/src/steward/triage.ts +29 -10
  584. package/src/storage/file-lock.ts +40 -4
  585. package/src/task-agent/actions.ts +4 -0
  586. package/src/task-agent/card-evidence.ts +59 -13
  587. package/src/task-agent/completion-evidence.ts +31 -3
  588. package/src/task-agent/cover.ts +61 -0
  589. package/src/task-agent/judge.ts +4 -3
  590. package/src/task-agent/land-worktree.ts +201 -0
  591. package/src/task-agent/live-move-history.ts +133 -0
  592. package/src/task-agent/live-moves.ts +222 -12
  593. package/src/task-agent/parent-host.ts +117 -8
  594. package/src/task-agent/rejudge-on-head.ts +297 -0
  595. package/src/task-agent/review-result-capture.ts +218 -0
  596. package/src/task-agent/shadow.ts +118 -7
  597. package/src/task-agent/task-hand.ts +138 -11
  598. package/src/task-orchestrator/surfaces/pod-child-providers.ts +29 -0
  599. package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
  600. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +16 -2
  601. package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
  602. package/src/task-orchestrator/surfaces/pod-lease.ts +93 -12
  603. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +25 -2
  604. package/src/task-orchestrator/surfaces/pod-pool.ts +203 -28
  605. package/src/task-orchestrator/surfaces/self-implement-pod.ts +259 -36
  606. package/src/task-orchestrator/surfaces/self-implement.ts +11 -0
  607. package/src/telegram-commands.ts +8 -0
  608. package/src/telegram-project-command.ts +6 -0
  609. package/src/telegram-service.ts +5 -1
  610. package/src/telegram.ts +17 -4
  611. package/src/time/format.ts +13 -4
  612. package/src/tool-runtime/goal-author-runtime.ts +1 -0
  613. package/src/tool-runtime/self-cognition-catalog.ts +23 -0
  614. package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
  615. package/src/typecheck-ratchet.ts +2 -1
  616. package/src/user-config.ts +167 -28
  617. package/src/ux-sim/slash-menu-frames.ts +168 -0
  618. package/src/version/packed-revision.json +1 -1
  619. package/src/web-terminal/preview-tap-registry.ts +5 -2
  620. package/src/workflow-runtime/executor.ts +24 -2
  621. package/src/workflow-runtime/triggers/registry.ts +27 -0
  622. package/src/workflow-runtime/triggers/schedule-source.ts +30 -3
  623. package/src/workflow-runtime/triggers/scheduler.ts +1 -0
  624. package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
  625. package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
  626. package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
  627. package/apps/pwa/out/_next/static/chunks/1307-c97eba9fb72a9a5e.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
  629. package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
  630. package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
  631. package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
  633. package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
  638. package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
  647. package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
  648. package/apps/pwa/out/_next/static/chunks/2489-ff55a35b202c0f94.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
  661. package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
  669. package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
  674. package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
  676. package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
  680. package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
  684. package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/5977-59fedea50d13c762.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
  689. package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
  690. package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
  692. package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
  693. package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
  701. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
  704. package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
  714. package/apps/pwa/out/_next/static/chunks/8857-f1762140ef9a96b1.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
  717. package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/9247-7581825d511a64c0.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
  721. package/apps/pwa/out/_next/static/chunks/9497-b0e758d1cd4ae8d7.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
  723. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/approvals/page-937c92292a4ab4f0.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d781be3e3a9cfd74.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/board/page-b0a80997903852d8.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/botlab/page-2b1263165630d9c8.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea998f7f5d156bea.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/ceo/page-33c328b64ca508f8.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/chat/page-e2d6bed48ac20120.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/control/page-544dd4bd4847eeb7.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/decisions/page-3ee191319bf97d87.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e4bcb2c503dab04b.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/editor/page-300897dcbbd5ed76.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/exec/page-a449f1ed472b81c2.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/field/page-9045094d6d3b5cd0.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/inside/page-c06673596849ef45.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/intake/page-103fa3191c1b2e08.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/layout-9f81233f29dcd409.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/live/page-be8b4615c919e36c.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/live-run/page-c685b104e0dfa609.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/loops/page-8d693331cfbb6add.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/market/page-cef4f30a4c22fae1.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66ea1b54fc83fa15.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/morning/page-7a12f61be4a579d1.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/not-found-c85b0589591a99c9.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/observatory/page-725a4da02dd129eb.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8cc707bd09a497d9.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-90b55be1f15ce0e8.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cb16606e08be65db.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/outputs/page-16dc64b74ed6a40a.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/page-21bec4afeb2f0917.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/reflection/page-dc39ee7a36d26385.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-84ae759f76053672.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/sessions/page-3db58ddb61fe2be9.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c5315e30f3528dc4.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/settings/page-2fe368efb6de3b6a.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8d04132dd0ac5e10.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/setup/page-f23484de467c9ea3.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/share/page-c69762987b751174.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/showroom/page-5456692bda39aafb.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d75f7cd65845ce98.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/term/page-5603f5e568b25ce3.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/today/page-d2cc0f4e89f42028.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/trace/page-a6eb73b8a4840f1c.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/vault/page-c0a3f4d10edb83fa.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6c0b88068c143f15.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/workflows/page-7f8d7fcdf058a845.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/workspace/page-22163556cd38bc88.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-141436fd26dd56fc.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
  779. package/apps/pwa/out/_next/static/css/e81df11490b4413b.css +0 -1
  780. /package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_ssgManifest.js +0 -0
@@ -1,8 +1,26 @@
1
+ import { spawnSync } from 'node:child_process';
1
2
  import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
3
  import { homedir } from 'node:os';
3
4
  import { join } from 'node:path';
4
5
 
5
- type Agent = 'claude' | 'codex' | 'grok';
6
+ type Agent = 'claude' | 'codex' | 'grok' | 'gemini';
7
+
8
+ function versionOf(binary: string): string | null {
9
+ const result = spawnSync(binary, ['--version'], { encoding: 'utf8', timeout: 3000 });
10
+ const line = `${result.stdout ?? ''}${result.stderr ?? ''}`.trim().split(/\r?\n/, 1)[0];
11
+ return result.status === 0 && line && /^[\w .+()-]{1,100}$/.test(line) ? line : null;
12
+ }
13
+
14
+ // Plugin and marketplace keys are `name@marketplace`; check each part instead of redacting every scoped name.
15
+ function safePluginName(name: string): string {
16
+ const parts = name.split('@');
17
+ return parts.length <= 2 && parts.every(part => part !== '' && safeIdentifier(part) === part) ? name : '<redacted>';
18
+ }
19
+
20
+ function safeNames(path: string): string[] | '«없음»' {
21
+ return !existsSync(path) ? '«없음»' : readdirSync(path, { withFileTypes: true })
22
+ .filter(entry => entry.isDirectory()).map(entry => safeIdentifier(entry.name) ?? '<redacted>').sort();
23
+ }
6
24
  type Presence = 'present' | '«없음»';
7
25
 
8
26
  function present(path: string): Presence {
@@ -54,7 +72,7 @@ function collectMcp(
54
72
  servers: unknown,
55
73
  source: McpSource,
56
74
  ): void {
57
- for (const [name, server] of Object.entries(record(servers))) into[name] = mcpEntry(server, source);
75
+ for (const [name, server] of Object.entries(record(servers))) into[safeIdentifier(name) ?? '<redacted>'] = mcpEntry(server, source);
58
76
  }
59
77
 
60
78
  function hookGroups(hooks: Record<string, unknown>): Record<string, unknown[]> {
@@ -86,6 +104,7 @@ function claude(home: string): Record<string, unknown> {
86
104
  const skillsDir = join(dir, 'skills');
87
105
  const team = join(home, '.teamclaude');
88
106
  const teamManifest = json(join(team, 'package.json'));
107
+ const marketplaces = record(data.extraKnownMarketplaces);
89
108
  const teamVersion = typeof teamManifest?.version === 'string' && /^\d+\.\d+\.\d+(?:[-+.][a-zA-Z0-9.-]+)?$/.test(teamManifest.version)
90
109
  ? teamManifest.version : undefined;
91
110
  const mcp: Record<string, unknown> = {};
@@ -98,6 +117,7 @@ function claude(home: string): Record<string, unknown> {
98
117
  }
99
118
  const mcpFilesMissing = settings === null && user === null;
100
119
  return {
120
+ version: versionOf('claude'),
101
121
  settings: settings === null ? '«없음»' : 'present',
102
122
  userConfig: user === null ? '«없음»' : 'present',
103
123
  permissionMode: safeIdentifier(record(data.permissions).defaultMode),
@@ -106,10 +126,10 @@ function claude(home: string): Record<string, unknown> {
106
126
  command: safeCommand(statusLine.command) ?? null,
107
127
  },
108
128
  hooks: settings === null ? '«없음»' : hookGroups(hooks),
109
- enabledPlugins: settings === null ? '«없음»' : Object.fromEntries(Object.entries(plugins).map(([name, enabled]) => [name, enabled === true])),
129
+ enabledPlugins: settings === null ? '«없음»' : Object.fromEntries(Object.entries(plugins).map(([name, enabled]) => [safePluginName(name), enabled === true])),
130
+ marketplaces: settings === null ? '«없음»' : Object.keys(marketplaces).map(name => safeIdentifier(name) ?? '<redacted>').sort(),
110
131
  mcpServers: mcpFilesMissing ? '«없음»' : mcp,
111
- skills: !existsSync(skillsDir) ? '«없음»' : readdirSync(skillsDir, { withFileTypes: true })
112
- .filter(entry => entry.isDirectory()).map(entry => entry.name).sort(),
132
+ skills: safeNames(skillsDir),
113
133
  teamclaude: { installed: present(team), version: teamVersion ?? null },
114
134
  auth: present(join(dir, 'auth.json')),
115
135
  credentials: present(join(dir, '.credentials.json')),
@@ -17,7 +17,12 @@ type AcpAgentManagerPort = {
17
17
  };
18
18
 
19
19
  export type JudgeVerdict = 'merge' | 'rework' | 'reject' | 'ambiguous';
20
- export interface AcpJudgeResult { verdict: JudgeVerdict; asks: string[]; reason: string; raw: string; }
20
+ export interface AcpJudgeResult {
21
+ verdict: JudgeVerdict; asks: string[]; reason: string; raw: string;
22
+ /** TA-LAND-MUSTFIX-ZERO — 심판 JSON 의 asks 가 없거나 배열이 아니거나 문자열 아닌 원소가 섞였다(`asks` 는 소비처 호환으로 `[]`·걸러진 값).
23
+ * ⛔ 이때 `asks: []` 는 «남은 지적 0» 이 아니라 «모름» — 자동 병합 관문이 `review-must-fix-unknown` 으로 막는다. */
24
+ asksUnreadable?: true;
25
+ }
21
26
 
22
27
  /** ACP 최종심판에 전달하는 PR diff의 기본 문자 상한. */
23
28
  export const DEFAULT_JUDGE_DIFF_CHAR_LIMIT = 24_000;
@@ -94,7 +99,8 @@ export function parseJudge(raw: string): AcpJudgeResult {
94
99
  const d = JSON.parse(json) as { verdict?: string; asks?: unknown; reason?: string };
95
100
  const verdict = (['merge', 'rework', 'reject', 'ambiguous'] as const).includes(d.verdict as JudgeVerdict) ? (d.verdict as JudgeVerdict) : 'ambiguous';
96
101
  const asks = Array.isArray(d.asks) ? d.asks.filter((x): x is string => typeof x === 'string') : [];
97
- return { verdict, asks, reason: typeof d.reason === 'string' ? d.reason : '', raw };
102
+ const asksUnreadable = !Array.isArray(d.asks) || asks.length !== d.asks.length;
103
+ return { verdict, asks, reason: typeof d.reason === 'string' ? d.reason : '', raw, ...(asksUnreadable ? { asksUnreadable: true as const } : {}) };
98
104
  } catch { return { verdict: 'ambiguous', asks: [], reason: 'json-parse-fail', raw }; }
99
105
  }
100
106
 
@@ -2,10 +2,12 @@ import type { Command } from 'commander';
2
2
  import { buildCapabilityMatrix, pickBackend } from './capability-matrix.js';
3
3
  import { createCapabilityReaders, type CapabilityRun } from './capability-readers.js';
4
4
  import { normalizeServiceName, type CapabilityEntry } from './capability-types.js';
5
+ import { buildCapabilityIndex, type CapabilityIndexReaders } from '../smart-wizard/capability-index.js';
5
6
 
6
7
  export interface CapabilitiesCliDeps {
7
8
  run?: CapabilityRun;
8
9
  write?: (text: string) => void;
10
+ indexReaders?: CapabilityIndexReaders;
9
11
  }
10
12
 
11
13
  /** Register the read-only capability inventory under agent-mission (and its codex alias). */
@@ -14,7 +16,20 @@ export function registerCapabilitiesCommand(parent: Command, deps: CapabilitiesC
14
16
  .description('List codex, claude and grok service capabilities (read only)')
15
17
  .option('--service <name>', 'Show observations and selected backend for a service')
16
18
  .option('--json', 'Output JSON')
17
- .action((opts: { service?: string; json?: boolean }) => {
19
+ .option('--index', 'Show provenance and authentication index (read only)')
20
+ .action(async (opts: { service?: string; json?: boolean; index?: boolean }) => {
21
+ if (opts.index) {
22
+ const index = await buildCapabilityIndex(deps.indexReaders);
23
+ const write = deps.write ?? (text => { process.stdout.write(text); });
24
+ if (opts.json) write(JSON.stringify(index) + '\n');
25
+ else {
26
+ write('SOURCE\tSTATUS\n');
27
+ for (const [source, status] of Object.entries(index.sources)) write(`${source}\t${status}\n`);
28
+ write('SOURCE\tID\tKIND\tSTATE\tAUTH\tPROVENANCE\n');
29
+ for (const entry of index.entries) write(`${entry.source}\t${entry.id}\t${entry.kind}\t${entry.state}\t${entry.auth}\t${entry.provenance}\n`);
30
+ }
31
+ return;
32
+ }
18
33
  const readers = createCapabilityReaders(deps.run);
19
34
  const matrix = buildCapabilityMatrix(readers);
20
35
  const entries: CapabilityEntry[] = opts.service
@@ -30,7 +30,7 @@ import { resolvePtyWebAddress } from '../cli/pty-web-address.js';
30
30
  import { verdictForFinalPtyScreen } from '../cli/pty-drive-verdict.js';
31
31
  import { reemitPtyUsage } from '../budget/pty-usage-reemit.js';
32
32
  import { classifyAuthError } from '../oauth/codex.js';
33
- import type { FallbackStep } from '../oauth/fallback-chain.js';
33
+ import { normalizeFallbackChain, type FallbackStep } from '../oauth/fallback-chain.js';
34
34
  import { runPtyControlLoop, controlDepsForHandle, type ControlDecision, type ControlObservation, type RunSupervisor } from '../autopilot/pty-control-loop.js';
35
35
  import { probeControlStance, stanceBlocksWrite } from '../pty-shell/pty-control-stance.js';
36
36
  import { mapControlStance, supervisionObservationFields } from '../self-implement/supervision-vocabulary.js';
@@ -352,7 +352,7 @@ export function resolveBackendSpawn(
352
352
  // ⚠️ 과금 스크럽 키만 — 중첩 표지는 정체성 allowlist 가 다시 싣는 키가 있어 이 PR 의 범위 밖이다.
353
353
  const unsetEnv = [...new Set(backend.scrubEnv ?? [])].filter((k) => !(k in env));
354
354
  // Codex drops parent env under shell_environment_policy inherit=core, so the nested-depth
355
- // marker rides on argv (`-c shell_environment_policy.set.ELANOUS_NESTED_DEPTH=<child>`).
355
+ // marker rides on argv (`-c shell_environment_policy.set.ELANOUS_NESTED_DEPTH="<child>"` — TOML 문자열).
356
356
  // Backends that cannot carry it are refused only when a nested elanous launch was requested.
357
357
  const args = [...backend.args, ...nestedDepthCodexArgs(backend.name, getNestDepth() + 1)];
358
358
  return { cmd: backend.cmd, args, env, unsetEnv, nestedEnvRemovedCount, forcedEnv };
@@ -441,7 +441,7 @@ export function agentBackendNames(): string[] {
441
441
  *
442
442
  * ⛔ 불변식 셋(윗 모듈에서 그대로 이어받는다):
443
443
  * ① **사람이 이름을 «명시»했으면 이 함수는 «안» 불린다** — 의도가 이긴다(호출자가 위에서 갈린다).
444
- * ② **기본 체인은 `['codex-rotate']`** 이라 옵션을 안 켠 사용자는 «항상 codex» — 무변경.
444
+ * ② **기본 체인은 `['codex-rotate', 'grok']`** 이며 claude-pty 는 명시 구성에서만 선택된다.
445
445
  * ③ **조용히 바꾸지 않는다** — 바꿨으면 관측에 남긴다. 조용한 폴백은 이 파일이 이미
446
446
  * 거부한 형태다(위 `resolveBackend` 주석: *"조용한 codex 폴백은 애그노스틱 위반"*).
447
447
  *
@@ -460,9 +460,9 @@ export function resolveDefaultBackend(
460
460
  return resolveRunFallback();
461
461
  });
462
462
  const decision = decide();
463
- if (decision.action === 'switch-backend' && decision.backend === 'grok') {
464
- debug.log('agent-mission.backend', 'fallback-switch', { from: 'codex', to: 'grok', reason: 'codex-exhausted' });
465
- return grokBackend;
463
+ if (decision.action === 'switch-backend' && (decision.backend === 'grok' || decision.backend === 'claude')) {
464
+ debug.log('agent-mission.backend', 'fallback-switch', { from: 'codex', to: decision.backend, reason: 'codex-exhausted' });
465
+ return decision.backend === 'claude' ? claudeBackend : grokBackend;
466
466
  }
467
467
  } catch (err) {
468
468
  debug.log('agent-mission.backend', 'fallback-failed', { message: (err as Error)?.message }, { level: 'warn' });
@@ -503,6 +503,20 @@ interface RuntimeFallbackContext extends RuntimeFallbackState {
503
503
  readonly fallbackEligible: boolean;
504
504
  }
505
505
 
506
+ /** 초기 백엔드의 체인 위치부터 남은 칸만 재시도한다. 실제 전환은 각 칸의 판정이 허용해야 한다. */
507
+ export function initialRuntimeFallback(backend: AgentBackend, chain: readonly FallbackStep[]): RuntimeFallbackContext {
508
+ const step: FallbackStep = backend.name === 'grok' ? 'grok' : backend.name === 'claude' ? 'claude-pty' : 'codex-rotate';
509
+ const position = chain.indexOf(step);
510
+ return {
511
+ fallbackEligible: true,
512
+ attemptedSteps: new Set<FallbackStep>([step]),
513
+ descents: 0,
514
+ // 초기 칸이 체인에 «없으면»(예: chain=['grok'] 인데 기본 codex 로 떴다) 체인 전체가 남은 칸이다 —
515
+ // 종전(codex 면 1칸)보다 줄이지 않는다.
516
+ maxDescents: position < 0 ? chain.filter((s) => s !== step).length : chain.length - position - 1,
517
+ };
518
+ }
519
+
506
520
  /** 한도 실패에만 재판정한다. 새·미시도 체인 칸과 최초 남은 칸 상한을 모두 만족해야 이동한다. */
507
521
  export function decideRuntimeFallback(
508
522
  failure: unknown,
@@ -512,8 +526,10 @@ export function decideRuntimeFallback(
512
526
  ): AgentBackend | null {
513
527
  if (classifyAuthError(failure).errorKind !== 'rate-limited' || state.descents >= state.maxDescents) return null;
514
528
  const decision = decide({ currentStep, currentCredentialRateLimited: true });
515
- if (decision.action !== 'switch-backend' || decision.backend !== 'grok' || state.attemptedSteps.has('grok')) return null;
516
- return grokBackend;
529
+ if (decision.action !== 'switch-backend') return null;
530
+ const nextStep = decision.backend === 'grok' ? 'grok' : decision.backend === 'claude' ? 'claude-pty' : null;
531
+ if (!nextStep || state.attemptedSteps.has(nextStep)) return null;
532
+ return nextStep === 'claude-pty' ? claudeBackend : grokBackend;
517
533
  }
518
534
 
519
535
  export interface AgentMissionSpec {
@@ -1586,10 +1602,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
1586
1602
  if (spec.plugin && (spec.headless || (backend.name !== 'codex' && backend.name !== 'claude'))) throw new Error('--plugin 은 codex/claude PTY 전용입니다');
1587
1603
  if (spec.workdir && spec.chain) throw new Error('workdir 모드는 넘기기 사슬을 쓰지 않는다');
1588
1604
  const runtimeFallback = deps.runtimeFallback ?? {
1605
+ ...initialRuntimeFallback(backend, normalizeFallbackChain(getUserConfig().llm?.fallbackChain).chain),
1589
1606
  fallbackEligible: spec.agent === undefined && !spec.chain,
1590
- attemptedSteps: new Set<FallbackStep>([backend.name === 'grok' ? 'grok' : 'codex-rotate']),
1591
- descents: 0,
1592
- maxDescents: backend.name === 'codex' ? 1 : 0,
1593
1607
  };
1594
1608
  const spawnPty = deps.startPty ?? startPty;
1595
1609
  const createMissionWorktree = deps.createWorktree ?? createWorktree;
@@ -2279,7 +2293,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
2279
2293
  const { resolveRunFallback: resolve } = require('../oauth/codex-account-store.js') as typeof import('../oauth/codex-account-store.js');
2280
2294
  return resolve(process.env, input);
2281
2295
  });
2282
- const currentStep: FallbackStep = backend.name === 'grok' ? 'grok' : 'codex-rotate';
2296
+ const currentStep: FallbackStep = backend.name === 'grok' ? 'grok' : backend.name === 'claude' ? 'claude-pty' : 'codex-rotate';
2283
2297
  const nextBackend = runtimeFallback.fallbackEligible ? decideRuntimeFallback(
2284
2298
  failure,
2285
2299
  currentStep,
@@ -2296,7 +2310,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
2296
2310
  });
2297
2311
  if (nextBackend && !deps.isMissionAborted?.()) {
2298
2312
  decisionEvent({ step: 'recover', text: `Switching ${backend.name} to ${nextBackend.name}`, detail: { blocked: control.termination.message, action: `Retry with ${nextBackend.name}` } });
2299
- const nextStep: FallbackStep = nextBackend.name === 'grok' ? 'grok' : 'codex-rotate';
2313
+ const nextStep: FallbackStep = nextBackend.name === 'grok' ? 'grok' : nextBackend.name === 'claude' ? 'claude-pty' : 'codex-rotate';
2300
2314
  stopLive();
2301
2315
  if (h.pid) await (deps.terminateProcessTree ?? terminateMissionProcessTree)(h.pid);
2302
2316
  try { h.kill(); } catch { /* noop */ }
@@ -25,10 +25,14 @@ import { AUTO_REVIEW_LABEL } from '../self-implement/context-capsule.js';
25
25
  import { resolveReworkBackendChoice, runReviewLoop, type ReviewLoopOpts, type ReviewLoopResult, type ReviewVerdict } from './review-loop.js';
26
26
  import type { ReviewResult } from '../agent-substrate/pr-reviewer.js';
27
27
 
28
- /** 1차 리뷰 결과(ReviewResult) → review-loop injectedReview. fail→reinforce(mustFix)·pass/warn→ok(clean). 순수. */
28
+ /** 1차 리뷰 결과(ReviewResult) → review-loop injectedReview. fail→reinforce(mustFix)·pass/warn→ok. 순수.
29
+ * TA-LAND-MUSTFIX-ZERO — pass/warn 의 must-fix 를 «지우지 않고» asks 로 싣는다: 지우면 review-loop 의
30
+ * 자동 병합 관문이 «must-fix 0» 으로 읽는다. must-fix 0 이면 종전과 같은 `asks: []`. */
29
31
  export function mapReviewToInjected(r: ReviewResult): { verdict: ReviewVerdict; asks: string[] } {
30
32
  if (r.verdict === 'fail') return { verdict: 'reinforce', asks: r.mustFix };
31
- return { verdict: 'ok', asks: [] };
33
+ // must-fix 목록을 못 읽으면 «0» 이 아니라 «모름» — ok 로 보내지 않는다(ambiguous = 명확화 요청 · 병합 없음).
34
+ if (!Array.isArray(r.mustFix)) return { verdict: 'ambiguous', asks: [] };
35
+ return { verdict: 'ok', asks: [...r.mustFix] };
32
36
  }
33
37
 
34
38
  /** [ISO] ELANOUS_STATE_DIR 존중(lazy) — 테스트격리 시 .elanous-test 로 스코프. */
@@ -31,6 +31,8 @@ export interface ReviewClassification {
31
31
  asks: string[];
32
32
  reason: string;
33
33
  classificationSource: ReviewClassificationSource;
34
+ /** TA-LAND-MUSTFIX-ZERO — 분류 JSON 의 asks 가 없거나 배열이 아니거나 문자열 아닌 원소가 섞였다. `asks: []` 는 그때 «0» 이 아니라 «모름». */
35
+ asksUnreadable?: true;
34
36
  }
35
37
 
36
38
  export interface ReviewLoopOpts {
@@ -115,6 +117,16 @@ function gh(args: string[]): string {
115
117
  return execFileSync('gh', args, { encoding: 'utf8', timeout: 60000, maxBuffer: 20 * 1024 * 1024, env: process.env });
116
118
  }
117
119
 
120
+ /** TA-LAND-MUSTFIX-ZERO — 자동 병합 «직전» must-fix 관문(#25941 `canAuto` 와 같은 축).
121
+ * 남은 지적(asks)이 있으면 `review-warn-with-must-fix` · 목록 자체가 배열이 아니면 «0» 이 아니라
122
+ * «모름» = `review-must-fix-unknown`(fail-closed). 막을 때 `review-loop` 범주에 `auto-merge-blocked` 를 남긴다. */
123
+ function reviewMergeMustFixBlock(pr: string, stage: 'initial-ok' | 'final-judge', asks: unknown, unreadable: boolean, round?: number): 'review-warn-with-must-fix' | 'review-must-fix-unknown' | null {
124
+ const known = Array.isArray(asks) && !unreadable;
125
+ const reason = !known ? 'review-must-fix-unknown' : (asks as unknown[]).length > 0 ? 'review-warn-with-must-fix' : null;
126
+ if (reason) debug.log('review-loop', 'auto-merge-blocked', { pr, stage, reason, mustFixCount: known ? (asks as unknown[]).length : null, ...(round !== undefined ? { round } : {}) });
127
+ return reason;
128
+ }
129
+
118
130
  /** Check every page of the PR file list immediately before an unattended review-loop merge. */
119
131
  function holdReleasePathBeforeReviewMerge(pr: string, runGh: (args: string[]) => string): boolean {
120
132
  let paths: string[];
@@ -254,10 +266,16 @@ export async function judgeAndFinalize(
254
266
  debug.log('review-loop', 'judge-start', { pr, round, diffChars: preparedDiff.totalChars, judgeBackend: judgeBackendResolution.backend, judgeBackendSource: judgeBackendResolution.source });
255
267
  const judge = opts.judge ?? judgeWithAcp;
256
268
  const j = await judge({ diff, context: `반영한 지적:\n${asks.join('\n')}${reviewerContext}`, gatePassed: true, cwd, backend: judgeBackendResolution.backend, ...(opts.judgeModel ? { model: opts.judgeModel } : {}) });
257
- debug.log('review-loop', 'judge-verdict', { pr, round, verdict: j.verdict, asks: j.asks.length });
269
+ debug.log('review-loop', 'judge-verdict', { pr, round, verdict: j.verdict, asks: Array.isArray(j.asks) ? j.asks.length : null });
258
270
  const diffScope = `심판 diff 범위: 본 ${preparedDiff.judgeChars}자 / 전체 ${preparedDiff.totalChars}자`;
259
271
 
260
272
  if (j.verdict === 'merge') {
273
+ // TA-LAND-MUSTFIX-ZERO — 심판이 «merge» 라도 남긴 asks(미해결 지적)가 있으면 자동 병합하지 않는다 → HITL.
274
+ const mustFixBlock = opts.autoMerge ? reviewMergeMustFixBlock(pr, 'final-judge', j.asks, j.asksUnreadable === true, round) : null;
275
+ if (mustFixBlock) {
276
+ try { runGh(['pr', 'comment', pr, '--body', `🛑 ACP Claude Code 2차 최종심판: **MERGE** 이나 미해결 지적이 남아 자동 병합하지 않음(${mustFixBlock} · 라운드 ${round}) → 대표 결정 필요.\n${diffScope}\n사유: ${j.reason}`]); } catch { /* noop */ }
277
+ return { pr, branch, verdict: 'reinforce', asks: Array.isArray(j.asks) ? j.asks : asks, action: 'parked', reworkOk: true, pushed: lastPushed, rounds: round, detail: `2차 심판 MERGE ⊕ ${mustFixBlock} → HITL: ${j.reason}` };
278
+ }
261
279
  if (opts.autoMerge) {
262
280
  if (holdReleasePathBeforeReviewMerge(pr, runGh)) return { pr, branch, verdict: 'reinforce', asks, action: 'parked', reworkOk: true, pushed: lastPushed, rounds: round, detail: 'OP approval required: release-path hold or PR file inspection unavailable' };
263
281
  const approve = opts.approve ?? approvePr;
@@ -279,7 +297,7 @@ export async function judgeAndFinalize(
279
297
  try { runGh(['pr', 'comment', pr, '--body', `🛑 ACP Claude Code 2차 최종심판: **${j.verdict.toUpperCase()}** (라운드 ${round}) → 대표 결정 필요.\n${diffScope}\n사유: ${j.reason}`]); } catch { /* noop */ }
280
298
  return { pr, branch, verdict: 'reinforce', asks, action: 'parked', reworkOk: true, pushed: lastPushed, rounds: round, detail: `2차 심판 ${j.verdict} → HITL: ${j.reason}` };
281
299
  }
282
- return { rework: j.asks.length > 0 ? j.asks : asks };
300
+ return { rework: Array.isArray(j.asks) && j.asks.length > 0 ? j.asks : asks };
283
301
  }
284
302
 
285
303
  export interface LatestReviewSource {
@@ -429,7 +447,8 @@ JSON 만: {"verdict":"...","asks":["..."],"reason":"..."}`;
429
447
  const d = JSON.parse(jm[0]) as { verdict?: string; asks?: unknown; reason?: string };
430
448
  const verdict = (['ok', 'reinforce', 'reject', 'ambiguous'] as const).includes(d.verdict as ReviewVerdict) ? (d.verdict as ReviewVerdict) : 'ambiguous';
431
449
  const asks = Array.isArray(d.asks) ? d.asks.filter((x): x is string => typeof x === 'string') : [];
432
- return { verdict, asks, reason: typeof d.reason === 'string' ? d.reason : '', classificationSource: 'llm' };
450
+ const asksUnreadable = !Array.isArray(d.asks) || asks.length !== d.asks.length;
451
+ return { verdict, asks, reason: typeof d.reason === 'string' ? d.reason : '', classificationSource: 'llm', ...(asksUnreadable ? { asksUnreadable: true as const } : {}) };
433
452
  } catch { return { verdict: 'ambiguous', asks: [], reason: 'JSON 파싱 실패', classificationSource: 'llm' }; }
434
453
  }
435
454
 
@@ -497,15 +516,24 @@ export async function runReviewLoop(pr: string, opts: ReviewLoopOpts = {}): Prom
497
516
  debug.log('review-loop', 'classified', {
498
517
  pr,
499
518
  verdict: cls.verdict,
500
- asks: cls.asks.length,
519
+ asks: Array.isArray(cls.asks) ? cls.asks.length : null, // 목록 없음 = null(«0» 아님) — 아래 must-fix 관문이 막는다
501
520
  source: opts.injectedReview ? 'injected' : 'gh',
502
521
  reason: cls.reason,
503
522
  classificationSource: cls.classificationSource,
504
523
  });
505
524
 
506
- let asks = cls.asks;
525
+ let asks = Array.isArray(cls.asks) ? cls.asks : []; // 목록 없음·못 읽음은 아래 자동 병합 관문이 cls 로 막는다 · rework/명확화 소비처만 `[]` 로 읽는다
507
526
 
508
527
  if (cls.verdict === 'ok') {
528
+ // TA-LAND-MUSTFIX-ZERO — 1차 «ok» 에 지적(asks)이 남았거나 목록을 못 읽으면 자동 병합 경로로 가지 않는다(승인도 안 함) → HITL.
529
+ // light·heavy 둘 다 — heavy 는 심판에 asks 를 안 넘기므로(`[]`) 여기서 막지 않으면 심판 merge 가 1차 must-fix 를 덮는다.
530
+ // 관문은 «이 경로가 실제로 자동 병합할 때»만 — light 는 autoMergeOnOk||autoMerge, heavy 는 심판 merge 의 autoMerge 뿐(autoMergeOnOk 만이면 종전대로 심판 → ready-to-merge).
531
+ const autoMergesHere = effectiveFinalJudge ? opts.autoMerge === true : (opts.autoMergeOnOk || opts.autoMerge);
532
+ const mustFixBlock = autoMergesHere ? reviewMergeMustFixBlock(pr, 'initial-ok', cls.asks, cls.asksUnreadable === true) : null;
533
+ if (mustFixBlock) {
534
+ try { runGh(['pr', 'comment', pr, '--body', `🛑 1차 리뷰 ok 이나 미해결 지적이 남아 자동 병합하지 않음(${mustFixBlock}) → 대표 결정 필요.`]); } catch { /* noop */ }
535
+ return { pr, branch, verdict: 'ok', asks: Array.isArray(cls.asks) ? cls.asks : [], action: 'parked', detail: `${depth}·1차 ok ⊕ ${mustFixBlock} → HITL(자동 병합 안 함)` };
536
+ }
509
537
  // light: 1차 clean 으로 충분 → approve + 머지. heavy: 1차 ok 여도 2차 심판 머스트.
510
538
  if (!effectiveFinalJudge) {
511
539
  if ((opts.autoMergeOnOk || opts.autoMerge) && holdReleasePathBeforeReviewMerge(pr, runGh)) {
@@ -69,8 +69,17 @@ function linkedRows(rows: readonly SupervisorLogRow[], missionIds: ReadonlySet<s
69
69
  const linked: SupervisorLogRow[] = [];
70
70
  let unlinked = false;
71
71
  for (const row of rows) {
72
- const key = missionKey(row.data);
73
- if (key && missionIds.has(key)) linked.push(row);
72
+ // The driver writes its runId into the ambient log payload and the PTY decision's
73
+ // sessionId; the decision emitter may replace missionId with a display alias.
74
+ // Without a runId, either retained identifier can identify an existing result.
75
+ const runId = row.data?.runId;
76
+ const sessionId = row.category === DECISION_CATEGORY ? row.data?.sessionId : undefined;
77
+ const key = typeof runId === 'string' && runId.trim() ? runId.trim() : null;
78
+ const sessionKey = typeof sessionId === 'string' && sessionId.trim() ? sessionId.trim() : null;
79
+ const missionId = typeof row.data?.missionId === 'string' && row.data.missionId.trim() ? row.data.missionId.trim() : null;
80
+ const matches = key ? missionIds.has(key)
81
+ : (missionId !== null && missionIds.has(missionId)) || (sessionKey !== null && missionIds.has(sessionKey));
82
+ if (matches) linked.push(row);
74
83
  else unlinked = true;
75
84
  }
76
85
  return { linked, unlinked };
@@ -123,6 +132,12 @@ export function aggregateSupervisorMetrics(
123
132
  ? unmeasured('questionsAnswered', '대화형 질문에 답해 넘긴 수', UNLINKED_REASON)
124
133
  : answers.linked.length === 0
125
134
  ? unmeasured('questionsAnswered', '대화형 질문에 답해 넘긴 수', '못 잼 · pty.decision answer 기록 없음')
135
+ : answers.linked.some((row) => {
136
+ const detail = row.data?.detail;
137
+ return !detail || typeof detail !== 'object' || !('answer' in detail)
138
+ || typeof detail.answer !== 'string' || !detail.answer.trim();
139
+ })
140
+ ? unmeasured('questionsAnswered', '대화형 질문에 답해 넘긴 수', '못 잼 · 답변 본문 기록 없음')
126
141
  : {
127
142
  id: 'questionsAnswered',
128
143
  label: '대화형 질문에 답해 넘긴 수',
@@ -25,10 +25,16 @@ export interface AcpReviewerOpts {
25
25
  cwd: string;
26
26
  /** ACP 백엔드 id (기본 claude = Claude Code via claude-code-acp). */
27
27
  backend?: string;
28
+ /** Per-review ACP spawn specification (subscription executor). */
29
+ backendSpec?: import('../acp/backend-registry.js').AcpBackendSpec;
30
+ /** Subscription child environment after billing credentials are removed. */
31
+ env?: Record<string, string>;
28
32
  /** 모델 tier 별칭 (opus|sonnet|haiku 등). 지정 시 session/set_model 로 고정(백엔드 CLI 기본 위임 아님). */
29
33
  model?: string;
30
34
  /** 리뷰 1턴 최대 대기(ms). 초과 시 cancel→throw(부분 리뷰로 오판 pass 방지). 기본 300000. */
31
35
  timeoutMs?: number;
36
+ /** One deadline for spawn → initialize → session/new → model select (ms). A child that never answers ACP must not hang the review. Default min(timeoutMs, 60000). */
37
+ handshakeTimeoutMs?: number;
32
38
  }
33
39
 
34
40
  /**
@@ -96,7 +102,7 @@ export function makeAcpReviewLLM(opts: AcpReviewerOpts): (prompt: string, images
96
102
  // ⇒ 이 한 줄만 자기 catch 로 감싼다(전체 try 를 앞당기면 `start` 관측이 그 안으로 들어간다).
97
103
  let transport: string | null;
98
104
  try {
99
- transport = injected ? null : getAcpBackend(backend).transport ?? 'acp';
105
+ transport = injected ? null : opts.backendSpec?.transport ?? getAcpBackend(backend).transport ?? 'acp';
100
106
  } catch (e) {
101
107
  debug.log('acp-review', 'error', {
102
108
  requestedBackend, backend, stage: 'resolve-backend', message: (e as Error).message,
@@ -116,6 +122,7 @@ export function makeAcpReviewLLM(opts: AcpReviewerOpts): (prompt: string, images
116
122
  let capabilitiesObserved = false;
117
123
  const agentOpts: Omit<AcpAgentOpts, 'backendId'> = {
118
124
  cwd: opts.cwd,
125
+ ...(opts.backendSpec ? { backendSpec: opts.backendSpec, env: opts.env } : {}),
119
126
  log: (message) => debug.log('acp-review', 'agent-log', { backend, message }),
120
127
  onCapabilities: (capabilities) => {
121
128
  capabilitiesObserved = true;
@@ -142,16 +149,25 @@ export function makeAcpReviewLLM(opts: AcpReviewerOpts): (prompt: string, images
142
149
  };
143
150
  // A review owns its manager and subprocess: the global manager caches
144
151
  // chat agents, whose callbacks and lifecycle must not be mutated here.
145
- const reviewManager = injected ? undefined : new AcpAgentManager();
152
+ const reviewManager = injected || opts.backendSpec ? undefined : new AcpAgentManager();
146
153
  let agent: AcpAgent | undefined;
147
154
  let text = '';
148
155
  let timedOut = false;
149
156
  let timer: ReturnType<typeof setTimeout> | undefined;
157
+ const handshakeTimeoutMs = opts.handshakeTimeoutMs ?? Math.min(timeoutMs, 60_000);
158
+ const handshakeDeadline = Date.now() + handshakeTimeoutMs;
159
+ let handshakeTimer: ReturnType<typeof setTimeout> | undefined;
160
+ const withinHandshake = <T>(step: Promise<T>): Promise<T> => Promise.race([step, new Promise<never>((_, reject) => {
161
+ handshakeTimer = setTimeout(() => {
162
+ debug.log('acp-review', 'handshake-timeout', { backend, handshakeTimeoutMs }, { level: 'error' });
163
+ reject(new Error(`ACP handshake timeout (${handshakeTimeoutMs}ms)`));
164
+ }, Math.max(0, handshakeDeadline - Date.now()));
165
+ })]).finally(() => { if (handshakeTimer) clearTimeout(handshakeTimer); });
150
166
  try {
151
- agent = opts.createAgent
152
- ? opts.createAgent({ backendId: requestedBackend, ...agentOpts })
153
- : await reviewManager!.getAgent(requestedBackend, agentOpts);
154
- if (injected) await agent.start();
167
+ if (opts.createAgent) agent = opts.createAgent({ backendId: requestedBackend, ...agentOpts });
168
+ else if (opts.backendSpec) agent = new AcpAgent({ backendId: requestedBackend, ...agentOpts });
169
+ else agent = await withinHandshake(reviewManager!.getAgent(requestedBackend, agentOpts));
170
+ if (injected || opts.backendSpec) await withinHandshake(agent.start());
155
171
  if (!capabilitiesObserved) {
156
172
  try {
157
173
  debug.log('acp-review', 'capabilities', {
@@ -165,9 +181,9 @@ export function makeAcpReviewLLM(opts: AcpReviewerOpts): (prompt: string, images
165
181
  // Observability must not interrupt a review.
166
182
  }
167
183
  }
168
- const sid = await agent.newSession();
184
+ const sid = await withinHandshake(agent.newSession());
169
185
  if (opts.model) {
170
- const picked = await agent.selectSessionModel(sid, opts.model);
186
+ const picked = await withinHandshake(agent.selectSessionModel(sid, opts.model));
171
187
  debug.log('acp-review', 'model', { requested: opts.model, picked: picked?.name ?? null, backend });
172
188
  }
173
189
  timer = setTimeout(() => { timedOut = true; agent!.cancel(sid).catch(() => { /* noop */ }); }, timeoutMs);
@@ -211,7 +227,7 @@ export function makeAcpReviewLLM(opts: AcpReviewerOpts): (prompt: string, images
211
227
  // cleanup seam, while the per-review manager releases its agents and
212
228
  // process hooks. An injected agent is external to the manager.
213
229
  try {
214
- if (injected) await agent?.stop();
230
+ if (injected || opts.backendSpec) await agent?.stop();
215
231
  else await reviewManager!.dispose();
216
232
  } catch (e) {
217
233
  debug.log('acp-review', 'stop-fail', { backend, message: (e as Error).message }, { level: 'error' });