elanous 0.2.21 → 0.2.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (780) hide show
  1. package/NOTICE +7 -0
  2. package/README.md +32 -22
  3. package/apps/pwa/out/404/index.html +1 -1
  4. package/apps/pwa/out/404.html +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{119fc678.6f591cdb84ca5791.js → 0673cc54.8e2ef1c23e49e190.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{a9f2b54d-40c16bd0efdb04b8.js → 0a09e062-34f747a17d8d8c2e.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/{f8626309.a4e5d362b1d55e59.js → 0e3acd34.d42b2ef87fdf4234.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +77 -0
  9. package/apps/pwa/out/_next/static/chunks/{7175-350f4ce2873bc038.js → 1325-dc3f3c21eb181cb4.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +34 -0
  11. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +24 -0
  12. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/{6767.8e6c5f6e744fcd9f.js → 1505.5826671109111e75.js} +2 -2
  14. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 1669-da843ed73aa301f5.js} +1 -1
  21. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +36 -0
  23. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +122 -0
  24. package/apps/pwa/out/_next/static/chunks/2528.0af5c0e1fad88df6.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +62 -0
  27. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/272-b23d2e92161d11fd.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{7899.597af4a9996c907f.js → 2721.bc9a8f36bd85c07a.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +149 -0
  35. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3961-fbef064c213b2b18.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +309 -0
  39. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{d70879db.c66c56a95a91efc6.js → 4c5e95ce.83e9b16add6fcd8c.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/{6158.566c890adc06a459.js → 5313.1697309c532b9856.js} +2 -2
  52. package/apps/pwa/out/_next/static/chunks/{79b78388.663188133449d707.js → 53746282.1be36038d1abd949.js} +1 -1
  53. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5578.ac963634373b28c6.js +286 -0
  56. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5967-c0a80f8ffe5d4050.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 5974.360f8441eb0ac1ec.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +74 -0
  64. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/6571-926ddf024a6ad5df.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +64 -0
  69. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/{9832.2ab2e818013574c7.js → 6702.ebbd165d5e4a4a14.js} +1 -1
  71. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +32 -0
  73. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +93 -0
  78. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 740.90b31555290236a9.js} +2 -2
  83. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +148 -0
  84. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +226 -0
  85. package/apps/pwa/out/_next/static/chunks/{9070.067c106528ec1ae6.js → 7518.49161e8f5814abdb.js} +1 -1
  86. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +27 -0
  87. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +115 -0
  90. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7905.b230b9d06cb4ad5d.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{8194.484f51e273d9abd2.js → 8264.00e434fbd02e9311.js} +16 -16
  97. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +8 -0
  99. package/apps/pwa/out/_next/static/chunks/{088d8e8a.8069543d082bec12.js → 83cfc5c8.349535543c1548b6.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +23 -0
  101. package/apps/pwa/out/_next/static/chunks/{1948.5f35b39eef222a94.js → 8438.ee7f0df3b3f6fcb4.js} +1 -1
  102. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/{4588.ad3364cb7fb97ada.js → 8532.a86e99acf9b761cb.js} +2 -2
  105. package/apps/pwa/out/_next/static/chunks/8569.b853a8daa8f31d12.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8925-2abfb48af477fb7f.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{88729267.9c6c000157c83f2f.js → 89849432.9eaa2f4c9c010965.js} +3 -3
  110. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +90 -0
  111. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +94 -0
  112. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +41 -0
  114. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +287 -0
  116. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +79 -0
  117. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{3522-1de1319d028ac89c.js → 9502-32c5dc22e8f120f5.js} +3 -3
  120. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +104 -0
  123. package/apps/pwa/out/_next/static/chunks/{7630.2b9a68659053ff4e.js → 9976.8f28864317639fe6.js} +16 -16
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d5341ac96203a983.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-0160ab83c8685a12.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-55c631c032dcc47e.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ad3bd8084048bee4.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-e6784759a2531031.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5c5d0e370f495ef6.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-c325e21543cd48a8.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/{page-111cabe4d1fd69ae.js → page-6168a7c43e6ef8f5.js} +1 -1
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-31417d3604154a6d.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-e9606dc0bdec9305.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-a648bc464c9dc754.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-25bb425afdb27541.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-32d72fdef1afe11a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-d27b794c8ba76bbb.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-2bd9ce9c020d02d4.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-a34096245e63b9f2.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-22170f4f00a15496.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/page-4cc66d22ca4ec502.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83b14c729fcea837.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-6e2781c523dad761.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-26dd415c8f13f341.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-ccdb83ed40c8d724.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-7ad3de8fa06fdea9.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-015c02c4fec4023e.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-6b0ae5b5c42f6d2f.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-786111f30b6f0969.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-48fb31810693c357.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e17cce5e2ed0fee.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-cb154acadb025414.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-16258e956ea93fc2.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-c2dd2b19c93f90ab.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f35dd1dd96ae87.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d3c007c8a0ddd7ee.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7837ce2aacb97b04.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-7350ee93f4fe1033.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-00723458575f2b19.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-745d9b6c015076f8.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-736d33c7414a8a1a.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-119be9a0444d2482.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-fa806c018833e332.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/page-c782041b5f5199ba.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-d431fbdea6ad93dd.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-0c056abff82b9891.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-242d668e4fbf72c4.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-847c3de6ca8a4416.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-81dd0d8ae923ed72.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-74e69ba2c8e970d4.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-70038f41ae7cf931.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/b4e12462-5fab4a813a63dadd.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → ce383d63.d2ede338788ed18e.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/{framework-5c169757551134ed.js → framework-b2763b10dc6b3836.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +1 -0
  184. package/apps/pwa/out/_next/static/css/5619d59e87eddf66.css +1 -0
  185. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +1 -0
  186. package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_buildManifest.js +1 -1
  187. package/apps/pwa/out/approvals/index.html +1 -1
  188. package/apps/pwa/out/approvals/index.txt +23 -23
  189. package/apps/pwa/out/autopilot/index.html +1 -1
  190. package/apps/pwa/out/autopilot/index.txt +23 -23
  191. package/apps/pwa/out/board/index.html +1 -1
  192. package/apps/pwa/out/board/index.txt +23 -23
  193. package/apps/pwa/out/botlab/index.html +1 -1
  194. package/apps/pwa/out/botlab/index.txt +22 -22
  195. package/apps/pwa/out/bots/index.html +1 -1
  196. package/apps/pwa/out/bots/index.txt +22 -22
  197. package/apps/pwa/out/ceo/index.html +1 -1
  198. package/apps/pwa/out/ceo/index.txt +23 -23
  199. package/apps/pwa/out/chat/index.html +1 -1
  200. package/apps/pwa/out/chat/index.txt +22 -22
  201. package/apps/pwa/out/consult/index.html +1 -1
  202. package/apps/pwa/out/consult/index.txt +23 -23
  203. package/apps/pwa/out/control/index.html +1 -1
  204. package/apps/pwa/out/control/index.txt +23 -23
  205. package/apps/pwa/out/decisions/index.html +1 -1
  206. package/apps/pwa/out/decisions/index.txt +22 -22
  207. package/apps/pwa/out/design-check/index.html +1 -1
  208. package/apps/pwa/out/design-check/index.txt +23 -23
  209. package/apps/pwa/out/editor/index.html +1 -1
  210. package/apps/pwa/out/editor/index.txt +24 -23
  211. package/apps/pwa/out/exec/index.html +1 -1
  212. package/apps/pwa/out/exec/index.txt +23 -23
  213. package/apps/pwa/out/field/index.html +1 -1
  214. package/apps/pwa/out/field/index.txt +23 -23
  215. package/apps/pwa/out/healthz +1 -1
  216. package/apps/pwa/out/index.html +1 -1
  217. package/apps/pwa/out/index.txt +22 -22
  218. package/apps/pwa/out/inside/index.html +1 -1
  219. package/apps/pwa/out/inside/index.txt +22 -22
  220. package/apps/pwa/out/intake/index.html +1 -1
  221. package/apps/pwa/out/intake/index.txt +23 -23
  222. package/apps/pwa/out/live/index.html +1 -1
  223. package/apps/pwa/out/live/index.txt +23 -23
  224. package/apps/pwa/out/live-run/index.html +1 -1
  225. package/apps/pwa/out/live-run/index.txt +24 -23
  226. package/apps/pwa/out/loops/index.html +1 -1
  227. package/apps/pwa/out/loops/index.txt +22 -22
  228. package/apps/pwa/out/market/index.html +1 -1
  229. package/apps/pwa/out/market/index.txt +22 -22
  230. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  231. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  232. package/apps/pwa/out/morning/index.html +1 -1
  233. package/apps/pwa/out/morning/index.txt +23 -23
  234. package/apps/pwa/out/observatory/index.html +1 -1
  235. package/apps/pwa/out/observatory/index.txt +23 -23
  236. package/apps/pwa/out/ops/checklist/index.html +1 -1
  237. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  238. package/apps/pwa/out/ops/release/index.html +1 -1
  239. package/apps/pwa/out/ops/release/index.txt +22 -22
  240. package/apps/pwa/out/ops/seats/index.html +1 -1
  241. package/apps/pwa/out/ops/seats/index.txt +22 -22
  242. package/apps/pwa/out/outputs/index.html +1 -1
  243. package/apps/pwa/out/outputs/index.txt +22 -22
  244. package/apps/pwa/out/reflection/index.html +1 -1
  245. package/apps/pwa/out/reflection/index.txt +23 -23
  246. package/apps/pwa/out/scheduler/index.html +1 -1
  247. package/apps/pwa/out/scheduler/index.txt +23 -23
  248. package/apps/pwa/out/sessions/index.html +1 -1
  249. package/apps/pwa/out/sessions/index.txt +22 -22
  250. package/apps/pwa/out/settings/devices/index.html +1 -1
  251. package/apps/pwa/out/settings/devices/index.txt +23 -23
  252. package/apps/pwa/out/settings/index.html +1 -1
  253. package/apps/pwa/out/settings/index.txt +23 -23
  254. package/apps/pwa/out/setup/done/index.html +1 -1
  255. package/apps/pwa/out/setup/done/index.txt +23 -23
  256. package/apps/pwa/out/setup/index.html +1 -1
  257. package/apps/pwa/out/setup/index.txt +23 -23
  258. package/apps/pwa/out/share/index.html +1 -1
  259. package/apps/pwa/out/share/index.txt +23 -23
  260. package/apps/pwa/out/showroom/index.html +1 -1
  261. package/apps/pwa/out/showroom/index.txt +22 -22
  262. package/apps/pwa/out/tasks/index.html +1 -1
  263. package/apps/pwa/out/tasks/index.txt +23 -23
  264. package/apps/pwa/out/term/index.html +1 -1
  265. package/apps/pwa/out/term/index.txt +23 -23
  266. package/apps/pwa/out/today/index.html +1 -1
  267. package/apps/pwa/out/today/index.txt +23 -23
  268. package/apps/pwa/out/trace/index.html +1 -1
  269. package/apps/pwa/out/trace/index.txt +23 -23
  270. package/apps/pwa/out/vault/index.html +1 -1
  271. package/apps/pwa/out/vault/index.txt +23 -23
  272. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  273. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  274. package/apps/pwa/out/workflows/index.html +1 -1
  275. package/apps/pwa/out/workflows/index.txt +23 -23
  276. package/apps/pwa/out/workspace/index.html +1 -1
  277. package/apps/pwa/out/workspace/index.txt +23 -23
  278. package/apps/pwa/out/worktrees/index.html +1 -1
  279. package/apps/pwa/out/worktrees/index.txt +23 -23
  280. package/catalog/models/anthropic/claude-haiku-5-5.yaml +32 -0
  281. package/catalog/models/anthropic/claude-opus-5-5.yaml +5 -0
  282. package/catalog/models/anthropic/claude-sonnet-5-5.yaml +31 -0
  283. package/catalog/models/anthropic/claude-sonnet-5.yaml +8 -2
  284. package/catalog/models/openai/gpt-6-astra.yaml +6 -0
  285. package/catalog/models/openai/gpt-6-luna.yaml +6 -0
  286. package/catalog/models/openai/gpt-6-sol.yaml +6 -0
  287. package/graphs/catalog/catalog.yaml +1 -1
  288. package/graphs/drafts/recipes.yaml +2 -2
  289. package/graphs/log-horizon/log-horizon-watch.yaml +25 -0
  290. package/graphs/log-horizon/recipes.yaml +3 -0
  291. package/graphs/release/recipes.yaml +1 -1
  292. package/graphs/release/release-loop.yaml +6 -2
  293. package/graphs/release-rehearsal/recipes.yaml +12 -0
  294. package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
  295. package/graphs/test-diet/recipes.yaml +3 -0
  296. package/graphs/test-diet/test-diet.yaml +3 -1
  297. package/package.json +4 -1
  298. package/scripts/bench-report.ts +82 -3
  299. package/scripts/ci-typecheck-changed.ts +10 -1
  300. package/scripts/f-session-monitor.ts +69 -0
  301. package/scripts/hq/hq-fence-wrapper.sh +148 -0
  302. package/scripts/hq/standby-snapshot.ts +7 -3
  303. package/scripts/knowledge-compress.ts +11 -0
  304. package/scripts/lib/typecheck-ratchet.ts +51 -0
  305. package/scripts/nightly-docops.ts +90 -3
  306. package/scripts/openai-relay-server.ts +5 -1
  307. package/scripts/release-loop/docs-node.ts +258 -43
  308. package/scripts/release-loop/gate-method.ts +59 -0
  309. package/scripts/release-loop/gate-node.ts +73 -7
  310. package/scripts/release-loop/gate-wall.ts +208 -0
  311. package/scripts/release-loop/known-issues-node.ts +53 -8
  312. package/scripts/release-loop/publish-at.ts +14 -0
  313. package/scripts/release-loop/publish-node.ts +17 -2
  314. package/scripts/release-loop/resume-release.ts +34 -4
  315. package/scripts/release-loop/resume.ts +53 -0
  316. package/scripts/release-loop/shard-plan.ts +3 -11
  317. package/scripts/release-loop/tui-node-checks.ts +22 -0
  318. package/scripts/release-loop/unattended-release.ts +8 -1
  319. package/scripts/research-coo-admin-dates.ts +39 -0
  320. package/scripts/rhythm/daily.ts +51 -2
  321. package/scripts/rhythm/weekly.ts +3 -2
  322. package/scripts/skills/public-check.ts +7 -2
  323. package/scripts/smart-merge/resync-shadow.ts +5 -3
  324. package/scripts/test-diet/lib.ts +81 -1
  325. package/scripts/test-diet/node.ts +48 -2
  326. package/scripts/tsc-main-safety-net.ts +189 -0
  327. package/scripts/usage-rollup.ts +8 -4
  328. package/scripts/verify-coo-admin-evidence.ts +83 -0
  329. package/src/acp/client.ts +4 -2
  330. package/src/acp/codex-plugins.ts +48 -6
  331. package/src/agent/monad-agent-turn.ts +67 -5
  332. package/src/agent/run-context.ts +14 -0
  333. package/src/agent/tool-profile.ts +28 -2
  334. package/src/agent-env/profile.ts +25 -5
  335. package/src/agent-mission/acp-judge.ts +8 -2
  336. package/src/agent-mission/capabilities-cli.ts +16 -1
  337. package/src/agent-mission/driver.ts +27 -13
  338. package/src/agent-mission/pr-review-watch.ts +6 -2
  339. package/src/agent-mission/review-loop.ts +33 -5
  340. package/src/agent-mission/supervisor-metrics.ts +17 -2
  341. package/src/agent-substrate/acp-reviewer.ts +25 -9
  342. package/src/agent-substrate/pr-reviewer.ts +175 -32
  343. package/src/agent-substrate/review-intent.ts +106 -5
  344. package/src/agent-substrate/self-review-cli.ts +111 -16
  345. package/src/agent-substrate/shard-boundary-intent.ts +92 -26
  346. package/src/ask-user-question/pending-questions.ts +8 -2
  347. package/src/autopilot/build/llm-conflict-merge.ts +238 -20
  348. package/src/autopilot/codebase-grounding.ts +44 -0
  349. package/src/autopilot/llm-control-brain.ts +13 -1
  350. package/src/autopilot/mission-codebase-gate.ts +8 -77
  351. package/src/autopilot/pr-manager.ts +30 -11
  352. package/src/away/release-watch.ts +47 -8
  353. package/src/boot/acp-server.ts +4 -7
  354. package/src/boot/acp-socket-path.ts +7 -0
  355. package/src/briefing/brief-items.ts +123 -22
  356. package/src/chat/index.ts +13 -3
  357. package/src/cli/agent-cli.ts +20 -0
  358. package/src/cli/brief-cli.ts +46 -22
  359. package/src/cli/cli-user-error.ts +9 -2
  360. package/src/cli/config-classify.ts +83 -0
  361. package/src/cli/control-cli.ts +14 -0
  362. package/src/cli/decisions-cli.ts +26 -16
  363. package/src/cli/log-event-names.ts +3 -0
  364. package/src/cli/logs-cli.ts +1 -0
  365. package/src/cli/logs-model-input.ts +1 -1
  366. package/src/cli/mcp-login.ts +111 -37
  367. package/src/cli/plugin-cli.ts +21 -1
  368. package/src/cli/pod-cli.ts +26 -0
  369. package/src/cli/pr-cli.ts +94 -9
  370. package/src/cli/pr-land-overlap-evidence.ts +131 -0
  371. package/src/cli/release-cli.ts +74 -15
  372. package/src/cli/self-update.ts +173 -10
  373. package/src/cli/skills-cli.ts +12 -3
  374. package/src/cli/tasks-cli.ts +241 -28
  375. package/src/connectors/types.ts +6 -6
  376. package/src/context-bus/context-first.ts +51 -2
  377. package/src/context-bus/context-now-surfaces.ts +29 -0
  378. package/src/context-bus/coord-events.ts +32 -4
  379. package/src/context-bus/long-term-memory.ts +26 -7
  380. package/src/context-bus/nightly-condense.ts +170 -21
  381. package/src/control/control-status.ts +87 -0
  382. package/src/control-plane/light-member.ts +5 -3
  383. package/src/control-plane/member.ts +172 -7
  384. package/src/core-turn/run-goal-loop.ts +108 -3
  385. package/src/dashboard/chat-fold.ts +20 -0
  386. package/src/dashboard/first-screen-band.ts +151 -1
  387. package/src/dashboard/index.ts +27 -5
  388. package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -3
  389. package/src/dashboard/stale-install-check.ts +13 -2
  390. package/src/dashboard/turn-stream-formatter.ts +25 -0
  391. package/src/debug/log-diet.ts +159 -0
  392. package/src/debug/log.ts +52 -17
  393. package/src/decisions/decision-cards.ts +20 -1
  394. package/src/decisions/decision-ledger.ts +11 -8
  395. package/src/decisions/web-push-decision-cards.ts +19 -3
  396. package/src/discord-self-message.ts +2 -2
  397. package/src/display/coordinator.ts +25 -2
  398. package/src/domains/coo-admin-dates.evidence.json +876 -0
  399. package/src/domains/coo-admin-tool.ts +75 -14
  400. package/src/domains/cron-match.ts +1 -0
  401. package/src/domains/ops-status.ts +53 -0
  402. package/src/domains/outbound-alert.ts +41 -7
  403. package/src/domains/release-tool.ts +119 -10
  404. package/src/domains/schedule-registry.ts +10 -7
  405. package/src/domains/schedule-runner.ts +1 -0
  406. package/src/elanous-config-dir.ts +2 -2
  407. package/src/elanous-daemon.ts +3 -3
  408. package/src/exec-requests/planner.ts +6 -0
  409. package/src/execution-loop/launch-gate.ts +1 -1
  410. package/src/expression/i18n/messages.en.ts +5 -0
  411. package/src/expression/i18n/messages.ja.ts +5 -0
  412. package/src/expression/i18n/messages.ko.ts +5 -0
  413. package/src/expression/i18n/messages.zh.ts +5 -0
  414. package/src/expression/i18n/types.ts +8 -0
  415. package/src/github/pr-labels.ts +1 -0
  416. package/src/graph-kinds/registry.ts +6 -6
  417. package/src/graph-runner/graph-cli.ts +34 -2
  418. package/src/graph-runner/graph-run-api.ts +7 -0
  419. package/src/graph-runner/graph-tick.ts +73 -12
  420. package/src/graph-runner/runner.ts +94 -13
  421. package/src/graph-unify/wf-to-graph.ts +79 -0
  422. package/src/graph-wizard/generate.ts +34 -2
  423. package/src/graph-wizard/steps.ts +13 -0
  424. package/src/harness/dispatch-backpressure.ts +259 -0
  425. package/src/harness/harness-cli-command.ts +227 -50
  426. package/src/harness/harness-queue.ts +58 -14
  427. package/src/harness/harness-seams.ts +2 -20
  428. package/src/harness/harness-substrate-default.ts +72 -1
  429. package/src/harness/launch-advice.ts +23 -0
  430. package/src/harness/nested-elanous-policy.ts +4 -2
  431. package/src/hq/fence-wrapper.ts +7 -0
  432. package/src/hq/hq.ts +33 -2
  433. package/src/hq/lease.ts +13 -0
  434. package/src/hq/seats.ts +114 -18
  435. package/src/index.ts +199 -71
  436. package/src/intake-plane/collect-github.ts +19 -1
  437. package/src/intake-plane/digest.ts +45 -20
  438. package/src/intake-plane/lens.ts +36 -8
  439. package/src/intelligence-map/model-alias.ts +6 -0
  440. package/src/intelligence-map/model-catalog.ts +41 -0
  441. package/src/knowledge/conclusion-compress.ts +93 -0
  442. package/src/knowledge/kgs/pack.ts +5 -2
  443. package/src/knowledge/kgs/sqlite-store.ts +15 -0
  444. package/src/knowledge/know-find.ts +9 -2
  445. package/src/knowledge/query.ts +20 -0
  446. package/src/knowledge/tools/knowledge-query.ts +20 -2
  447. package/src/knowledge/write.ts +234 -2
  448. package/src/llm/bedrock-provider.ts +175 -0
  449. package/src/llm/bedrock.ts +345 -0
  450. package/src/llm/provider-credentials.ts +3 -1
  451. package/src/llm.ts +332 -51
  452. package/src/loops/budget.ts +150 -0
  453. package/src/loops/neighbor-runtime.ts +88 -0
  454. package/src/loops/orchestrator/author-depth.ts +29 -11
  455. package/src/loops/orchestrator/overlap.ts +7 -1
  456. package/src/loops/orchestrator/resync-shadow.ts +1 -1
  457. package/src/loops/orchestrator/seat-share.ts +6 -49
  458. package/src/loops/orchestrator/tick.ts +35 -2
  459. package/src/loops/orchestrator/traffic.ts +6 -80
  460. package/src/loops/registry.ts +5 -0
  461. package/src/market/publish.ts +17 -1
  462. package/src/market/signed-index.ts +42 -0
  463. package/src/maturity/feature-maturity.ts +2 -1
  464. package/src/mcp/mcp-oauth.ts +136 -17
  465. package/src/model-tier/llm-tier-map.ts +48 -4
  466. package/src/models/prompts.ts +22 -1
  467. package/src/mss/logging/horizon-watch.ts +168 -0
  468. package/src/mss/logging/log-store.ts +204 -15
  469. package/src/mss/logging/redaction.ts +17 -0
  470. package/src/native-tool-catalog.ts +1 -1
  471. package/src/nexus/api/consult-requests.ts +7 -10
  472. package/src/nexus/api/discord-trigger-bot.ts +6 -3
  473. package/src/nexus/api/draft-metrics.ts +22 -8
  474. package/src/nexus/api/error-reports.ts +30 -8
  475. package/src/nexus/api/graph-peer-edit.ts +77 -0
  476. package/src/nexus/api/graph-wizard-api.ts +9 -1
  477. package/src/nexus/api/graphs-api.ts +145 -7
  478. package/src/nexus/api/http-server.ts +101 -8
  479. package/src/nexus/api/loop-resources.ts +42 -0
  480. package/src/nexus/api/outbound-report.ts +8 -3
  481. package/src/nexus/api/plugins-market.ts +24 -0
  482. package/src/nexus/api/telegram-trigger-bot.ts +6 -3
  483. package/src/nexus/index.ts +13 -2
  484. package/src/nexus/outbound/format.ts +2 -0
  485. package/src/nexus/outbound/router.ts +198 -13
  486. package/src/oauth/claude-pty-maturity.ts +24 -0
  487. package/src/oauth/codex-account-rotation.ts +16 -18
  488. package/src/oauth/codex-account-store.ts +134 -5
  489. package/src/oauth/fallback-chain.ts +50 -15
  490. package/src/onboarding.ts +2 -1
  491. package/src/plugins/adapters/claude-package.ts +4 -12
  492. package/src/plugins/core/capability-policy.ts +141 -0
  493. package/src/plugins/core/host.ts +21 -8
  494. package/src/plugins/core/manifest.ts +19 -2
  495. package/src/plugins/core/trust-store.ts +15 -0
  496. package/src/plugins/core/types.ts +12 -0
  497. package/src/plugins/install/market-fetch.ts +68 -16
  498. package/src/plugins/install/plugin-install.ts +187 -16
  499. package/src/plugins/maker/market-bundle.ts +9 -0
  500. package/src/plugins/maker/plugin-maker.ts +32 -21
  501. package/src/plugins/maker/wizard-generate.ts +87 -9
  502. package/src/policy/llm-policy.ts +24 -6
  503. package/src/process/pid-liveness.ts +1 -1
  504. package/src/prompt-cache/openai.ts +10 -6
  505. package/src/prompt-cache/openrouter.ts +94 -0
  506. package/src/prompt-enhance/enhance.ts +46 -5
  507. package/src/prompt-library/family-prompt-coverage.ts +1 -0
  508. package/src/prompt-library/universal-preamble.ts +2 -2
  509. package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
  510. package/src/registry/loader.ts +6 -1
  511. package/src/release-loop/checklist-board.ts +27 -0
  512. package/src/release-loop/checklist.ts +62 -9
  513. package/src/release-loop/feature-store.ts +3 -0
  514. package/src/release-loop/gate-shards.ts +48 -4
  515. package/src/release-loop/landed-to-green.ts +81 -0
  516. package/src/release-loop/light-rc.ts +11 -1
  517. package/src/release-loop/merged-pr-checklist.ts +10 -0
  518. package/src/release-loop/placement.ts +91 -22
  519. package/src/release-loop/rehearsal.ts +317 -0
  520. package/src/release-loop/release-schedule.ts +13 -1
  521. package/src/release-loop/rubric-types.ts +1 -0
  522. package/src/release-loop/rubric.ts +2 -2
  523. package/src/retro/daily.ts +23 -9
  524. package/src/seat-address/seat-address.ts +1 -0
  525. package/src/seat-loop/seat-loop.ts +208 -21
  526. package/src/seat-loop/seat-report.ts +29 -1
  527. package/src/seat-loop/traffic-signal.ts +44 -0
  528. package/src/self-dev/ask-launch-flow.ts +2 -2
  529. package/src/self-dev/dev-cli.ts +157 -11
  530. package/src/self-dev/dev-pipeline.ts +18 -1
  531. package/src/self-dev/draft-residue.ts +463 -0
  532. package/src/self-dev/draft-sweep.ts +195 -17
  533. package/src/self-dev/draft-triage-rules.ts +27 -1
  534. package/src/self-dev/launch-preflight-text.ts +549 -0
  535. package/src/self-dev/launch-preflight.ts +10 -545
  536. package/src/self-dev/orchestrate-cli.ts +57 -2
  537. package/src/self-dev/orchestrate-summary-line.ts +13 -0
  538. package/src/self-dev/orchestrate.ts +9 -133
  539. package/src/self-dev/review-provider-fallback.ts +179 -0
  540. package/src/self-dev/run-store.ts +1 -3
  541. package/src/self-dev/run-supervisor.ts +8 -23
  542. package/src/self-dev/run-types.ts +178 -0
  543. package/src/self-dev/shard-aggregate.ts +61 -13
  544. package/src/self-dev/shard-plan.ts +5 -1
  545. package/src/self-dev/shard-run.ts +23 -5
  546. package/src/self-dev/supervisor-verdict-edges.ts +2 -4
  547. package/src/self-implement/blocked-draft-policy.ts +3 -19
  548. package/src/self-implement/draft-on-stop-mode.ts +18 -0
  549. package/src/self-implement/follow-up-goals.ts +114 -38
  550. package/src/self-implement/gate-baseline-reap.ts +157 -0
  551. package/src/self-implement/gate-baseline.ts +78 -16
  552. package/src/self-implement/gate-cli.ts +12 -2
  553. package/src/self-implement/gate-remote.ts +17 -6
  554. package/src/self-implement/goal-author.ts +24 -4
  555. package/src/self-implement/goal-digest.ts +19 -0
  556. package/src/self-implement/graph-overlay-condition.ts +4 -0
  557. package/src/self-implement/harness-policy-gates.ts +7 -5
  558. package/src/self-implement/headless-elanous-driver.ts +11 -9
  559. package/src/self-implement/host-regate.ts +148 -43
  560. package/src/self-implement/l8-merge-queue.ts +147 -13
  561. package/src/self-implement/merge-train.ts +131 -0
  562. package/src/self-implement/off-diff-evidence.ts +9 -0
  563. package/src/self-implement/orchestrator.ts +201 -43
  564. package/src/self-implement/review-finding-recurrence.ts +28 -0
  565. package/src/self-implement/rework-policy.ts +2 -1
  566. package/src/self-implement/round-summary-card.ts +63 -0
  567. package/src/self-implement/run-ledger.ts +4 -3
  568. package/src/self-implement/run-step-projection.ts +147 -0
  569. package/src/self-implement/run-stop.ts +1 -1
  570. package/src/self-implement/seams.ts +41 -6
  571. package/src/self-implement/self-implement-cli.ts +6 -0
  572. package/src/self-implement/train-gate-remote.ts +158 -0
  573. package/src/session-runtime/index.ts +10 -1
  574. package/src/session-runtime/retry-api.ts +11 -1
  575. package/src/shell-env-bootstrap.ts +19 -4
  576. package/src/skills/gift-install.ts +119 -0
  577. package/src/skills/runner.ts +59 -2
  578. package/src/skills/skill-feedback.ts +31 -1
  579. package/src/skills/skill-tier.ts +1 -0
  580. package/src/smart-wizard/capability-index.ts +231 -0
  581. package/src/smart-wizard/rung.ts +74 -0
  582. package/src/steward/launch.ts +20 -9
  583. package/src/steward/triage.ts +29 -10
  584. package/src/storage/file-lock.ts +40 -4
  585. package/src/task-agent/actions.ts +4 -0
  586. package/src/task-agent/card-evidence.ts +59 -13
  587. package/src/task-agent/completion-evidence.ts +31 -3
  588. package/src/task-agent/cover.ts +61 -0
  589. package/src/task-agent/judge.ts +4 -3
  590. package/src/task-agent/land-worktree.ts +201 -0
  591. package/src/task-agent/live-move-history.ts +133 -0
  592. package/src/task-agent/live-moves.ts +222 -12
  593. package/src/task-agent/parent-host.ts +117 -8
  594. package/src/task-agent/rejudge-on-head.ts +297 -0
  595. package/src/task-agent/review-result-capture.ts +218 -0
  596. package/src/task-agent/shadow.ts +118 -7
  597. package/src/task-agent/task-hand.ts +138 -11
  598. package/src/task-orchestrator/surfaces/pod-child-providers.ts +29 -0
  599. package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
  600. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +16 -2
  601. package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
  602. package/src/task-orchestrator/surfaces/pod-lease.ts +93 -12
  603. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +25 -2
  604. package/src/task-orchestrator/surfaces/pod-pool.ts +203 -28
  605. package/src/task-orchestrator/surfaces/self-implement-pod.ts +259 -36
  606. package/src/task-orchestrator/surfaces/self-implement.ts +11 -0
  607. package/src/telegram-commands.ts +8 -0
  608. package/src/telegram-project-command.ts +6 -0
  609. package/src/telegram-service.ts +5 -1
  610. package/src/telegram.ts +17 -4
  611. package/src/time/format.ts +13 -4
  612. package/src/tool-runtime/goal-author-runtime.ts +1 -0
  613. package/src/tool-runtime/self-cognition-catalog.ts +23 -0
  614. package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
  615. package/src/typecheck-ratchet.ts +2 -1
  616. package/src/user-config.ts +167 -28
  617. package/src/ux-sim/slash-menu-frames.ts +168 -0
  618. package/src/version/packed-revision.json +1 -1
  619. package/src/web-terminal/preview-tap-registry.ts +5 -2
  620. package/src/workflow-runtime/executor.ts +24 -2
  621. package/src/workflow-runtime/triggers/registry.ts +27 -0
  622. package/src/workflow-runtime/triggers/schedule-source.ts +30 -3
  623. package/src/workflow-runtime/triggers/scheduler.ts +1 -0
  624. package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
  625. package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
  626. package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
  627. package/apps/pwa/out/_next/static/chunks/1307-c97eba9fb72a9a5e.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
  629. package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
  630. package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
  631. package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
  633. package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
  638. package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
  647. package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
  648. package/apps/pwa/out/_next/static/chunks/2489-ff55a35b202c0f94.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
  661. package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
  669. package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
  674. package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
  676. package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
  680. package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
  684. package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/5977-59fedea50d13c762.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
  689. package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
  690. package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
  692. package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
  693. package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
  701. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
  704. package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
  714. package/apps/pwa/out/_next/static/chunks/8857-f1762140ef9a96b1.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
  717. package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/9247-7581825d511a64c0.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
  721. package/apps/pwa/out/_next/static/chunks/9497-b0e758d1cd4ae8d7.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
  723. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/approvals/page-937c92292a4ab4f0.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d781be3e3a9cfd74.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/board/page-b0a80997903852d8.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/botlab/page-2b1263165630d9c8.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea998f7f5d156bea.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/ceo/page-33c328b64ca508f8.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/chat/page-e2d6bed48ac20120.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/control/page-544dd4bd4847eeb7.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/decisions/page-3ee191319bf97d87.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e4bcb2c503dab04b.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/editor/page-300897dcbbd5ed76.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/exec/page-a449f1ed472b81c2.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/field/page-9045094d6d3b5cd0.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/inside/page-c06673596849ef45.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/intake/page-103fa3191c1b2e08.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/layout-9f81233f29dcd409.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/live/page-be8b4615c919e36c.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/live-run/page-c685b104e0dfa609.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/loops/page-8d693331cfbb6add.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/market/page-cef4f30a4c22fae1.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66ea1b54fc83fa15.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/morning/page-7a12f61be4a579d1.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/not-found-c85b0589591a99c9.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/observatory/page-725a4da02dd129eb.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8cc707bd09a497d9.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-90b55be1f15ce0e8.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cb16606e08be65db.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/outputs/page-16dc64b74ed6a40a.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/page-21bec4afeb2f0917.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/reflection/page-dc39ee7a36d26385.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-84ae759f76053672.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/sessions/page-3db58ddb61fe2be9.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c5315e30f3528dc4.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/settings/page-2fe368efb6de3b6a.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8d04132dd0ac5e10.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/setup/page-f23484de467c9ea3.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/share/page-c69762987b751174.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/showroom/page-5456692bda39aafb.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d75f7cd65845ce98.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/term/page-5603f5e568b25ce3.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/today/page-d2cc0f4e89f42028.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/trace/page-a6eb73b8a4840f1c.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/vault/page-c0a3f4d10edb83fa.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6c0b88068c143f15.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/workflows/page-7f8d7fcdf058a845.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/workspace/page-22163556cd38bc88.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-141436fd26dd56fc.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
  779. package/apps/pwa/out/_next/static/css/e81df11490b4413b.css +0 -1
  780. /package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_ssgManifest.js +0 -0
@@ -3,7 +3,7 @@ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSy
3
3
  import { spawn } from 'node:child_process';
4
4
  import { createHash, randomBytes } from 'node:crypto';
5
5
  import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from 'node:path';
6
- import { groundMissionInCodebase, isRepositoryImplementationCandidate, type CodebaseGrounding } from '../autopilot/mission-codebase-gate.js';
6
+ import { isRepositoryImplementationCandidate, type CodebaseGrounding } from '../autopilot/codebase-grounding.js';
7
7
  import { extractSlugSource, generateMissionSlug, slugify } from '../autopilot/mission-registry.js';
8
8
  import { enhancePrompt, type EnhanceOpts, type EnhanceResult } from '../prompt-enhance/enhance.js';
9
9
  import type { LLMUsage } from '../prompt-cache/types.js';
@@ -44,7 +44,7 @@ import { extractGoalDocSections, type GoalDocSourceLine } from './goal-doc/secti
44
44
  import { isGoalAuthorFileName } from './goal-document.js';
45
45
  import { resolveGoalDocumentsDir } from './goal-documents-dir.js';
46
46
  import { REQUIRED_EVIDENCE_COMMAND_SEPARATOR } from './off-diff-evidence.js';
47
- import { renderLaunchPreflight, siblingTestPath, type LaunchPreflightResult } from '../self-dev/launch-preflight.js';
47
+ import { renderLaunchPreflight, siblingTestPath, type LaunchPreflightResult } from '../self-dev/launch-preflight-text.js';
48
48
  import { quoteShellArg } from '../cli/logs-cli.js';
49
49
  import type { HarnessGroundingProvenance } from './context-capsule.js';
50
50
  import { hasGoalStepCodeName } from './goal-step-code-name.js';
@@ -121,6 +121,21 @@ export interface GoalAuthorGroundingResult {
121
121
  facts: CodebaseGrounding;
122
122
  }
123
123
 
124
+ // A function-local slot is initialized only on access, after cyclic ESM evaluation has finished.
125
+ function goalAuthorGroundMissionSlot(): { fn?: NonNullable<GoalAuthorGroundingDeps['groundMission']> } {
126
+ const key = Symbol.for('elanous.goalAuthor.groundMission');
127
+ const registry = globalThis as typeof globalThis & { [key: symbol]: { fn?: NonNullable<GoalAuthorGroundingDeps['groundMission']> } };
128
+ return registry[key] ??= {};
129
+ }
130
+
131
+ export function registerGoalAuthorGroundMission(fn: NonNullable<GoalAuthorGroundingDeps['groundMission']> | undefined): void {
132
+ goalAuthorGroundMissionSlot().fn = fn;
133
+ }
134
+
135
+ export function hasGoalAuthorGroundMission(): boolean {
136
+ return goalAuthorGroundMissionSlot().fn !== undefined;
137
+ }
138
+
124
139
  export interface GoalAuthorPersistentGroundingDecision {
125
140
  readonly enabled: boolean;
126
141
  readonly source: ObserveOnlySource;
@@ -5583,12 +5598,17 @@ export async function groundForGoalAuthor(
5583
5598
  cwd: string,
5584
5599
  deps: GoalAuthorGroundingDeps = {},
5585
5600
  ): Promise<GoalAuthorGroundingResult> {
5601
+ const groundMission = deps.groundMission ?? goalAuthorGroundMissionSlot().fn;
5602
+ if (!groundMission) {
5603
+ debug.log('goal-author.grounding', 'route-unregistered', { cwd });
5604
+ throw new Error('route-unregistered: mission-codebase-gate 를 로드하라');
5605
+ }
5586
5606
  return {
5587
5607
  path: 'groundMissionInCodebase',
5588
5608
  // ⛔⭐ 사람이 ask 에 «이름을 댄» 경로를 접지에 «넘긴다» — 접지가 그것을 후보로 쓴다.
5589
5609
  // ⛔ 추출기를 «새로 만들지 않는다» — 이 파일이 이미 갖고 있는 askPathTokens 하나를 쓴다
5590
5610
  // (2026-08-11 72차: 같은 것에 두 이름을 준 병을 하루에 여섯 번 셌다).
5591
- facts: await (deps.groundMission ?? groundMissionInCodebase)(ask, {
5611
+ facts: await groundMission(ask, {
5592
5612
  cwd,
5593
5613
  seedPaths: askPathTokens(ask),
5594
5614
  ...(deps.persistent !== undefined ? { persistent: deps.persistent } : {}),
@@ -5694,7 +5714,7 @@ export function defaultGoalAuthorDeps(cwd: string): GoalAuthorDeps {
5694
5714
  * 이 칸을 «안 주므로» 기본값 `coverage-gate` 로 종전 문면을 그대로 받는다.
5695
5715
  */
5696
5716
  enhance(ask, opts) {
5697
- return enhancePrompt(ask, { ...opts, checklistUse: 'authoring' });
5717
+ return enhancePrompt(ask, { ...opts, checklistUse: 'authoring', config: opts?.config ?? getUserConfig() });
5698
5718
  },
5699
5719
  readSourceFile: createRepositoryReferencedFileReader(cwd),
5700
5720
  runHelpProbe: (argv) => runDefaultHelpProbe(cwd, argv),
@@ -89,6 +89,25 @@ function scaled(limit: number): { reserved: number; minSection: number } {
89
89
  return { reserved: Math.floor(RESERVED_FOR_NOTICE * k), minSection: Math.max(40, Math.floor(MIN_SECTION_CHARS * k)) };
90
90
  }
91
91
 
92
+ /** 골 문서에서 `판정 신호` 절만 뽑아 리뷰 acceptance 로 쓴다. 계보 = self-implement seams. */
93
+ export function extractHarnessReviewAcceptance(goalDocument: string | undefined): { goal: string | undefined; acceptance: string | undefined } {
94
+ let goal: string | undefined;
95
+ try {
96
+ goal = goalDocument?.trim() || undefined;
97
+ } catch {
98
+ return { goal: undefined, acceptance: undefined };
99
+ }
100
+ if (!goal) return { goal: undefined, acceptance: undefined };
101
+ try {
102
+ const acceptance = splitGoalSections(supervisorGoalDigest(goal, 3000).text)
103
+ .find((section) => isSupervisorDecisionSection(section.title) && section.title.includes('판정 신호'))
104
+ ?.body.trim() || undefined;
105
+ return { goal, acceptance };
106
+ } catch {
107
+ return { goal, acceptance: undefined };
108
+ }
109
+ }
110
+
92
111
  /** `## <제목>` 기준으로 절을 가른다. 헤더 앞 서두는 제목 `''` 로 담는다. */
93
112
  export function splitGoalSections(goal: string): Section[] {
94
113
  return extractGoalDocSections(goal, {
@@ -53,6 +53,10 @@ export function evaluateOverlayCondition(
53
53
  const { key, operator, literal } = parsed.condition;
54
54
  if (!(key in state)) return { kind: 'key-absent', key };
55
55
  const actual = state[key];
56
+ if (actual === undefined || actual === null) return { kind: 'key-absent', key };
57
+ // Measured boolean branch keys accept only a real boolean observation — any textual lookalike
58
+ // ('true', 'TRUE', 'yes', 1) is unknown, whatever the literal spelling in the condition.
59
+ if ((key === 'sibling_overlap' || key === 'main_sync_conflict') && typeof actual !== 'boolean') return { kind: 'key-absent', key };
56
60
 
57
61
  if (typeof literal === 'number') {
58
62
  // ⛔ 수 비교인데 값이 수가 아니면 「비교 불가」다 — 거짓으로 접지 않는다.
@@ -5,16 +5,17 @@ import { runMockModuleRestoreGate } from '../../scripts/ci-mock-module-restore-g
5
5
  import { runModelHardcodeGate } from '../../scripts/ci-model-hardcode-gate.js';
6
6
  import { runDaemonPortGate } from '../../scripts/ci-daemon-port-gate.js';
7
7
  import { runPublicExportLeakGate } from '../../scripts/ci-public-export-leak-gate.js';
8
+ import { runPublicExportImportGate } from '../../scripts/ci-public-export-import-gate.js';
8
9
 
9
- type GateName = 'isolation-gate' | 'mock-module-restore-gate' | 'model-hardcode-gate' | 'daemon-port-gate' | 'public-export-leak';
10
+ type GateName = 'isolation-gate' | 'mock-module-restore-gate' | 'model-hardcode-gate' | 'daemon-port-gate' | 'public-export-leak' | 'public-export-import';
10
11
  type GateOutput = { args: string[]; cwd: string; log: (line: string) => void; error: (line: string) => void };
11
- type GateRunner = (out: GateOutput) => number;
12
+ type GateRunner = (out: GateOutput) => number | Promise<number>;
12
13
 
13
- export function runHarnessPolicyGates(input: {
14
+ export async function runHarnessPolicyGates(input: {
14
15
  cwd: string;
15
16
  changedFiles: readonly string[];
16
17
  gates?: Partial<Record<GateName, GateRunner>>;
17
- }): { passed: boolean; failures: Array<{ gate: GateName; lines: string[] }>; skipped?: string } {
18
+ }): Promise<{ passed: boolean; failures: Array<{ gate: GateName; lines: string[] }>; skipped?: string }> {
18
19
  try {
19
20
  if (!statSync(join(input.cwd, 'scripts')).isDirectory()) {
20
21
  return { passed: true, failures: [], skipped: 'no-scripts' };
@@ -30,12 +31,13 @@ export function runHarnessPolicyGates(input: {
30
31
  ['daemon-port-gate', input.gates?.['daemon-port-gate'] ?? ((out) => runDaemonPortGate({ log: out.log, error: out.error, cwd: out.cwd, args: [] }))],
31
32
  // LEAK1 — the same pre-export check as pr land; an unmeasured result is a nonzero failure, not a pass.
32
33
  ['public-export-leak', input.gates?.['public-export-leak'] ?? runPublicExportLeakGate],
34
+ ['public-export-import', input.gates?.['public-export-import'] ?? runPublicExportImportGate],
33
35
  ];
34
36
  const failures: Array<{ gate: GateName; lines: string[] }> = [];
35
37
  for (const [gate, run] of runners) {
36
38
  const lines: string[] = [];
37
39
  try {
38
- const status = run({ cwd: input.cwd, args: ['--changed-files', ...input.changedFiles], log: (line) => lines.push(line), error: (line) => lines.push(line) });
40
+ const status = await run({ cwd: input.cwd, args: ['--changed-files', ...input.changedFiles], log: (line) => lines.push(line), error: (line) => lines.push(line) });
39
41
  if (status !== 0) failures.push({ gate, lines: [...lines, `✗ ${gate}: violation detected`] });
40
42
  } catch (error) {
41
43
  failures.push({ gate, lines: [...lines, `⚠ ${gate}: 게이트가 «못 쟀다» — ${error instanceof Error ? error.message : String(error)}`] });
@@ -996,8 +996,8 @@ export interface HeadlessGoalLoopPtyOptions {
996
996
  /** 밖에서 쓴 이력 조회 심 — 기본은 실물(`pty-control-ipc`). ⭐ 테스트가 전역을 찌르지 않게
997
997
  * `spawn`·`ptyAvailable` 과 **같은 방식**으로 주입한다(새 패턴 아님 · 테스트 전용 export 도 아님). */
998
998
  externalWriteProvenance?: (ptyId: string) => { externalWrites: number; externalWriteAgoMs: number; externalWriteActor: string } | undefined;
999
- /** ★S4 P2b — brain 상담 1회 최대 대기(ms·기본 15초). 초과 시 abort + fail-soft(`brain.fail`).
1000
- * ⚠️ **테스트 seam 겸용**(리뷰 must-fix — 이게 없으면 timeout fail-soft 경로를 15초 없이 검증할 수
999
+ /** ★S4 P2b — brain 상담 1회 최대 대기(ms·기본 45초). 초과 시 abort + fail-soft(`brain.fail`).
1000
+ * ⚠️ **테스트 seam 겸용**(리뷰 must-fix — 이게 없으면 timeout fail-soft 경로를 45초 없이 검증할 수
1001
1001
  * 없다). 프로덕션은 기본값을 쓴다(호출부 미지정). */
1002
1002
  brainTimeoutMs?: number;
1003
1003
  /** ★S4 P3 **관측 시계 seam**(테스트 전용·기본 `Date.now`).
@@ -1520,8 +1520,8 @@ export async function runHeadlessGoalLoopPty(opts: HeadlessGoalLoopPtyOptions):
1520
1520
  let previousStallMetrics: { toolCalls: number; chars: number } | undefined;
1521
1521
  let keyframeSeq = 0; // 이 run 의 키프레임 순번(파일 키·seq 순 추출).
1522
1522
  // ⭐⭐ **wall-clock 상한**(리뷰 must-fix 2026-07-26) — 이 루프의 회계는 `i`(≈초·pollMs≈1000ms 가정)
1523
- // 기반이다. S4 P2b brain 상담이 tick 당 최대 `brainTimeoutMs`(기본 15초)를 **직렬 await** 하므로
1524
- // 전이가 반복되면 1 tick 이 ~16초가 되어 `maxWaitSec` 계약을 **최대 16배 초과**한다(600s → ~2.7h).
1523
+ // 기반이다. S4 P2b brain 상담이 tick 당 최대 `brainTimeoutMs`(기본 45초)를 **직렬 await** 하므로
1524
+ // 전이가 반복되면 1 tick 이 ~46초가 되어 `maxWaitSec` 계약을 초과할 수 있다.
1525
1525
  // ⇒ 기존 활동-grace 의미(i 기반)는 **그대로 두고** 절대 경과시간을 **추가 상한**으로만 얹는다.
1526
1526
  // 단조 안전: 더 **일찍** 멈출 뿐 늦게 멈추는 경우가 없다. brain 미주입이면 i≈초라 두 조건이 일치
1527
1527
  // (무회귀). ROADMAP §2 P1(종료 지연)의 회계 구조를 재작성하지 않는 최소 개입이다.
@@ -1563,7 +1563,7 @@ export async function runHeadlessGoalLoopPty(opts: HeadlessGoalLoopPtyOptions):
1563
1563
  debug.log('self-implement', 'poll.heartbeat', { ptyId, runId, i, alive: h.isAlive(), lastActivityI, silentFor, ...parentObservation });
1564
1564
  }
1565
1565
  // #24 finer 마커 — stall 시 "poll 루프 안(자식 구동·정상)" vs "다른 동기 op" 구분.
1566
- setEventLoopActivity(`headless:poll-${i}:alive-${h.isAlive() ? 1 : 0}`);
1566
+ setEventLoopActivity(`headless:poll:alive-${h.isAlive() ? 1 : 0}`);
1567
1567
  const delta = h.drainDelta();
1568
1568
  phase = 'snapshot';
1569
1569
  const snap = h.snapshot(); // ★ 1회 캡처 — 화면 릴레이 + GOAL-COMPLETE 공용(중복 snapshot 제거)
@@ -1697,6 +1697,7 @@ export async function runHeadlessGoalLoopPty(opts: HeadlessGoalLoopPtyOptions):
1697
1697
  if (opts.signal?.aborted) onBrainAbort();
1698
1698
  else opts.signal?.addEventListener('abort', onBrainAbort, { once: true });
1699
1699
  let timer: ReturnType<typeof setTimeout> | undefined;
1700
+ const brainStartedMs = Date.now();
1700
1701
  try {
1701
1702
  // Lost and unknown are the same ownership axis exercised by the stalled-screen
1702
1703
  // tests, not separate stances. Preserve their measured ownership and observation
@@ -1709,12 +1710,12 @@ export async function runHeadlessGoalLoopPty(opts: HeadlessGoalLoopPtyOptions):
1709
1710
  Promise.resolve(opts.brain.decide(controlObs, controller.signal)),
1710
1711
  new Promise<ControlDecision>((_, reject) => {
1711
1712
  // ⭐ **남은 절대 예산으로 clamp**(리뷰 must-fix 2R) — wall-clock 상한은 **tick 시작**에서만
1712
- // 검사하므로, deadline 직전에 시작된 상담이 그대로면 최대 brainTimeoutMs(기본 15초)만큼
1713
+ // 검사하므로, deadline 직전에 시작된 상담이 그대로면 최대 brainTimeoutMs(기본 45초)만큼
1713
1714
  // hard deadline 을 **초과**한다. 상담 자체를 남은 예산 안으로 묶어 창을 닫는다.
1714
1715
  // 최소 1ms(음수·0 이면 즉시 timeout → 다음 tick 상단 wall-clock 체크가 루프를 끊는다).
1715
1716
  const remainMs = Math.max(1, hardI * 1000 - (Date.now() - loopStartedMs));
1716
1717
  timer = setTimeout(() => { controller.abort(); reject(new Error('brain suggestion timeout')); },
1717
- Math.min(opts.brainTimeoutMs ?? 15_000, remainMs));
1718
+ Math.min(opts.brainTimeoutMs ?? 45_000, remainMs));
1718
1719
  }),
1719
1720
  ...(parentAbort ? [parentAbort] : []),
1720
1721
  ]);
@@ -1761,6 +1762,7 @@ export async function runHeadlessGoalLoopPty(opts: HeadlessGoalLoopPtyOptions):
1761
1762
  // 관측 계약은 화면 분류 원문을 보존한다. 완료 정보량·자동 정지는 아래의
1762
1763
  // `completionState` 폐쇄형 정규화만 소비하므로 blocked/idle 기록을 잃지 않는다.
1763
1764
  ptyId: h.id, runId, moment: 'in-round', step: i, trigger, state: curState, action: decision.action,
1765
+ durationMs: Date.now() - brainStartedMs,
1764
1766
  // `delivery-outcome` is a follow-up observation, not another verdict. Consumers count
1765
1767
  // either initial stage once per decision and can distinguish verdicts without input.
1766
1768
  supervisionRecordStage: decision.action === 'input' ? 'verdict-input' : 'verdict-no-input',
@@ -1848,7 +1850,7 @@ export async function runHeadlessGoalLoopPty(opts: HeadlessGoalLoopPtyOptions):
1848
1850
  }
1849
1851
  } catch (e) {
1850
1852
  // Parent cancel outranks suggestion observation: leave the poll loop immediately so PTY cleanup is not
1851
- // held by the 15s consultation timeout, even when a custom brain ignores its AbortSignal.
1853
+ // held by the 45s consultation timeout, even when a custom brain ignores its AbortSignal.
1852
1854
  if (opts.signal?.aborted) {
1853
1855
  timedOut = false;
1854
1856
  exitReason = 'abort';
@@ -1856,7 +1858,7 @@ export async function runHeadlessGoalLoopPty(opts: HeadlessGoalLoopPtyOptions):
1856
1858
  }
1857
1859
  debug.log('self-implement', 'brain.fail', {
1858
1860
  ptyId: h.id, runId, step: i, trigger, state: curState,
1859
- roundContextPresent,
1861
+ roundContextPresent, durationMs: Date.now() - brainStartedMs,
1860
1862
  error: String(e instanceof Error ? e.message : e).slice(0, 120),
1861
1863
  });
1862
1864
  } finally {
@@ -1,30 +1,40 @@
1
1
  import { spawnSync } from 'node:child_process';
2
- import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
2
+ import { existsSync, lstatSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
3
3
  import { tmpdir } from 'node:os';
4
- import { dirname, join } from 'node:path';
4
+ import { dirname, join, resolve } from 'node:path';
5
5
  import { debug } from '../debug/log.js';
6
6
  import { getUserConfig } from '../user-config.js';
7
7
  import { publicExposureFiles, runExposeGate } from './expose-gate.js';
8
8
  import { admitLandingMerge } from './frozen-merges.js';
9
9
  import { releaseGitDiffPaths, releasePathHold, releasePathHoldShouldPost, releasePathHoldComment, releasePathHoldCommentsArgs, RELEASE_PATH_LABEL } from '../self-dev/release-path-guard.js';
10
10
  import { detectTestInterference, parseFailureCount, runBunTest } from '../../scripts/detect-test-interference.js';
11
- import { runTestInterferenceGate } from '../../scripts/ci-test-interference-gate.js';
11
+ import { MAX_INSPECTED_TEST_FILES, runTestInterferenceGate } from '../../scripts/ci-test-interference-gate.js';
12
+ import { pwaGraph, pwaReach } from '../../scripts/ci-pwa-build-gate.js';
13
+
14
+ /** Use pr-land's PWA reachability (including its undecidable-graph build fallback), not a blanket src/** trigger. */
15
+ export function needsPwaBuild(files: readonly string[], repoRoot: string, graph: (root: string) => ReturnType<typeof pwaGraph> = pwaGraph): boolean {
16
+ return pwaReach(files, () => graph(repoRoot)).reaches;
17
+ }
12
18
 
13
19
  /**
14
- * The PWA's static build type-checks every `src/**` file it imports, under Next's stricter
15
- * `ProcessEnv` — a change that only touches `src/**` can break it while tsc and bun test stay
16
- * green (2026-09-27: two such changes kept main's PWA build red for two hours). Build whenever
17
- * app code or non-test source changed; test files are never imported by the PWA.
20
+ * Give a temporary checkout the source checkout's dependencies: link `<dir>/node_modules` when it is really installed
21
+ * there (its `marker` package exists), otherwise install into the candidate. Shared by host regate and the task agent's
22
+ * land worktree (TA-LAND-WORKTREE).
18
23
  */
19
- export function needsPwaBuild(files: readonly string[]): boolean {
20
- return files.some((file) => file.startsWith('apps/pwa/') || (file.startsWith('src/') && !/\.test\.tsx?$/.test(file)));
24
+ export function provideCheckoutDependencies(candidate: string, sourceRoot: string, dir: string, marker: string, install: (cwd: string) => void): void {
25
+ if (existsSync(join(candidate, dir, 'node_modules'))) return;
26
+ if (existsSync(join(sourceRoot, dir, 'node_modules', marker, 'package.json'))) {
27
+ symlinkSync(join(sourceRoot, dir, 'node_modules'), join(candidate, dir, 'node_modules'), 'dir');
28
+ } else install(join(candidate, dir));
21
29
  }
22
30
 
23
- export interface HostRegateInput { prNumber: number; headCommit: string; repoRoot: string; goalFile?: string; verifyOnly?: boolean; /** Called by a resume sweep that already holds this PR's claim. */ resumed?: true }
31
+ export interface HostRegateInput { prNumber: number; headCommit: string; repoRoot: string; goalFile?: string; verifyOnly?: boolean; /** TA-LIVE-LAND-2: run the full landing gates (release-path hold · neighbours · PR re-read) but stop before the freeze admission and `gh pr merge` — the task agent lands it later via `pr land --expected-head`. */ noMerge?: true; /** Called by a resume sweep that already holds this PR's claim. */ resumed?: true }
24
32
  export interface HostRegateResult { passed: boolean; failures: Array<{ step: string; detail: string }>; os: string; status?: 'passed' | 'failed' | 'unmeasured' | 'frozen'; /** verifyOnly: 실제로 얹어 잰 base 끝 */ baseCommit?: string }
33
+ export type InterferenceVerdict = { passed: boolean; detail?: string; unmeasured?: boolean; /** neighbour tests left out so the selection fits the inspection cap */ neighborsTrimmed?: number };
25
34
  export type HostRegateDeps = {
26
35
  command?: (bin: string, args: readonly string[], cwd: string, env?: NodeJS.ProcessEnv) => { status: number | null; stdout: string; stderr: string };
27
- interference?: (files: readonly string[], cwd: string) => Promise<{ passed: boolean; detail?: string; unmeasured?: boolean }>;
36
+ interference?: (files: readonly string[], cwd: string) => Promise<InterferenceVerdict>;
37
+ /** Legacy injection for callers that supply an ephemeral worktree instead of a locked slot. */
28
38
  makeTemp?: () => string;
29
39
  removeTemp?: (path: string) => void;
30
40
  acquire?: (repoRoot: string) => Promise<() => void>;
@@ -46,17 +56,28 @@ const defaultCommand: NonNullable<HostRegateDeps['command']> = (bin, args, cwd,
46
56
  };
47
57
 
48
58
  /** The informational pr-land gate always returns zero; enforce its measured report and the combined test result instead. */
49
- async function defaultInterference(files: readonly string[], cwd: string, opts: { neighbors?: boolean } = {}): Promise<{ passed: boolean; detail?: string; unmeasured?: boolean }> {
50
- const tests = files.filter((file) => /\.test\.tsx?$/.test(file));
51
- const neighbors = new Set<string>(tests);
52
- // verifyOnly(승인 탭)는 «이 PR 이 바꾼 시험»만 잰다 — 이웃 시험을 넣으면 간섭 관문의 상한(8)에 잘려 영영 «측정 불가»가 되고,
53
- // 이웃의 기존 실패가 이 PR 을 막는다(2026-09-28 #21239 실측: scripts/lib 이웃 9 → 상한 8 · nl-routing-measurement 기존 1 fail).
59
+ export async function defaultInterference(files: readonly string[], cwd: string, opts: { neighbors?: boolean; detect?: typeof detectTestInterference } = {}): Promise<InterferenceVerdict> {
60
+ const tests = [...new Set(files.filter((file) => /\.test\.tsx?$/.test(file)))].sort();
61
+ const changed = new Set(tests);
62
+ const neighbors = new Set<string>();
63
+ // verifyOnly(승인 탭)는 «이 PR 이 바꾼 시험»만 잰다 — 이웃의 기존 실패가 이 PR 을 막지 않게
64
+ // (2026-09-28 #21239 실측: scripts/lib 이웃 9 · nl-routing-measurement 기존 1 fail).
54
65
  if (opts.neighbors !== false) for (const file of tests) {
55
66
  for (const sibling of readdirSync(join(cwd, dirname(file)))) {
56
- if (/\.test\.tsx?$/.test(sibling)) neighbors.add(join(dirname(file), sibling));
67
+ const path = join(dirname(file), sibling);
68
+ if (/\.test\.tsx?$/.test(sibling) && !changed.has(path)) neighbors.add(path);
57
69
  }
58
70
  }
59
- const selected = [...neighbors].sort();
71
+ // 이웃이 간섭 관문의 상한(MAX_INSPECTED_TEST_FILES)을 넘기면 그 관문이 잘라 «영영 측정 불가»가 된다
72
+ // (2026-10-08 #25180·#25187 실측: src/self-implement 시험 175 · src/seat-loop 11). 바뀐 시험은 전부 두고 남는 칸만 이웃으로 채운다.
73
+ // 바뀐 시험만으로 상한을 넘으면 정직하게 «측정 불가»로 남는다.
74
+ const sortedNeighbors = [...neighbors].sort();
75
+ const room = Math.max(0, MAX_INSPECTED_TEST_FILES - tests.length);
76
+ const kept = tests.length > MAX_INSPECTED_TEST_FILES ? sortedNeighbors : sortedNeighbors.slice(0, room);
77
+ const neighborsTrimmed = sortedNeighbors.length - kept.length;
78
+ const trimmed = neighborsTrimmed > 0 ? { neighborsTrimmed } : {};
79
+ const trimNote = neighborsTrimmed > 0 ? ` · neighbours trimmed ${neighborsTrimmed} to fit inspection cap ${MAX_INSPECTED_TEST_FILES}` : '';
80
+ const selected = [...tests, ...kept].sort();
60
81
  if (!selected.length) return { passed: true };
61
82
  // 간섭 관문은 시험 파일이 둘 이상일 때만 잰다 — 하나면 간섭이라는 말이 없으니 그 파일을 한 번 돌려 실패 수로 본다.
62
83
  if (selected.length === 1) {
@@ -69,13 +90,13 @@ async function defaultInterference(files: readonly string[], cwd: string, opts:
69
90
  let report: Awaited<ReturnType<typeof detectTestInterference>> | undefined;
70
91
  await runTestInterferenceGate({
71
92
  args: ['--changed-files', ...selected], log: () => {},
72
- detect: async (paths) => (report = await detectTestInterference(paths, (batch) => runBunTest(batch, undefined, cwd))),
93
+ detect: async (paths) => (report = await (opts.detect ?? detectTestInterference)(paths, (batch) => runBunTest(batch, undefined, cwd))),
73
94
  });
74
- if (!report || report.status === 'unmeasurable' || selected.length > report.order.length) return { passed: false, unmeasured: true, detail: 'test interference measurement unavailable or truncated' };
95
+ if (!report || report.status === 'unmeasurable' || selected.length > report.order.length) return { passed: false, unmeasured: true, ...trimmed, detail: `test interference measurement unavailable or truncated (selected ${selected.length}, changed tests ${tests.length}, cap ${MAX_INSPECTED_TEST_FILES})${trimNote}` };
75
96
  if (report.isolatedFailures !== 0 || report.combinedFailures !== 0 || report.status === 'interference') {
76
- return { passed: false, detail: `isolated=${report.isolatedFailures}, combined=${report.combinedFailures}, interference=${report.status}` };
97
+ return { passed: false, ...trimmed, detail: `isolated=${report.isolatedFailures}, combined=${report.combinedFailures}, interference=${report.status}${trimNote}` };
77
98
  }
78
- return { passed: true };
99
+ return { passed: true, ...trimmed, ...(trimNote ? { detail: trimNote.slice(3) } : {}) };
79
100
  }
80
101
 
81
102
  const SLOT_WAIT_MS = 30 * 60_000;
@@ -92,7 +113,7 @@ function slotOwnerAlive(slot: string): boolean {
92
113
  }
93
114
  }
94
115
 
95
- export async function acquireSlot(repoRoot: string, opts: { waitMs?: number; pollMs?: number; now?: () => number } = {}): Promise<() => void> {
116
+ export async function acquireSlot(repoRoot: string, opts: { waitMs?: number; pollMs?: number; now?: () => number } = {}): Promise<(() => void) & { worktree: string }> {
96
117
  const gitDir = spawnSync('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], { cwd: repoRoot, encoding: 'utf8' });
97
118
  if (gitDir.status !== 0 || !gitDir.stdout.trim()) throw new Error('git common directory unavailable for host regate lock');
98
119
  const root = join(gitDir.stdout.trim(), 'elanous-host-regate');
@@ -105,7 +126,7 @@ export async function acquireSlot(repoRoot: string, opts: { waitMs?: number; pol
105
126
  try {
106
127
  mkdirSync(slot);
107
128
  writeFileSync(join(slot, 'pid'), String(process.pid));
108
- return () => rmSync(slot, { recursive: true, force: true });
129
+ return Object.assign(() => rmSync(slot, { recursive: true, force: true }), { worktree: join(root, `worktree-${i}`) });
109
130
  } catch (error) {
110
131
  if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
111
132
  // A slot left by a crashed host process would otherwise block every later run.
@@ -121,6 +142,24 @@ export async function acquireSlot(repoRoot: string, opts: { waitMs?: number; pol
121
142
  }
122
143
  }
123
144
 
145
+ function removeBrokenSlotRegistration(repoRoot: string, worktree: string): void {
146
+ const gitDir = spawnSync('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], { cwd: repoRoot, encoding: 'utf8' });
147
+ if (gitDir.status !== 0 || !gitDir.stdout.trim()) throw new Error('git common directory unavailable for slot repair');
148
+ const registrations = join(gitDir.stdout.trim(), 'worktrees');
149
+ if (!existsSync(registrations)) return;
150
+ for (const name of readdirSync(registrations)) {
151
+ const registration = join(registrations, name);
152
+ if (!lstatSync(registration).isDirectory()) continue;
153
+ const pointer = join(registration, 'gitdir');
154
+ if (!existsSync(pointer) || lstatSync(pointer).isSymbolicLink()) continue;
155
+ if (resolve(readFileSync(pointer, 'utf8').trim()) !== resolve(worktree, '.git')) continue;
156
+ rmSync(registration, { recursive: true });
157
+ }
158
+ }
159
+
160
+ /** Callers: podSelfImplementSpawn in src/task-orchestrator/surfaces/self-implement-pod.ts calls
161
+ * (options.hostRegate ?? runHostRegate)({ prNumber, headCommit, repoRoot: hostRoot, ... });
162
+ * sweepFrozenMerges in frozen-merges.ts also calls runHostRegate(entry); landing queue serialization stays there. */
124
163
  export async function runHostRegate(input: HostRegateInput, deps: HostRegateDeps = {}): Promise<HostRegateResult> {
125
164
  const command = deps.command ?? defaultCommand;
126
165
  const log = deps.log ?? ((event: 'passed' | 'failed' | 'unmeasured' | 'base-raced', data: Record<string, unknown>) => debug.log('harness.host-regate', event, data));
@@ -129,13 +168,27 @@ export async function runHostRegate(input: HostRegateInput, deps: HostRegateDeps
129
168
  let base = '';
130
169
  let worktree: string | undefined;
131
170
  let attached = false;
171
+ let ephemeral = false;
172
+ let slotCommonDir: string | undefined;
173
+ const verifySlot = (): void => {
174
+ if (!worktree || !slotCommonDir || lstatSync(worktree).isSymbolicLink() || !lstatSync(worktree).isDirectory()) throw new Error('slot worktree mismatch');
175
+ const pointer = join(worktree, '.git');
176
+ if (!lstatSync(pointer).isFile() || lstatSync(pointer).isSymbolicLink()) throw new Error('slot worktree mismatch');
177
+ const common = realpathSync(run('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], worktree));
178
+ const registration = realpathSync(run('git', ['rev-parse', '--path-format=absolute', '--git-dir'], worktree));
179
+ if (common !== slotCommonDir || dirname(registration) !== join(slotCommonDir, 'worktrees')
180
+ || resolve(readFileSync(join(registration, 'gitdir'), 'utf8').trim()) !== resolve(pointer)
181
+ || resolve(readFileSync(pointer, 'utf8').trim().replace(/^gitdir: /, '')) !== registration
182
+ || run('git', ['rev-parse', '--show-toplevel'], worktree) !== worktree) throw new Error('slot worktree mismatch');
183
+ };
132
184
  let release: (() => void) | undefined;
133
185
  let endLanding: ((merged?: boolean) => void) | undefined;
134
186
  let landed = false;
135
187
  let verifiedBase: string | undefined;
188
+ let interferenceNote: Record<string, unknown> = {};
136
189
  const result = (event: 'passed' | 'failed' | 'unmeasured', step?: string, detail?: string): HostRegateResult => {
137
190
  if (step) failures.push({ step, detail: detail ?? 'unknown' });
138
- log(event, { pr: input.prNumber, files, os: process.platform, ...(step ? { failedStep: step } : {}) });
191
+ log(event, { pr: input.prNumber, files, os: process.platform, ...interferenceNote, ...(step ? { failedStep: step, detail: (detail ?? 'unknown').slice(0, 300) } : {}) });
139
192
  return { passed: event === 'passed', failures, os: process.platform, ...(input.verifyOnly ? { status: event, ...(verifiedBase ? { baseCommit: verifiedBase } : {}) } : {}) };
140
193
  };
141
194
  const run = (bin: string, args: readonly string[], cwd: string, env?: NodeJS.ProcessEnv): string => {
@@ -155,16 +208,57 @@ export async function runHostRegate(input: HostRegateInput, deps: HostRegateDeps
155
208
  const baseRefName = view.baseRefName;
156
209
  // verifyOnly(승인 탭): PR 에 기록된 base(baseRefOid)는 main 의 «지금 끝»보다 늙을 수 있다 — 지금 끝에 얹어 잰다.
157
210
  let baseCommit = view.baseRefOid!;
211
+ // REGATE-STALE-BASE: GitHub's baseRefOid can stay at the PR-open tip after main moves. After the bounded re-reads the
212
+ // regate measures on the fetched base tip (what the squash merge lands on) and records the stale PR base instead of failing.
213
+ // The closing PR re-read must still show the last PR base seen here (a PR that changed again is not the PR we measured).
214
+ let stalePrBase: string | undefined;
215
+ const initialPrBase = baseCommit;
216
+ let buildPwa = false;
158
217
  try {
159
218
  run('git', ['fetch', 'origin', `refs/heads/${baseRefName}`], input.repoRoot);
160
- const fetchedBase = run('git', ['rev-parse', 'FETCH_HEAD'], input.repoRoot);
219
+ let fetchedBase = run('git', ['rev-parse', 'FETCH_HEAD'], input.repoRoot);
161
220
  if (input.verifyOnly) { baseCommit = fetchedBase; verifiedBase = fetchedBase; }
162
- else if (fetchedBase !== baseCommit) throw new Error('fetched PR base differs from checked SHA');
221
+ else {
222
+ for (let attempt = 1; fetchedBase !== baseCommit; attempt++) {
223
+ debug.log('harness.host-regate', 'base-moved-retry', { pr: input.prNumber, attempt, checked: baseCommit, fetched: fetchedBase });
224
+ if (attempt === 3) {
225
+ stalePrBase = baseCommit;
226
+ debug.log('harness.host-regate', 'base-stale', { pr: input.prNumber, prBaseRefOidInitial: initialPrBase, prBaseRefOid: baseCommit, fetched: fetchedBase, candidateBase: fetchedBase });
227
+ baseCommit = fetchedBase;
228
+ break;
229
+ }
230
+ await new Promise((resolve) => setTimeout(resolve, 1_000));
231
+ view = readPr();
232
+ if (view.headRefOid !== input.headCommit || view.state !== 'OPEN' || view.isDraft !== false || view.baseRefName !== baseRefName || !/^[0-9a-f]{40}$/i.test(view.baseRefOid ?? '')) {
233
+ return result('unmeasured', 'pr-head', 'PR head, base commit, ready state or open state unavailable or changed');
234
+ }
235
+ baseCommit = view.baseRefOid!;
236
+ run('git', ['fetch', 'origin', `refs/heads/${baseRefName}`], input.repoRoot);
237
+ fetchedBase = run('git', ['rev-parse', 'FETCH_HEAD'], input.repoRoot);
238
+ }
239
+ }
163
240
  run('git', ['fetch', 'origin', `refs/pull/${input.prNumber}/head`], input.repoRoot);
164
241
  if (run('git', ['rev-parse', 'FETCH_HEAD'], input.repoRoot) !== input.headCommit) throw new Error('fetched PR head differs from checked SHA');
165
- worktree = (deps.makeTemp ?? (() => mkdtempSync(join(tmpdir(), 'elanous-host-regate-'))))();
166
- run('git', ['worktree', 'add', '--detach', worktree, baseCommit], input.repoRoot);
167
- attached = true;
242
+ const slotWorktree = (release as (() => void) & { worktree?: string }).worktree;
243
+ ephemeral = !!deps.makeTemp || !slotWorktree;
244
+ worktree = deps.makeTemp?.() ?? slotWorktree ?? mkdtempSync(join(tmpdir(), 'host-regate-'));
245
+ if (ephemeral && slotWorktree && resolve(worktree) === resolve(slotWorktree)) throw new Error('temporary worktree overlaps locked slot');
246
+ if (!ephemeral && !deps.acquire) {
247
+ slotCommonDir = realpathSync(run('git', ['rev-parse', '--path-format=absolute', '--git-common-dir'], input.repoRoot));
248
+ }
249
+ if (!ephemeral && existsSync(worktree)) {
250
+ if (slotCommonDir) verifySlot();
251
+ attached = true;
252
+ // A previous host may have died mid-merge; never carry its index or untracked files into this run.
253
+ run('git', ['reset', '--hard'], worktree);
254
+ run('git', ['clean', '-fdx', '-e', 'node_modules', '-e', '.next', '-e', '*.tsbuildinfo'], worktree);
255
+ run('git', ['checkout', '--detach', baseCommit], worktree);
256
+ }
257
+ if (!attached) {
258
+ if (!ephemeral && !deps.acquire) removeBrokenSlotRegistration(input.repoRoot, worktree);
259
+ run('git', ['worktree', 'add', '--detach', worktree, baseCommit], input.repoRoot);
260
+ attached = true;
261
+ }
168
262
  if (run('git', ['rev-parse', 'HEAD'], worktree) !== baseCommit) throw new Error('worktree base HEAD mismatch');
169
263
  base = run('git', ['merge-base', baseCommit, input.headCommit], worktree);
170
264
  files = run('git', ['diff', '--name-only', base, input.headCommit], worktree).split('\n').filter(Boolean);
@@ -200,17 +294,14 @@ export async function runHostRegate(input: HostRegateInput, deps: HostRegateDeps
200
294
  // a temporary checkout whose node_modules is empty or purged; linking it turned every gate into
201
295
  // «Cannot find package 'typescript'» (unmeasured · 2026-09-29 #21239). Install into the candidate instead.
202
296
  const candidate = worktree;
203
- const provide = (dir: string, marker: string): void => {
204
- if (existsSync(join(candidate, dir, 'node_modules'))) return;
205
- if (existsSync(join(input.repoRoot, dir, 'node_modules', marker, 'package.json'))) {
206
- symlinkSync(join(input.repoRoot, dir, 'node_modules'), join(candidate, dir, 'node_modules'), 'dir');
207
- } else run('bun', ['install', '--frozen-lockfile'], join(candidate, dir));
208
- };
297
+ const provide = (dir: string, marker: string): void => provideCheckoutDependencies(candidate, input.repoRoot, dir, marker, (cwd) => { run('bun', ['install', '--frozen-lockfile'], cwd); });
209
298
  provide('', 'typescript');
210
- if (needsPwaBuild(files) && existsSync(join(worktree, 'apps/pwa'))) provide('apps/pwa', 'next');
299
+ buildPwa = needsPwaBuild(files, worktree);
300
+ if (buildPwa && existsSync(join(worktree, 'apps/pwa'))) provide('apps/pwa', 'next');
211
301
  } catch (e) { return result('unmeasured', 'worktree', String(e)); }
212
302
  try {
213
303
  const interference = await (deps.interference ?? ((f: readonly string[], c: string) => defaultInterference(f, c, { neighbors: !input.verifyOnly })))(files, worktree);
304
+ if (interference.neighborsTrimmed) interferenceNote = { neighborsTrimmed: interference.neighborsTrimmed, interferenceDetail: (interference.detail ?? '').slice(0, 300) };
214
305
  if (!interference.passed) return result(interference.unmeasured ? 'unmeasured' : 'failed', 'test-interference', interference.detail);
215
306
  } catch (e) { return result('unmeasured', 'test-interference', String(e)); }
216
307
  // Landing can also be initiated by the host after the child gate; judge the checked PR here too.
@@ -230,19 +321,21 @@ export async function runHostRegate(input: HostRegateInput, deps: HostRegateDeps
230
321
  try { run('bun', ['scripts/ci-isolation-hardcode-gate.ts', '--changed-files', ...files], worktree); }
231
322
  catch (e) { return result(/\[isolation-gate\] FAIL/.test(String(e)) ? 'failed' : 'unmeasured', 'isolation-gate', String(e)); }
232
323
  }
233
- if (needsPwaBuild(files)) {
324
+ if (buildPwa) {
234
325
  try { run('bun', ['bin/elanous.mjs', '--test', 'nexus', 'build'], worktree); }
235
326
  catch (e) { return result(String(e).includes('command unavailable') ? 'unmeasured' : 'failed', 'nexus-build', String(e)); }
236
327
  }
237
328
  let current: PrView;
238
329
  try { current = readPr(); }
239
330
  catch (e) { return result('unmeasured', 'pr-view', String(e)); }
240
- if (current.headRefOid !== input.headCommit || current.baseRefName !== baseRefName || (!input.verifyOnly && current.baseRefOid !== baseCommit) || current.state !== 'OPEN' || current.isDraft !== false) {
331
+ if (current.headRefOid !== input.headCommit || current.baseRefName !== baseRefName || (!input.verifyOnly && current.baseRefOid !== (stalePrBase ?? baseCommit)) || current.state !== 'OPEN' || current.isDraft !== false) {
241
332
  return result('unmeasured', 'pr-base-changed', 'PR head or base changed during host regate; rerun against the new base');
242
333
  }
243
334
  // --match-head-commit pins the head. gh has no base pin, so the base was re-read just
244
335
  // above; the seconds between that read and the merge are checked after the fact below.
245
336
  if (input.verifyOnly) return result('passed');
337
+ // TA-REJUDGE-ON-HEAD — 병합 없는 재게이트는 «잰 base 끝»을 같이 낸다(겹침 증거의 gate.baseCommit).
338
+ if (input.noMerge) return { ...result('passed'), status: 'passed', baseCommit };
246
339
  const landing = admitLandingMerge({ prNumber: input.prNumber, headCommit: input.headCommit, repoRoot: input.repoRoot, ...(input.goalFile ? { goalFile: input.goalFile } : {}) }, deps.freezeRoot, {}, input.resumed ? undefined : { prNumber: input.prNumber, repoRoot: input.repoRoot, headCommit: input.headCommit }, { prodFreezeRoot: deps.prodFreezeRoot });
247
340
  if (landing.kind !== 'merge') {
248
341
  debug.log('harness.merge', 'frozen', { pr: input.prNumber, ...(landing.kind === 'held' ? { reason: landing.freeze.reason, until: landing.freeze.until } : { resumedElsewhere: true }) });
@@ -281,10 +374,22 @@ export async function runHostRegate(input: HostRegateInput, deps: HostRegateDeps
281
374
  return result('unmeasured', 'host-regate', String(e));
282
375
  } finally {
283
376
  try { endLanding?.(landed); } catch (e) { log('unmeasured', { pr: input.prNumber, files, os: process.platform, failedStep: 'landing-release', detail: String(e) }); }
284
- try { if (attached && worktree) run('git', ['worktree', 'remove', '--force', worktree], input.repoRoot); }
285
- catch (e) { log('unmeasured', { pr: input.prNumber, files, os: process.platform, failedStep: 'cleanup', detail: String(e) }); }
286
- try { if (worktree) (deps.removeTemp ?? ((path) => rmSync(path, { recursive: true, force: true })))(worktree); }
287
- catch (e) { log('unmeasured', { pr: input.prNumber, files, os: process.platform, failedStep: 'cleanup', detail: String(e) }); }
377
+ try {
378
+ if (attached && worktree) {
379
+ if (slotCommonDir) verifySlot();
380
+ run('git', ['reset', '--hard'], worktree);
381
+ run('git', ['clean', '-fdx', '-e', 'node_modules', '-e', '.next', '-e', '*.tsbuildinfo'], worktree);
382
+ }
383
+ } catch (e) { log('unmeasured', { pr: input.prNumber, files, os: process.platform, failedStep: 'cleanup', detail: String(e) }); }
384
+ if (ephemeral && worktree) {
385
+ try {
386
+ if (attached) run('git', ['worktree', 'remove', '--force', worktree], input.repoRoot);
387
+ } catch (e) { log('unmeasured', { pr: input.prNumber, files, os: process.platform, failedStep: 'cleanup', detail: String(e) }); }
388
+ try {
389
+ if (deps.removeTemp) deps.removeTemp(worktree);
390
+ else rmSync(worktree, { recursive: true, force: true });
391
+ } catch (e) { log('unmeasured', { pr: input.prNumber, files, os: process.platform, failedStep: 'cleanup', detail: String(e) }); }
392
+ }
288
393
  try { release?.(); }
289
394
  catch (e) { log('unmeasured', { pr: input.prNumber, files, os: process.platform, failedStep: 'lock', detail: String(e) }); }
290
395
  if (failures.length && failures[0]?.step !== 'release-path-hold') {