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
@@ -0,0 +1,189 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
3
+ import { dirname, join, resolve } from 'node:path';
4
+ import { debug } from '../src/debug/log.js';
5
+ import { effectiveInstanceRoot } from '../src/instance/resolve.js';
6
+ import { GATE_REMOTE_DEFAULTS, isValidGateHost, resolveGateRemoteSettings, runOnRemote, type ExecResult, type RemoteRunOptions, type RemoteRunOutcome } from '../src/self-implement/gate-remote.js';
7
+ import { getUserConfig } from '../src/user-config.js';
8
+ import { parseTypecheckErrors, tscEnv } from '../src/typecheck-ratchet.js';
9
+ import { compareDiagnostics, normalizeDiagnostics, type NormalizedDiagnostic } from './tsc-baseline-comparison.js';
10
+
11
+ const TSC_ARGV = ['bunx', 'tsc', '--noEmit', '-p', 'tsconfig.gate.json', '--incremental', 'false'];
12
+ const COMMIT = /^[0-9a-f]{40}$/i;
13
+ const UNMEASURABLE = /\berror TS(?:2688|5083|6053):/;
14
+
15
+ export interface SafetyNetEntry {
16
+ at: string;
17
+ commit: string;
18
+ outcome: 'clean' | 'added' | 'unmeasured' | 'baseline';
19
+ total: number;
20
+ added: NormalizedDiagnostic[];
21
+ removed: number;
22
+ ms: number;
23
+ host: string;
24
+ /** Full measured snapshot: `added` alone cannot serve as the next day's baseline. */
25
+ diagnostics?: NormalizedDiagnostic[];
26
+ }
27
+
28
+ export interface SafetyNetDeps {
29
+ local?: (cmd: string, args: string[], cwd: string, options?: { env?: NodeJS.ProcessEnv }) => ExecResult;
30
+ remote?: (options: RemoteRunOptions) => RemoteRunOutcome;
31
+ compare?: typeof compareDiagnostics;
32
+ exists?: (path: string) => boolean;
33
+ instanceRoot?: () => string;
34
+ settings?: () => ReturnType<typeof resolveGateRemoteSettings>;
35
+ now?: () => number;
36
+ observed?: (entry: { commit: string; outcome: SafetyNetEntry['outcome']; total: number; added: number; removed: number; ms: number; host: string }) => void;
37
+ }
38
+
39
+ const realLocal: NonNullable<SafetyNetDeps['local']> = (cmd, args, cwd, options) => {
40
+ const result = spawnSync(cmd, args, { cwd, encoding: 'utf8', maxBuffer: 64 * 1024 * 1024, ...(options?.env ? { env: options.env } : {}) });
41
+ return { rc: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '', ...(result.error ? { error: String(result.error) } : {}) };
42
+ };
43
+
44
+ function flags(argv: readonly string[]): { local: boolean; host?: string; ledger?: string; json: boolean } {
45
+ let local = false;
46
+ let host: string | undefined;
47
+ let ledger: string | undefined;
48
+ let json = false;
49
+ for (let i = 0; i < argv.length; i++) {
50
+ const arg = argv[i];
51
+ if (arg === '--local') local = true;
52
+ else if (arg === '--json') json = true;
53
+ else if (arg === '--remote' || arg === '--ledger') {
54
+ const value = argv[++i];
55
+ if (!value || value.startsWith('--')) throw new Error(`${arg} requires a value`);
56
+ if (arg === '--remote') host = value;
57
+ else ledger = value;
58
+ } else throw new Error(`unknown argument: ${arg}`);
59
+ }
60
+ if (local && host) throw new Error('--local and --remote cannot be combined');
61
+ if (host && !isValidGateHost(host)) throw new Error(`invalid --remote host: ${host}`);
62
+ return { local, host, ledger, json };
63
+ }
64
+
65
+ function measuredSnapshot(path: string): NormalizedDiagnostic[] | undefined {
66
+ if (!existsSync(path)) return undefined;
67
+ const rows = readFileSync(path, 'utf8').trim().split('\n').filter(Boolean);
68
+ for (let i = rows.length - 1; i >= 0; i--) {
69
+ const entry = JSON.parse(rows[i]!) as SafetyNetEntry;
70
+ if (entry.outcome === 'unmeasured') continue;
71
+ if (!Array.isArray(entry.diagnostics) || !entry.diagnostics.every((d) => d && typeof d.file === 'string' && typeof d.code === 'string' && typeof d.message === 'string')) {
72
+ throw new Error('last measured ledger entry has no valid diagnostic snapshot');
73
+ }
74
+ return entry.diagnostics;
75
+ }
76
+ return undefined;
77
+ }
78
+
79
+ function diagnosticsOf(result: { rc: number | null; stdout: string; stderr: string; error?: string }, root: string): NormalizedDiagnostic[] | undefined {
80
+ const output = `${result.stdout}\n${result.stderr}`;
81
+ if (result.error || result.rc === null || (result.rc !== 0 && result.rc !== 1 && result.rc !== 2) || UNMEASURABLE.test(output)
82
+ || /heap out of memory|Ineffective mark-compacts near heap limit/i.test(output)) return undefined;
83
+ const parsed = parseTypecheckErrors(output);
84
+ const errorLines = output.split(/\r?\n/).filter((line) => /\berror TS\d+:/.test(line));
85
+ if (parsed.length !== errorLines.length || (result.rc === 0 && errorLines.length > 0) || (result.rc !== 0 && parsed.length === 0)) return undefined;
86
+ if (output.split(/\r?\n/).some((line) => line.trim() && !/^.+\(\d+,\d+\):\s+error\s+TS\d+:/.test(line) && !/^\s+/.test(line)
87
+ && !/^Found \d+ errors?\.?$/.test(line))) return undefined;
88
+ return normalizeDiagnostics(parsed, root);
89
+ }
90
+
91
+ export async function runSafetyNet(repo: string, argv: readonly string[] = [], deps: SafetyNetDeps = {}): Promise<{ exitCode: number; entry: SafetyNetEntry; json: boolean }> {
92
+ const input = flags(argv);
93
+ const run = deps.local ?? realLocal;
94
+ const remote = deps.remote ?? runOnRemote;
95
+ const exists = deps.exists ?? existsSync;
96
+ const root = deps.instanceRoot?.() ?? effectiveInstanceRoot();
97
+ const settings = deps.settings?.() ?? (input.local ? GATE_REMOTE_DEFAULTS : resolveGateRemoteSettings(getUserConfig().gateRemote));
98
+ const host = input.local ? 'local' : (input.host ?? settings.host ?? GATE_REMOTE_DEFAULTS.host);
99
+ if (host !== 'local' && !isValidGateHost(host)) throw new Error(`invalid gateRemote host: ${host}`);
100
+ const ledger = resolve(input.ledger ?? join(root, 'tsc-safety-net', 'ledger.jsonl'));
101
+ const worktree = join(root, 'tsc-safety-net', 'worktree');
102
+ const started = (deps.now ?? Date.now)();
103
+ let commit = '';
104
+ let diagnostics: NormalizedDiagnostic[] | undefined;
105
+ let reason: string | undefined;
106
+ let dependencyFailed = false;
107
+ const git = (args: string[], cwd: string): ExecResult => {
108
+ const env = { ...process.env };
109
+ delete env.GIT_DIR; delete env.GIT_WORK_TREE; delete env.GIT_COMMON_DIR;
110
+ return run('git', args, cwd, { env });
111
+ };
112
+ const checked = (args: string[], cwd: string): ExecResult => {
113
+ const result = git(args, cwd);
114
+ if (result.error || result.rc !== 0) throw new Error(`git ${args.join(' ')}: ${result.error ?? result.stderr ?? `rc=${result.rc}`}`);
115
+ return result;
116
+ };
117
+ try {
118
+ checked(['fetch', 'origin', '+refs/heads/main:refs/remotes/origin/main'], repo);
119
+ commit = checked(['rev-parse', '--verify', 'origin/main^{commit}'], repo).stdout.trim();
120
+ if (!COMMIT.test(commit)) throw new Error('origin/main did not resolve to a commit');
121
+ if (!exists(worktree)) {
122
+ mkdirSync(dirname(worktree), { recursive: true });
123
+ checked(['worktree', 'add', '--detach', worktree, commit], repo);
124
+ } else {
125
+ const listed = checked(['worktree', 'list', '--porcelain'], repo).stdout;
126
+ if (!listed.split('\n').some((line) => line === `worktree ${worktree}`)) throw new Error('worktree path is not a registered git worktree');
127
+ }
128
+ const status = checked(['status', '--porcelain'], worktree).stdout;
129
+ if (status.trim()) checked(['reset', '--hard'], worktree);
130
+ // Porcelain status omits ignored files, including stale .ts files from a previous measurement.
131
+ checked(['clean', '-fdx', '-e', 'node_modules'], worktree);
132
+ checked(['checkout', '--detach', 'origin/main'], worktree);
133
+ if (checked(['rev-parse', 'HEAD'], worktree).stdout.trim() !== commit || checked(['status', '--porcelain'], worktree).stdout.trim()) throw new Error('worktree is not clean at origin/main');
134
+ if (input.local) {
135
+ // The retained node_modules may belong to yesterday's lockfile; frozen install reconciles it to this checkout.
136
+ dependencyFailed = true;
137
+ const install = run('bun', ['install', '--frozen-lockfile'], worktree);
138
+ if (install.rc !== 0 || install.error || !exists(join(worktree, 'node_modules'))) {
139
+ throw new Error(`local dependencies unavailable: ${install.error ?? install.stderr ?? `rc=${install.rc}`}`);
140
+ }
141
+ dependencyFailed = false;
142
+ const result = run(TSC_ARGV[0]!, TSC_ARGV.slice(1), worktree, { env: tscEnv() });
143
+ diagnostics = diagnosticsOf(result, worktree);
144
+ if (!diagnostics) reason = 'local tsc did not produce a complete measurement';
145
+ } else {
146
+ const result = remote({ repo: worktree, host, mirror: settings.mirror, hostCap: settings.hostCap, argv: TSC_ARGV });
147
+ if (result.kind === 'ran') {
148
+ if (result.commit !== commit) throw new Error('remote measured a different commit');
149
+ diagnostics = diagnosticsOf({ rc: result.rc, stdout: result.stdout.toString('utf8'), stderr: result.stderr.toString('utf8') }, worktree);
150
+ if (!diagnostics) reason = 'remote tsc did not produce a complete measurement';
151
+ } else reason = result.kind === 'busy' ? 'remote busy' : `remote infra: ${result.reason}`;
152
+ }
153
+ } catch (error) {
154
+ reason = error instanceof Error ? error.message : String(error);
155
+ }
156
+ let previous: NormalizedDiagnostic[] | undefined;
157
+ try { previous = measuredSnapshot(ledger); }
158
+ catch (error) { diagnostics = undefined; reason = `ledger unreadable: ${error instanceof Error ? error.message : String(error)}`; }
159
+ const comparison = diagnostics && previous ? (deps.compare ?? compareDiagnostics)(diagnostics, previous) : undefined;
160
+ if (comparison?.kind === 'unavailable') reason = `comparison unavailable: ${comparison.reason}`;
161
+ const outcome: SafetyNetEntry['outcome'] = !diagnostics || comparison?.kind === 'unavailable'
162
+ ? 'unmeasured' : !previous ? 'baseline' : comparison?.kind === 'added' ? 'added' : 'clean';
163
+ const entry: SafetyNetEntry = {
164
+ at: new Date((deps.now ?? Date.now)()).toISOString(), commit, outcome, total: diagnostics?.length ?? 0,
165
+ added: comparison && comparison.kind !== 'unavailable' ? comparison.added : [],
166
+ removed: comparison && comparison.kind !== 'unavailable' ? comparison.removed.length : 0,
167
+ ms: (deps.now ?? Date.now)() - started, host,
168
+ ...(outcome !== 'unmeasured' && diagnostics ? { diagnostics } : {}),
169
+ };
170
+ if (!dependencyFailed) {
171
+ mkdirSync(dirname(ledger), { recursive: true });
172
+ appendFileSync(ledger, `${JSON.stringify(entry)}\n`);
173
+ }
174
+ const observation = { commit, outcome, total: entry.total, added: entry.added.length, removed: entry.removed, ms: entry.ms, host };
175
+ (deps.observed ?? ((data) => debug.log('tsc.safety-net', 'run', data)))(observation);
176
+ if (reason) console.error(`[tsc.safety-net] ${reason}`);
177
+ return { exitCode: outcome === 'unmeasured' ? 2 : outcome === 'added' ? 1 : 0, entry, json: input.json };
178
+ }
179
+
180
+ if (import.meta.main) {
181
+ try {
182
+ const result = await runSafetyNet(process.cwd(), process.argv.slice(2));
183
+ console.log(result.json ? JSON.stringify(result.entry) : `[tsc.safety-net] ${result.entry.outcome} commit=${result.entry.commit} total=${result.entry.total} added=${result.entry.added.length} removed=${result.entry.removed} host=${result.entry.host}`);
184
+ process.exitCode = result.exitCode;
185
+ } catch (error) {
186
+ console.error(`[tsc.safety-net] unmeasured: ${error instanceof Error ? error.message : String(error)}`);
187
+ process.exitCode = 2;
188
+ }
189
+ }
@@ -2,14 +2,14 @@
2
2
  // 실행 칸(Pod 등)이 사라지기 «전»에 자기 llm.usage 를 한 줄로 요약해 stdout 에 — 슈퍼바이저가 호스트로 가져간다.
3
3
  // RFC-fleet-supervisor-substrates-benchmark-and-token-accounting §A2·F2 · 2026-09-25.
4
4
  // bun scripts/usage-rollup.ts [--since 6h]
5
- // 출력: ELANOUS_USAGE_ROLLUP {"substrate","runId","armId","truncated","rows":[{site,provider,model,calls,inputTokens,outputTokens,cacheReadInputTokens,usdKnown,unknownCostCalls}],"total":{…}}
5
+ // 출력: ELANOUS_USAGE_ROLLUP {"substrate","runId","armId","truncated","rows":[{site,provider,model,calls,inputTokens,outputTokens,cacheReadInputTokens,cacheCreationInputTokens,usdKnown,unknownCostCalls}],"total":{…}}
6
6
  // ⛔ 의존성 없음(설치본 `elanous` 만 부른다) — clone 에 node_modules 가 없어도 돈다.
7
7
  // ⛔ 비용을 모르는 호출(cost.kind≠known)은 0 으로 합치지 않고 따로 센다.
8
8
  // ⛔ `--all --include-test` 로 «그 기계의 모든 우주»를 읽는다 — Pod(자기 스토어뿐)에서는 그것이 곧 그 칸의 사용량이지만,
9
9
  // 호스트(맥)에서 돌리면 테스트 우주·워크트리·다른 트랙의 런까지 섞인다(📏 09-25: 운영만 16회 vs 전체 124회). 호스트 집계용이 아니다.
10
10
  import { spawnSync } from 'node:child_process';
11
11
 
12
- export interface UsageRow { site: string; provider: string; model: string; calls: number; inputTokens: number; outputTokens: number; cacheReadInputTokens: number; usdKnown: number; unknownCostCalls: number; includedCalls: number; apiEquivalentUsd: number }
12
+ export interface UsageRow { site: string; provider: string; model: string; calls: number; inputTokens: number; outputTokens: number; cacheReadInputTokens: number; cacheCreationInputTokens: number; cacheCreationUnmeasuredCalls: number; usdKnown: number; unknownCostCalls: number; includedCalls: number; apiEquivalentUsd: number }
13
13
 
14
14
  export function rollup(lines: readonly string[]): { rows: UsageRow[]; truncated: boolean } {
15
15
  const by = new Map<string, UsageRow>();
@@ -20,14 +20,18 @@ export function rollup(lines: readonly string[]): { rows: UsageRow[]; truncated:
20
20
  let r: { event?: string; data?: Record<string, unknown> };
21
21
  try { r = JSON.parse(line); } catch { continue; }
22
22
  if (r.event !== 'llm-usage' || !r.data) continue;
23
- const d = r.data as { site?: string; provider?: string; billingProvider?: string; model?: string; inputTokens?: number; outputTokens?: number; cacheReadInputTokens?: number; cost?: { kind?: string; usd?: number } };
23
+ const d = r.data as { site?: string; provider?: string; billingProvider?: string; model?: string; inputTokens?: number; outputTokens?: number; cacheReadInputTokens?: number; cacheCreationInputTokens?: number; cost?: { kind?: string; usd?: number } };
24
24
  const provider = d.billingProvider ?? d.provider ?? '?'; // ⭐ 과금 주체 우선(B10)
25
25
  const key = `${d.site ?? '?'}|${provider}|${d.model ?? '?'}`;
26
- const row = by.get(key) ?? { site: d.site ?? '?', provider, model: d.model ?? '?', calls: 0, inputTokens: 0, outputTokens: 0, cacheReadInputTokens: 0, usdKnown: 0, unknownCostCalls: 0, includedCalls: 0, apiEquivalentUsd: 0 };
26
+ const row = by.get(key) ?? { site: d.site ?? '?', provider, model: d.model ?? '?', calls: 0, inputTokens: 0, outputTokens: 0, cacheReadInputTokens: 0, cacheCreationInputTokens: 0, cacheCreationUnmeasuredCalls: 0, usdKnown: 0, unknownCostCalls: 0, includedCalls: 0, apiEquivalentUsd: 0 };
27
27
  row.calls++;
28
28
  row.inputTokens += Number(d.inputTokens ?? 0);
29
29
  row.outputTokens += Number(d.outputTokens ?? 0);
30
30
  row.cacheReadInputTokens += Number(d.cacheReadInputTokens ?? 0);
31
+ // ⭐ 캐시 «쓰기»(Anthropic cache_creation_input_tokens) — 빠지면 호스트 원장이 0 으로 보고 재매김 $ 가 쓰기 비용을 잃는다.
32
+ row.cacheCreationInputTokens += Number(d.cacheCreationInputTokens ?? 0);
33
+ // 캐시 읽기는 보고했는데 쓰기 칸이 없는 호출은 쓰기량을 «모른다» — 0 으로 접지 않고 따로 센다(호스트 재매김이 이 수를 보고 멈춘다).
34
+ if (d.cacheReadInputTokens !== undefined && d.cacheCreationInputTokens === undefined) row.cacheCreationUnmeasuredCalls++;
31
35
  // ⛔ «모름»을 0 으로 접지 않는다 — partial 의 «알려진 몫»은 더하고, 모르는 호출은 따로 센다(BACKLOG C5).
32
36
  // ⭐ 구독·local(`included`)은 청구 0 이고 «모름»이 아니다 — 따로 세고 API 환산가는 별도 합(BACKLOG C6).
33
37
  if (d.cost?.kind === 'included') { row.includedCalls++; if (typeof (d.cost as { apiEquivalentUsd?: number }).apiEquivalentUsd === 'number') row.apiEquivalentUsd += (d.cost as { apiEquivalentUsd: number }).apiEquivalentUsd; }
@@ -0,0 +1,83 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { fetchLinearProjectIssues, type LinearProjectIssue } from '../src/connectors/linear.js';
3
+
4
+ type RecordedIssue = {
5
+ identifier: string; title: string; url: string; createdAt: string; updatedAt: string;
6
+ existingDueDate: string | null; priority: number;
7
+ };
8
+ type Evidence = {
9
+ project: string;
10
+ verifiedIssues: RecordedIssue[];
11
+ cohort: { excludedCurrentIssues: Array<{identifier: string; url: string; dueDate: string | null; priority: number; createdAt: string}> };
12
+ };
13
+ type LiveIssue = LinearProjectIssue & { createdAt: string };
14
+
15
+ export function compareCooEvidence(record: Evidence, live: LiveIssue[], truncated: boolean): string[] {
16
+ const errors: string[] = [];
17
+ if (truncated) errors.push('Linear result truncated');
18
+ if (live.length !== 33) errors.push(`current open count: ${live.length} != 33`);
19
+ if (record.verifiedIssues.length !== 29) errors.push(`recorded count: ${record.verifiedIssues.length} != 29`);
20
+ const sorted = [...live].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
21
+ const selected = sorted.slice(0, 29);
22
+ const excluded = sorted.slice(29);
23
+ const actual = new Map(live.map(issue => [issue.identifier, issue]));
24
+ if (actual.size !== live.length) errors.push('duplicate Linear identifier');
25
+ const seen = new Set<string>();
26
+ for (const row of record.verifiedIssues) {
27
+ if (seen.has(row.identifier)) errors.push(`duplicate recorded identifier: ${row.identifier}`);
28
+ seen.add(row.identifier);
29
+ const issue = actual.get(row.identifier);
30
+ if (!issue) { errors.push(`not in Linear: ${row.identifier}`); continue; }
31
+ for (const [field, expected, value] of [
32
+ ['title', row.title, issue.title], ['url', row.url, issue.url],
33
+ ['createdAt', row.createdAt, issue.createdAt], ['updatedAt', row.updatedAt, issue.updatedAt],
34
+ ['dueDate', row.existingDueDate, issue.dueDate], ['priority', row.priority, issue.priority],
35
+ ] as const) if (expected !== value) errors.push(`${row.identifier} ${field}: recorded=${String(expected)} Linear=${String(value)}`);
36
+ }
37
+ const selectedIds = selected.map(issue => issue.identifier).sort().join(',');
38
+ if ([...seen].sort().join(',') !== selectedIds) errors.push('recorded identifiers differ from oldest 29 currently open by createdAt');
39
+ if (selected.filter(issue => issue.dueDate !== null).length !== 4) errors.push('Linear selected dueDate count != 4');
40
+ if (selected.filter(issue => issue.priority !== 0).length !== 7) errors.push('Linear selected priority count != 7');
41
+ const excludedRecorded = record.cohort.excludedCurrentIssues;
42
+ if (excludedRecorded.map(issue => issue.identifier).sort().join(',') !== excluded.map(issue => issue.identifier).sort().join(',')) errors.push('excluded identifiers differ from Linear');
43
+ for (const row of excludedRecorded) {
44
+ const issue = actual.get(row.identifier);
45
+ if (!issue) continue;
46
+ if (row.url !== issue.url || row.createdAt !== issue.createdAt || row.dueDate !== issue.dueDate || row.priority !== issue.priority) errors.push(`excluded ${row.identifier} differs from Linear`);
47
+ }
48
+ return errors;
49
+ }
50
+
51
+ // Linear GraphQL read-only fetchLinearProjectIssues resolves the project and paginates the open issues.
52
+ // createdAt is queried separately because the shared COO tool's projection does not include it.
53
+ export async function readLiveCooIssues(apiKey: string, project: string): Promise<{ issues: LiveIssue[]; truncated: boolean }> {
54
+ const issues = await fetchLinearProjectIssues({apiKey, project});
55
+ const identifiers = issues.map(issue => issue.identifier);
56
+ if (new Set(identifiers).size !== identifiers.length) throw new Error('duplicate Linear identifier');
57
+ const query = 'query CooIssueCreation($id: String!) { issue(id: $id) { identifier createdAt } }';
58
+ const creations = await Promise.all(identifiers.map(async identifier => {
59
+ const response = await fetch('https://api.linear.app/graphql', {
60
+ method: 'POST', headers: {Authorization: apiKey, 'Content-Type': 'application/json'},
61
+ body: JSON.stringify({query, variables: {id: identifier}}),
62
+ });
63
+ if (!response.ok) throw new Error(`Linear creation read HTTP ${response.status}`);
64
+ const body = await response.json() as { errors?: unknown[]; data?: {issue?: {identifier: string; createdAt: string}} };
65
+ if (body.errors?.length || body.data?.issue?.identifier !== identifier || !body.data.issue.createdAt) throw new Error(`Linear creation read failed: ${identifier}`);
66
+ return body.data.issue.createdAt;
67
+ }));
68
+ return {issues: issues.map((issue, index) => ({...issue, createdAt: creations[index]!})), truncated: issues.truncated};
69
+ }
70
+
71
+ if (import.meta.main) {
72
+ const apiKey = process.env.LINEAR_API_KEY?.trim();
73
+ if (!apiKey) throw new Error('LINEAR_API_KEY absent; cannot compare recorded evidence to live Linear');
74
+ const record = JSON.parse(await readFile(new URL('../src/domains/coo-admin-dates.evidence.json', import.meta.url), 'utf8')) as Evidence;
75
+ const {issues, truncated} = await readLiveCooIssues(apiKey, record.project);
76
+ const errors = compareCooEvidence(record, issues, truncated);
77
+ if (errors.length) {
78
+ for (const error of errors) console.error(error);
79
+ process.exitCode = 1;
80
+ } else {
81
+ console.log(`PASS Linear live comparison: open=${issues.length} selected=${record.verifiedIssues.length} dueDates=${record.verifiedIssues.filter(issue => issue.existingDueDate !== null).length} priorities=${record.verifiedIssues.filter(issue => issue.priority !== 0).length} excluded=${record.cohort.excludedCurrentIssues.length}`);
82
+ }
83
+ }
package/src/acp/client.ts CHANGED
@@ -371,6 +371,8 @@ export function readClientInfo(
371
371
  export interface AcpAgentOpts {
372
372
  /** Backend id from ACP_BACKENDS. */
373
373
  backendId: string;
374
+ /** Review-owned ACP executable override; never changes the shared backend registry. */
375
+ backendSpec?: AcpBackendSpec;
374
376
  /** Working directory the agent runs in (cwd argument to spawn).
375
377
  * Affects file-tool resolution. Default: getSessionCwd() so a
376
378
  * Ctrl+W / /wd in the dashboard retargets new ACP agents. */
@@ -443,7 +445,7 @@ export class AcpAgent {
443
445
  private authMethods: string[] = [];
444
446
 
445
447
  constructor(opts: AcpAgentOpts) {
446
- this.spec = getAcpBackend(opts.backendId);
448
+ this.spec = opts.backendSpec ?? getAcpBackend(opts.backendId);
447
449
  // WD7 — default to the session working directory; ACP agents
448
450
  // inherit the "active project" concept.
449
451
  this.cwd = opts.cwd ?? getSessionCwd();
@@ -456,7 +458,7 @@ export class AcpAgent {
456
458
  // proactively. Mirrors zed's env-strip pattern for provider
457
459
  // tokens (acp.rs:232-243), generalized here for any env that
458
460
  // breaks nested agents.
459
- const cleanEnv: NodeJS.ProcessEnv = { ...process.env, ...opts.env };
461
+ const cleanEnv: NodeJS.ProcessEnv = opts.backendSpec && opts.env ? { ...opts.env, NODE_ENV: process.env.NODE_ENV } : { ...process.env, ...opts.env };
460
462
  for (const key of Object.keys(cleanEnv)) {
461
463
  if (NESTED_AGENT_ENV_BLOCKLIST.has(key) || /^CLAUDE_CODE_/.test(key)) {
462
464
  delete cleanEnv[key];
@@ -15,7 +15,7 @@
15
15
  // installations don't churn quickly and a BackendPickerChip re-render
16
16
  // should not trigger a fresh RPC roundtrip every time.
17
17
 
18
- import type { CodexAppServerClient } from './codex-app-server-client.js';
18
+ import { spawnCodexAppServer, type CodexAppServerClient } from './codex-app-server-client.js';
19
19
 
20
20
  export interface CodexPlugin {
21
21
  /** Plugin slug as reported by codex (e.g. "gmail", "google-calendar"). */
@@ -43,13 +43,55 @@ export interface FetchCodexPluginsOpts {
43
43
  noCache?: boolean;
44
44
  }
45
45
 
46
+ /** Uncached inventory probe: distinguish no session / RPC failure from an empty installed list. */
47
+ export async function readCodexPluginsObservation(client: CodexAppServerClient | null | undefined): Promise<
48
+ { status: 'ok'; plugins: ReadonlyArray<CodexPlugin> } | { status: 'unknown'; plugins: readonly [] }
49
+ > {
50
+ if (!client) return { status: 'unknown', plugins: [] };
51
+ try {
52
+ const response = await client.request<Record<string, never>, unknown>('plugin/list', {});
53
+ if (!isWellFormedPluginList(response)) return { status: 'unknown', plugins: [] };
54
+ return { status: 'ok', plugins: parseCodexPluginsResponse(response) };
55
+ } catch { return { status: 'unknown', plugins: [] }; }
56
+ }
57
+
58
+ /** Every marketplace and plugin row must have the shape the projector reads; a damaged or changed
59
+ * RPC response is unknown, never a confirmed empty install list. */
60
+ function isWellFormedPluginList(response: unknown): boolean {
61
+ if (!response || typeof response !== 'object') return false;
62
+ const marketplaces = (response as { marketplaces?: unknown }).marketplaces;
63
+ if (!Array.isArray(marketplaces)) return false;
64
+ return marketplaces.every(market => !!market && typeof market === 'object'
65
+ && typeof (market as { name?: unknown }).name === 'string' && (market as { name: string }).name.length > 0
66
+ && Array.isArray((market as { plugins?: unknown }).plugins)
67
+ && ((market as { plugins: unknown[] }).plugins).every(plugin => !!plugin && typeof plugin === 'object'
68
+ && typeof (plugin as { name?: unknown }).name === 'string' && (plugin as { name: string }).name.length > 0));
69
+ }
70
+
71
+ export type CodexPluginObservation = Awaited<ReturnType<typeof readCodexPluginsObservation>>;
72
+
73
+ /** Isolated read-only RPC probe; always closes its own app-server process. */
74
+ export async function readCodexPluginsFromAppServer(
75
+ spawn: typeof spawnCodexAppServer = spawnCodexAppServer,
76
+ ): Promise<CodexPluginObservation> {
77
+ let server: ReturnType<typeof spawnCodexAppServer>;
78
+ try { server = spawn({ requestTimeoutMs: 5000 }); }
79
+ catch { return { status: 'unknown', plugins: [] }; }
80
+ try {
81
+ await server.client.request('initialize', {
82
+ clientInfo: { name: 'elanous', version: '0.x' }, capabilities: { experimentalApi: true },
83
+ });
84
+ return await readCodexPluginsObservation(server.client);
85
+ } catch { return { status: 'unknown', plugins: [] }; }
86
+ finally {
87
+ try { await server.client.close(); }
88
+ finally { server.child.kill(); }
89
+ }
90
+ }
91
+
46
92
  /** Query codex `plugin/list` and project the response into the
47
93
  * BackendPickerChip-ready shape. Cached per client for 5 min.
48
- *
49
- * Returns an empty array when:
50
- * - `client` is null/undefined (no active codex session)
51
- * - the RPC throws (timeout / closed / codex error) — soft-fail
52
- * with stale cache if available, otherwise [] */
94
+ * Returns [] for no client or RPC failure (stale cache when available). */
53
95
  export async function fetchCodexPlugins(
54
96
  client: CodexAppServerClient | null | undefined,
55
97
  opts: FetchCodexPluginsOpts = {},
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { existsSync } from 'node:fs';
18
18
  import type { UserConfig } from '../user-config.js';
19
- import { runTurn } from '../session/chat.js';
19
+ import { runTurn, type RunTurnOpts } from '../session/chat.js';
20
20
  import type { SessionSource } from '../session/index.js';
21
21
  import { buildContinuationAgentTools } from '../dispatch/continuation-turn-runner.js';
22
22
  import { buildTerminalCapableTurn } from './terminal-surface.js';
@@ -56,6 +56,54 @@ function recentSentContext(): string {
56
56
  } catch { return ''; }
57
57
  }
58
58
 
59
+ interface ToolRun { id: string; name: string; result?: unknown }
60
+
61
+ const TOOL_RESULT_CLIP_CHARS = 1500;
62
+ const TOOL_RESULT_MAX_RUNS = 12;
63
+
64
+ function clipToolResult(result: unknown): string {
65
+ if (result === undefined) return '(결과 없음)';
66
+ let text: string;
67
+ try { text = typeof result === 'string' ? result : JSON.stringify(result) ?? String(result); } catch { text = String(result); }
68
+ return text.length > TOOL_RESULT_CLIP_CHARS ? `${text.slice(0, TOOL_RESULT_CLIP_CHARS)}…` : text;
69
+ }
70
+
71
+ /** 툴만 부르고 최종 텍스트가 빈 턴 — 관측을 남기고 툴 결과 요약 재턴을 한 번 돌린다. 재턴도 비면 바닥줄이 아니라
72
+ * 실패 문구를 돌려준다. 세션 재생은 role:'tool' 기록을 빼므로 재턴 프롬프트가 툴 결과를 직접 싣는다. */
73
+ async function recoverEmptyAnswer(args: {
74
+ runTurnImpl: typeof runTurn;
75
+ opts: RunTurnOpts;
76
+ llmOpts: RunTurnOpts['llmOpts'];
77
+ systemPrompt: string;
78
+ toolRuns: ToolRun[];
79
+ surface: SessionSource;
80
+ }): Promise<string> {
81
+ const { runTurnImpl, opts, llmOpts, systemPrompt, toolRuns, surface } = args;
82
+ let message = '';
83
+ let sawToolCall = false;
84
+ let retryText = '';
85
+ try {
86
+ const summary = toolRuns.slice(-TOOL_RESULT_MAX_RUNS)
87
+ .map((run) => `- ${run.name}: ${clipToolResult(run.result)}`).join('\n');
88
+ const retry = await runTurnImpl({
89
+ ...opts,
90
+ userText: `[툴 결과 요약 재턴] 아래 툴 실행 결과를 근거로 사용자 질문에 대한 최종 답을 텍스트로 작성하세요. 툴은 더 부르지 마세요.\n\n사용자 질문: ${opts.userText}\n\n툴 결과:\n${summary}`,
91
+ onDelta: (delta) => { message += delta; },
92
+ onToolCall: () => { message = ''; sawToolCall = true; },
93
+ onToolResult: () => {},
94
+ skipMemoryInjection: true,
95
+ llmOpts,
96
+ systemPrompt,
97
+ tools: [],
98
+ });
99
+ retryText = (sawToolCall ? message : retry.text)?.trim() ?? '';
100
+ } catch { /* 재턴 실패는 아래 실패 문구로 */ }
101
+ debug.log('agent.turn', 'empty-answer', {
102
+ surface, sessionId: opts.sessionId, toolCalls: toolRuns.length, recovered: retryText !== '',
103
+ });
104
+ return retryText || `⚠️ 답을 만들지 못했다 — 툴 ${toolRuns.length}개 실행`;
105
+ }
106
+
59
107
  /** Build the tool-enabled elanous self runTurn for a messenger surface:
60
108
  * the full agent tool surface (Read/Grep/Glob/ListDir/Edit/Write +
61
109
  * Bash + PtyShell + search), plus — when the finance domain pack is
@@ -229,6 +277,8 @@ export function makeElanousAgentRunTurn(cfg: UserConfig, surface: SessionSource,
229
277
  llmOpts = terminal.llmOpts;
230
278
  let currentMessage = '';
231
279
  let sawToolCall = false;
280
+ const toolRuns: ToolRun[] = [];
281
+ const systemPrompt = terminal.systemPromptParts.join('\n\n');
232
282
  return runTurnImpl({
233
283
  ...opts,
234
284
  onDelta: (delta) => {
@@ -238,21 +288,33 @@ export function makeElanousAgentRunTurn(cfg: UserConfig, surface: SessionSource,
238
288
  onToolCall: (call) => {
239
289
  currentMessage = '';
240
290
  sawToolCall = true;
291
+ toolRuns.push({ id: call.id, name: call.name });
241
292
  opts.onToolCall?.(call);
242
293
  },
294
+ onToolResult: (call) => {
295
+ const run = toolRuns.find((candidate) => candidate.id === call.id);
296
+ if (run) run.result = call.result;
297
+ opts.onToolResult?.(call);
298
+ },
243
299
  llmOpts,
244
- systemPrompt: terminal.systemPromptParts.join('\n\n'),
300
+ systemPrompt,
245
301
  tools: terminal.specs,
246
302
  dispatchTool: terminal.dispatch,
247
- }).then((result) => {
303
+ }).then(async (result) => {
248
304
  // /cancel self-awareness — when the turn was aborted mid-run (user hit
249
305
  // `/cancel`), the tool loop returns with little/no final text. Substitute
250
306
  // a CLEAR cancellation marker so (a) the user gets an ack, and (b) it is
251
307
  // the text recorded to cross-surface memory (recordInboundTurn) — so the
252
308
  // NEXT turn's memory_recall knows the task was CANCELLED, not silently
253
309
  // dropped or still running. Only turnAbort (=/cancel) aborts this signal.
254
- const wasAborted = opts.signal?.aborted === true;
255
- const answer = sawToolCall ? currentMessage.trim() : result.text;
310
+ let wasAborted = opts.signal?.aborted === true;
311
+ let answer = sawToolCall ? currentMessage.trim() : result.text;
312
+ // Telegram only: other messenger surfaces (Discord …) keep their current final-answer behaviour.
313
+ if (!wasAborted && sawToolCall && !answer && surface === 'telegram') {
314
+ answer = await recoverEmptyAnswer({ runTurnImpl, opts, llmOpts, systemPrompt, toolRuns, surface });
315
+ // A /cancel that lands during the retry turn still wins over the retry answer or the failure sentence.
316
+ if (opts.signal?.aborted === true) { wasAborted = true; answer = ''; }
317
+ }
256
318
  const responseText = wasAborted
257
319
  ? (answer?.trim()
258
320
  ? `${answer}\n\n⏹️ 이 작업은 /cancel 로 취소되었습니다 (실행 중이던 Bash/PTY 종료됨).`
@@ -9,6 +9,7 @@
9
9
 
10
10
  import { normalizeChildLlmProvider } from '../self-dev/dev-cli.js';
11
11
  import { providerEnvKey } from '../llm/provider-credentials.js';
12
+ import { bedrockChildRelayEnv } from '../llm/bedrock.js';
12
13
 
13
14
  export type RunContext = 'production' | 'benchmark' | 'simulator' | 'self-build';
14
15
 
@@ -54,6 +55,8 @@ export interface ChildLlmSelection {
54
55
  effort?: ChildLlmEffort;
55
56
  /** 선택이 CLI 플래그에서 왔나, self-dev 설정에서 왔나. 같은 모델이라도 다른 사실이다. */
56
57
  source: 'flag' | 'config';
58
+ /** Grok weekly cap rerouted this run to Codex: allow prepaid credits even when subscription quota is exhausted. */
59
+ codexQuotaPolicy?: 'credits';
57
60
  }
58
61
 
59
62
  /** ⭐⭐ **가르는 축은 「키냐 주소냐」가 «아니라» 「그 자격이 «파일»에 사나 «env»에 사나」다**
@@ -76,6 +79,12 @@ function childLocalEndpointEnv(provider: string): Record<string, string> {
76
79
  return url ? { LOCAL_LLM_URL: url } : {};
77
80
  }
78
81
 
82
+ /** BEDROCK-PROVIDER — Bedrock 자격은 «파일»(~/.aws · HOME 으로 자식이 그대로 읽는다)과 «env»(AWS_*) 둘 다에 산다.
83
+ * env 쪽은 replace env 라 상속이 없으므로 이름 목록대로 릴레이한다(값은 싣기만 하고 어디에도 찍지 않는다). */
84
+ function childBedrockEnv(provider: string): Record<string, string> {
85
+ return provider === 'bedrock' ? bedrockChildRelayEnv() : {};
86
+ }
87
+
79
88
  /** The family classifier is model-id based, so preserve local-provider identity
80
89
  * across the replace-env child boundary without changing non-local model IDs. */
81
90
  function childRelayModel(provider: string, model: string): string {
@@ -91,6 +100,8 @@ export function childLlmSelectionEnv(selection?: ChildLlmSelection): Record<stri
91
100
  return {
92
101
  ELANOUS_LLM_PROVIDER: provider,
93
102
  ELANOUS_LLM_MODEL: childRelayModel(provider, selection.model),
103
+ ...(selection.codexQuotaPolicy === 'credits' && provider === 'openai-codex'
104
+ ? { ELANOUS_CODEX_QUOTA_POLICY: 'credits' } : {}),
94
105
  // ⛔⭐ 새 env 이름을 «짓지 않는다» — `ELANOUS_ESCALATE_EFFORT` 가 «이미» 있고
95
106
  // `user-config.ts` 가 그것으로 `reasoningLevel`(anthropic)과
96
107
  // `codexReasoning.effort`(openai-codex/sol) 를 ***둘 다*** 덮는다.
@@ -98,6 +109,7 @@ export function childLlmSelectionEnv(selection?: ChildLlmSelection): Record<stri
98
109
  ...(selection.effort ? { ELANOUS_ESCALATE_EFFORT: selection.effort } : {}),
99
110
  ...childProviderKeyEnv(provider),
100
111
  ...childLocalEndpointEnv(provider),
112
+ ...childBedrockEnv(provider),
101
113
  };
102
114
  }
103
115
  // ⛔⭐ 상속 갈래도 local 이면 «주소»를 같이 넘긴다(BACKLOG B12 · 2026-09-25).
@@ -108,5 +120,7 @@ export function childLlmSelectionEnv(selection?: ChildLlmSelection): Record<stri
108
120
  ...(process.env.ELANOUS_LLM_PROVIDER !== undefined ? { ELANOUS_LLM_PROVIDER: process.env.ELANOUS_LLM_PROVIDER } : {}),
109
121
  ...(process.env.ELANOUS_LLM_MODEL !== undefined ? { ELANOUS_LLM_MODEL: process.env.ELANOUS_LLM_MODEL } : {}),
110
122
  ...(inheritedProvider ? childLocalEndpointEnv(inheritedProvider) : {}),
123
+ // 상속 갈래도 bedrock 이면 AWS_* 를 같이 넘긴다(명시 갈래와 같은 규칙 — replace env 라 자동 상속이 없다).
124
+ ...(inheritedProvider ? childBedrockEnv(inheritedProvider) : {}),
111
125
  };
112
126
  }
@@ -15,11 +15,27 @@
15
15
  // ELANOUS_CHILD_TOOL_PROFILE=full 전부
16
16
  // ELANOUS_CHILD_TOOL_PROFILE=finance,ops 기본 ⊕ 고른 묶음
17
17
  // (없음) coding(기본)
18
+ //
19
+ // 🩸 CHILD-TOOL-PROFILE-TRIM(10-10 실측 · base 0317d73034 · Plan 켬): `coding` 이 33개 중 27개(스키마 26,742자)를
20
+ // 남겼다 — 판·자리 운영·회수·스킬·서브에이전트 도구가 «어느 묶음에도 안 들어서» 기본으로 갔을 뿐이다.
21
+ // ⇒ 화이트리스트를 따로 두지 않고(09-25 설계 유지) 그것들을 새 묶음 넷(admin · recall · skills · subagent)으로 옮긴다.
22
+ // ⇒ `coding` 의 기대 집합 = Read · Grep · Glob · ListDir · Edit · Write · Bash · Plan · MarkStepDone(9개).
23
+ // 빠진 묶음은 상황 신호(골 문면)와 ToolSearch(전체 목록에서 찾는다)로 계속 닿는다.
24
+
25
+ import { debug } from '../debug/log.js';
18
26
 
19
27
  /** 추가 묶음 — 코딩 기본에서 빠지고 «고르면 더해지는» 도구들. 접두 ⊕ 정확한 이름. */
20
28
  export const TOOL_EXTRA_GROUPS = {
21
29
  finance: { prefixes: ['finance_', 'conatus_'], names: [] as string[] },
22
30
  ops: { prefixes: [] as string[], names: ['schedule_manage', 'session_manage', 'autopilot_missions', 'ops_status', 'se_build', 'mission_decide'] },
31
+ /** 판·자리·결정 운영 — 코딩 일에는 안 쓴다. */
32
+ admin: { prefixes: ['release_'], names: ['coo_admin', 'ops_seats', 'decisions_pending', 'proact_meter'] },
33
+ /** 기억·회수·관측 조회. */
34
+ recall: { prefixes: [] as string[], names: ['memory_recall', 'fact_check', 'self_recall', 'context_now', 'logs_query'] },
35
+ /** 스킬 목록·실행. */
36
+ skills: { prefixes: [] as string[], names: ['elanous_skills_list', 'skill_exec'] },
37
+ /** 서브에이전트 — ⚠️ 기본에서 빼도 완주율이 안 떨어지는지는 아직 안 쟀다(SMALL-MODEL-BENCH 가 잰다). 신호·ToolSearch 로 되살린다. */
38
+ subagent: { prefixes: [] as string[], names: ['Agent', 'AgentOutput', 'AgentReply', 'AgentStop', 'AgentList'] },
23
39
  } as const;
24
40
  export type ToolExtraGroup = keyof typeof TOOL_EXTRA_GROUPS;
25
41
  const ALL_GROUPS = Object.keys(TOOL_EXTRA_GROUPS) as ToolExtraGroup[];
@@ -45,6 +61,10 @@ export function activeToolProfile(env: NodeJS.ProcessEnv = process.env): ToolPro
45
61
  export const SITUATIONAL_GROUP_SIGNALS: Record<ToolExtraGroup, RegExp> = {
46
62
  finance: /금융|주식|종목|주가|시세|매매|포트폴리오|포지션|투자|백테스트|13F|재무|finance_|conatus|stock|ticker|portfolio|backtest|trading/i,
47
63
  ops: /스케줄|크론|예약 실행|오토파일럿|미션 결정|운영 상태|schedule_manage|autopilot|ops_status|mission_decide|cron/i,
64
+ admin: /release_(status|change)|coo_admin|ops_seats|decisions_pending|proact_meter|판 칸|칸 근거|칸 상태|체크리스트 칸|checklist (set|status)|결정 대기|자리 현황/i,
65
+ recall: /memory_recall|fact_check|self_recall|context_now|logs_query|기억 조회|기억을 (찾|조회|회수)|자기 이력|사실 확인|팩트 ?체크/i,
66
+ skills: /elanous_skills_list|skill_exec|스킬(을)? 실행|스킬 목록|run (a|the) skill/i,
67
+ subagent: /서브\s?에이전트|하위\s?에이전트|sub-?agents?|에이전트를 (띄|병렬)|병렬 에이전트|Agent(Output|Reply|Stop|List)\b|Agent 도구/i,
48
68
  };
49
69
 
50
70
  export function situationalToolGroups(goalText: string | undefined): ToolExtraGroup[] {
@@ -58,9 +78,15 @@ export function situationalToolGroups(goalText: string | undefined): ToolExtraGr
58
78
  * ③ 둘 다 없으면 `coding`(다이어트) */
59
79
  export function childToolProfile(env: NodeJS.ProcessEnv = process.env, goalText?: string): string {
60
80
  const explicit = env.ELANOUS_CHILD_TOOL_PROFILE?.trim();
61
- if (explicit) return explicit;
81
+ if (explicit) {
82
+ const parsed = parseToolProfile(explicit);
83
+ debug.log('agent.tool-profile', 'child-profile-chosen', { source: 'env', raw: explicit, profile: parsed?.name ?? 'coding', groups: parsed ? [...parsed.groups] : [] });
84
+ return explicit;
85
+ }
62
86
  const groups = situationalToolGroups(goalText);
63
- return groups.length ? groups.join(',') : 'coding';
87
+ const profile = groups.length ? groups.join(',') : 'coding';
88
+ debug.log('agent.tool-profile', 'child-profile-chosen', { source: groups.length ? 'situational' : 'default', profile, groups, goalChars: goalText?.length ?? 0 });
89
+ return profile;
64
90
  }
65
91
 
66
92
  /** 기본 모드에서 뺀 묶음을 자식에게 «한 줄»로 알린다 — 필요하면 ToolSearch 로 불러 쓴다(스키마는 안 싣는다). */