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
@@ -1,9 +1,10 @@
1
- import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs';
2
- import { randomUUID } from 'node:crypto';
1
+ import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { createHash, randomUUID } from 'node:crypto';
3
3
  import { tmpdir } from 'node:os';
4
4
  import { spawnSync } from 'node:child_process';
5
- import { join } from 'node:path/posix';
5
+ import { basename, join, resolve } from 'node:path/posix';
6
6
  import { prepareDeterministicChildEnvironment } from '../../scripts/lib/deterministic-env.js';
7
+ import { audit as auditEntryBudget, entryBudgetAffected } from '../../scripts/ratchets/next-tui-entry-budget.js';
7
8
  import { withGateTestEnv } from '../../scripts/lib/gate-test-env.js';
8
9
  import { runIsolationHardcodeGate } from '../../scripts/ci-isolation-hardcode-gate.js';
9
10
  import { runModelHardcodeGate } from '../../scripts/ci-model-hardcode-gate.js';
@@ -13,13 +14,15 @@ import { runIosUnitTestGate } from '../../scripts/ci-ios-unit-tests.js';
13
14
  import { runPwaBuildGate } from '../../scripts/ci-pwa-build-gate.js';
14
15
  import { runMockModuleRestoreGate } from '../../scripts/ci-mock-module-restore-gate.js';
15
16
  import { parseReviewDepthFromFilesJson } from '../agent-mission/review-depth.js';
16
- import { buildGateBaselineReport, calculateGateTestCountChange, formatGateBaselineNote, formatGateTestCountNote, isGateTestFile, recheckTimeoutOnlyIntroducedFailures, runGateBaseline, type BaselineProcessResult, type BaselineProcessStatus, type GateTestFailure, type TimeoutRecheckRecord, type TimeoutRerunObservation } from './gate-baseline.js';
17
+ import { buildGateBaselineReport, calculateGateTestCountChange, formatGateBaselineNote, formatGateTestCountNote, isGateTestFile, recheckOutsideScopeFailures, recheckTimeoutOnlyIntroducedFailures, runGateBaseline, type BaselineProcessResult, type BaselineProcessStatus, type GateBaselineReport, type GateTestFailure, type InterferenceRecheckRecord, type TimeoutRecheckRecord, type TimeoutRerunObservation } from './gate-baseline.js';
17
18
  import { resolveGateScope } from './gate-scope.js';
18
19
  import { publicExposureFiles, runExposeGate } from './expose-gate.js';
19
20
  import { getUserConfig } from '../user-config.js';
20
21
  import { debug, redactSecretText } from '../debug/log.js';
22
+ import { getElanousConfigDir } from '../elanous-config-dir.js';
21
23
  import { buildDocumentGuardianIndex, formatDocumentGuardians } from './document-guardian-index.js';
22
24
  import { buildImporterTestIndex, importerTestsNotInRunSet, isTestPath, type ImporterTestIndex } from './importer-test-index.js';
25
+ import { isCommentOnlySourceChange } from './comment-only-source.js';
23
26
  import { buildRouteConsumerTestIndex } from './route-consumer-test-index.js';
24
27
  import { gitChangedFiles, observeGateBaselineLocation } from './seams.js';
25
28
  import {
@@ -27,7 +30,7 @@ import {
27
30
  overlapWithCurrentChanges,
28
31
  } from '../cli/pr-granularity.js';
29
32
  import { listWorktrees } from '../git-fs/worktree.js';
30
- import { runShardedGateTests, writeShardFailureEvidence, remoteShardArgv, type ShardRunProgress } from '../self-dev/shard-run.js';
33
+ import { runShardedGateTests, runShardedGateTestsAsync, writeShardFailureEvidence, remoteShardArgv, type ShardRunProgress, type ShardRunResult } from '../self-dev/shard-run.js';
31
34
  import { planGateRemoteShards, shardPlanOrchestrationId, type GateRemoteShard } from '../self-dev/shard-plan.js';
32
35
  import { parseGateScenario, readGateScenarioFile } from './gate-scenario.js';
33
36
  import { isGateSpawnLaneFile } from '../self-dev/spawn-lane-files.js';
@@ -36,7 +39,11 @@ import { defaultGateEnvKey, defaultRevResolver, resolveArtifactDir, writeGateArt
36
39
  export interface SelfGateCliOptions {
37
40
  base?: string;
38
41
  pr?: string;
42
+ /** Bypass reuse of the last passing test radius; still write this run's receipt for the next invocation. */
43
+ noInherit?: boolean;
39
44
  shards?: number;
45
+ /** Live shard bundle concurrency; default three, bounded to one through four. */
46
+ shardConcurrency?: number;
40
47
  /** OP FU (LAND-TRAIN-LIVE side) — opt-in with `shards`: sorted round-robin into exactly that N, no RSS pre-measurement.
41
48
  * Every other output (shardsDetail · baseline · artifacts · exit) keeps its shape; absent = measured planner unchanged. */
42
49
  fixedShardDistribution?: boolean;
@@ -102,10 +109,11 @@ interface SelfGateCliDeps {
102
109
  runTests?: (cwd: string, files: readonly string[]) => ProcessResult;
103
110
  runBaseline?: (cwd: string, files: readonly string[], baseRef: string) => BaselineProcessResult;
104
111
  runTimeoutRecheck?: (cwd: string, file: string, name: string, timeoutMs: number) => { observation?: TimeoutRerunObservation; elapsedMs: number; output: string };
112
+ runInterferenceRecheck?: (cwd: string, report: GateBaselineReport, baseRef: string, relatedTestFiles: readonly string[]) => GateBaselineReport;
105
113
  runShards?: typeof runShardedGateTests;
114
+ runShardsAsync?: typeof runShardedGateTestsAsync;
106
115
  /** Test seam for the live progress line. */
107
116
  writeProgressStderr?: (line: string) => void;
108
- now?: () => number;
109
117
  runIsolationGate?: (out: GateOutput) => number;
110
118
  runMockModuleRestoreGate?: (out: GateOutput) => number;
111
119
  /** 모델 이름 하드코딩 래칫(🅕 #20521) — `pr land` 만 물고 하니스 무인 병합은 안 물면 위반이 main 에 들어가 남의 착지를 막는다(🅣 2026-09-25). */
@@ -117,17 +125,25 @@ interface SelfGateCliDeps {
117
125
  /** iOS 순수-로직 시험 게이트 심(시험 주입용). */
118
126
  runIosGate?: (out: GateOutput) => number;
119
127
  runPwaGate?: (out: GateOutput) => number;
128
+ runEntryBudgetGate?: (cwd: string, changedFiles: readonly string[]) => { affected: boolean; errors: string[] };
120
129
  listPrWorktrees?: (cwd: string) => PrWorktreeListEntry[] | { lookupFailed: string };
121
130
  inspectWorktreeDirtiness?: (path: string) => { dirty: boolean } | { lookupFailed: string };
122
131
  /** `--artifact-dir` 전용 심 — 커밋 sha 해석(실패 = null) · 환경 키. */
123
132
  resolveRev?: RevResolver;
124
133
  envKey?: () => string;
134
+ /** Receipt-store seam for tests; production stores under ~/.elanous/gate-receipts. */
135
+ gateReceiptDir?: () => string;
136
+ now?: () => number;
125
137
  }
126
138
 
127
139
  /** `--artifact-dir` 가 쓸 재료 — 판정 경로가 «채우기만» 하고 읽지 않는다. */
128
140
  interface GateArtifactCapture {
129
141
  baseRef?: string;
130
142
  testFiles?: readonly string[];
143
+ fullTestFiles?: readonly string[];
144
+ failedTestFiles?: readonly string[];
145
+ testReceiptMeasured?: boolean;
146
+ receiptDecision?: GateReceiptDecision;
131
147
  sharded?: ReturnType<typeof runShardedGateTests>;
132
148
  verdict?: string;
133
149
  verdictLine?: string;
@@ -138,6 +154,7 @@ interface GateArtifactCapture {
138
154
  unrunImporters?: number | null;
139
155
  importerLookupFailed?: string;
140
156
  timeoutRechecks?: readonly TimeoutRecheckRecord[];
157
+ interferenceRechecks?: readonly InterferenceRecheckRecord[];
141
158
  }
142
159
 
143
160
  /** SIDE-VERIFY ③ — summary 정수 칸: 게이트가 이미 낸 `result.baseline` ⊕ `unrunImporterTotal` 을 «옮기기만» 한다.
@@ -675,6 +692,30 @@ function logGateCliBaseline(cwd: string, payload: GateCliBaselinePayload): void
675
692
  type GateSelectionOptions = Pick<SelfGateCliOptions, 'base' | 'pr' | 'alwaysInclude' | 'includeImporterTests' | 'scenario' | 'scenarioFile'>;
676
693
  type GateSelectionDeps = Pick<SelfGateCliDeps, 'changedFiles' | 'exists' | 'isRegularFile' | 'runCommand'>;
677
694
 
695
+ function commentOnlyChangedSources(selection: ChangedFileSelection, cwd: string, runCommand: SelfGateCliDeps['runCommand']): string[] {
696
+ const run = runCommand ?? defaultRunCommand;
697
+ // Fail closed: an unreadable base, source or Git command keeps the normal importer set.
698
+ const base = selection.baseRef === 'HEAD'
699
+ ? 'HEAD'
700
+ : (() => {
701
+ try {
702
+ const result = run('git', ['merge-base', selection.baseRef, 'HEAD'], cwd);
703
+ return result.status === 0 && !result.error ? result.stdout?.trim() : undefined;
704
+ } catch { return undefined; }
705
+ })();
706
+ if (!base) return [];
707
+ const commentOnly: string[] = [];
708
+ for (const path of selection.files) {
709
+ if (!/^(?:src|scripts)\/.+\.(?:[cm]?[jt]sx?)$/.test(path) || isTestPath(path)) continue;
710
+ try {
711
+ const prior = run('git', ['show', `${base}:${path}`], cwd);
712
+ if (prior.status !== 0 || prior.error || prior.stdout === undefined) continue;
713
+ if (isCommentOnlySourceChange(prior.stdout, readFileSync(join(cwd, path), 'utf8'), path)) commentOnly.push(path);
714
+ } catch { /* A failed comparison must retain importer coverage. */ }
715
+ }
716
+ return commentOnly;
717
+ }
718
+
678
719
  function prepareGateTestSelection(cwd: string, options: GateSelectionOptions, deps: GateSelectionDeps) {
679
720
  const selection = (deps.changedFiles ?? ((dir, input) => defaultChangedFiles(dir, input, deps.runCommand)))(cwd, options);
680
721
  const exists = deps.exists ?? ((path) => existsSync(`${cwd}/${path}`));
@@ -683,16 +724,23 @@ function prepareGateTestSelection(cwd: string, options: GateSelectionOptions, de
683
724
  const importerIndex = buildGateImporterTestIndex(options.includeImporterTests
684
725
  ? selection.files : selection.files.filter((path) => !SCRIPT_SOURCE_PATH_RE.test(path)), cwd, deps.runCommand);
685
726
  const lookupFailed = importerIndex && 'lookupFailed' in importerIndex ? importerIndex.lookupFailed : undefined;
686
- const availableIndex = importerIndex && !('lookupFailed' in importerIndex) ? importerIndex : undefined;
727
+ const originalIndex = importerIndex && !('lookupFailed' in importerIndex) ? importerIndex : undefined;
728
+ const commentOnlySources = options.includeImporterTests && originalIndex
729
+ ? commentOnlyChangedSources(selection, cwd, deps.runCommand) : [];
730
+ // testPaths is the independent full tracked-test inventory; only the changed-source
731
+ // reverse edges are filtered. Other consumers still need that complete inventory.
732
+ const availableIndex = originalIndex && commentOnlySources.length
733
+ ? { ...originalIndex, testsBySource: new Map([...originalIndex.testsBySource].filter(([source]) => !commentOnlySources.includes(source))) }
734
+ : originalIndex;
687
735
  const routeIndex = availableIndex?.testPaths
688
- ? buildRouteConsumerTestIndex(cwd, availableIndex.testPaths, selection.files, selection.baseRef) : null;
736
+ ? buildRouteConsumerTestIndex(cwd, availableIndex.testPaths, selection.files.filter((path) => !commentOnlySources.includes(path)), selection.baseRef) : null;
689
737
  const scope = resolveGateScope(selection.files, exists, availableIndex,
690
738
  { routeConsumerTestIndex: routeIndex ?? undefined });
691
- return { selection, exists, lookupFailed, availableIndex, routeIndex, scope };
739
+ return { selection, exists, lookupFailed, availableIndex, commentOnlySources, routeIndex, scope };
692
740
  }
693
741
 
694
742
  function finishGateTestSelection(prepared: ReturnType<typeof prepareGateTestSelection>, options: GateSelectionOptions, cwd: string, deps: GateSelectionDeps) {
695
- const { selection, exists, lookupFailed, availableIndex, routeIndex, scope } = prepared;
743
+ const { selection, exists, lookupFailed, availableIndex, commentOnlySources, routeIndex, scope } = prepared;
696
744
  const alwaysInclude = [...new Set((options.alwaysInclude ?? []).map(normalizeGatePath).filter(Boolean))];
697
745
  const alwaysIncludeMissing = alwaysInclude.filter((path) => !exists(path));
698
746
  const scopedTests = scope.testArgs ?? [];
@@ -720,20 +768,21 @@ function finishGateTestSelection(prepared: ReturnType<typeof prepareGateTestSele
720
768
  // RELEASE-DAILY-LIGHT-RC ② — the scope already runs importer tests as callers, but capped (GATE_CALLER_TEST_LIMIT);
721
769
  // a day of landings overflows that cap and source-only regressions went unrun (0.2.24: 20). Opt-in: every importer.
722
770
  const changedSources = selection.files.filter((path) => !isTestPath(path));
771
+ const importerSources = changedSources.filter((path) => !commentOnlySources.includes(path));
723
772
  const importerTestsAdded = options.includeImporterTests && availableIndex
724
- ? [...new Set(changedSources.flatMap((source) => availableIndex.testsBySource.get(source) ?? []))]
773
+ ? [...new Set(importerSources.flatMap((source) => availableIndex.testsBySource.get(source) ?? []))]
725
774
  .filter((path) => exists(path) && !scopedTests.includes(path) && !alwaysIncludeExtra.includes(path)).sort()
726
775
  : [];
727
776
  const defaultTests = [...scopedTests, ...alwaysIncludeExtra, ...importerTestsAdded];
728
777
  const testFiles = scenarioTests.length ? [...new Set([...defaultTests, ...scenarioTests])] : defaultTests;
729
778
  const skipTestStep = scope.skipTestStep && alwaysIncludeExtra.length === 0 && importerTestsAdded.length === 0 && scenarioTests.length === 0;
730
779
  const importerTestsNotRun = (options.includeImporterTests || scenarioTests.length > 0) && availableIndex
731
- ? importerTestsNotInRunSet(availableIndex, changedSources, testFiles) : scope.importerTestsNotRun;
780
+ ? importerTestsNotInRunSet(availableIndex, importerSources, testFiles) : scope.importerTestsNotRun;
732
781
  const unrunImporterTotal = lookupFailed ? null : (importerTestsNotRun?.total ?? 0);
733
782
  // Overflowed callers that ② ran anyway are not «not run».
734
783
  const callerTestsOverflow = scope.callerTestsOverflow.filter(({ file }) => !importerTestsAdded.includes(file) && !scenarioTests.includes(file));
735
784
  const importerLookupFailed = Boolean(lookupFailed);
736
- return { ...prepared, alwaysInclude, alwaysIncludeMissing, alwaysIncludeExtra, importerTestsAdded, scenarioTests,
785
+ return { ...prepared, alwaysInclude, alwaysIncludeMissing, alwaysIncludeExtra, importerTestsAdded, commentOnlySources, scenarioTests,
737
786
  testFiles, skipTestStep, importerTestsNotRun, unrunImporterTotal, callerTestsOverflow, importerLookupFailed };
738
787
  }
739
788
 
@@ -760,7 +809,17 @@ export function selectGateTestFiles(cwd: string, options: GateSelectionOptions =
760
809
 
761
810
  export function runSelfGateCli(cwd: string, options: SelfGateCliOptions = {}, deps: SelfGateCliDeps = {}): SelfGateCliResult {
762
811
  const capture: GateArtifactCapture = {};
763
- const result = runSelfGateCliCore(cwd, options, deps, capture);
812
+ const result = runSelfGateCliCore(cwd, options, deps, capture, false) as SelfGateCliResult;
813
+ persistGateReceipt(cwd, capture, deps);
814
+ if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps);
815
+ return result;
816
+ }
817
+
818
+ /** Production path: shard bundles use async Bun children; all non-shard policy and timeout logic is shared. */
819
+ export async function runSelfGateCliAsync(cwd: string, options: SelfGateCliOptions = {}, deps: SelfGateCliDeps = {}): Promise<SelfGateCliResult> {
820
+ const capture: GateArtifactCapture = {};
821
+ const result = await runSelfGateCliCore(cwd, options, deps, capture, true);
822
+ persistGateReceipt(cwd, capture, deps);
764
823
  if (options.artifactDir !== undefined) emitGateArtifacts(cwd, options.artifactDir, result, capture, deps);
765
824
  return result;
766
825
  }
@@ -784,6 +843,7 @@ function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCli
784
843
  verdict: capture.verdict ?? null,
785
844
  ...(capture.verdictLine !== undefined ? { verdictLine: capture.verdictLine } : {}),
786
845
  ...(capture.timeoutRechecks ? { timeoutRechecks: capture.timeoutRechecks } : {}),
846
+ ...(capture.interferenceRechecks ? { interferenceRechecks: capture.interferenceRechecks } : {}),
787
847
  exitCode: result.exitCode,
788
848
  counts: counts.counts,
789
849
  ...(counts.reason !== undefined ? { countsUnavailableReason: counts.reason } : {}),
@@ -798,6 +858,246 @@ function emitGateArtifacts(cwd: string, artifactDir: string, result: SelfGateCli
798
858
  }
799
859
  }
800
860
 
861
+ const GATE_RECEIPT_TTL_MS = 7 * 24 * 60 * 60 * 1000;
862
+ const GATE_RECEIPT_SCHEMA = 1;
863
+
864
+ interface GateReceipt {
865
+ schema: 1;
866
+ createdAt: number;
867
+ repositoryHash: string;
868
+ branch: string;
869
+ baseSha: string;
870
+ headSha: string;
871
+ runtime: string;
872
+ environmentKey: string;
873
+ lockfileHash: string;
874
+ fullTestFiles: string[];
875
+ failedTestFiles: string[];
876
+ measured: boolean;
877
+ }
878
+
879
+ interface GateReceiptIdentity extends Omit<GateReceipt, 'createdAt' | 'fullTestFiles' | 'failedTestFiles' | 'measured'> {
880
+ receiptPath: string;
881
+ receiptDir: string;
882
+ }
883
+
884
+ interface GateReceiptDecision {
885
+ mode: 'full' | 'inherit';
886
+ reason: string;
887
+ identity?: GateReceiptIdentity;
888
+ sourceHead?: string;
889
+ runTestFiles?: readonly string[];
890
+ inheritedTestFiles?: readonly string[];
891
+ }
892
+
893
+ function sha256(value: string | Buffer): string {
894
+ return createHash('sha256').update(value).digest('hex');
895
+ }
896
+
897
+ function normalizedRepositoryUrl(value: string): string | undefined {
898
+ const raw = value.trim();
899
+ if (!raw) return undefined;
900
+ if (!raw.includes('://')) {
901
+ const scp = /^(?:[^@]+@)?([^:]+):(.+)$/.exec(raw);
902
+ if (scp) return `${scp[1].toLowerCase()}/${scp[2]}`.replace(/\.git$/i, '');
903
+ }
904
+ try {
905
+ const url = new URL(raw);
906
+ url.username = '';
907
+ url.password = '';
908
+ url.search = '';
909
+ url.hash = '';
910
+ return `${url.protocol.toLowerCase()}//${url.host.toLowerCase()}${url.pathname}`.replace(/\.git$/i, '').replace(/\/$/, '');
911
+ } catch { return undefined; }
912
+ }
913
+
914
+ function gateReceiptIdentity(
915
+ cwd: string,
916
+ selection: ChangedFileSelection,
917
+ deps: SelfGateCliDeps,
918
+ ): { identity?: GateReceiptIdentity; reason?: string } {
919
+ const run = deps.runCommand ?? defaultRunCommand;
920
+ const command = (args: string[]) => {
921
+ try { return run('git', args, cwd); }
922
+ catch (error) { return { status: null, stderr: error instanceof Error ? error.message : String(error) }; }
923
+ };
924
+ const worktree = command(['status', '--porcelain=v1', '-z', '--untracked-files=all']);
925
+ if (worktree.status !== 0 || worktree.error || worktree.stdout === undefined) {
926
+ return { reason: 'worktree-status-unavailable' };
927
+ }
928
+ if (worktree.stdout.length > 0) return { reason: 'worktree-dirty' };
929
+ const remote = command(['config', '--get', 'remote.origin.url']);
930
+ const repositoryUrl = remote.status === 0 ? normalizedRepositoryUrl(remote.stdout ?? '') : undefined;
931
+ if (!repositoryUrl) return { reason: 'repository-origin-unavailable' };
932
+ const branch = selection.prHeadRefName?.trim() || (() => {
933
+ const result = command(['branch', '--show-current']);
934
+ return result.status === 0 ? (result.stdout ?? '').trim() : '';
935
+ })();
936
+ if (!branch) return { reason: 'branch-unavailable' };
937
+ if (selection.baseRef === 'HEAD') return { reason: 'uncommitted-or-no-stable-base' };
938
+ const resolveRev = deps.resolveRev ?? defaultRevResolver(cwd);
939
+ const baseSha = resolveRev(selection.baseRef);
940
+ const headSha = resolveRev('HEAD');
941
+ if (!baseSha || !headSha || !/^[0-9a-f]{40}$/.test(baseSha) || !/^[0-9a-f]{40}$/.test(headSha)) {
942
+ return { reason: 'base-or-head-sha-unavailable' };
943
+ }
944
+ const lockfile = ['bun.lock', 'bun.lockb'].map((name) => join(cwd, name)).find((path) => existsSync(path));
945
+ if (!lockfile) return { reason: 'lockfile-unavailable' };
946
+ let lockfileHash: string;
947
+ try { lockfileHash = sha256(readFileSync(lockfile)); }
948
+ catch { return { reason: 'lockfile-unreadable' }; }
949
+ const runtime = process.versions.bun ?? (globalThis as { Bun?: { version?: string } }).Bun?.version;
950
+ if (!runtime) return { reason: 'bun-runtime-unavailable' };
951
+ let environmentKey: string;
952
+ try { environmentKey = (deps.envKey ?? defaultGateEnvKey)(); }
953
+ catch { return { reason: 'environment-key-unavailable' }; }
954
+ const repositoryHash = sha256(repositoryUrl);
955
+ const receiptDir = deps.gateReceiptDir?.() ?? join(getElanousConfigDir(), 'gate-receipts');
956
+ const key = sha256(`${repositoryUrl}\0${branch}\0${baseSha}`);
957
+ return {
958
+ identity: {
959
+ schema: GATE_RECEIPT_SCHEMA, repositoryHash, branch, baseSha, headSha, runtime,
960
+ environmentKey, lockfileHash, receiptDir, receiptPath: join(receiptDir, `${key}.json`),
961
+ },
962
+ };
963
+ }
964
+
965
+ function pruneExpiredGateReceipts(receiptDir: string, now: number): void {
966
+ try {
967
+ for (const name of readdirSync(receiptDir)) {
968
+ if (!/^[a-f0-9]{64}\.json$/.test(name)) continue;
969
+ const path = join(receiptDir, name);
970
+ try {
971
+ const stat = lstatSync(path);
972
+ if (stat.isFile() && !stat.isSymbolicLink() && now - stat.mtimeMs > GATE_RECEIPT_TTL_MS) rmSync(path, { force: true });
973
+ } catch { /* a stale receipt disappearing concurrently is harmless */ }
974
+ }
975
+ } catch { /* the first receipt has no directory to prune */ }
976
+ }
977
+
978
+ function isGateReceipt(value: unknown): value is GateReceipt {
979
+ if (!value || typeof value !== 'object') return false;
980
+ const item = value as Partial<GateReceipt>;
981
+ return item.schema === GATE_RECEIPT_SCHEMA && typeof item.createdAt === 'number'
982
+ && typeof item.repositoryHash === 'string' && typeof item.branch === 'string'
983
+ && typeof item.baseSha === 'string' && /^[0-9a-f]{40}$/.test(item.baseSha)
984
+ && typeof item.headSha === 'string' && /^[0-9a-f]{40}$/.test(item.headSha)
985
+ && typeof item.runtime === 'string' && typeof item.environmentKey === 'string'
986
+ && typeof item.lockfileHash === 'string' && /^[0-9a-f]{64}$/.test(item.lockfileHash)
987
+ && Array.isArray(item.fullTestFiles) && item.fullTestFiles.every((path) => typeof path === 'string' && isGateTestFile(path))
988
+ && Array.isArray(item.failedTestFiles) && item.failedTestFiles.every((path) => typeof path === 'string' && isGateTestFile(path))
989
+ && typeof item.measured === 'boolean';
990
+ }
991
+
992
+ function rejectGateReceipt(cwd: string, reason: string, details: Record<string, unknown> = {}): GateReceiptDecision {
993
+ try { debug.log('self-implement', 'gate.receipt-inheritance-rejected', { reason, ...details }); } catch { /* telemetry must not alter the gate */ }
994
+ return { mode: 'full', reason };
995
+ }
996
+
997
+ function decideGateReceiptInheritance(
998
+ cwd: string,
999
+ options: SelfGateCliOptions,
1000
+ selection: ChangedFileSelection,
1001
+ fullTestFiles: readonly string[],
1002
+ deps: SelfGateCliDeps,
1003
+ ): GateReceiptDecision {
1004
+ // Existing injected-command fixtures stay isolated unless a test explicitly supplies a receipt directory.
1005
+ if (deps.runCommand && !deps.gateReceiptDir) return { mode: 'full', reason: 'injected-command-no-receipt-store' };
1006
+ const resolved = gateReceiptIdentity(cwd, selection, deps);
1007
+ if (!resolved.identity) return rejectGateReceipt(cwd, resolved.reason ?? 'receipt-identity-unavailable');
1008
+ const identity = resolved.identity;
1009
+ if (options.noInherit) {
1010
+ try { debug.log('self-implement', 'gate.receipt-inheritance-rejected', { reason: 'forced-full', baseSha: identity.baseSha, headSha: identity.headSha }); } catch { /* observation only */ }
1011
+ return { mode: 'full', reason: 'forced-full', identity };
1012
+ }
1013
+ const now = deps.now?.() ?? Date.now();
1014
+ pruneExpiredGateReceipts(identity.receiptDir, now);
1015
+ let prior: unknown;
1016
+ try {
1017
+ const stat = lstatSync(identity.receiptPath);
1018
+ if (!stat.isFile() || stat.isSymbolicLink()) return rejectGateReceipt(cwd, 'receipt-not-regular-file', { baseSha: identity.baseSha });
1019
+ prior = JSON.parse(readFileSync(identity.receiptPath, 'utf8'));
1020
+ } catch (error) {
1021
+ const code = (error as NodeJS.ErrnoException)?.code;
1022
+ return rejectGateReceipt(cwd, code === 'ENOENT' ? 'no-prior-receipt' : 'receipt-read-failed', { baseSha: identity.baseSha });
1023
+ }
1024
+ if (!isGateReceipt(prior)) return rejectGateReceipt(cwd, 'receipt-schema-invalid', { baseSha: identity.baseSha });
1025
+ if (now - prior.createdAt > GATE_RECEIPT_TTL_MS) {
1026
+ try { rmSync(identity.receiptPath, { force: true }); } catch { /* stale file can remain without affecting the full gate */ }
1027
+ return rejectGateReceipt(cwd, 'receipt-expired', { previousHead: prior.headSha });
1028
+ }
1029
+ if (prior.repositoryHash !== identity.repositoryHash || prior.branch !== identity.branch) return rejectGateReceipt(cwd, 'repository-or-branch-mismatch');
1030
+ if (prior.baseSha !== identity.baseSha) return rejectGateReceipt(cwd, 'base-sha-mismatch', { previousBase: prior.baseSha, currentBase: identity.baseSha });
1031
+ if (prior.runtime !== identity.runtime || prior.environmentKey !== identity.environmentKey) return rejectGateReceipt(cwd, 'runtime-mismatch', { previousRuntime: prior.runtime, currentRuntime: identity.runtime });
1032
+ if (prior.lockfileHash !== identity.lockfileHash) return rejectGateReceipt(cwd, 'lockfile-hash-mismatch');
1033
+ if (!prior.measured) return rejectGateReceipt(cwd, 'previous-test-run-unmeasured', { previousHead: prior.headSha });
1034
+ const ancestor = (deps.runCommand ?? defaultRunCommand)('git', ['merge-base', '--is-ancestor', prior.headSha, identity.headSha], cwd);
1035
+ if (ancestor.status !== 0 || ancestor.error) return rejectGateReceipt(cwd, 'previous-head-not-ancestor', { previousHead: prior.headSha, currentHead: identity.headSha });
1036
+
1037
+ const diff = (deps.runCommand ?? defaultRunCommand)('git', ['diff', '--name-only', `${prior.headSha}..${identity.headSha}`], cwd);
1038
+ if (diff.status !== 0 || diff.error || diff.stdout === undefined) return rejectGateReceipt(cwd, 'head-delta-unavailable', { previousHead: prior.headSha });
1039
+ const changedFiles = [...new Set(diff.stdout.split('\n').map((path) => normalizeGatePath(path.trim())).filter(Boolean))].sort();
1040
+ try {
1041
+ const deltaSelection = { files: changedFiles, baseRef: prior.headSha };
1042
+ const deltaOptions: GateSelectionOptions = { ...options, base: prior.headSha, pr: undefined };
1043
+ const deltaDeps: GateSelectionDeps = { ...deps, changedFiles: () => deltaSelection };
1044
+ const deltaPrepared = prepareGateTestSelection(cwd, deltaOptions, deltaDeps);
1045
+ if (deltaPrepared.lookupFailed || deltaPrepared.routeIndex?.lookupFailures.length) {
1046
+ return rejectGateReceipt(cwd, 'head-delta-test-radius-unmeasured', { previousHead: prior.headSha });
1047
+ }
1048
+ const deltaTests = finishGateTestSelection(deltaPrepared, deltaOptions, cwd, deltaDeps).testFiles;
1049
+ const current = new Set(fullTestFiles);
1050
+ const previous = new Set(prior.fullTestFiles);
1051
+ const previousFailures = new Set(prior.failedTestFiles);
1052
+ const changed = new Set(deltaTests);
1053
+ const runTestFiles = fullTestFiles.filter((path) => changed.has(path) || previousFailures.has(path) || !previous.has(path));
1054
+ const run = new Set(runTestFiles);
1055
+ const inheritedTestFiles = fullTestFiles.filter((path) => previous.has(path) && !previousFailures.has(path) && !run.has(path));
1056
+ // A current scope path not accounted for by the receipt is run, never silently inherited.
1057
+ for (const path of fullTestFiles) if (!previous.has(path) && !run.has(path)) return rejectGateReceipt(cwd, 'new-test-not-selected', { path });
1058
+ if (current.size !== fullTestFiles.length) return rejectGateReceipt(cwd, 'current-test-scope-duplicate');
1059
+ try {
1060
+ debug.log('self-implement', 'gate.receipt-inheritance-accepted', {
1061
+ previousHead: prior.headSha, currentHead: identity.headSha, baseSha: identity.baseSha,
1062
+ changedFiles, rerunTestFiles: runTestFiles, inheritedTestFiles,
1063
+ });
1064
+ } catch { /* observation only */ }
1065
+ return { mode: 'inherit', reason: 'matching-prior-receipt', identity, sourceHead: prior.headSha,
1066
+ runTestFiles, inheritedTestFiles };
1067
+ } catch (error) {
1068
+ return rejectGateReceipt(cwd, 'head-delta-test-radius-failed', { message: error instanceof Error ? error.message : String(error) });
1069
+ }
1070
+ }
1071
+
1072
+ function persistGateReceipt(cwd: string, capture: GateArtifactCapture, deps: SelfGateCliDeps): void {
1073
+ const decision = capture.receiptDecision;
1074
+ const identity = decision?.identity;
1075
+ if (!identity) return;
1076
+ if (deps.runCommand && !deps.gateReceiptDir) return;
1077
+ if (capture.testReceiptMeasured !== true || !capture.fullTestFiles || !capture.failedTestFiles) {
1078
+ try { debug.log('self-implement', 'gate.receipt-write-rejected', { reason: 'test-outcome-unmeasured', headSha: identity.headSha }); } catch { /* observation only */ }
1079
+ return;
1080
+ }
1081
+ const failed = [...new Set(capture.failedTestFiles)].filter((path) => capture.fullTestFiles!.includes(path)).sort();
1082
+ const receipt: GateReceipt = {
1083
+ schema: GATE_RECEIPT_SCHEMA, createdAt: deps.now?.() ?? Date.now(), repositoryHash: identity.repositoryHash,
1084
+ branch: identity.branch, baseSha: identity.baseSha, headSha: identity.headSha, runtime: identity.runtime,
1085
+ environmentKey: identity.environmentKey, lockfileHash: identity.lockfileHash,
1086
+ fullTestFiles: [...new Set(capture.fullTestFiles)].sort(), failedTestFiles: failed, measured: true,
1087
+ };
1088
+ const temporary = join(identity.receiptDir, `.${basename(identity.receiptPath)}.${process.pid}.${randomUUID()}.tmp`);
1089
+ try {
1090
+ mkdirSync(identity.receiptDir, { recursive: true, mode: 0o700 });
1091
+ pruneExpiredGateReceipts(identity.receiptDir, receipt.createdAt);
1092
+ writeFileSync(temporary, `${JSON.stringify(receipt, null, 2)}\n`, { flag: 'wx', mode: 0o600 });
1093
+ renameSync(temporary, identity.receiptPath);
1094
+ try { debug.log('self-implement', 'gate.receipt-written', { headSha: identity.headSha, baseSha: identity.baseSha, testFiles: receipt.fullTestFiles.length, failedTestFiles: failed.length }); } catch { /* observation only */ }
1095
+ } catch (error) {
1096
+ try { rmSync(temporary, { force: true }); } catch { /* best effort */ }
1097
+ try { debug.log('self-implement', 'gate.receipt-write-rejected', { reason: 'receipt-write-failed', message: error instanceof Error ? error.message : String(error) }); } catch { /* observation only */ }
1098
+ }
1099
+ }
1100
+
801
1101
  /** A completed bundle is observed immediately, before the synchronous runner returns. Each sink is best effort. */
802
1102
  function shardProgressObserver(cwd: string, options: SelfGateCliOptions, deps: SelfGateCliDeps): (progress: ShardRunProgress) => void {
803
1103
  const now = deps.now ?? Date.now;
@@ -823,17 +1123,27 @@ function shardProgressObserver(cwd: string, options: SelfGateCliOptions, deps: S
823
1123
  };
824
1124
  }
825
1125
 
826
- function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: SelfGateCliDeps, capture: GateArtifactCapture): SelfGateCliResult {
1126
+ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: SelfGateCliDeps, capture: GateArtifactCapture, asyncShards: boolean): SelfGateCliResult | Promise<SelfGateCliResult> {
827
1127
  if (options.base && options.pr) throw new Error('use either --base <ref> or --pr <number>, not both');
828
1128
  if (options.shards !== undefined && (!Number.isSafeInteger(options.shards) || options.shards < 1)) throw new Error('invalid --shards count');
1129
+ if (options.shardConcurrency !== undefined && (!Number.isSafeInteger(options.shardConcurrency) || options.shardConcurrency < 1 || options.shardConcurrency > 4)) throw new Error('invalid shard concurrency (expected 1–4)');
829
1130
  if (options.fixedShardDistribution && options.shards === undefined) throw new Error('--fixed-shard-distribution requires --shards <n>');
830
1131
  const prepared = prepareGateTestSelection(cwd, options, deps);
831
1132
  const { selection, lookupFailed, routeIndex, scope } = prepared;
832
1133
  const expose = publicExposureFiles(selection.files).length > 0
833
1134
  ? runExposeGate(cwd, selection.files, getUserConfig().harness?.exposeGate === 'strict' ? 'strict' : 'warn', deps.runCommand)
834
1135
  : { passed: true, log: '' };
835
- const { alwaysInclude, alwaysIncludeMissing, alwaysIncludeExtra, importerTestsAdded, scenarioTests, testFiles,
1136
+ const { alwaysInclude, alwaysIncludeMissing, alwaysIncludeExtra, importerTestsAdded, commentOnlySources, scenarioTests, testFiles: fullTestFiles,
836
1137
  skipTestStep, importerTestsNotRun, unrunImporterTotal, callerTestsOverflow, importerLookupFailed } = finishGateTestSelection(prepared, options, cwd, deps);
1138
+ const receiptDecision = options.base || options.pr || options.noInherit
1139
+ ? decideGateReceiptInheritance(cwd, options, selection, fullTestFiles, deps) : undefined;
1140
+ if (receiptDecision && !receiptDecision.identity && (!deps.runCommand || deps.gateReceiptDir)) {
1141
+ receiptDecision.identity = gateReceiptIdentity(cwd, selection, deps).identity;
1142
+ }
1143
+ const testFiles = receiptDecision?.mode === 'inherit' ? [...(receiptDecision.runTestFiles ?? fullTestFiles)] : [...fullTestFiles];
1144
+ capture.fullTestFiles = [...fullTestFiles];
1145
+ capture.receiptDecision = receiptDecision;
1146
+ const relatedTestFiles = [...new Set([...selection.files.filter(isTestPath), ...(scope.testArgs ?? []), ...importerTestsAdded])];
837
1147
  const lines = [
838
1148
  // ⛔⭐ 「changed=0」을 «초록»으로 읽는 사고가 났다(2026-09-02 · 🅕 보고 · 🅣 재현).
839
1149
  // 커밋 «전»에 돌리면 작업 트리 변경은 «안 세므로» changed=0 이 나오는데,
@@ -842,7 +1152,10 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
842
1152
  + (selection.files.length === 0 && (selection.ignoredDirtyPaths?.length ?? 0) > 0
843
1153
  ? ` ⚠️ 센 것이 0인데 «커밋 안 된» 변경 ${selection.ignoredDirtyPaths!.length}개가 있다 — 「통과」가 아니라 「안 쟀다」다(커밋 뒤 다시 돌려라)`
844
1154
  : ''),
845
- `scope: ${scope.testArgs?.join(', ') ?? '(test step skipped)'}`,
1155
+ `scope: ${receiptDecision?.mode === 'inherit' ? testFiles.join(', ') || '(all tests inherited)' : scope.testArgs?.join(', ') ?? '(test step skipped)'}`,
1156
+ ...(receiptDecision ? [receiptDecision.mode === 'inherit'
1157
+ ? `gate receipt: inherited ${receiptDecision.inheritedTestFiles?.length ?? 0} · rerun ${testFiles.length} · source head ${receiptDecision.sourceHead?.slice(0, 12) ?? '(unknown)'}`
1158
+ : `gate receipt: full radius (${receiptDecision.reason})`] : []),
846
1159
  `ignored unrelated worktree changes: ${selection.ignoredDirtyPaths === undefined ? '(not checked)' : selection.ignoredDirtyPaths.join(', ') || '(none)'}`,
847
1160
  `unverified: ${scope.unverified.length} (${scope.unverified.join(', ') || '(none)'})`,
848
1161
  `elanous runtime artifacts: ${scope.elanousRuntimeArtifacts.length} (${scope.elanousRuntimeArtifacts.join(', ') || '(none)'})`,
@@ -870,6 +1183,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
870
1183
  ...(options.includeImporterTests
871
1184
  ? [`importer tests added: ${lookupFailed ? `lookup failed (${lookupFailed})` : `${importerTestsAdded.length} (reason=changed-source-importer${importerTestsAdded.length ? ` · ${importerTestsAdded.join(', ')}` : ''})`}`]
872
1185
  : []),
1186
+ ...(commentOnlySources.length ? [`comment-only importer expansion excluded: ${commentOnlySources.join(', ')}`] : []),
873
1187
  ...(options.scenario !== undefined || options.scenarioFile !== undefined ? [`scenario tests: ${scenarioTests.length} (${scenarioTests.join(', ')})`] : []),
874
1188
  ];
875
1189
  if (expose.log) lines.push(expose.log);
@@ -896,12 +1210,46 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
896
1210
  // 🍎 iOS 축 — 안드로이드와 «같은 자리»에 둔다(skipTestStep 앞). Swift 만 바뀐 PR 도 여기서 조기 리턴한다.
897
1211
  const iosPassed = runAdditionalGate('ios-gate', deps.runIosGate ?? runIosUnitTestGate, selection.files, cwd, lines);
898
1212
  const pwaPassed = runAdditionalGate('pwa-gate', deps.runPwaGate ?? runPwaBuildGate, selection.files, cwd, lines);
1213
+ let entryBudgetPassed = false;
1214
+ try {
1215
+ const budget = (deps.runEntryBudgetGate ?? ((dir, files) => {
1216
+ const affected = entryBudgetAffected(files);
1217
+ return { affected, errors: affected ? auditEntryBudget(dir).errors : [] };
1218
+ }))(cwd, selection.files);
1219
+ entryBudgetPassed = budget.errors.length === 0;
1220
+ lines.push(budget.affected
1221
+ ? `next-tui-entry-budget: ${entryBudgetPassed ? 'pass' : `FAIL ${budget.errors.join('; ')}`}`
1222
+ : 'next-tui-entry-budget: skip (unrelated changes)');
1223
+ } catch (error) {
1224
+ lines.push(`next-tui-entry-budget: UNMEASURED ${error instanceof Error ? error.message : String(error)}`);
1225
+ }
1226
+
1227
+ if (receiptDecision?.mode === 'inherit' && testFiles.length === 0 && fullTestFiles.length > 0) {
1228
+ capture.testReceiptMeasured = true;
1229
+ capture.failedTestFiles = [];
1230
+ capture.verdict = 'passed';
1231
+ const testLine = formatPartialObservationNote(unrunImporterTotal ?? 0,
1232
+ `tests: pass (${receiptDecision.inheritedTestFiles?.length ?? 0} files inherited from ${receiptDecision.sourceHead?.slice(0, 12) ?? 'prior receipt'})`);
1233
+ lines.push(testLine);
1234
+ capture.verdictLine = testLine;
1235
+ const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
1236
+ logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
1237
+ return {
1238
+ exitCode: policyPassed && androidPassed && iosPassed && pwaPassed && entryBudgetPassed && expose.passed ? 0 : 1,
1239
+ lines, changedFiles: selection.files, testFiles, unverified: scope.unverified,
1240
+ documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests,
1241
+ alwaysIncludeMissing, importerTestsAdded,
1242
+ baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 },
1243
+ };
1244
+ }
899
1245
 
900
1246
  if (skipTestStep) {
901
1247
  const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
1248
+ capture.testReceiptMeasured = false;
1249
+ capture.failedTestFiles = [];
902
1250
  logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
903
1251
  Object.assign(capture, { verdict: 'skipped', artifactsUnavailable: 'no-tests' } satisfies GateArtifactCapture);
904
- return { exitCode: androidPassed && iosPassed && pwaPassed && policyPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles: [], unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
1252
+ return { exitCode: androidPassed && iosPassed && pwaPassed && entryBudgetPassed && policyPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles: [], unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
905
1253
  }
906
1254
 
907
1255
  // The default direct Bun path has one process and one 300s limit. Route real child/PTY tests through
@@ -909,99 +1257,124 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
909
1257
  if (options.shards !== undefined || testFiles.some(isGateSpawnLaneFile)) {
910
1258
  const spawnFileCount = testFiles.filter(isGateSpawnLaneFile).length;
911
1259
  const shardCount = options.shards ?? (Math.min(3, spawnFileCount) + Number(testFiles.length > spawnFileCount));
912
- const runShards = deps.runShards ?? runShardedGateTests;
913
1260
  const onShardComplete = shardProgressObserver(cwd, options, deps);
914
- const sharded = options.fixedShardDistribution
915
- ? runShards(cwd, testFiles, selection.baseRef, shardCount, undefined, undefined, undefined, { fixedDistribution: true, onShardComplete })
916
- : runShards(cwd, testFiles, selection.baseRef, shardCount, undefined, undefined, undefined, { onShardComplete });
917
- capture.sharded = sharded;
918
- capture.verdict = sharded.aggregate.status;
919
- lines.push(`shards: ${sharded.shards.length} (${sharded.shards.map((shard) => `${shard.id}=${shard.files.join(',')}`).join('; ')})${sharded.expandedFrom !== undefined ? ` · RSS 예산상 ${sharded.expandedFrom}→${sharded.shards.length} 자동 확장` : ''}${sharded.measurementFailures ? ` · 측정 실패 ${sharded.measurementFailures}` : ''}${options.fixedShardDistribution ? ' · 고정 분배(사전 측정 없음)' : ''}${sharded.distribution === 'fixed-cap-fallback' ? ` · 호스트 상한 자동 고정 분배(${sharded.fallbackReason})` : ''}`);
920
- // 조각이 «못 쟀다»일 때 이유가 줄에 없으면 자리·시간 초과·죽음을 가를 수 없다(OP 10-09 light RC) — 종료 코드·신호를 같이 싣는다.
921
- const side = (code: number | null, signal: string | null | undefined, junit: string | undefined) => signal ? `signal ${signal}` : code === null ? 'exit ?' : `exit ${code}${junit === undefined ? ' · junit 없음' : ''}`;
922
- for (const attempt of sharded.attempts) {
923
- const plannedFiles = sharded.shards.find((shard) => shard.id === attempt.shardId)?.files;
924
- const baselineFiles = attempt.baselineFiles;
925
- const baselineDifference = baselineFiles && plannedFiles && (baselineFiles.length !== plannedFiles.length || baselineFiles.some((file, index) => file !== plannedFiles[index]))
926
- ? ` · 기준 파일 ${baselineFiles.join(',') || '(none)'}` : '';
927
- lines.push(`shard attempt: ${attempt.shardId} #${attempt.attempt} · 지금 ${side(attempt.currentExitCode, attempt.currentSignal, attempt.currentJUnit)} · 기준 ${side(attempt.baselineExitCode, attempt.baselineSignal, attempt.baselineJUnit)} · 파일 ${plannedFiles?.join(',') ?? '(unknown)'}${baselineDifference}`);
928
- const renderDiagnostic = (value: string): string => redactSecretText(value).replace(/[\r\n\t\x00-\x1f\x7f]+/g, ' ').slice(0, 500);
929
- if (attempt.currentJUnit === undefined && attempt.currentDiagnostic) lines.push(`shard diagnostic: ${attempt.shardId} #${attempt.attempt} 지금 · ${renderDiagnostic(attempt.currentDiagnostic)}`);
930
- if (attempt.baselineJUnit === undefined && attempt.baselineDiagnostic) lines.push(`shard diagnostic: ${attempt.shardId} #${attempt.attempt} 기준 · ${renderDiagnostic(attempt.baselineDiagnostic)}`);
931
- }
932
- // OP FU (MK #8178 shard-9) — 실패 조각의 자식 출력 꼬리 ⊕ exit/signal 을 파일로 남긴다(관측만 · 판정·exit 불변).
933
- // --artifact-dir 이 있으면 그 아래, 없으면 임시 디렉토리(JUnit 임시 디렉토리 옆 tmpdir)에.
934
- if (sharded.failureEvidence?.length) {
935
- try {
936
- const evidenceDir = options.artifactDir?.trim() ? resolveArtifactDir(options.artifactDir, cwd) : mkdtempSync(join(tmpdir(), 'elanous-shard-failure-'));
937
- for (const path of writeShardFailureEvidence(evidenceDir, sharded.failureEvidence)) lines.push(`shard failure evidence: ${path}`);
938
- } catch (error) {
939
- lines.push(`⚠ shard failure evidence: 못 썼다 — ${error instanceof Error ? error.message : String(error)} (판정은 그대로다)`);
1261
+ const mode = { ...(options.fixedShardDistribution ? { fixedDistribution: true } : {}), onShardComplete,
1262
+ ...(options.shardConcurrency !== undefined ? { concurrency: options.shardConcurrency } : {}) };
1263
+ const runResult = asyncShards
1264
+ ? (deps.runShardsAsync ?? runShardedGateTestsAsync)(cwd, testFiles, selection.baseRef, shardCount, undefined, undefined, undefined, mode)
1265
+ : (deps.runShards ?? runShardedGateTests)(cwd, testFiles, selection.baseRef, shardCount, undefined, undefined, undefined, mode);
1266
+ const finishShardedGate = (sharded: ShardRunResult): SelfGateCliResult => {
1267
+ capture.sharded = sharded;
1268
+ capture.verdict = sharded.aggregate.status;
1269
+ lines.push(`shards: ${sharded.shards.length} (${sharded.shards.map((shard) => `${shard.id}=${shard.files.join(',')}`).join('; ')})${sharded.expandedFrom !== undefined ? ` · RSS 예산상 ${sharded.expandedFrom}→${sharded.shards.length} 자동 확장` : ''}${sharded.measurementFailures ? ` · 측정 실패 ${sharded.measurementFailures}` : ''}${options.fixedShardDistribution ? ' · 고정 분배(사전 측정 없음)' : ''}${sharded.distribution === 'fixed-cap-fallback' ? ` · 호스트 상한 자동 고정 분배(${sharded.fallbackReason})` : ''}${sharded.concurrency !== undefined ? ` · 동시성 ${sharded.concurrency} (${sharded.concurrencyReason ?? 'reason unavailable'})` : ''}${sharded.measurementMs !== undefined ? ` · RSS 사전 측정 ${(sharded.measurementMs / 1000).toFixed(1)}s · 묶음 ${((sharded.bundleMs ?? 0) / 1000).toFixed(1)}s · currentΣ ${((sharded.currentProcessMs ?? 0) / 1000).toFixed(1)}s · baselineΣ ${((sharded.baselineProcessMs ?? 0) / 1000).toFixed(1)}s` : ''}`);
1270
+ // 조각이 «못 쟀다»일 때 이유가 줄에 없으면 자리·시간 초과·죽음을 가를 수 없다(OP 10-09 light RC) — 종료 코드·신호를 같이 싣는다.
1271
+ const side = (code: number | null, signal: string | null | undefined, junit: string | undefined) => signal ? `signal ${signal}` : code === null ? 'exit ?' : `exit ${code}${junit === undefined ? ' · junit 없음' : ''}`;
1272
+ for (const attempt of sharded.attempts) {
1273
+ const plannedFiles = sharded.shards.find((shard) => shard.id === attempt.shardId)?.files;
1274
+ const baselineFiles = attempt.baselineFiles;
1275
+ const baselineDifference = baselineFiles && plannedFiles && (baselineFiles.length !== plannedFiles.length || baselineFiles.some((file, index) => file !== plannedFiles[index]))
1276
+ ? ` · 기준 파일 ${baselineFiles.join(',') || '(none)'}` : '';
1277
+ lines.push(`shard attempt: ${attempt.shardId} #${attempt.attempt} · 지금 ${side(attempt.currentExitCode, attempt.currentSignal, attempt.currentJUnit)} · 기준 ${side(attempt.baselineExitCode, attempt.baselineSignal, attempt.baselineJUnit)} · 파일 ${plannedFiles?.join(',') ?? '(unknown)'}${baselineDifference}`);
1278
+ const renderDiagnostic = (value: string): string => redactSecretText(value).replace(/[\r\n\t\x00-\x1f\x7f]+/g, ' ').slice(0, 500);
1279
+ if (attempt.currentJUnit === undefined && attempt.currentDiagnostic) lines.push(`shard diagnostic: ${attempt.shardId} #${attempt.attempt} 지금 · ${renderDiagnostic(attempt.currentDiagnostic)}`);
1280
+ if (attempt.baselineJUnit === undefined && attempt.baselineDiagnostic) lines.push(`shard diagnostic: ${attempt.shardId} #${attempt.attempt} 기준 · ${renderDiagnostic(attempt.baselineDiagnostic)}`);
940
1281
  }
941
- }
942
- const { aggregate } = sharded;
943
- let shardBaseline: SelfGateCliResult['baseline'];
944
- let unmeasuredReason: string | undefined;
945
- if (aggregate.status === 'unmeasured') {
946
- unmeasuredReason = sharded.reason
947
- ? redactSecretText(sharded.reason).replace(/[\r\n\t\x00-\x1f\x7f]+/g, ' ').slice(0, 500)
948
- : aggregate.retryShardIds.join(', ') || 'no complete JUnit';
949
- for (const shardId of aggregate.retryShardIds) {
950
- lines.push(`shard unmeasured: ${shardId} · ${sharded.unmeasuredByShard?.[shardId] ?? sharded.reason ?? 'cause unavailable'}`);
1282
+ // OP FU (MK #8178 shard-9) — 실패 조각의 자식 출력 꼬리 ⊕ exit/signal 을 파일로 남긴다(관측만 · 판정·exit 불변).
1283
+ // --artifact-dir 이 있으면 그 아래, 없으면 임시 디렉토리(JUnit 임시 디렉토리 옆 tmpdir)에.
1284
+ if (sharded.failureEvidence?.length) {
1285
+ try {
1286
+ const evidenceDir = options.artifactDir?.trim() ? resolveArtifactDir(options.artifactDir, cwd) : mkdtempSync(join(tmpdir(), 'elanous-shard-failure-'));
1287
+ for (const path of writeShardFailureEvidence(evidenceDir, sharded.failureEvidence)) lines.push(`shard failure evidence: ${path}`);
1288
+ } catch (error) {
1289
+ lines.push(`⚠ shard failure evidence: 못 썼다 — ${error instanceof Error ? error.message : String(error)} (판정은 그대로다)`);
1290
+ }
951
1291
  }
952
- lines.push(`shards: unmeasured (${unmeasuredReason})`);
953
- if (sharded.baselineStderrTail) lines.push(`baseline worktree-add git stderr: ${sharded.baselineStderrTail}`);
954
- capture.unmeasuredReason = unmeasuredReason;
955
- }
956
- else if (aggregate.report) {
957
- const report = recheckTimeoutOnlyIntroducedFailures(cwd, aggregate.report, deps.runTimeoutRecheck);
958
- capture.timeoutRechecks = report.timeoutRechecks;
959
- const timeoutRecheckResolvedFailure = aggregate.status === 'failed'
960
- && (report.timeoutRecheckPassed ?? 0) > 0
961
- && report.introduced === 0 && report.unknown === 0 && report.preconditionUnmet === 0
962
- && report.timedOut === 0 && report.flakyRerun === 0 && report.worktreeFailuresParsed
963
- && report.baselineStatus !== 'unknown';
964
- const effectiveStatus = timeoutRecheckResolvedFailure ? 'passed' : aggregate.status;
965
- capture.verdict = effectiveStatus;
966
- logGateCliBaseline(cwd, {
967
- introduced: report.introduced, preexisting: report.preexisting, unknown: report.unknown,
968
- preconditionUnmet: report.preconditionUnmet, timedOut: report.timedOut,
969
- timeoutPassedAtBase: report.timeoutPassedAtBase, failures: report.failures.slice(0, 20),
970
- baselineFiles: report.files, baselineStatus: report.baselineStatus, unrunImporterTotal, lookupFailed: importerLookupFailed,
971
- });
972
- lines.push(formatPartialObservationNote(unrunImporterTotal ?? 0, formatGateBaselineNote(report, unrunImporterTotal ?? 0)));
973
- shardBaseline = { introduced: report.introduced, preexisting: report.preexisting, unknown: report.unknown, preconditionUnmet: report.preconditionUnmet };
974
- } else {
975
- lines.push(formatPartialObservationNote(unrunImporterTotal ?? 0, `tests: pass (${testFiles.length} files)`));
976
- logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
977
- shardBaseline = { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 };
978
- }
979
- capture.verdictLine = lines[lines.length - 1];
980
- const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
981
- return {
982
- exitCode: capture.verdict !== 'passed' || !policyPassed || !androidPassed || !iosPassed || !pwaPassed || !expose.passed ? 1 : 0,
983
- lines, changedFiles: selection.files, testFiles, unverified: scope.unverified,
984
- documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests,
985
- alwaysIncludeMissing, importerTestsAdded, ...(shardBaseline ? { baseline: shardBaseline } : {}),
986
- ...(unmeasuredReason !== undefined ? { unmeasuredReason } : {}),
1292
+ const { aggregate } = sharded;
1293
+ let shardBaseline: SelfGateCliResult['baseline'];
1294
+ let unmeasuredReason: string | undefined;
1295
+ if (aggregate.status === 'unmeasured') {
1296
+ capture.testReceiptMeasured = false;
1297
+ capture.failedTestFiles = [];
1298
+ unmeasuredReason = sharded.reason
1299
+ ? redactSecretText(sharded.reason).replace(/[\r\n\t\x00-\x1f\x7f]+/g, ' ').slice(0, 500)
1300
+ : aggregate.retryShardIds.join(', ') || 'no complete JUnit';
1301
+ for (const shardId of aggregate.retryShardIds) {
1302
+ lines.push(`shard unmeasured: ${shardId} · ${sharded.unmeasuredByShard?.[shardId] ?? sharded.reason ?? 'cause unavailable'}`);
1303
+ }
1304
+ lines.push(`shards: unmeasured (${unmeasuredReason})`);
1305
+ if (sharded.baselineStderrTail) lines.push(`baseline worktree-add git stderr: ${sharded.baselineStderrTail}`);
1306
+ capture.unmeasuredReason = unmeasuredReason;
1307
+ }
1308
+ else if (aggregate.report) {
1309
+ const timeoutReport = recheckTimeoutOnlyIntroducedFailures(cwd, aggregate.report, deps.runTimeoutRecheck);
1310
+ const report = deps.runShards || deps.runShardsAsync
1311
+ ? deps.runInterferenceRecheck?.(cwd, timeoutReport, selection.baseRef, relatedTestFiles) ?? timeoutReport
1312
+ : (deps.runInterferenceRecheck ?? recheckOutsideScopeFailures)(cwd, timeoutReport, selection.baseRef, relatedTestFiles);
1313
+ capture.timeoutRechecks = report.timeoutRechecks;
1314
+ capture.interferenceRechecks = report.interferenceRechecks;
1315
+ const timeoutRecheckResolvedFailure = aggregate.status === 'failed'
1316
+ && (report.loadTimeout ?? 0) > 0
1317
+ && report.introduced === 0 && report.unknown === 0 && report.preconditionUnmet === 0
1318
+ && report.timedOut === 0 && report.flakyRerun === 0 && report.worktreeFailuresParsed
1319
+ && report.baselineStatus !== 'unknown';
1320
+ const effectiveStatus = timeoutRecheckResolvedFailure ? 'passed' : aggregate.status;
1321
+ capture.verdict = effectiveStatus;
1322
+ capture.testReceiptMeasured = report.unknown === 0 && report.preconditionUnmet === 0 && report.worktreeFailuresParsed;
1323
+ capture.failedTestFiles = [...new Set(report.failures.map((failure) => failure.file).filter((file): file is string => typeof file === 'string'))];
1324
+ logGateCliBaseline(cwd, {
1325
+ introduced: report.introduced, preexisting: report.preexisting, unknown: report.unknown,
1326
+ preconditionUnmet: report.preconditionUnmet, timedOut: report.timedOut,
1327
+ timeoutPassedAtBase: report.timeoutPassedAtBase, failures: report.failures.slice(0, 20),
1328
+ baselineFiles: report.files, baselineStatus: report.baselineStatus, unrunImporterTotal, lookupFailed: importerLookupFailed,
1329
+ });
1330
+ lines.push(formatPartialObservationNote(unrunImporterTotal ?? 0, formatGateBaselineNote(report, unrunImporterTotal ?? 0)));
1331
+ shardBaseline = { introduced: report.introduced, preexisting: report.preexisting, unknown: report.unknown, preconditionUnmet: report.preconditionUnmet };
1332
+ } else {
1333
+ capture.testReceiptMeasured = true;
1334
+ capture.failedTestFiles = [];
1335
+ lines.push(formatPartialObservationNote(unrunImporterTotal ?? 0, `tests: pass (${testFiles.length} files)`));
1336
+ logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
1337
+ shardBaseline = { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 };
1338
+ }
1339
+ capture.verdictLine = lines[lines.length - 1];
1340
+ const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
1341
+ return {
1342
+ exitCode: capture.verdict !== 'passed' || !policyPassed || !androidPassed || !iosPassed || !pwaPassed || !entryBudgetPassed || !expose.passed ? 1 : 0,
1343
+ lines, changedFiles: selection.files, testFiles, unverified: scope.unverified,
1344
+ documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests,
1345
+ alwaysIncludeMissing, importerTestsAdded, ...(shardBaseline ? { baseline: shardBaseline } : {}),
1346
+ ...(unmeasuredReason !== undefined ? { unmeasuredReason } : {}),
1347
+ };
987
1348
  };
1349
+ return runResult instanceof Promise ? runResult.then(finishShardedGate) : finishShardedGate(runResult);
988
1350
  }
989
1351
 
990
1352
  const test = (deps.runTests ?? ((dir, files) => (deps.runCommand ?? defaultRunCommand)('bun', ['test', ...files], dir)))(cwd, testFiles);
991
1353
  const worktreeLog = formatProcessOutput(test);
992
1354
  Object.assign(capture, { unshardedRc: test.status, artifactsUnavailable: 'unsharded' } satisfies GateArtifactCapture);
993
1355
  if (test.status === 0 && !test.error) {
1356
+ capture.testReceiptMeasured = true;
1357
+ capture.failedTestFiles = [];
994
1358
  lines.push(formatPartialObservationNote(unrunImporterTotal ?? 0, `tests: pass (${testFiles.length} files)`));
995
1359
  Object.assign(capture, { verdict: 'passed', verdictLine: lines[lines.length - 1] } satisfies GateArtifactCapture);
996
1360
  const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
997
1361
  logGateCliBaseline(cwd, { ...ZERO_GATE_BASELINE, unrunImporterTotal, lookupFailed: importerLookupFailed });
998
- return { exitCode: policyPassed && androidPassed && iosPassed && pwaPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
1362
+ return { exitCode: policyPassed && androidPassed && iosPassed && pwaPassed && entryBudgetPassed && expose.passed ? 0 : 1, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: 0, preexisting: 0, unknown: 0, preconditionUnmet: 0 } };
999
1363
  }
1000
1364
 
1001
1365
  if (worktreeLog.includes('deterministic environment setup failed')) lines.push(worktreeLog);
1002
1366
  const baseline = (deps.runBaseline ?? runGateBaseline)(cwd, testFiles, selection.baseRef);
1003
- const report = recheckTimeoutOnlyIntroducedFailures(cwd, buildGateBaselineReport(worktreeLog, baseline), deps.runTimeoutRecheck);
1367
+ // An injected runner can represent a virtual checkout; only the real runner may use this host's file tree.
1368
+ const currentFileExists = deps.runTests ? undefined : (file: string) => existsSync(resolve(cwd, file));
1369
+ const timeoutReport = recheckTimeoutOnlyIntroducedFailures(cwd,
1370
+ buildGateBaselineReport(worktreeLog, baseline, undefined, 0, currentFileExists), deps.runTimeoutRecheck);
1371
+ const report = deps.runTests
1372
+ ? deps.runInterferenceRecheck?.(cwd, timeoutReport, selection.baseRef, relatedTestFiles) ?? timeoutReport
1373
+ : (deps.runInterferenceRecheck ?? recheckOutsideScopeFailures)(cwd, timeoutReport, selection.baseRef, relatedTestFiles);
1004
1374
  capture.timeoutRechecks = report.timeoutRechecks;
1375
+ capture.interferenceRechecks = report.interferenceRechecks;
1376
+ capture.testReceiptMeasured = report.unknown === 0 && report.preconditionUnmet === 0 && report.worktreeFailuresParsed;
1377
+ capture.failedTestFiles = [...new Set(report.failures.map((failure) => failure.file).filter((file): file is string => typeof file === 'string'))];
1005
1378
  logGateCliBaseline(cwd, {
1006
1379
  introduced: report.introduced,
1007
1380
  preexisting: report.preexisting,
@@ -1021,7 +1394,7 @@ function runSelfGateCliCore(cwd: string, options: SelfGateCliOptions, deps: Self
1021
1394
  verdictLine: lines[lines.length - 1],
1022
1395
  } satisfies GateArtifactCapture);
1023
1396
  const policyPassed = runPolicyGates(selection.files, cwd, lines, deps);
1024
- const exitCode = !androidPassed || !iosPassed || !pwaPassed || !policyPassed || !expose.passed || report.introduced > 0 || report.unknown > 0 || report.preconditionUnmet > 0 ? 1 : 0;
1397
+ const exitCode = !androidPassed || !iosPassed || !pwaPassed || !entryBudgetPassed || !policyPassed || !expose.passed || report.introduced > 0 || report.unknown > 0 || report.preconditionUnmet > 0 ? 1 : 0;
1025
1398
  return { exitCode, lines, changedFiles: selection.files, testFiles, unverified: scope.unverified, documentPaths: scope.documentPaths, documentsWithoutDerivedTests: scope.documentsWithoutDerivedTests, alwaysIncludeMissing, importerTestsAdded, baseline: { introduced: report.introduced, preexisting: report.preexisting, unknown: report.unknown, preconditionUnmet: report.preconditionUnmet } };
1026
1399
  }
1027
1400