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
@@ -0,0 +1,53 @@
1
+ import type { GraphRunState } from '../../src/graph-runner/runner.js';
2
+ import { publicWaiverReason } from './known-issues-node.js';
3
+
4
+ export interface AcceptedRegression { id: string; note: string }
5
+
6
+ /** Merge explicit public issues with the saved release input without changing the ledger shape. */
7
+ export function releaseResumeAcceptedRegressions(state: GraphRunState, additions: AcceptedRegression[], from?: string): AcceptedRegression[] {
8
+ if (!Array.isArray(additions) || additions.some((issue) => !issue || typeof issue.id !== 'string' || !issue.id.trim() || typeof issue.note !== 'string' || !issue.note.trim())) {
9
+ throw new Error('acceptedRegressions must be an array of {id, note}');
10
+ }
11
+ const input = state.input;
12
+ if (!input || typeof input !== 'object' || Array.isArray(input) || typeof (input as { version?: unknown }).version !== 'string') throw new Error('release run has no input');
13
+ const existing = (input as { acceptedRegressions?: unknown }).acceptedRegressions;
14
+ if (existing !== undefined && (!Array.isArray(existing) || existing.some((issue) => !issue || typeof issue.id !== 'string' || !issue.id.trim() || typeof issue.note !== 'string' || !issue.note.trim()))) {
15
+ throw new Error('saved acceptedRegressions is invalid');
16
+ }
17
+ // A rerun of a formerly waived node supersedes only that node's recorded waiver;
18
+ // independently supplied accepted issues (including similarly named IDs) are not inferred to be waivers.
19
+ const prior = (existing ?? []) as AcceptedRegression[];
20
+ // Every waived record at or after the restart boundary is cut from the ledger, so each one's issue retires too.
21
+ const start = from === undefined ? -1 : state.path.indexOf(from);
22
+ const retired = start < 0 ? [] : state.nodes.slice(start)
23
+ .filter((record) => record.waiver && record.executed === false && record.ok === true)
24
+ .map((record) => ({ id: `waive:${record.nodeId}`, note: record.waiver!.reason }));
25
+ const combined = [...prior.filter((issue) => !retired.some((gone) => gone.id === issue.id && gone.note === issue.note)), ...additions];
26
+ if (new Set(combined.map(({ id }) => id)).size !== combined.length) throw new Error('acceptedRegressions IDs must be unique');
27
+ return combined;
28
+ }
29
+
30
+ /** Only the recorded failure at the restart boundary may be waived. `--from` is never a waiver. */
31
+ export function releaseResumeWaiver(
32
+ state: GraphRunState,
33
+ opts: { from: string; waive?: string; reason?: string; acceptedRegressions?: AcceptedRegression[] },
34
+ ): { nodeId: string; reason: string; acceptedRegressions: AcceptedRegression[] } | undefined {
35
+ if ((opts.waive === undefined) !== (opts.reason === undefined)) throw new Error('--waive <node> and --reason <text> must be supplied together');
36
+ if (opts.waive !== undefined && !opts.waive.trim()) throw new Error('--waive must not be empty');
37
+ if (opts.waive === undefined) return undefined;
38
+ const reason = opts.reason?.trim();
39
+ if (!reason) throw new Error('--reason must not be empty');
40
+ publicWaiverReason(reason);
41
+ if (opts.from !== opts.waive) throw new Error('--from must name the waived node; --from alone does not waive a failure');
42
+ const index = state.path.indexOf(opts.waive);
43
+ if (index < 0 || state.path.lastIndexOf(opts.waive) !== index || state.nodes[index]?.nodeId !== opts.waive || state.nodes[index]?.ok !== false ||
44
+ state.nodes[index]?.executed !== true || state.path.at(-2) !== opts.waive || state.path.at(-1) !== 'failed' || state.nodes.at(-1)?.nodeId !== 'failed') {
45
+ throw new Error(`--waive ${opts.waive} requires the failed executable node on the saved path`);
46
+ }
47
+ // Only user-visible, non-publication checks can become accepted regressions; build, safety and approval gates stay blocking.
48
+ if (!['mac-smoke', 'tui'].includes(opts.waive)) {
49
+ throw new Error(`--waive ${opts.waive} cannot waive a safety, side-effect or approval node`);
50
+ }
51
+ return { nodeId: opts.waive, reason, acceptedRegressions: releaseResumeAcceptedRegressions(state,
52
+ [...(opts.acceptedRegressions ?? []), { id: `waive:${opts.waive}`, note: reason }]) };
53
+ }
@@ -1,6 +1,7 @@
1
1
  import { readdirSync, readFileSync, statSync } from 'node:fs';
2
2
  import { basename, dirname, join, resolve } from 'node:path';
3
3
  import { debug } from '../../src/debug/log.js';
4
+ import { readJunitFileSeconds } from './gate-method';
4
5
 
5
6
  /** Plan weights for a Pod sweep: wall-scaled when the previous cut recorded shard wall times, junit seconds otherwise. */
6
7
  export function planDurations(durationSource: string | undefined): { durations: Map<string, number>; wall?: { shards: number; scaledFiles: number }; fallback?: string } {
@@ -66,21 +67,12 @@ export function logPlanWalltime(wall: { shards: number; scaledFiles: number } |
66
67
  export function readFileDurations(dir: string): Map<string, number> {
67
68
  const durations = new Map<string, number>();
68
69
  let names: string[];
69
- const entities: Record<string, string> = { '&amp;': '&', '&quot;': '"', '&apos;': "'", '&lt;': '<', '&gt;': '>' };
70
70
  try { names = readdirSync(dir).filter((name) => name.endsWith('.junit.xml')).sort(); }
71
71
  catch { return durations; }
72
72
  for (const name of names) {
73
73
  try {
74
- const xml = readFileSync(join(dir, name), 'utf8');
75
- for (const match of xml.matchAll(/<testsuite\b([^>]*)>/g)) {
76
- const attrs = match[1]!;
77
- const file = /\bfile="([^"]+)"/.exec(attrs)?.[1];
78
- const rawTime = /\btime="([^"]+)"/.exec(attrs)?.[1];
79
- if (!file || rawTime === undefined) continue;
80
- const seconds = Number(rawTime);
81
- if (!Number.isFinite(seconds) || seconds < 0) continue;
82
- const path = file.replace(/&(?:amp|quot|apos|lt|gt);/g, (entity) => entities[entity]!);
83
- durations.set(path, Math.max(durations.get(path) ?? 0, seconds));
74
+ for (const [file, seconds] of readJunitFileSeconds(readFileSync(join(dir, name), 'utf8'))) {
75
+ durations.set(file, Math.max(durations.get(file) ?? 0, seconds));
84
76
  }
85
77
  } catch { /* One unreadable report must not discard the others. */ }
86
78
  }
@@ -28,6 +28,28 @@ export function tuiVerdict(checks: readonly TuiCheck[]): 'pass' | 'fail' {
28
28
  return checks.every((c) => c.pass) ? 'pass' : 'fail';
29
29
  }
30
30
 
31
+ /** `tui-sim-node.ts --json` prints the raw result (no `outcome`); `node-verdict.ts tui` adds it. Same rule here so a
32
+ * prefetched raw result is judged exactly like the wrapped node result: exit 0 with pass|flaky → ok. */
33
+ export function withTuiOutcome(status: number | null, data: Record<string, unknown> | null): Record<string, unknown> | null {
34
+ if (!data) return null;
35
+ const outcome = status === 0 && (data.verdict === 'pass' || data.verdict === 'flaky') ? 'ok' : status === 1 ? 'fail' : 'error';
36
+ return { ...data, outcome };
37
+ }
38
+
39
+ export function reusableTui(data: unknown, commit: string): Record<string, unknown> | null {
40
+ if (!data || typeof data !== 'object' || Array.isArray(data)) return null;
41
+ const value = data as Record<string, unknown>;
42
+ if (value.outcome !== 'ok' || value.commit !== commit || (value.verdict !== 'pass' && value.verdict !== 'flaky')
43
+ || (value.verdict === 'pass' ? value.attempts !== 1 : value.attempts !== 2)
44
+ || !Array.isArray(value.checks) || value.checks.length !== 6) return null;
45
+ const ids = ['boot', 'prompt', 'status-bar', 'help-opens', 'help-closes', 'no-error-text'];
46
+ if (value.checks.some((check: unknown, i: number) => !check || typeof check !== 'object'
47
+ || (check as TuiCheck).id !== ids[i] || (check as TuiCheck).pass !== true
48
+ || typeof (check as TuiCheck).detail !== 'string')) return null;
49
+ if (value.regress === null || typeof value.regress !== 'object' || Array.isArray(value.regress)) return null;
50
+ return value;
51
+ }
52
+
31
53
  export type TuiRegress = {
32
54
  pass: number;
33
55
  fail: number;
@@ -11,6 +11,7 @@ import { debug } from '../../src/debug/log.js';
11
11
  import { runGraph, type GraphRunState } from '../../src/graph-runner/runner.js';
12
12
  import { releaseRunUniverse } from './release-universe.js';
13
13
  import { baseVersion, isStableVersion, nextPrereleaseVersion, type PrereleaseKind } from './release-version.js';
14
+ import { publishAtError } from './publish-at.js';
14
15
 
15
16
  const VERSION = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/;
16
17
  const GRAPH = join(import.meta.dir, '../../graphs/release/release-loop.yaml');
@@ -40,6 +41,7 @@ export interface ReleaseRunInput extends ReleaseLoopConfig {
40
41
  cutCommit?: string;
41
42
  gatePodPool: string;
42
43
  forceFreeze?: boolean;
44
+ publishAt?: string;
43
45
  /** RELEASE-BRANCH: version-release cuts release/<v> from main HEAD and bumps only the branch. */
44
46
  branchCut?: boolean;
45
47
  }
@@ -117,7 +119,7 @@ export function buildReleaseRunInput(version: string, deps: UnattendedReleaseDep
117
119
 
118
120
  /** Fail closed at the entry boundary, before any graph node can change a release. */
119
121
  export async function runUnattendedRelease(
120
- opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind },
122
+ opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string },
121
123
  deps: UnattendedReleaseDeps = {},
122
124
  ): Promise<{ input: ReleaseRunInput; dryRun: boolean; state?: GraphRunState }> {
123
125
  // RELEASE-BRANCH (10-06): the default cut is a release branch, so main keeps landing and the run no longer needs a
@@ -134,6 +136,11 @@ export async function runUnattendedRelease(
134
136
  }
135
137
  const version = resolveRunVersion(opts.version, opts.prerelease, deps);
136
138
  const input = buildReleaseRunInput(version, deps, opts.cutCommit);
139
+ if (opts.publishAt !== undefined) {
140
+ const invalid = publishAtError(opts.publishAt);
141
+ if (invalid) throw new Error(invalid);
142
+ input.publishAt = new Date(opts.publishAt).toISOString();
143
+ }
137
144
  if (opts.forceFreeze) input.forceFreeze = true;
138
145
  if (branchCut) input.branchCut = true;
139
146
  debug.log('release.run', 'input', { version, requested: opts.version, branchCut, prerelease: opts.prerelease ?? null, dryRun: opts.dryRun === true });
@@ -0,0 +1,39 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ import { searchFirecrawl } from '../skills/omni-crawl/src/firecrawl.js';
3
+
4
+ type Check = { identifier: string; query: string; inspectedLead: { url: string } | null };
5
+ type Search = (query: string, options: { limit: number }) => Promise<{ items: Array<{ url?: string }> }>;
6
+
7
+ export async function recheckCooAdminLeads(checks: Check[], search: Search): Promise<string[]> {
8
+ let verified = 0;
9
+ let withUrl = 0;
10
+ let withoutUrl = 0;
11
+ const lines: string[] = [];
12
+ for (const check of checks) {
13
+ const result = await search(check.query, { limit: 3 });
14
+ const recordedUrl = check.inspectedLead?.url?.trim();
15
+ if (!recordedUrl) {
16
+ withoutUrl++;
17
+ lines.push(`${check.identifier} hits=${result.items.length} recordedUrl=none (not verified) query=${check.query}`);
18
+ continue;
19
+ }
20
+ withUrl++;
21
+ const found = result.items.some(item => item.url === recordedUrl);
22
+ if (found) verified++;
23
+ lines.push(`${check.identifier} hits=${result.items.length} recordedUrlVerified=${found} query=${check.query}`);
24
+ }
25
+ lines.push(`SEARCH checked=${checks.length} recordedUrlVerified=${verified}/${withUrl} noRecordedUrl=${withoutUrl} recordedUrlNotInCurrentTop3=${withUrl - verified} (search rankings change; no official date inferred)`);
26
+ return lines;
27
+ }
28
+
29
+ if (import.meta.main) {
30
+ const evidence = JSON.parse(await readFile(new URL('../src/domains/coo-admin-dates.evidence.json', import.meta.url), 'utf8')) as {
31
+ verifiedIssues: Array<{ identifier: string }>;
32
+ research: { issueChecks: Check[] };
33
+ };
34
+ const checks = evidence.research.issueChecks;
35
+ if (checks.length !== 29 || checks.some((check, index) => check.identifier !== evidence.verifiedIssues[index]?.identifier || !check.query)) {
36
+ throw new Error('29 issue search queries do not match recorded issue identifiers');
37
+ }
38
+ for (const line of await recheckCooAdminLeads(checks, searchFirecrawl)) console.log(line);
39
+ }
@@ -17,6 +17,7 @@ import { recordOutbound } from '../../src/domains/outbound-alert.js';
17
17
  import { listSelfDevRuns, runSummaryLine, selfDevRunsDir } from '../../src/self-dev/run-store.js';
18
18
  import { runDraftSweep } from '../../src/self-dev/draft-sweep.js';
19
19
  import { retroBriefingLines } from '../../src/retro/daily.js';
20
+ import { dispatchCooAdmin } from '../../src/domains/coo-admin-tool.js';
20
21
 
21
22
  export type Section<T> = { status: 'ok'; value: T } | { status: 'unreadable'; reason: string };
22
23
  export type Landing = { title: string; seat: string; mergedAt: string; prNumber?: number };
@@ -348,6 +349,47 @@ function sendReview(file: string, text: string, target: { chatId: number; botTok
348
349
  finally { db.close(); }
349
350
  }
350
351
 
352
+ function adminSection(markdown: string): string {
353
+ return markdown.split('## ⑧ 행정\n')[1]?.split('\n\n## ')[0]?.trim() ?? '측정 불가 · 행정 절 없음';
354
+ }
355
+
356
+ function adminMessage(markdown: string): string {
357
+ const text = adminSection(markdown);
358
+ if (text.length <= 1_800) return `## ⑧ 행정\n${text}`;
359
+ // Keep the full ordered read in the report. Reserve one dated link from each required
360
+ // category before spending the remaining transport budget on earlier deadlines.
361
+ const groups: { heading: string; items: string[] }[] = [];
362
+ for (const line of text.split('\n')) {
363
+ if (/^(?:지난 기한|14일 안 기한) \d+건$/.test(line) || line.startsWith('그 밖 · ')) {
364
+ groups.push({ heading: line, items: [] });
365
+ } else if (line.startsWith('- ') && groups.length) {
366
+ groups.at(-1)!.items.push(line);
367
+ } else if (line.startsWith(' https://') && groups.at(-1)?.items.length) {
368
+ const group = groups.at(-1)!;
369
+ group.items[group.items.length - 1] += `\n${line}`;
370
+ }
371
+ }
372
+ if (!groups.some(group => group.heading.startsWith('지난 기한 ')) || !groups.some(group => group.heading.startsWith('14일 안 기한 ')))
373
+ return `## ⑧ 행정\n${text.slice(0, 1_800)}\n… 전체 목록은 리뷰 파일 참조`;
374
+ const compact = (item: string) => item.replace(/^(- [^\n]*? · (?:Urgent|High|우선순위 [^ ·]+) · )([^\n]*?)( · 대표 손이 필요한 날 \d{4}-\d{2}-\d{2})?(\n https:\/\/[^\n]+)$/, (_match, prefix: string, title: string, action: string | undefined, link: string) =>
375
+ `${prefix}${title.length > 90 ? `${title.slice(0, 89)}…` : title}${action ?? ''}${link}`);
376
+ const selected = groups.map(group => ({ heading: group.heading, items: group.items.length ? [compact(group.items[0]!)] : [] }));
377
+ const warning = text.startsWith('조회 상한 250건 ·') ? `${text.split('\n', 1)[0]}\n` : '';
378
+ const render = () => warning + selected.map(group => `${group.heading}\n${group.items.join('\n') || '없음'}`).join('\n');
379
+ const priorityOrder = [...groups.keys()].sort((a, b) =>
380
+ Number(!groups[a]!.heading.startsWith('14일 안 기한 ')) - Number(!groups[b]!.heading.startsWith('14일 안 기한 ')) || a - b);
381
+ for (const i of priorityOrder) {
382
+ const source = groups[i]!;
383
+ for (const item of source.items.slice(selected[i]!.items.length)) {
384
+ const next = compact(item);
385
+ if (render().length + next.length + 1 + '\n… 전체 목록은 리뷰 파일 참조'.length > 1_800) break;
386
+ selected[i]!.items.push(next);
387
+ }
388
+ }
389
+ const omitted = groups.some((group, i) => group.items.length > selected[i]!.items.length);
390
+ return `## ⑧ 행정\n${render()}${omitted ? '\n… 전체 목록은 리뷰 파일 참조' : ''}`;
391
+ }
392
+
351
393
  function newsMessage(markdown: string): string | null {
352
394
  const section = markdown.split('## ⑦ 외부 동향\n')[1]?.split('\n\n## ')[0];
353
395
  if (!section || section.startsWith('못 읽음 ·')) return null;
@@ -366,6 +408,7 @@ function sendNewsAfterReview(delivery: DeliveryResult, file: string, markdown: s
366
408
  export type DailyDeps = { now?: () => Date; root?: string; vaultRoot?: string | null; sendEnabled?: boolean; repoRoot?: string; repoName?: string;
367
409
  landings?: (now: Date) => Promise<Landing[]>; release?: () => Promise<Release>; loops?: () => Promise<Loop[]>;
368
410
  grid?: () => Promise<Seat[]>; decisions?: () => Promise<Pending[]>; news?: () => Promise<News[]>;
411
+ cooAdmin?: (now: Date) => Promise<string>;
369
412
  target?: { chatId: number; botToken: string };
370
413
  send?: (request: DailySendRequest) => DailySendConfirmation | null; receipt?: (key: string) => DeliveryReceipt;
371
414
  recordDelivery?: (text: string, kind: 'ops-report') => void;
@@ -426,7 +469,7 @@ export async function runDaily(options: { dryRun?: boolean; noNews?: boolean; st
426
469
  catch (error) { sendError = `발송 설정 못 읽음 · ${shortReason(reasonOf(error))}`; deliveryState = 'unknown'; }
427
470
  }
428
471
  if (options.stage === 'deliver' && !options.dryRun && enabled) {
429
- const text = `${header}\n\n## 위험 톱 5\n${riskBlock}${suggestionBlock ? `\n\n## PROACT1-LITE 제안\n${suggestionBlock}` : ''}\n\n${file}`;
472
+ const text = `${header}\n\n## 위험 톱 5\n${riskBlock}${suggestionBlock ? `\n\n## PROACT1-LITE 제안\n${suggestionBlock}` : ''}\n\n${adminMessage(markdown)}\n\n${file}`;
430
473
  chars = `${text}\n${receiptKey}`.length;
431
474
  let resolved: ReturnType<typeof recipient> = null;
432
475
  try { resolved = recipient(deps); }
@@ -468,6 +511,12 @@ export async function runDaily(options: { dryRun?: boolean; noNews?: boolean; st
468
511
  news: options.noNews ? unreadable('건너뜀 (--no-news)') : await safe(async () => cleanNews(await (deps.news ?? collectNews)())),
469
512
  };
470
513
  const review = composeDaily(parts, now);
514
+ const readAdmin = deps.cooAdmin ?? ((date: Date) => dispatchCooAdmin({}, { now: date, briefing: true }));
515
+ const admin = await safe(() => readAdmin(now));
516
+ const adminText = admin.status === 'unreadable' ? `측정 불가 · ${admin.reason}`
517
+ : admin.value.startsWith('Linear 키가 없습니다') || admin.value.startsWith('못 읽었습니다(')
518
+ ? `측정 불가 · ${shortReason(admin.value)}` : admin.value;
519
+ review.markdown += `\n## ⑧ 행정\n${adminText}\n`;
471
520
  const root = deps.root ?? effectiveInstanceRoot();
472
521
  const observed = await safe(async (): Promise<ProactSignals> => {
473
522
  if (deps.proactSignals) return deps.proactSignals();
@@ -553,7 +602,7 @@ export async function runDaily(options: { dryRun?: boolean; noNews?: boolean; st
553
602
  let chars = 0;
554
603
  let target = 'unknown';
555
604
  if (!options.dryRun && options.stage !== 'collect' && enabled) {
556
- const text = `${review.header}\n\n## 위험 톱 5\n${review.risks.map((r, i) => `${i + 1}. ${r.name} — ${r.score}점 · ${r.reason}`).join('\n') || '확인된 위험 없음'}${recorded ? `\n\n## PROACT1-LITE 제안\n${recorded}` : ''}${retroBlock}\n\n${file}`;
605
+ const text = `${review.header}\n\n## 위험 톱 5\n${review.risks.map((r, i) => `${i + 1}. ${r.name} — ${r.score}점 · ${r.reason}`).join('\n') || '확인된 위험 없음'}${recorded ? `\n\n## PROACT1-LITE 제안\n${recorded}` : ''}${retroBlock}\n\n${adminMessage(review.markdown)}\n\n${file}`;
557
606
  chars = `${text}\n${receiptKey}`.length;
558
607
  let resolved: ReturnType<typeof recipient> = null;
559
608
  try { resolved = recipient(deps); }
@@ -135,7 +135,8 @@ function compose(parts: WeeklyParts, key: string, now: Date, versions: Section<s
135
135
  `# 주간 미팅 — ${key} (KST)`, header,
136
136
  section('landings', parts.landings, list => {
137
137
  const seats = [...new Set(list.map(i => i.seat))].sort(sortNames).map(s => `${s} ${list.filter(i => i.seat === s).length}`).join(' · ');
138
- return `총 ${list.length}건 · 자리별 ${seats || '없음'}\n발행된 판: ${versions.status === 'ok' ? versions.value.join(', ') || '없음' : `못 읽음 · ${versions.reason}`}`;
138
+ const shown = list.slice(0, 10);
139
+ return `총 ${list.length}건 · 자리별 ${seats || '없음'}\n발행된 판: ${versions.status === 'ok' ? versions.value.join(', ') || '없음' : `못 읽음 · ${versions.reason}`}\n지난주 지표: 착지 ${list.length}건 · 발행 ${versions.status === 'ok' ? `${versions.value.length}판` : `못 읽음 · ${versions.reason}`}\n지난주 착지:\n${shown.map(i => `- ${i.title} (${i.seat} · ${i.mergedAt})`).join('\n') || '없음'}${list.length > shown.length ? `\n외 ${list.length - shown.length}건` : ''}`;
139
140
  }),
140
141
  section('release', parts.release, r => `${r.version}: green ${r.green}/${r.total} · 다음 판 ${r.nextVersion ?? '미정'} ${r.nextGreen ?? '못 읽음'}/${r.nextTotal ?? '못 읽음'} · 다음 컷 ${r.cutAt ?? '미정'}\nred 칸: ${r.red.map(i => i.name).join(', ') || '없음'}`),
141
142
  section('issues', parts.issues, list => list.map(i => `- ${i.id} ${i.title} · ${i.owner} · 기한 ${i.due}`).join('\n') || '열린 현안 없음'),
@@ -226,7 +227,7 @@ export async function runWeekly(options: { dryRun?: boolean; stage?: 'collect' |
226
227
  };
227
228
  const issues = await safe(async () => issueHistory(root));
228
229
  const parts: WeeklyParts = {
229
- landings: await safe(() => deps.landings ? deps.landings(now, { from, to }) : collectLandings(now, { from, to }, { repoRoot: deps.repoRoot, repoName: deps.repoName })),
230
+ landings: await safe(() => deps.landings ? deps.landings(now, { from, to }) : collectLandings(now, { from, to }, { repoRoot: deps.repoRoot, repoName: deps.repoName, stateRoot: root })),
230
231
  release: await safe(deps.release ?? (() => collectWeeklyRelease(now, root))),
231
232
  issues: issues.status === 'ok' ? { status: 'ok', value: [...latest(issues.value).values()].filter(i => i.status === 'open') } : issues,
232
233
  followThrough: issues.status === 'ok' ? { status: 'ok', value: [...new Set([
@@ -140,10 +140,15 @@ export function checkPublicSkills(root: string, boundary: SkillBoundaryReport =
140
140
  const errors = [...boundary.errors];
141
141
  const skills: PublicSkillRow[] = [];
142
142
  const skillsDir = join(root, 'skills');
143
- const addon = new Set(boundary.skills.filter((row) => row.verdict === 'addon').map((row) => row.skill));
143
+ // Scope discrepancy: the stated 15 public deployments have no named fifteenth
144
+ // skill in this tree's boundary inventory (14 core, 5 addons). No verified
145
+ // deployment-name list is available here to justify adding a row. Never use
146
+ // an addon to fill the gap; keep the existing report shape and exit semantics.
147
+ // Unclassified folders retain their check rows and boundary errors.
148
+ const verdicts = new Map(boundary.skills.map((row) => [row.skill, row.verdict]));
144
149
  const names = existsSync(skillsDir) ? readdirSync(skillsDir).filter((name) => {
145
150
  const dir = join(skillsDir, name);
146
- return lstatSync(dir).isDirectory() && !addon.has(name);
151
+ return lstatSync(dir).isDirectory() && verdicts.get(name) !== 'addon';
147
152
  }).sort() : [];
148
153
  if (!existsSync(skillsDir)) errors.push('skills/ 디렉터리가 없다');
149
154
  for (const row of boundary.skills) {
@@ -8,7 +8,6 @@ import {
8
8
  defaultGitMergeSeam, defaultLlmResolve, mergeMainWithLlmResolve,
9
9
  type MergeGitSeam,
10
10
  } from '../../src/autopilot/build/llm-conflict-merge.js';
11
- import { NEXT_MD_PATH } from '../../src/release-loop/next-md-merge.js';
12
11
 
13
12
  type Command = (cwd: string, program: 'git' | 'gh', args: readonly string[]) => { status: number; stdout: string; stderr: string };
14
13
  export type ShadowOutcome = 'clean' | 'resolved-deterministic' | 'resolved-llm' | 'unresolved' | 'unmeasured';
@@ -108,9 +107,12 @@ export async function runResyncShadow(options: ShadowOptions): Promise<ShadowRow
108
107
  const result = await mergeMainWithLlmResolve(temp, 'origin/main',
109
108
  options.resolve ?? ((file, conflicted) => defaultLlmResolve(file, conflicted, 'origin/main', { worktreePath: temp })), observedGit);
110
109
  if (result.status === 'merged' || result.status === 'up-to-date') outcome = 'clean';
111
- else if (result.status === 'llm-resolved') {
110
+ else if (result.status === 'deterministic-resolved') {
112
111
  files = result.resolvedFiles ?? files;
113
- outcome = files.length > 0 && files.every((file) => file === NEXT_MD_PATH) ? 'resolved-deterministic' : 'resolved-llm';
112
+ outcome = 'resolved-deterministic';
113
+ } else if (result.status === 'llm-resolved') {
114
+ files = result.resolvedFiles ?? files;
115
+ outcome = 'resolved-llm';
114
116
  } else if (result.status === 'conflict-unresolved') outcome = 'unresolved';
115
117
  // A git error is a measurement failure, not evidence of an unresolvable conflict.
116
118
  } catch {
@@ -1,8 +1,88 @@
1
1
  // TD2 — a daily look at the test suite, one cost-weighted slice at a time (shadow: it measures and drafts, it
2
2
  // never deletes or moves a test). Design: 내부 문서 `TD1-v2-gate-content-review-2026-10-01`.
3
- import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync } from 'node:fs';
4
4
  import { join } from 'node:path';
5
5
 
6
+ /** These were reported as preexisting in the recent gate/harvest; remeasurement, not this list, decides today's count. */
7
+ export const DEFAULT_MAIN_FAILURE_FILES = [
8
+ 'src/task-orchestrator/surfaces/pod-pool-cli.test.ts',
9
+ 'src/self-dev/dev-cli.test.ts',
10
+ 'src/self-dev/dev-pipeline.test.ts',
11
+ 'src/agent-mission/agent-backend-flag-smoke.test.ts',
12
+ 'scripts/release-story/draft.test.ts',
13
+ 'scripts/release-loop/freeze-off-parity.test.ts',
14
+ ] as const;
15
+
16
+ export type MainFailureClass = '시험이 낡음' | '코드 결함' | '환경·부하 의존' | '외부 의존';
17
+ export interface MainFailureResult { file: string; rc: number | null; stdout: string; stderr: string; timedOut?: boolean }
18
+ export interface MainFailureRow { file: string; failures: number; firstError: string; classification: MainFailureClass; draft: '고침' | '격리' }
19
+ export interface MainFailureDay { date: string; at: string; owner: 'TC'; mode: 'shadow'; commit: string; selected: string[]; rows: MainFailureRow[]; unmeasured: { file: string; reason: string }[]; failingFiles: number; previousFailingFiles: number | null; delta: number | null }
20
+
21
+ export function mainFailureLedgerPath(root: string, date: string): string { return join(root, 'test-diet', 'main-failures', `${date}.json`); }
22
+ export function kstDay(at: Date): string { return new Date(at.getTime() + 9 * 3600_000).toISOString().slice(0, 10); }
23
+
24
+ export function mainFailureFiles(value: unknown): string[] {
25
+ const files = value === undefined ? [...DEFAULT_MAIN_FAILURE_FILES] : value;
26
+ if (!Array.isArray(files) || files.length === 0 || !files.every((file) => typeof file === 'string' && /^(?:src|scripts|test)\/[A-Za-z0-9_./-]+\.test\.tsx?$/.test(file) && !file.split('/').includes('..'))) {
27
+ throw new Error('main failure files must be nonempty repository-relative test paths');
28
+ }
29
+ return [...new Set(files as string[])];
30
+ }
31
+
32
+ /** A heuristic draft, never a finding about the root cause or permission to skip a test. */
33
+ export function mainFailureRow(result: MainFailureResult): MainFailureRow | null {
34
+ const text = `${result.stdout}\n${result.stderr}`.replace(/\x1b\[[0-9;]*m/g, '');
35
+ const count = [...text.matchAll(/^\s*(\d+) fail\b/gm)].at(-1);
36
+ const failures = count ? Number(count[1]) : 0;
37
+ const ran = /Ran [1-9]\d* tests? across [1-9]\d* files?/m.test(text);
38
+ if (result.timedOut || !ran || !Number.isSafeInteger(failures) || (result.rc !== 0 && failures === 0)
39
+ || (result.rc === 0 && failures > 0) || /^(?:\s*[1-9]\d* errors?\b|# Unhandled error between tests)/m.test(text)) {
40
+ throw new Error(`test not measured: ${result.file}: ${text.split('\n').map((line) => line.trim()).find((line) => /error:|Error:|timed out|timeout|Cannot find|not found|errors?\b/i.test(line)) ?? 'no completed test result'}`);
41
+ }
42
+ if (failures === 0 && result.rc === 0) return null;
43
+ const firstError = text.split('\n').map((line) => line.trim()).find((line) => /^(?:\(fail\)|error:|\w*Error:|Expected:|Received:|Cannot find|Unable to)/i.test(line))
44
+ ?? `test exited ${result.rc} without a diagnostic`;
45
+ const classification: MainFailureClass = /timed out|timeout|load average|resource temporarily unavailable/i.test(firstError) ? '환경·부하 의존'
46
+ : /codex|--yolo|network|ECONN|API key|Unable to|Cannot find module|ENOENT/i.test(firstError) ? '외부 의존'
47
+ : /snapshot|next\.md|expected|Received|toEqual|toContain/i.test(firstError) ? '시험이 낡음' : '코드 결함';
48
+ return { file: result.file, failures, firstError: firstError.slice(0, 240), classification,
49
+ draft: classification === '환경·부하 의존' || classification === '외부 의존' ? '격리' : '고침' };
50
+ }
51
+
52
+ /** One KST-day snapshot, replaced on remeasurement. Incomplete runs cannot masquerade as zero failures. */
53
+ export function writeMainFailureDay(root: string, selected: string[], results: MainFailureResult[], commit: string, at = new Date()): MainFailureDay {
54
+ if (results.length !== selected.length || results.some((r, i) => r.file !== selected[i])) throw new Error('incomplete main failure measurement');
55
+ const date = kstDay(at);
56
+ const dir = join(root, 'test-diet', 'main-failures');
57
+ mkdirSync(dir, { recursive: true });
58
+ const dates = earlierMainFailureDays(dir, date);
59
+ const previous = dates.at(-1);
60
+ const previousDay = previous ? JSON.parse(readFileSync(join(dir, previous), 'utf8')) as MainFailureDay : null;
61
+ const rows: MainFailureRow[] = [];
62
+ const unmeasured: MainFailureDay['unmeasured'] = [];
63
+ for (const result of results) {
64
+ try {
65
+ const row = mainFailureRow(result);
66
+ if (row) rows.push(row);
67
+ } catch (error) {
68
+ // 못 잰 파일은 «실패»가 아니다 — 행으로 접으면 측정 실패가 main 결함 1건으로 둔갑한다.
69
+ unmeasured.push({ file: result.file, reason: (error instanceof Error ? error.message : String(error)).slice(0, 240) });
70
+ }
71
+ }
72
+ const previousFailingFiles = unmeasured.length === 0 && previousDay?.unmeasured?.length === 0
73
+ && previousDay.selected.join('\0') === selected.join('\0') ? previousDay.failingFiles : null;
74
+ const line: MainFailureDay = { date, at: at.toISOString(), owner: 'TC', mode: 'shadow', commit, selected, rows, unmeasured, failingFiles: rows.length,
75
+ previousFailingFiles, delta: previousFailingFiles === null ? null : rows.length - previousFailingFiles };
76
+ const path = mainFailureLedgerPath(root, date);
77
+ writeFileSync(`${path}.${process.pid}.tmp`, JSON.stringify(line, null, 2) + '\n');
78
+ renameSync(`${path}.${process.pid}.tmp`, path);
79
+ return line;
80
+ }
81
+
82
+ function earlierMainFailureDays(dir: string, date: string): string[] {
83
+ return readdirSync(dir).filter((name) => /^\d{4}-\d{2}-\d{2}\.json$/.test(name) && name < `${date}.json`).sort();
84
+ }
85
+
6
86
  export const DEFAULT_COST_SECS = 10;
7
87
  export const SLOW_SECS = 60;
8
88
  export const HEAVY_MB = 2048;
@@ -3,13 +3,15 @@
3
3
  // bun scripts/test-diet/node.ts pick|measure|audit|record (test-diet or nightly-audit graph)
4
4
  import { spawnSync } from 'node:child_process';
5
5
  import { createHash } from 'node:crypto';
6
- import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
6
+ import { appendFileSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
7
+ import { tmpdir } from 'node:os';
7
8
  import { join } from 'node:path';
8
9
  import { debug } from '../../src/debug/log.js';
9
10
  import { effectiveInstanceRoot } from '../../src/instance/resolve.js';
10
11
  import { CardStore } from '../../src/task-cards/card-store.js';
11
12
  import { GATE_NIGHTLY_AUDITS } from '../release-loop/gate-node.js';
12
- import { appendLedger, costTable, judge, lastLedgerLine, ledgerPath, nightlyAuditLedgerPath, pickRange, propose, td1Dispositions, writeCardDraft, type LedgerLine, type Measurement, type Td1Disposition } from './lib.js';
13
+ import { isCredentialKey } from '../lib/deterministic-env.js';
14
+ import { appendLedger, costTable, judge, lastLedgerLine, ledgerPath, mainFailureFiles, nightlyAuditLedgerPath, pickRange, propose, td1Dispositions, writeCardDraft, writeMainFailureDay, type LedgerLine, type MainFailureResult, type Measurement, type Td1Disposition } from './lib.js';
13
15
  import { fixedCountAssertions, flakeVerdict, sweepSlice, unreachableImports, type Mutation, type TestRun } from './effectiveness.js';
14
16
 
15
17
  type Context = { graphId?: string; input: Record<string, unknown>; outputs: Record<string, Record<string, unknown> | null> };
@@ -235,6 +237,49 @@ export function record(ctx: Context, deps: { createStore?: (root: string) => Pic
235
237
  return emit({ outcome: 'ok', summary: `test-diet ${line.range} · keep ${counts.keep} · review ${counts.review} · failing ${counts.failing}${card ? ' · card draft' : ''}`, range: line.range, ...counts, ...(card ? { card } : {}) });
236
238
  }
237
239
 
240
+ export function mainFailures(ctx: Context, deps: { root?: string; checkout?: string; runFile?: (file: string, cwd: string) => MainFailureResult; now?: Date } = {}): number {
241
+ const selected = mainFailureFiles(ctx.input.files);
242
+ const root = deps.root ?? effectiveInstanceRoot();
243
+ const guarded = process.env.NODE_ENV === 'test' || !!process.env.ELANOUS_TEST_HOME;
244
+ const directory = deps.checkout || guarded ? undefined : mkdtempSync(join(tmpdir(), 'test-diet-main-'));
245
+ try {
246
+ let checkout = deps.checkout ?? directory ?? '';
247
+ let commit: string;
248
+ if (guarded) {
249
+ // No clone, install, test subprocess or harness dispatch in the test universe.
250
+ const at = deps.now ?? new Date();
251
+ const ledger = join(root, 'test-diet', 'main-failures', `${at.toISOString().slice(0, 10)}-guard.json`);
252
+ mkdirSync(join(root, 'test-diet', 'main-failures'), { recursive: true });
253
+ writeFileSync(ledger, JSON.stringify({ at: at.toISOString(), selected, measured: false, reason: 'test environment', owner: 'TC', mode: 'shadow' }) + '\n');
254
+ return emit({ outcome: 'ok', summary: 'main failures record only: test environment (not measured)', ledger, selected, measured: false });
255
+ } else if (deps.checkout) {
256
+ const head = spawnSync('git', ['rev-parse', 'HEAD'], { cwd: checkout, encoding: 'utf8' });
257
+ if (head.status !== 0) throw new Error(`main checkout unreadable: ${checkout}`);
258
+ commit = head.stdout.trim();
259
+ } else {
260
+ const source = process.cwd();
261
+ const clone = spawnSync('git', ['clone', '--quiet', '--shared', '--single-branch', '--branch', 'main', source, checkout], { encoding: 'utf8', timeout: 120_000 });
262
+ if (clone.status !== 0) return emit({ outcome: 'error', summary: `main checkout failed: ${clone.stderr || clone.error}` });
263
+ commit = spawnSync('git', ['rev-parse', 'HEAD'], { cwd: checkout, encoding: 'utf8' }).stdout.trim();
264
+ const install = spawnSync('bun', ['install', '--frozen-lockfile'], { cwd: checkout, encoding: 'utf8', timeout: 300_000, maxBuffer: 1024 * 1024 });
265
+ if (install.status !== 0) return emit({ outcome: 'error', summary: `main install failed: ${install.stderr || install.error}` });
266
+ }
267
+ const runFile = deps.runFile ?? ((file: string, cwd: string): MainFailureResult => {
268
+ if (!existsSync(join(cwd, file))) return { file, rc: null, stdout: '', stderr: 'test file not present on main' };
269
+ const env = Object.fromEntries(Object.entries(process.env).filter(([key]) => !isCredentialKey(key)));
270
+ const child = spawnSync('bun', ['run', 'test:deterministic', file], {
271
+ cwd, encoding: 'utf8', timeout: 300_000, maxBuffer: 4 * 1024 * 1024,
272
+ env: { ...env, NODE_ENV: 'test', ELANOUS_STATE_DIR: join(root, 'test-diet', 'isolated-test-state') },
273
+ });
274
+ return { file, rc: child.status, stdout: child.stdout ?? '', stderr: child.stderr ?? String(child.error ?? ''), timedOut: (child.error as NodeJS.ErrnoException | undefined)?.code === 'ETIMEDOUT' };
275
+ });
276
+ const results = selected.map((file) => runFile(file, checkout));
277
+ const day = writeMainFailureDay(root, selected, results, commit, deps.now);
278
+ debug.log('test-diet.main-failures', 'recorded', { selected: selected.length, failingFiles: day.failingFiles, delta: day.delta, guarded });
279
+ return emit({ outcome: 'ok', summary: `main failures ${day.failingFiles}/${selected.length} · delta ${day.delta ?? 'n/a'} · shadow TC`, ledger: join(root, 'test-diet', 'main-failures', `${day.date}.json`), ...day });
280
+ } finally { if (directory) rmSync(directory, { recursive: true, force: true }); }
281
+ }
282
+
238
283
  function status(root: string, options: { json?: boolean; days?: number } = {}): number {
239
284
  const path = ledgerPath(root);
240
285
  const ledger = existsSync(path) ? readFileSync(path, 'utf8') : '';
@@ -286,6 +331,7 @@ if (import.meta.main) {
286
331
  const ctx = context();
287
332
  const flags = process.argv.slice(3);
288
333
  process.exitCode = step === 'pick' ? pick(ctx, flags.includes('--sweep')) : step === 'measure' ? measure(ctx, false, flags.includes('--effectiveness')) : step === 'audit' ? measure(ctx, true)
334
+ : step === 'main-failures' ? mainFailures(ctx)
289
335
  : step === 'record' ? (ctx.graphId === 'nightly-audit' || Object.hasOwn(ctx.outputs, 'audit') ? recordNightlyAudit(ctx) : record(ctx)) : emit({ outcome: 'error', summary: `unknown step: ${step}` });
290
336
  }
291
337
  } catch (error) {