elanous 0.2.36 → 0.2.37

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 (630) 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/{uC-N0emedeNOFuaBQFv-I → 8kITumG9GAZ1LwT9POrAR}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1224.2ceca6c180d5130b.js +62 -0
  8. package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 1262.a89bb27a5b2f844e.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 1746.3563617ea64023a3.js} +1 -1
  12. package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1ed5e8af.cf424815c7c0efad.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 2002-a43a3f380df873ec.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/210.90b2cbd64926cf34.js +32 -0
  19. package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 2283.edd9627b7bdfb546.js} +2 -2
  20. package/apps/pwa/out/_next/static/chunks/2318-450e75d07605b8fe.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 2375.bf364c85dbb6f085.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2479-fe7e188bd9402d14.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +148 -0
  25. package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +27 -0
  29. package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 3199.6a1a9b0e6cd01dc6.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/{2986.45d7652e4f13557e.js → 3578.4e9f9948a9a6f2f4.js} +2 -2
  35. package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +36 -0
  37. package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/4036.d54e55e1ebf5acdc.js +90 -0
  39. package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +226 -0
  40. package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +287 -0
  41. package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{7481.39f7a4654907bf6e.js → 4313.76f232c304a15bde.js} +1 -1
  43. package/apps/pwa/out/_next/static/chunks/4324.c99ba3e83eb1b691.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4337e36d.f42c3b391b3d8f20.js +122 -0
  45. package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 4383.18e5c54db3a22c88.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{3757-180308bc61021b05.js → 4725-34bed25720cc326b.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4833-7934c592c5569f00.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +24 -0
  52. package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 4931.95cc6dbd230774ca.js} +3 -3
  53. package/apps/pwa/out/_next/static/chunks/4937-28d437999b77c9dd.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5046.7fd5cbd859299448.js} +2 -2
  56. package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +104 -0
  57. package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 58edce7d.f1b0c72acf13b123.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +93 -0
  65. package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 5952.294fc574a8625184.js} +1 -1
  66. package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 5f6af561-f90b7a67f4f75d13.js} +1 -1
  67. package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +74 -0
  68. package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 6252.240578f10952e091.js} +1 -1
  69. package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 6680.6a693c28aae4cd19.js} +2 -2
  71. package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 6745-5a63492933959dd9.js} +3 -3
  72. package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +149 -0
  74. package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 6819.be5c9c4d67f22922.js} +3 -3
  75. package/apps/pwa/out/_next/static/chunks/6877-84d47b7e85d0c41e.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6971-fb5f9dc0a2cb5d2d.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → 709a918c.4fd3b4e2a32cb4e3.js} +1 -1
  78. package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +41 -0
  80. package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +24 -0
  83. package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 7424.c0fe2a595d4232b5.js} +1 -1
  87. package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/757-4fbaf50942b8c424.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 7867.e8725745ddd1d940.js} +4 -4
  93. package/apps/pwa/out/_next/static/chunks/{6466-92e65a48490b68a9.js → 7893-e444a1b0809cd1e4.js} +1 -1
  94. package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{ccae1c4b-0cf414f5eff1b10d.js → 7c5ed21f-f286708e57cf88f7.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +8 -0
  98. package/apps/pwa/out/_next/static/chunks/{3840-5825d56d46976a92.js → 8080-40d781e7704d3671.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +77 -0
  100. package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +286 -0
  103. package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +79 -0
  107. package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → 8c58d09b.e8724a299658d86f.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 9151.a2c51e93f9156dae.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/9175-7d383df15a82e2be.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +94 -0
  117. package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{190.285c832bd9626f8c.js → 958.53a8dcf4729e6997.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-5c112c6d7c33656e.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/{page-e2de2e59111c9aad.js → page-3337c6a1328c2674.js} +1 -1
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/{page-f2b2e4bf6e981450.js → page-89acd5d68c0bc560.js} +1 -1
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/{page-2af16e62c12f22df.js → page-fe986fe79b107546.js} +1 -1
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-1e5da297557d2354.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-88a1edbff62eaf1d.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-443364c9e4a23b31.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-b9af2ac1c4737ce8.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-fb9e639c107f5f72.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/page-ac2c1e6169cfce57.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-c1c80e345fa9d6f5.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → d9815f84.4918f682a45a8502.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → de8446d3.31b73eb239fecd7b.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.js +1 -0
  184. package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/graphs/drafts/recipes.yaml +27 -7
  279. package/graphs/work/draft-close.yaml +54 -0
  280. package/graphs/work/green-close.yaml +37 -0
  281. package/graphs/work/recipes.yaml +46 -1
  282. package/graphs/work/run-research.yaml +35 -0
  283. package/package.json +1 -1
  284. package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
  285. package/scripts/boundary-proof-mapping-audit.ts +88 -0
  286. package/scripts/codex-fallback-live-probe.ts +17 -15
  287. package/scripts/fleet/node-setup.sh +32 -2
  288. package/scripts/fleet/run-light-worker.sh +9 -0
  289. package/scripts/gate-0226-failure-census.ts +507 -0
  290. package/scripts/goals/authoring-metrics.ts +258 -0
  291. package/scripts/graph-units/draft-close-node.ts +222 -0
  292. package/scripts/hook-order-sweep.ts +7 -4
  293. package/scripts/land-global-checks.ts +69 -1
  294. package/scripts/measure-nl-routing-corpus.ts +207 -2
  295. package/scripts/release-loop/docs-node.ts +140 -0
  296. package/scripts/release-loop/gate-closure.ts +48 -0
  297. package/scripts/release-loop/gate-diff.ts +2 -1
  298. package/scripts/release-loop/known-issues-node.ts +6 -4
  299. package/scripts/release-loop/notes-repair.ts +216 -0
  300. package/scripts/release-loop/prepare-node.ts +61 -5
  301. package/scripts/release-loop/resume-release.ts +114 -4
  302. package/scripts/release-loop/resume-test-traffic.ts +10 -0
  303. package/scripts/release-loop/version-node.ts +81 -12
  304. package/scripts/train/green-leg.ts +176 -0
  305. package/scripts/tui-continue-real-evidence.ts +47 -0
  306. package/scripts/ux-sim.ts +1 -1
  307. package/src/acp/client.ts +31 -5
  308. package/src/acp/core-turn-bridge.ts +6 -0
  309. package/src/acp/stderr-summary.ts +49 -0
  310. package/src/agent/monad-agent-turn.ts +1 -0
  311. package/src/agent/terminal-surface.ts +217 -0
  312. package/src/agent-substrate/pr-reviewer.ts +11 -3
  313. package/src/agent-substrate/self-review-cli.ts +343 -31
  314. package/src/autopilot/lineage/sources.ts +1 -1
  315. package/src/autopilot/pr-manager.ts +64 -13
  316. package/src/boot/daemon-runtime.ts +35 -3
  317. package/src/boot/daemon-tools/pty-shell.ts +2 -1
  318. package/src/budget/run-usage-rollup.ts +12 -7
  319. package/src/budget/unified-usage.ts +20 -0
  320. package/src/capture/tui-self-report.ts +32 -3
  321. package/src/cli/autopilot-cli.ts +24 -9
  322. package/src/cli/decisions-cli.ts +7 -4
  323. package/src/cli/doctor-cli.ts +116 -7
  324. package/src/cli/logs-cli.ts +357 -2
  325. package/src/cli/memory-cli.ts +30 -1
  326. package/src/cli/msg-cli.ts +15 -11
  327. package/src/cli/pr-granularity.ts +5 -3
  328. package/src/cli/release-checklist-read-cli.ts +109 -4
  329. package/src/cli/release-cli.ts +43 -10
  330. package/src/cli/self-update.ts +23 -5
  331. package/src/cli/self-utterances-cli.ts +13 -16
  332. package/src/cli/tasks-cli.ts +309 -11
  333. package/src/cli/usage-cli.ts +12 -10
  334. package/src/context-bus/claude-memory-import.ts +99 -0
  335. package/src/context-bus/long-term-memory.ts +125 -0
  336. package/src/core-turn/run-goal-loop.ts +5 -2
  337. package/src/core-turn/types.ts +2 -0
  338. package/src/dashboard/chat/acp-chat.ts +9 -0
  339. package/src/dashboard/index.ts +97 -13
  340. package/src/dashboard/input/agent-wake.ts +43 -0
  341. package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
  342. package/src/dashboard/replay-preview.ts +25 -0
  343. package/src/dashboard/slash-runtime/dashboard-handlers.ts +17 -8
  344. package/src/dashboard/synchronized-frame-output.ts +74 -0
  345. package/src/display/coordinator.ts +45 -12
  346. package/src/display/resize-listener.ts +41 -20
  347. package/src/display/synchronized-output-region.ts +60 -0
  348. package/src/domains/surface-events.ts +80 -1
  349. package/src/exec-requests/planner.ts +37 -2
  350. package/src/execution-loop/launch-gate.ts +4 -3
  351. package/src/git-fs/cli-stderr.ts +45 -0
  352. package/src/git-fs/gh-cli.ts +6 -3
  353. package/src/git-fs/git-cli.ts +11 -5
  354. package/src/graph-runner/graph-cli.ts +26 -2
  355. package/src/graph-runner/graph-run-api.ts +3 -2
  356. package/src/graph-runner/runner.ts +17 -5
  357. package/src/graph-wizard/generate.ts +29 -6
  358. package/src/harness/harness-cli-command.ts +179 -33
  359. package/src/harness/review-adapter.ts +26 -6
  360. package/src/index.ts +116 -13
  361. package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
  362. package/src/llm/route-decision.ts +13 -0
  363. package/src/llm-tool-name.ts +37 -0
  364. package/src/llm-tool-schema.ts +35 -0
  365. package/src/llm.ts +123 -11
  366. package/src/loops/checker.ts +100 -0
  367. package/src/loops/consensus.ts +26 -2
  368. package/src/loops/loop-cli.ts +9 -4
  369. package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
  370. package/src/loops/orchestrator/tick.ts +49 -4
  371. package/src/model-tier/llm-tier-map.ts +12 -17
  372. package/src/msg/msg-store.ts +17 -0
  373. package/src/native-tool-catalog.ts +1 -1
  374. package/src/nexus/api/graph-wizard-api.ts +27 -2
  375. package/src/nexus/api/grid.ts +24 -4
  376. package/src/nexus/api/http-server.ts +1 -1
  377. package/src/nexus/api/ops-api.ts +14 -6
  378. package/src/nexus/state/state.ts +7 -1
  379. package/src/oauth/codex-account-store.ts +34 -1
  380. package/src/ops/loops-map.ts +46 -0
  381. package/src/ops/overview-cache.ts +22 -4
  382. package/src/ops/overview.ts +41 -5
  383. package/src/policy/llm-policy.ts +3 -1
  384. package/src/prompt-enhance/enhance.ts +4 -4
  385. package/src/pty-shell/availability.ts +7 -0
  386. package/src/pty-shell/herdr-agent-report.ts +40 -31
  387. package/src/pty-shell/herdr-prune-stale.ts +17 -0
  388. package/src/pty-shell/herdr-sequence-lease.ts +60 -0
  389. package/src/pty-shell/pty-control-ipc.ts +187 -18
  390. package/src/pty-shell/registry.ts +25 -15
  391. package/src/pty-shell/tui-run-state.ts +235 -1
  392. package/src/release-loop/checklist.ts +50 -5
  393. package/src/release-loop/feature-store.ts +9 -9
  394. package/src/release-loop/landed-but-yellow.ts +93 -12
  395. package/src/repl/index.ts +8 -0
  396. package/src/seat-loop/seat-report.ts +1 -0
  397. package/src/self-dev/ask-launch-flow.ts +86 -10
  398. package/src/self-dev/decompose-proposal.ts +29 -18
  399. package/src/self-dev/dev-pipeline.ts +29 -7
  400. package/src/self-dev/draft-sweep.ts +241 -16
  401. package/src/self-dev/draft-triage-rules.ts +19 -5
  402. package/src/self-dev/review-provider-fallback.ts +45 -7
  403. package/src/self-dev/shard-plan.ts +48 -0
  404. package/src/self-dev/shard-run.ts +50 -3
  405. package/src/self-implement/doctor-visit.ts +83 -0
  406. package/src/self-implement/gate-artifacts.ts +6 -2
  407. package/src/self-implement/gate-baseline.ts +64 -1
  408. package/src/self-implement/gate-cli.ts +93 -9
  409. package/src/self-implement/gate-remote.ts +28 -4
  410. package/src/self-implement/gate-scope.ts +13 -1
  411. package/src/self-implement/goal-author.ts +333 -18
  412. package/src/self-implement/goal-supervisor-fill.ts +75 -26
  413. package/src/self-implement/importer-test-index.ts +215 -2
  414. package/src/self-implement/knowhow-pack.ts +5 -5
  415. package/src/self-implement/orchestrator.ts +318 -25
  416. package/src/self-implement/review-round-brief.ts +300 -0
  417. package/src/self-implement/rework-policy.ts +14 -0
  418. package/src/self-implement/run-ledger.ts +170 -6
  419. package/src/self-implement/run-stop.ts +1 -1
  420. package/src/self-implement/running-runs.ts +17 -3
  421. package/src/self-implement/seams.ts +12 -6
  422. package/src/self-implement/stop-autoheal.ts +1 -0
  423. package/src/self-implement/test-seams.ts +13 -1
  424. package/src/self-implement/train-reach-grouping.ts +8 -2
  425. package/src/session/chat.ts +7 -1
  426. package/src/session/id-prefix.ts +60 -0
  427. package/src/session/index.ts +4 -0
  428. package/src/session-runtime/index.ts +9 -1
  429. package/src/skills/tools/pty.ts +5 -0
  430. package/src/status/metrics.ts +12 -1
  431. package/src/steward/rejudge-tick.ts +12 -5
  432. package/src/steward/resync-tick.ts +31 -4
  433. package/src/task-agent/actions.ts +199 -4
  434. package/src/task-agent/boundary-proof-mapping.ts +12 -0
  435. package/src/task-agent/boundary-proof-producer.ts +147 -0
  436. package/src/task-agent/completion-evidence.ts +2 -1
  437. package/src/task-agent/green-close-recipe.ts +239 -0
  438. package/src/task-agent/green-sweep.ts +64 -10
  439. package/src/task-agent/live-moves.ts +48 -3
  440. package/src/task-agent/map-host-adapter.ts +134 -0
  441. package/src/task-agent/map-reduce.ts +158 -0
  442. package/src/task-agent/map-run-ledger.ts +226 -0
  443. package/src/task-agent/parent-host.ts +21 -11
  444. package/src/task-agent/rejudge-on-head.ts +72 -5
  445. package/src/task-agent/repair-cycle.ts +41 -0
  446. package/src/task-agent/repair-next-move.ts +12 -2
  447. package/src/task-agent/review-prior-fix.ts +12 -2
  448. package/src/task-agent/shadow.ts +188 -5
  449. package/src/task-agent/task-hand.ts +158 -13
  450. package/src/task-agent/task-parent-role-llm.ts +9 -0
  451. package/src/task-agent/tier-split.ts +4 -3
  452. package/src/task-agent/work-order.ts +53 -2
  453. package/src/task-orchestrator/dispatcher.ts +46 -1
  454. package/src/task-orchestrator/generator-prompt.ts +6 -0
  455. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
  456. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
  457. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
  458. package/src/task-orchestrator/surfaces/pod-pool.ts +50 -4
  459. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
  460. package/src/task-orchestrator/surfaces/self-implement-pod.ts +217 -36
  461. package/src/task-orchestrator/surfaces/self-implement.ts +4 -0
  462. package/src/testing/linux-env.ts +177 -0
  463. package/src/tui/chat/goal-interim.ts +5 -1
  464. package/src/tui/entry.ts +258 -4
  465. package/src/tui/input/at-picker.ts +55 -0
  466. package/src/tui/slash/resume.ts +35 -12
  467. package/src/tui/slash/signals.ts +114 -0
  468. package/src/tui/slash/term-next.ts +71 -0
  469. package/src/tui-client/local-chat-turn.ts +4 -3
  470. package/src/user-config.ts +19 -1
  471. package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
  472. package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
  473. package/src/ux-sim/fake-gh.ts +174 -0
  474. package/src/ux-sim/fake-kubectl.ts +142 -0
  475. package/src/ux-sim/fake-llm.ts +6 -1
  476. package/src/ux-sim/next-tui-seat-scenarios.ts +124 -6
  477. package/src/ux-sim/resume-picker-device.ts +173 -0
  478. package/src/ux-sim/session-id-seed.ts +60 -0
  479. package/src/ux-sim/skills-tools-shell-device.ts +156 -0
  480. package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
  481. package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
  482. package/src/version/packed-revision.json +1 -1
  483. package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
  484. package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
  490. package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
  493. package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
  498. package/apps/pwa/out/_next/static/chunks/2812ca6a.3b9f4a7a08885744.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
  502. package/apps/pwa/out/_next/static/chunks/3031-85328a92fcce4da6.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/3148-98efd4869d660a87.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
  505. package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
  509. package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
  510. package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
  512. package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
  515. package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/4116.a84a92a2492c080e.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
  519. package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
  522. package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
  524. package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
  526. package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/599.c39c571b6733f2a2.js +0 -41
  531. package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
  532. package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/6566.926a1d1b7c911442.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
  544. package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/6925.562d532110879886.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/7784.1f0ac4a16d190cf4.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/8037.e254fd797aa224d1.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
  557. package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
  559. package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
  560. package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
  565. package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/app/outputs/page-e7abc34a48a6f71e.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/app/term/page-c15958835534404b.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
  630. /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → 8kITumG9GAZ1LwT9POrAR}/_ssgManifest.js +0 -0
@@ -20,18 +20,40 @@ import { dirname, join } from 'node:path';
20
20
  import { effectiveInstanceRoot } from '../instance/resolve.js';
21
21
  import { tierModel } from '../llm/model-defaults.js';
22
22
  import { buildReviewObservation, safeLogText } from './review-observation.js';
23
+ import { checkCitedReviewPathsAtHead } from './review-finding-key.js';
23
24
  import { DEFAULT_REVIEW_BACKEND, defaultAcpReviewTimeoutSec } from './acp-reviewer.js';
24
25
  import { ZAI_OPENROUTER_FALLBACK_MODEL } from '../llm/zai-coding-plan.js';
25
26
  import { debug } from '../debug/log.js';
26
27
  import { ACP_BACKENDS, canonicalizeBackendId } from '../acp/backend-registry.js';
27
28
  import { buildManualReviewIntent, intentFromPr, prIntentSectionCoverage, reviewIntentTruncationFromPr, reviewIntentTruncationObservation } from './review-intent.js';
28
- import { budgetReviewerContext, reviewDiffBudgetObservation, splitDiffByFile, type ReviewImage, type ReviewInput, type ReviewerContextItem, type ReviewResult } from './pr-reviewer.js';
29
+ import { budgetReviewerContext, isNoneSentinelFinding, reviewDiffBudgetObservation, splitDiffByFile, type ReviewImage, type ReviewInput, type ReviewerContextItem, type ReviewResult } from './pr-reviewer.js';
29
30
  import type { ReferencedFileReader } from '../self-implement/goal-file-reader.js';
30
- import { getUserConfig, type LLMProviderName, type RoleLlmSpec, type SubscriptionReviewerSpec } from '../user-config.js';
31
+ import { getUserConfig, type LLMProviderName, type ReviewerMixSpec, type RoleLlmSpec, type SubscriptionReviewerSpec } from '../user-config.js';
32
+ import { loadLlmPolicy } from '../policy/llm-policy.js';
31
33
  import { listRunLedgers, lookupPrGoalAcceptance, lookupRunLedger, type PrGoalAcceptanceLookup, type RunLedgerEntry, type RunLedgerLookup } from '../self-implement/run-ledger.js';
32
34
 
33
35
  /** SUBSCRIPTION-EXHAUST-REROUTE — API reviewer when the configured `roleLlm.reviewer` lane is unavailable (off codex). */
34
36
  export const ROLE_REVIEWER_FALLBACK_MODEL = 'openrouter/z-ai/glm-5.3';
37
+ export const DEFAULT_REVIEWER_MIX: ReviewerMixSpec = { sol: 1, claude: 1, glm: 1 };
38
+ type ReviewLane = keyof ReviewerMixSpec;
39
+ const REVIEW_LANES: readonly ReviewLane[] = ['sol', 'claude', 'glm'];
40
+
41
+ /** A PR keeps the same primary lane through every review round, regardless of head SHA. */
42
+ export function reviewLaneOrder(pr: string, mix: ReviewerMixSpec): ReviewLane[] {
43
+ if (!/^\d+$/.test(pr)) return [];
44
+ const total = REVIEW_LANES.reduce((sum, lane) => sum + mix[lane], 0);
45
+ if (!Number.isSafeInteger(total) || total <= 0) return [];
46
+ const slot = Number(BigInt(pr) % BigInt(total));
47
+ let offset = 0;
48
+ let primary: ReviewLane | undefined;
49
+ for (const lane of REVIEW_LANES) {
50
+ offset += mix[lane];
51
+ if (slot < offset) { primary = lane; break; }
52
+ }
53
+ if (!primary) return [];
54
+ const start = REVIEW_LANES.indexOf(primary);
55
+ return [...REVIEW_LANES.slice(start), ...REVIEW_LANES.slice(0, start)].filter(lane => mix[lane] > 0);
56
+ }
35
57
 
36
58
  /** Only an explicit provider+model role setting selects the API review model. */
37
59
  export function apiReviewModelFromRoleSpec(spec: RoleLlmSpec | undefined): string | undefined {
@@ -54,6 +76,15 @@ export interface SelfReviewCliOpts {
54
76
  reviewDenyBackends?: string[] | undefined;
55
77
  /** `roleLlm.reviewer` (same resolution as the harness). Used only when no explicit reviewer flag is given. */
56
78
  roleReviewer?: SubscriptionReviewerSpec | undefined;
79
+ /** Default resolves from policy/config; null keeps the legacy single reviewer for isolated callers. */
80
+ reviewerMix?: ReviewerMixSpec | null | undefined;
81
+ /** Internal route metadata; the user-facing mix is selected once per PR. */
82
+ reviewerMixPrimaryLane?: ReviewLane | undefined;
83
+ reviewerMixAttemptLane?: ReviewLane | undefined;
84
+ reviewerMixExpectedHead?: string | undefined;
85
+ /** Internal: the same command already claimed its single over-cap exception for this pinned head. */
86
+ reviewerMixCapClaimed?: boolean | undefined;
87
+ disableClaudeGlmFallback?: boolean | undefined;
57
88
  acpTimeout?: string | undefined;
58
89
  context?: string[] | undefined;
59
90
  contextText?: string[] | undefined;
@@ -67,6 +98,8 @@ export interface SelfReviewCliOpts {
67
98
 
68
99
  /** 셸/네트워크/로그 경계 — 테스트는 전부 대역으로 채운다. */
69
100
  export interface SelfReviewCliDeps {
101
+ /** Explicit repository root for exact-head cited-path checks; absent means unmeasured. */
102
+ reviewRepositoryPath?: string;
70
103
  /** `gh` 호출. 실패도 예외 없이 `{status, stdout, stderr}` 로 돌려준다(spawnSync 동형). */
71
104
  gh(args: string[], timeoutMs: number): { status: number | null; stdout: string; stderr: string };
72
105
  /** ⭐ `git` 호출(선택). 주입되면 리뷰 증거를 **이 PR 이 저작한 변경**으로 좁힌다(아래 참조).
@@ -1371,6 +1404,105 @@ function createDetachedReviewWorktree(commit: string, deps: SelfReviewCliDeps):
1371
1404
  return { cwd, commit, remove };
1372
1405
  }
1373
1406
 
1407
+ // ── 착지 관문(landing gate) — requested/actual ────────────────────────────────────────────
1408
+ //
1409
+ // ⚠️ 왜 생산자(여기)에 있나: 착지 관문(`src/cli/pr-land-overlap-evidence.ts`)도 결과 JSON 을 읽어
1410
+ // 같은 대조를 하지만, 그 파일을 **만드는 자리**가 틀린 requested/actual 을 적으면 관문은 그
1411
+ // 거짓을 근거로 판정한다. 그리고 `acp.reviewDenyBackends` 가 금지한 백엔드가 낸 판정은 파일이
1412
+ // 되기 **전에** 거부돼야 `--save` 로도 착지 근거가 될 수 없다(fail-closed).
1413
+ //
1414
+ // ⛔ 못 잰 값(`unmeasured`)을 «일치»로 적지 않는다 — 부재와 미지를 같은 값으로 두지 않는다.
1415
+
1416
+ /** 사람이 요청한 리뷰어. `value` 는 화면·로그에 그대로 나가는 **요청 원문**이다. */
1417
+ interface LandingGateRequest {
1418
+ kind: 'api-model' | 'acp-backend' | 'role-lane';
1419
+ value: string;
1420
+ /** api-model 요청의 정규화된 기대 모델(짧은 별칭 → 정본 ID). */
1421
+ model?: string;
1422
+ /** acp-backend 요청의 기대 백엔드. */
1423
+ backend?: string;
1424
+ }
1425
+
1426
+ /** 실제로 판정을 낸 리뷰어. `value` 는 실측 원문(`api:<model>` · `acp:<backend>` · `unmeasured`). */
1427
+ interface LandingGateActual {
1428
+ kind: 'api' | 'acp' | 'unknown';
1429
+ value: string;
1430
+ model?: string;
1431
+ backend?: string;
1432
+ respondedProvider?: string;
1433
+ respondedModel?: string;
1434
+ }
1435
+
1436
+ type LandingGateOutcome =
1437
+ | { state: 'consistent'; requested: string; actual: string }
1438
+ | { state: 'mismatch'; requested: string; actual: string; warning: string }
1439
+ | { state: 'denied'; requested: string; actual: string; warning: string; refusal: 'review-forbidden-acp-backend'; deniedBackend: string };
1440
+
1441
+ function normalizedReviewBackend(value: string | undefined): string {
1442
+ return canonicalizeBackendId((value ?? '').trim()).trim().toLowerCase();
1443
+ }
1444
+
1445
+ /** 금지 목록 대조. 문자열 엔트리와 구조형(`{backend, expiresAt}`) 엔트리가 같은 값으로 접힌다. */
1446
+ function deniedReviewBackend(backend: string | undefined, denyBackends: readonly string[]): boolean {
1447
+ const target = normalizedReviewBackend(backend);
1448
+ if (!target) return false;
1449
+ return denyBackends.some((denied) => normalizedReviewBackend(denied) === target);
1450
+ }
1451
+
1452
+ function landingGateAgrees(request: LandingGateRequest, actual: LandingGateActual): boolean {
1453
+ // ⛔ 실측을 못 잰 것을 «일치»로 적지 않는다(요청이 있으면 불일치로 남긴다).
1454
+ if (actual.kind === 'unknown') return false;
1455
+ if (request.kind === 'api-model') {
1456
+ if (actual.kind !== 'api') return false;
1457
+ const requested = (request.model ?? request.value).trim().toLowerCase();
1458
+ const selected = (actual.model ?? '').trim().toLowerCase();
1459
+ if (selected && selected === requested) return true;
1460
+ const respondedProvider = (actual.respondedProvider ?? '').trim().toLowerCase();
1461
+ const respondedModel = (actual.respondedModel ?? '').trim().toLowerCase();
1462
+ // 요청이 공급자 한정 형태(`openrouter/<model>`)일 때만 공급자·응답 모델을 대조한다 —
1463
+ // 맨 모델 ID(`gpt-6-sol`·`claude-sonnet-4`)는 공급자와 비교할 수 없다.
1464
+ const slash = requested.indexOf('/');
1465
+ if (slash <= 0) return false;
1466
+ const requestedProvider = requested.slice(0, slash);
1467
+ const requestedTail = requested.slice(slash + 1);
1468
+ return Boolean(respondedProvider) && respondedProvider === requestedProvider
1469
+ && Boolean(respondedModel) && (respondedModel === requestedTail || respondedModel === requested);
1470
+ }
1471
+ if (request.kind === 'acp-backend') {
1472
+ return actual.kind === 'acp' && normalizedReviewBackend(actual.backend) === normalizedReviewBackend(request.backend);
1473
+ }
1474
+ // role-lane: 설정이 고른 레인은 provider 표기(`claude-acp`)와 백엔드 표기(`claude`)가 달라
1475
+ // 백엔드 이름으로 비교하지 않는다 — 「ACP 레인으로 판정했나」만 본다.
1476
+ return actual.kind === 'acp';
1477
+ }
1478
+
1479
+ function landingGateOutcome(input: {
1480
+ pr: string;
1481
+ reviewRoute: 'api' | 'acp' | 'acp-fallback';
1482
+ request?: LandingGateRequest | undefined;
1483
+ actual: LandingGateActual;
1484
+ deniedBackends: readonly string[];
1485
+ }): LandingGateOutcome {
1486
+ const requested = input.request?.value ?? '(none)';
1487
+ const actual = input.actual.value;
1488
+ if (input.actual.kind === 'acp' && deniedReviewBackend(input.actual.backend, input.deniedBackends)) {
1489
+ const deniedBackend = normalizedReviewBackend(input.actual.backend);
1490
+ return {
1491
+ state: 'denied', requested, actual, refusal: 'review-forbidden-acp-backend', deniedBackend,
1492
+ warning: `⛔ LANDING GATE DENY (fail-closed): requested=${requested} actual=${actual} denied=${deniedBackend} reviewRoute=${input.reviewRoute} — acp.reviewDenyBackends 가 금지한 백엔드가 판정을 냈습니다. PR ${input.pr} 의 이 리뷰는 착지 근거가 아니며 self review 는 실패(rc≠0)로 끝납니다.`,
1493
+ };
1494
+ }
1495
+ if (!input.request || landingGateAgrees(input.request, input.actual)) return { state: 'consistent', requested, actual };
1496
+ const responded = [
1497
+ input.actual.respondedProvider ? `respondedProvider=${input.actual.respondedProvider}` : '',
1498
+ input.actual.respondedModel ? `respondedModel=${input.actual.respondedModel}` : '',
1499
+ ].filter(Boolean).join(' ');
1500
+ return {
1501
+ state: 'mismatch', requested, actual,
1502
+ warning: `⚠️ LANDING GATE REQUESTED/ACTUAL MISMATCH: requested=${requested} actual=${actual} reviewRoute=${input.reviewRoute}${responded ? ` ${responded}` : ''} — 요청한 리뷰어와 실제로 판정을 낸 리뷰어가 다릅니다(PR ${input.pr}). 이 리뷰를 착지 근거로 쓰기 전에 확인하세요.`,
1503
+ };
1504
+ }
1505
+
1374
1506
  /** `elanous self review <pr...>` 본문. read-only — 머지하지 않는다. */
1375
1507
  /**
1376
1508
  * `self review --json` stdout 한 줄 — 결과가 하나면 객체, 여럿이면 배열. index.ts 액션이 이것을 그대로 쓴다.
@@ -1380,27 +1512,13 @@ export function selfReviewJsonLine(results: readonly unknown[]): string {
1380
1512
  return JSON.stringify(results.length === 1 ? results[0] : results) + '\n';
1381
1513
  }
1382
1514
 
1383
- // Normalize only whole-item forms whose complete text is an explicit no-finding
1384
- // sentinel. Any extra clause stays in mustFix (fail-closed).
1385
- const NO_FINDING_REVIEW_NOTE_ALLOWLIST: readonly RegExp[] = [
1386
- /^(?:없음|해당\s*없음|none|nothing|n\/a)[.!。]?$/i,
1387
- /^\((?:없음|해당\s*없음|none|nothing|n\/a)\)[.!。]?$/i,
1388
- /^\(이 조각에서 확인된 코어 결함 없음\s*[—–-]\s*명시 intent 기준 mustFix 는 비움\)$/i,
1389
- /^\(이 조각에서 검증된 (?:차단 )?결함은 발견되지 않음(?:\s*\(mustFix \[\]\))?\)$/i,
1390
- ];
1391
-
1392
- function isNoFindingReviewNote(finding: string): boolean {
1393
- const wholeItem = finding.trim();
1394
- return NO_FINDING_REVIEW_NOTE_ALLOWLIST.some((form) => form.test(wholeItem));
1395
- }
1396
-
1397
1515
  function normalizeSavedReviewMustFix(result: Record<string, unknown>): { result: Record<string, unknown>; count: number } {
1398
1516
  if (!Array.isArray(result.mustFix)) return { result, count: 0 };
1399
1517
  const noFindingNotes = result.mustFix.filter((finding): finding is string =>
1400
- typeof finding === 'string' && isNoFindingReviewNote(finding));
1518
+ typeof finding === 'string' && isNoneSentinelFinding(finding));
1401
1519
  if (noFindingNotes.length === 0) return { result, count: 0 };
1402
1520
  const retained = result.mustFix.filter((finding) =>
1403
- typeof finding !== 'string' || !isNoFindingReviewNote(finding));
1521
+ typeof finding !== 'string' || !isNoneSentinelFinding(finding));
1404
1522
  const existingNotes = Array.isArray(result.noFindingNotes) ? result.noFindingNotes : [];
1405
1523
  return {
1406
1524
  result: { ...result, mustFix: retained, noFindingNotes: [...existingNotes, ...noFindingNotes] },
@@ -1415,6 +1533,103 @@ export async function runSelfReviewCliCommand(
1415
1533
  ): Promise<SelfReviewCliOutcome> {
1416
1534
  const pins: ReviewWorktree[] = [];
1417
1535
  try {
1536
+ // Resolve inside the leaf CLI seam so src/index.ts needs no mix-specific registration.
1537
+ const reviewerMix = opts.reviewerMix === undefined
1538
+ ? loadLlmPolicy().policy.roles.reviewerMix ?? getUserConfig().roleLlm?.reviewerMix ?? DEFAULT_REVIEWER_MIX
1539
+ : opts.reviewerMix;
1540
+ // The route is chosen outside the existing single-review pipeline so explicit CLI flags retain
1541
+ // their exact behavior. A failed reviewer is retried on the same pinned PR diff by the next lane.
1542
+ if (reviewerMix && (opts.save === undefined || /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(opts.save)) &&
1543
+ !opts.model?.trim() && !opts.acp && !opts.acpBackend && !opts.acpModel && !deps.envModel()) {
1544
+ const results: Array<Record<string, unknown>> = [];
1545
+ let failed = 0;
1546
+ for (const arg of prArgs) {
1547
+ const pr = normalizeReviewPrArg(arg, deps);
1548
+ const lanes = pr ? reviewLaneOrder(pr, reviewerMix) : [];
1549
+ if (!pr || lanes.length === 0) {
1550
+ const outcome = await runSelfReviewCliCommandPinned([arg], { ...opts, reviewerMix: undefined }, deps, pins);
1551
+ results.push(...outcome.results);
1552
+ failed += outcome.failed;
1553
+ continue;
1554
+ }
1555
+ const initialHead = prHeadCommit(pr, deps);
1556
+ if (initialHead.state !== 'known') {
1557
+ deps.log('review.lane-head-unknown', { pr, headState: initialHead.state }, { level: 'warn' });
1558
+ results.push({ pr, reviewed: false, refusal: 'reviewer-mix-head-unknown',
1559
+ failureReason: 'PR head could not be pinned before review', reviewerMixPrimaryLane: lanes[0] });
1560
+ failed += 1;
1561
+ continue;
1562
+ }
1563
+ let completed: Record<string, unknown> | undefined;
1564
+ let last: Record<string, unknown> | undefined;
1565
+ let completedLane: ReviewLane | undefined;
1566
+ let attemptedLane: ReviewLane | undefined;
1567
+ let completedWithError = false;
1568
+ const pinnedHead = initialHead.value;
1569
+ let capClaimed = false;
1570
+ let pendingFallback: { from: ReviewLane; reason: string } | undefined;
1571
+ for (const [index, lane] of lanes.entries()) {
1572
+ const observedHead = prHeadCommit(pr, deps);
1573
+ if (observedHead.state !== 'known' || observedHead.value !== pinnedHead) {
1574
+ last = { pr, reviewed: false, refusal: 'reviewer-mix-head-changed', stale: true,
1575
+ expectedHeadCommit: pinnedHead, headCommit: observedHead.value };
1576
+ deps.log('review.lane-head-changed', { pr, expectedHead: pinnedHead,
1577
+ observedHead: observedHead.value }, { level: 'warn' });
1578
+ break;
1579
+ }
1580
+ const laneOpts: SelfReviewCliOpts = {
1581
+ ...opts, reviewerMix: undefined, reviewerMixPrimaryLane: lanes[0], reviewerMixAttemptLane: lane,
1582
+ reviewerMixExpectedHead: pinnedHead, reviewerMixCapClaimed: capClaimed,
1583
+ disableClaudeGlmFallback: true, json: true,
1584
+ ...(lane === 'claude' ? { acp: true, acpBackend: 'claude', model: undefined } :
1585
+ { acp: false, acpBackend: undefined, model: lane === 'sol' ? 'gpt-6-sol' : ROLE_REVIEWER_FALLBACK_MODEL }),
1586
+ };
1587
+ let reviewerStarted = false;
1588
+ const laneDeps: SelfReviewCliDeps = { ...deps,
1589
+ reviewPullRequest: (input, llm) => { reviewerStarted = true; return deps.reviewPullRequest(input, llm); },
1590
+ observeDoctorReview: (event, data, options) => {
1591
+ if (event === 'cap-override') capClaimed = true;
1592
+ deps.observeDoctorReview?.(event, data, options);
1593
+ },
1594
+ };
1595
+ try {
1596
+ const outcome = await runSelfReviewCliCommandPinned([arg], laneOpts, laneDeps, pins);
1597
+ last = outcome.results[0];
1598
+ completedWithError = last?.reviewed === true && outcome.failed > 0;
1599
+ } catch (error) {
1600
+ last = { pr, reviewed: false, failureReason: safeLogText(error instanceof Error ? error.message : String(error), 400) };
1601
+ }
1602
+ if (last?.refusal === 'reviewer-mix-head-changed' || last?.refusal === 'cap-refused' || last?.stale === true) break;
1603
+ if (reviewerStarted) {
1604
+ attemptedLane = lane;
1605
+ deps.log('review.lane-chosen', { pr, lane, primaryLane: lanes[0], attempt: index + 1, weights: reviewerMix });
1606
+ }
1607
+ if (pendingFallback && reviewerStarted) {
1608
+ deps.log('review.lane-fallback', { pr, from: pendingFallback.from, to: lane,
1609
+ reason: pendingFallback.reason }, { level: 'warn' });
1610
+ pendingFallback = undefined;
1611
+ }
1612
+ if (last?.reviewed === true) {
1613
+ completed = last;
1614
+ completedLane = lane;
1615
+ break;
1616
+ }
1617
+ if (last?.refusal || last?.stale === true || index === lanes.length - 1) break;
1618
+ pendingFallback = { from: lane,
1619
+ reason: safeLogText(String(last?.failureReason ?? last?.error ?? 'reviewed=false'), 400) };
1620
+ }
1621
+ const result = completed ?? last;
1622
+ if (result) {
1623
+ const selectedLane = completedLane ?? attemptedLane;
1624
+ const enriched: Record<string, unknown> = { ...result, reviewerMixPrimaryLane: lanes[0],
1625
+ ...(selectedLane ? { reviewerMixSelectedLane: selectedLane } : {}) };
1626
+ results.push(enriched);
1627
+ if (!opts.json) deps.print(`\n━━ PR ${pr} (${String(enriched.model ?? 'review failed')}) ━━\n${deps.renderReview(enriched as unknown as ReviewResult)}`);
1628
+ }
1629
+ if (!completed || completedWithError) failed += 1;
1630
+ }
1631
+ return { results, failed };
1632
+ }
1418
1633
  return await runSelfReviewCliCommandPinned(prArgs, opts, deps, pins);
1419
1634
  } finally {
1420
1635
  for (const pin of pins) pin.remove();
@@ -1468,8 +1683,10 @@ async function runSelfReviewCliCommandPinned(
1468
1683
  deps.error(message);
1469
1684
  return { results: opts.json ? [{ error: message }] : [], failed: 1 };
1470
1685
  }
1471
- const automaticFallbacks = orderedAcpReviewFallbackBackends(opts.configuredAcpBackend,
1472
- opts.reviewDenyBackends === undefined ? configuredReviewDenyBackends : reviewDenyBackends);
1686
+ // 이 명령이 실제로 적용하는 금지 목록 — 자동 폴백 후보에서 빼는 데 쓰이고(종전과 같은 값),
1687
+ // 이제 착지 관문이 «실제로 판정을 낸 백엔드»를 대조하는 데에도 같은 값으로 쓰인다.
1688
+ const effectiveReviewDenyBackends: string[] = opts.reviewDenyBackends === undefined ? configuredReviewDenyBackends : reviewDenyBackends;
1689
+ const automaticFallbacks = orderedAcpReviewFallbackBackends(opts.configuredAcpBackend, effectiveReviewDenyBackends);
1473
1690
  const fallbackAcpBackends = opts.acpBackend
1474
1691
  ? [canonicalizeBackendId(opts.acpBackend)]
1475
1692
  : automaticFallbacks.backends;
@@ -1520,7 +1737,13 @@ async function runSelfReviewCliCommandPinned(
1520
1737
  const made = deps.makeRoleReviewerLlm
1521
1738
  ? deps.makeRoleReviewerLlm(opts.roleReviewer, { timeoutMs: acpTimeoutSec * 1000 })
1522
1739
  : { reason: 'role-reviewer-seam-missing' };
1523
- if ('llm' in made) roleReviewer = { llm: made.llm, model: `acp:${made.backend}` };
1740
+ // ⛔ 금지 목록(acp.reviewDenyBackends)은 «자동 폴백 후보»만이 아니라 **자동 선택 전부**를 막는다.
1741
+ // 역할 레인은 사람이 친 플래그가 아니라 설정이 고른 자동 선택이므로, 금지된 백엔드가 레인을
1742
+ // 잡으면 그 리뷰가 그대로 착지 근거가 됐다(fail-open). ⇒ 레인을 쓰지 않고 같은 사유 코드로
1743
+ // API 로 내려간다(`role-reviewer-fallback · stage=availability` 가 관측에 남는다).
1744
+ if ('llm' in made && deniedReviewBackend(made.backend, effectiveReviewDenyBackends)) {
1745
+ roleReviewerUnavailableReason = 'denied-by-acp.reviewDenyBackends';
1746
+ } else if ('llm' in made) roleReviewer = { llm: made.llm, model: `acp:${made.backend}` };
1524
1747
  else roleReviewerUnavailableReason = safeLogText(made.reason, 400);
1525
1748
  } catch (error) {
1526
1749
  roleReviewerUnavailableReason = roleAcpErrorReason(error);
@@ -1555,7 +1778,7 @@ async function runSelfReviewCliCommandPinned(
1555
1778
  if (previousRoundCount >= 5) {
1556
1779
  deps.observeDoctorReview?.('cap-attempt', { pr, previousRoundCount, round: previousRoundCount + 1, reasonProvided: Boolean(reason), opAllowed }, { level: 'warn' });
1557
1780
  }
1558
- if (previousRoundCount >= 5 && (!opAllowed || (!authorization && !reason))) {
1781
+ if (previousRoundCount >= 5 && (!opAllowed || (!authorization && !reason && !opts.reviewerMixCapClaimed))) {
1559
1782
  const refusalHead = prHeadCommit(pr, deps).value;
1560
1783
  const message = !opAllowed
1561
1784
  ? `PR ${pr}: r5 상한 초과 리뷰는 OP traffic.json reviewOverCapAllow 허용 목록에 있어야 합니다.`
@@ -1567,7 +1790,17 @@ async function runSelfReviewCliCommandPinned(
1567
1790
  continue;
1568
1791
  }
1569
1792
  const diffRead = readDiffAtHead(pr, deps);
1570
- if (previousRoundCount >= 5 && authorization && diffRead.headCommit.toLowerCase() === authorization.head) {
1793
+ if (opts.reviewerMixExpectedHead && diffRead.headCommit !== opts.reviewerMixExpectedHead) {
1794
+ const refusal = { pr, reviewed: false, verdict: null, mustFix: [], shouldFix: [],
1795
+ refusal: 'reviewer-mix-head-changed', stale: true, headCommit: diffRead.headCommit,
1796
+ expectedHeadCommit: opts.reviewerMixExpectedHead };
1797
+ deps.log('review.lane-head-changed', { pr, expectedHead: opts.reviewerMixExpectedHead,
1798
+ observedHead: diffRead.headCommit }, { level: 'warn' });
1799
+ if (opts.json || opts.save !== undefined) results.push(refusal);
1800
+ failed += 1;
1801
+ continue;
1802
+ }
1803
+ if (previousRoundCount >= 5 && authorization && diffRead.headCommit.toLowerCase() === authorization.head && !opts.reviewerMixCapClaimed) {
1571
1804
  const message = `PR ${pr}: 동일 head는 이미 승인 소모 기록이 있습니다.`;
1572
1805
  deps.observeDoctorReview?.('cap-refused', { pr, head: diffRead.headCommit, previousRoundCount, round: previousRoundCount + 1, reason: 'same-head-already-used' }, { level: 'warn' });
1573
1806
  deps.error(message);
@@ -1584,7 +1817,7 @@ async function runSelfReviewCliCommandPinned(
1584
1817
  continue;
1585
1818
  }
1586
1819
  let mergeOnlyDeltaRange: { base: string; head: string } | undefined;
1587
- if (previousRoundCount >= 5 && authorization) {
1820
+ if (previousRoundCount >= 5 && authorization && !opts.reviewerMixCapClaimed) {
1588
1821
  const git = deps.git;
1589
1822
  if (!git || diffRead.source !== 'sha-pinned' || diffRead.headCommitState !== 'known'
1590
1823
  || diffRead.currentHeadCommitState !== 'known' || diffRead.stale || diffRead.diff.status !== 0) {
@@ -1629,7 +1862,9 @@ async function runSelfReviewCliCommandPinned(
1629
1862
  }
1630
1863
  if (commits.stdout.trim() === '') mergeOnlyDeltaRange = { base: classificationBase, head: diffRead.headCommit.toLowerCase() };
1631
1864
  }
1632
- } else if (previousRoundCount >= 5 && reason) {
1865
+ } else if (previousRoundCount >= 5 && reason && !opts.reviewerMixCapClaimed) {
1866
+ // Claim only the exact SHA-pinned diff that the reviewer will see; never spend an OP
1867
+ // authorization on a separately read head that may move before readDiffAtHead.
1633
1868
  const claimable = diffRead.source === 'sha-pinned' && diffRead.headCommitState === 'known'
1634
1869
  && diffRead.currentHeadCommitState === 'known' && !diffRead.stale && diffRead.diff.status === 0;
1635
1870
  if (!claimable || !claimCapOverride(pr, diffRead.headCommit, reason, deps.now())) {
@@ -1654,13 +1889,16 @@ async function runSelfReviewCliCommandPinned(
1654
1889
  diffRead.diff = delta;
1655
1890
  diffRead.baseCommit = mergeOnlyDeltaRange.base;
1656
1891
  }
1657
- if (previousRoundCount >= 5 && authorization && !claimCapOverride(pr, diffRead.headCommit, authorization.reason, deps.now())) {
1892
+ if (previousRoundCount >= 5 && authorization && !opts.reviewerMixCapClaimed && !claimCapOverride(pr, diffRead.headCommit, authorization.reason, deps.now())) {
1658
1893
  const message = `PR ${pr}: 후속 head 승인 사용 기록을 남기지 못했습니다.`;
1659
1894
  deps.error(message);
1660
1895
  if (opts.json || opts.save !== undefined) results.push({ pr, error: message, reviewed: false, refusal: 'cap-refused', previousRoundCount, headCommit: diffRead.headCommit });
1661
1896
  failed += 1;
1662
1897
  continue;
1663
1898
  }
1899
+ if (previousRoundCount >= 5 && authorization && !opts.reviewerMixCapClaimed) {
1900
+ deps.observeDoctorReview?.('cap-override', { pr, head: diffRead.headCommit, previousRoundCount, round: previousRoundCount + 1, reason: authorization.reason }, { level: 'warn' });
1901
+ }
1664
1902
  const localHeadComparison = compareLocalHead(pr, { value: diffRead.headCommit, state: diffRead.headCommitState }, deps);
1665
1903
  const { diff } = diffRead;
1666
1904
  const baseReviewerContext = hasProvidedReviewerContext
@@ -1936,7 +2174,7 @@ async function runSelfReviewCliCommandPinned(
1936
2174
  // An explicit `--acp-model` is the operator's model choice: it is not silently swapped for GLM.
1937
2175
  // GLM that throws or also ends without a verdict keeps the claude result, and says so (`glmReviewed`).
1938
2176
  let claudeFallbackGlm: { reason: string; model: string; glmReviewed: boolean; glmFailureReason?: string } | undefined;
1939
- if (useAcp && !roleReview && !acpModel && canonicalizeBackendId(acpBackend) === 'claude' && review.reviewed !== true) {
2177
+ if (useAcp && !roleReview && !acpModel && !opts.disableClaudeGlmFallback && canonicalizeBackendId(acpBackend) === 'claude' && review.reviewed !== true) {
1940
2178
  const reason = safeLogText(review.failureReason || 'reviewed=false', 400);
1941
2179
  debug.log('review.acp', 'claude-fallback-glm', { reason }, { level: 'warn' });
1942
2180
  fallbackAttempted = true;
@@ -1967,6 +2205,50 @@ async function runSelfReviewCliCommandPinned(
1967
2205
  ...(reviewPin && reviewedOnPin ? { reviewCwdCommit: reviewPin.commit } : {}),
1968
2206
  ...(reviewCwdPinFallbackReason ? { reviewCwdPinFallbackReason } : {}),
1969
2207
  };
2208
+ // ⭐ 착지 관문 — 요청한 리뷰어와 실제로 판정을 낸 리뷰어를 대조한다. 판정이 나온 리뷰에만
2209
+ // 의미가 있다(리뷰가 없으면 근거도 없고, 실패는 기존 회계가 이미 센다).
2210
+ const acpActual = (backendText: string | undefined): LandingGateActual => {
2211
+ const backend = normalizedReviewBackend(backendText);
2212
+ return backend ? { kind: 'acp', value: `acp:${backend}`, backend } : { kind: 'unknown', value: 'unmeasured' };
2213
+ };
2214
+ const landingGateRequest: LandingGateRequest | undefined = requestedModel
2215
+ ? { kind: 'api-model', value: opts.model?.trim() || requestedModel, model: explicitApiModel ?? requestedModel }
2216
+ : useAcp
2217
+ ? { kind: 'acp-backend', value: `acp:${canonicalizeBackendId(acpBackend)}`, backend: acpBackend }
2218
+ : reviewerSource === 'role-config' && opts.roleReviewer
2219
+ ? { kind: 'role-lane', value: `acp:${opts.roleReviewer.provider}` }
2220
+ : undefined;
2221
+ const landingGateActual: LandingGateActual = reviewRoute === 'acp-fallback'
2222
+ ? acpActual(fallbackBackend)
2223
+ : reviewRoute === 'acp'
2224
+ ? acpActual(roleReview && prRoleReviewer ? prRoleReviewer.model.replace(/^acp:/, '') : acpBackend)
2225
+ : ((): LandingGateActual => {
2226
+ const apiModel = (selectedModel ?? '').trim();
2227
+ if (!apiModel) return { kind: 'unknown', value: 'unmeasured' };
2228
+ return {
2229
+ kind: 'api', value: `api:${apiModel}`, model: apiModel,
2230
+ ...(responded.provider ? { respondedProvider: responded.provider } : {}),
2231
+ ...(responded.model ? { respondedModel: responded.model } : {}),
2232
+ };
2233
+ })();
2234
+ const landingGate = review.reviewed === true
2235
+ ? landingGateOutcome({ pr, reviewRoute, request: landingGateRequest, actual: landingGateActual, deniedBackends: effectiveReviewDenyBackends })
2236
+ : undefined;
2237
+ if (landingGate && landingGate.state !== 'consistent') {
2238
+ deps.error(landingGate.warning);
2239
+ deps.log('landing-gate', {
2240
+ pr: safeLogText(pr), decision: landingGate.state, reviewRoute,
2241
+ requested: safeLogText(landingGate.requested), actual: safeLogText(landingGate.actual),
2242
+ ...(landingGate.state === 'denied' ? { deniedBackend: landingGate.deniedBackend } : {}),
2243
+ }, { level: 'warn' });
2244
+ }
2245
+ const landingGateAdmitted = landingGate?.state !== 'denied';
2246
+ const landingGateDeniedBackend = landingGate?.state === 'denied' ? landingGate.deniedBackend : undefined;
2247
+ const landingGateFields: Record<string, unknown> = landingGate?.state === 'mismatch'
2248
+ ? { landingGateDecision: 'mismatch', landingGateRequested: landingGate.requested, landingGateActual: landingGate.actual }
2249
+ : landingGate?.state === 'denied'
2250
+ ? { landingGateDecision: 'denied', landingGateRequested: landingGate.requested, landingGateActual: landingGate.actual, landingGateDeniedBackend: landingGate.deniedBackend }
2251
+ : {};
1970
2252
  if (!fallbackAttempted) {
1971
2253
  fallbackNotAttemptedReason = useAcp ? 'explicit-acp' : requestedModel && review.reviewed !== true ? 'explicit-model' : 'primary-review-succeeded';
1972
2254
  }
@@ -1991,7 +2273,27 @@ async function runSelfReviewCliCommandPinned(
1991
2273
  const reviewerSelection = {
1992
2274
  ...reviewerSourceObservation(),
1993
2275
  ...(roleReviewerFallbackReason !== undefined ? { roleReviewerFallbackReason } : {}),
2276
+ ...(opts.reviewerMixPrimaryLane ? { reviewerMixPrimaryLane: opts.reviewerMixPrimaryLane,
2277
+ reviewerMixSelectedLane: opts.reviewerMixAttemptLane } : {}),
1994
2278
  };
2279
+ // The reviewer owns its finding severity. A missing citation is separate evidence,
2280
+ // never a new must-fix or a verified defect. Keep unreadable heads distinct too.
2281
+ const reviewRepositoryPath = deps.reviewRepositoryPath;
2282
+ const findingPathHeadChecks = review.reviewed === true && landingGateAdmitted
2283
+ && diffRead.headCommitState === 'known' && reviewRepositoryPath
2284
+ ? ([...review.mustFix.map(finding => ({ severity: 'mustFix' as const, finding })),
2285
+ ...review.shouldFix.map(finding => ({ severity: 'shouldFix' as const, finding }))]
2286
+ .map(({ severity, finding }) => ({ severity, finding,
2287
+ ...checkCitedReviewPathsAtHead(finding, reviewRepositoryPath, diffRead.headCommit) }))
2288
+ .filter(check => check.paths.length > 0))
2289
+ : [];
2290
+ const pathWarnings = findingPathHeadChecks.flatMap(check => check.paths
2291
+ .filter(path => path.status !== 'present')
2292
+ .map(path => `${path.status === 'missing' ? '경로 미확인' : '경로 검증 불가'}: ${path.path} (PR head ${check.head})`));
2293
+ if (pathWarnings.length) deps.log('finding-path-head-check', {
2294
+ pr, headCommit: diffRead.headCommit, missing: findingPathHeadChecks.flatMap(check => check.paths).filter(path => path.status === 'missing').length,
2295
+ unreadable: findingPathHeadChecks.flatMap(check => check.paths).filter(path => path.status === 'unreadable').length,
2296
+ }, { level: 'warn' });
1995
2297
  // ⚠️ verdict=fail 은 **정상 동작**(리뷰가 일한 것)이라 warn 으로 올리지 않는다. 대신 `reviewed:false`
1996
2298
  // (fail-soft pass·리뷰 미실행)는 조용히 통과로 읽히면 위험하므로 warn 이다.
1997
2299
  deps.log('done',
@@ -2011,6 +2313,7 @@ async function runSelfReviewCliCommandPinned(
2011
2313
  acceptanceChars: goalAcceptance.acceptanceChars,
2012
2314
  ...reviewerSelection,
2013
2315
  ...reviewCwdOutput,
2316
+ ...landingGateFields,
2014
2317
  },
2015
2318
  { level: review.reviewed === false ? 'warn' : 'info' });
2016
2319
  // --acp 는 대표가 명시 요청한 리뷰 — fail-soft(reviewed=false)면 조용히 pass 하지 말고 표면화(관측=acp-review).
@@ -2024,12 +2327,21 @@ async function runSelfReviewCliCommandPinned(
2024
2327
  }
2025
2328
  const contextOutput = reviewerContextOutput(reviewerContext, decompositionContext);
2026
2329
  const jsonReview = review.reviewed === true ? review : { ...review, verdict: null };
2027
- if (opts.json || opts.save !== undefined) results.push({ pr, model: selectedModel, ...jsonReview, ...reviewProvenance, ...respondedOutput, ...reviewerSelection, ...reviewCwdOutput, ...provenance, ...contextOutput, evidence: evidence.evidence, prDiffFiles: evidence.prDiffFiles, ...(evidence.authoredFiles !== undefined ? { authoredFiles: evidence.authoredFiles } : {}) });
2028
- if (!opts.json) deps.print(`\n━━ PR ${pr} (${selectedModel}) ━━\n${renderProvenance(diffRead)}\n${evidenceLine}\n${reviewerContextStatus}\n${deps.renderReview(review)}`);
2330
+ // ⛔ 금지 백엔드가 낸 판정은 «근거 거부»다 — verdict·mustFix 를 그대로 실어 보내면 읽는 쪽이
2331
+ // 그것을 착지 판정으로 쓴다(관문도 reviewed===true 를 근거 조건으로 본다).
2332
+ const refusalOverride = landingGateAdmitted ? {} : { reviewed: false, verdict: null, refusal: 'review-forbidden-acp-backend' as const };
2333
+ if (opts.json || opts.save !== undefined) results.push({ pr, model: selectedModel, ...jsonReview, ...reviewProvenance, ...respondedOutput, ...reviewerSelection, ...reviewCwdOutput, ...provenance, ...contextOutput, ...refusalOverride, ...landingGateFields, findingPathHeadChecks, pathWarnings, evidence: evidence.evidence, prDiffFiles: evidence.prDiffFiles, ...(evidence.authoredFiles !== undefined ? { authoredFiles: evidence.authoredFiles } : {}) });
2334
+ if (!opts.json) {
2335
+ if (!landingGateAdmitted) deps.print(`\n━━ PR ${pr} (${selectedModel}) ━━\n${renderProvenance(diffRead)}\n⛔ LANDING GATE: review-forbidden-acp-backend (${landingGateDeniedBackend ?? 'unknown'}) — 이 리뷰는 착지 근거가 아닙니다.\n${reviewerContextStatus}`);
2336
+ else deps.print(`\n━━ PR ${pr} (${selectedModel}) ━━\n${renderProvenance(diffRead)}\n${evidenceLine}\n${reviewerContextStatus}\n${deps.renderReview(review)}${pathWarnings.length ? `\n${pathWarnings.join('\n')}` : ''}`);
2337
+ }
2029
2338
  // REVIEW-ERROR-RC — 기본(API)·role 경로가 1차·폴백 모두 실패해 reviewed≠true 로 끝나도 «못 리뷰한 PR» 이다(verdict:null).
2030
- if (review.reviewed !== true) failed += 1;
2339
+ // ⛔ 착지 관문 거부도 같은 회계다 — 금지 백엔드가 판정을 냈으면 리뷰가 «성공»해도 근거가 아니다(rc≠0).
2340
+ if (review.reviewed !== true || !landingGateAdmitted) failed += 1;
2031
2341
  if (opts.save !== undefined) {
2032
- if (review.reviewed !== true || diffRead.headCommitState !== 'known' || diffRead.currentHeadCommitState !== 'known' || diffRead.currentHeadCommit !== diffRead.headCommit || diffRead.headCommit.length !== 40) {
2342
+ if (!landingGateAdmitted) {
2343
+ deps.error(`PR ${pr}: --save 거부 — acp.reviewDenyBackends 가 금지한 백엔드(${landingGateDeniedBackend ?? 'unknown'})의 결과는 착지 근거로 저장하지 않습니다.`);
2344
+ } else if (review.reviewed !== true || diffRead.headCommitState !== 'known' || diffRead.currentHeadCommitState !== 'known' || diffRead.currentHeadCommit !== diffRead.headCommit || diffRead.headCommit.length !== 40) {
2033
2345
  deps.error(`PR ${pr}: --save 불가 — 완료된 리뷰와 확인된 40자 PR head가 필요합니다.`);
2034
2346
  if (review.reviewed === true) failed += 1;
2035
2347
  } else {
@@ -30,7 +30,7 @@ export function harnessRunsToLineage(entries: readonly RunLedgerTimelineEntry[])
30
30
  store: 'observation' as const,
31
31
  at: entry.executedAt,
32
32
  seq: entry.pieceIndex,
33
- summary: `self-implement run ${entry.runId}${entry.orchestrationId ? ` · orchestration ${entry.orchestrationId}` : ''}${entry.shardId ? ` · shard ${entry.shardId}` : ''}${entry.pieceTotal !== undefined ? ` · ${entry.pieceTotal} pieces` : ''}`,
33
+ summary: `self-implement run ${entry.runId}${entry.orchestrationId ? ` · orchestration ${entry.orchestrationId}` : ''}${entry.shardId ? ` · shard ${entry.shardId}` : ''}${entry.pieceTotal !== undefined ? ` · ${entry.pieceTotal} pieces` : ''}${entry.unitVisits?.orphanCount ? ` · graph.unit orphan ${entry.unitVisits.orphanCount}` : ''}`,
34
34
  }));
35
35
  }
36
36