elanous 0.2.23 → 0.2.25

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 (688) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +36 -0
  8. package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +148 -0
  10. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1454-37fd16f479f5554a.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/{8532.a86e99acf9b761cb.js → 1516.83dd2c1b86b4e507.js} +2 -2
  16. package/apps/pwa/out/_next/static/chunks/{89849432.9eaa2f4c9c010965.js → 16e57f67.3ea19e893461e611.js} +3 -3
  17. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{1505.5826671109111e75.js → 1743.563d3168e95825ef.js} +2 -2
  19. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +27 -0
  20. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +24 -0
  25. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +32 -0
  28. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2846.d6a433b8663819a5.js +309 -0
  30. package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +34 -0
  31. package/apps/pwa/out/_next/static/chunks/{5967-c0a80f8ffe5d4050.js → 3259-86f3be56e43eaf6a.js} +1 -1
  32. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +287 -0
  36. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{5578.ac963634373b28c6.js → 4084.15ecaf4240bd9e77.js} +2 -2
  41. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{8438.ee7f0df3b3f6fcb4.js → 4204.a409ab6250c0f6a8.js} +1 -1
  43. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +8 -0
  47. package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{7905.b230b9d06cb4ad5d.js → 4593.10f5b9bd702d4a6c.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +104 -0
  51. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +149 -0
  53. package/apps/pwa/out/_next/static/chunks/{8569.b853a8daa8f31d12.js → 5081.a240b63fad28663a.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{2528.0af5c0e1fad88df6.js → 5408.377c8c543635b81f.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{9502-32c5dc22e8f120f5.js → 5492-e05e26a033ba80d2.js} +3 -3
  61. package/apps/pwa/out/_next/static/chunks/5785-ea8d2c633b6688e3.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/599-a914cc0468f56143.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +23 -0
  67. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{5974.360f8441eb0ac1ec.js → 6196.34d6b229079e9e28.js} +1 -1
  70. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +77 -0
  72. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +64 -0
  74. package/apps/pwa/out/_next/static/chunks/{ce383d63.d2ede338788ed18e.js → 65ebff95.081daeff622d238e.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +2 -0
  77. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/{83cfc5c8.349535543c1548b6.js → 6def8a8e.c81f9ca41028eccf.js} +1 -1
  79. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/{2721.bc9a8f36bd85c07a.js → 7483.ba01c6c209b81bba.js} +1 -1
  84. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +62 -0
  87. package/apps/pwa/out/_next/static/chunks/{6702.ebbd165d5e4a4a14.js → 7752.5cbdd0b433c54af9.js} +1 -1
  88. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/{8925-2abfb48af477fb7f.js → 8085-1e5fce59500a2cc2.js} +1 -1
  94. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +226 -0
  96. package/apps/pwa/out/_next/static/chunks/{b4e12462-5fab4a813a63dadd.js → 83a80514-b897b64df43ce108.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +93 -0
  98. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +24 -0
  99. package/apps/pwa/out/_next/static/chunks/{8264.00e434fbd02e9311.js → 8578.dff22d988cc2b106.js} +3 -3
  100. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +115 -0
  103. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +41 -0
  105. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +74 -0
  106. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +94 -0
  107. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{7518.49161e8f5814abdb.js → 9311.24c8f5ea793253dd.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/{9976.8f28864317639fe6.js → 94.4cfed21c0b781a06.js} +3 -3
  111. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +90 -0
  113. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{0e3acd34.d42b2ef87fdf4234.js → 973cbf1b.3bbcf2b41548eca7.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/{6571-926ddf024a6ad5df.js → 9917-9e26abc5f7772735.js} +1 -1
  118. package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +79 -0
  119. package/apps/pwa/out/_next/static/chunks/{740.90b31555290236a9.js → 9974.e77b4ff4884557b3.js} +2 -2
  120. package/apps/pwa/out/_next/static/chunks/{4c5e95ce.83e9b16add6fcd8c.js → ab4d57c2.e90bc2cb31949045.js} +7 -7
  121. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/approvals/page-9360b1285b2a346e.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f08f6529d09ffae1.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/board/page-f000d54d258f9ef6.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-ad3bd8084048bee4.js → page-b12149c51f7d04b1.js} +1 -1
  126. package/apps/pwa/out/_next/static/chunks/app/bots/page-22f674e7e4c2c9d5.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8888733e40cea6d1.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/chat/page-9717ec6964b92276.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/consult/page-44eaad486bc98a45.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/control/page-97fa6cf3d34c7eb9.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/decisions/page-305cd294e754906e.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/design-check/{page-a648bc464c9dc754.js → page-dea4b795741126fd.js} +1 -1
  133. package/apps/pwa/out/_next/static/chunks/app/editor/page-35e05d7450461a67.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/exec/page-45889e7070d11126.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/field/page-16a2e893f83ae4d0.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2638013c0bf7dfd.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/intake/page-56888bc744e08dac.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/layout-c44f93a41167536f.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/live/page-952c6ceec6d9de38.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live-run/page-6d0202af568f4c63.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/loops/page-1b810474507f3702.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/market/page-74366ae2693a7d95.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-4fb6fc34e20c07b7.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/morning/page-e9502921f4f01b1f.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/not-found-b6169ea2f09cf287.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/observatory/page-6a14333d1b1b3967.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8c91a9a66c9ec90a.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-48fb31810693c357.js → page-4e634c5b98fd4e93.js} +1 -1
  150. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ed3070d637850548.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/outputs/{page-cb154acadb025414.js → page-b9cc8a10bc6078b4.js} +1 -1
  152. package/apps/pwa/out/_next/static/chunks/app/page-3d3fc73dd187ed52.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/reflection/page-128458c8d86fbb5f.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-9c04dac0831c2bbb.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/sessions/page-cf0c2b0183991d09.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-04de9ca6d52a3893.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/page-62527677bbc2fdc4.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9a2e09c4a311764c.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/page-bfeb35d69e8b24bb.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/share/page-89cb33bced824e4a.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/showroom/page-b008aff96be56654.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/tasks/page-814394dcbae789b1.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/term/page-6a87325c87f09dd2.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/today/page-6445ac4cbb8dd869.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/trace/page-852170303c6cd755.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/vault/page-087ceeb975ef272b.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-97c7361cc2a19319.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/page-20162174b77f96cf.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8c6901833f897496.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-05a4b2c9b91034aa.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{53746282.1be36038d1abd949.js → e117f801.e92bf10242653497.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +122 -0
  175. package/apps/pwa/out/_next/static/chunks/{0673cc54.8e2ef1c23e49e190.js → f4dfbfc0.a69fb12f854882aa.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +1 -0
  182. package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +1 -0
  183. package/apps/pwa/out/_next/static/{rfkMm4movqkqMebBrCXiR → dRS6lEhSRRBr1abbzp7fJ}/_buildManifest.js +1 -1
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +23 -23
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +23 -23
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +23 -23
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +22 -22
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +22 -22
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +23 -23
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +22 -22
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +23 -23
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +23 -23
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +22 -22
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +23 -23
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +23 -23
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +23 -23
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +23 -23
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +22 -22
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +22 -22
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +23 -23
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +23 -23
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +23 -23
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +22 -22
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +22 -22
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +23 -23
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +23 -23
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +22 -22
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +22 -22
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +22 -22
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +23 -23
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +23 -23
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +22 -22
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +23 -23
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +23 -23
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +23 -23
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +23 -23
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +23 -23
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +22 -22
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +23 -23
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +23 -23
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +23 -23
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +23 -23
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +23 -23
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +23 -23
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +23 -23
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +23 -23
  277. package/catalog/models/openrouter/deepseek-v4-pro-0813.yaml +39 -0
  278. package/catalog/models/openrouter/deepseek-v4.1-flash.yaml +38 -0
  279. package/catalog/models/openrouter/glm-5.3-flash.yaml +35 -0
  280. package/catalog/providers/openrouter.yaml +2 -0
  281. package/graphs/implement-loop.yaml +31 -0
  282. package/graphs/ops/harness-gc.yaml +17 -0
  283. package/graphs/ops/recipes.yaml +3 -0
  284. package/graphs/overlays/README.md +1 -1
  285. package/graphs/overlays/stop-heal-ladder.yaml +105 -0
  286. package/graphs/release/release-loop.yaml +5 -5
  287. package/graphs/steward/recipes.yaml +4 -0
  288. package/graphs/steward/steward.yaml +10 -1
  289. package/package.json +1 -1
  290. package/scripts/add-api-key.sh +1 -1
  291. package/scripts/bench-report.ts +46 -1
  292. package/scripts/ci-typecheck-changed.ts +73 -14
  293. package/scripts/fleet/bedrock-pod-secret.ts +122 -0
  294. package/scripts/fleet/node-setup-linux.sh +97 -0
  295. package/scripts/fleet/node-setup.sh +11 -0
  296. package/scripts/fleet/zai-pod-secret.ts +86 -0
  297. package/scripts/land-global-checks.ts +3 -0
  298. package/scripts/measure-log-diet-2.ts +213 -0
  299. package/scripts/measure-tsc-affected-roots.ts +289 -0
  300. package/scripts/release-loop/auto-approve-node.ts +6 -0
  301. package/scripts/release-loop/gate-closure.ts +286 -0
  302. package/scripts/release-loop/gate-executor.ts +28 -0
  303. package/scripts/release-loop/gate-node.ts +333 -37
  304. package/scripts/release-loop/gate-partial.ts +34 -6
  305. package/scripts/release-loop/ops-upgrade-node.ts +63 -42
  306. package/scripts/release-loop/publish-node.ts +6 -0
  307. package/scripts/release-loop/resume-release.ts +46 -13
  308. package/scripts/release-loop/resume.ts +110 -4
  309. package/scripts/release-loop/unattended-release.ts +22 -7
  310. package/scripts/tsc-baseline-cache.ts +172 -0
  311. package/scripts/usage-rollup.ts +72 -6
  312. package/scripts/ux-sim.ts +30 -1
  313. package/skills/youtube-master/scripts/main.ts +4 -1
  314. package/skills/youtube-master/src/obsidian.ts +9 -0
  315. package/src/agent/run-context.ts +10 -0
  316. package/src/agent-mission/driver.ts +18 -3
  317. package/src/agent-mission/resource-ladder.ts +8 -3
  318. package/src/agent-mission/review-loop.ts +8 -2
  319. package/src/agent-substrate/acp-implementer.ts +146 -0
  320. package/src/agent-substrate/pr-reviewer.ts +60 -13
  321. package/src/agent-substrate/self-review-cli.ts +170 -15
  322. package/src/autopilot/mission-critique.ts +18 -5
  323. package/src/autopilot/mission-feasibility-negotiate.ts +11 -10
  324. package/src/autopilot/mission-trace.ts +12 -1
  325. package/src/autopilot/system-lookback-run.ts +16 -10
  326. package/src/bench/bench.ts +183 -0
  327. package/src/budget/cost-tier-advisor.ts +91 -0
  328. package/src/budget/fetchers/grok.ts +15 -5
  329. package/src/budget/llm-cost.ts +37 -5
  330. package/src/budget/shadow-arms.ts +77 -0
  331. package/src/budget/types.ts +10 -2
  332. package/src/budget/unified-usage.ts +256 -10
  333. package/src/cli/bench-cli.ts +34 -0
  334. package/src/cli/doctor-cli.ts +21 -0
  335. package/src/cli/friendly-errors.ts +113 -0
  336. package/src/cli/guardian-cli.ts +26 -1
  337. package/src/cli/image-cli.ts +101 -0
  338. package/src/cli/intake-cli.ts +3 -1
  339. package/src/cli/log-event-names.ts +4 -0
  340. package/src/cli/memory-cli.ts +182 -0
  341. package/src/cli/model-watch-cli.ts +4 -1
  342. package/src/cli/pr-cli.ts +62 -5
  343. package/src/cli/pr-land-overlap-evidence.ts +160 -12
  344. package/src/cli/pr-land-pod-shadow.ts +54 -0
  345. package/src/cli/release-cli.ts +27 -16
  346. package/src/cli/release-run-if-ready.ts +11 -0
  347. package/src/cli/resource-cli.ts +48 -0
  348. package/src/cli/retro-cli.ts +12 -3
  349. package/src/cli/rfc-status.ts +52 -2
  350. package/src/cli/seat-requests-cli.ts +25 -0
  351. package/src/cli/self-update.ts +104 -0
  352. package/src/cli/tasks-cli.ts +139 -10
  353. package/src/cli/usage-cli.ts +93 -8
  354. package/src/compact/verify-probe.ts +23 -3
  355. package/src/context-card/index.ts +50 -0
  356. package/src/control/control-status.ts +30 -1
  357. package/src/core-turn/run-goal-loop.ts +5 -4
  358. package/src/dashboard/ad-run-setup-bindings.ts +279 -0
  359. package/src/dashboard/index.ts +18 -276
  360. package/src/dashboard/slash-runtime/dashboard-handlers.ts +4 -138
  361. package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
  362. package/src/dashboard/stale-install-check.ts +11 -0
  363. package/src/debug/log-diet.ts +53 -10
  364. package/src/debug/log.ts +19 -1
  365. package/src/domains/morning-essential.ts +18 -3
  366. package/src/domains/release-tool.ts +43 -0
  367. package/src/error-report/report.ts +21 -4
  368. package/src/execution-loop/launch-gate.ts +158 -2
  369. package/src/fleet/host-doctor.ts +375 -0
  370. package/src/github/pr-labels.ts +1 -0
  371. package/src/goals/judge.ts +20 -6
  372. package/src/graph-runner/graph-cli.ts +42 -1
  373. package/src/graph-runner/runner.ts +176 -11
  374. package/src/graph-wizard/archetypes.ts +14 -8
  375. package/src/graph-wizard/generate.ts +77 -1
  376. package/src/grok/usage.ts +23 -2
  377. package/src/grok.ts +13 -7
  378. package/src/grounding/ref-index.ts +253 -0
  379. package/src/harness/dispatch-backpressure.ts +10 -2
  380. package/src/harness/harness-clean.ts +199 -78
  381. package/src/harness/harness-cli-command.ts +176 -52
  382. package/src/harness/harness-gc.ts +331 -0
  383. package/src/harness/harness-stop.ts +82 -10
  384. package/src/harness/harness-substrate-default.ts +142 -7
  385. package/src/harness/launch-registry.ts +6 -0
  386. package/src/harness/worktree-branch-prefix.ts +9 -0
  387. package/src/hq/fence.ts +187 -0
  388. package/src/hq/seats.ts +38 -22
  389. package/src/images/image-ledger.ts +179 -0
  390. package/src/index.ts +110 -186
  391. package/src/instance/child-scope.ts +32 -1
  392. package/src/instance/dev-project.ts +133 -0
  393. package/src/instance/resolve.ts +24 -0
  394. package/src/instance/spawn-elanous.ts +45 -0
  395. package/src/intake-plane/collect-github.ts +7 -2
  396. package/src/intake-plane/lens.ts +46 -4
  397. package/src/intake-plane/ref-prefetch.ts +110 -0
  398. package/src/intake-plane/requirement-funnel.ts +53 -1
  399. package/src/intelligence-map/catalog-feed.ts +119 -0
  400. package/src/intelligence-map/model-catalog.ts +72 -0
  401. package/src/intelligence-map/model-watch-intake.ts +40 -0
  402. package/src/intelligence-map/model-watch-mission.ts +14 -1
  403. package/src/llm/bedrock-eventstream.ts +215 -0
  404. package/src/llm/bedrock-provider.ts +114 -41
  405. package/src/llm/bedrock.ts +174 -28
  406. package/src/llm/open-weight-discipline.ts +21 -0
  407. package/src/llm/openrouter-byok-cost.ts +96 -0
  408. package/src/llm/openrouter-deepseek.ts +151 -0
  409. package/src/llm/openrouter-upstream-pins.config.ts +25 -0
  410. package/src/llm/zai-coding-plan.ts +700 -0
  411. package/src/llm.ts +91 -24
  412. package/src/loops/checker.ts +148 -9
  413. package/src/loops/orchestrator/resync-shadow.ts +34 -7
  414. package/src/maturity/feature-maturity.ts +3 -3
  415. package/src/model-tier/llm-tier-map.ts +9 -5
  416. package/src/models/prompts.ts +2 -1
  417. package/src/mss/logging/log-store.ts +58 -11
  418. package/src/nexus/api/http-server.ts +22 -0
  419. package/src/nexus/api/missions.ts +73 -2
  420. package/src/nexus/api/ops-api.ts +18 -0
  421. package/src/nexus/index.ts +7 -75
  422. package/src/nexus/tools-kind.ts +78 -0
  423. package/src/oauth/codex-account-rotation.ts +43 -3
  424. package/src/oauth/codex-account-store.ts +339 -27
  425. package/src/oauth/codex-quota-policy.ts +33 -4
  426. package/src/oauth/fallback-chain.ts +53 -15
  427. package/src/onboarding/first-run.ts +37 -18
  428. package/src/onboarding/web-first.ts +20 -2
  429. package/src/ops/machine-heartbeat.ts +185 -0
  430. package/src/ops/overview-cache.ts +175 -0
  431. package/src/ops/overview.ts +8 -0
  432. package/src/preview/terminal.ts +15 -5
  433. package/src/project/project-store.ts +20 -0
  434. package/src/prompt-cache/openai.ts +3 -0
  435. package/src/prompt-cache/types.ts +5 -0
  436. package/src/prompt-enhance/enhance.ts +23 -0
  437. package/src/release-loop/auto-start.ts +7 -5
  438. package/src/release-loop/checklist.ts +11 -1
  439. package/src/release-loop/gate-shards.ts +4 -0
  440. package/src/release-loop/light-rc.ts +84 -13
  441. package/src/release-loop/merged-pr-checklist.ts +35 -5
  442. package/src/release-loop/placement.ts +16 -1
  443. package/src/release-loop/rehearsal.ts +1 -1
  444. package/src/requirements/requirement-ledger.ts +536 -0
  445. package/src/retro/daily.ts +5 -5
  446. package/src/seat-loop/duty-ledger.ts +64 -0
  447. package/src/seat-loop/seat-loop.ts +32 -10
  448. package/src/self-dev/decompose.ts +37 -3
  449. package/src/self-dev/dev-cli.ts +44 -10
  450. package/src/self-dev/dev-pipeline.ts +39 -9
  451. package/src/self-dev/draft-residue.ts +27 -5
  452. package/src/self-dev/draft-sweep.ts +151 -0
  453. package/src/self-dev/fabric-decompose-adapter.ts +9 -2
  454. package/src/self-dev/graph-journey-route.ts +6 -0
  455. package/src/self-dev/orchestrate-cli.ts +25 -3
  456. package/src/self-dev/orchestrate.ts +41 -6
  457. package/src/self-dev/run-supervisor.ts +218 -15
  458. package/src/self-dev/run-types.ts +13 -0
  459. package/src/self-dev/supervisor-verdict-edges.ts +1 -0
  460. package/src/self-implement/budget-gate.ts +53 -13
  461. package/src/self-implement/child-context-composition.ts +139 -0
  462. package/src/self-implement/child-llm-preference.ts +13 -5
  463. package/src/self-implement/claude-acp-implement.ts +67 -0
  464. package/src/self-implement/flex-signals.ts +59 -0
  465. package/src/self-implement/frozen-merges.ts +8 -3
  466. package/src/self-implement/gate-cli.ts +29 -10
  467. package/src/self-implement/gate-remote.ts +4 -1
  468. package/src/self-implement/goal-author-decompose.ts +10 -2
  469. package/src/self-implement/goal-author.ts +36 -11
  470. package/src/self-implement/goal-new-paths.ts +42 -0
  471. package/src/self-implement/graph-overlay-condition.ts +28 -0
  472. package/src/self-implement/graph-overlay-yaml.ts +41 -7
  473. package/src/self-implement/graph-templates.ts +33 -1
  474. package/src/self-implement/graph-yaml.ts +56 -0
  475. package/src/self-implement/heal-intake.ts +5 -1
  476. package/src/self-implement/host-regate.ts +124 -30
  477. package/src/self-implement/importer-test-index.ts +3 -1
  478. package/src/self-implement/l8-merge-queue.ts +80 -2
  479. package/src/self-implement/merge-train.ts +19 -0
  480. package/src/self-implement/off-diff-evidence.ts +40 -1
  481. package/src/self-implement/orchestrator.ts +230 -32
  482. package/src/self-implement/premise-review.ts +159 -0
  483. package/src/self-implement/regate-detail.ts +79 -0
  484. package/src/self-implement/review-deferred-to-host.ts +21 -0
  485. package/src/self-implement/rework-budget-judgment.ts +23 -3
  486. package/src/self-implement/running-runs.ts +75 -5
  487. package/src/self-implement/scope-adjacency.ts +23 -0
  488. package/src/self-implement/seams.ts +89 -8
  489. package/src/self-implement/self-implement-cli.ts +9 -4
  490. package/src/self-implement/stop-autoheal.ts +69 -2
  491. package/src/session-runtime/retry-policy.ts +2 -1
  492. package/src/skills/tools/agent.ts +16 -1
  493. package/src/skills/tools/persistent-grounding.ts +11 -1
  494. package/src/skills/tools/shell.ts +33 -1
  495. package/src/steward/launch.ts +5 -4
  496. package/src/steward/rejudge-tick.ts +142 -0
  497. package/src/steward/triage-budget.ts +62 -0
  498. package/src/steward/triage.ts +83 -22
  499. package/src/task-agent/actions.ts +62 -5
  500. package/src/task-agent/board.ts +92 -3
  501. package/src/task-agent/card-evidence.ts +88 -1
  502. package/src/task-agent/completion-evidence.ts +5 -0
  503. package/src/task-agent/cover.ts +166 -3
  504. package/src/task-agent/judge.ts +16 -0
  505. package/src/task-agent/land-order-ledger.ts +95 -0
  506. package/src/task-agent/live-move-history.ts +87 -1
  507. package/src/task-agent/live-moves.ts +350 -20
  508. package/src/task-agent/parent-host.ts +27 -3
  509. package/src/task-agent/rejudge-on-head.ts +223 -24
  510. package/src/task-agent/review-prior-fix.ts +146 -0
  511. package/src/task-agent/review-result-capture.ts +3 -1
  512. package/src/task-agent/run-adopt.ts +136 -0
  513. package/src/task-agent/shadow.ts +65 -9
  514. package/src/task-agent/task-hand.ts +57 -7
  515. package/src/task-orchestrator/surfaces/pod-account-broker.ts +38 -5
  516. package/src/task-orchestrator/surfaces/pod-bedrock-child.ts +74 -0
  517. package/src/task-orchestrator/surfaces/pod-child-default.ts +50 -0
  518. package/src/task-orchestrator/surfaces/pod-child-providers.ts +14 -1
  519. package/src/task-orchestrator/surfaces/pod-command-job.ts +14 -0
  520. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +79 -6
  521. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +122 -0
  522. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -5
  523. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +11 -5
  524. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +23 -0
  525. package/src/task-orchestrator/surfaces/pod-pool.ts +73 -4
  526. package/src/task-orchestrator/surfaces/pod-zai-child.ts +101 -0
  527. package/src/task-orchestrator/surfaces/self-implement-pod.ts +432 -35
  528. package/src/task-orchestrator/surfaces/self-implement.ts +19 -1
  529. package/src/typecheck-ratchet.ts +1 -0
  530. package/src/user-config.ts +69 -15
  531. package/src/ux-sim/fault-cred-expiry.ts +100 -0
  532. package/src/ux-sim/fault-pod-death.ts +74 -0
  533. package/src/ux-sim/fault-pool-cap.ts +81 -0
  534. package/src/version/packed-revision.json +1 -1
  535. package/src/webclone/qa-table.ts +22 -0
  536. package/src/workflow-runtime/triggers/registry.ts +59 -0
  537. package/src/workflow-runtime/triggers/webhook-source.ts +35 -5
  538. package/apps/pwa/out/_next/static/chunks/0a09e062-34f747a17d8d8c2e.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +0 -77
  540. package/apps/pwa/out/_next/static/chunks/1325-dc3f3c21eb181cb4.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +0 -34
  542. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +0 -24
  543. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/1669-da843ed73aa301f5.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +0 -36
  553. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +0 -122
  554. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +0 -62
  556. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/272-b23d2e92161d11fd.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +0 -149
  563. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/3961-fbef064c213b2b18.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +0 -309
  567. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/5313.1697309c532b9856.js +0 -2
  579. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +0 -74
  587. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +0 -64
  591. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +0 -32
  594. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +0 -24
  595. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +0 -93
  599. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +0 -148
  604. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +0 -226
  605. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +0 -27
  606. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +0 -115
  609. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +0 -8
  616. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +0 -23
  617. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +0 -90
  622. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +0 -94
  623. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +0 -41
  625. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +0 -287
  627. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +0 -79
  628. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +0 -104
  633. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d5341ac96203a983.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-0160ab83c8685a12.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/app/board/page-55c631c032dcc47e.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/app/bots/page-e6784759a2531031.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5c5d0e370f495ef6.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/app/chat/page-c325e21543cd48a8.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/app/consult/page-6168a7c43e6ef8f5.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/app/control/page-31417d3604154a6d.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/app/decisions/page-e9606dc0bdec9305.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/app/editor/page-25bb425afdb27541.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/app/exec/page-32d72fdef1afe11a.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/field/page-d27b794c8ba76bbb.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/inside/page-2bd9ce9c020d02d4.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/intake/page-a34096245e63b9f2.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/layout-22170f4f00a15496.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/live/page-4cc66d22ca4ec502.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83b14c729fcea837.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/loops/page-6e2781c523dad761.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/market/page-26dd415c8f13f341.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-ccdb83ed40c8d724.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/morning/page-7ad3de8fa06fdea9.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/not-found-015c02c4fec4023e.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/observatory/page-6b0ae5b5c42f6d2f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-786111f30b6f0969.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e17cce5e2ed0fee.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/page-16258e956ea93fc2.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/reflection/page-c2dd2b19c93f90ab.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f35dd1dd96ae87.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d3c007c8a0ddd7ee.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7837ce2aacb97b04.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/settings/page-7350ee93f4fe1033.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-00723458575f2b19.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/setup/page-745d9b6c015076f8.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/share/page-736d33c7414a8a1a.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/showroom/page-119be9a0444d2482.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/tasks/page-fa806c018833e332.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/term/page-c782041b5f5199ba.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/today/page-d431fbdea6ad93dd.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/trace/page-0c056abff82b9891.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/vault/page-242d668e4fbf72c4.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-847c3de6ca8a4416.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/workflows/page-81dd0d8ae923ed72.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/workspace/page-74e69ba2c8e970d4.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-70038f41ae7cf931.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/framework-b2763b10dc6b3836.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +0 -1
  687. package/apps/pwa/out/_next/static/css/5619d59e87eddf66.css +0 -1
  688. /package/apps/pwa/out/_next/static/{rfkMm4movqkqMebBrCXiR → dRS6lEhSRRBr1abbzp7fJ}/_ssgManifest.js +0 -0
@@ -0,0 +1,146 @@
1
+ // ── ACP Claude Code 를 «구현» 실행기로 (CLAUDE-IMPL-LANE · `--child-llm-provider claude-acp`) ──
2
+ //
3
+ // acp-reviewer.ts 의 짝이다. 리뷰어는 read-only 라 읽기 툴만 허가하지만, 구현 실행기는 런 워크트리 안에서
4
+ // 쓰기·실행을 허가해야 한다. 대표 대표 결정(10-12): ACP 세션 권한 모드는 호스트 설정(auto)을 그대로 두고
5
+ // 바꾸지 않으며, approver 가 불려도 «워크트리 밖 경로 쓰기»를 거부하지 않고 허가하되 insideWorktree 로 관측한다.
6
+ // 자식은 claude 구독 ACP 어댑터(`claude-agent-acp`)이며 env 는 subscriptionReviewerSpawn 의 과금 스크럽
7
+ // (ANTHROPIC_API_KEY 등 제거)을 그대로 쓴다 — 지우지 않으면 구독이 아니라 API 로 과금된다.
8
+ import { isAbsolute, relative, resolve } from 'node:path';
9
+ import { AcpAgent, type AcpAgentOpts } from '../acp/client.js';
10
+ import { debug } from '../debug/log.js';
11
+ import { subscriptionReviewerSpawn } from '../self-dev/review-provider-fallback.js';
12
+ import type { SubscriptionReviewerSpec } from '../user-config.js';
13
+ import { isReadOnlyReviewTool } from './acp-reviewer.js';
14
+
15
+ const WRITE_TOOL_KINDS = new Set(['edit', 'delete', 'move']);
16
+ const PATH_INPUT_KEYS = ['file_path', 'filePath', 'path', 'notebook_path', 'destination', 'source'] as const;
17
+
18
+ export interface ImplementerPermissionRequest {
19
+ title: string;
20
+ kind?: string;
21
+ rawInput?: unknown;
22
+ }
23
+
24
+ export interface ImplementerPermissionDecision {
25
+ tool: string;
26
+ path: string | null;
27
+ /** 판정에 쓴 경로가 워크트리 안인가 — 경로가 없으면 null. 밖이어도 허가한다(대표 10-12); 이 칸이 그 관측이다. */
28
+ insideWorktree: boolean | null;
29
+ decision: 'allow' | 'deny';
30
+ }
31
+
32
+ function requestedPaths(rawInput: unknown): string[] {
33
+ if (!rawInput || typeof rawInput !== 'object') return [];
34
+ const input = rawInput as Record<string, unknown>;
35
+ return PATH_INPUT_KEYS.flatMap((key) => (typeof input[key] === 'string' && input[key] ? [input[key] as string] : []));
36
+ }
37
+
38
+ function insideWorktree(worktree: string, target: string): boolean {
39
+ const rel = relative(resolve(worktree), resolve(worktree, target));
40
+ return rel === '' || (!rel.startsWith('..') && !isAbsolute(rel));
41
+ }
42
+
43
+ /** 허가 판정(순수 함수). 쓰기 계열(edit·delete·move)은 경로가 있으면 워크트리 안팎을 가리지 않고 허가한다
44
+ * (대표 10-12 — 밖 쓰기 거부를 걷었다 · insideWorktree 로 관측만 한다). 실행(execute)·읽기 계열은 허가,
45
+ * 그 외(모르는 kind)는 경로가 있을 때만 허가 — 경로 없는 쓰기·모르는 요청은 여전히 거부. */
46
+ export function decideImplementerPermission(req: ImplementerPermissionRequest, worktree: string): ImplementerPermissionDecision {
47
+ const paths = requestedPaths(req.rawInput);
48
+ const outside = paths.find((p) => !insideWorktree(worktree, p));
49
+ const tool = req.title.slice(0, 80);
50
+ const shown = outside ?? paths[0] ?? null;
51
+ const inside = paths.length === 0 ? null : outside === undefined;
52
+ const verdict = (allow: boolean): ImplementerPermissionDecision => ({ tool, path: shown, insideWorktree: inside, decision: allow ? 'allow' : 'deny' });
53
+ if (req.kind && WRITE_TOOL_KINDS.has(req.kind)) return verdict(paths.length > 0);
54
+ if (req.kind === 'execute') return verdict(true);
55
+ if (isReadOnlyReviewTool(req.kind, req.title)) return verdict(true);
56
+ return verdict(paths.length > 0);
57
+ }
58
+
59
+ export interface AcpImplementerOpts {
60
+ /** 런 워크트리 — ACP 자식의 cwd 이자 쓰기 허용 경계. */
61
+ worktree: string;
62
+ /** 자식 env 의 원천(기본 process.env). 과금 키는 subscriptionReviewerSpawn 이 제거한다. */
63
+ env?: NodeJS.ProcessEnv;
64
+ /** cct 실행기가 `teamclaude env --no-mitm` 에서 읽은 프록시 주소. */
65
+ proxyBaseUrl?: string;
66
+ spec?: SubscriptionReviewerSpec;
67
+ /** 모델 별칭 — 지정 시 session/set_model 로 고정. */
68
+ model?: string;
69
+ /** 이어갈 ACP 세션 id — 주면 newSession 대신 loadSession 으로 이어간다. */
70
+ resumeSessionId?: string;
71
+ /** 구현 1턴 최대 대기(ms). 초과 시 cancel → throw. 기본 1_800_000. */
72
+ timeoutMs?: number;
73
+ /** spawn → initialize → session 준비까지의 단일 기한(ms). 기본 60_000. */
74
+ handshakeTimeoutMs?: number;
75
+ /** 테스트용 ACP 에이전트 생성기. */
76
+ createAgent?: (opts: AcpAgentOpts) => AcpAgent;
77
+ }
78
+
79
+ export interface AcpImplementerResult {
80
+ text: string;
81
+ sessionId: string;
82
+ allowed: number;
83
+ denied: number;
84
+ }
85
+
86
+ const OBS = 'agent-substrate.acp-implementer';
87
+
88
+ export function makeAcpImplementer(opts: AcpImplementerOpts): (prompt: string) => Promise<AcpImplementerResult> {
89
+ return async (prompt) => {
90
+ const spawn = subscriptionReviewerSpawn(opts.spec ?? { provider: 'claude-acp' }, opts.env ?? process.env, opts.proxyBaseUrl);
91
+ const timeoutMs = opts.timeoutMs ?? 1_800_000;
92
+ const handshakeTimeoutMs = opts.handshakeTimeoutMs ?? 60_000;
93
+ let allowed = 0;
94
+ let denied = 0;
95
+ const agentOpts: AcpAgentOpts = {
96
+ backendId: 'claude',
97
+ backendSpec: spawn.backendSpec,
98
+ env: spawn.env,
99
+ cwd: opts.worktree,
100
+ log: (message) => debug.log(OBS, 'agent-log', { message }),
101
+ permissionApprover: async (req) => {
102
+ const verdict = decideImplementerPermission(req, opts.worktree);
103
+ if (verdict.decision === 'allow') allowed++; else denied++;
104
+ debug.log(OBS, 'permission', {
105
+ tool: verdict.tool, path: verdict.path, insideWorktree: verdict.insideWorktree, allowed: verdict.decision === 'allow',
106
+ });
107
+ return verdict.decision === 'allow';
108
+ },
109
+ };
110
+ const agent = opts.createAgent ? opts.createAgent(agentOpts) : new AcpAgent(agentOpts);
111
+ let handshakeTimer: ReturnType<typeof setTimeout> | undefined;
112
+ const withinHandshake = <T>(step: Promise<T>): Promise<T> => Promise.race([step, new Promise<never>((_, reject) => {
113
+ handshakeTimer = setTimeout(() => reject(new Error(`ACP handshake timeout (${handshakeTimeoutMs}ms)`)), handshakeTimeoutMs);
114
+ })]).finally(() => { if (handshakeTimer) clearTimeout(handshakeTimer); });
115
+ let timer: ReturnType<typeof setTimeout> | undefined;
116
+ let timedOut = false;
117
+ let text = '';
118
+ try {
119
+ await withinHandshake(agent.start());
120
+ let sid: string;
121
+ if (opts.resumeSessionId) {
122
+ await withinHandshake(agent.loadSession({ sessionId: opts.resumeSessionId, cwd: opts.worktree }));
123
+ sid = opts.resumeSessionId;
124
+ } else {
125
+ sid = await withinHandshake(agent.newSession());
126
+ }
127
+ if (opts.model) await withinHandshake(agent.selectSessionModel(sid, opts.model));
128
+ debug.log(OBS, 'start', { cwd: opts.worktree, model: opts.model ?? '(default)', resumed: Boolean(opts.resumeSessionId) });
129
+ timer = setTimeout(() => { timedOut = true; agent.cancel(sid).catch(() => { /* noop */ }); }, timeoutMs);
130
+ await agent.prompt(sid, [{ type: 'text', text: prompt }], (u) => {
131
+ if (u.sessionUpdate === 'agent_message_chunk' && u.content.type === 'text' && u.content.text) text += u.content.text;
132
+ });
133
+ if (timedOut) throw new Error(`ACP 구현 타임아웃(${timeoutMs}ms)`);
134
+ debug.log(OBS, 'done', { chars: text.length, allowed, denied });
135
+ return { text, sessionId: sid, allowed, denied };
136
+ } catch (e) {
137
+ debug.log(OBS, 'error', { message: (e as Error).message, allowed, denied }, { level: 'error' });
138
+ throw e;
139
+ } finally {
140
+ if (timer) clearTimeout(timer);
141
+ try { await agent.stop(); } catch (e) {
142
+ debug.log(OBS, 'stop-fail', { message: (e as Error).message }, { level: 'error' });
143
+ }
144
+ }
145
+ };
146
+ }
@@ -652,20 +652,48 @@ export function buildReviewPrompt(
652
652
  * `none of the tests …`. 표지 낱말로 시작하는 실제 블로커를 지우면 PASS/WARN 리뷰에서 블로커가 사라진다. */
653
653
  const NONE_WORD = String.raw`(?:없음|해당\s*없음|n\/a|none|nothing)`;
654
654
  const BARE_SENTINEL = new RegExp(String.raw`^${NONE_WORD}\s*[.。]?$`, 'i');
655
- const BRACKETED_SENTINEL = new RegExp(String.raw`^[([(【]\s*${NONE_WORD}(?:\s*[—–\-:.,;]\s*([^)\])】]*))?\s*[)\])】]$`, 'i');
655
+ const BRACKETED_SENTINEL = new RegExp(String.raw`^[([(【]\s*${NONE_WORD}(?:\s*[—–\-:.,;·]\s*([^)\])】]*))?\s*[)\])】]$`, 'i');
656
656
  // ⭐ 설명 «전체»가 「지적 없음」 한 문장일 때만 — 일부만 맞아도 접으면 `(none: no blockers are checked because …)` 같은 지적이 사라진다.
657
657
  const NO_FINDING_REMARK = new RegExp([
658
658
  String.raw`^(?:(?:블로커|차단)\s*)?(?:수준의?\s*)?(?:결함|문제|이슈|지적|블로커)(?:은|는|이|가)?\s*(?:발견되지\s*않(?:음|았(?:다|습니다)?)|없(?:음|다|습니다))[.。]?$`,
659
659
  String.raw`^(?:no|zero)\s+(?:blocking\s+)?(?:blockers?|issues?|problems?|findings?|must-?fix(?:es)?)(?:\s+found)?\.?$`,
660
660
  String.raw`^nothing\s+(?:blocking|to\s+fix)\.?$`,
661
+ // REVIEW-MUSTFIX-NONE-SENTINEL — `(없음 — 수용기준 충족)` · `(none — acceptance criteria met)` (GLM 실측 6건). «미충족» 은 ^ 앵커로 안 맞는다.
662
+ String.raw`^수용\s*기준(?:을|이)?\s*(?:(?:모두|전부)\s*)?충족(?:함|됨|했다|합니다)?[.。]?$`,
663
+ String.raw`^(?:all\s+)?acceptance\s+criteria\s+(?:are\s+)?(?:all\s+)?met\.?$`,
661
664
  ].join('|'), 'i');
662
- function isNoneSentinelFinding(finding: string): boolean {
665
+ // REVIEW-MUSTFIX-NONE-SENTINEL 후속 — GLM 이 괄호 안에 «무소견 머리 + 긴 근거»를 쓴다(10-11 TC `pr land` 가 `review-must-fix-1` 로 거부):
666
+ // `(없음 — 수용기준 충족: 머리말에 … 반영됨 …)` · `(없음 — 수용기준 3항 모두 충족: … (\`'failed'\` 반환) · …)`(근거 안에 괄호가 또 있다).
667
+ // ⭐ 길이 무관 0 은 «머리»가 무소견 서술이고 바로 구분자가 올 때만 — 머리가 결함 서술이면(`(없음 — 하지만 X 가 깨진다)`) 지적으로 남긴다.
668
+ // ⛔ 근거에 역접·미충족(`하지만`·`다만`·`미충족`·`but`·`except`·`not met` …)이 있으면 보수적으로 지적으로 남긴다.
669
+ const LONG_BRACKETED_SENTINEL = new RegExp(String.raw`^[([(【]\s*${NONE_WORD}\s*[—–\-:·]\s*([\s\S]+?)\s*[)\])】]$`, 'i');
670
+ const NO_FINDING_HEAD = new RegExp('^(?:' + [
671
+ String.raw`수용\s*기준(?:\s*\d+\s*(?:항|개|건)(?:목)?)?(?:을|이)?\s*(?:(?:모두|전부)\s*)?충족(?:함|됨|했다|합니다)?`,
672
+ String.raw`(?:all\s+)?acceptance\s+criteria\s+(?:are\s+)?(?:all\s+)?met`,
673
+ String.raw`must-?fix\s*(?:항목)?(?:은|는|이|가)?\s*(?:없(?:음|다|습니다)|0\s*건)`,
674
+ String.raw`(?:no|zero)\s+(?:blocking\s+)?(?:blockers?|must-?fix(?:es)?)(?:\s+found)?`,
675
+ String.raw`(?:(?:블로커|차단)\s*)?(?:수준의?\s*)?(?:결함|블로커)(?:은|는|이|가)?\s*(?:발견되지\s*않(?:음|았(?:다|습니다)?)|없(?:음|다|습니다))`,
676
+ ].join('|') + String.raw`)\s*(?:[::—–\-·,;.。(]|$)`, 'i');
677
+ const LONG_REMARK_DISSENT = /하지만|그러나|다만|(?<![가-힣])단(?:,|\s)|미\s*충족|불\s*충족|충족하지|충족되지|\bbut\b|\bhowever\b|\bexcept\b|\balthough\b|\bnot\s+(?:yet\s+)?met\b|\bunmet\b/i;
678
+ /** 괄호 안이 «없음 + 구분자 + 무소견 머리 …» 인가 — 길이 무관(근거 안 괄호도 허용). `isNoneSentinelFinding` 의 갈래. */
679
+ function isLongNoFindingBracket(text: string): boolean {
680
+ const m = LONG_BRACKETED_SENTINEL.exec(text.trim());
681
+ if (!m) return false;
682
+ const remark = m[1]!.trim();
683
+ return NO_FINDING_HEAD.test(remark) && !LONG_REMARK_DISSENT.test(remark);
684
+ }
685
+ /** must-fix 항목이 «지적 없음» 표지인가 — must-fix 를 세는 자리는 전부 `parseReviewResult` 를 거친다
686
+ * (`self review --json` 의 `mustFix` → TA `parseReviewResultOutput` → `pr land --overlap-evidence` 의 `review-must-fix-N`).
687
+ * ⭐ export — `parseReviewResultOutput` 가 «같은» 판정으로 저장된 결과의 표지 줄을 다시 접는다(PR-LAND-MUSTFIX-NONE · 복제 금지). */
688
+ export function isNoneSentinelFinding(finding: string): boolean {
663
689
  const text = finding.trim();
664
690
  if (BARE_SENTINEL.test(text)) return true;
665
691
  const bracketed = BRACKETED_SENTINEL.exec(text);
666
- if (!bracketed) return false;
667
- const remark = bracketed[1]?.trim();
668
- return !remark || NO_FINDING_REMARK.test(remark);
692
+ if (bracketed) {
693
+ const remark = bracketed[1]?.trim();
694
+ if (!remark || NO_FINDING_REMARK.test(remark)) return true;
695
+ }
696
+ return isLongNoFindingBracket(text);
669
697
  }
670
698
 
671
699
  /** critic 응답 파싱 → ReviewResult. 순수함수. VERDICT + MUST-FIX/SHOULD-FIX/REQUIREMENTS 섹션 분해.
@@ -738,6 +766,25 @@ function reviewedResultFromRaw(raw: string, runId: string | undefined, pass?: {
738
766
  return { verdict: 'pass', mustFix: [], shouldFix: [], reviewed: false, failureReason: NO_VERDICT_LINE_REASON };
739
767
  }
740
768
 
769
+ /** REVIEW-PROMPT-SIZE — llmReview 호출 하나(단일·청크 패스)마다 프롬프트·응답 크기를 남긴다.
770
+ * 관측이 리뷰를 막지 않는다(다른 review.* 관측과 같은 계약). */
771
+ function logReviewPromptSize(
772
+ prompt: string,
773
+ response: string,
774
+ pass: { pass: number; chunked: boolean },
775
+ runId: string | undefined,
776
+ ): void {
777
+ try {
778
+ debug.log('review.prompt-size', 'call', {
779
+ pass: pass.pass,
780
+ promptChars: prompt.length,
781
+ responseChars: response.length,
782
+ chunked: pass.chunked,
783
+ ...(runId !== undefined ? { runId } : {}),
784
+ });
785
+ } catch { /* Observation must not prevent the review. */ }
786
+ }
787
+
741
788
  function failureReasonText(error: unknown): string {
742
789
  if (error instanceof Error) return safeLogText(error.message, 400);
743
790
  if (typeof error === 'string') return safeLogText(error, 400);
@@ -889,10 +936,11 @@ export async function reviewPullRequest(
889
936
  + ' 「여기 안 보인다」를 결함으로 판정하지 마십시오.',
890
937
  ].filter(Boolean).join('\n'),
891
938
  };
892
- passResults.push(reviewedResultFromRaw(await llmReview(
893
- buildReviewPrompt(passInput, passBudget, '', passContext[index]?.budget),
894
- reviewImages.length > 0 && index === 0 ? reviewImages : undefined,
895
- ), input.reviewContext?.runId, { index, of: plan.passes.length }));
939
+ const passPrompt = buildReviewPrompt(passInput, passBudget, '', passContext[index]?.budget);
940
+ const passImages = reviewImages.length > 0 && index === 0 ? reviewImages : undefined;
941
+ const passRaw = await llmReview(passPrompt, passImages);
942
+ logReviewPromptSize(passPrompt, passRaw, { pass: index + 1, chunked: true }, input.reviewContext?.runId);
943
+ passResults.push(reviewedResultFromRaw(passRaw, input.reviewContext?.runId, { index, of: plan.passes.length }));
896
944
  }
897
945
  return {
898
946
  ...foldReviewResults(passResults),
@@ -916,10 +964,9 @@ export async function reviewPullRequest(
916
964
  } : {}),
917
965
  };
918
966
  }
919
- const raw = await llmReview(
920
- buildReviewPrompt(input, diffBudget, referencedContext.text, singleContextBudget),
921
- reviewImages.length > 0 ? reviewImages : undefined,
922
- );
967
+ const prompt = buildReviewPrompt(input, diffBudget, referencedContext.text, singleContextBudget);
968
+ const raw = await llmReview(prompt, reviewImages.length > 0 ? reviewImages : undefined);
969
+ logReviewPromptSize(prompt, raw, { pass: 1, chunked: false }, input.reviewContext?.runId);
923
970
  return {
924
971
  ...reviewedResultFromRaw(raw, input.reviewContext?.runId),
925
972
  diffBudget: {
@@ -14,6 +14,9 @@
14
14
  //
15
15
  // index.ts 의 액션은 옵션 파싱과 실제 의존 배선만 남는다(얇은 껍데기).
16
16
 
17
+ import { mkdtempSync, rmSync } from 'node:fs';
18
+ import { tmpdir } from 'node:os';
19
+ import { join } from 'node:path';
17
20
  import { tierModel } from '../llm/model-defaults.js';
18
21
  import { buildReviewObservation, safeLogText } from './review-observation.js';
19
22
  import { DEFAULT_REVIEW_BACKEND } from './acp-reviewer.js';
@@ -24,6 +27,9 @@ import type { ReferencedFileReader } from '../self-implement/goal-file-reader.js
24
27
  import type { SubscriptionReviewerSpec } from '../user-config.js';
25
28
  import { listRunLedgers, lookupPrGoalAcceptance, lookupRunLedger, type PrGoalAcceptanceLookup, type RunLedgerEntry, type RunLedgerLookup } from '../self-implement/run-ledger.js';
26
29
 
30
+ /** SUBSCRIPTION-EXHAUST-REROUTE — API reviewer when the configured `roleLlm.reviewer` lane is unavailable (off codex). */
31
+ export const ROLE_REVIEWER_FALLBACK_MODEL = 'openrouter/z-ai/glm-5.3';
32
+
27
33
  export interface SelfReviewCliOpts {
28
34
  intent?: string | undefined;
29
35
  model?: string | undefined;
@@ -54,8 +60,13 @@ export interface SelfReviewCliDeps {
54
60
  * (`#7486` 리뷰 must-fix · 실제로 `index.ts` 래퍼가 그렇게 한 번 떨어뜨렸다). */
55
61
  reviewPullRequest(input: ReviewInput, llm: (prompt: string, images?: readonly ReviewImage[]) => Promise<string>): Promise<ReviewResult>;
56
62
  renderReview(review: ReviewResult): string;
57
- /** 기본 경로 리뷰어 LLM(API). */
58
- makeApiLlm(model: string): (prompt: string) => Promise<string>;
63
+ /**
64
+ * 기본 경로 리뷰어 LLM(API).
65
+ * `o.pinProvider` — 명시 `--model` 일 때 true: 구현은 streamLLM 의 provider 를 그 모델의 provider 로 고정해
66
+ * 라우터 폴백(grok 등)으로 조용히 넘어가지 않고 실패를 오류로 낸다.
67
+ * `o.onResolved` — streamLLM 이 «실제로 응답한» provider·model 을 알린다.
68
+ */
69
+ makeApiLlm(model: string, o?: { pinProvider?: boolean; onResolved?: (provider: string, model: string) => void }): (prompt: string) => Promise<string>;
59
70
  /** `--acp` 경로 리뷰어 LLM(독립 프로세스). */
60
71
  /**
61
72
  * ⭐ `P4b` — 두 번째 인자가 **멀티미디어 통로**다.
@@ -67,15 +78,20 @@ export interface SelfReviewCliDeps {
67
78
  *
68
79
  * ⚠️ API 백엔드(`makeApiLlm`)는 이 인자를 안 받는다 — ACP 경로만 이미지를 나른다.
69
80
  */
70
- makeAcpLlm(o: { backend: string; model?: string; timeoutMs: number }): (prompt: string, images?: readonly ReviewImage[]) => Promise<string>;
81
+ makeAcpLlm(o: { backend: string; model?: string; timeoutMs: number; cwd?: string }): (prompt: string, images?: readonly ReviewImage[]) => Promise<string>;
71
82
  /**
72
83
  * Reviewer ACP lane selected by `roleLlm.reviewer` (no explicit flag). Returns the LLM when the
73
84
  * subscription is usable, or a reason code when it is not — the caller then reviews on the API
74
85
  * exactly as before. Absent seam = the lane is unavailable (`role-reviewer-seam-missing`).
75
86
  */
76
- makeRoleReviewerLlm?(spec: SubscriptionReviewerSpec, o: { timeoutMs: number }):
87
+ makeRoleReviewerLlm?(spec: SubscriptionReviewerSpec, o: { timeoutMs: number; cwd?: string }):
77
88
  | { llm: (prompt: string, images?: readonly ReviewImage[]) => Promise<string>; backend: string }
78
89
  | { reason: string };
90
+ /**
91
+ * SUBSCRIPTION-EXHAUST-REROUTE — API model used when `roleLlm.reviewer` is configured (no explicit flag) but its
92
+ * lane is unavailable or fails. Absent seam or empty answer = the codex-ladder default as before.
93
+ */
94
+ roleFallbackModel?(): string | undefined;
79
95
  /** 관측 sink 등록 — ⭐ 이 호출이 분기 밖에 있는지가 이 트랙의 계약이다. */
80
96
  registerSink(surface: string): Promise<void>;
81
97
  /** `data` 는 payload 객체 — 순수 헬퍼가 만든 관측 타입도 그대로 받는다(인덱스 시그니처 강요 금지). */
@@ -95,6 +111,8 @@ export interface SelfReviewCliDeps {
95
111
 
96
112
  export interface SelfReviewCliOutcome {
97
113
  results: Array<Record<string, unknown>>;
114
+ /** 리뷰하지 못한 PR 수(`gh pr diff` 실패 · ACP 리뷰 reviewed=false) — json·비json 둘 다 센다. index.ts 가 1 이상이면 rc=1. */
115
+ failed: number;
98
116
  }
99
117
 
100
118
  interface GhResult {
@@ -1149,6 +1167,65 @@ export function renderReviewerContextStatus(loaded: LoadedReviewerContext, decom
1149
1167
  return `Reviewer context: ${loaded.items.length} loaded, ${loaded.failed.length} not loaded.${source}${truncation}${decompositionStatus}${labels ? `\n${labels}` : ''}${failures ? `\n${failures}` : ''}`;
1150
1168
  }
1151
1169
 
1170
+ /**
1171
+ * 머지된 PR 의 사후 리뷰 격리 — 리뷰어 cwd 가 main 최신이면 그 뒤 수리를 인용한다.
1172
+ * `merged` 는 그 PR 의 머지 커밋, `open` 은 종전(cwd 불변), `unpinnable` 은 MERGED 인데 머지 커밋을 못 구한 경우다.
1173
+ */
1174
+ type PrMergeState =
1175
+ | { kind: 'open' }
1176
+ | { kind: 'merged'; commit: string }
1177
+ | { kind: 'unpinnable'; reason: 'merge-commit-unknown' };
1178
+
1179
+ function readPrMergeState(pr: string, deps: SelfReviewCliDeps): PrMergeState {
1180
+ const view = deps.gh(['pr', 'view', pr, '--json', 'state,mergeCommit'], 15_000);
1181
+ if (view.status !== 0) return { kind: 'open' };
1182
+ try {
1183
+ const parsed = JSON.parse(view.stdout) as { state?: unknown; mergeCommit?: { oid?: unknown } | null };
1184
+ if (parsed?.state !== 'MERGED') return { kind: 'open' };
1185
+ const oid = parsed.mergeCommit?.oid;
1186
+ return typeof oid === 'string' && COMMIT_OID.test(oid)
1187
+ ? { kind: 'merged', commit: oid }
1188
+ : { kind: 'unpinnable', reason: 'merge-commit-unknown' };
1189
+ } catch {
1190
+ return { kind: 'open' };
1191
+ }
1192
+ }
1193
+
1194
+ interface ReviewWorktree {
1195
+ cwd: string;
1196
+ commit: string;
1197
+ /** 멱등 — 두 번 불러도 안전하다. */
1198
+ remove(): void;
1199
+ }
1200
+
1201
+ type ReviewWorktreeResult = ReviewWorktree | { reason: 'no-git-seam' | 'worktree-add-failed' };
1202
+
1203
+ function createDetachedReviewWorktree(commit: string, deps: SelfReviewCliDeps): ReviewWorktreeResult {
1204
+ const git = deps.git;
1205
+ if (!git) return { reason: 'no-git-seam' };
1206
+ const parent = mkdtempSync(join(tmpdir(), 'elanous-review-pin-'));
1207
+ const cwd = join(parent, 'wt');
1208
+ const add = () => git(['worktree', 'add', '--detach', cwd, commit], 120_000);
1209
+ let added = add();
1210
+ if (added.status !== 0) {
1211
+ git(['fetch', 'origin', commit], 120_000);
1212
+ added = add();
1213
+ }
1214
+ let removed = false;
1215
+ const remove = (): void => {
1216
+ if (removed) return;
1217
+ removed = true;
1218
+ git(['worktree', 'remove', '--force', cwd], 60_000);
1219
+ rmSync(parent, { recursive: true, force: true });
1220
+ // ⛔ `git worktree prune` 은 부르지 않는다 — 저장소 «전체»의 stale 메타데이터를 지워 남의 worktree 까지 건드린다.
1221
+ };
1222
+ if (added.status !== 0) {
1223
+ remove();
1224
+ return { reason: 'worktree-add-failed' };
1225
+ }
1226
+ return { cwd, commit, remove };
1227
+ }
1228
+
1152
1229
  /** `elanous self review <pr...>` 본문. read-only — 머지하지 않는다. */
1153
1230
  /**
1154
1231
  * `self review --json` stdout 한 줄 — 결과가 하나면 객체, 여럿이면 배열. index.ts 액션이 이것을 그대로 쓴다.
@@ -1162,6 +1239,20 @@ export async function runSelfReviewCliCommand(
1162
1239
  prArgs: string[],
1163
1240
  opts: SelfReviewCliOpts,
1164
1241
  deps: SelfReviewCliDeps,
1242
+ ): Promise<SelfReviewCliOutcome> {
1243
+ const pins: ReviewWorktree[] = [];
1244
+ try {
1245
+ return await runSelfReviewCliCommandPinned(prArgs, opts, deps, pins);
1246
+ } finally {
1247
+ for (const pin of pins) pin.remove();
1248
+ }
1249
+ }
1250
+
1251
+ async function runSelfReviewCliCommandPinned(
1252
+ prArgs: string[],
1253
+ opts: SelfReviewCliOpts,
1254
+ deps: SelfReviewCliDeps,
1255
+ pins: ReviewWorktree[],
1165
1256
  ): Promise<SelfReviewCliOutcome> {
1166
1257
  // 관측 sink는 모든 종료 경로보다 먼저 등록해 거부도 운영 로그에 남긴다.
1167
1258
  await deps.registerSink('self-review');
@@ -1175,7 +1266,7 @@ export async function runSelfReviewCliCommand(
1175
1266
  invalidPrArgs: safeInvalidPrArgs,
1176
1267
  }, { level: 'warn' });
1177
1268
  deps.error(`PR 인자가 올바르지 않습니다: ${safeInvalidPrArgs.join(', ')}. PR 번호는 숫자 형식이어야 합니다 (예: elanous self review 5502).`);
1178
- return { results: [] };
1269
+ return { results: [], failed: 0 };
1179
1270
  }
1180
1271
 
1181
1272
  const useAcp = opts.acp === true;
@@ -1197,11 +1288,19 @@ export async function runSelfReviewCliCommand(
1197
1288
  if (useAcp) {
1198
1289
  acpReviewLLM = deps.makeAcpLlm({ backend: acpBackend, ...(acpModel ? { model: acpModel } : {}), timeoutMs: acpTimeoutSec * 1000 });
1199
1290
  }
1200
- const model = useAcp ? `acp:${acpBackend}${acpModel ? `/${acpModel}` : ''}` : (opts.model || deps.envModel() || tierModel('better'));
1201
1291
  // ⭐ Reviewer selection source. An explicit flag always wins byte-for-byte; only without one does
1202
1292
  // `roleLlm.reviewer` (the harness's reviewer row) pick the ACP lane. Worst case = today's API review.
1203
1293
  const explicitReviewerFlag = opts.acp === true || Boolean(opts.acpBackend) || Boolean(opts.acpModel?.trim()) || Boolean(opts.model?.trim());
1204
1294
  const reviewerSource: 'cli' | 'role-config' | 'default' = explicitReviewerFlag ? 'cli' : opts.roleReviewer ? 'role-config' : 'default';
1295
+ // SUBSCRIPTION-EXHAUST-REROUTE (0.2.24): when `roleLlm.reviewer` is configured but its lane is unavailable
1296
+ // (10-11 prod: «Claude subscription usage unavailable or at harness cap (60%)»), the API fallback was the codex
1297
+ // ladder default (`tierModel('better')` = gpt-6-sol) — the CLI read roleLlm.reviewer, then spent codex anyway.
1298
+ // ⇒ the role-config lane falls back to `roleFallbackModel()` (off codex) when the seam gives one. Explicit flag
1299
+ // and ELANOUS_PR_REVIEW_MODEL still win; no seam / no answer = today's default byte-for-byte.
1300
+ const envModel = deps.envModel();
1301
+ const roleFallbackModel = !useAcp && !opts.model && !envModel && reviewerSource === 'role-config'
1302
+ ? deps.roleFallbackModel?.()?.trim() || undefined : undefined;
1303
+ const model = useAcp ? `acp:${acpBackend}${acpModel ? `/${acpModel}` : ''}` : (opts.model || envModel || roleFallbackModel || tierModel('better'));
1205
1304
  let roleReviewer: { llm: (prompt: string, images?: readonly ReviewImage[]) => Promise<string>; model: string } | undefined;
1206
1305
  let roleReviewerUnavailableReason: string | undefined;
1207
1306
  let roleReviewerAvailabilityMs: number | undefined;
@@ -1223,6 +1322,7 @@ export async function runSelfReviewCliCommand(
1223
1322
  deps.log('role-reviewer-fallback', {
1224
1323
  reviewerSource, roleReviewerProvider: opts.roleReviewer.provider, roleReviewerAvailabilityMs,
1225
1324
  stage: 'availability', reason: roleReviewerUnavailableReason, fallbackModel: safeLogText(model),
1325
+ fallbackModelSource: roleFallbackModel ? 'role-fallback' : 'default',
1226
1326
  }, { level: 'warn' });
1227
1327
  }
1228
1328
  }
@@ -1234,6 +1334,7 @@ export async function runSelfReviewCliCommand(
1234
1334
  ...(roleReviewerUnavailableReason ? { roleReviewerFallbackReason: roleReviewerUnavailableReason } : {}),
1235
1335
  });
1236
1336
  const results: Array<Record<string, unknown>> = [];
1337
+ let failed = 0;
1237
1338
  const providedReviewerContext = loadReviewerContext(opts, deps.readReferencedFile);
1238
1339
  const hasProvidedReviewerContext = (opts.contextOrder?.length ?? 0) > 0 || (opts.context?.length ?? 0) > 0 || (opts.contextText?.length ?? 0) > 0;
1239
1340
  for (const pr of prArgs) {
@@ -1247,6 +1348,7 @@ export async function runSelfReviewCliCommand(
1247
1348
  // ⛔ `relation-unknown` 도 경고한다(위 주석 · 리뷰가 두 라운드 반복 지적) — 그 밖 unavailable 은 조용하다.
1248
1349
  // ⭐ 경고 여부 판정은 `localHeadWarningDetails` 한 곳에 있다(호출부에서 같은 함수를 두 번 부르지 않는다).
1249
1350
  const mismatchWarning = localHeadWarningDetails(localHeadComparison);
1351
+ const mergeState = readPrMergeState(pr, deps);
1250
1352
  const view = deps.gh(['pr', 'view', pr, '--json', 'title,body'], 15_000);
1251
1353
  let prView: { title?: string; body?: string } | undefined;
1252
1354
  if (view.status === 0) {
@@ -1311,6 +1413,7 @@ export async function runSelfReviewCliCommand(
1311
1413
  const contextOutput = reviewerContextOutput(reviewerContext, decompositionContext);
1312
1414
  if (opts.json) results.push({ pr, error: err, ...contextOutput, ...comparisonData, ...(mismatchWarning ?? {}) });
1313
1415
  else deps.error(`PR ${pr}: ${err}\n${reviewerContextStatus}`);
1416
+ failed += 1;
1314
1417
  continue;
1315
1418
  }
1316
1419
  // ⭐ S2(2026-07-30) — 리뷰 증거를 **이 PR 이 저작한 변경**으로 좁힌다. 실측 7건에서 1건만
@@ -1373,9 +1476,44 @@ export async function runSelfReviewCliCommand(
1373
1476
  else deps.print(`\n━━ PR ${pr} (${primaryModel}) ━━\n${renderStaleRefusal(diffRead)}\n${reviewerContextStatus}`);
1374
1477
  continue;
1375
1478
  }
1479
+ // ⭐ 머지된 PR 만 머지 커밋 detached worktree 에서 리뷰한다 — main 최신이 아니라 그 PR 이 머지된 시점의 코드를 본다.
1480
+ // 열린 PR 은 종전 그대로(cwd = process.cwd() · 리뷰어 심이 cwd 를 받지 않는다).
1481
+ let reviewPin: ReviewWorktree | undefined;
1482
+ let reviewCwdPinFallbackReason: string | undefined;
1483
+ // cwd 를 받는 레인(ACP · role 리뷰어)일 때만 worktree 를 뜬다 — API 리뷰어는 cwd 를 안 받으므로 떠도 그 위에서 돌지 않는다.
1484
+ const pinLane = useAcp || Boolean(roleReviewer && opts.roleReviewer && deps.makeRoleReviewerLlm);
1485
+ let rolePinned = false;
1486
+ if (!pinLane) {
1487
+ // 비-ACP 레인 — 격리하지 않는다(종전 그대로 · reviewCwdCommit 없음).
1488
+ } else if (mergeState.kind === 'merged') {
1489
+ const made = createDetachedReviewWorktree(mergeState.commit, deps);
1490
+ if ('cwd' in made) {
1491
+ reviewPin = made;
1492
+ pins.push(made);
1493
+ } else reviewCwdPinFallbackReason = made.reason;
1494
+ } else if (mergeState.kind === 'unpinnable') reviewCwdPinFallbackReason = mergeState.reason;
1495
+ const reviewCwd = reviewPin?.cwd;
1496
+ const prAcpReviewLLM = reviewCwd && useAcp
1497
+ ? deps.makeAcpLlm({ backend: acpBackend, ...(acpModel ? { model: acpModel } : {}), timeoutMs: acpTimeoutSec * 1000, cwd: reviewCwd })
1498
+ : acpReviewLLM;
1499
+ let prRoleReviewer = roleReviewer;
1500
+ if (reviewCwd && roleReviewer && opts.roleReviewer && deps.makeRoleReviewerLlm) {
1501
+ try {
1502
+ const pinned = deps.makeRoleReviewerLlm(opts.roleReviewer, { timeoutMs: acpTimeoutSec * 1000, cwd: reviewCwd });
1503
+ if ('llm' in pinned) { prRoleReviewer = { llm: pinned.llm, model: `acp:${pinned.backend}` }; rolePinned = true; }
1504
+ else reviewCwdPinFallbackReason = 'role-reviewer-cwd-unavailable';
1505
+ } catch {
1506
+ reviewCwdPinFallbackReason = 'role-reviewer-cwd-unavailable';
1507
+ }
1508
+ }
1376
1509
  const startedAt = deps.now();
1377
1510
  // Role-config lane builds the API reviewer only when it falls back (`made().api` stays 0 on ACP success).
1378
- const llmReview = roleReviewer ? undefined : (acpReviewLLM ?? deps.makeApiLlm(model));
1511
+ const responded: { provider?: string; model?: string } = {};
1512
+ const makeApi = () => deps.makeApiLlm(model, {
1513
+ pinProvider: Boolean(opts.model?.trim()),
1514
+ onResolved: (provider, respondedModel) => { responded.provider = provider; responded.model = respondedModel; },
1515
+ });
1516
+ const llmReview = prRoleReviewer ? undefined : (prAcpReviewLLM ?? makeApi());
1379
1517
  // ⛔ evidenceNote 는 **별도 채널**이다 — phaseIntent 에 섞으면 의도 채널이 오염된다(실측: 그렇게
1380
1518
  // 했다가 intent 배선 테스트 3개가 즉시 깨졌다).
1381
1519
  // ⛔ 사람 `--intent`(phaseIntent) 와 골 acceptance 는 다른 인자 — 충돌하지 않고, 충돌해도 intent 가 이긴다.
@@ -1395,10 +1533,10 @@ export async function runSelfReviewCliCommand(
1395
1533
  let roleReview: ReviewResult | undefined;
1396
1534
  let roleReviewerFallbackReason = roleReviewerUnavailableReason;
1397
1535
  let roleReviewMs: number | undefined;
1398
- if (roleReviewer) {
1536
+ if (prRoleReviewer) {
1399
1537
  const roleStartedAt = deps.now();
1400
1538
  try {
1401
- const attempt = await deps.reviewPullRequest(reviewInput, roleReviewer.llm);
1539
+ const attempt = await deps.reviewPullRequest(reviewInput, prRoleReviewer.llm);
1402
1540
  if (attempt.reviewed === true) roleReview = attempt;
1403
1541
  // Code, not the reviewer's raw failure text (same rule as the throw path above).
1404
1542
  else roleReviewerFallbackReason = 'acp-review-not-completed';
@@ -1414,8 +1552,8 @@ export async function runSelfReviewCliCommand(
1414
1552
  }, { level: 'warn' });
1415
1553
  }
1416
1554
  }
1417
- let review = roleReview ?? await deps.reviewPullRequest(reviewInput, llmReview ?? acpReviewLLM ?? deps.makeApiLlm(model));
1418
- let selectedModel = roleReview && roleReviewer ? roleReviewer.model : model;
1555
+ let review = roleReview ?? await deps.reviewPullRequest(reviewInput, llmReview ?? prAcpReviewLLM ?? makeApi());
1556
+ let selectedModel = roleReview && prRoleReviewer ? prRoleReviewer.model : model;
1419
1557
  let reviewRoute: 'api' | 'acp' | 'acp-fallback' = useAcp || roleReview ? 'acp' : 'api';
1420
1558
  let fallbackAttempted = false;
1421
1559
  let fallbackBackend: string | undefined;
@@ -1435,7 +1573,7 @@ export async function runSelfReviewCliCommand(
1435
1573
  try {
1436
1574
  const fallbackReview = await deps.reviewPullRequest(
1437
1575
  reviewInput,
1438
- deps.makeAcpLlm({ backend, timeoutMs: acpTimeoutSec * 1000 }),
1576
+ deps.makeAcpLlm({ backend, timeoutMs: acpTimeoutSec * 1000, ...(reviewCwd ? { cwd: reviewCwd } : {}) }),
1439
1577
  );
1440
1578
  if (fallbackReview.reviewed === true) {
1441
1579
  review = fallbackReview;
@@ -1451,6 +1589,14 @@ export async function runSelfReviewCliCommand(
1451
1589
  }
1452
1590
  }
1453
1591
  }
1592
+ reviewPin?.remove();
1593
+ // reviewCwdCommit 은 «최종 판정을 낸 LLM 이 실제로 그 cwd 를 받았을 때만» 싣는다(role 실패 → API 폴백이면 안 싣는다).
1594
+ const reviewedOnPin = Boolean(reviewPin) && (roleReview ? rolePinned : reviewRoute === 'acp-fallback' ? true : reviewRoute === 'acp' && useAcp);
1595
+ if (reviewPin && !reviewedOnPin) reviewCwdPinFallbackReason ??= 'final-reviewer-not-pinned';
1596
+ const reviewCwdOutput = {
1597
+ ...(reviewPin && reviewedOnPin ? { reviewCwdCommit: reviewPin.commit } : {}),
1598
+ ...(reviewCwdPinFallbackReason ? { reviewCwdPinFallbackReason } : {}),
1599
+ };
1454
1600
  if (!fallbackAttempted) {
1455
1601
  fallbackNotAttemptedReason = useAcp ? 'explicit-acp' : 'primary-review-succeeded';
1456
1602
  }
@@ -1463,6 +1609,11 @@ export async function runSelfReviewCliCommand(
1463
1609
  ...(fallbackFailures.length ? { fallbackFailures } : {}),
1464
1610
  ...(skippedAcpFallbackBackends.length ? { skippedAcpFallbackBackends } : {}),
1465
1611
  };
1612
+ // API 경로로 «성공한» 리뷰만 응답 provider·model 을 싣는다(요청 model 과 다르면 둘 다 보인다).
1613
+ // ⚠️ streamLLM 의 onResolvedProvider 는 시도 «전»에 불린다 — 실패한 리뷰에 실으면 응답 안 한 provider 를 «응답했다»로 적는다.
1614
+ const respondedOutput = reviewRoute === 'api' && review.reviewed === true && responded.provider
1615
+ ? { respondedProvider: responded.provider, respondedModel: responded.model }
1616
+ : {};
1466
1617
  // ⚠️ `buildReviewObservation` drops unknown keys — the selection rides next to it, not inside it.
1467
1618
  const reviewerSelection = {
1468
1619
  ...reviewerSourceObservation(),
@@ -1486,20 +1637,24 @@ export async function runSelfReviewCliCommand(
1486
1637
  goalLoaded: goalAcceptance.goalLoaded,
1487
1638
  acceptanceChars: goalAcceptance.acceptanceChars,
1488
1639
  ...reviewerSelection,
1640
+ ...reviewCwdOutput,
1489
1641
  },
1490
1642
  { level: review.reviewed === false ? 'warn' : 'info' });
1491
1643
  // --acp 는 대표가 명시 요청한 리뷰 — fail-soft(reviewed=false)면 조용히 pass 하지 말고 표면화(관측=acp-review).
1492
1644
  if (useAcp && review.reviewed === false) {
1493
1645
  const err = 'ACP 리뷰 실행 실패(reviewed=false) — 관측: elanous logs --category acp-review';
1494
1646
  const contextOutput = reviewerContextOutput(reviewerContext, decompositionContext);
1495
- if (opts.json) results.push({ pr, error: err, ...review, verdict: null, ...reviewProvenance, ...reviewerSelection, ...provenance, ...contextOutput });
1647
+ if (opts.json) results.push({ pr, error: err, ...review, verdict: null, ...reviewProvenance, ...respondedOutput, ...reviewerSelection, ...reviewCwdOutput, ...provenance, ...contextOutput });
1496
1648
  else deps.error(`PR ${pr}: ${err}\n${renderProvenance(diffRead)}\n${reviewerContextStatus}`);
1649
+ failed += 1;
1497
1650
  continue;
1498
1651
  }
1499
1652
  const contextOutput = reviewerContextOutput(reviewerContext, decompositionContext);
1500
1653
  const jsonReview = review.reviewed === true ? review : { ...review, verdict: null };
1501
- if (opts.json) results.push({ pr, model: selectedModel, ...jsonReview, ...reviewProvenance, ...reviewerSelection, ...provenance, ...contextOutput, evidence: evidence.evidence, prDiffFiles: evidence.prDiffFiles, ...(evidence.authoredFiles !== undefined ? { authoredFiles: evidence.authoredFiles } : {}) });
1654
+ if (opts.json) results.push({ pr, model: selectedModel, ...jsonReview, ...reviewProvenance, ...respondedOutput, ...reviewerSelection, ...reviewCwdOutput, ...provenance, ...contextOutput, evidence: evidence.evidence, prDiffFiles: evidence.prDiffFiles, ...(evidence.authoredFiles !== undefined ? { authoredFiles: evidence.authoredFiles } : {}) });
1502
1655
  else deps.print(`\n━━ PR ${pr} (${selectedModel}) ━━\n${renderProvenance(diffRead)}\n${evidenceLine}\n${reviewerContextStatus}\n${deps.renderReview(review)}`);
1656
+ // REVIEW-ERROR-RC — 기본(API)·role 경로가 1차·폴백 모두 실패해 reviewed≠true 로 끝나도 «못 리뷰한 PR» 이다(verdict:null).
1657
+ if (review.reviewed !== true) failed += 1;
1503
1658
  }
1504
- return { results };
1659
+ return { results, failed };
1505
1660
  }
@@ -106,12 +106,25 @@ export function buildCritiquePrompt(input: { planBody: string; changedFiles: str
106
106
  ].join('\n');
107
107
  }
108
108
 
109
- /** LLM 응답 파싱 → verdict + findings. 순수함수(LLM node 규칙). */
109
+ /** 판정 줄 — «줄 머리» VERDICT 만 판정으로 읽는다(본문 중간 인용·설명 속 «VERDICT:» 오인 방지).
110
+ * 들여쓰기는 허용(mission-engine 의 미션 판정 파서와 같은 앵커). */
111
+ const CRITIQUE_VERDICT_LINE = /^[ \t]*VERDICT:\s*(PASS|WARN|FAIL)/im;
112
+ /** 판정 줄이 없을 때 findings 에 남기는 fail-closed 사유(REVIEW-NO-VERDICT-FAILCLOSED #25937). */
113
+ const NO_VERDICT_FINDING = '비평 판정 줄(VERDICT) 없음 — 판정 없음은 통과가 아니다(fail-closed · REVIEW-NO-VERDICT-FAILCLOSED #25937)';
114
+ const MAX_CRITIQUE_FINDINGS = 4;
115
+
116
+ /** LLM 응답 파싱 → verdict + findings. 순수함수(LLM node 규칙).
117
+ * ⛔ 판정 줄이 «없으면» pass 로 기본하지 않는다(칸 MISSION-CRITIQUE-FAILCLOSED · #25937):
118
+ * «판정 없음 = 통과 아님» ⇒ verdict 'warn' + 사유 finding.
119
+ * 'fail' 이 아니라 'warn' 인 이유 — 소비측(nocturnal-runner)은 critique verdict==='fail' 에
120
+ * gate-failed(재구현 요구)를 건다. «비평가 응답의 형식 결함»을 «구현 훼손」으로
121
+ * 오귀속시키는 것이다. 'warn' 은 PR 본문(renderCritique)·자율 원장에 그대로 표시되어 사람(HITL)이 판단한다.
122
+ * (post-PR 리뷰 축 parseReviewResult 는 substrate 가 `reviewed:false` 로 같은 fail-closed 를 이미 한다.) */
110
123
  export function parseLLMCritique(text: string): { verdict: CritiqueResult['verdict']; findings: string[] } {
111
- const vm = /VERDICT:\s*(PASS|WARN|FAIL)/i.exec(text);
112
- const verdict = (vm ? vm[1]!.toLowerCase() : 'pass') as CritiqueResult['verdict'];
113
- const findings = text.split('\n').map((l) => l.trim()).filter((l) => l.startsWith('- ')).map((l) => l.slice(2).trim()).slice(0, 4);
114
- return { verdict, findings };
124
+ const bullets = text.split('\n').map((l) => l.trim()).filter((l) => l.startsWith('- ')).map((l) => l.slice(2).trim());
125
+ const vm = CRITIQUE_VERDICT_LINE.exec(text);
126
+ if (!vm) return { verdict: 'warn', findings: [NO_VERDICT_FINDING, ...bullets].slice(0, MAX_CRITIQUE_FINDINGS) };
127
+ return { verdict: vm[1]!.toLowerCase() as CritiqueResult['verdict'], findings: bullets.slice(0, MAX_CRITIQUE_FINDINGS) };
115
128
  }
116
129
 
117
130
  /** ★ R1 결정론 + LLM 비평(대표 2026-07-12) — 결정론(R0) 먼저, llmReview 주입 시 LLM 심층 비평