elanous 0.2.37 → 0.2.40

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 (727) 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/{8kITumG9GAZ1LwT9POrAR → HjeK7zONHfR7op1hKXp4k}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{1746.3563617ea64023a3.js → 1060.014f1f01a17aec26.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{9151.a2c51e93f9156dae.js → 1281.d81877e35b9068f4.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/1350.59f40e39e02d91b1.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1452.162bb2d9d699e82a.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +286 -0
  10. package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +149 -0
  12. package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +90 -0
  14. package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +104 -0
  15. package/apps/pwa/out/_next/static/chunks/{3578.4e9f9948a9a6f2f4.js → 2047.8f23e210995d4548.js} +2 -2
  16. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{7424.c0fe2a595d4232b5.js → 2066.a77257c8c350770a.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{4931.95cc6dbd230774ca.js → 2177.df8547f9d7215c4e.js} +16 -16
  20. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{6680.6a693c28aae4cd19.js → 2226.2cf61ec781827219.js} +2 -2
  22. package/apps/pwa/out/_next/static/chunks/2281-b8cede695c6c650e.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2499.02fbfd18126c10c0.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{6252.240578f10952e091.js → 2522.f2766b76d22c8bdf.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/{1262.a89bb27a5b2f844e.js → 2566.beaffc3a5e1fcd2e.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/261.0d471e8aded799f3.js +226 -0
  27. package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +27 -0
  30. package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{2318-450e75d07605b8fe.js → 2774-719820e3f5b2a3eb.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/{4725-34bed25720cc326b.js → 2829-734fe8bf2eee7347.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3330.7443183b7e6fdbdf.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3746-f80a78f220bf37b5.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +24 -0
  45. package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +77 -0
  46. package/apps/pwa/out/_next/static/chunks/{4337e36d.f42c3b391b3d8f20.js → 3b355b3d.6f73c98bf6f9c749.js} +1 -1
  47. package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +36 -0
  48. package/apps/pwa/out/_next/static/chunks/{58edce7d.f1b0c72acf13b123.js → 409c787b.e48c5bec8ec10456.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +287 -0
  52. package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4351.0f37a6db2b34d50b.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{5046.7fd5cbd859299448.js → 470.51a72a2348306455.js} +2 -2
  56. package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/{2375.bf364c85dbb6f085.js → 4769.9fd582071301f382.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{de8446d3.31b73eb239fecd7b.js → 4864a2ca.1c1c280a7772c5e5.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +74 -0
  63. package/apps/pwa/out/_next/static/chunks/{4383.18e5c54db3a22c88.js → 5383.bdfa5d886e39a826.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/5436.fdf6fa8ae3e9588d.js +64 -0
  65. package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5622.94893f5aea7185d0.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +8 -0
  70. package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +62 -0
  72. package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +94 -0
  76. package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{6745-5a63492933959dd9.js → 6051-0ae955eedb10adb9.js} +3 -3
  78. package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/{2283.edd9627b7bdfb546.js → 6257.c0037b8949239f5e.js} +2 -2
  80. package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/6624.981ef7caeb680560.js +32 -0
  85. package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/{6819.be5c9c4d67f22922.js → 6749.0744ce6eb08d40e9.js} +16 -16
  87. package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +148 -0
  90. package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/6cc1d1d6.9a98dd4622f1afc6.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +93 -0
  96. package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7515.1ad6efe157fa4448.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +24 -0
  100. package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8086.1ab9103c41be884f.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{2002-a43a3f380df873ec.js → 8272-025653884f9645d2.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{7867.e8725745ddd1d940.js → 8357.1aaa713b052a78b1.js} +4 -4
  110. package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9069.657590a84afb8fac.js +41 -0
  115. package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{4313.76f232c304a15bde.js → 9175.2de5209a5ce6f68a.js} +1 -1
  117. package/apps/pwa/out/_next/static/chunks/9184.45afbf44fec87574.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{8c58d09b.e8724a299658d86f.js → 9189505a.980427ac048c8c60.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9992.07ce73c10bd5e6a1.js +79 -0
  123. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ba957ff875a026a0.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live/{page-3337c6a1328c2674.js → page-4edb8df90f4537ce.js} +1 -1
  143. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/morning/{page-1e5da297557d2354.js → page-fca2e59a81744d9e.js} +1 -1
  148. package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/term/{page-ac2c1e6169cfce57.js → page-139d722de1dcd6c1.js} +1 -1
  167. package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workspace/{page-c1c80e345fa9d6f5.js → page-ccde99f07aaf71f7.js} +1 -1
  173. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{d9815f84.4918f682a45a8502.js → b84cad00.594027ebe0531fe2.js} +3 -3
  175. package/apps/pwa/out/_next/static/chunks/c696986b.5dc8bb1143af16d1.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/{709a918c.4fd3b4e2a32cb4e3.js → ca3702f8.2913182e73889fa2.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/{5f6af561-f90b7a67f4f75d13.js → d8de0de2-dd0f4ac8e5ab1832.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +22 -22
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +22 -22
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +22 -22
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +21 -21
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +21 -21
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +22 -22
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +21 -21
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +22 -22
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +22 -22
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +21 -21
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +22 -22
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +22 -22
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +22 -22
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +22 -22
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +21 -21
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +21 -21
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +22 -22
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +22 -22
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +22 -22
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +21 -21
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +21 -21
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +22 -22
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +22 -22
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +21 -21
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +21 -21
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +21 -21
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +22 -22
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +22 -22
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +21 -21
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +22 -22
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +22 -22
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +22 -22
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +22 -22
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +22 -22
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +21 -21
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +22 -22
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +22 -22
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +22 -22
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +22 -22
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +22 -22
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +22 -22
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +22 -22
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +22 -22
  278. package/graphs/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
  279. package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
  280. package/graphs/demo/persona-marketer/recipes.yaml +19 -0
  281. package/graphs/release/recipes.yaml +9 -0
  282. package/graphs/release/release-loop.yaml +26 -18
  283. package/graphs/video/explainer-line.yaml +4 -1
  284. package/package.json +1 -1
  285. package/scripts/ask-op-inbox-once.ts +17 -0
  286. package/scripts/brand/check.ts +13 -4
  287. package/scripts/dead-code/report.ts +169 -0
  288. package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
  289. package/scripts/gate-0226-failure-census.ts +39 -0
  290. package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
  291. package/scripts/lib/morning-report-options.ts +3 -4
  292. package/scripts/lib/tui-regress-evidence.ts +56 -0
  293. package/scripts/morning-report.ts +5 -1
  294. package/scripts/provision-export-redactions.ts +15 -0
  295. package/scripts/public-copy-lint.ts +122 -0
  296. package/scripts/public-export.ts +77 -2
  297. package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
  298. package/scripts/ratchets/train-side-invariants.sh +7 -1
  299. package/scripts/release-loop/cut-branch.ts +61 -12
  300. package/scripts/release-loop/export-check-node.ts +21 -3
  301. package/scripts/release-loop/gate-node.ts +527 -60
  302. package/scripts/release-loop/gate-partial.ts +82 -3
  303. package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
  304. package/scripts/release-loop/gate-radius-live.ts +4 -2
  305. package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
  306. package/scripts/release-loop/gate-shard-receipts.ts +89 -0
  307. package/scripts/release-loop/gate-wall.ts +5 -5
  308. package/scripts/release-loop/preflight.ts +6 -2
  309. package/scripts/release-loop/resume-cap.ts +2 -1
  310. package/scripts/release-loop/resume-release.ts +317 -13
  311. package/scripts/release-loop/resume.ts +61 -5
  312. package/scripts/release-loop/traffic-node.ts +12 -4
  313. package/scripts/release-loop/traffic-transition.ts +53 -13
  314. package/scripts/release-loop/version-node.ts +35 -5
  315. package/scripts/release-story/draft.ts +1 -1
  316. package/scripts/research-bench/README.md +53 -0
  317. package/scripts/research-bench/questions.json +66 -0
  318. package/scripts/research-bench/rubric.md +33 -0
  319. package/scripts/research-bench/run.ts +523 -0
  320. package/scripts/tui-regress.ts +85 -10
  321. package/scripts/ux-sim.ts +1 -1
  322. package/scripts/video-pipeline.ts +2 -2
  323. package/src/acp/core-turn-bridge.ts +14 -1
  324. package/src/agent/autonomous-tools.ts +10 -3
  325. package/src/agent/monad-agent-turn.ts +4 -1
  326. package/src/agent/registry.ts +26 -2
  327. package/src/agent/run-context.ts +1 -1
  328. package/src/agent/shared-app-tools.ts +1 -1
  329. package/src/agent/surface-ux/build.ts +12 -3
  330. package/src/agent/surface-ux/types.ts +1 -1
  331. package/src/agent/task-notification.ts +78 -7
  332. package/src/agent/types.ts +3 -0
  333. package/src/agent-mission/driver.ts +29 -3
  334. package/src/agent-mission/mission-cli.ts +2 -1
  335. package/src/agent-substrate/review-context-pack.ts +365 -0
  336. package/src/agent-substrate/review-observation.ts +10 -0
  337. package/src/agent-substrate/self-review-cli.ts +419 -42
  338. package/src/ask-user-question/index.ts +6 -0
  339. package/src/ask-user-question/inline-resolver.ts +49 -0
  340. package/src/auto-research/question-ladder-contract.ts +156 -0
  341. package/src/auto-research/research-turn.ts +467 -0
  342. package/src/autopilot/agent-loop.ts +1 -1
  343. package/src/autopilot/discovery/doc-lint.ts +1 -1
  344. package/src/autopilot/pty-control-loop.ts +8 -1
  345. package/src/boot/daemon-tools/index.ts +4 -3
  346. package/src/boot/daemon-tools/self-implement.ts +270 -2
  347. package/src/boot/daemon-tools/types.ts +2 -0
  348. package/src/bots/screen-probe.ts +1 -1
  349. package/src/budget/llm-cost.ts +44 -5
  350. package/src/budget/unified-usage.ts +17 -1
  351. package/src/capture/tui-self-report.ts +24 -2
  352. package/src/chat/index.ts +34 -7
  353. package/src/chat/tool-render/dispatch.ts +8 -1
  354. package/src/cli/agent-cli.ts +43 -8
  355. package/src/cli/guardian-cli.ts +3 -1
  356. package/src/cli/intake-cli.ts +70 -13
  357. package/src/cli/lesson-cli.ts +86 -10
  358. package/src/cli/log-event-names.ts +1 -0
  359. package/src/cli/pod-cli.ts +17 -2
  360. package/src/cli/pr-land-overlap-evidence.ts +38 -5
  361. package/src/cli/pr-land-refusal.ts +1 -1
  362. package/src/cli/pty-takeover-cli.ts +125 -12
  363. package/src/cli/release-checklist-read-cli.ts +5 -2
  364. package/src/cli/release-cli.ts +99 -15
  365. package/src/cli/repo-cli.ts +2 -1
  366. package/src/cli/review-carry.ts +77 -0
  367. package/src/cli/self-update.ts +1 -1
  368. package/src/cli/tasks-card-show.ts +31 -1
  369. package/src/cli/tasks-cli.ts +98 -32
  370. package/src/cli/tasks-read-cli.ts +13 -5
  371. package/src/context-bus/context-now.ts +86 -2
  372. package/src/control-plane/ledger.ts +21 -4
  373. package/src/core-turn/run-core-turn.ts +51 -3
  374. package/src/core-turn/run-goal-loop.ts +152 -8
  375. package/src/core-turn/types.ts +12 -0
  376. package/src/dashboard/chat/acp-chat.ts +2 -2
  377. package/src/dashboard/classic-sigquit.ts +16 -0
  378. package/src/dashboard/index.ts +339 -44
  379. package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
  380. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
  381. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  382. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  383. package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
  384. package/src/dashboard/input/external-input-host.ts +2 -0
  385. package/src/dashboard/input/terminal-modal-router.ts +8 -159
  386. package/src/dashboard/side-basic-runtime.ts +61 -0
  387. package/src/dashboard/sidetab-runtime.ts +228 -0
  388. package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
  389. package/src/dashboard/slash-runtime/dashboard-handlers.ts +22 -8
  390. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
  391. package/src/dashboard/term-slash-runtime.ts +18 -18
  392. package/src/dashboard/turn-preamble.ts +30 -4
  393. package/src/domains/guardian-tick.ts +9 -0
  394. package/src/domains/knowledge.ts +1 -1
  395. package/src/esc-abort-gate.ts +33 -1
  396. package/src/execution-loop/launch-gate.ts +206 -1
  397. package/src/git-fs/watcher.ts +27 -22
  398. package/src/git-fs/worktree.ts +19 -3
  399. package/src/graph-runner/graph-cli.ts +6 -4
  400. package/src/graph-runner/graph-grow.ts +37 -9
  401. package/src/graph-runner/runner.ts +48 -11
  402. package/src/graph-wizard/generate.ts +16 -7
  403. package/src/graph-wizard/mission-compose.ts +201 -0
  404. package/src/grok/agent-search.ts +8 -2
  405. package/src/grok/credential.ts +112 -36
  406. package/src/grounding/ref-index.ts +11 -0
  407. package/src/grounding/ref-vector.ts +61 -0
  408. package/src/grounding/sources-cli.ts +2 -2
  409. package/src/grounding/sources.ts +15 -1
  410. package/src/harness/harness-cli-command.ts +38 -9
  411. package/src/harness/harness-pod-dispatch.ts +7 -1
  412. package/src/hq/fence-wrapper.ts +1 -1
  413. package/src/hq/transfer.ts +1 -1
  414. package/src/index.ts +60 -16
  415. package/src/input/external-input-queue.ts +10 -0
  416. package/src/intake-plane/collect-telegram-saved.ts +90 -6
  417. package/src/intake-plane/intake-to-tasks.ts +246 -3
  418. package/src/interactive-terminal-modal.ts +3 -0
  419. package/src/keybindings.ts +17 -22
  420. package/src/lessons/friction-ledger.ts +154 -0
  421. package/src/live-supply/collector.ts +149 -0
  422. package/src/live-supply/probes.ts +52 -0
  423. package/src/live-supply/snapshot.ts +40 -0
  424. package/src/llm/provider-credentials.ts +1 -1
  425. package/src/llm-tool-schema.ts +20 -0
  426. package/src/llm.ts +486 -61
  427. package/src/loops/orchestrator/inbox-once.ts +28 -0
  428. package/src/loops/orchestrator/inbox.ts +130 -1
  429. package/src/loops/orchestrator/tick.ts +14 -3
  430. package/src/maturity/feature-maturity.ts +1 -0
  431. package/src/nexus/api/channel-ask-op.ts +96 -0
  432. package/src/nexus/api/discord-trigger-bot.ts +28 -1
  433. package/src/nexus/api/harness-api.ts +2 -1
  434. package/src/nexus/api/telegram-trigger-bot.ts +24 -0
  435. package/src/nexus/api/terminals.ts +28 -6
  436. package/src/patents/ledger.ts +18 -1
  437. package/src/preview/terminal.ts +4 -2
  438. package/src/prompt-cache/anthropic.ts +2 -0
  439. package/src/prompt-enhance/enhance.ts +5 -0
  440. package/src/pty/snapshot.py +132 -0
  441. package/src/pty-shell/pty-control-ipc.ts +29 -2
  442. package/src/pty-shell/pty-manifest.ts +75 -5
  443. package/src/pty-shell/registry.ts +2 -0
  444. package/src/pty-shell/tui-run-state.ts +80 -3
  445. package/src/release-loop/gate-host-reservation.ts +13 -4
  446. package/src/release-loop/gate-shard-ledger.ts +68 -0
  447. package/src/release-loop/gate-shards.ts +61 -0
  448. package/src/release-loop/light-rc.ts +7 -4
  449. package/src/release-loop/merged-pr-checklist.ts +25 -2
  450. package/src/release-loop/rehearsal-shard-plan.ts +6 -1
  451. package/src/release-loop/rehearsal.ts +28 -1
  452. package/src/repl/index.ts +10 -0
  453. package/src/research/axis-fanout.ts +133 -0
  454. package/src/research/edge-decision.ts +197 -0
  455. package/src/research/gap-followup.ts +249 -0
  456. package/src/research/lenses/counter-evidence.ts +100 -0
  457. package/src/research/lenses/working-backwards.ts +89 -0
  458. package/src/research/output-router.ts +127 -0
  459. package/src/research/plugin-discovery.ts +242 -0
  460. package/src/research-bridge/format.ts +16 -1
  461. package/src/research-bridge/index.ts +1 -0
  462. package/src/research-bridge/invoke.ts +45 -7
  463. package/src/research-bridge/types.ts +2 -0
  464. package/src/self-dev/ask-launch-flow.ts +34 -106
  465. package/src/self-dev/decompose.ts +45 -9
  466. package/src/self-dev/dev-cli.ts +2 -0
  467. package/src/self-dev/dev-pipeline.ts +8 -4
  468. package/src/self-dev/draft-residue.ts +221 -2
  469. package/src/self-dev/draft-sweep.ts +29 -16
  470. package/src/self-dev/graph-journey-route.ts +10 -2
  471. package/src/self-dev/launch-preflight-text.ts +2 -2
  472. package/src/self-dev/launch-preflight.ts +38 -7
  473. package/src/self-dev/orchestrate-cli.ts +1 -0
  474. package/src/self-dev/orchestrate.ts +1 -0
  475. package/src/self-dev/run-supervisor.ts +41 -7
  476. package/src/self-dev/shard-run.ts +260 -3
  477. package/src/self-implement/comment-only-source.ts +54 -0
  478. package/src/self-implement/device-first.ts +8 -2
  479. package/src/self-implement/doctor-visit.ts +100 -57
  480. package/src/self-implement/gate-artifacts.ts +5 -2
  481. package/src/self-implement/gate-baseline.ts +119 -13
  482. package/src/self-implement/gate-cli.ts +466 -93
  483. package/src/self-implement/gate-failure-signature.ts +44 -0
  484. package/src/self-implement/gate-receipt-registry.ts +180 -0
  485. package/src/self-implement/gate-remote.ts +147 -22
  486. package/src/self-implement/goal-author-clarification.ts +178 -24
  487. package/src/self-implement/goal-author-decompose.ts +24 -15
  488. package/src/self-implement/goal-author.ts +82 -7
  489. package/src/self-implement/goal-doc/section.ts +22 -0
  490. package/src/self-implement/goal-supervisor-fill.ts +38 -4
  491. package/src/self-implement/host-regate.ts +120 -45
  492. package/src/self-implement/impl-findings-feedback.ts +188 -0
  493. package/src/self-implement/knowhow-pack.ts +301 -9
  494. package/src/self-implement/l8-merge-queue.ts +198 -32
  495. package/src/self-implement/off-diff-evidence.ts +147 -0
  496. package/src/self-implement/orchestrator.ts +137 -16
  497. package/src/self-implement/pod-inplace-worktree.ts +82 -0
  498. package/src/self-implement/pod-warm-pool-profile.ts +2 -2
  499. package/src/self-implement/premise-review.ts +7 -5
  500. package/src/self-implement/run-ledger.ts +304 -8
  501. package/src/self-implement/run-stop.ts +12 -0
  502. package/src/self-implement/seams.ts +39 -13
  503. package/src/self-implement/self-implement-cli.ts +30 -4
  504. package/src/session/channel-ask-op-envelope.ts +36 -0
  505. package/src/session/channel-op-reply-route.ts +200 -0
  506. package/src/session/chat.ts +92 -15
  507. package/src/session/index.ts +2 -0
  508. package/src/session-runtime/index.ts +9 -22
  509. package/src/session-runtime/provider-circuit.ts +140 -0
  510. package/src/shell-runner/file-engine.ts +1 -0
  511. package/src/shell-runner/types.ts +4 -0
  512. package/src/sidetab-core/model.ts +176 -0
  513. package/src/skills/runner.ts +7 -3
  514. package/src/skills/tools/dev-harness.ts +2 -2
  515. package/src/skills/tools/schedule-wakeup.ts +24 -7
  516. package/src/skills/tools/shell.ts +51 -5
  517. package/src/status/bar.ts +3 -3
  518. package/src/steward/directive-audit.ts +354 -0
  519. package/src/storage/file-lock.ts +17 -4
  520. package/src/surface/child-process.ts +31 -0
  521. package/src/surface/tui-stderr-owner.ts +48 -0
  522. package/src/task-agent/adopt-pr.ts +63 -2
  523. package/src/task-agent/cover.ts +30 -12
  524. package/src/task-agent/evidence-command-normalize.ts +42 -0
  525. package/src/task-agent/export-redactions-provision.ts +43 -0
  526. package/src/task-agent/judge.ts +56 -0
  527. package/src/task-agent/parent-host.ts +59 -12
  528. package/src/task-agent/postland-card.ts +35 -2
  529. package/src/task-agent/rejudge-on-head.ts +46 -2
  530. package/src/task-agent/repair-cycle.ts +68 -9
  531. package/src/task-agent/repair-worker.ts +37 -1
  532. package/src/task-agent/task-hand.ts +226 -33
  533. package/src/task-agent/tier-split.ts +142 -24
  534. package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
  535. package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
  536. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +57 -5
  537. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
  538. package/src/task-orchestrator/surfaces/pod-pool.ts +27 -4
  539. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
  540. package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
  541. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
  542. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
  543. package/src/task-orchestrator/surfaces/self-implement-pod.ts +310 -79
  544. package/src/task-orchestrator/surfaces/self-implement.ts +33 -2
  545. package/src/terminal/session-registry.ts +1 -0
  546. package/src/terminal/terminal-modal-router.ts +156 -0
  547. package/src/tool-hints/gate.ts +6 -4
  548. package/src/tool-hints/signals.ts +33 -1
  549. package/src/tool-runtime/skill-exec-runtime.ts +95 -5
  550. package/src/tui/chat/background-job-status.ts +8 -2
  551. package/src/tui/entry.ts +483 -32
  552. package/src/tui/inline-choice.ts +188 -0
  553. package/src/tui/sidetab/attach.ts +304 -0
  554. package/src/tui/sidetab/list.ts +2 -0
  555. package/src/tui/sidetab/nl-tool.ts +136 -0
  556. package/src/tui/slash/resume-command.ts +23 -0
  557. package/src/tui/slash/resume.ts +3 -23
  558. package/src/tui/slash/term-next.ts +2 -1
  559. package/src/tui/slash/term.ts +12 -1
  560. package/src/tui-client/dashboard-session.ts +7 -1
  561. package/src/tui-client/local-chat-turn.ts +29 -8
  562. package/src/user-config.ts +42 -3
  563. package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
  564. package/src/ux-sim/fake-land-queue.ts +88 -0
  565. package/src/ux-sim/fake-llm.ts +11 -5
  566. package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
  567. package/src/ux-sim/goal-interim-trace.ts +24 -0
  568. package/src/ux-sim/next-tui-seat-scenarios.ts +61 -14
  569. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
  570. package/src/version/packed-revision.json +1 -1
  571. package/src/video-pipeline/recipes/explainer.ts +54 -2
  572. package/src/web-search/grok.ts +32 -6
  573. package/src/web-search/index.ts +8 -7
  574. package/src/workflow-runtime/node-catalog.ts +53 -4
  575. package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/1224.2ceca6c180d5130b.js +0 -62
  579. package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/1ed5e8af.cf424815c7c0efad.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/210.90b2cbd64926cf34.js +0 -32
  587. package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/2479-fe7e188bd9402d14.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +0 -148
  590. package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +0 -27
  594. package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/3199.6a1a9b0e6cd01dc6.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +0 -36
  601. package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/4036.d54e55e1ebf5acdc.js +0 -90
  603. package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +0 -226
  604. package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +0 -287
  605. package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/4324.c99ba3e83eb1b691.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/4833-7934c592c5569f00.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +0 -24
  612. package/apps/pwa/out/_next/static/chunks/4937-28d437999b77c9dd.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +0 -104
  615. package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +0 -93
  622. package/apps/pwa/out/_next/static/chunks/5952.294fc574a8625184.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +0 -74
  624. package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +0 -149
  627. package/apps/pwa/out/_next/static/chunks/6877-84d47b7e85d0c41e.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/6971-fb5f9dc0a2cb5d2d.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +0 -41
  631. package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +0 -24
  634. package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/757-4fbaf50942b8c424.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/7893-e444a1b0809cd1e4.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/7c5ed21f-f286708e57cf88f7.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +0 -8
  647. package/apps/pwa/out/_next/static/chunks/8080-40d781e7704d3671.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +0 -77
  649. package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +0 -286
  652. package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +0 -79
  656. package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/9175-7d383df15a82e2be.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +0 -94
  664. package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/958.53a8dcf4729e6997.js +0 -64
  666. package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/intake/page-5c112c6d7c33656e.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/live-run/page-89acd5d68c0bc560.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-fe986fe79b107546.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-88a1edbff62eaf1d.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/outputs/page-443364c9e4a23b31.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/page-b9af2ac1c4737ce8.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/share/page-fb9e639c107f5f72.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.js +0 -1
  725. package/scripts/migrate-monad-to-elanous.ts +0 -195
  726. package/scripts/rebrand-elanous.ts +0 -242
  727. /package/apps/pwa/out/_next/static/{8kITumG9GAZ1LwT9POrAR → HjeK7zONHfR7op1hKXp4k}/_ssgManifest.js +0 -0
@@ -14,13 +14,13 @@
14
14
  //
15
15
  // index.ts 의 액션은 옵션 파싱과 실제 의존 배선만 남는다(얇은 껍데기).
16
16
 
17
- import { mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
17
+ import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
18
18
  import { homedir, tmpdir } from 'node:os';
19
19
  import { dirname, join } from 'node:path';
20
20
  import { effectiveInstanceRoot } from '../instance/resolve.js';
21
21
  import { tierModel } from '../llm/model-defaults.js';
22
- import { buildReviewObservation, safeLogText } from './review-observation.js';
23
- import { checkCitedReviewPathsAtHead } from './review-finding-key.js';
22
+ import { buildReviewObservation, reviewIntentFingerprint, safeLogText } from './review-observation.js';
23
+ import { checkCitedReviewPathsAtHead, citedReviewPaths } from './review-finding-key.js';
24
24
  import { DEFAULT_REVIEW_BACKEND, defaultAcpReviewTimeoutSec } from './acp-reviewer.js';
25
25
  import { ZAI_OPENROUTER_FALLBACK_MODEL } from '../llm/zai-coding-plan.js';
26
26
  import { debug } from '../debug/log.js';
@@ -89,9 +89,13 @@ export interface SelfReviewCliOpts {
89
89
  context?: string[] | undefined;
90
90
  contextText?: string[] | undefined;
91
91
  contextOrder?: Array<{ kind: 'file' | 'text'; value: string }> | undefined;
92
+ /** Skip the default repository-grounded review context pack. */
93
+ noContextPack?: boolean | undefined;
92
94
  json?: boolean | undefined;
93
95
  /** Save completed reviews under the task-agent state's review-results directory. */
94
96
  save?: string | undefined;
97
+ /** Review only commits after a previously saved PR review head. */
98
+ sinceReview?: string | undefined;
95
99
  /** One invocation past r5, only for a PR in OP's traffic.json allowlist; the reason is recorded before review starts. */
96
100
  overCapReason?: string | undefined;
97
101
  }
@@ -171,37 +175,187 @@ export interface SelfReviewCliOutcome {
171
175
  failed: number;
172
176
  }
173
177
 
174
- /** Saved results are round evidence only when their PR, exact head and reviewed status agree. */
175
- function savedReviewRecords(pr: string, root = effectiveInstanceRoot()): Array<{ head: string; reviewedAt: number }> {
178
+ interface SavedReviewEvidence {
179
+ heads: string[];
180
+ records: Array<{ head: string; reviewedAt: number }>;
181
+ unreadableFiles: string[];
182
+ }
183
+
184
+ interface SavedReviewForDelta {
185
+ file: string;
186
+ headCommit: string;
187
+ mustFix: string[];
188
+ reviewInputChars: number;
189
+ reviewDurationMs: number;
190
+ }
191
+
192
+ function selectSavedReviewForDelta(pr: string, selector: string, root = effectiveInstanceRoot()):
193
+ | { review: SavedReviewForDelta }
194
+ | { error: string } {
176
195
  const dir = join(root, 'review-results');
177
196
  let names: string[];
178
- try { names = readdirSync(dir); } catch { return []; }
179
- // Manual review saves in the operating house also use head10; the JSON's full head is authoritative.
180
- const matching = new RegExp(`^.+-${pr}-([a-f0-9]{7,40})\\.json$`, 'i');
181
- const records = new Map<string, { head: string; reviewedAt: number }>();
197
+ try { names = readdirSync(dir); } catch { return { error: 'saved-review-directory-missing' }; }
198
+ const token = selector.trim();
199
+ if (!token) return { error: 'saved-review-selector-empty' };
200
+ const records: Array<SavedReviewForDelta & { mtimeMs: number }> = [];
182
201
  for (const name of names) {
183
- const match = matching.exec(name);
202
+ if (!name.toLowerCase().endsWith('.json')) continue;
203
+ let raw: unknown;
204
+ try { raw = JSON.parse(readFileSync(join(dir, name), 'utf8')); } catch { continue; }
205
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) continue;
206
+ const row = raw as Record<string, unknown>;
207
+ const recordPr = typeof row.pr === 'string' ? row.pr
208
+ : Number.isSafeInteger(row.pr) ? String(row.pr) : undefined;
209
+ if (recordPr !== pr || row.reviewed !== true || typeof row.headCommit !== 'string' || !COMMIT_OID.test(row.headCommit)) continue;
210
+ const named = name === token || name === `${token}.json` || name.startsWith(`${token}-${pr}-`);
211
+ const byHead = /^[a-f0-9]{7,64}$/i.test(token) && row.headCommit.toLowerCase().startsWith(token.toLowerCase());
212
+ if (!named && !byHead) continue;
213
+ if (!Array.isArray(row.mustFix) || !row.mustFix.every((item) => typeof item === 'string')) continue;
214
+ if (typeof row.reviewInputChars !== 'number' || !Number.isFinite(row.reviewInputChars) || row.reviewInputChars <= 0
215
+ || typeof row.reviewDurationMs !== 'number' || !Number.isFinite(row.reviewDurationMs) || row.reviewDurationMs <= 0) continue;
216
+ let mtimeMs = 0;
217
+ try { mtimeMs = statSync(join(dir, name)).mtimeMs; } catch { continue; }
218
+ records.push({ file: name, headCommit: row.headCommit.toLowerCase(), mustFix: row.mustFix as string[],
219
+ reviewInputChars: row.reviewInputChars, reviewDurationMs: row.reviewDurationMs, mtimeMs });
220
+ }
221
+ const distinctHeads = [...new Set(records.map((record) => record.headCommit))];
222
+ if (distinctHeads.length > 1) return { error: 'saved-review-selector-ambiguous' };
223
+ const selected = records.sort((a, b) => b.mtimeMs - a.mtimeMs)[0];
224
+ return selected ? { review: selected } : { error: 'saved-review-not-found-or-missing-efficiency-receipt' };
225
+ }
226
+
227
+ function reviewInputCharacterCount(input: ReviewInput): number {
228
+ return input.prDiff.length + input.phaseIntent.length + (input.acceptance?.length ?? 0)
229
+ + (input.evidenceNote?.length ?? 0)
230
+ + (input.workingMemory?.length ?? 0)
231
+ + (input.reviewerContext ?? []).reduce((sum, item) => sum + item.label.length + item.body.length, 0);
232
+ }
233
+
234
+ function readDeltaDiffAtHead(pr: string, base: string, deps: SelfReviewCliDeps):
235
+ | { read: DiffRead }
236
+ | { error: string; headCommit?: string } {
237
+ if (!COMMIT_OID.test(base)) return { error: 'saved-review-head-malformed' };
238
+ const before = prHeadCommit(pr, deps);
239
+ if (before.state !== 'known') return { error: 'current-pr-head-unavailable' };
240
+ if (before.value.toLowerCase() === base.toLowerCase()) return { error: 'no-new-head-since-review', headCommit: before.value };
241
+ const { repo } = prCompareAnchors(pr, deps);
242
+ if (!repo) return { error: 'pr-repository-unavailable', headCommit: before.value };
243
+ const comparePath = `repos/${repo}/compare/${base}...${before.value}`;
244
+ const comparison = deps.gh(['api', comparePath], 25_000);
245
+ if (comparison.status !== 0) return { error: 'saved-review-head-not-ancestor', headCommit: before.value };
246
+ try {
247
+ const parsed = JSON.parse(comparison.stdout) as { status?: unknown; merge_base_commit?: { sha?: unknown } };
248
+ if (parsed.status !== 'ahead' || typeof parsed.merge_base_commit?.sha !== 'string'
249
+ || parsed.merge_base_commit.sha.toLowerCase() !== base.toLowerCase()) {
250
+ return { error: 'saved-review-head-not-ancestor', headCommit: before.value };
251
+ }
252
+ } catch { return { error: 'compare-response-invalid', headCommit: before.value }; }
253
+ const diff = deps.gh(['api', comparePath, '-H', 'Accept: application/vnd.github.diff'], 25_000);
254
+ if (diff.status !== 0 || !diff.stdout.trim()) return { error: 'delta-diff-unavailable', headCommit: before.value };
255
+ const after = prHeadCommit(pr, deps);
256
+ if (after.state !== 'known' || after.value !== before.value) return { error: 'current-pr-head-moved', headCommit: before.value };
257
+ return { read: { diff, headCommit: before.value, headCommitState: 'known', currentHeadCommit: after.value,
258
+ currentHeadCommitState: 'known', stale: false, refetched: false, source: 'sha-pinned', baseCommit: base.toLowerCase() } };
259
+ }
260
+
261
+ function deltaReviewIntent(base: SavedReviewForDelta): string {
262
+ const findings = base.mustFix.length
263
+ ? base.mustFix.map((finding, index) => `${index + 1}. ${finding}`).join('\n')
264
+ : '(직전 mustFix 없음 — 새 정확성·안전·데이터 손실 문제만 확인)';
265
+ return [
266
+ 'DELTA REVIEW — 직전 저장 리뷰와 현재 head 사이의 변경만 판정한다.',
267
+ '직전 mustFix 각각을 REQUIREMENTS 항목에 `DELTA-FINDING <번호>: FIXED|OPEN` 형식으로 정확히 한 번 기록한다. OPEN에는 짧은 근거를 덧붙인다.',
268
+ '새 MUST-FIX는 현재 delta가 만든 정확성·안전·데이터 손실 문제만 허용하며, 각 항목은 `[NEW-CORRECTNESS]`, `[NEW-SAFETY]`, `[NEW-DATA-LOSS]` 중 하나로 시작한다.',
269
+ '새 SHOULD-FIX나 스타일·범위 확장 지적은 만들지 않는다. 직전 findings를 다시 리뷰 전체로 확장하지 않는다.',
270
+ '직전 mustFix:', findings,
271
+ ].join('\n\n');
272
+ }
273
+
274
+ function assessDeltaReview(review: ReviewResult, previous: SavedReviewForDelta):
275
+ | { valid: true; mustFix: string[]; deltaFindings: Array<{ finding: string; status: 'fixed' | 'open' }>; excludedNewFindings: number }
276
+ | { valid: false; reason: string } {
277
+ const statuses = new Map<number, 'fixed' | 'open'>();
278
+ for (const item of review.requirements ?? []) {
279
+ const match = /^DELTA-FINDING\s+(\d+):\s*(FIXED|OPEN)(?:\s+—.*)?$/i.exec(item.trim());
184
280
  if (!match) continue;
281
+ const index = Number(match[1]);
282
+ if (index < 1 || index > previous.mustFix.length || statuses.has(index)) return { valid: false, reason: 'delta-assessment-invalid' };
283
+ statuses.set(index, match[2]!.toLowerCase() as 'fixed' | 'open');
284
+ }
285
+ if (statuses.size !== previous.mustFix.length) return { valid: false, reason: 'delta-assessment-incomplete' };
286
+ const deltaFindings = previous.mustFix.map((finding, index) => ({ finding, status: statuses.get(index + 1)! }));
287
+ const openFindings = deltaFindings.filter((item) => item.status === 'open').map((item) => item.finding);
288
+ const allowedPrefix = /^\[(?:NEW-CORRECTNESS|NEW-SAFETY|NEW-DATA-LOSS)\]\s*/i;
289
+ const newFindings = review.mustFix.filter((finding) => allowedPrefix.test(finding)).map((finding) => finding.replace(allowedPrefix, ''));
290
+ const excludedNewFindings = review.mustFix.length - newFindings.length;
291
+ return { valid: true, mustFix: [...openFindings, ...newFindings], deltaFindings, excludedNewFindings };
292
+ }
293
+
294
+ function savedReviewEvidence(
295
+ pr: string,
296
+ root = effectiveInstanceRoot(),
297
+ onUnreadable?: (file: string) => void,
298
+ ): SavedReviewEvidence {
299
+ const dir = join(root, 'review-results');
300
+ let names: string[];
301
+ try { names = readdirSync(dir); } catch { return { heads: [], records: [], unreadableFiles: [] }; }
302
+ const escapedPr = pr.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
303
+ const matchingPrInName = new RegExp(`(?:^|-)${escapedPr}(?:-|\\.json$)`, 'i');
304
+ const records = new Map<string, { head: string; reviewedAt: number }>();
305
+ const unreadableFiles: string[] = [];
306
+ for (const name of names) {
307
+ if (!name.toLowerCase().endsWith('.json')) continue;
308
+ const nameSuggestsPr = matchingPrInName.test(name);
185
309
  try {
186
- const recordPath = join(dir, name);
187
- const raw: unknown = JSON.parse(readFileSync(recordPath, 'utf8'));
188
- if (!raw || typeof raw !== 'object' || Array.isArray(raw)) continue;
310
+ const raw: unknown = JSON.parse(readFileSync(join(dir, name), 'utf8'));
311
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
312
+ if (nameSuggestsPr) { unreadableFiles.push(name); onUnreadable?.(name); }
313
+ continue;
314
+ }
189
315
  const result = raw as Record<string, unknown>;
316
+ const recordPr = typeof result.pr === 'string' ? result.pr
317
+ : Number.isSafeInteger(result.pr) ? String(result.pr) : undefined;
318
+ if (recordPr !== pr) {
319
+ // A parseable, explicit foreign PR identity outranks a misleading filename.
320
+ if (recordPr === undefined && nameSuggestsPr) { unreadableFiles.push(name); onUnreadable?.(name); }
321
+ continue;
322
+ }
323
+ if (result.reviewed !== true) continue;
190
324
  const head = result.headCommit;
191
- if (String(result.pr) !== pr || result.reviewed !== true || typeof head !== 'string'
192
- || !COMMIT_OID.test(head) || !head.toLowerCase().startsWith(match[1]!.toLowerCase())) continue;
193
- const normalized = head.toLowerCase();
194
- const existing = records.get(normalized);
325
+ if (typeof head !== 'string' || !COMMIT_OID.test(head)) {
326
+ unreadableFiles.push(name);
327
+ onUnreadable?.(name);
328
+ continue;
329
+ }
330
+ // The result payload is authoritative: round-tagged filenames and stale suffixes
331
+ // still count by their full PR/head identity, then deduplicate on that identity.
332
+ const recordPath = join(dir, name);
195
333
  const reviewedAt = typeof result.reviewedAt === 'number' && Number.isFinite(result.reviewedAt)
196
334
  ? result.reviewedAt : statSync(recordPath).mtimeMs;
335
+ const normalized = head.toLowerCase();
336
+ const existing = records.get(normalized);
197
337
  if (!existing || reviewedAt > existing.reviewedAt) records.set(normalized, { head: normalized, reviewedAt });
198
- } catch { /* corrupt or partial result is not a completed round */ }
338
+ } catch {
339
+ // A filename can associate an unreadable record with this PR; fail closed at the cap.
340
+ if (nameSuggestsPr) { unreadableFiles.push(name); onUnreadable?.(name); }
341
+ }
199
342
  }
200
- return [...records.values()];
343
+ const saved = [...records.values()];
344
+ return { heads: saved.map(({ head }) => head), records: saved, unreadableFiles };
201
345
  }
202
346
 
203
347
  export function savedReviewHeads(pr: string, root = effectiveInstanceRoot()): string[] {
204
- return savedReviewRecords(pr, root).map(({ head }) => head);
348
+ return savedReviewEvidence(pr, root).heads;
349
+ }
350
+
351
+ function isReplaceableErrorArtifact(path: string, pr: string, head: string): boolean {
352
+ try {
353
+ const result = JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>;
354
+ const recordPr = typeof result.pr === 'string' ? result.pr
355
+ : Number.isSafeInteger(result.pr) ? String(result.pr) : undefined;
356
+ return recordPr === pr && result.headCommit === head && result.reviewed === false
357
+ && typeof result.error === 'string' && result.error.length > 0;
358
+ } catch { return false; }
205
359
  }
206
360
 
207
361
  function normalizeReviewPrArg(input: string, deps: SelfReviewCliDeps): string | null {
@@ -742,7 +896,7 @@ interface AuthoredEvidence {
742
896
  /** 리뷰 증거로 쓸 diff. */
743
897
  diff: string;
744
898
  /** 좁혔나. `full` = 종전 three-dot 그대로. */
745
- evidence: 'full' | 'authored-only';
899
+ evidence: 'full' | 'authored-only' | 'saved-review-delta';
746
900
  prDiffFiles: number;
747
901
  /** 좁힌 뒤 파일 수. 안 좁혔으면 **잰 적 없음**을 뜻하는 undefined 가 아니라, 잰 경우에만 채운다. */
748
902
  authoredFiles?: number;
@@ -1539,7 +1693,7 @@ export async function runSelfReviewCliCommand(
1539
1693
  : opts.reviewerMix;
1540
1694
  // The route is chosen outside the existing single-review pipeline so explicit CLI flags retain
1541
1695
  // 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)) &&
1696
+ if (!opts.sinceReview && reviewerMix && (opts.save === undefined || /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(opts.save)) &&
1543
1697
  !opts.model?.trim() && !opts.acp && !opts.acpBackend && !opts.acpModel && !deps.envModel()) {
1544
1698
  const results: Array<Record<string, unknown>> = [];
1545
1699
  let failed = 0;
@@ -1566,6 +1720,17 @@ export async function runSelfReviewCliCommand(
1566
1720
  let attemptedLane: ReviewLane | undefined;
1567
1721
  let completedWithError = false;
1568
1722
  const pinnedHead = initialHead.value;
1723
+ const priorEvidence = savedReviewEvidence(pr);
1724
+ const capWasActive = priorEvidence.heads.length + priorEvidence.unreadableFiles.length >= 5;
1725
+ const canonicalResultPath = join(effectiveInstanceRoot(), 'review-results', `pr-${pr}-${pinnedHead.slice(0, 12)}.json`);
1726
+ if (capWasActive && existsSync(canonicalResultPath)
1727
+ && !isReplaceableErrorArtifact(canonicalResultPath, pr, pinnedHead)) {
1728
+ const message = `PR ${pr}: 동일 head 리뷰 결과가 이미 저장되어 있습니다: ${canonicalResultPath}`;
1729
+ results.push({ pr, reviewed: false, refusal: 'cap-refused', existingResult: canonicalResultPath, headCommit: pinnedHead });
1730
+ deps.error(message);
1731
+ failed += 1;
1732
+ continue;
1733
+ }
1569
1734
  let capClaimed = false;
1570
1735
  let pendingFallback: { from: ReviewLane; reason: string } | undefined;
1571
1736
  for (const [index, lane] of lanes.entries()) {
@@ -1624,6 +1789,33 @@ export async function runSelfReviewCliCommand(
1624
1789
  const enriched: Record<string, unknown> = { ...result, reviewerMixPrimaryLane: lanes[0],
1625
1790
  ...(selectedLane ? { reviewerMixSelectedLane: selectedLane } : {}) };
1626
1791
  results.push(enriched);
1792
+ if (completed && completed.reviewed === true) {
1793
+ try {
1794
+ mkdirSync(dirname(canonicalResultPath), { recursive: true });
1795
+ const normalized = normalizeSavedReviewMustFix(enriched);
1796
+ if (enriched.headCommit !== pinnedHead || enriched.stale === true
1797
+ || enriched.currentHeadCommit !== pinnedHead) {
1798
+ throw new Error('review result is not pinned to the confirmed current PR head');
1799
+ }
1800
+ writeFileSync(canonicalResultPath, selfReviewJsonLine([normalized.result]));
1801
+ } catch (error) {
1802
+ failed += 1;
1803
+ deps.error(`PR ${pr}: 리뷰 결과 저장 실패 (${canonicalResultPath}): ${error instanceof Error ? error.message : String(error)}`);
1804
+ if (capWasActive) {
1805
+ const authorization = readCapOverride(pr);
1806
+ const claimPath = authorization?.head === pinnedHead.toLowerCase()
1807
+ ? join(effectiveInstanceRoot(), 'review-results', `cap-override-${pr}.json`)
1808
+ : join(effectiveInstanceRoot(), 'review-results', `cap-override-${pr}-head-${pinnedHead.toLowerCase()}.json`);
1809
+ try { unlinkSync(claimPath); } catch { /* already absent or owned by another lane */ }
1810
+ }
1811
+ }
1812
+ } else if (capWasActive && !completed && capClaimed) {
1813
+ const authorization = readCapOverride(pr);
1814
+ const claimPath = authorization?.head === pinnedHead.toLowerCase()
1815
+ ? join(effectiveInstanceRoot(), 'review-results', `cap-override-${pr}.json`)
1816
+ : join(effectiveInstanceRoot(), 'review-results', `cap-override-${pr}-head-${pinnedHead.toLowerCase()}.json`);
1817
+ try { unlinkSync(claimPath); } catch { /* already absent or owned by another lane */ }
1818
+ }
1627
1819
  if (!opts.json) deps.print(`\n━━ PR ${pr} (${String(enriched.model ?? 'review failed')}) ━━\n${deps.renderReview(enriched as unknown as ReviewResult)}`);
1628
1820
  }
1629
1821
  if (!completed || completedWithError) failed += 1;
@@ -1662,6 +1854,11 @@ async function runSelfReviewCliCommandPinned(
1662
1854
  deps.error('--save 이름은 영문자·숫자로 시작하고 영문자·숫자·점·밑줄·하이픈만 포함해야 합니다.');
1663
1855
  return { results: [], failed: 1 };
1664
1856
  }
1857
+ if (opts.sinceReview && ((opts.contextOrder?.length ?? 0) > 0 || (opts.context?.length ?? 0) > 0 || (opts.contextText?.length ?? 0) > 0)) {
1858
+ const message = '--since-review 는 직전 지적에 인용된 파일만 맥락으로 싣습니다; --context/--context-text 와 함께 쓸 수 없습니다.';
1859
+ deps.error(message);
1860
+ return { results: opts.json ? [{ error: message, reviewed: false, refusal: 'delta-context-expansion' }] : [], failed: 1 };
1861
+ }
1665
1862
 
1666
1863
  // An explicit API model is the caller's reviewer choice even when a default ACP lane supplied both flags.
1667
1864
  const requestedModel = opts.model?.trim() || undefined;
@@ -1769,8 +1966,12 @@ async function runSelfReviewCliCommandPinned(
1769
1966
  const providedReviewerContext = loadReviewerContext(opts, deps.readReferencedFile);
1770
1967
  const hasProvidedReviewerContext = (opts.contextOrder?.length ?? 0) > 0 || (opts.context?.length ?? 0) > 0 || (opts.contextText?.length ?? 0) > 0;
1771
1968
  for (const pr of normalizedPrArgs as string[]) {
1772
- const previousHeads = savedReviewHeads(pr);
1773
- const previousRoundCount = previousHeads.length;
1969
+ const savedEvidence = savedReviewEvidence(pr, undefined, (file) => {
1970
+ deps.observeDoctorReview?.('saved-result-unreadable', { pr, file }, { level: 'warn' });
1971
+ });
1972
+ const previousHeads = savedEvidence.heads;
1973
+ const previousRoundCount = previousHeads.length + savedEvidence.unreadableFiles.length;
1974
+ const shouldPersistCapResult = previousRoundCount >= 5 && !opts.reviewerMixPrimaryLane;
1774
1975
  const reason = opts.overCapReason?.trim();
1775
1976
  const authorization = previousRoundCount >= 5 ? readCapOverride(pr) : undefined;
1776
1977
  deps.observeDoctorReview?.('round-counted', { pr, previousRoundCount, round: previousRoundCount + 1 });
@@ -1789,7 +1990,49 @@ async function runSelfReviewCliCommandPinned(
1789
1990
  failed += 1;
1790
1991
  continue;
1791
1992
  }
1792
- const diffRead = readDiffAtHead(pr, deps);
1993
+ let deltaBase: SavedReviewForDelta | undefined;
1994
+ if (opts.sinceReview !== undefined) {
1995
+ const selected = selectSavedReviewForDelta(pr, opts.sinceReview);
1996
+ if ('error' in selected) {
1997
+ const message = `PR ${pr}: --since-review 기준을 읽지 못했습니다 (${selected.error}).`;
1998
+ deps.error(message);
1999
+ if (opts.json || opts.save !== undefined) results.push({ pr, error: message, reviewed: false, refusal: 'delta-base-invalid', deltaRefusal: selected.error });
2000
+ failed += 1;
2001
+ continue;
2002
+ }
2003
+ deltaBase = selected.review;
2004
+ }
2005
+ const diffResult = deltaBase ? readDeltaDiffAtHead(pr, deltaBase.headCommit, deps) : { read: readDiffAtHead(pr, deps) };
2006
+ if ('error' in diffResult) {
2007
+ const message = `PR ${pr}: 델타 리뷰를 고정하지 못했습니다 (${diffResult.error}).`;
2008
+ deps.error(message);
2009
+ if (opts.json || opts.save !== undefined) results.push({ pr, error: message, reviewed: false, refusal: 'delta-base-invalid', deltaRefusal: diffResult.error,
2010
+ ...(diffResult.headCommit ? { headCommit: diffResult.headCommit } : {}) });
2011
+ failed += 1;
2012
+ continue;
2013
+ }
2014
+ const diffRead = diffResult.read;
2015
+ const canonicalResultPath = COMMIT_OID.test(diffRead.headCommit)
2016
+ ? join(effectiveInstanceRoot(), 'review-results', `pr-${pr}-${diffRead.headCommit.slice(0, 12)}.json`)
2017
+ : undefined;
2018
+ let claimedCapPath: string | undefined;
2019
+ const releaseCapClaim = (): void => {
2020
+ if (!claimedCapPath || opts.reviewerMixPrimaryLane) return;
2021
+ try {
2022
+ unlinkSync(claimedCapPath);
2023
+ claimedCapPath = undefined;
2024
+ } catch (error) {
2025
+ deps.error(`PR ${pr}: 상한 예외 사용 기록 롤백 실패 (${claimedCapPath}): ${error instanceof Error ? error.message : String(error)}`);
2026
+ }
2027
+ };
2028
+ if (shouldPersistCapResult && canonicalResultPath && existsSync(canonicalResultPath)
2029
+ && !isReplaceableErrorArtifact(canonicalResultPath, pr, diffRead.headCommit)) {
2030
+ const message = `PR ${pr}: 동일 head 리뷰 결과가 이미 저장되어 있습니다: ${canonicalResultPath}`;
2031
+ deps.error(message);
2032
+ results.push({ pr, error: message, reviewed: false, refusal: 'cap-refused', previousRoundCount, headCommit: diffRead.headCommit, existingResult: canonicalResultPath });
2033
+ failed += 1;
2034
+ continue;
2035
+ }
1793
2036
  if (opts.reviewerMixExpectedHead && diffRead.headCommit !== opts.reviewerMixExpectedHead) {
1794
2037
  const refusal = { pr, reviewed: false, verdict: null, mustFix: [], shouldFix: [],
1795
2038
  refusal: 'reviewer-mix-head-changed', stale: true, headCommit: diffRead.headCommit,
@@ -1801,10 +2044,13 @@ async function runSelfReviewCliCommandPinned(
1801
2044
  continue;
1802
2045
  }
1803
2046
  if (previousRoundCount >= 5 && authorization && diffRead.headCommit.toLowerCase() === authorization.head && !opts.reviewerMixCapClaimed) {
1804
- const message = `PR ${pr}: 동일 head는 이미 승인 소모 기록이 있습니다.`;
2047
+ const resultExists = canonicalResultPath && existsSync(canonicalResultPath);
2048
+ const message = resultExists
2049
+ ? `PR ${pr}: 동일 head 리뷰 결과가 이미 저장되어 있습니다: ${canonicalResultPath}`
2050
+ : `PR ${pr}: 동일 head는 이미 승인 소모 기록이 있습니다. 결과 파일을 찾을 수 없어 재리뷰하지 않습니다.`;
1805
2051
  deps.observeDoctorReview?.('cap-refused', { pr, head: diffRead.headCommit, previousRoundCount, round: previousRoundCount + 1, reason: 'same-head-already-used' }, { level: 'warn' });
1806
2052
  deps.error(message);
1807
- if (opts.json || opts.save !== undefined) results.push({ pr, error: message, reviewed: false, refusal: 'cap-refused', previousRoundCount, headCommit: diffRead.headCommit });
2053
+ if (opts.json || opts.save !== undefined || resultExists) results.push({ pr, error: message, reviewed: false, refusal: 'cap-refused', previousRoundCount, headCommit: diffRead.headCommit, ...(resultExists ? { existingResult: canonicalResultPath } : {}) });
1808
2054
  failed += 1;
1809
2055
  continue;
1810
2056
  }
@@ -1827,7 +2073,7 @@ async function runSelfReviewCliCommandPinned(
1827
2073
  failed += 1;
1828
2074
  continue;
1829
2075
  }
1830
- const savedRecords = savedReviewRecords(pr);
2076
+ const savedRecords = savedEvidence.records;
1831
2077
  const latestReviewed = savedRecords.reduce<(typeof savedRecords)[number] | undefined>(
1832
2078
  (latest, record) => !latest || record.reviewedAt > latest.reviewedAt ? record : latest, undefined,
1833
2079
  );
@@ -1875,6 +2121,9 @@ async function runSelfReviewCliCommandPinned(
1875
2121
  failed += 1;
1876
2122
  continue;
1877
2123
  }
2124
+ claimedCapPath = join(effectiveInstanceRoot(), 'review-results', authorization
2125
+ ? `cap-override-${pr}-head-${diffRead.headCommit.toLowerCase()}.json`
2126
+ : `cap-override-${pr}.json`);
1878
2127
  deps.observeDoctorReview?.('cap-override', { pr, head: diffRead.headCommit, previousRoundCount, round: previousRoundCount + 1, reason }, { level: 'warn' });
1879
2128
  }
1880
2129
  if (mergeOnlyDeltaRange) {
@@ -1883,6 +2132,7 @@ async function runSelfReviewCliCommandPinned(
1883
2132
  const message = `PR ${pr}: merge-only 후속 head의 delta diff를 고정할 수 없습니다.`;
1884
2133
  deps.error(message);
1885
2134
  if (opts.json || opts.save !== undefined) results.push({ pr, error: message, reviewed: false, refusal: 'cap-refused', previousRoundCount, headCommit: diffRead.headCommit });
2135
+ releaseCapClaim();
1886
2136
  failed += 1;
1887
2137
  continue;
1888
2138
  }
@@ -1897,32 +2147,58 @@ async function runSelfReviewCliCommandPinned(
1897
2147
  continue;
1898
2148
  }
1899
2149
  if (previousRoundCount >= 5 && authorization && !opts.reviewerMixCapClaimed) {
2150
+ claimedCapPath = join(effectiveInstanceRoot(), 'review-results', `cap-override-${pr}-head-${diffRead.headCommit.toLowerCase()}.json`);
1900
2151
  deps.observeDoctorReview?.('cap-override', { pr, head: diffRead.headCommit, previousRoundCount, round: previousRoundCount + 1, reason: authorization.reason }, { level: 'warn' });
1901
2152
  }
1902
2153
  const localHeadComparison = compareLocalHead(pr, { value: diffRead.headCommit, state: diffRead.headCommitState }, deps);
1903
2154
  const { diff } = diffRead;
1904
- const baseReviewerContext = hasProvidedReviewerContext
1905
- ? providedReviewerContext
1906
- : loadPrDiffReviewerContext(pr, diffRead.headCommit, diffFilePaths(diff.stdout), deps);
2155
+ const deltaContextPaths = deltaBase ? [...new Set(deltaBase.mustFix.flatMap(citedReviewPaths))] : undefined;
2156
+ const baseReviewerContext = deltaBase
2157
+ ? loadPrDiffReviewerContext(pr, diffRead.headCommit, deltaContextPaths ?? [], deps)
2158
+ : hasProvidedReviewerContext
2159
+ ? providedReviewerContext
2160
+ : loadPrDiffReviewerContext(pr, diffRead.headCommit, diffFilePaths(diff.stdout), deps);
1907
2161
  const comparisonData = comparisonObservation(localHeadComparison);
1908
2162
  // ⛔ `relation-unknown` 도 경고한다(위 주석 · 리뷰가 두 라운드 반복 지적) — 그 밖 unavailable 은 조용하다.
1909
2163
  // ⭐ 경고 여부 판정은 `localHeadWarningDetails` 한 곳에 있다(호출부에서 같은 함수를 두 번 부르지 않는다).
1910
2164
  const mismatchWarning = localHeadWarningDetails(localHeadComparison);
1911
2165
  const mergeState = readPrMergeState(pr, deps);
1912
- const view = deps.gh(['pr', 'view', pr, '--json', 'title,body'], 15_000);
2166
+ const view = deltaBase ? { status: 1, stdout: '', stderr: '' }
2167
+ : deps.gh(['pr', 'view', pr, '--json', 'title,body'], 15_000);
1913
2168
  let prView: { title?: string; body?: string } | undefined;
1914
2169
  if (view.status === 0) {
1915
2170
  try { prView = JSON.parse(view.stdout) as { title?: string; body?: string }; } catch { /* fallback below */ }
1916
2171
  }
1917
2172
  const title = prView?.title ?? '';
1918
2173
  const body = prView?.body;
1919
- const decompositionContext = lookupDecompositionContextForReview(`${title}\n${body ?? ''}`, deps);
1920
- const reviewerContext = appendDecompositionContext(baseReviewerContext, decompositionContext);
2174
+ const decompositionContext = deltaBase ? { status: 'absent' as const }
2175
+ : lookupDecompositionContextForReview(`${title}\n${body ?? ''}`, deps);
2176
+ const pack = deltaBase || opts.noContextPack ? undefined : await import('./review-context-pack.js').then(({ buildReviewContextPack }) => buildReviewContextPack({
2177
+ pr,
2178
+ prTitle: title,
2179
+ prBody: body ?? '',
2180
+ files: diffFilePaths(diff.stdout),
2181
+ rootDir: deps.reviewRepositoryPath,
2182
+ gh: (args) => {
2183
+ const result = deps.gh([...args], 15_000);
2184
+ return result.status === 0
2185
+ ? { ok: true, stdout: result.stdout }
2186
+ : { ok: false, stdout: result.stdout, error: result.stderr || `gh exited ${String(result.status)}` };
2187
+ },
2188
+ }));
2189
+ const contextWithPack = pack
2190
+ ? { ...baseReviewerContext, items: [...baseReviewerContext.items, { label: 'review context pack', body: pack.text }] }
2191
+ : baseReviewerContext;
2192
+ const reviewerContext = appendDecompositionContext(contextWithPack, decompositionContext);
1921
2193
  const reviewerContextStatus = renderReviewerContextStatus(reviewerContext, decompositionContext);
1922
2194
  let intent: string;
1923
2195
  let intentSource: 'flag' | 'flag+pr-body' | 'pr-body' | 'pr-title' | 'fallback';
1924
2196
  let intentTruncation: ReturnType<typeof reviewIntentTruncationObservation>;
1925
- if (opts.intent !== undefined) {
2197
+ if (deltaBase) {
2198
+ intent = deltaReviewIntent(deltaBase);
2199
+ intentTruncation = {};
2200
+ intentSource = 'fallback';
2201
+ } else if (opts.intent !== undefined) {
1926
2202
  if (body?.trim()) {
1927
2203
  const intentText = `## 명시 intent\n${opts.intent}\n\n## PR 본문\n${body.trim()}`;
1928
2204
  intent = buildManualReviewIntent(opts.intent, body.trim());
@@ -1941,7 +2217,7 @@ async function runSelfReviewCliCommandPinned(
1941
2217
  intentSource = body?.trim() ? 'pr-body' : title.trim() ? 'pr-title' : 'fallback';
1942
2218
  if (!intent) intent = `PR ${pr}`;
1943
2219
  }
1944
- if (previousRoundCount >= 2 && diff.status === 0 && !diffRead.stale && diffRead.headCommitState === 'known') {
2220
+ if (!deltaBase && previousRoundCount >= 2 && diff.status === 0 && !diffRead.stale && diffRead.headCommitState === 'known') {
1945
2221
  if (!deps.loadDoctorReviewBrief) {
1946
2222
  deps.observeDoctorReview?.('brief-unavailable', { pr, head: diffRead.headCommit, previousRoundCount, reason: 'module-not-wired' });
1947
2223
  } else {
@@ -1989,22 +2265,40 @@ async function runSelfReviewCliCommandPinned(
1989
2265
  { pr: safeLogText(pr), exit: diff.status, error: safeLogText(diff.stderr || err, 160) },
1990
2266
  { level: 'warn' });
1991
2267
  const contextOutput = reviewerContextOutput(reviewerContext, decompositionContext);
1992
- if (opts.json || opts.save !== undefined) results.push({ pr, error: err, ...contextOutput, ...comparisonData, ...(mismatchWarning ?? {}) });
2268
+ const errorResult = { pr, error: err, reviewed: false, headCommit: diffRead.headCommit,
2269
+ currentHeadCommit: diffRead.currentHeadCommit, stale: diffRead.stale,
2270
+ ...contextOutput, ...comparisonData, ...(mismatchWarning ?? {}) };
2271
+ if (opts.json || opts.save !== undefined) results.push(errorResult);
2272
+ if (canonicalResultPath && COMMIT_OID.test(diffRead.headCommit)
2273
+ && diffRead.headCommitState === 'known' && diffRead.currentHeadCommitState === 'known'
2274
+ && diffRead.currentHeadCommit === diffRead.headCommit && !diffRead.stale) {
2275
+ try {
2276
+ if (!existsSync(canonicalResultPath) || isReplaceableErrorArtifact(canonicalResultPath, pr, diffRead.headCommit)) {
2277
+ mkdirSync(dirname(canonicalResultPath), { recursive: true });
2278
+ writeFileSync(canonicalResultPath, selfReviewJsonLine([errorResult]));
2279
+ }
2280
+ } catch (error) {
2281
+ deps.error(`PR ${pr}: 오류 리뷰 결과 저장 실패 (${canonicalResultPath}): ${error instanceof Error ? error.message : String(error)}`);
2282
+ }
2283
+ }
1993
2284
  if (!opts.json) deps.error(`PR ${pr}: ${err}\n${reviewerContextStatus}`);
2285
+ releaseCapClaim();
1994
2286
  failed += 1;
1995
2287
  continue;
1996
2288
  }
1997
2289
  // ⭐ S2(2026-07-30) — 리뷰 증거를 **이 PR 이 저작한 변경**으로 좁힌다. 실측 7건에서 1건만
1998
2290
  // 좁히고(49→6) 나머지는 그대로다. ⚠️ 새 이벤트를 만들지 않는다 — 증거는 **입력의 성질**이므로
1999
2291
  // `start` payload 에 싣는다(발화 순서 계약 보존).
2000
- const evidence = narrowEvidenceToAuthored(pr, diffRead.headCommit, diff.stdout, deps);
2292
+ const evidence = deltaBase
2293
+ ? { diff: diff.stdout, evidence: 'saved-review-delta' as const, prDiffFiles: diffFilePaths(diff.stdout).length }
2294
+ : narrowEvidenceToAuthored(pr, diffRead.headCommit, diff.stdout, deps);
2001
2295
  const evidenceLine = renderEvidenceProvenance(evidence);
2002
2296
  // ⭐ 골 판정 신호는 reviewInput 조립 전에 PR당 한 번만 조회한다. ACP 폴백이 같은 객체를
2003
2297
  // 재사용하므로 리뷰 루프 안에서 queryRunChain 을 반복하지 않는다.
2004
2298
  const lookupGoalAcceptance = deps.lookupPrGoalAcceptance ?? lookupPrGoalAcceptance;
2005
2299
  let goalAcceptance: PrGoalAcceptanceLookup = { goalLoaded: false, acceptanceChars: 0 };
2006
2300
  try {
2007
- goalAcceptance = lookupGoalAcceptance(Number(pr));
2301
+ if (!deltaBase) goalAcceptance = lookupGoalAcceptance(Number(pr));
2008
2302
  } catch {
2009
2303
  goalAcceptance = { goalLoaded: false, acceptanceChars: 0 };
2010
2304
  }
@@ -2052,6 +2346,7 @@ async function runSelfReviewCliCommandPinned(
2052
2346
  };
2053
2347
  if (opts.json || opts.save !== undefined) results.push(refused);
2054
2348
  if (!opts.json) deps.print(`\n━━ PR ${pr} (${primaryModel}) ━━\n${renderStaleRefusal(diffRead)}\n${reviewerContextStatus}`);
2349
+ releaseCapClaim();
2055
2350
  continue;
2056
2351
  }
2057
2352
  // ⭐ 머지된 PR 만 머지 커밋 detached worktree 에서 리뷰한다 — main 최신이 아니라 그 PR 이 머지된 시점의 코드를 본다.
@@ -2096,7 +2391,7 @@ async function runSelfReviewCliCommandPinned(
2096
2391
  // ⛔ evidenceNote 는 **별도 채널**이다 — phaseIntent 에 섞으면 의도 채널이 오염된다(실측: 그렇게
2097
2392
  // 했다가 intent 배선 테스트 3개가 즉시 깨졌다).
2098
2393
  // ⛔ 사람 `--intent`(phaseIntent) 와 골 acceptance 는 다른 인자 — 충돌하지 않고, 충돌해도 intent 가 이긴다.
2099
- const reviewInput = {
2394
+ const reviewInput: ReviewInput = {
2100
2395
  prDiff: evidence.diff,
2101
2396
  phaseIntent: intent,
2102
2397
  evidenceNote: evidenceLine,
@@ -2105,6 +2400,8 @@ async function runSelfReviewCliCommandPinned(
2105
2400
  ...(deps.readReferencedFile ? { readReferencedFile: deps.readReferencedFile } : {}),
2106
2401
  ...(goalAcceptance.acceptance ? { acceptance: goalAcceptance.acceptance } : {}),
2107
2402
  };
2403
+ const reviewInputChars = reviewInputCharacterCount(reviewInput);
2404
+ const intentFingerprint = reviewIntentFingerprint(reviewInput.phaseIntent);
2108
2405
  // ⭐ Role-config ACP lane: a completed ACP review is used as-is; anything else (throw, reviewed≠true)
2109
2406
  // falls to the same API review this command ran before the lane existed — and is observed.
2110
2407
  // ⚠️ Stricter than the harness lane on purpose: `runSubscriptionReviewer` accepts any non-empty text;
@@ -2197,6 +2494,43 @@ async function runSelfReviewCliCommandPinned(
2197
2494
  claudeFallbackGlm = { reason, model: ZAI_OPENROUTER_FALLBACK_MODEL, glmReviewed: glmFailureReason === undefined,
2198
2495
  ...(glmFailureReason !== undefined ? { glmFailureReason } : {}) };
2199
2496
  }
2497
+ const reviewDurationMs = Math.max(0, deps.now() - startedAt);
2498
+ let deltaReceipt: Record<string, unknown> = {};
2499
+ if (deltaBase) {
2500
+ const assessed = assessDeltaReview(review, deltaBase);
2501
+ const deltaEfficiency = {
2502
+ inputRatio: reviewInputChars / deltaBase.reviewInputChars,
2503
+ timeRatio: reviewDurationMs / deltaBase.reviewDurationMs,
2504
+ maxRatio: 1 / 3,
2505
+ };
2506
+ const efficient = deltaEfficiency.inputRatio <= deltaEfficiency.maxRatio
2507
+ && deltaEfficiency.timeRatio <= deltaEfficiency.maxRatio;
2508
+ if (review.reviewed !== true) {
2509
+ const reason = review.failureReason || 'delta-review-not-completed';
2510
+ review = { ...review, reviewed: false, verdict: 'fail', mustFix: [], shouldFix: [], failureReason: reason };
2511
+ deltaReceipt = { basedOn: deltaBase.headCommit, basedOnReview: deltaBase.file,
2512
+ deltaInputChars: reviewInputChars, deltaDurationMs: reviewDurationMs, deltaEfficiency,
2513
+ deltaRefusal: 'delta-review-not-completed' };
2514
+ } else if (!assessed.valid) {
2515
+ review = { ...review, reviewed: false, verdict: 'fail', mustFix: [], shouldFix: [],
2516
+ failureReason: assessed.reason };
2517
+ deltaReceipt = { basedOn: deltaBase.headCommit, basedOnReview: deltaBase.file,
2518
+ deltaInputChars: reviewInputChars, deltaDurationMs: reviewDurationMs, deltaEfficiency,
2519
+ deltaRefusal: assessed.reason };
2520
+ } else if (!efficient) {
2521
+ review = { ...review, reviewed: false, verdict: 'fail', mustFix: [], shouldFix: [],
2522
+ failureReason: 'delta-efficiency-limit-exceeded' };
2523
+ deltaReceipt = { basedOn: deltaBase.headCommit, basedOnReview: deltaBase.file,
2524
+ deltaFindings: assessed.deltaFindings, deltaInputChars: reviewInputChars,
2525
+ deltaDurationMs: reviewDurationMs, deltaEfficiency, deltaRefusal: 'delta-efficiency-limit-exceeded' };
2526
+ } else {
2527
+ review = { ...review, reviewed: true, verdict: assessed.mustFix.length ? 'fail' : 'pass',
2528
+ mustFix: assessed.mustFix, shouldFix: [] };
2529
+ deltaReceipt = { basedOn: deltaBase.headCommit, basedOnReview: deltaBase.file,
2530
+ deltaFindings: assessed.deltaFindings, excludedNewFindings: assessed.excludedNewFindings,
2531
+ deltaInputChars: reviewInputChars, deltaDurationMs: reviewDurationMs, deltaEfficiency };
2532
+ }
2533
+ }
2200
2534
  reviewPin?.remove();
2201
2535
  // reviewCwdCommit 은 «최종 판정을 낸 LLM 이 실제로 그 cwd 를 받았을 때만» 싣는다(role 실패 → API 폴백이면 안 싣는다).
2202
2536
  const reviewedOnPin = Boolean(reviewPin) && (roleReview ? rolePinned : reviewRoute === 'acp-fallback' ? true : reviewRoute === 'acp' && useAcp);
@@ -2299,7 +2633,7 @@ async function runSelfReviewCliCommandPinned(
2299
2633
  deps.log('done',
2300
2634
  {
2301
2635
  ...buildReviewObservation({
2302
- pr, model: selectedModel, intent, review, durationMs: deps.now() - startedAt,
2636
+ pr, model: selectedModel, intent, intentFingerprint, review, durationMs: reviewDurationMs,
2303
2637
  ...reviewProvenance,
2304
2638
  ...intentTruncation,
2305
2639
  ...reviewDiffBudgetObservation(review),
@@ -2322,6 +2656,7 @@ async function runSelfReviewCliCommandPinned(
2322
2656
  const contextOutput = reviewerContextOutput(reviewerContext, decompositionContext);
2323
2657
  if (opts.json || opts.save !== undefined) results.push({ pr, error: err, ...review, verdict: null, ...reviewProvenance, ...respondedOutput, ...reviewerSelection, ...reviewCwdOutput, ...provenance, ...contextOutput });
2324
2658
  if (!opts.json) deps.error(`PR ${pr}: ${err}\n${renderProvenance(diffRead)}\n${reviewerContextStatus}`);
2659
+ releaseCapClaim();
2325
2660
  failed += 1;
2326
2661
  continue;
2327
2662
  }
@@ -2330,7 +2665,27 @@ async function runSelfReviewCliCommandPinned(
2330
2665
  // ⛔ 금지 백엔드가 낸 판정은 «근거 거부»다 — verdict·mustFix 를 그대로 실어 보내면 읽는 쪽이
2331
2666
  // 그것을 착지 판정으로 쓴다(관문도 reviewed===true 를 근거 조건으로 본다).
2332
2667
  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 } : {}) });
2668
+ const resultOutput = { pr, model: selectedModel, ...jsonReview, reviewInputChars, reviewDurationMs,
2669
+ ...(deltaBase ? deltaReceipt : {}), ...reviewProvenance, ...respondedOutput, ...reviewerSelection,
2670
+ ...reviewCwdOutput, ...provenance, ...contextOutput, ...refusalOverride, ...landingGateFields,
2671
+ findingPathHeadChecks, pathWarnings, evidence: evidence.evidence, prDiffFiles: evidence.prDiffFiles,
2672
+ ...(evidence.authoredFiles !== undefined ? { authoredFiles: evidence.authoredFiles } : {}) };
2673
+ if (opts.json || opts.save !== undefined || shouldPersistCapResult) results.push(resultOutput);
2674
+ if (!shouldPersistCapResult
2675
+ && landingGateAdmitted && review.reviewed === true && diffRead.headCommitState === 'known'
2676
+ && diffRead.currentHeadCommitState === 'known' && diffRead.currentHeadCommit === diffRead.headCommit
2677
+ && !diffRead.stale && COMMIT_OID.test(diffRead.headCommit)) {
2678
+ const path = canonicalResultPath ?? join(effectiveInstanceRoot(), 'review-results', `pr-${pr}-${diffRead.headCommit.slice(0, 12)}.json`);
2679
+ const normalized = normalizeSavedReviewMustFix(resultOutput);
2680
+ try {
2681
+ mkdirSync(dirname(path), { recursive: true });
2682
+ // A successful review replaces an earlier error artifact for the same PR head.
2683
+ writeFileSync(path, selfReviewJsonLine([normalized.result]));
2684
+ if (normalized.count > 0 && opts.save === undefined) deps.log('mustfix-normalized', { pr, head: diffRead.headCommit, count: normalized.count });
2685
+ } catch (error) {
2686
+ deps.error(`PR ${pr}: 리뷰 결과 저장 실패 (${path}): ${error instanceof Error ? error.message : String(error)}`);
2687
+ }
2688
+ }
2334
2689
  if (!opts.json) {
2335
2690
  if (!landingGateAdmitted) deps.print(`\n━━ PR ${pr} (${selectedModel}) ━━\n${renderProvenance(diffRead)}\n⛔ LANDING GATE: review-forbidden-acp-backend (${landingGateDeniedBackend ?? 'unknown'}) — 이 리뷰는 착지 근거가 아닙니다.\n${reviewerContextStatus}`);
2336
2691
  else deps.print(`\n━━ PR ${pr} (${selectedModel}) ━━\n${renderProvenance(diffRead)}\n${evidenceLine}\n${reviewerContextStatus}\n${deps.renderReview(review)}${pathWarnings.length ? `\n${pathWarnings.join('\n')}` : ''}`);
@@ -2361,6 +2716,28 @@ async function runSelfReviewCliCommandPinned(
2361
2716
  }
2362
2717
  }
2363
2718
  }
2719
+ if (shouldPersistCapResult) {
2720
+ if (!landingGateAdmitted || review.reviewed !== true || !canonicalResultPath
2721
+ || diffRead.headCommitState !== 'known' || diffRead.currentHeadCommitState !== 'known'
2722
+ || diffRead.currentHeadCommit !== diffRead.headCommit || !COMMIT_OID.test(diffRead.headCommit)) {
2723
+ releaseCapClaim();
2724
+ deps.error(`PR ${pr}: 상한 예외 리뷰 결과가 저장 가능한 상태가 아니어서 승인 사용 기록을 되돌렸습니다.`);
2725
+ } else {
2726
+ const rawResult = results.at(-1);
2727
+ const normalized = rawResult && typeof rawResult === 'object'
2728
+ ? normalizeSavedReviewMustFix(rawResult)
2729
+ : { result: rawResult, count: 0 };
2730
+ try {
2731
+ mkdirSync(dirname(canonicalResultPath), { recursive: true });
2732
+ writeFileSync(canonicalResultPath, selfReviewJsonLine([normalized.result]));
2733
+ if (normalized.count > 0) deps.log('mustfix-normalized', { pr, head: diffRead.headCommit, count: normalized.count });
2734
+ } catch (error) {
2735
+ releaseCapClaim();
2736
+ failed += 1;
2737
+ deps.error(`PR ${pr}: 상한 예외 리뷰 결과 저장 실패${canonicalResultPath ? ` (${canonicalResultPath})` : ''}: ${error instanceof Error ? error.message : String(error)}`);
2738
+ }
2739
+ }
2740
+ }
2364
2741
  }
2365
2742
  return { results, failed };
2366
2743
  }