elanous 0.2.22 → 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 (705) 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-80ed511e02c81412.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/{aBi6EyMtLsrl7J8eH4kF7 → 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/log-horizon/log-horizon-watch.yaml +25 -0
  288. package/graphs/log-horizon/recipes.yaml +3 -0
  289. package/graphs/release/recipes.yaml +1 -1
  290. package/graphs/release/release-loop.yaml +6 -2
  291. package/graphs/release-rehearsal/recipes.yaml +12 -0
  292. package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
  293. package/package.json +4 -1
  294. package/scripts/bench-report.ts +82 -3
  295. package/scripts/ci-typecheck-changed.ts +10 -1
  296. package/scripts/hq/hq-fence-wrapper.sh +148 -0
  297. package/scripts/lib/typecheck-ratchet.ts +51 -0
  298. package/scripts/openai-relay-server.ts +5 -1
  299. package/scripts/release-loop/docs-node.ts +258 -43
  300. package/scripts/release-loop/gate-method.ts +59 -0
  301. package/scripts/release-loop/gate-node.ts +73 -7
  302. package/scripts/release-loop/gate-wall.ts +208 -0
  303. package/scripts/release-loop/known-issues-node.ts +53 -8
  304. package/scripts/release-loop/publish-at.ts +14 -0
  305. package/scripts/release-loop/publish-node.ts +17 -2
  306. package/scripts/release-loop/resume-release.ts +34 -4
  307. package/scripts/release-loop/resume.ts +53 -0
  308. package/scripts/release-loop/shard-plan.ts +3 -11
  309. package/scripts/release-loop/tui-node-checks.ts +22 -0
  310. package/scripts/release-loop/unattended-release.ts +8 -1
  311. package/scripts/rhythm/daily.ts +51 -2
  312. package/scripts/rhythm/weekly.ts +3 -2
  313. package/scripts/tsc-main-safety-net.ts +189 -0
  314. package/scripts/usage-rollup.ts +8 -4
  315. package/src/acp/codex-plugins.ts +48 -6
  316. package/src/agent/monad-agent-turn.ts +67 -5
  317. package/src/agent/run-context.ts +10 -0
  318. package/src/agent/tool-profile.ts +28 -2
  319. package/src/agent-mission/acp-judge.ts +8 -2
  320. package/src/agent-mission/capabilities-cli.ts +16 -1
  321. package/src/agent-mission/driver.ts +1 -1
  322. package/src/agent-mission/pr-review-watch.ts +6 -2
  323. package/src/agent-mission/review-loop.ts +33 -5
  324. package/src/agent-substrate/acp-reviewer.ts +17 -8
  325. package/src/agent-substrate/pr-reviewer.ts +164 -28
  326. package/src/agent-substrate/review-intent.ts +6 -4
  327. package/src/agent-substrate/self-review-cli.ts +111 -16
  328. package/src/agent-substrate/shard-boundary-intent.ts +92 -26
  329. package/src/ask-user-question/pending-questions.ts +8 -2
  330. package/src/autopilot/build/llm-conflict-merge.ts +216 -12
  331. package/src/autopilot/codebase-grounding.ts +44 -0
  332. package/src/autopilot/llm-control-brain.ts +13 -1
  333. package/src/autopilot/mission-codebase-gate.ts +8 -77
  334. package/src/autopilot/pr-manager.ts +12 -3
  335. package/src/boot/acp-server.ts +4 -7
  336. package/src/boot/acp-socket-path.ts +7 -0
  337. package/src/briefing/brief-items.ts +21 -13
  338. package/src/chat/index.ts +12 -3
  339. package/src/cli/agent-cli.ts +20 -0
  340. package/src/cli/brief-cli.ts +27 -21
  341. package/src/cli/cli-user-error.ts +9 -2
  342. package/src/cli/log-event-names.ts +3 -0
  343. package/src/cli/logs-cli.ts +1 -0
  344. package/src/cli/mcp-login.ts +111 -37
  345. package/src/cli/plugin-cli.ts +21 -1
  346. package/src/cli/pod-cli.ts +26 -0
  347. package/src/cli/pr-cli.ts +30 -2
  348. package/src/cli/pr-land-overlap-evidence.ts +131 -0
  349. package/src/cli/release-cli.ts +53 -11
  350. package/src/cli/self-update.ts +173 -10
  351. package/src/cli/skills-cli.ts +12 -3
  352. package/src/cli/tasks-cli.ts +133 -27
  353. package/src/context-bus/context-first.ts +51 -2
  354. package/src/context-bus/context-now-surfaces.ts +13 -2
  355. package/src/context-bus/long-term-memory.ts +3 -1
  356. package/src/context-bus/nightly-condense.ts +3 -2
  357. package/src/core-turn/run-goal-loop.ts +86 -2
  358. package/src/dashboard/chat-fold.ts +20 -0
  359. package/src/dashboard/first-screen-band.ts +151 -1
  360. package/src/dashboard/index.ts +27 -5
  361. package/src/dashboard/slash-runtime/dashboard-handlers.ts +5 -3
  362. package/src/dashboard/stale-install-check.ts +13 -2
  363. package/src/dashboard/turn-stream-formatter.ts +25 -0
  364. package/src/debug/log-diet.ts +159 -0
  365. package/src/debug/log.ts +52 -17
  366. package/src/display/coordinator.ts +25 -2
  367. package/src/domains/coo-admin-tool.ts +27 -0
  368. package/src/domains/cron-match.ts +1 -0
  369. package/src/domains/outbound-alert.ts +17 -6
  370. package/src/domains/release-tool.ts +119 -10
  371. package/src/domains/schedule-registry.ts +10 -7
  372. package/src/domains/schedule-runner.ts +1 -0
  373. package/src/elanous-config-dir.ts +2 -2
  374. package/src/elanous-daemon.ts +3 -3
  375. package/src/execution-loop/launch-gate.ts +1 -1
  376. package/src/expression/i18n/messages.en.ts +5 -0
  377. package/src/expression/i18n/messages.ja.ts +5 -0
  378. package/src/expression/i18n/messages.ko.ts +5 -0
  379. package/src/expression/i18n/messages.zh.ts +5 -0
  380. package/src/expression/i18n/types.ts +8 -0
  381. package/src/github/pr-labels.ts +1 -0
  382. package/src/graph-runner/runner.ts +54 -5
  383. package/src/harness/dispatch-backpressure.ts +259 -0
  384. package/src/harness/harness-cli-command.ts +107 -28
  385. package/src/harness/harness-seams.ts +2 -20
  386. package/src/harness/harness-substrate-default.ts +72 -1
  387. package/src/harness/nested-elanous-policy.ts +4 -2
  388. package/src/hq/fence-wrapper.ts +7 -0
  389. package/src/hq/hq.ts +33 -2
  390. package/src/hq/lease.ts +13 -0
  391. package/src/hq/seats.ts +114 -18
  392. package/src/index.ts +163 -64
  393. package/src/intake-plane/collect-github.ts +19 -1
  394. package/src/intake-plane/digest.ts +45 -20
  395. package/src/intake-plane/lens.ts +36 -8
  396. package/src/intelligence-map/model-alias.ts +6 -0
  397. package/src/intelligence-map/model-catalog.ts +41 -0
  398. package/src/knowledge/kgs/pack.ts +5 -2
  399. package/src/knowledge/kgs/sqlite-store.ts +15 -0
  400. package/src/knowledge/tools/knowledge-query.ts +20 -2
  401. package/src/knowledge/write.ts +234 -2
  402. package/src/llm/bedrock-provider.ts +175 -0
  403. package/src/llm/bedrock.ts +345 -0
  404. package/src/llm/provider-credentials.ts +3 -1
  405. package/src/llm.ts +306 -35
  406. package/src/loops/budget.ts +150 -0
  407. package/src/loops/orchestrator/seat-share.ts +6 -49
  408. package/src/loops/orchestrator/traffic.ts +5 -81
  409. package/src/market/signed-index.ts +42 -0
  410. package/src/mcp/mcp-oauth.ts +136 -17
  411. package/src/model-tier/llm-tier-map.ts +48 -4
  412. package/src/models/prompts.ts +22 -1
  413. package/src/mss/logging/horizon-watch.ts +168 -0
  414. package/src/mss/logging/log-store.ts +204 -15
  415. package/src/native-tool-catalog.ts +1 -1
  416. package/src/nexus/api/consult-requests.ts +7 -10
  417. package/src/nexus/api/discord-trigger-bot.ts +6 -3
  418. package/src/nexus/api/error-reports.ts +30 -8
  419. package/src/nexus/api/http-server.ts +8 -0
  420. package/src/nexus/api/loop-resources.ts +42 -0
  421. package/src/nexus/api/outbound-report.ts +8 -3
  422. package/src/nexus/api/telegram-trigger-bot.ts +6 -3
  423. package/src/nexus/index.ts +10 -0
  424. package/src/nexus/outbound/format.ts +2 -0
  425. package/src/nexus/outbound/router.ts +198 -13
  426. package/src/oauth/codex-account-rotation.ts +16 -18
  427. package/src/oauth/codex-account-store.ts +134 -5
  428. package/src/oauth/fallback-chain.ts +28 -6
  429. package/src/onboarding.ts +2 -1
  430. package/src/plugins/adapters/claude-package.ts +4 -12
  431. package/src/plugins/core/capability-policy.ts +141 -0
  432. package/src/plugins/core/host.ts +21 -8
  433. package/src/plugins/core/manifest.ts +19 -2
  434. package/src/plugins/core/trust-store.ts +15 -0
  435. package/src/plugins/core/types.ts +12 -0
  436. package/src/plugins/install/market-fetch.ts +68 -16
  437. package/src/plugins/install/plugin-install.ts +187 -16
  438. package/src/plugins/maker/plugin-maker.ts +25 -20
  439. package/src/plugins/maker/wizard-generate.ts +16 -2
  440. package/src/policy/llm-policy.ts +14 -1
  441. package/src/process/pid-liveness.ts +1 -1
  442. package/src/prompt-cache/openai.ts +10 -6
  443. package/src/prompt-cache/openrouter.ts +94 -0
  444. package/src/prompt-enhance/enhance.ts +46 -5
  445. package/src/prompt-library/family-prompt-coverage.ts +1 -0
  446. package/src/prompt-library/universal-preamble.ts +2 -2
  447. package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
  448. package/src/registry/loader.ts +6 -1
  449. package/src/release-loop/checklist.ts +24 -9
  450. package/src/release-loop/feature-store.ts +3 -0
  451. package/src/release-loop/gate-shards.ts +48 -4
  452. package/src/release-loop/landed-to-green.ts +81 -0
  453. package/src/release-loop/light-rc.ts +11 -1
  454. package/src/release-loop/merged-pr-checklist.ts +10 -0
  455. package/src/release-loop/placement.ts +91 -22
  456. package/src/release-loop/rehearsal.ts +317 -0
  457. package/src/release-loop/release-schedule.ts +13 -1
  458. package/src/release-loop/rubric-types.ts +1 -0
  459. package/src/release-loop/rubric.ts +2 -2
  460. package/src/retro/daily.ts +23 -9
  461. package/src/seat-loop/seat-loop.ts +34 -1
  462. package/src/seat-loop/traffic-signal.ts +44 -0
  463. package/src/self-dev/ask-launch-flow.ts +2 -2
  464. package/src/self-dev/dev-cli.ts +67 -3
  465. package/src/self-dev/dev-pipeline.ts +4 -6
  466. package/src/self-dev/draft-residue.ts +463 -0
  467. package/src/self-dev/draft-sweep.ts +151 -10
  468. package/src/self-dev/draft-triage-rules.ts +27 -1
  469. package/src/self-dev/launch-preflight-text.ts +549 -0
  470. package/src/self-dev/launch-preflight.ts +10 -545
  471. package/src/self-dev/orchestrate-cli.ts +57 -2
  472. package/src/self-dev/orchestrate-summary-line.ts +13 -0
  473. package/src/self-dev/orchestrate.ts +8 -135
  474. package/src/self-dev/review-provider-fallback.ts +115 -19
  475. package/src/self-dev/run-store.ts +1 -3
  476. package/src/self-dev/run-supervisor.ts +3 -22
  477. package/src/self-dev/run-types.ts +178 -0
  478. package/src/self-dev/shard-aggregate.ts +61 -13
  479. package/src/self-dev/shard-plan.ts +5 -1
  480. package/src/self-dev/shard-run.ts +23 -5
  481. package/src/self-dev/supervisor-verdict-edges.ts +2 -4
  482. package/src/self-implement/blocked-draft-policy.ts +3 -19
  483. package/src/self-implement/draft-on-stop-mode.ts +18 -0
  484. package/src/self-implement/follow-up-goals.ts +114 -38
  485. package/src/self-implement/gate-baseline-reap.ts +157 -0
  486. package/src/self-implement/gate-baseline.ts +78 -16
  487. package/src/self-implement/gate-cli.ts +12 -2
  488. package/src/self-implement/gate-remote.ts +17 -6
  489. package/src/self-implement/goal-author.ts +24 -4
  490. package/src/self-implement/goal-digest.ts +19 -0
  491. package/src/self-implement/graph-overlay-condition.ts +4 -0
  492. package/src/self-implement/headless-elanous-driver.ts +11 -9
  493. package/src/self-implement/host-regate.ts +120 -29
  494. package/src/self-implement/l8-merge-queue.ts +67 -5
  495. package/src/self-implement/merge-train.ts +131 -0
  496. package/src/self-implement/off-diff-evidence.ts +9 -0
  497. package/src/self-implement/orchestrator.ts +133 -16
  498. package/src/self-implement/review-finding-recurrence.ts +28 -0
  499. package/src/self-implement/rework-policy.ts +2 -1
  500. package/src/self-implement/round-summary-card.ts +63 -0
  501. package/src/self-implement/run-ledger.ts +4 -3
  502. package/src/self-implement/run-step-projection.ts +147 -0
  503. package/src/self-implement/run-stop.ts +1 -1
  504. package/src/self-implement/seams.ts +36 -3
  505. package/src/self-implement/self-implement-cli.ts +3 -1
  506. package/src/self-implement/train-gate-remote.ts +158 -0
  507. package/src/session-runtime/index.ts +10 -1
  508. package/src/session-runtime/retry-api.ts +11 -1
  509. package/src/skills/gift-install.ts +119 -0
  510. package/src/skills/runner.ts +59 -2
  511. package/src/skills/skill-feedback.ts +31 -1
  512. package/src/skills/skill-tier.ts +1 -0
  513. package/src/smart-wizard/capability-index.ts +231 -0
  514. package/src/smart-wizard/rung.ts +74 -0
  515. package/src/steward/launch.ts +20 -9
  516. package/src/steward/triage.ts +4 -2
  517. package/src/storage/file-lock.ts +8 -1
  518. package/src/task-agent/actions.ts +4 -0
  519. package/src/task-agent/card-evidence.ts +59 -13
  520. package/src/task-agent/judge.ts +4 -3
  521. package/src/task-agent/land-worktree.ts +201 -0
  522. package/src/task-agent/live-move-history.ts +133 -0
  523. package/src/task-agent/live-moves.ts +106 -19
  524. package/src/task-agent/parent-host.ts +117 -8
  525. package/src/task-agent/rejudge-on-head.ts +297 -0
  526. package/src/task-agent/review-result-capture.ts +218 -0
  527. package/src/task-agent/shadow.ts +103 -7
  528. package/src/task-agent/task-hand.ts +136 -11
  529. package/src/task-orchestrator/surfaces/pod-child-providers.ts +29 -0
  530. package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
  531. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +16 -2
  532. package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
  533. package/src/task-orchestrator/surfaces/pod-lease.ts +93 -12
  534. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +25 -2
  535. package/src/task-orchestrator/surfaces/pod-pool.ts +66 -14
  536. package/src/task-orchestrator/surfaces/self-implement-pod.ts +259 -36
  537. package/src/task-orchestrator/surfaces/self-implement.ts +6 -2
  538. package/src/telegram-service.ts +5 -1
  539. package/src/telegram.ts +17 -4
  540. package/src/time/format.ts +13 -4
  541. package/src/tool-runtime/goal-author-runtime.ts +1 -0
  542. package/src/tool-runtime/self-cognition-catalog.ts +23 -0
  543. package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
  544. package/src/user-config.ts +132 -24
  545. package/src/ux-sim/slash-menu-frames.ts +168 -0
  546. package/src/version/packed-revision.json +1 -1
  547. package/src/web-terminal/preview-tap-registry.ts +5 -2
  548. package/src/workflow-runtime/triggers/scheduler.ts +1 -0
  549. package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
  550. package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
  551. package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
  552. package/apps/pwa/out/_next/static/chunks/1307-08b716476f1d50af.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
  554. package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
  555. package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
  556. package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
  558. package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
  563. package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
  572. package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
  573. package/apps/pwa/out/_next/static/chunks/2489-d238d3e2eb5b2bf5.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
  586. package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/3857-5985236d9307f676.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
  594. package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
  599. package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
  601. package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
  605. package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/5633-d6852385000738ef.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
  610. package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/5977-5b9e8a45a5b0c823.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
  615. package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
  616. package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
  618. package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
  619. package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
  627. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
  630. package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
  640. package/apps/pwa/out/_next/static/chunks/8857-aa1cc4ac90af4d40.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
  643. package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/9247-55bcfbb0e8057f59.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
  647. package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
  648. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/approvals/page-88459e0903da2803.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d85c43f46f58716b.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/board/page-4e645600579ae952.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/botlab/page-87edbfd19117823b.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/bots/page-7f0c2b7801ac6a54.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/ceo/page-bf1f030a9d1adffd.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/chat/page-cbaf66b1e1804adf.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/control/page-9f5610caaa06178c.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/decisions/page-ec8f3575e339de74.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/design-check/page-86d753e460f1a989.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/editor/page-4166a7d51cf0a57d.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/exec/page-2a19c5cd3b562580.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/field/page-b6a09cde2e07521a.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/inside/page-f7eae1518ca0c353.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/intake/page-456a8573ad811381.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/layout-8462d6a543cbb2d9.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/live/page-2974cdfb87c0f9c9.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f927ffa25f3c86d1.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/loops/page-abd86cd832aaa011.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/market/page-79daf68f6256adaa.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8c3f168fc3f91939.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/morning/page-786fb4504d0f2fa9.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/not-found-75209f14597dcb8f.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/observatory/page-bf30affe3a85af7e.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1187a44b7515434b.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-3d0910185a66ed54.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f401ee1dd5a26e25.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5dfe7604fd842784.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/page-76cf838050a8d681.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7ec8e289b4c14df6.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-8c8ac17d52be2a79.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d359ab048d63a9d9.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-b8b345c880bf78d1.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/settings/page-f151cc10ad026940.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9875f103057da433.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/setup/page-9789328af9a9aa62.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/share/page-bf495a1e284f4e00.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/showroom/page-a263d94bca4be22a.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/tasks/page-3962eab8ec58d16e.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/term/page-9abcfac07e02a542.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/today/page-bee49f927c333abb.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/trace/page-bac2d56dcb02d955.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/vault/page-937cbcc13176295c.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d09495594f7f480d.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/workflows/page-69cb93d1a2e57e0e.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/workspace/page-72ec543928d67c3e.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-82906eeda0186a7b.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
  704. package/apps/pwa/out/_next/static/css/f2bd5257e6af88d8.css +0 -1
  705. /package/apps/pwa/out/_next/static/{aBi6EyMtLsrl7J8eH4kF7 → rfkMm4movqkqMebBrCXiR}/_ssgManifest.js +0 -0
@@ -30,7 +30,8 @@ import type { ReasoningEffortCeiling } from '../intelligence-map/model-catalog.j
30
30
  import { tierModel } from '../llm/model-defaults.js';
31
31
  import { LLM_TIER_MAP_BY_PROVIDER } from '../model-tier/llm-tier-map.js';
32
32
  import { MODEL_TIERS } from '../model-tier/types.js';
33
- import { getCatalog } from '../registry/loader.js';
33
+ import { getCatalog, isolatedCatalogTestUniverse } from '../registry/loader.js';
34
+ import { isLiveVerifiedOpenRouterModel, liveLookupOpenRouterModel, OPENROUTER_SNAPSHOT_STALE_DAYS, readFoldSnapshotAgeDays, upstreamOpenRouterId } from '../registry/discovery/openrouter-live-resolve.js';
34
35
  import { singleRunAsJobResult } from '../self-implement/self-implement-cli.js';
35
36
  import { superviseRun, type SupervisorDecision, type SupervisorStopReason } from './run-supervisor.js';
36
37
  import { readDecomposeProposals, orderPiecesTopologically } from './decompose-proposal.js';
@@ -63,6 +64,7 @@ import { findGeminiModel, GEMINI_MODELS } from '../gemini/models.js';
63
64
  import { findGrokModel, GROK_MODELS } from '../grok/models.js';
64
65
  import { resolveModelAlias } from '../intelligence-map/model-alias.js';
65
66
  import { BUILTIN_CATALOG } from '../intelligence-map/model-catalog.js';
67
+ import { BEDROCK_DEFAULT_MODEL, BEDROCK_MODELS, findBedrockModel, resolveBedrockModelId } from '../llm/bedrock.js';
66
68
 
67
69
  /** `dev --plan` 도움말이 가리키는 대응 문. ⛔ 도움말에 이 문자열을 리터럴로 다시 적지 마라. */
68
70
  export const DEV_PLAN_REPLACEMENT = 'elanous harness say';
@@ -1339,7 +1341,7 @@ export function normalizeChildLlmProvider(provider: string): string {
1339
1341
  }
1340
1342
 
1341
1343
  function isKnownChildLlmProvider(provider: string): boolean {
1342
- return ['grok', 'anthropic', 'gemini', 'openai', 'openai-codex', 'local', 'openrouter'].includes(normalizeChildLlmProvider(provider));
1344
+ return ['grok', 'anthropic', 'gemini', 'openai', 'openai-codex', 'local', 'openrouter', 'bedrock'].includes(normalizeChildLlmProvider(provider));
1343
1345
  }
1344
1346
 
1345
1347
  function findPickerCatalogModel(provider: string, id: string): CatalogModelView | undefined {
@@ -1350,16 +1352,27 @@ function findPickerCatalogModel(provider: string, id: string): CatalogModelView
1350
1352
  case 'openai':
1351
1353
  case 'openai-codex': return findCodexModel(id);
1352
1354
  case 'openrouter': return findOpenRouterChildModel(id);
1355
+ case 'bedrock': return findBedrockChildModel(id);
1353
1356
  default: return undefined;
1354
1357
  }
1355
1358
  }
1356
1359
 
1360
+ /** BEDROCK-PROVIDER — `anthropic.claude-sonnet-5-5` · `bedrock/claude-sonnet-5-5` · (provider=bedrock 일 때) `claude-sonnet-5-5`
1361
+ * 를 받아 와이어 id(`anthropic.` 접두)로 해석한다. 표 밖은 «모른다» → 거부(다른 provider 와 같은 규율). */
1362
+ function findBedrockChildModel(id: string): CatalogModelView | undefined {
1363
+ const entry = findBedrockModel(id);
1364
+ if (!entry) return undefined;
1365
+ // 지역 접두(`us.anthropic.…`)를 줬으면 그 와이어 id 를 그대로 쓴다(데이터 거주 선택 보존).
1366
+ return { id: resolveBedrockModelId(id), tier: entry.tier, supportsThinking: entry.supportsThinking, recommended: entry.id === BEDROCK_DEFAULT_MODEL };
1367
+ }
1368
+
1357
1369
  /** 결정 2026-09-23 — openrouter 는 피커 목록이 없다(454개 게이트웨이). 받는 것 = ⑴ openrouter 사다리의 모델
1358
1370
  * ⊕ ⑵ 카탈로그 폴드에 있는 `openrouter/*`(운영 스냅숏이 갱신됐을 때). 둘 다 아니면 «모른다» → 거부. */
1359
1371
  function findOpenRouterChildModel(id: string): CatalogModelView | undefined {
1360
1372
  const ladder = MODEL_TIERS.map((t) => LLM_TIER_MAP_BY_PROVIDER.openrouter[t].model);
1361
1373
  const folded = getCatalog().models.get(id);
1362
- if (!ladder.includes(id) && folded?.provider !== 'openrouter') return undefined;
1374
+ if (!ladder.includes(id) && folded?.provider !== 'openrouter' && !isLiveVerifiedOpenRouterModel(id)
1375
+ && !(isolatedCatalogTestUniverse() && !process.env.ELANOUS_CATALOG_DISCOVERY_SNAPSHOT?.trim() && /^openrouter\/[^/\s]+\/[^/\s]+$/.test(id))) return undefined;
1363
1376
  return {
1364
1377
  id,
1365
1378
  tier: id === LLM_TIER_MAP_BY_PROVIDER.openrouter.balanced.model ? 'balanced' : 'standard',
@@ -1404,6 +1417,7 @@ function listImplementationChildModelCandidates(provider: string): string[] {
1404
1417
  case 'openai':
1405
1418
  case 'openai-codex': return CODEX_MODELS.map((model) => model.id);
1406
1419
  case 'openrouter': return [...new Set(MODEL_TIERS.map((t) => LLM_TIER_MAP_BY_PROVIDER.openrouter[t].model))];
1420
+ case 'bedrock': return BEDROCK_MODELS.map((model) => model.id);
1407
1421
  default: return [];
1408
1422
  }
1409
1423
  })();
@@ -1444,6 +1458,56 @@ export function resolveImplementationChildModel(provider: string, model: string)
1444
1458
  };
1445
1459
  }
1446
1460
 
1461
+ let staleOpenRouterSnapshotWarned = false;
1462
+
1463
+ /** OR-MODEL-NAMESPACE — 발사 «전» 비동기 관문. 동기 해석(`resolveImplementationChildModel`)이 스냅숏 밖의
1464
+ * `openrouter/<vendor>/<model>` 을 거부할 때만 공개 `/models` 를 한 번 묻는다.
1465
+ * ⛔ openrouter 가 아닌 provider · 스냅숏에 이미 있는 id 는 네트워크 0 · 해석 결과 불변.
1466
+ * ⛔ 확인 못 함(네트워크·시간 초과·봉투 오류)은 거부(fail-closed) ⊕ 사유 «카탈로그 확인 못 함». */
1467
+ export async function ensureOpenRouterChildModelLive(
1468
+ provider: string | undefined,
1469
+ model: string | undefined,
1470
+ deps: { fetchImpl?: typeof fetch; timeoutMs?: number; write?: (line: string) => void; now?: () => number; persist?: boolean } = {},
1471
+ ): Promise<void> {
1472
+ if (!provider?.trim() || !model?.trim()) return;
1473
+ if (normalizeChildLlmProvider(provider) !== 'openrouter') return;
1474
+ const write = deps.write ?? ((line: string) => process.stderr.write(line));
1475
+ const ageDays = readFoldSnapshotAgeDays((deps.now ?? Date.now)());
1476
+ if (ageDays !== undefined && ageDays > OPENROUTER_SNAPSHOT_STALE_DAYS && !staleOpenRouterSnapshotWarned) {
1477
+ staleOpenRouterSnapshotWarned = true;
1478
+ write(`[dev] ⚠️ OpenRouter 모델 스냅숏이 ${ageDays}일 묵었다(discovery-snapshot.json) — 없는 모델은 공개 카탈로그로 한 번 확인한다\n`);
1479
+ }
1480
+ try {
1481
+ resolveImplementationChildModel(provider, model);
1482
+ return;
1483
+ } catch (err) {
1484
+ const entered = model.trim();
1485
+ const aliased = resolveModelAlias(entered) ?? entered;
1486
+ if (!upstreamOpenRouterId(aliased)) throw err;
1487
+ const lookup = await liveLookupOpenRouterModel(aliased, {
1488
+ ...(deps.fetchImpl ? { fetchImpl: deps.fetchImpl } : {}),
1489
+ ...(deps.timeoutMs !== undefined ? { timeoutMs: deps.timeoutMs } : {}),
1490
+ ...(deps.now ? { now: deps.now } : {}),
1491
+ ...(deps.persist !== undefined ? { persist: deps.persist } : {}),
1492
+ });
1493
+ if (lookup.found) {
1494
+ if (!lookup.persisted && deps.persist !== false) {
1495
+ write(`[dev] ⚠️ ${aliased} 은 OpenRouter 에서 확인했지만 스냅숏에 못 합쳤다 — 이 프로세스에서만 통과(자식·Pod 재해석은 거부될 수 있다)\n`);
1496
+ }
1497
+ resolveImplementationChildModel(provider, model);
1498
+ return;
1499
+ }
1500
+ if (lookup.error) {
1501
+ throw new DevPipelineError(`${err instanceof Error ? err.message : String(err)} · 카탈로그 확인 못 함(${lookup.error})`);
1502
+ }
1503
+ throw err;
1504
+ }
1505
+ }
1506
+
1507
+ export function __resetStaleOpenRouterSnapshotWarningForTests(): void {
1508
+ staleOpenRouterSnapshotWarned = false;
1509
+ }
1510
+
1447
1511
  export const CHILD_LLM_EFFORT_LADDER = ['minimal', 'low', 'medium', 'high', 'xhigh', 'max'] as const;
1448
1512
 
1449
1513
  export function childLlmEffortCeiling(_provider: string, model: string): ReasoningEffortCeiling {
@@ -44,7 +44,7 @@ import { getUserConfig, resolveRoleLlm } from '../user-config.js';
44
44
  import { reviewReasoningEffort } from '../model-tier/review-effort.js';
45
45
  import { getProvider, inferProviderFromModel } from '../llm.js';
46
46
  import { buildReviewProviderAttempts, defaultReviewFallbackModel, runReviewWithFallback, reviewFallbackModelsFromConfig, runSubscriptionReviewer, type SubscriptionReviewerDeps } from './review-provider-fallback.js';
47
- import { loadLlmPolicy } from '../policy/llm-policy.js';
47
+ import { loadLlmPolicy, resolveSubscriptionReviewer } from '../policy/llm-policy.js';
48
48
  import type { DefaultSeamsOptions } from '../self-implement/seams.js';
49
49
  import { harnessTargetOptions, resolveHarnessTarget, revalidateHarnessTarget, type HarnessTargetResolution } from '../self-implement/harness-target-options.js';
50
50
  import { provisionRepository, type RepoProvisionResult } from '../self-implement/repo-provision.js';
@@ -1148,11 +1148,9 @@ export async function buildDefaultSelfImplementSeams(
1148
1148
  }
1149
1149
  let subscriptionReviewLLM: ((prompt: string) => Promise<string>) | undefined;
1150
1150
  if (reviewerIsDefaultApiCall) {
1151
- const userConfig = getUserConfig();
1152
- const policy = loadLlmPolicy();
1153
- const spec = policy.policy.roles.reviewer ?? userConfig.roleLlm?.reviewer;
1154
- if (spec) {
1155
- const cap = policy.policy.caps.claude.harness;
1151
+ const reviewer = resolveSubscriptionReviewer(loadLlmPolicy(), getUserConfig().roleLlm);
1152
+ if (reviewer) {
1153
+ const { spec, cap } = reviewer;
1156
1154
  subscriptionReviewLLM = (prompt) => runSubscriptionReviewer(spec, cap, prompt, defaultApiReview, async (text, spawn) => {
1157
1155
  if (deps.makeSubscriptionReviewLLM) return deps.makeSubscriptionReviewLLM(spawn)(text);
1158
1156
  const { makeAcpReviewLLM } = await import('../agent-substrate/acp-reviewer.js');
@@ -0,0 +1,463 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { readdirSync, readFileSync, existsSync } from 'node:fs';
3
+ import { gunzipSync } from 'node:zlib';
4
+ import { basename, dirname, join } from 'node:path';
5
+ import { findGitDir } from '../git-fs/locate.js';
6
+ import { debug } from '../debug/log.js';
7
+ import { PR_LABELS } from '../github/pr-labels.js';
8
+ import { appendRunLedgerEntry, listRunLedgers, loadRunLedger, runLedgerDir, type RunLedgerEntry } from '../self-implement/run-ledger.js';
9
+ import { queryRunningRuns } from '../self-implement/running-runs.js';
10
+ import { DRAFT_SWEEP_CLOSE_CAP } from './draft-sweep.js';
11
+ import { PROTECTED_LABELS, sameVerifiedGoal, type DraftTriagePr } from './draft-triage-rules.js';
12
+
13
+ export type PodTerminalClass = 'landed' | 'merge-ready-not-merged' | 'failed-with-pr' | 'failed-no-pr' | 'failed-pr-unobserved';
14
+ export interface PrTerminalRecord {
15
+ childRunId: string;
16
+ prNumber: number | null;
17
+ prUrl: string | null;
18
+ repository: string | null;
19
+ headSha: string | null;
20
+ terminalClass: PodTerminalClass;
21
+ stage: string | null;
22
+ owner: string;
23
+ ownerSource: 'seat' | 'card' | 'unknown';
24
+ card: string | null;
25
+ at: string;
26
+ }
27
+ export interface PodTerminalInput {
28
+ childRunId: string;
29
+ state: 'complete' | 'failed' | 'aborted';
30
+ disposition?: { prNumber?: number | null; prUrl?: string | null; checkedHeadCommit?: string | null; stage?: string; merged?: boolean; ok?: boolean } | null;
31
+ env?: Readonly<Record<string, string | undefined>>;
32
+ prBody?: string;
33
+ goalText?: string;
34
+ at?: string;
35
+ }
36
+
37
+ const cardOf = (text?: string): string | null => /^칸:\s*(\S.*?)\s*$/m.exec(text ?? '')?.[1]?.trim() || null;
38
+ const harvestable = PR_LABELS.find((label) => label.name === 'elanous:harvestable')!.name;
39
+ const superseded = PR_LABELS.find((label) => label.name === 'elanous:superseded')!.name;
40
+
41
+ export function classifyPodTerminal(input: PodTerminalInput): PrTerminalRecord {
42
+ const d = input.disposition;
43
+ const prNumber = Number.isSafeInteger(d?.prNumber) && (d?.prNumber ?? 0) > 0 ? d!.prNumber! : null;
44
+ const prUrl = typeof d?.prUrl === 'string' ? d.prUrl : null;
45
+ const match = prUrl && /^https:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/pull\/(\d+)\/?$/.exec(prUrl);
46
+ const repository = match && Number(match[3]) === prNumber ? `${match[1]}/${match[2]}` : null;
47
+ const card = cardOf(input.prBody) ?? cardOf(input.goalText);
48
+ const seat = input.env?.ELANOUS_HARNESS_SEAT;
49
+ const ownerSource = seat === 'OP' || seat === 'TC' || seat === 'MK' || seat === 'UX' ? 'seat' : card ? 'card' : 'unknown';
50
+ return {
51
+ childRunId: input.childRunId, prNumber, prUrl, repository,
52
+ headSha: typeof d?.checkedHeadCommit === 'string' && /^[a-f0-9]{40}$/i.test(d.checkedHeadCommit) ? d.checkedHeadCommit : null,
53
+ terminalClass: !d ? 'failed-pr-unobserved' : d.merged === true ? 'landed'
54
+ : prNumber === null ? 'failed-no-pr'
55
+ : input.state === 'complete' && d.ok !== false ? 'merge-ready-not-merged' : 'failed-with-pr',
56
+ stage: d?.stage ?? null,
57
+ owner: ownerSource === 'seat' ? seat! : ownerSource === 'card' ? card! : 'unknown',
58
+ ownerSource, card, at: input.at ?? new Date().toISOString(),
59
+ };
60
+ }
61
+
62
+ export interface ResiduePr extends DraftTriagePr {
63
+ createdAt: string;
64
+ labels: readonly string[];
65
+ body?: string;
66
+ comments?: readonly string[];
67
+ /** GitHub PR state at lookup time (review r8) — absent only from injected inventories. */
68
+ state?: 'OPEN' | 'CLOSED' | 'MERGED';
69
+ }
70
+ export interface DraftResidueAdapters {
71
+ loadLedger(runId: string, ledgerDir: string): readonly RunLedgerEntry[] | null;
72
+ appendLedger(entry: RunLedgerEntry, ledgerDir: string): void;
73
+ getPr(number: number): Promise<ResiduePr | undefined> | ResiduePr | undefined;
74
+ listOpenDrafts(repository: string): Promise<readonly ResiduePr[] | undefined> | readonly ResiduePr[] | undefined;
75
+ addLabel(repository: string, number: number, label: string): Promise<void> | void;
76
+ setLabels(repository: string, number: number, change: { add: string; remove: readonly string[] }): Promise<void> | void;
77
+ comment(repository: string, number: number, body: string): Promise<void> | void;
78
+ closePr(repository: string, number: number): Promise<void> | void;
79
+ /** Undefined means liveness could not be established, not that no branch is live. */
80
+ listLiveBranches(repository: string): Promise<ReadonlySet<string> | undefined> | ReadonlySet<string> | undefined;
81
+ /** Undefined means the prior run could not be identified as ended. */
82
+ getRunStatus(draft: ResiduePr, repository: string): Promise<string | undefined> | string | undefined;
83
+ }
84
+ /** One close budget shared by every terminal replayed in a tick and the draft sweep that follows. */
85
+ export interface DraftCloseBudget { remaining: number }
86
+ export interface DraftResidueContext {
87
+ ledgerRunId: string;
88
+ ledgerDir: string;
89
+ adapters?: DraftResidueAdapters;
90
+ closeBudget?: DraftCloseBudget;
91
+ }
92
+ export type DraftResidueResult = { status: 'recorded' | 'skipped' | 'failed'; reason?: string; step?: string };
93
+
94
+ function gh(args: string[]): string {
95
+ const result = spawnSync('gh', args, { cwd: findGitDir(process.cwd())?.root ?? process.cwd(), encoding: 'utf8', timeout: 60_000 });
96
+ if (result.status !== 0) throw new Error((result.stderr || result.error?.message || `gh exited ${result.status}`).trim().slice(0, 200));
97
+ return result.stdout.trim();
98
+ }
99
+ function ghPr(row: { number: number; title: string; headRefName: string; createdAt: string; body: string; labels: Array<{ name: string }>; comments?: Array<{ body: string }>; state?: string }): ResiduePr {
100
+ const state = row.state === 'OPEN' || row.state === 'CLOSED' || row.state === 'MERGED' ? row.state : undefined;
101
+ return { number: row.number, title: row.title, branch: row.headRefName, createdAt: row.createdAt, body: row.body,
102
+ labels: row.labels.map((label) => label.name), comments: row.comments?.map((comment) => comment.body), ...(state ? { state } : {}) };
103
+ }
104
+ /** Where the default `getRunStatus` reads run facts. Production reads the federated host ledgers and the running-runs
105
+ * query; tests pass ledgers on disk and a running snapshot, exercising the same decision code (review r6). */
106
+ export interface ResidueRunStatusSources {
107
+ ledgers(): ReadonlyArray<{ runId: string; entries: readonly RunLedgerEntry[] }>;
108
+ running(): { completeness: 'complete' | 'partial'; entries: ReadonlyArray<{ runId: string; status?: string }> };
109
+ }
110
+
111
+ const defaultRunStatusSources: ResidueRunStatusSources = {
112
+ ledgers: () => listRunLedgers().matches,
113
+ running: () => queryRunningRuns(),
114
+ };
115
+
116
+ function refersToPr(entry: RunLedgerEntry, number: number, repository: string): boolean {
117
+ const repo = typeof entry.data.repository === 'string' ? entry.data.repository : undefined;
118
+ const url = entry.data.url ?? entry.data.html_url;
119
+ const sameRepo = repo !== undefined ? repo.toLowerCase() === repository.toLowerCase()
120
+ : typeof url === 'string' ? url.toLowerCase() === `https://github.com/${repository}/pull/${number}`.toLowerCase() : false;
121
+ if (entry.event === 'pr-opened') return entry.data.number === number && sameRepo;
122
+ if (entry.event === 'pr-terminal') return entry.data.prNumber === number && sameRepo;
123
+ // Any other entry naming this PR without a repository is counted as related: more related runs only defers a close.
124
+ return entry.data.prNumber === number && (repo === undefined || sameRepo);
125
+ }
126
+
127
+ /** Review r6: the status of the run(s) behind a draft. A recorded `pr-terminal` settles it only when no run that
128
+ * touched that PR is still alive — a later run reworking the same PR keeps it «running». Unknown stays undefined. */
129
+ export function residueRunStatus(draft: Pick<ResiduePr, 'number'>, repository: string, sources: ResidueRunStatusSources = defaultRunStatusSources): string | undefined {
130
+ const related = sources.ledgers().filter((match) => match.entries.some((entry) => refersToPr(entry, draft.number, repository)));
131
+ if (related.length === 0) return undefined;
132
+ const running = sources.running();
133
+ if (running.completeness !== 'complete') return undefined;
134
+ const statuses = related.map((match) => running.entries.find((entry) => entry.runId === match.runId)?.status
135
+ ?? [...match.entries].reverse().find((entry) => entry.event === 'run-status')?.data.runStatus);
136
+ if (statuses.some((status) => status === 'running' || status === 'probable-running')) return 'running';
137
+ // Review r9: every related run must be accounted for — its own pr-terminal for this PR, or an observed status.
138
+ // A related run with neither is unconfirmed, so another run's terminal cannot settle the PR.
139
+ const unconfirmed = related.some((match, index) => typeof statuses[index] !== 'string'
140
+ && terminalRunStatus(draft.number, repository, [match]) === undefined);
141
+ if (unconfirmed) return undefined;
142
+ const ended = terminalRunStatus(draft.number, repository, related);
143
+ if (ended) return ended;
144
+ return statuses.length === 1 && typeof statuses[0] === 'string' ? statuses[0] : undefined;
145
+ }
146
+
147
+ export function defaultAdapters(sources: ResidueRunStatusSources = defaultRunStatusSources): DraftResidueAdapters {
148
+ const fields = 'number,title,headRefName,createdAt,body,labels,comments,state';
149
+ return {
150
+ loadLedger: loadRunLedger,
151
+ appendLedger: appendRunLedgerEntry,
152
+ getPr: (number) => ghPr(JSON.parse(gh(['pr', 'view', String(number), '-R', hostRepository() ?? '', '--json', fields]))),
153
+ listOpenDrafts: (repository) => {
154
+ const rows: ResiduePr[] = [];
155
+ for (let page = 1; page <= 100; page++) {
156
+ const result = JSON.parse(gh(['api', `repos/${repository}/pulls?state=open&per_page=100&page=${page}`])) as Array<{
157
+ number: number; title: string; head: { ref: string }; created_at: string; body: string; draft: boolean; labels: Array<{ name: string }>;
158
+ }>;
159
+ if (!Array.isArray(result)) throw new Error('Invalid open PR inventory');
160
+ rows.push(...result.filter((pr) => pr.draft).map((pr) => ghPr({ number: pr.number, title: pr.title, headRefName: pr.head.ref, createdAt: pr.created_at, body: pr.body, labels: pr.labels })));
161
+ if (result.length < 100) return rows;
162
+ }
163
+ throw new Error('Open PR inventory exceeded pagination limit');
164
+ },
165
+ addLabel: (repository, number, label) => { gh(['pr', 'edit', String(number), '-R', repository, '--add-label', label]); },
166
+ setLabels: (repository, number, change) => { gh(['pr', 'edit', String(number), '-R', repository, '--add-label', change.add, ...change.remove.flatMap((label) => ['--remove-label', label])]); },
167
+ comment: (repository, number, body) => { gh(['pr', 'comment', String(number), '-R', repository, '--body', body]); },
168
+ closePr: (repository, number) => { gh(['pr', 'close', String(number), '-R', repository]); },
169
+ listLiveBranches: (repository) => {
170
+ if (repository.toLowerCase() !== hostRepository()?.toLowerCase()) return undefined;
171
+ const root = findGitDir(process.cwd())?.root;
172
+ if (!root) return undefined;
173
+ const result = spawnSync('git', ['worktree', 'list', '--porcelain'], { cwd: root, encoding: 'utf8', timeout: 60_000 });
174
+ if (result.status !== 0) return undefined;
175
+ return new Set(result.stdout.split('\n').filter((line) => line.startsWith('branch refs/heads/'))
176
+ .map((line) => line.slice('branch refs/heads/'.length).trim()));
177
+ },
178
+ getRunStatus: (draft, repository) => residueRunStatus(draft, repository, sources),
179
+ };
180
+ }
181
+
182
+ /** Review r5: a host ledger `pr-terminal` for that PR proves the run that opened it has ended (it is written at the
183
+ * run's terminal). Returns the ended status, or undefined when no terminal for that PR is recorded. */
184
+ export function terminalRunStatus(draftNumber: number, repository: string, ledgers: ReadonlyArray<{ entries: readonly RunLedgerEntry[] }>): 'completed' | 'failed' | undefined {
185
+ for (const ledger of ledgers) {
186
+ for (const entry of ledger.entries) {
187
+ if (entry.event !== 'pr-terminal' || entry.data.prNumber !== draftNumber) continue;
188
+ const repo = typeof entry.data.repository === 'string' ? entry.data.repository : '';
189
+ if (repo.toLowerCase() !== repository.toLowerCase()) continue;
190
+ return entry.data.terminalClass === 'landed' ? 'completed' : 'failed';
191
+ }
192
+ }
193
+ return undefined;
194
+ }
195
+
196
+ export function podTerminalPrBody(disposition: PodTerminalInput['disposition']): string | undefined {
197
+ const url = disposition?.prUrl;
198
+ const number = disposition?.prNumber;
199
+ const match = typeof url === 'string' ? /^https:\/\/github\.com\/([\w.-]+\/[\w.-]+)\/pull\/(\d+)\/?$/.exec(url) : null;
200
+ if (!match || Number(match[2]) !== number || match[1]!.toLowerCase() !== hostRepository()?.toLowerCase()) return undefined;
201
+ try { return gh(['pr', 'view', String(number), '-R', match[1]!, '--json', 'body', '--jq', '.body']); }
202
+ catch { return undefined; }
203
+ }
204
+
205
+ function hostRepository(): string | null {
206
+ const root = findGitDir(process.cwd())?.root;
207
+ if (!root) return null;
208
+ const result = spawnSync('git', ['remote', 'get-url', 'origin'], { cwd: root, encoding: 'utf8', timeout: 60_000 });
209
+ const match = result.status === 0 ? /^(?:https:\/\/github\.com\/|git@github\.com:)([\w.-]+\/[\w.-]+?)(?:\.git)?\/?\s*$/.exec(result.stdout) : null;
210
+ return match?.[1] ?? null;
211
+ }
212
+
213
+ export interface DraftResidueReplayOptions {
214
+ repository?: string;
215
+ ledgerDir?: string;
216
+ adapters?: DraftResidueAdapters;
217
+ /** Directory enumeration seam for the host run-ledger scan. */
218
+ listLedgers?: (dir: string) => readonly string[];
219
+ /** This tick's close cap — shared with the sweep that runs after the replay. */
220
+ closeCap?: number;
221
+ }
222
+
223
+ /** Replay unfinished terminal effects from the host ledger, not from PR age or title guesses. */
224
+ export async function replayPodTerminals(options: DraftResidueReplayOptions = {}): Promise<{
225
+ /** `unresolved` — terminals that can never be settled from the record (no repository); settled once, not retried. */
226
+ attempted: number; recovered: number; pending: number; unresolved: number; closed: number;
227
+ }> {
228
+ const cap = Number.isSafeInteger(options.closeCap) && (options.closeCap ?? 0) >= 0 ? options.closeCap! : DRAFT_SWEEP_CLOSE_CAP;
229
+ const closeBudget: DraftCloseBudget = { remaining: cap };
230
+ const closedSoFar = () => cap - closeBudget.remaining;
231
+ const ledgerDir = options.ledgerDir ?? runLedgerDir();
232
+ const list = options.listLedgers ?? readdirSync;
233
+ let attempted = 0;
234
+ let recovered = 0;
235
+ let pending = 0;
236
+ let unresolved = 0;
237
+ let files: readonly string[];
238
+ try { files = list(ledgerDir); }
239
+ catch (error) {
240
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { attempted, recovered, pending, unresolved, closed: 0 };
241
+ throw error;
242
+ }
243
+ const canonical = /^run-[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/;
244
+ const active = files.filter((file) => file.endsWith('.jsonl')).map((file) => file.slice(0, -'.jsonl'.length)).filter((id) => canonical.test(id));
245
+ const archiveDir = join(ledgerDir, 'archive');
246
+ let archived: string[] = [];
247
+ try { archived = (options.listLedgers ?? readdirSync)(archiveDir).filter((file) => /^\.archived-run-/.test(file))
248
+ .map((file) => file.slice('.archived-'.length)).filter((id) => canonical.test(id)); }
249
+ catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
250
+ for (const ledgerRunId of [...new Set([...active, ...archived])]) {
251
+ const entries = active.includes(ledgerRunId) ? (options.adapters?.loadLedger ?? loadRunLedger)(ledgerRunId, ledgerDir)
252
+ : (() => {
253
+ const path = readFileSync(join(archiveDir, `.archived-${ledgerRunId}`), 'utf8');
254
+ const month = basename(dirname(path));
255
+ if (!/^\d{4}-(?:0[1-9]|1[0-2])$/.test(month)
256
+ || path !== join(archiveDir, month, `${ledgerRunId}.jsonl.gz`) || !existsSync(path)) {
257
+ throw new Error(`Archived terminal ledger unavailable: ${ledgerRunId}`);
258
+ }
259
+ const lines = gunzipSync(readFileSync(path)).toString('utf8').trimEnd().split('\n').filter(Boolean);
260
+ return lines.map((line) => {
261
+ const entry = JSON.parse(line) as RunLedgerEntry;
262
+ if (entry.runId !== ledgerRunId || typeof entry.event !== 'string' || !entry.data || typeof entry.data !== 'object') {
263
+ throw new Error(`Invalid archived terminal ledger: ${ledgerRunId}`);
264
+ }
265
+ return entry;
266
+ });
267
+ })();
268
+ if (!entries) throw new Error(`Terminal ledger disappeared: ${ledgerRunId}`);
269
+ const terminals = entries.filter((entry) => entry.event === 'pr-terminal');
270
+ for (const terminal of terminals) {
271
+ const record = terminal.data as unknown as PrTerminalRecord;
272
+ if (typeof record.childRunId !== 'string' || typeof record.owner !== 'string'
273
+ || !['landed', 'merge-ready-not-merged', 'failed-with-pr', 'failed-no-pr', 'failed-pr-unobserved'].includes(record.terminalClass)
274
+ || (record.prNumber !== null && (!Number.isSafeInteger(record.prNumber) || record.prNumber <= 0))
275
+ || (record.repository !== null && (typeof record.repository !== 'string' || !/^[\w.-]+\/[\w.-]+$/.test(record.repository)))) {
276
+ throw new Error(`Invalid terminal record: ${ledgerRunId}`);
277
+ }
278
+ if (record.repository && options.repository && record.repository.toLowerCase() !== options.repository.toLowerCase()) continue;
279
+ if (!options.adapters && record.repository) {
280
+ const host = hostRepository();
281
+ // Unknown host ≠ foreign repository: an unreadable origin keeps the terminal pending for a later replay.
282
+ if (host === null) { attempted++; pending++; debug.log('draft.residue', 'skipped', { childRunId: record.childRunId, prNumber: record.prNumber, reason: 'host-repository-unobserved' }); continue; }
283
+ if (record.repository.toLowerCase() !== host.toLowerCase()) continue;
284
+ }
285
+ if (entries.some((entry) => entry.event === 'pr-terminal-effect' && entry.data.childRunId === record.childRunId
286
+ && (entry.data.effect === 'complete' || entry.data.effect === 'protected') && entry.data.number === (record.prNumber ?? 0))) continue;
287
+ if (!record.repository && entries.some((entry) => entry.event === 'pr-terminal-effect' && entry.data.childRunId === record.childRunId
288
+ && entry.data.effect === 'unresolved-repository')) { unresolved++; continue; }
289
+ attempted++;
290
+ const adapters = options.adapters ?? defaultAdapters();
291
+ const replayAdapters: DraftResidueAdapters = active.includes(ledgerRunId) ? adapters : {
292
+ ...adapters,
293
+ loadLedger: (id, dir) => {
294
+ const live = adapters.loadLedger(id, dir);
295
+ return live?.some((entry) => entry.event === 'pr-terminal') ? live : [...entries, ...(live ?? [])];
296
+ },
297
+ };
298
+ const outcome = await applyPodTerminal(record, { ledgerDir, ledgerRunId, adapters: replayAdapters, closeBudget });
299
+ if (outcome.status === 'recorded' || outcome.reason === 'already-recorded') recovered++;
300
+ else if (outcome.status === 'skipped' && outcome.reason === 'repository-unobserved') unresolved++;
301
+ else if (outcome.status === 'skipped' && !['previous-run-unverified', 'previous-run-live', 'close-cap', 'host-repository-unobserved'].includes(outcome.reason ?? '')) recovered++;
302
+ else pending++;
303
+ }
304
+ }
305
+ return { attempted, recovered, pending, unresolved, closed: closedSoFar() };
306
+ }
307
+
308
+ export async function applyPodTerminal(record: PrTerminalRecord, ctx: DraftResidueContext): Promise<DraftResidueResult> {
309
+ const adapters = ctx.adapters ?? defaultAdapters();
310
+ const fields = { childRunId: record.childRunId, prNumber: record.prNumber, terminalClass: record.terminalClass, owner: record.owner, ownerSource: record.ownerSource };
311
+ const log = (event: string, data: Record<string, unknown> = {}) => debug.log('draft.residue', event, { ...fields, ...data });
312
+ const skipped = (reason: string): DraftResidueResult => { log('skipped', { reason }); return { status: 'skipped', reason }; };
313
+ const budget: DraftCloseBudget = ctx.closeBudget ?? { remaining: DRAFT_SWEEP_CLOSE_CAP };
314
+ let step = 'ledger';
315
+ try {
316
+ const ledger = adapters.loadLedger(ctx.ledgerRunId, ctx.ledgerDir);
317
+ if (ledger === undefined) throw new Error('Terminal ledger unavailable');
318
+ const rows = (ledger ?? []).filter((entry) => entry.data.childRunId === record.childRunId);
319
+ const completed = (effect: string, number: number): boolean => rows.some((entry) => entry.event === 'pr-terminal-effect'
320
+ && entry.data.effect === effect && entry.data.number === number);
321
+ const acknowledge = (effect: string, number: number): void => {
322
+ adapters.appendLedger({ runId: ctx.ledgerRunId, event: 'pr-terminal-effect', data: { childRunId: record.childRunId, effect, number } }, ctx.ledgerDir);
323
+ };
324
+ if (completed('complete', record.prNumber ?? 0) || completed('protected', record.prNumber ?? 0)) return skipped('already-recorded');
325
+ if (!rows.some((entry) => entry.event === 'pr-terminal')) {
326
+ adapters.appendLedger({ runId: ctx.ledgerRunId, event: 'pr-terminal', data: { ...record } }, ctx.ledgerDir);
327
+ log('terminal-recorded');
328
+ }
329
+ if (record.terminalClass === 'failed-no-pr' || record.terminalClass === 'failed-pr-unobserved' || record.prNumber === null) {
330
+ acknowledge('complete', 0);
331
+ return skipped(record.terminalClass);
332
+ }
333
+ // Review r7: the record is immutable — a terminal without a parseable PR URL can never learn its repository on
334
+ // replay. Settle it once with a distinct `unresolved-repository` effect (never a normal `complete`: no GitHub write
335
+ // happened) so replay stops retrying it, and leave it visible as `unresolved` for a human.
336
+ if (!record.repository) {
337
+ if (!completed('unresolved-repository', record.prNumber)) {
338
+ acknowledge('unresolved-repository', record.prNumber);
339
+ log('unresolved', { reason: 'repository-unobserved', prUrl: record.prUrl });
340
+ }
341
+ return skipped('repository-unobserved');
342
+ }
343
+ if (!ctx.adapters) {
344
+ const host = hostRepository();
345
+ // Unknown host is recoverable — never complete it; only a confirmed different repository is foreign.
346
+ if (host === null) return skipped('host-repository-unobserved');
347
+ if (record.repository.toLowerCase() !== host.toLowerCase()) {
348
+ acknowledge('complete', record.prNumber);
349
+ return skipped('foreign-repository');
350
+ }
351
+ }
352
+ step = 'get-pr';
353
+ const pr = await adapters.getPr(record.prNumber);
354
+ if (!pr || pr.number !== record.prNumber || !Array.isArray(pr.labels) || !pr.branch || !Number.isFinite(Date.parse(pr.createdAt))) throw new Error('PR lookup unavailable');
355
+ // Review r8: the PR may have merged or closed after this run's terminal — a failed terminal then writes nothing
356
+ // (no harvestable label, no owner comment) and settles once.
357
+ if (record.terminalClass !== 'landed' && pr.state !== undefined && pr.state !== 'OPEN') {
358
+ step = 'ledger';
359
+ acknowledge('complete', pr.number);
360
+ return skipped(`pr-${pr.state.toLowerCase()}`);
361
+ }
362
+ const protectedPr = pr.labels.some((label) => PROTECTED_LABELS.has(label));
363
+ // Policy (review r4 · r6): a protected PR (keep · release-path · …) that is still open belongs to a human. The
364
+ // terminal does not label, comment on, or supersede around it, and records a distinct `protected` effect — never a
365
+ // normal `complete`. A protected PR that has LANDED is no longer pending a human: its merge makes older same-goal
366
+ // drafts stale, so it supersedes them like any landed PR (the label protects that PR, not other runs' drafts).
367
+ if (protectedPr && record.terminalClass !== 'landed') {
368
+ step = 'ledger';
369
+ acknowledge('protected', pr.number);
370
+ return skipped('protected');
371
+ }
372
+ if (record.terminalClass !== 'landed') {
373
+ if (!completed('harvestable', pr.number)) {
374
+ if (!pr.labels.includes(harvestable)) {
375
+ step = 'add-label';
376
+ await adapters.addLabel(record.repository, pr.number, harvestable);
377
+ log('harvestable-labeled');
378
+ }
379
+ step = 'ledger';
380
+ acknowledge('harvestable', pr.number);
381
+ }
382
+ const body = `Draft residue: ${record.terminalClass} · owner=${record.owner}(${record.ownerSource}) · run=${record.childRunId} · head=${record.headSha ?? 'unobserved'}`;
383
+ if (!completed('owner-comment', pr.number)) {
384
+ if (!pr.comments?.includes(body)) { step = 'comment'; await adapters.comment(record.repository, pr.number, body); }
385
+ step = 'ledger';
386
+ acknowledge('owner-comment', pr.number);
387
+ }
388
+ } else skipped('landed');
389
+ step = 'list-open-drafts';
390
+ const drafts = await adapters.listOpenDrafts(record.repository);
391
+ if (!drafts || !Array.isArray(drafts) || drafts.some((draft) => !Number.isSafeInteger(draft.number) || draft.number <= 0
392
+ || !Array.isArray(draft.labels) || !draft.branch || !Number.isFinite(Date.parse(draft.createdAt)))) {
393
+ throw new Error('Open draft lookup unavailable or incomplete');
394
+ }
395
+ const newerAt = Date.parse(pr.createdAt);
396
+ const candidates = drafts.filter((draft: ResiduePr) => draft.number !== pr.number && draft.branch.startsWith('self-impl/')
397
+ && Date.parse(draft.createdAt) < newerAt && !draft.labels.some((label: string) => PROTECTED_LABELS.has(label))
398
+ && !completed('superseded-close', draft.number)
399
+ && (!draft.labels.includes(superseded) || completed('supersede-intent', draft.number))
400
+ // Only a verified goal identifier may close a PR — a shared «칸:» value or seat is not the same goal.
401
+ && sameVerifiedGoal(draft, pr));
402
+ let liveBranches: ReadonlySet<string> | undefined;
403
+ if (candidates.length) {
404
+ step = 'list-live-branches';
405
+ liveBranches = await adapters.listLiveBranches(record.repository);
406
+ if (!liveBranches) throw new Error('Branch liveness unavailable');
407
+ }
408
+ let deferred = false;
409
+ let capped = false;
410
+ for (const draft of candidates) {
411
+ if (budget.remaining <= 0) { capped = true; break; }
412
+ step = 'get-run-status';
413
+ const status = await adapters.getRunStatus(draft, record.repository);
414
+ if (liveBranches!.has(draft.branch) || !['completed', 'failed', 'cancelled', 'abandoned', 'self-implement.result final'].includes(status ?? '')) {
415
+ deferred = true;
416
+ skipped(`previous-run-${status === 'running' || status === 'probable-running' || liveBranches!.has(draft.branch) ? 'live' : 'unobserved'}`);
417
+ continue;
418
+ }
419
+ if (!completed('supersede-intent', draft.number)) {
420
+ step = 'ledger';
421
+ acknowledge('supersede-intent', draft.number);
422
+ }
423
+ if (!completed('superseded-label', draft.number)) {
424
+ if (!draft.labels.includes(superseded)) {
425
+ step = 'set-labels';
426
+ await adapters.setLabels(record.repository, draft.number, { add: superseded,
427
+ remove: PR_LABELS.filter((label) => label.axis === 'state' && draft.labels.includes(label.name) && label.name !== superseded).map((label) => label.name) });
428
+ }
429
+ step = 'ledger';
430
+ acknowledge('superseded-label', draft.number);
431
+ }
432
+ const body = `Draft residue: superseded-by #${pr.number} (newer run ${record.childRunId} of the same goal). Branch preserved.`;
433
+ if (!completed('supersede-comment', draft.number)) {
434
+ // REST draft listings do not contain comments; fetch them on a retry after the label was applied.
435
+ let comments = draft.comments;
436
+ if (comments === undefined && completed('superseded-label', draft.number)) {
437
+ step = 'get-pr';
438
+ const prior = await adapters.getPr(draft.number);
439
+ if (!prior || prior.number !== draft.number) throw new Error('Previous PR lookup unavailable');
440
+ comments = prior.comments;
441
+ }
442
+ if (!comments?.includes(body)) { step = 'comment'; await adapters.comment(record.repository, draft.number, body); }
443
+ step = 'ledger';
444
+ acknowledge('supersede-comment', draft.number);
445
+ }
446
+ step = 'close-pr';
447
+ await adapters.closePr(record.repository, draft.number);
448
+ budget.remaining--;
449
+ step = 'ledger';
450
+ acknowledge('superseded-close', draft.number);
451
+ log('superseded-previous', { previousPrNumber: draft.number });
452
+ }
453
+ if (deferred) return skipped('previous-run-unverified');
454
+ if (capped) return skipped('close-cap');
455
+ step = 'ledger';
456
+ acknowledge('complete', record.prNumber);
457
+ return { status: 'recorded' };
458
+ } catch (error) {
459
+ const reason = error instanceof Error ? error.message : String(error);
460
+ log('failed', { step, reason });
461
+ return { status: 'failed', step, reason };
462
+ }
463
+ }