elanous 0.2.22 → 0.2.24

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 (803) 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/{aBi6EyMtLsrl7J8eH4kF7 → Q-7iofoxOEv1WX18S35of}/_buildManifest.js +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{119fc678.6f591cdb84ca5791.js → 0673cc54.8e2ef1c23e49e190.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/{a9f2b54d-40c16bd0efdb04b8.js → 0a09e062-34f747a17d8d8c2e.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/{f8626309.a4e5d362b1d55e59.js → 0e3acd34.d42b2ef87fdf4234.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +77 -0
  10. package/apps/pwa/out/_next/static/chunks/{7175-350f4ce2873bc038.js → 1325-dc3f3c21eb181cb4.js} +1 -1
  11. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +34 -0
  12. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +24 -0
  13. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{6767.8e6c5f6e744fcd9f.js → 1505.5826671109111e75.js} +2 -2
  15. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 1669-da843ed73aa301f5.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +36 -0
  24. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +122 -0
  25. package/apps/pwa/out/_next/static/chunks/2528.0af5c0e1fad88df6.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +62 -0
  28. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/272-0eed0fb0aab716b6.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{7899.597af4a9996c907f.js → 2721.bc9a8f36bd85c07a.js} +1 -1
  31. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +149 -0
  36. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3961-aaae04ed1d32622f.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +309 -0
  40. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{d70879db.c66c56a95a91efc6.js → 4c5e95ce.83e9b16add6fcd8c.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/{6158.566c890adc06a459.js → 5313.1697309c532b9856.js} +2 -2
  53. package/apps/pwa/out/_next/static/chunks/{79b78388.663188133449d707.js → 53746282.1be36038d1abd949.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5578.ac963634373b28c6.js +286 -0
  57. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5967-c0a80f8ffe5d4050.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 5974.360f8441eb0ac1ec.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +74 -0
  65. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6571-926ddf024a6ad5df.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +64 -0
  70. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/{9832.2ab2e818013574c7.js → 6702.ebbd165d5e4a4a14.js} +1 -1
  72. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +32 -0
  74. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +24 -0
  75. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +93 -0
  79. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 740.90b31555290236a9.js} +2 -2
  84. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +148 -0
  85. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +226 -0
  86. package/apps/pwa/out/_next/static/chunks/{9070.067c106528ec1ae6.js → 7518.49161e8f5814abdb.js} +1 -1
  87. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +27 -0
  88. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +115 -0
  91. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7905.b230b9d06cb4ad5d.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/{8194.484f51e273d9abd2.js → 8264.00e434fbd02e9311.js} +16 -16
  98. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +8 -0
  100. package/apps/pwa/out/_next/static/chunks/{088d8e8a.8069543d082bec12.js → 83cfc5c8.349535543c1548b6.js} +1 -1
  101. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +23 -0
  102. package/apps/pwa/out/_next/static/chunks/{1948.5f35b39eef222a94.js → 8438.ee7f0df3b3f6fcb4.js} +1 -1
  103. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{4588.ad3364cb7fb97ada.js → 8532.a86e99acf9b761cb.js} +2 -2
  106. package/apps/pwa/out/_next/static/chunks/8569.b853a8daa8f31d12.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/8925-2abfb48af477fb7f.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{88729267.9c6c000157c83f2f.js → 89849432.9eaa2f4c9c010965.js} +3 -3
  111. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +90 -0
  112. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +94 -0
  113. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +41 -0
  115. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +287 -0
  117. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +79 -0
  118. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/{3522-1de1319d028ac89c.js → 9502-32c5dc22e8f120f5.js} +3 -3
  121. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +104 -0
  124. package/apps/pwa/out/_next/static/chunks/{7630.2b9a68659053ff4e.js → 9976.8f28864317639fe6.js} +16 -16
  125. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/approvals/page-3b9fc39362473ae7.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f2b62c19ca68fef8.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/board/page-d7602d489edf5f37.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/botlab/page-24282bf9f90031a5.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/bots/page-8b7c5ab6b5bc8d64.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/ceo/page-4eb84d454f8c3415.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/chat/page-b2e494bdad57fcb5.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/consult/{page-80ed511e02c81412.js → page-c0ab229673a8b0eb.js} +1 -1
  134. package/apps/pwa/out/_next/static/chunks/app/control/page-3e2b45f3c36dbac4.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c22aa511b28743ad.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/design-check/page-26345242e4049f55.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/editor/page-bf88c0f558d8ef54.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/exec/page-52fec523e5b5d3ad.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/field/page-67723dfdcde92b31.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/inside/page-22725e2570f1126b.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/intake/page-1891335950d68b70.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/layout-3267af1ebdc73cf5.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live/page-c314b75c11234998.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/live-run/page-9f9c85415f61782b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/loops/page-c1d4276059085587.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/market/page-833aab587f26ad4c.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8526c17ae38e6a50.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/morning/page-f998637a8402115c.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/not-found-b7bb53828b17b335.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/observatory/page-1b1850de0257e46d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6f23159fedb41f67.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1d809a87139dd024.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-da9e570234d481fd.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b92caddb5c715f30.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/page-8ce3a38e210b810a.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/reflection/page-57ffeeb6019440fd.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-abbb417bf514630b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2c2b3f29cec1efa4.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-9369279f72fc7b51.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/settings/page-64861f14039499c3.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ddc4c93efd8ab94b.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/page-901a1391b81053bc.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/share/page-68d9bbaac9841a58.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/showroom/page-b5c0c996f329371e.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/tasks/page-89881ccbcf728978.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/term/page-0e87a803b3d7165e.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/today/page-58d4e5cb30ef4871.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/trace/page-02ce4c3b5f39e4d2.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/vault/page-e620d1bb8eadcec2.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-acf868c64d77f950.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workflows/page-54fa605fa6dba457.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workspace/page-bc79f0833533fa84.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d5c4398eea03d8f3.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/b4e12462-5fab4a813a63dadd.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → ce383d63.d2ede338788ed18e.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/{framework-5c169757551134ed.js → framework-b2763b10dc6b3836.js} +1 -1
  180. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +1 -0
  185. package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +1 -0
  186. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +1 -0
  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/catalog/models/openrouter/deepseek-v4-pro-0813.yaml +39 -0
  288. package/catalog/models/openrouter/deepseek-v4.1-flash.yaml +38 -0
  289. package/catalog/models/openrouter/glm-5.3-flash.yaml +35 -0
  290. package/catalog/providers/openrouter.yaml +2 -0
  291. package/graphs/implement-loop.yaml +31 -0
  292. package/graphs/log-horizon/log-horizon-watch.yaml +25 -0
  293. package/graphs/log-horizon/recipes.yaml +3 -0
  294. package/graphs/ops/harness-gc.yaml +17 -0
  295. package/graphs/ops/recipes.yaml +3 -0
  296. package/graphs/overlays/README.md +1 -1
  297. package/graphs/overlays/stop-heal-ladder.yaml +105 -0
  298. package/graphs/release/recipes.yaml +1 -1
  299. package/graphs/release/release-loop.yaml +6 -2
  300. package/graphs/release-rehearsal/recipes.yaml +12 -0
  301. package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
  302. package/package.json +4 -1
  303. package/scripts/add-api-key.sh +1 -1
  304. package/scripts/bench-report.ts +82 -3
  305. package/scripts/ci-typecheck-changed.ts +80 -14
  306. package/scripts/fleet/bedrock-pod-secret.ts +122 -0
  307. package/scripts/fleet/node-setup-linux.sh +97 -0
  308. package/scripts/fleet/node-setup.sh +11 -0
  309. package/scripts/fleet/zai-pod-secret.ts +86 -0
  310. package/scripts/hq/hq-fence-wrapper.sh +148 -0
  311. package/scripts/land-global-checks.ts +3 -0
  312. package/scripts/lib/typecheck-ratchet.ts +51 -0
  313. package/scripts/measure-log-diet-2.ts +213 -0
  314. package/scripts/measure-tsc-affected-roots.ts +289 -0
  315. package/scripts/openai-relay-server.ts +5 -1
  316. package/scripts/release-loop/docs-node.ts +258 -43
  317. package/scripts/release-loop/gate-executor.ts +28 -0
  318. package/scripts/release-loop/gate-method.ts +59 -0
  319. package/scripts/release-loop/gate-node.ts +335 -33
  320. package/scripts/release-loop/gate-wall.ts +208 -0
  321. package/scripts/release-loop/known-issues-node.ts +53 -8
  322. package/scripts/release-loop/publish-at.ts +14 -0
  323. package/scripts/release-loop/publish-node.ts +17 -2
  324. package/scripts/release-loop/resume-release.ts +40 -4
  325. package/scripts/release-loop/resume.ts +94 -0
  326. package/scripts/release-loop/shard-plan.ts +3 -11
  327. package/scripts/release-loop/tui-node-checks.ts +22 -0
  328. package/scripts/release-loop/unattended-release.ts +29 -7
  329. package/scripts/rhythm/daily.ts +51 -2
  330. package/scripts/rhythm/weekly.ts +3 -2
  331. package/scripts/tsc-baseline-cache.ts +147 -0
  332. package/scripts/tsc-main-safety-net.ts +189 -0
  333. package/scripts/usage-rollup.ts +64 -8
  334. package/src/acp/codex-plugins.ts +48 -6
  335. package/src/agent/monad-agent-turn.ts +67 -5
  336. package/src/agent/run-context.ts +20 -0
  337. package/src/agent/tool-profile.ts +28 -2
  338. package/src/agent-mission/acp-judge.ts +8 -2
  339. package/src/agent-mission/capabilities-cli.ts +16 -1
  340. package/src/agent-mission/driver.ts +19 -4
  341. package/src/agent-mission/pr-review-watch.ts +6 -2
  342. package/src/agent-mission/resource-ladder.ts +8 -3
  343. package/src/agent-mission/review-loop.ts +41 -7
  344. package/src/agent-substrate/acp-implementer.ts +139 -0
  345. package/src/agent-substrate/acp-reviewer.ts +17 -8
  346. package/src/agent-substrate/pr-reviewer.ts +191 -28
  347. package/src/agent-substrate/review-intent.ts +6 -4
  348. package/src/agent-substrate/self-review-cli.ts +155 -21
  349. package/src/agent-substrate/shard-boundary-intent.ts +92 -26
  350. package/src/ask-user-question/pending-questions.ts +8 -2
  351. package/src/autopilot/build/llm-conflict-merge.ts +216 -12
  352. package/src/autopilot/codebase-grounding.ts +44 -0
  353. package/src/autopilot/llm-control-brain.ts +13 -1
  354. package/src/autopilot/mission-codebase-gate.ts +8 -77
  355. package/src/autopilot/mission-critique.ts +18 -5
  356. package/src/autopilot/mission-feasibility-negotiate.ts +11 -10
  357. package/src/autopilot/mission-trace.ts +12 -1
  358. package/src/autopilot/pr-manager.ts +12 -3
  359. package/src/autopilot/system-lookback-run.ts +16 -10
  360. package/src/bench/bench.ts +183 -0
  361. package/src/boot/acp-server.ts +4 -7
  362. package/src/boot/acp-socket-path.ts +7 -0
  363. package/src/briefing/brief-items.ts +21 -13
  364. package/src/budget/fetchers/grok.ts +15 -5
  365. package/src/budget/llm-cost.ts +37 -5
  366. package/src/budget/types.ts +8 -2
  367. package/src/budget/unified-usage.ts +88 -6
  368. package/src/chat/index.ts +12 -3
  369. package/src/cli/agent-cli.ts +20 -0
  370. package/src/cli/bench-cli.ts +34 -0
  371. package/src/cli/brief-cli.ts +27 -21
  372. package/src/cli/cli-user-error.ts +9 -2
  373. package/src/cli/guardian-cli.ts +26 -1
  374. package/src/cli/image-cli.ts +101 -0
  375. package/src/cli/log-event-names.ts +7 -0
  376. package/src/cli/logs-cli.ts +1 -0
  377. package/src/cli/mcp-login.ts +111 -37
  378. package/src/cli/plugin-cli.ts +21 -1
  379. package/src/cli/pod-cli.ts +26 -0
  380. package/src/cli/pr-cli.ts +90 -5
  381. package/src/cli/pr-land-overlap-evidence.ts +279 -0
  382. package/src/cli/release-cli.ts +63 -12
  383. package/src/cli/rfc-status.ts +52 -2
  384. package/src/cli/self-update.ts +277 -10
  385. package/src/cli/skills-cli.ts +12 -3
  386. package/src/cli/tasks-cli.ts +241 -30
  387. package/src/cli/usage-cli.ts +91 -8
  388. package/src/context-bus/context-first.ts +51 -2
  389. package/src/context-bus/context-now-surfaces.ts +13 -2
  390. package/src/context-bus/long-term-memory.ts +3 -1
  391. package/src/context-bus/nightly-condense.ts +3 -2
  392. package/src/core-turn/run-goal-loop.ts +87 -2
  393. package/src/dashboard/ad-run-setup-bindings.ts +279 -0
  394. package/src/dashboard/chat-fold.ts +20 -0
  395. package/src/dashboard/first-screen-band.ts +151 -1
  396. package/src/dashboard/index.ts +45 -281
  397. package/src/dashboard/slash-runtime/dashboard-handlers.ts +5 -3
  398. package/src/dashboard/stale-install-check.ts +24 -2
  399. package/src/dashboard/turn-stream-formatter.ts +25 -0
  400. package/src/debug/log-diet.ts +190 -0
  401. package/src/debug/log.ts +70 -17
  402. package/src/display/coordinator.ts +25 -2
  403. package/src/domains/coo-admin-tool.ts +27 -0
  404. package/src/domains/cron-match.ts +1 -0
  405. package/src/domains/outbound-alert.ts +17 -6
  406. package/src/domains/release-tool.ts +158 -10
  407. package/src/domains/schedule-registry.ts +10 -7
  408. package/src/domains/schedule-runner.ts +1 -0
  409. package/src/elanous-config-dir.ts +2 -2
  410. package/src/elanous-daemon.ts +3 -3
  411. package/src/error-report/report.ts +21 -4
  412. package/src/execution-loop/launch-gate.ts +1 -1
  413. package/src/expression/i18n/messages.en.ts +5 -0
  414. package/src/expression/i18n/messages.ja.ts +5 -0
  415. package/src/expression/i18n/messages.ko.ts +5 -0
  416. package/src/expression/i18n/messages.zh.ts +5 -0
  417. package/src/expression/i18n/types.ts +8 -0
  418. package/src/github/pr-labels.ts +2 -0
  419. package/src/graph-runner/graph-cli.ts +42 -1
  420. package/src/graph-runner/runner.ts +218 -8
  421. package/src/grok/usage.ts +23 -2
  422. package/src/grounding/ref-index.ts +253 -0
  423. package/src/harness/dispatch-backpressure.ts +267 -0
  424. package/src/harness/harness-clean.ts +199 -78
  425. package/src/harness/harness-cli-command.ts +229 -35
  426. package/src/harness/harness-gc.ts +331 -0
  427. package/src/harness/harness-seams.ts +2 -20
  428. package/src/harness/harness-stop.ts +4 -2
  429. package/src/harness/harness-substrate-default.ts +214 -8
  430. package/src/harness/launch-registry.ts +6 -0
  431. package/src/harness/nested-elanous-policy.ts +4 -2
  432. package/src/harness/worktree-branch-prefix.ts +9 -0
  433. package/src/hq/fence-wrapper.ts +7 -0
  434. package/src/hq/fence.ts +187 -0
  435. package/src/hq/hq.ts +33 -2
  436. package/src/hq/lease.ts +13 -0
  437. package/src/hq/seats.ts +133 -21
  438. package/src/images/image-ledger.ts +179 -0
  439. package/src/index.ts +250 -69
  440. package/src/instance/child-scope.ts +32 -1
  441. package/src/instance/dev-project.ts +133 -0
  442. package/src/instance/resolve.ts +24 -0
  443. package/src/instance/spawn-elanous.ts +45 -0
  444. package/src/intake-plane/collect-github.ts +19 -1
  445. package/src/intake-plane/digest.ts +45 -20
  446. package/src/intake-plane/lens.ts +36 -8
  447. package/src/intake-plane/ref-prefetch.ts +110 -0
  448. package/src/intelligence-map/model-alias.ts +6 -0
  449. package/src/intelligence-map/model-catalog.ts +113 -0
  450. package/src/knowledge/kgs/pack.ts +5 -2
  451. package/src/knowledge/kgs/sqlite-store.ts +15 -0
  452. package/src/knowledge/tools/knowledge-query.ts +20 -2
  453. package/src/knowledge/write.ts +234 -2
  454. package/src/llm/bedrock-eventstream.ts +215 -0
  455. package/src/llm/bedrock-provider.ts +248 -0
  456. package/src/llm/bedrock.ts +491 -0
  457. package/src/llm/openrouter-byok-cost.ts +96 -0
  458. package/src/llm/openrouter-deepseek.ts +151 -0
  459. package/src/llm/openrouter-upstream-pins.config.ts +25 -0
  460. package/src/llm/provider-credentials.ts +3 -1
  461. package/src/llm/zai-coding-plan.ts +700 -0
  462. package/src/llm.ts +383 -41
  463. package/src/loops/budget.ts +150 -0
  464. package/src/loops/checker.ts +148 -9
  465. package/src/loops/orchestrator/resync-shadow.ts +34 -7
  466. package/src/loops/orchestrator/seat-share.ts +6 -49
  467. package/src/loops/orchestrator/traffic.ts +5 -81
  468. package/src/market/signed-index.ts +42 -0
  469. package/src/maturity/feature-maturity.ts +2 -2
  470. package/src/mcp/mcp-oauth.ts +136 -17
  471. package/src/model-tier/llm-tier-map.ts +52 -4
  472. package/src/models/prompts.ts +23 -1
  473. package/src/mss/logging/horizon-watch.ts +168 -0
  474. package/src/mss/logging/log-store.ts +262 -26
  475. package/src/native-tool-catalog.ts +1 -1
  476. package/src/nexus/api/consult-requests.ts +7 -10
  477. package/src/nexus/api/discord-trigger-bot.ts +6 -3
  478. package/src/nexus/api/error-reports.ts +30 -8
  479. package/src/nexus/api/http-server.ts +8 -0
  480. package/src/nexus/api/loop-resources.ts +42 -0
  481. package/src/nexus/api/missions.ts +73 -2
  482. package/src/nexus/api/ops-api.ts +18 -0
  483. package/src/nexus/api/outbound-report.ts +8 -3
  484. package/src/nexus/api/telegram-trigger-bot.ts +6 -3
  485. package/src/nexus/index.ts +17 -75
  486. package/src/nexus/outbound/format.ts +2 -0
  487. package/src/nexus/outbound/router.ts +198 -13
  488. package/src/nexus/tools-kind.ts +78 -0
  489. package/src/oauth/codex-account-rotation.ts +55 -20
  490. package/src/oauth/codex-account-store.ts +451 -23
  491. package/src/oauth/fallback-chain.ts +75 -15
  492. package/src/onboarding/first-run.ts +37 -18
  493. package/src/onboarding/web-first.ts +20 -2
  494. package/src/onboarding.ts +2 -1
  495. package/src/ops/machine-heartbeat.ts +185 -0
  496. package/src/ops/overview-cache.ts +175 -0
  497. package/src/ops/overview.ts +8 -0
  498. package/src/plugins/adapters/claude-package.ts +4 -12
  499. package/src/plugins/core/capability-policy.ts +141 -0
  500. package/src/plugins/core/host.ts +21 -8
  501. package/src/plugins/core/manifest.ts +19 -2
  502. package/src/plugins/core/trust-store.ts +15 -0
  503. package/src/plugins/core/types.ts +12 -0
  504. package/src/plugins/install/market-fetch.ts +68 -16
  505. package/src/plugins/install/plugin-install.ts +187 -16
  506. package/src/plugins/maker/plugin-maker.ts +25 -20
  507. package/src/plugins/maker/wizard-generate.ts +16 -2
  508. package/src/policy/llm-policy.ts +14 -1
  509. package/src/process/pid-liveness.ts +1 -1
  510. package/src/prompt-cache/openai.ts +13 -6
  511. package/src/prompt-cache/openrouter.ts +94 -0
  512. package/src/prompt-cache/types.ts +5 -0
  513. package/src/prompt-enhance/enhance.ts +69 -5
  514. package/src/prompt-library/family-prompt-coverage.ts +1 -0
  515. package/src/prompt-library/universal-preamble.ts +2 -2
  516. package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
  517. package/src/registry/loader.ts +6 -1
  518. package/src/release-loop/checklist.ts +24 -9
  519. package/src/release-loop/feature-store.ts +3 -0
  520. package/src/release-loop/gate-shards.ts +48 -4
  521. package/src/release-loop/landed-to-green.ts +81 -0
  522. package/src/release-loop/light-rc.ts +11 -1
  523. package/src/release-loop/merged-pr-checklist.ts +10 -0
  524. package/src/release-loop/placement.ts +107 -23
  525. package/src/release-loop/rehearsal.ts +317 -0
  526. package/src/release-loop/release-schedule.ts +13 -1
  527. package/src/release-loop/rubric-types.ts +1 -0
  528. package/src/release-loop/rubric.ts +2 -2
  529. package/src/requirements/requirement-ledger.ts +536 -0
  530. package/src/retro/daily.ts +26 -12
  531. package/src/seat-loop/seat-loop.ts +66 -11
  532. package/src/seat-loop/traffic-signal.ts +44 -0
  533. package/src/self-dev/ask-launch-flow.ts +2 -2
  534. package/src/self-dev/dev-cli.ts +109 -11
  535. package/src/self-dev/dev-pipeline.ts +11 -8
  536. package/src/self-dev/draft-residue.ts +475 -0
  537. package/src/self-dev/draft-sweep.ts +254 -10
  538. package/src/self-dev/draft-triage-rules.ts +27 -1
  539. package/src/self-dev/graph-journey-route.ts +6 -0
  540. package/src/self-dev/launch-preflight-text.ts +549 -0
  541. package/src/self-dev/launch-preflight.ts +10 -545
  542. package/src/self-dev/orchestrate-cli.ts +82 -5
  543. package/src/self-dev/orchestrate-summary-line.ts +13 -0
  544. package/src/self-dev/orchestrate.ts +49 -141
  545. package/src/self-dev/review-provider-fallback.ts +115 -19
  546. package/src/self-dev/run-store.ts +1 -3
  547. package/src/self-dev/run-supervisor.ts +190 -36
  548. package/src/self-dev/run-types.ts +191 -0
  549. package/src/self-dev/shard-aggregate.ts +61 -13
  550. package/src/self-dev/shard-plan.ts +5 -1
  551. package/src/self-dev/shard-run.ts +23 -5
  552. package/src/self-dev/supervisor-verdict-edges.ts +3 -4
  553. package/src/self-implement/blocked-draft-policy.ts +3 -19
  554. package/src/self-implement/budget-gate.ts +53 -13
  555. package/src/self-implement/child-context-composition.ts +139 -0
  556. package/src/self-implement/child-llm-preference.ts +13 -5
  557. package/src/self-implement/claude-acp-implement.ts +67 -0
  558. package/src/self-implement/draft-on-stop-mode.ts +18 -0
  559. package/src/self-implement/flex-signals.ts +59 -0
  560. package/src/self-implement/follow-up-goals.ts +114 -38
  561. package/src/self-implement/frozen-merges.ts +8 -3
  562. package/src/self-implement/gate-baseline-reap.ts +157 -0
  563. package/src/self-implement/gate-baseline.ts +78 -16
  564. package/src/self-implement/gate-cli.ts +12 -2
  565. package/src/self-implement/gate-remote.ts +17 -6
  566. package/src/self-implement/goal-author-decompose.ts +10 -2
  567. package/src/self-implement/goal-author.ts +48 -13
  568. package/src/self-implement/goal-digest.ts +19 -0
  569. package/src/self-implement/graph-overlay-condition.ts +32 -0
  570. package/src/self-implement/graph-overlay-yaml.ts +41 -7
  571. package/src/self-implement/graph-templates.ts +33 -1
  572. package/src/self-implement/graph-yaml.ts +56 -0
  573. package/src/self-implement/headless-elanous-driver.ts +11 -9
  574. package/src/self-implement/heal-intake.ts +5 -1
  575. package/src/self-implement/host-regate.ts +120 -29
  576. package/src/self-implement/l8-merge-queue.ts +67 -5
  577. package/src/self-implement/merge-train.ts +131 -0
  578. package/src/self-implement/off-diff-evidence.ts +9 -0
  579. package/src/self-implement/orchestrator.ts +271 -25
  580. package/src/self-implement/review-finding-recurrence.ts +28 -0
  581. package/src/self-implement/rework-policy.ts +2 -1
  582. package/src/self-implement/round-summary-card.ts +63 -0
  583. package/src/self-implement/run-ledger.ts +4 -3
  584. package/src/self-implement/run-step-projection.ts +147 -0
  585. package/src/self-implement/run-stop.ts +1 -1
  586. package/src/self-implement/running-runs.ts +75 -5
  587. package/src/self-implement/seams.ts +83 -4
  588. package/src/self-implement/self-implement-cli.ts +12 -5
  589. package/src/self-implement/stop-autoheal.ts +69 -2
  590. package/src/self-implement/train-gate-remote.ts +158 -0
  591. package/src/session-runtime/index.ts +10 -1
  592. package/src/session-runtime/retry-api.ts +11 -1
  593. package/src/session-runtime/retry-policy.ts +2 -1
  594. package/src/skills/gift-install.ts +119 -0
  595. package/src/skills/runner.ts +59 -2
  596. package/src/skills/skill-feedback.ts +31 -1
  597. package/src/skills/skill-tier.ts +1 -0
  598. package/src/smart-wizard/capability-index.ts +231 -0
  599. package/src/smart-wizard/rung.ts +74 -0
  600. package/src/steward/launch.ts +22 -10
  601. package/src/steward/triage-budget.ts +62 -0
  602. package/src/steward/triage.ts +87 -24
  603. package/src/storage/file-lock.ts +8 -1
  604. package/src/task-agent/actions.ts +66 -5
  605. package/src/task-agent/card-evidence.ts +59 -13
  606. package/src/task-agent/completion-evidence.ts +5 -0
  607. package/src/task-agent/cover.ts +101 -3
  608. package/src/task-agent/judge.ts +20 -3
  609. package/src/task-agent/land-order-ledger.ts +95 -0
  610. package/src/task-agent/land-worktree.ts +201 -0
  611. package/src/task-agent/live-move-history.ts +219 -0
  612. package/src/task-agent/live-moves.ts +451 -34
  613. package/src/task-agent/parent-host.ts +117 -8
  614. package/src/task-agent/rejudge-on-head.ts +352 -0
  615. package/src/task-agent/review-prior-fix.ts +146 -0
  616. package/src/task-agent/review-result-capture.ts +218 -0
  617. package/src/task-agent/run-adopt.ts +136 -0
  618. package/src/task-agent/shadow.ts +154 -14
  619. package/src/task-agent/task-hand.ts +186 -14
  620. package/src/task-orchestrator/surfaces/pod-account-broker.ts +38 -5
  621. package/src/task-orchestrator/surfaces/pod-bedrock-child.ts +74 -0
  622. package/src/task-orchestrator/surfaces/pod-child-default.ts +50 -0
  623. package/src/task-orchestrator/surfaces/pod-child-providers.ts +42 -0
  624. package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
  625. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +94 -7
  626. package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
  627. package/src/task-orchestrator/surfaces/pod-lease.ts +110 -17
  628. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +32 -3
  629. package/src/task-orchestrator/surfaces/pod-pool.ts +86 -18
  630. package/src/task-orchestrator/surfaces/pod-zai-child.ts +101 -0
  631. package/src/task-orchestrator/surfaces/self-implement-pod.ts +463 -50
  632. package/src/task-orchestrator/surfaces/self-implement.ts +25 -3
  633. package/src/telegram-service.ts +5 -1
  634. package/src/telegram.ts +17 -4
  635. package/src/time/format.ts +13 -4
  636. package/src/tool-runtime/goal-author-runtime.ts +1 -0
  637. package/src/tool-runtime/self-cognition-catalog.ts +23 -0
  638. package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
  639. package/src/typecheck-ratchet.ts +1 -0
  640. package/src/user-config.ts +180 -32
  641. package/src/ux-sim/slash-menu-frames.ts +168 -0
  642. package/src/version/packed-revision.json +1 -1
  643. package/src/web-terminal/preview-tap-registry.ts +5 -2
  644. package/src/workflow-runtime/triggers/registry.ts +59 -0
  645. package/src/workflow-runtime/triggers/scheduler.ts +1 -0
  646. package/src/workflow-runtime/triggers/webhook-source.ts +35 -5
  647. package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
  648. package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
  649. package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
  650. package/apps/pwa/out/_next/static/chunks/1307-08b716476f1d50af.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
  652. package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
  653. package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
  654. package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
  656. package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
  661. package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
  670. package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
  671. package/apps/pwa/out/_next/static/chunks/2489-d238d3e2eb5b2bf5.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
  684. package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/3857-5985236d9307f676.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
  692. package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
  697. package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
  699. package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
  703. package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/5633-d6852385000738ef.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
  708. package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/5977-5b9e8a45a5b0c823.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
  713. package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
  714. package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
  716. package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
  717. package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
  725. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
  728. package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
  738. package/apps/pwa/out/_next/static/chunks/8857-aa1cc4ac90af4d40.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
  741. package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/9247-55bcfbb0e8057f59.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
  745. package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
  746. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/approvals/page-88459e0903da2803.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d85c43f46f58716b.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/board/page-4e645600579ae952.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/botlab/page-87edbfd19117823b.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/bots/page-7f0c2b7801ac6a54.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/ceo/page-bf1f030a9d1adffd.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/chat/page-cbaf66b1e1804adf.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/control/page-9f5610caaa06178c.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/decisions/page-ec8f3575e339de74.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/design-check/page-86d753e460f1a989.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/editor/page-4166a7d51cf0a57d.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/exec/page-2a19c5cd3b562580.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/field/page-b6a09cde2e07521a.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/inside/page-f7eae1518ca0c353.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/intake/page-456a8573ad811381.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/layout-8462d6a543cbb2d9.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/live/page-2974cdfb87c0f9c9.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f927ffa25f3c86d1.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/loops/page-abd86cd832aaa011.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/market/page-79daf68f6256adaa.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8c3f168fc3f91939.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/morning/page-786fb4504d0f2fa9.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/not-found-75209f14597dcb8f.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/observatory/page-bf30affe3a85af7e.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1187a44b7515434b.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-3d0910185a66ed54.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f401ee1dd5a26e25.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5dfe7604fd842784.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/page-76cf838050a8d681.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7ec8e289b4c14df6.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-8c8ac17d52be2a79.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d359ab048d63a9d9.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-b8b345c880bf78d1.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/settings/page-f151cc10ad026940.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9875f103057da433.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/setup/page-9789328af9a9aa62.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/share/page-bf495a1e284f4e00.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/showroom/page-a263d94bca4be22a.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/tasks/page-3962eab8ec58d16e.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/term/page-9abcfac07e02a542.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/today/page-bee49f927c333abb.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/trace/page-bac2d56dcb02d955.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/vault/page-937cbcc13176295c.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d09495594f7f480d.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/workflows/page-69cb93d1a2e57e0e.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/app/workspace/page-72ec543928d67c3e.js +0 -1
  795. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-82906eeda0186a7b.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
  802. package/apps/pwa/out/_next/static/css/f2bd5257e6af88d8.css +0 -1
  803. /package/apps/pwa/out/_next/static/{aBi6EyMtLsrl7J8eH4kF7 → Q-7iofoxOEv1WX18S35of}/_ssgManifest.js +0 -0
@@ -0,0 +1,289 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { mkdtempSync, rmSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join, resolve } from 'node:path';
5
+ import { debug } from '../src/debug/log.js';
6
+ import { parseTypecheckErrors, tscEnv } from '../src/typecheck-ratchet.js';
7
+ import { compareDiagnostics, normalizeDiagnostics, type NormalizedDiagnostic } from './tsc-baseline-comparison.js';
8
+
9
+ export interface CommandResult {
10
+ status: number | null;
11
+ signal?: NodeJS.Signals | null;
12
+ stdout: string;
13
+ stderr: string;
14
+ error?: Error;
15
+ durationMs: number;
16
+ }
17
+ export type Runner = (command: string, args: string[], cwd: string, env?: NodeJS.ProcessEnv) => Promise<CommandResult>;
18
+ export interface Metrics { durationMs: number | null; rssMb: number | null; }
19
+ export interface PrMeasurement {
20
+ pr: number;
21
+ head: string;
22
+ base: string;
23
+ verdict: 'missed' | 'same' | 'stricter' | 'unmeasured';
24
+ missedDiagnostics: NormalizedDiagnostic[];
25
+ addedDiagnostics: NormalizedDiagnostic[];
26
+ fullBase: Metrics;
27
+ fullHead: Metrics;
28
+ narrowed: Metrics;
29
+ gateExitCode: number | null;
30
+ reason?: string;
31
+ worktree: string;
32
+ }
33
+ export interface MeasurementReport {
34
+ prs: PrMeasurement[];
35
+ summary: { missed: number; same: number; stricter: number; unmeasured: number; of: number };
36
+ exitCode: number;
37
+ }
38
+ export interface Options { run?: Runner; platform?: NodeJS.Platform; makeTemp?: () => string; removeTemp?: (path: string) => void; }
39
+ interface Pr { number: number; mergeCommit: { oid: string } | null; files: { path: string }[]; mergedAt?: string; changedFiles?: number; }
40
+ const emptyMetrics = (): Metrics => ({ durationMs: null, rssMb: null });
41
+ const hash = (text: string): boolean => /^[0-9a-f]{40}$/i.test(text);
42
+ const reason = (result: CommandResult): string => result.error?.message ?? (result.stderr.trim() || result.stdout.trim() || `exit ${result.status}`);
43
+
44
+ export const spawnRunner: Runner = (command, args, cwd, extraEnv) => new Promise((done) => {
45
+ const started = performance.now();
46
+ const env = tscEnv({ ...process.env, ...extraEnv });
47
+ delete env.GIT_DIR;
48
+ delete env.GIT_WORK_TREE;
49
+ delete env.GIT_COMMON_DIR;
50
+ let child;
51
+ try { child = spawn(command, args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'] }); }
52
+ catch (cause) {
53
+ done({ status: null, stdout: '', stderr: '', error: cause instanceof Error ? cause : new Error(String(cause)), durationMs: performance.now() - started });
54
+ return;
55
+ }
56
+ const stdout: Buffer[] = [];
57
+ const stderr: Buffer[] = [];
58
+ child.stdout.on('data', (chunk: Buffer) => stdout.push(chunk));
59
+ child.stderr.on('data', (chunk: Buffer) => stderr.push(chunk));
60
+ let error: Error | undefined;
61
+ child.on('error', (cause: Error) => { error = cause; });
62
+ child.on('close', (status, signal) => done({ status, signal, stdout: Buffer.concat(stdout).toString(), stderr: Buffer.concat(stderr).toString(), error, durationMs: performance.now() - started }));
63
+ });
64
+
65
+ export function parseRss(output: string, platform: NodeJS.Platform): number | null {
66
+ const mac = output.match(/^\s*(\d+)\s+maximum resident set size\s*$/im);
67
+ const linux = output.match(/^\s*Maximum resident set size \(kbytes\):\s*(\d+)\s*$/im);
68
+ const value = platform === 'darwin' ? mac : platform === 'linux' ? linux : null;
69
+ if (!value) return null;
70
+ const bytes = Number(value[1]) * (platform === 'linux' ? 1024 : 1);
71
+ return Number.isSafeInteger(bytes) ? bytes / 1048576 : null;
72
+ }
73
+
74
+ function optionsFromArgs(argv: readonly string[]): { numbers: number[] | null; recent: number; keep: boolean } {
75
+ let numbers: number[] | null = null;
76
+ let recent = 10;
77
+ let explicitRecent = false;
78
+ let keep = false;
79
+ for (let i = 0; i < argv.length; i++) {
80
+ const arg = argv[i];
81
+ if (arg === '--prs' || arg === '--recent') {
82
+ const value = argv[++i];
83
+ if (!value) throw new Error(`${arg} requires a value`);
84
+ if (arg === '--prs') {
85
+ if (numbers || explicitRecent || !/^\d+(,\d+)*$/.test(value)) throw new Error('invalid --prs list');
86
+ numbers = value.split(',').map(Number);
87
+ if (numbers.some((n) => !Number.isSafeInteger(n) || n < 1) || new Set(numbers).size !== numbers.length) throw new Error('invalid --prs list');
88
+ } else {
89
+ if (numbers || explicitRecent || !/^\d+$/.test(value)) throw new Error('invalid --recent count');
90
+ recent = Number(value);
91
+ if (!Number.isSafeInteger(recent) || recent < 1) throw new Error('invalid --recent count');
92
+ explicitRecent = true;
93
+ }
94
+ } else if (arg === '--json') continue;
95
+ else if (arg === '--keep') keep = true;
96
+ else throw new Error(`unknown option: ${arg}`);
97
+ }
98
+ return { numbers, recent, keep };
99
+ }
100
+
101
+ async function required(run: Runner, command: string, args: string[], cwd: string, env?: NodeJS.ProcessEnv): Promise<CommandResult> {
102
+ const result = await run(command, args, cwd, env);
103
+ if (result.error || result.signal || result.status !== 0) throw new Error(`${command} ${args.join(' ')}: ${reason(result)}`);
104
+ return result;
105
+ }
106
+ function parsePr(value: unknown): Pr {
107
+ if (!value || typeof value !== 'object') throw new Error('invalid PR response');
108
+ const pr = value as Pr;
109
+ if (!Number.isSafeInteger(pr.number) || pr.number < 1 || !pr.mergeCommit || !hash(pr.mergeCommit.oid) || !Array.isArray(pr.files) || !pr.files.every((file) => typeof file?.path === 'string')) throw new Error(`invalid merged PR response: ${JSON.stringify(value)}`);
110
+ return pr;
111
+ }
112
+ const typeScriptFile = (path: string): boolean => /\.[cm]?tsx?$/.test(path);
113
+ /** The list API truncates `files`; when the listed files are fewer than `changedFiles`, read the full paginated list. */
114
+ async function touchesTypeScript(run: Runner, repo: string, pr: Pr): Promise<boolean> {
115
+ if (pr.files.some((file) => typeScriptFile(file.path))) return true;
116
+ if (typeof pr.changedFiles === 'number' && pr.changedFiles <= pr.files.length) return false;
117
+ const all = (await required(run, 'gh', ['api', '--paginate', `repos/{owner}/{repo}/pulls/${pr.number}/files`, '--jq', '.[].filename'], repo)).stdout.split('\n').map((line) => line.trim()).filter(Boolean);
118
+ if (typeof pr.changedFiles === 'number' && all.length < pr.changedFiles) throw new Error(`PR #${pr.number}: file list incomplete (${all.length} of ${pr.changedFiles})`);
119
+ return all.some(typeScriptFile);
120
+ }
121
+ async function selectPrs(repo: string, opts: ReturnType<typeof optionsFromArgs>, run: Runner): Promise<Pr[]> {
122
+ if (opts.numbers) {
123
+ const prs: Pr[] = [];
124
+ for (const n of opts.numbers) {
125
+ const pr = parsePr(JSON.parse((await required(run, 'gh', ['pr', 'view', String(n), '--json', 'number,mergeCommit,files'], repo)).stdout));
126
+ if (pr.number !== n) throw new Error(`requested PR #${n} but received #${pr.number}`);
127
+ prs.push(pr);
128
+ }
129
+ return prs;
130
+ }
131
+ let limit = Math.max(100, opts.recent);
132
+ let previousCount = -1;
133
+ for (;;) {
134
+ const result = await required(run, 'gh', ['pr', 'list', '--state', 'merged', '--base', 'main', '--search', 'sort:merged-desc', '--limit', String(limit), '--json', 'number,mergeCommit,files,mergedAt,changedFiles'], repo);
135
+ const raw: unknown = JSON.parse(result.stdout);
136
+ if (!Array.isArray(raw)) throw new Error('invalid merged PR list');
137
+ if (raw.some((item) => typeof item?.mergedAt !== 'string')) throw new Error('merged PR list has no merge dates');
138
+ const prs: Pr[] = [];
139
+ for (const pr of raw.map(parsePr)) if (await touchesTypeScript(run, repo, pr)) prs.push(pr);
140
+ if (prs.length >= opts.recent || raw.length < limit || raw.length === previousCount) return prs.sort((a, b) => b.mergedAt!.localeCompare(a.mergedAt!)).slice(0, opts.recent);
141
+ previousCount = raw.length;
142
+ limit += 100;
143
+ }
144
+ }
145
+
146
+ function elapsed(result: CommandResult, platform: NodeJS.Platform): Metrics {
147
+ return { durationMs: Number.isFinite(result.durationMs) ? result.durationMs : null, rssMb: parseRss(result.stderr, platform) };
148
+ }
149
+ function checked(result: CommandResult, label: string, output: string): void {
150
+ if (result.error || result.signal || ![0, 1, 2].includes(result.status ?? -1) || /error TS(?:2688|5083|6053)\b|heap out of memory|Ineffective mark-compacts near heap limit/i.test(output)) throw new Error(`${label}: tsc not measured: ${reason(result)}`);
151
+ const diagnostics = parseTypecheckErrors(output);
152
+ if (result.status !== 0 && diagnostics.length === 0) throw new Error(`${label}: nonzero exit without parseable diagnostics: ${reason(result)}`);
153
+ if ((/error TS\d+/.test(output) && diagnostics.length === 0) || (result.status === 0 && diagnostics.length > 0 && label === 'full')) throw new Error(`${label}: inconsistent tsc diagnostics and exit status`);
154
+ }
155
+ function fullDiagnostics(result: CommandResult, root: string): NormalizedDiagnostic[] {
156
+ const output = `${result.stdout}\n${result.stderr}`;
157
+ checked(result, 'full', output);
158
+ return normalizeDiagnostics(parseTypecheckErrors(output), root);
159
+ }
160
+ function gateDiagnostics(result: CommandResult, root: string): NormalizedDiagnostic[] {
161
+ const output = `${result.stdout}\n${result.stderr}`;
162
+ const diagnosticOutput = output.split('\n').map((line) => line.replace(/^ /, '')).join('\n');
163
+ checked(result, 'narrowed', diagnosticOutput);
164
+ if (/tsc 를 «못 쟀다»|tsc 가 정상 실행됐음을 확인할 수 없다|변경 파일 없음|변경 파일 수집 실패/i.test(output)
165
+ || (result.status === 0 && !/\[tsc-gate\] PASS —/.test(output))
166
+ || (result.status !== 0 && !/\[tsc-gate\] FAIL —/.test(output))) throw new Error('narrowed gate did not measure tsc');
167
+ return normalizeDiagnostics(parseTypecheckErrors(diagnosticOutput), root);
168
+ }
169
+ async function timed(run: Runner, platform: NodeJS.Platform, command: string, args: string[], cwd: string, env?: NodeJS.ProcessEnv): Promise<CommandResult> {
170
+ if (platform === 'darwin' || platform === 'linux') return run('/usr/bin/time', [platform === 'darwin' ? '-l' : '-v', command, ...args], cwd, env);
171
+ return run(command, args, cwd, env);
172
+ }
173
+
174
+ /**
175
+ * The pre-merge base of the whole PR. Merge commit → first parent. Single-parent merge commit: the PR's complete
176
+ * commit count comes from REST (`pulls/N .commits`) for every PR — never from the possibly truncated listed commits.
177
+ * One commit → `head^1`. k > 1 commits → squash (one commit on main) or rebase-merge (k rewritten commits); the
178
+ * method is decided by GitHub's commit↔PR association of `head~1 … head~(k-1)` (all ours → rebase → `head~k`,
179
+ * none ours → squash → `head^1`), never by commit subjects. Anything else is ambiguous and the PR is unmeasured,
180
+ * so an error introduced by an earlier rebased commit is never hidden behind a wrong baseline.
181
+ */
182
+ async function preMergeRevision(run: Runner, repo: string, pr: Pr, head: string): Promise<string> {
183
+ const parents = (await required(run, 'git', ['rev-list', '--parents', '-n', '1', head], repo)).stdout.trim().split(/\s+/).filter(Boolean);
184
+ if (parents.length > 2) return `${head}^1`;
185
+ const totalText = (await required(run, 'gh', ['api', `repos/{owner}/{repo}/pulls/${pr.number}`, '--jq', '.commits'], repo)).stdout.trim();
186
+ const total = Number(totalText);
187
+ if (!/^\d+$/.test(totalText) || !Number.isSafeInteger(total) || total < 1) throw new Error(`PR #${pr.number}: commit count unreadable (${totalText || 'empty'}) — pre-merge base not determinable`);
188
+ if (total === 1) return `${head}^1`;
189
+ const ours: boolean[] = [];
190
+ for (let back = 1; back < total; back += 1) {
191
+ const sha = (await required(run, 'git', ['rev-parse', `${head}~${back}`], repo)).stdout.trim();
192
+ if (!hash(sha)) throw new Error(`PR #${pr.number}: ${head}~${back} unresolvable — pre-merge base not determinable`);
193
+ const numbers = (await required(run, 'gh', ['api', `repos/{owner}/{repo}/commits/${sha}/pulls`, '--jq', '.[].number'], repo)).stdout.split(/\s+/).filter(Boolean);
194
+ ours.push(numbers.includes(String(pr.number)));
195
+ }
196
+ if (ours.every(Boolean)) return `${head}~${total}`;
197
+ if (ours.every((owned) => !owned)) return `${head}^1`;
198
+ throw new Error(`PR #${pr.number}: merge method ambiguous (${ours.filter(Boolean).length}/${ours.length} of the preceding commits belong to the PR) — pre-merge base not determinable`);
199
+ }
200
+
201
+ async function measurePr(repo: string, pr: Pr, run: Runner, platform: NodeJS.Platform, keep: boolean, makeTemp: () => string, removeTemp: (path: string) => void): Promise<PrMeasurement> {
202
+ const head = pr.mergeCommit!.oid;
203
+ const workspace = makeTemp();
204
+ const worktree = join(workspace, 'pr');
205
+ const result: PrMeasurement = { pr: pr.number, head, base: '', worktree, verdict: 'unmeasured', missedDiagnostics: [], addedDiagnostics: [], fullBase: emptyMetrics(), fullHead: emptyMetrics(), narrowed: emptyMetrics(), gateExitCode: null };
206
+ let attempted = false;
207
+ try {
208
+ const base = (await required(run, 'git', ['rev-parse', await preMergeRevision(run, repo, pr, head)], repo)).stdout.trim();
209
+ if (!hash(base)) throw new Error(`invalid first parent of ${head}: ${base}`);
210
+ result.base = base;
211
+ attempted = true;
212
+ await required(run, 'git', ['worktree', 'add', '--detach', worktree, head], repo);
213
+ await required(run, 'git', ['checkout', '--detach', base], worktree);
214
+ await required(run, 'bun', ['install', '--frozen-lockfile'], worktree);
215
+ const baseRun = await timed(run, platform, './node_modules/.bin/tsc', ['--noEmit', '-p', 'tsconfig.gate.json'], worktree);
216
+ result.fullBase = elapsed(baseRun, platform);
217
+ const baseline = fullDiagnostics(baseRun, worktree);
218
+ await required(run, 'git', ['checkout', '--detach', head], worktree);
219
+ await required(run, 'bun', ['install', '--frozen-lockfile'], worktree);
220
+ const headRun = await timed(run, platform, './node_modules/.bin/tsc', ['--noEmit', '-p', 'tsconfig.gate.json'], worktree);
221
+ result.fullHead = elapsed(headRun, platform);
222
+ const current = fullDiagnostics(headRun, worktree);
223
+ const added = compareDiagnostics(current, baseline);
224
+ if (added.kind === 'unavailable') throw new Error(added.reason);
225
+ result.addedDiagnostics = added.added;
226
+ const gateRun = await timed(run, platform, 'bun', ['scripts/ci-typecheck-changed.ts', '--local'], worktree, { ...process.env, TSC_BASE_REF: base });
227
+ result.narrowed = elapsed(gateRun, platform);
228
+ result.gateExitCode = gateRun.status;
229
+ const seen = gateDiagnostics(gateRun, worktree);
230
+ const unseen = compareDiagnostics(added.added, seen);
231
+ result.missedDiagnostics = unseen.kind === 'added' ? unseen.added : [];
232
+ result.verdict = added.added.length > 0
233
+ ? gateRun.status === 0 || result.missedDiagnostics.length > 0 ? 'missed' : 'same'
234
+ : gateRun.status === 0 ? 'same' : 'stricter';
235
+ } catch (error) {
236
+ result.reason = error instanceof Error ? error.message : String(error);
237
+ result.verdict = 'unmeasured';
238
+ } finally {
239
+ if (!keep) {
240
+ try {
241
+ if (attempted) {
242
+ const removed = await run('git', ['worktree', 'remove', '--force', worktree], repo);
243
+ if (removed.error || removed.signal || (removed.status !== 0 && !/is not a working tree|is not a worktree/i.test(removed.stderr))) throw new Error(`git worktree remove: ${reason(removed)}`);
244
+ }
245
+ } catch (error) {
246
+ if (result.verdict !== 'missed') result.verdict = 'unmeasured';
247
+ result.reason = `${result.reason ? `${result.reason}; ` : ''}cleanup failed: ${error instanceof Error ? error.message : String(error)}`;
248
+ }
249
+ try { removeTemp(workspace); }
250
+ catch (error) {
251
+ if (result.verdict !== 'missed') result.verdict = 'unmeasured';
252
+ result.reason = `${result.reason ? `${result.reason}; ` : ''}workspace cleanup failed: ${error instanceof Error ? error.message : String(error)}`;
253
+ }
254
+ }
255
+ debug.log('tsc.affected-roots', 'measure-pr', { pr: result.pr, head, base: result.base, verdict: result.verdict, missedDiagnostics: result.missedDiagnostics.length, fullBase: result.fullBase, fullHead: result.fullHead, narrowed: result.narrowed, reason: result.reason });
256
+ }
257
+ return result;
258
+ }
259
+
260
+ export async function measureAffectedRoots(repo: string, argv: readonly string[] = [], options: Options = {}): Promise<MeasurementReport> {
261
+ const opts = optionsFromArgs(argv);
262
+ const run = options.run ?? spawnRunner;
263
+ const prs = await selectPrs(repo, opts, run);
264
+ if (prs.length === 0) throw new Error('no merged TypeScript PRs to measure');
265
+ const rows: PrMeasurement[] = [];
266
+ for (const pr of prs) rows.push(await measurePr(repo, pr, run, options.platform ?? process.platform, opts.keep, options.makeTemp ?? (() => mkdtempSync(join(tmpdir(), 'tsc-affected-roots-'))), options.removeTemp ?? ((path) => rmSync(path, { recursive: true, force: true }))));
267
+ const summary = { missed: rows.filter((row) => row.verdict === 'missed').length, same: rows.filter((row) => row.verdict === 'same').length, stricter: rows.filter((row) => row.verdict === 'stricter').length, unmeasured: rows.filter((row) => row.verdict === 'unmeasured').length, of: rows.length };
268
+ return { prs: rows, summary, exitCode: summary.missed ? 1 : summary.unmeasured ? 2 : 0 };
269
+ }
270
+ export function formatReport(report: MeasurementReport, json = false): string {
271
+ if (json) return JSON.stringify(report);
272
+ const metric = (m: Metrics) => `${m.durationMs === null ? '—' : Math.round(m.durationMs)} / ${m.rssMb === null ? '—' : m.rssMb}`;
273
+ return [
274
+ 'PR | verdict | missed diagnostics | full base ms/RSS MB | full head ms/RSS MB | narrowed ms/RSS MB',
275
+ ...report.prs.map((row) => `#${row.pr} | ${row.verdict} | ${row.missedDiagnostics.length} | ${metric(row.fullBase)} | ${metric(row.fullHead)} | ${metric(row.narrowed)}${row.reason ? ` | ${row.reason}` : ''}`),
276
+ `missed=${report.summary.missed} same=${report.summary.same} stricter=${report.summary.stricter} unmeasured=${report.summary.unmeasured} of ${report.summary.of}`,
277
+ ].join('\n');
278
+ }
279
+ if (import.meta.main) {
280
+ try {
281
+ const argv = process.argv.slice(2);
282
+ const report = await measureAffectedRoots(resolve(process.cwd()), argv);
283
+ console.log(formatReport(report, argv.includes('--json')));
284
+ process.exitCode = report.exitCode;
285
+ } catch (error) {
286
+ console.error(`tsc affected roots measurement unavailable: ${error instanceof Error ? error.message : String(error)}`);
287
+ process.exitCode = 2;
288
+ }
289
+ }
@@ -17,11 +17,15 @@ import { resolveGrokCredential } from '../src/grok/credential.js';
17
17
  import { debug } from '../src/debug/log.js';
18
18
  import { getOpenAiRelaySharedSecret, hydrateEnvFromKeyCache } from '../src/config.js';
19
19
  import { registerLogStoreSink } from '../src/mss/logging/log-store.js';
20
+ import { getUserConfig } from '../src/user-config.js';
20
21
 
21
22
  // ⛔ 독립 프로세스라 데몬의 부팅 배선을 안 탄다 — 스토어 싱크를 «직접» 단다.
22
23
  // 이걸 안 달면 debug.log 가 화면에만 남고 `elanous logs` 조회에 «영영 안 닿는다»
23
24
  // (2026-08-23 실측: nexus.openai-relay 는 닿았고 이 프로세스 자기 로그는 0건이었다).
24
- registerLogStoreSink(debug.registerSink.bind(debug), 'openai-relay');
25
+ // 🩸 10-09 22:2x: 보존 설정 없이 등록하면 기본 상한 500MB 로 시작 보존이 돈다 — 운영 config 는 4000MB 인데
26
+ // 레일 설치마다 재기동되는 이 프로세스가 1.1GB logs.db 의 행을 최대 50% 지웠다(«지운 주체가 안 보이는» 소실).
27
+ // 다른 독립 스크립트처럼 config 의 보존 값을 넘긴다.
28
+ registerLogStoreSink(debug.registerSink.bind(debug), 'openai-relay', getUserConfig().logs.retention);
25
29
 
26
30
  const MODELS_PATH = '/v1/models';
27
31
  const HEALTH_PATH = '/healthz';
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env bun
2
- import { chmodSync, existsSync, readdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
3
- import { randomUUID } from 'node:crypto';
4
- import { spawnSync } from 'node:child_process';
5
- import { mkdtempSync } from 'node:fs';
2
+ import { chmodSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
3
+ import { createHash, randomUUID } from 'node:crypto';
4
+ import { spawn, spawnSync } from 'node:child_process';
5
+ import { isAbsolute, basename, dirname, join, resolve } from 'node:path';
6
6
  import { tmpdir } from 'node:os';
7
- import { basename, dirname, join, resolve } from 'node:path';
8
7
  import { debug } from '../../src/debug/log.js';
9
8
  import { effectiveInstanceRoot } from '../../src/instance/resolve.js';
10
9
  import type { ReleaseManifest } from '../../src/release-loop/manifest.js';
11
10
  import { flipNextReleaseMarkers, foldPreLandedNotes, renderReleaseNotes } from './release-docs.js';
12
- import { emitNodeResult, readGraphContext } from './node-verdict.js';
11
+ import { emitNodeResult, lastResult, nodeOutput, readGraphContext, type GraphContext } from './node-verdict.js';
12
+ import { reusableTui, withTuiOutcome } from './tui-node-checks.js';
13
13
 
14
14
  interface DocsResult {
15
15
  outcome: 'ok' | 'error';
@@ -126,47 +126,262 @@ export function runDocs(
126
126
  }
127
127
  }
128
128
 
129
- if (import.meta.main) {
130
- let result: DocsResult | undefined;
131
- const graphContext = process.env.ELANOUS_GRAPH_CONTEXT;
132
- let isReleaseGraph = false;
129
+ // Prefetch artifacts live alongside THIS graph run's numbered context files, never in a global version cache.
130
+ const SHA = /^[0-9a-f]{40}$/i;
131
+ const PREFETCH_DEADLINE_MS = 15 * 60_000;
132
+ type Cut = { version: string; commit: string; manifestHash: string };
133
+ type PrefetchCache = Cut & { main: string; tree: string; docs: DocsResult; tui: Record<string, unknown> | null };
134
+ type Runner = (command: string, args: string[], cwd?: string, timeout?: number, env?: NodeJS.ProcessEnv) => string;
135
+ export const commandRunner: Runner = (command, args, cwd, timeout, env) => {
136
+ const output = spawnSync(command, args, { cwd, env: env ?? process.env, timeout: timeout ?? 15 * 60_000, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
137
+ if (output.status !== 0 || output.error) throw new Error(`${command} ${args[0]} failed: ${output.error ?? output.stderr ?? output.stdout}`);
138
+ return output.stdout.trim();
139
+ };
140
+
141
+ function runCacheDir(env: NodeJS.ProcessEnv): string {
142
+ const path = env.ELANOUS_GRAPH_CONTEXT;
143
+ if (!path || !isAbsolute(path) || !/^\d+\.json$/.test(basename(path)) || !dirname(path).endsWith('.json.contexts')) {
144
+ throw new Error('prefetch requires an absolute graph run context file');
145
+ }
146
+ return join(dirname(path), 'docs-prefetch');
147
+ }
148
+ function cutFor(context: GraphContext, stateRoot: string): Cut {
149
+ const version = context.input.version;
150
+ const commit = nodeOutput(context, 'version-release', 'commit');
151
+ if (context.outputs['version-release']?.outcome !== 'ok' || !SHA.test(commit)) throw new Error('invalid release commit');
152
+ const raw = readFileSync(join(stateRoot, 'release', version, 'manifest.json'));
153
+ const manifest = JSON.parse(raw.toString()) as ReleaseManifest;
154
+ if (manifest.version !== version || manifest.cutoff?.sha !== commit || !Array.isArray(manifest.in)) throw new Error('manifest cutoff differs from release commit');
155
+ return { version, commit, manifestHash: createHash('sha256').update(raw).digest('hex') };
156
+ }
157
+ /** Exclusive create — true iff this caller is the first to claim the run's prefetch slot. */
158
+ function claimPrefetch(dir: string, owner: 'worker' | 'docs'): boolean {
159
+ try { writeFileSync(join(dir, 'claim'), owner, { flag: 'wx' }); return true; }
160
+ catch (error) { if ((error as NodeJS.ErrnoException).code === 'EEXIST') return false; throw error; }
161
+ }
162
+ function cacheFile(dir: string, cut: Cut): string {
163
+ return join(dir, `${cut.commit}-${cut.manifestHash}.json`);
164
+ }
165
+ function loadCache(dir: string, cut: Cut): PrefetchCache | null {
166
+ try {
167
+ const value = JSON.parse(readFileSync(cacheFile(dir, cut), 'utf8')) as PrefetchCache;
168
+ if (value.version !== cut.version || value.commit !== cut.commit || value.manifestHash !== cut.manifestHash
169
+ || !SHA.test(value.main) || value.tree !== join(dir, 'tree') || !existsSync(value.tree)
170
+ || value.docs?.outcome !== 'ok' || value.docs.version !== cut.version
171
+ || value.docs.notes !== join(value.tree, 'release/public/docs/releases', `${cut.version}.md`)
172
+ || value.docs.pages !== join(value.tree, 'website/pages.json')
173
+ || !existsSync(value.docs.notes) || !existsSync(value.docs.pages)) return null;
174
+ return value;
175
+ } catch { return null; }
176
+ }
177
+
178
+ /** Worker performs ONLY local reads and temporary worktree writes; failure is a cache miss, not a gate failure. */
179
+ export function stagePrefetch(context: GraphContext, env: NodeJS.ProcessEnv = process.env, repo = process.cwd(),
180
+ runner: Runner = commandRunner, deps: { stateRoot?: string; tui?: (commit: string) => Record<string, unknown> | null; deadline?: number } = {}): PrefetchCache {
181
+ // One whole-worker deadline: every step gets at most the time left, and no step starts after it.
182
+ const deadline = deps.deadline ?? Date.now() + PREFETCH_DEADLINE_MS;
183
+ const left = () => {
184
+ const ms = deadline - Date.now();
185
+ if (ms <= 0) throw new Error('prefetch worker deadline exceeded');
186
+ return ms;
187
+ };
188
+ const run: Runner = (command, args, cwd, timeout, childEnv) => runner(command, args, cwd, Math.min(timeout ?? 15 * 60_000, left()), childEnv);
189
+ const dir = runCacheDir(env);
190
+ const stateRoot = deps.stateRoot ?? effectiveInstanceRoot();
191
+ const cut = cutFor(context, stateRoot);
192
+ mkdirSync(dir, { recursive: true });
193
+ const already = loadCache(dir, cut);
194
+ if (already) return already;
195
+ const tree = join(dir, 'tree');
196
+ let added = false;
133
197
  try {
134
- if (graphContext) {
135
- const value = JSON.parse(graphContext.trimStart().startsWith('{') ? graphContext : readFileSync(graphContext, 'utf8')) as { input?: { previousVersion?: unknown }; outputs?: unknown };
136
- isReleaseGraph = value?.input?.previousVersion !== undefined || value?.outputs !== undefined;
198
+ const main = run('git', ['rev-parse', '--verify', 'origin/main^{commit}'], repo);
199
+ if (!SHA.test(main)) throw new Error('invalid origin/main commit');
200
+ // TUI runs against the cut, on its own isolated worktree, before touching the docs checkout.
201
+ // tui-sim-node.ts prints the RAW result (no `outcome`); judge it the way node-verdict.ts tui would before reuse.
202
+ const tuiData = deps.tui ? deps.tui(cut.commit) : (() => {
203
+ const tuiRun = spawnSync('bun', ['scripts/release-loop/tui-sim-node.ts', '--commit', cut.commit, '--json'], {
204
+ cwd: repo, timeout: Math.min(6 * 60_000, left()), encoding: 'utf8', maxBuffer: 16 * 1024 * 1024,
205
+ });
206
+ return tuiRun.status === 0 ? lastResult({ status: tuiRun.status, stdout: tuiRun.stdout ?? '', stderr: tuiRun.stderr ?? '' }) ?? null : null;
207
+ })();
208
+ const tui = reusableTui(withTuiOutcome(0, tuiData), cut.commit);
209
+ run('git', ['worktree', 'add', '--detach', tree, main], repo);
210
+ added = true;
211
+ run('bun', ['install', '--frozen-lockfile'], tree);
212
+ // Docs staging runs as its own process so the whole-worker deadline can stop it (an in-process call could not be).
213
+ const docsOut = run(process.execPath, [resolve(import.meta.filename), '--version', cut.version, '--base', tree, '--json'], repo, undefined,
214
+ { ...process.env, ELANOUS_GRAPH_CONTEXT: '', ELANOUS_STATE_DIR: stateRoot });
215
+ const docs = JSON.parse(docsOut.trim().split('\n').at(-1) ?? 'null') as DocsResult;
216
+ if (!docs || typeof docs !== 'object') throw new Error('docs staging returned no result');
217
+ if (docs.outcome !== 'ok') throw new Error(docs.error ?? 'docs staging failed');
218
+ // Recheck the cut before publishing an atomic result; stale results are never reused.
219
+ left();
220
+ const finalCut = cutFor(context, stateRoot);
221
+ if (finalCut.manifestHash !== cut.manifestHash) throw new Error('manifest changed during prefetch');
222
+ const result: PrefetchCache = { ...cut, main, tree, docs, tui };
223
+ const final = cacheFile(dir, cut);
224
+ const staged = `${final}.${process.pid}.${randomUUID()}.tmp`;
225
+ writeFileSync(staged, JSON.stringify(result) + '\n');
226
+ // Publication handshake: whoever creates `claim` first (O_EXCL) wins. The docs node claims before it reads,
227
+ // so a worker that loses can never publish a cache that a docs attempt would consume.
228
+ if (!claimPrefetch(dir, 'worker')) {
229
+ rmSync(staged, { force: true });
230
+ throw new Error('docs node already ran; late prefetch is discarded');
137
231
  }
232
+ renameSync(staged, final);
233
+ return result;
138
234
  } catch (error) {
139
- result = { outcome: 'error', version: null, error: error instanceof Error ? error.message : String(error) };
235
+ if (added) { try { runner('git', ['worktree', 'remove', '--force', tree], repo, 60_000); } catch { /* preserve original failure */ } }
236
+ throw error;
140
237
  }
141
- if (!result && isReleaseGraph) {
142
- let version: string | null = null;
143
- let tree: string | undefined;
144
- try {
238
+ }
239
+
240
+ /** TUI is measured against the cut commit, so reuse keys on commit ⊕ manifest hash only — origin/main is a docs-tree input, not a TUI input. */
241
+ export function joinTui(context: GraphContext, env: NodeJS.ProcessEnv, repo: string,
242
+ fallback: (commit: string) => { status: number | null; stdout: string; stderr: string } = (commit) => {
243
+ const output = spawnSync('bun', ['scripts/release-loop/node-verdict.ts', 'tui'], {
244
+ cwd: repo, env, encoding: 'utf8', timeout: 7 * 60_000, maxBuffer: 16 * 1024 * 1024,
245
+ });
246
+ return { status: output.status, stdout: output.stdout ?? '', stderr: output.stderr ?? '' };
247
+ }, stateRoot = effectiveInstanceRoot()): Record<string, unknown> {
248
+ if (context.outputs.upgrade?.outcome !== 'ok') throw new Error('upgrade did not pass');
249
+ // Any failure to key the cache (no manifest, cutoff mismatch, no run dir) is a cache miss → original TUI path.
250
+ let cut: Cut | null = null;
251
+ let cached: PrefetchCache | null = null;
252
+ try { cut = cutFor(context, stateRoot); cached = loadCache(runCacheDir(env), cut); } catch { /* cache miss */ }
253
+ const reused = cut && cached?.tui && reusableTui(cached.tui, cut.commit);
254
+ if (reused) return { ...reused, outcome: 'ok', summary: `tui ${reused.verdict}` };
255
+ // Preserve node-verdict.ts's exit convention and last-JSON output on a cache miss.
256
+ const output = fallback(cut?.commit ?? String(context.outputs['version-release']?.commit ?? ''));
257
+ const data = lastResult(output);
258
+ if (!data) throw new Error(`tui fallback returned no verdict: ${output.stderr}`);
259
+ // A timed-out or crashed fallback never passes on an earlier success line: exit status, outcome and verdict must agree.
260
+ // node-verdict.ts convention: ok ↔ exit 0 with pass|flaky · fail ↔ exit 1 with fail · error ↔ exit 2.
261
+ const agrees = output.status === 0 ? data.outcome === 'ok' && (data.verdict === 'pass' || data.verdict === 'flaky')
262
+ : output.status === 1 ? data.outcome === 'fail' && data.verdict === 'fail'
263
+ : output.status === 2 ? data.outcome === 'error' && data.verdict === 'fail' : false;
264
+ if (!agrees) {
265
+ throw new Error(`tui fallback exited ${output.status} with outcome ${String(data.outcome)} / verdict ${String(data.verdict)}`);
266
+ }
267
+ return data;
268
+ }
269
+
270
+ export function graphDocs(context: GraphContext, env: NodeJS.ProcessEnv, repo: string, run: Runner = commandRunner,
271
+ stateRoot = effectiveInstanceRoot()): DocsResult {
272
+ const version = context.input.version;
273
+ let tree: string | undefined;
274
+ // Before ANY check (and so also on every failure path): only the first docs attempt may consume a staged cache,
275
+ // and only when the worker won the claim; otherwise this attempt claims the slot so a late worker cannot publish.
276
+ let mayConsume = false;
277
+ let cacheDir: string | undefined;
278
+ try {
279
+ cacheDir = runCacheDir(env);
280
+ mkdirSync(cacheDir, { recursive: true });
281
+ const closed = join(cacheDir, 'docs-closed');
282
+ const firstAttempt = !existsSync(closed);
283
+ writeFileSync(closed, `${new Date().toISOString()}\n`);
284
+ const docsWon = claimPrefetch(cacheDir, 'docs');
285
+ mayConsume = firstAttempt && !docsWon && readFileSync(join(cacheDir, 'claim'), 'utf8') === 'worker';
286
+ } catch { /* standalone/legacy graph — no prefetch */ }
287
+ try {
288
+ // No fetch (nor any write to remote) until every gate is verified.
289
+ for (const node of ['gate', 'prepare', 'upgrade', 'tui']) if (context.outputs[node]?.outcome !== 'ok') throw new Error(`${node} did not pass`);
290
+ let cached: PrefetchCache | null = null;
291
+ // A cache key that cannot be computed is a miss — the original fresh-worktree path runs.
292
+ if (mayConsume && cacheDir) { try { const cut = cutFor(context, stateRoot); cached = loadCache(cacheDir, cut); } catch { cached = null; } }
293
+ const branch = `release-docs/${version}`;
294
+ run('git', ['fetch', 'origin', 'main'], repo);
295
+ const main = run('git', ['rev-parse', '--verify', 'origin/main^{commit}'], repo);
296
+ if (cached && cached.main === main && SHA.test(main)) {
297
+ tree = cached.tree;
298
+ // Attach the staged detached checkout to the branch only at the late docs node.
299
+ run('git', ['-C', tree, 'switch', '-c', branch], repo);
300
+ // Consumed: a resumed run must not reuse a tree that is now on the branch (fresh path instead).
301
+ rmSync(cacheFile(cacheDir!, cached), { force: true });
302
+ } else {
303
+ const root = mkdtempSync(join(tmpdir(), 'release-docs-'));
304
+ tree = join(root, 'tree');
305
+ run('git', ['worktree', 'add', '-b', branch, tree, 'origin/main'], repo);
306
+ run('bun', ['install', '--frozen-lockfile'], tree);
307
+ }
308
+ const result = cached && cached.main === main ? cached.docs : runDocs(['--version', version, '--base', tree, '--json'], repo, env, { stateRoot });
309
+ if (result.outcome !== 'ok') throw new Error(result.error ?? 'docs generation failed');
310
+ run('git', ['add', 'release/public/docs', 'website/pages.json'], tree);
311
+ run('git', ['commit', '-m', `docs: release ${version}`], tree);
312
+ run('git', ['push', '-u', 'origin', branch], tree);
313
+ return { ...result, branch, worktree: tree };
314
+ } catch (error) {
315
+ return { outcome: 'error', version, error: error instanceof Error ? error.message : String(error), ...(tree ? { worktree: tree } : {}) };
316
+ }
317
+ }
318
+
319
+ /** Detached prefetch worker; an asynchronous spawn failure is logged as a cache miss and never escapes the node. */
320
+ export function startPrefetchWorker(version: string, commit: string,
321
+ spawnWorker: () => ReturnType<typeof spawn> = () => spawn(process.execPath, [resolve(import.meta.filename), '--prefetch-worker'], {
322
+ cwd: process.cwd(), env: process.env, detached: true, stdio: ['ignore', 'ignore', 'ignore'],
323
+ })): number {
324
+ const child = spawnWorker();
325
+ child.on('error', (error) => debug.log('release-loop.docs', 'prefetch-skipped', { version, commit, reason: `worker spawn error: ${error.message}` }));
326
+ if (!child.pid) throw new Error('prefetch worker did not start');
327
+ child.unref();
328
+ return child.pid;
329
+ }
330
+
331
+ function graphNodeId(env: NodeJS.ProcessEnv): string | null {
332
+ const location = env.ELANOUS_GRAPH_CONTEXT;
333
+ if (!location) return null;
334
+ const context = JSON.parse(location.trimStart().startsWith('{') ? location : readFileSync(location, 'utf8')) as { nodeId?: unknown; input?: { previousVersion?: unknown }; outputs?: unknown };
335
+ return typeof context.nodeId === 'string' ? context.nodeId : context.input?.previousVersion !== undefined || context.outputs !== undefined ? 'docs' : null;
336
+ }
337
+
338
+ if (import.meta.main) {
339
+ let result: DocsResult | (Record<string, unknown> & { outcome: 'ok' | 'error' | 'fail'; version?: string | null; error?: string });
340
+ let node: string | null = null;
341
+ try {
342
+ node = graphNodeId(process.env);
343
+ if (process.argv.includes('--prefetch-worker')) {
344
+ if (node !== 'prefetch') throw new Error('prefetch worker requires prefetch node');
145
345
  const context = readGraphContext();
146
- version = context.input.version;
147
- for (const node of ['upgrade', 'tui', 'prepare', 'gate']) if (context.outputs[node]?.outcome !== 'ok') throw new Error(`${node} did not pass`);
148
- const branch = `release-docs/${version}`;
149
- const run = (command: string, args: string[], cwd = process.cwd()) => {
150
- const output = spawnSync(command, args, { cwd, encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
151
- if (output.status !== 0) throw new Error(`${command} ${args[0]} failed: ${output.stderr || output.stdout}`);
152
- return output.stdout.trim();
153
- };
154
- run('git', ['fetch', 'origin', 'main']);
155
- tree = mkdtempSync(join(tmpdir(), 'release-docs-'));
156
- const worktree = join(tree, 'tree');
157
- run('git', ['worktree', 'add', '-b', branch, worktree, 'origin/main']);
158
- run('bun', ['install', '--frozen-lockfile'], worktree);
159
- result = runDocs(['--version', version, '--base', worktree, '--json']);
160
- if (result.outcome !== 'ok') throw new Error(result.error ?? 'docs generation failed');
161
- run('git', ['add', 'release/public/docs', 'website/pages.json'], worktree);
162
- run('git', ['commit', '-m', `docs: release ${version}`], worktree);
163
- run('git', ['push', '-u', 'origin', branch], worktree);
164
- result = { ...result, branch, worktree };
165
- } catch (error) {
166
- result = { outcome: 'error', version, error: error instanceof Error ? error.message : String(error), ...(tree ? { worktree: join(tree, 'tree') } : {}) };
346
+ stagePrefetch(context);
347
+ // Worker stdout is not a graph verdict; the initiating node has already returned.
348
+ process.exit(0);
167
349
  }
168
- } else if (!result) result = runDocs(process.argv.slice(2));
169
- debug.log('release-loop.docs', 'result', { version: result.version, outcome: result.outcome });
170
- emitNodeResult({ ...result, verdict: result.outcome === 'ok' ? 'pass' : 'fail', summary: result.outcome === 'ok' ? `docs v${result.version} · ${result.flipped?.length ?? 0} pages` : `docs: ${result.error ?? 'failed'}` });
171
- if (result.outcome === 'error') process.exitCode = 1;
350
+ if (node === 'prefetch') {
351
+ let version: string | null = null;
352
+ try {
353
+ const context = readGraphContext();
354
+ version = context.input.version;
355
+ const cut = cutFor(context, effectiveInstanceRoot());
356
+ const dir = runCacheDir(process.env);
357
+ mkdirSync(dir, { recursive: true });
358
+ if (!loadCache(dir, cut)) {
359
+ const pid = startPrefetchWorker(cut.version, cut.commit);
360
+ // This is not a gate: the late nodes validate the atomic artifact or run their original path.
361
+ debug.log('release-loop.docs', 'prefetch-start', { version: cut.version, commit: cut.commit, pid });
362
+ }
363
+ result = { outcome: 'ok', version: cut.version, summary: `prefetch v${cut.version} started` };
364
+ } catch (error) {
365
+ // Any pre-worker failure is a cache miss — the gate and the late nodes' original paths still run.
366
+ const reason = error instanceof Error ? error.message : String(error);
367
+ debug.log('release-loop.docs', 'prefetch-skipped', { version, reason });
368
+ result = { outcome: 'ok', version, summary: `prefetch skipped (cache miss): ${reason}` };
369
+ }
370
+ } else if (node === 'tui') {
371
+ const context = readGraphContext();
372
+ result = { ...joinTui(context, process.env, process.cwd()), version: context.input.version } as typeof result;
373
+ } else if (node === 'docs') {
374
+ result = graphDocs(readGraphContext(), process.env, process.cwd(), commandRunner);
375
+ } else if (node === null) result = runDocs(process.argv.slice(2));
376
+ else throw new Error(`unknown release docs node: ${node}`);
377
+ } catch (error) {
378
+ result = { outcome: 'error', version: null, error: error instanceof Error ? error.message : String(error) };
379
+ }
380
+ debug.log('release-loop.docs', 'result', { node, version: result.version, outcome: result.outcome });
381
+ const details = result as Record<string, unknown>;
382
+ const verdict = details.verdict;
383
+ emitNodeResult({ ...details, outcome: result.outcome, verdict: verdict === 'pass' || verdict === 'flaky' || verdict === 'fail' ? verdict : result.outcome === 'ok' ? 'pass' : 'fail',
384
+ summary: typeof details.summary === 'string' ? details.summary : result.outcome === 'ok'
385
+ ? `docs v${result.version} · ${(details.flipped as string[] | undefined)?.length ?? 0} pages` : `docs: ${result.error ?? 'failed'}` });
386
+ if (result.outcome !== 'ok') process.exitCode = result.outcome === 'fail' ? 1 : node === 'tui' ? 2 : 1;
172
387
  }