elanous 0.2.36 → 0.2.38

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 (741) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 1026-44010f405704050c.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
  6. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 1632.7d87f998e714bede.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
  14. package/apps/pwa/out/_next/static/chunks/{7784.1f0ac4a16d190cf4.js → 2104.70e086d5174a4736.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{6566.926a1d1b7c911442.js → 214.186a430da28338f1.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
  18. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
  19. package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 2415.738b777642a02233.js} +1 -1
  20. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 3086.fb14b60ce98b53d3.js} +1 -1
  27. package/apps/pwa/out/_next/static/chunks/{3148-98efd4869d660a87.js → 3124-561f7f037943cde2.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
  31. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 3291.f6c1005387d514bd.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
  34. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
  38. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 3528.e4b8ab70d339f965.js} +2 -2
  40. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
  45. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{3031-85328a92fcce4da6.js → 4199-f7c6eb40cd0322f8.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
  57. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +90 -0
  58. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
  60. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
  63. package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
  65. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
  68. package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 5307.d7328020227880c2.js} +4 -4
  70. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
  73. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5638.107314dc479e2f37.js} +2 -2
  75. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
  80. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/{6925.562d532110879886.js → 6493.27ad77de7aac7966.js} +1 -1
  84. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +62 -0
  88. package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 7161-8f22db3ec5ed005e.js} +3 -3
  89. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 7488.966b116789f3d41a.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/{4116.a84a92a2492c080e.js → 7524.ce973525d30b3d52.js} +1 -1
  94. package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
  95. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 7628.6b16863ac3972333.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 7954.4f7a8832663ee979.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 8019.21ca554a821dad01.js} +16 -16
  102. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 8487.291666583bebe640.js} +1 -1
  107. package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 8879.ac06755bcf3e44a1.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
  111. package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 8911.bf5e712acb25fb6c.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 8994d93e.33ba491f95345fc2.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{599.c39c571b6733f2a2.js → 9223.cbcc88e0e9950426.js} +2 -2
  115. package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
  116. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
  117. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{8037.e254fd797aa224d1.js → 9581.da63ddf41acfad46.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
  121. package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/{page-e7abc34a48a6f71e.js → page-291ab19fe2acb173.js} +1 -1
  153. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-c15958835534404b.js → page-6b140f77593576eb.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → b7459770.6539b11860eb8a9c.js} +7 -7
  174. package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → b7478fef.5917716286213fcc.js} +3 -3
  175. package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/{2812ca6a.3b9f4a7a08885744.js → de8b930d.d94c0f42acf807fc.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → eaad0cba.771200940c529df7.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
  184. package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/graphs/drafts/recipes.yaml +27 -7
  279. package/graphs/release/recipes.yaml +9 -0
  280. package/graphs/release/release-loop.yaml +26 -18
  281. package/graphs/work/draft-close.yaml +54 -0
  282. package/graphs/work/green-close.yaml +37 -0
  283. package/graphs/work/recipes.yaml +46 -1
  284. package/graphs/work/run-research.yaml +35 -0
  285. package/package.json +1 -1
  286. package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
  287. package/scripts/ask-op-inbox-once.ts +17 -0
  288. package/scripts/boundary-proof-mapping-audit.ts +88 -0
  289. package/scripts/brand/check.ts +13 -4
  290. package/scripts/codex-fallback-live-probe.ts +17 -15
  291. package/scripts/fleet/node-setup.sh +32 -2
  292. package/scripts/fleet/run-light-worker.sh +9 -0
  293. package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
  294. package/scripts/gate-0226-failure-census.ts +546 -0
  295. package/scripts/goals/authoring-metrics.ts +258 -0
  296. package/scripts/graph-units/draft-close-node.ts +222 -0
  297. package/scripts/hook-order-sweep.ts +7 -4
  298. package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
  299. package/scripts/land-global-checks.ts +69 -1
  300. package/scripts/measure-nl-routing-corpus.ts +207 -2
  301. package/scripts/provision-export-redactions.ts +15 -0
  302. package/scripts/public-copy-lint.ts +122 -0
  303. package/scripts/public-export.ts +69 -2
  304. package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
  305. package/scripts/ratchets/train-side-invariants.sh +7 -1
  306. package/scripts/release-loop/cut-branch.ts +61 -12
  307. package/scripts/release-loop/docs-node.ts +140 -0
  308. package/scripts/release-loop/gate-closure.ts +48 -0
  309. package/scripts/release-loop/gate-diff.ts +2 -1
  310. package/scripts/release-loop/gate-node.ts +161 -25
  311. package/scripts/release-loop/gate-partial.ts +82 -3
  312. package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
  313. package/scripts/release-loop/gate-radius-live.ts +4 -2
  314. package/scripts/release-loop/known-issues-node.ts +6 -4
  315. package/scripts/release-loop/notes-repair.ts +216 -0
  316. package/scripts/release-loop/prepare-node.ts +61 -5
  317. package/scripts/release-loop/resume-cap.ts +2 -1
  318. package/scripts/release-loop/resume-release.ts +406 -7
  319. package/scripts/release-loop/resume-test-traffic.ts +10 -0
  320. package/scripts/release-loop/resume.ts +13 -5
  321. package/scripts/release-loop/traffic-node.ts +12 -4
  322. package/scripts/release-loop/traffic-transition.ts +53 -13
  323. package/scripts/release-loop/version-node.ts +109 -15
  324. package/scripts/train/green-leg.ts +176 -0
  325. package/scripts/tui-continue-real-evidence.ts +47 -0
  326. package/scripts/ux-sim.ts +1 -1
  327. package/scripts/video-pipeline.ts +2 -2
  328. package/src/acp/client.ts +31 -5
  329. package/src/acp/core-turn-bridge.ts +12 -1
  330. package/src/acp/stderr-summary.ts +49 -0
  331. package/src/agent/monad-agent-turn.ts +1 -0
  332. package/src/agent/run-context.ts +1 -1
  333. package/src/agent/task-notification.ts +3 -1
  334. package/src/agent/terminal-surface.ts +217 -0
  335. package/src/agent-substrate/pr-reviewer.ts +11 -3
  336. package/src/agent-substrate/review-observation.ts +10 -0
  337. package/src/agent-substrate/self-review-cli.ts +537 -57
  338. package/src/auto-research/question-ladder-contract.ts +137 -0
  339. package/src/auto-research/research-turn.ts +134 -0
  340. package/src/autopilot/discovery/doc-lint.ts +1 -1
  341. package/src/autopilot/lineage/sources.ts +1 -1
  342. package/src/autopilot/pr-manager.ts +64 -13
  343. package/src/boot/daemon-runtime.ts +35 -3
  344. package/src/boot/daemon-tools/pty-shell.ts +2 -1
  345. package/src/bots/screen-probe.ts +1 -1
  346. package/src/budget/run-usage-rollup.ts +12 -7
  347. package/src/budget/unified-usage.ts +20 -0
  348. package/src/capture/tui-self-report.ts +42 -5
  349. package/src/chat/index.ts +1 -0
  350. package/src/chat/tool-render/dispatch.ts +8 -1
  351. package/src/cli/autopilot-cli.ts +24 -9
  352. package/src/cli/decisions-cli.ts +7 -4
  353. package/src/cli/doctor-cli.ts +116 -7
  354. package/src/cli/guardian-cli.ts +3 -1
  355. package/src/cli/intake-cli.ts +48 -12
  356. package/src/cli/lesson-cli.ts +69 -9
  357. package/src/cli/logs-cli.ts +357 -2
  358. package/src/cli/memory-cli.ts +30 -1
  359. package/src/cli/msg-cli.ts +15 -11
  360. package/src/cli/pr-granularity.ts +5 -3
  361. package/src/cli/pr-land-overlap-evidence.ts +38 -5
  362. package/src/cli/pr-land-refusal.ts +1 -1
  363. package/src/cli/pty-takeover-cli.ts +58 -5
  364. package/src/cli/release-checklist-read-cli.ts +112 -4
  365. package/src/cli/release-cli.ts +89 -18
  366. package/src/cli/review-carry.ts +77 -0
  367. package/src/cli/self-update.ts +24 -6
  368. package/src/cli/self-utterances-cli.ts +13 -16
  369. package/src/cli/tasks-card-show.ts +31 -1
  370. package/src/cli/tasks-cli.ts +370 -33
  371. package/src/cli/tasks-read-cli.ts +13 -5
  372. package/src/cli/usage-cli.ts +12 -10
  373. package/src/context-bus/claude-memory-import.ts +99 -0
  374. package/src/context-bus/context-now.ts +86 -2
  375. package/src/context-bus/long-term-memory.ts +125 -0
  376. package/src/core-turn/run-core-turn.ts +9 -2
  377. package/src/core-turn/run-goal-loop.ts +5 -2
  378. package/src/core-turn/types.ts +5 -0
  379. package/src/dashboard/chat/acp-chat.ts +9 -0
  380. package/src/dashboard/index.ts +115 -30
  381. package/src/dashboard/input/agent-wake.ts +43 -0
  382. package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
  383. package/src/dashboard/input/terminal-modal-router.ts +8 -159
  384. package/src/dashboard/replay-preview.ts +25 -0
  385. package/src/dashboard/side-basic-runtime.ts +61 -0
  386. package/src/dashboard/slash-runtime/dashboard-handlers.ts +19 -8
  387. package/src/dashboard/synchronized-frame-output.ts +74 -0
  388. package/src/dashboard/term-slash-runtime.ts +2 -0
  389. package/src/dashboard/turn-preamble.ts +28 -4
  390. package/src/display/coordinator.ts +45 -12
  391. package/src/display/resize-listener.ts +41 -20
  392. package/src/display/synchronized-output-region.ts +60 -0
  393. package/src/domains/guardian-tick.ts +9 -0
  394. package/src/domains/surface-events.ts +80 -1
  395. package/src/exec-requests/planner.ts +37 -2
  396. package/src/execution-loop/launch-gate.ts +4 -3
  397. package/src/git-fs/cli-stderr.ts +45 -0
  398. package/src/git-fs/gh-cli.ts +6 -3
  399. package/src/git-fs/git-cli.ts +11 -5
  400. package/src/git-fs/watcher.ts +27 -22
  401. package/src/git-fs/worktree.ts +19 -3
  402. package/src/graph-runner/graph-cli.ts +26 -2
  403. package/src/graph-runner/graph-grow.ts +37 -9
  404. package/src/graph-runner/graph-run-api.ts +3 -2
  405. package/src/graph-runner/runner.ts +34 -7
  406. package/src/graph-wizard/generate.ts +29 -6
  407. package/src/grok/credential.ts +107 -36
  408. package/src/harness/harness-cli-command.ts +179 -33
  409. package/src/harness/review-adapter.ts +26 -6
  410. package/src/hq/fence-wrapper.ts +1 -1
  411. package/src/hq/transfer.ts +1 -1
  412. package/src/index.ts +151 -18
  413. package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
  414. package/src/intake-plane/collect-telegram-saved.ts +54 -5
  415. package/src/interactive-terminal-modal.ts +3 -0
  416. package/src/keybindings.ts +17 -22
  417. package/src/llm/provider-credentials.ts +1 -1
  418. package/src/llm/route-decision.ts +13 -0
  419. package/src/llm-tool-name.ts +37 -0
  420. package/src/llm-tool-schema.ts +55 -0
  421. package/src/llm.ts +203 -21
  422. package/src/loops/checker.ts +100 -0
  423. package/src/loops/consensus.ts +26 -2
  424. package/src/loops/loop-cli.ts +9 -4
  425. package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
  426. package/src/loops/orchestrator/inbox-once.ts +28 -0
  427. package/src/loops/orchestrator/inbox.ts +130 -1
  428. package/src/loops/orchestrator/tick.ts +55 -7
  429. package/src/maturity/feature-maturity.ts +1 -0
  430. package/src/model-tier/llm-tier-map.ts +12 -17
  431. package/src/msg/msg-store.ts +17 -0
  432. package/src/native-tool-catalog.ts +1 -1
  433. package/src/nexus/api/channel-ask-op.ts +96 -0
  434. package/src/nexus/api/discord-trigger-bot.ts +28 -1
  435. package/src/nexus/api/graph-wizard-api.ts +27 -2
  436. package/src/nexus/api/grid.ts +24 -4
  437. package/src/nexus/api/http-server.ts +1 -1
  438. package/src/nexus/api/ops-api.ts +14 -6
  439. package/src/nexus/api/telegram-trigger-bot.ts +24 -0
  440. package/src/nexus/api/terminals.ts +28 -6
  441. package/src/nexus/state/state.ts +7 -1
  442. package/src/oauth/codex-account-store.ts +34 -1
  443. package/src/ops/loops-map.ts +46 -0
  444. package/src/ops/overview-cache.ts +22 -4
  445. package/src/ops/overview.ts +41 -5
  446. package/src/patents/ledger.ts +18 -1
  447. package/src/policy/llm-policy.ts +3 -1
  448. package/src/preview/terminal.ts +4 -2
  449. package/src/prompt-cache/anthropic.ts +2 -0
  450. package/src/prompt-enhance/enhance.ts +9 -4
  451. package/src/pty-shell/availability.ts +7 -0
  452. package/src/pty-shell/herdr-agent-report.ts +40 -31
  453. package/src/pty-shell/herdr-prune-stale.ts +17 -0
  454. package/src/pty-shell/herdr-sequence-lease.ts +60 -0
  455. package/src/pty-shell/pty-control-ipc.ts +187 -18
  456. package/src/pty-shell/pty-manifest.ts +16 -2
  457. package/src/pty-shell/registry.ts +25 -15
  458. package/src/pty-shell/tui-run-state.ts +235 -1
  459. package/src/release-loop/checklist.ts +50 -5
  460. package/src/release-loop/feature-store.ts +9 -9
  461. package/src/release-loop/gate-shards.ts +61 -0
  462. package/src/release-loop/landed-but-yellow.ts +93 -12
  463. package/src/release-loop/light-rc.ts +7 -4
  464. package/src/release-loop/rehearsal.ts +1 -1
  465. package/src/repl/index.ts +18 -0
  466. package/src/research/axis-fanout.ts +133 -0
  467. package/src/research/edge-decision.ts +88 -0
  468. package/src/research/output-router.ts +127 -0
  469. package/src/research-bridge/format.ts +16 -1
  470. package/src/research-bridge/index.ts +1 -0
  471. package/src/research-bridge/invoke.ts +41 -5
  472. package/src/seat-loop/seat-report.ts +1 -0
  473. package/src/self-dev/ask-launch-flow.ts +86 -10
  474. package/src/self-dev/decompose-proposal.ts +29 -18
  475. package/src/self-dev/decompose.ts +45 -9
  476. package/src/self-dev/dev-pipeline.ts +29 -7
  477. package/src/self-dev/draft-residue.ts +221 -2
  478. package/src/self-dev/draft-sweep.ts +254 -16
  479. package/src/self-dev/draft-triage-rules.ts +19 -5
  480. package/src/self-dev/orchestrate.ts +1 -0
  481. package/src/self-dev/review-provider-fallback.ts +45 -7
  482. package/src/self-dev/run-supervisor.ts +22 -7
  483. package/src/self-dev/shard-plan.ts +48 -0
  484. package/src/self-dev/shard-run.ts +310 -6
  485. package/src/self-implement/comment-only-source.ts +54 -0
  486. package/src/self-implement/doctor-visit.ts +108 -0
  487. package/src/self-implement/gate-artifacts.ts +6 -2
  488. package/src/self-implement/gate-baseline.ts +99 -1
  489. package/src/self-implement/gate-cli.ts +231 -82
  490. package/src/self-implement/gate-failure-signature.ts +44 -0
  491. package/src/self-implement/gate-remote.ts +30 -4
  492. package/src/self-implement/gate-scope.ts +13 -1
  493. package/src/self-implement/goal-author.ts +407 -21
  494. package/src/self-implement/goal-doc/section.ts +22 -0
  495. package/src/self-implement/goal-supervisor-fill.ts +110 -27
  496. package/src/self-implement/importer-test-index.ts +215 -2
  497. package/src/self-implement/knowhow-pack.ts +125 -12
  498. package/src/self-implement/l8-merge-queue.ts +198 -32
  499. package/src/self-implement/off-diff-evidence.ts +23 -0
  500. package/src/self-implement/orchestrator.ts +369 -33
  501. package/src/self-implement/pod-inplace-worktree.ts +82 -0
  502. package/src/self-implement/pod-warm-pool-profile.ts +2 -2
  503. package/src/self-implement/premise-review.ts +7 -5
  504. package/src/self-implement/review-round-brief.ts +300 -0
  505. package/src/self-implement/rework-policy.ts +14 -0
  506. package/src/self-implement/run-ledger.ts +428 -6
  507. package/src/self-implement/run-stop.ts +1 -1
  508. package/src/self-implement/running-runs.ts +17 -3
  509. package/src/self-implement/seams.ts +45 -16
  510. package/src/self-implement/self-implement-cli.ts +26 -2
  511. package/src/self-implement/stop-autoheal.ts +1 -0
  512. package/src/self-implement/test-seams.ts +13 -1
  513. package/src/self-implement/train-reach-grouping.ts +8 -2
  514. package/src/session/channel-ask-op-envelope.ts +36 -0
  515. package/src/session/channel-op-reply-route.ts +200 -0
  516. package/src/session/chat.ts +10 -1
  517. package/src/session/id-prefix.ts +60 -0
  518. package/src/session/index.ts +6 -0
  519. package/src/session-runtime/index.ts +18 -23
  520. package/src/skills/runner.ts +7 -3
  521. package/src/skills/tools/dev-harness.ts +2 -2
  522. package/src/skills/tools/pty.ts +5 -0
  523. package/src/skills/tools/schedule-wakeup.ts +1 -6
  524. package/src/status/bar.ts +3 -3
  525. package/src/status/metrics.ts +12 -1
  526. package/src/steward/rejudge-tick.ts +12 -5
  527. package/src/steward/resync-tick.ts +31 -4
  528. package/src/storage/file-lock.ts +17 -4
  529. package/src/task-agent/actions.ts +199 -4
  530. package/src/task-agent/adopt-pr.ts +63 -2
  531. package/src/task-agent/boundary-proof-mapping.ts +12 -0
  532. package/src/task-agent/boundary-proof-producer.ts +147 -0
  533. package/src/task-agent/completion-evidence.ts +2 -1
  534. package/src/task-agent/evidence-command-normalize.ts +42 -0
  535. package/src/task-agent/export-redactions-provision.ts +43 -0
  536. package/src/task-agent/green-close-recipe.ts +239 -0
  537. package/src/task-agent/green-sweep.ts +64 -10
  538. package/src/task-agent/live-moves.ts +48 -3
  539. package/src/task-agent/map-host-adapter.ts +134 -0
  540. package/src/task-agent/map-reduce.ts +158 -0
  541. package/src/task-agent/map-run-ledger.ts +226 -0
  542. package/src/task-agent/parent-host.ts +74 -17
  543. package/src/task-agent/rejudge-on-head.ts +72 -5
  544. package/src/task-agent/repair-cycle.ts +108 -8
  545. package/src/task-agent/repair-next-move.ts +12 -2
  546. package/src/task-agent/repair-worker.ts +37 -1
  547. package/src/task-agent/review-prior-fix.ts +12 -2
  548. package/src/task-agent/shadow.ts +188 -5
  549. package/src/task-agent/task-hand.ts +253 -20
  550. package/src/task-agent/task-parent-role-llm.ts +9 -0
  551. package/src/task-agent/tier-split.ts +40 -5
  552. package/src/task-agent/work-order.ts +53 -2
  553. package/src/task-orchestrator/dispatcher.ts +46 -1
  554. package/src/task-orchestrator/generator-prompt.ts +6 -0
  555. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
  556. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
  557. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
  558. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
  559. package/src/task-orchestrator/surfaces/pod-pool.ts +77 -8
  560. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
  561. package/src/task-orchestrator/surfaces/self-implement-pod.ts +338 -79
  562. package/src/task-orchestrator/surfaces/self-implement.ts +37 -2
  563. package/src/terminal/session-registry.ts +1 -0
  564. package/src/terminal/terminal-modal-router.ts +156 -0
  565. package/src/testing/linux-env.ts +177 -0
  566. package/src/tool-hints/gate.ts +6 -4
  567. package/src/tool-hints/signals.ts +33 -1
  568. package/src/tui/chat/background-job-status.ts +8 -2
  569. package/src/tui/chat/goal-interim.ts +5 -1
  570. package/src/tui/entry.ts +722 -30
  571. package/src/tui/input/at-picker.ts +55 -0
  572. package/src/tui/sidetab/attach.ts +304 -0
  573. package/src/tui/sidetab/list.ts +176 -0
  574. package/src/tui/sidetab/nl-tool.ts +136 -0
  575. package/src/tui/slash/resume-command.ts +23 -0
  576. package/src/tui/slash/resume.ts +38 -35
  577. package/src/tui/slash/signals.ts +114 -0
  578. package/src/tui/slash/term-next.ts +72 -0
  579. package/src/tui-client/local-chat-turn.ts +31 -9
  580. package/src/user-config.ts +30 -3
  581. package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
  582. package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
  583. package/src/ux-sim/fake-gh.ts +174 -0
  584. package/src/ux-sim/fake-kubectl.ts +142 -0
  585. package/src/ux-sim/fake-llm.ts +17 -6
  586. package/src/ux-sim/next-tui-seat-scenarios.ts +176 -6
  587. package/src/ux-sim/resume-picker-device.ts +173 -0
  588. package/src/ux-sim/session-id-seed.ts +60 -0
  589. package/src/ux-sim/skills-tools-shell-device.ts +156 -0
  590. package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
  591. package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
  592. package/src/version/packed-revision.json +1 -1
  593. package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
  594. package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +0 -64
  600. package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
  601. package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
  604. package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
  609. package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
  612. package/apps/pwa/out/_next/static/chunks/2986.45d7652e4f13557e.js +0 -2
  613. package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
  614. package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
  618. package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
  619. package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
  621. package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/3757-180308bc61021b05.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
  625. package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
  629. package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
  632. package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
  634. package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
  636. package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
  641. package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
  653. package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/7481.39f7a4654907bf6e.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
  664. package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
  666. package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
  667. package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
  672. package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/ccae1c4b-0cf414f5eff1b10d.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
  739. package/scripts/migrate-monad-to-elanous.ts +0 -195
  740. package/scripts/rebrand-elanous.ts +0 -242
  741. /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
@@ -0,0 +1,124 @@
1
+ import ts from 'typescript';
2
+ import { readdirSync, readFileSync, statSync } from 'node:fs';
3
+ import { dirname, join, relative, resolve, sep } from 'node:path';
4
+
5
+ export const ENTRY_LINE_LIMIT = 4_000;
6
+ export const ENTRY_MODULE_LIMIT = 1_188;
7
+ export const INDEX_MODULE_LIMIT = 1_264;
8
+ const DASHBOARD_BASELINE = 'src/dashboard/loop-scheduler.ts';
9
+
10
+ export interface AuditResult { errors: string[]; notes: string[]; entryModules: number; indexModules: number; oversized: Array<{ file: string; lines: number }> }
11
+
12
+ function walkTs(root: string): string[] {
13
+ return readdirSync(root).flatMap((name) => {
14
+ const path = join(root, name);
15
+ return statSync(path).isDirectory() ? walkTs(path) : /\.(?:[cm]?ts|tsx)$/.test(path) ? [path] : [];
16
+ });
17
+ }
18
+
19
+ function isInside(root: string, path: string): boolean {
20
+ const rel = relative(root, path);
21
+ return rel === '' || (!rel.startsWith(`..${sep}`) && rel !== '..' && !resolve(path).startsWith(`${resolve(root, 'node_modules')}${sep}`));
22
+ }
23
+
24
+ function staticClosure(repo: string, entry: string): Set<string> {
25
+ const configPath = join(repo, 'tsconfig.json');
26
+ const config = ts.readConfigFile(configPath, ts.sys.readFile);
27
+ if (config.error) throw new Error(ts.flattenDiagnosticMessageText(config.error.messageText, '\n'));
28
+ const parsed = ts.parseJsonConfigFileContent(config.config, ts.sys, repo);
29
+ if (parsed.errors.length) throw new Error(parsed.errors.map((diagnostic) => ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')).join('; '));
30
+ const options = parsed.options;
31
+ const seen = new Set<string>();
32
+ const visit = (file: string): void => {
33
+ const abs = resolve(file);
34
+ if (seen.has(abs)) return;
35
+ seen.add(abs);
36
+ const source = ts.createSourceFile(abs, readFileSync(abs, 'utf8'), ts.ScriptTarget.Latest, true);
37
+ for (const node of source.statements) {
38
+ if (ts.isImportDeclaration(node)) {
39
+ if (node.importClause?.isTypeOnly || !ts.isStringLiteral(node.moduleSpecifier)) continue;
40
+ const specifier = node.moduleSpecifier.text;
41
+ const result = ts.resolveModuleName(specifier, abs, options, ts.sys).resolvedModule;
42
+ if (!result) {
43
+ if (specifier.startsWith('.') || specifier.startsWith('/')) throw new Error(`unresolved static import ${relative(repo, abs)} -> ${specifier}`);
44
+ continue;
45
+ }
46
+ if (isInside(repo, result.resolvedFileName)) visit(result.resolvedFileName);
47
+ } else if (ts.isExportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
48
+ if (node.isTypeOnly) continue;
49
+ const specifier = node.moduleSpecifier.text;
50
+ const result = ts.resolveModuleName(specifier, abs, options, ts.sys).resolvedModule;
51
+ if (!result) {
52
+ if (specifier.startsWith('.') || specifier.startsWith('/')) throw new Error(`unresolved static re-export ${relative(repo, abs)} -> ${specifier}`);
53
+ continue;
54
+ }
55
+ if (isInside(repo, result.resolvedFileName)) visit(result.resolvedFileName);
56
+ }
57
+ }
58
+ };
59
+ visit(entry);
60
+ return seen;
61
+ }
62
+
63
+ export function entryBudgetAffected(changedFiles: readonly string[]): boolean {
64
+ if (changedFiles.some((file) => file === 'bin/elanous.mjs' || file === 'tsconfig.json' || file === 'scripts/ratchets/next-tui-entry-budget.ts')) return true;
65
+ // Any source edit can add/remove an importer or delete a module from a base
66
+ // closure. The changed tree alone cannot prove non-membership in the base graph.
67
+ return changedFiles.some((file) => /^src\/.+\.[cm]?[jt]sx?$/.test(file));
68
+ }
69
+
70
+ export function audit(repo: string): AuditResult {
71
+ const errors: string[] = [];
72
+ const notes: string[] = [];
73
+ const tuiFiles = [join(repo, 'src/tui.ts'), ...walkTs(join(repo, 'src/tui'))];
74
+ const oversized = tuiFiles.map((file) => {
75
+ const contents = readFileSync(file, 'utf8');
76
+ const lines = contents.length === 0 ? 0 : contents.split(/\r?\n/).length - (contents.endsWith('\n') ? 1 : 0);
77
+ return { file: relative(repo, file), lines };
78
+ })
79
+ .filter(({ lines }) => lines > ENTRY_LINE_LIMIT);
80
+ for (const item of oversized) errors.push(`${item.file}: ${item.lines} lines exceeds ${ENTRY_LINE_LIMIT}`);
81
+
82
+ const entryClosure = staticClosure(repo, join(repo, 'src/tui/entry.ts'));
83
+ const entryPaths = [...entryClosure].map((file) => relative(repo, file).replaceAll('\\', '/'));
84
+ if (entryClosure.size > ENTRY_MODULE_LIMIT) errors.push(`Next entry static module count ${entryClosure.size} exceeds ${ENTRY_MODULE_LIMIT}`);
85
+ else if (entryClosure.size < ENTRY_MODULE_LIMIT) notes.push(`tighten entry module cap ${ENTRY_MODULE_LIMIT} -> ${entryClosure.size}`);
86
+ const forbiddenIndex = entryPaths.filter((p) => p === 'src/index.ts');
87
+ if (forbiddenIndex.length) errors.push('Next entry statically imports forbidden src/index.ts');
88
+ const dashboard = entryPaths.filter((p) => p.startsWith('src/dashboard/'));
89
+ const unexpectedDashboard = dashboard.filter((p) => p !== DASHBOARD_BASELINE);
90
+ if (unexpectedDashboard.length) errors.push(`forbidden dashboard static imports: ${unexpectedDashboard.join(', ')}`);
91
+ if (dashboard.includes(DASHBOARD_BASELINE)) notes.push(`${DASHBOARD_BASELINE} is temporary baseline; remove at NEXT-TUI-EXTRACT-FROM-INDEX`);
92
+
93
+ const binPath = join(repo, 'bin/elanous.mjs');
94
+ const bin = readFileSync(binPath, 'utf8');
95
+ // The deployment entry sends every unrecognized route to src/index.ts. The current
96
+ // light router does not claim --tui next, so measure that fallback's static closure.
97
+ const binSource = ts.createSourceFile(binPath, bin, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);
98
+ let importsIndex = false;
99
+ const visitBin = (node: ts.Node): void => {
100
+ if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword
101
+ && node.arguments[0] && ts.isStringLiteral(node.arguments[0])
102
+ && /(?:^|\/)src\/index\.ts$/.test(node.arguments[0].text.replaceAll('\\', '/'))) importsIndex = true;
103
+ ts.forEachChild(node, visitBin);
104
+ };
105
+ visitBin(binSource);
106
+ const indexClosure = importsIndex ? staticClosure(repo, join(repo, 'src/index.ts')) : new Set<string>();
107
+ if (importsIndex && indexClosure.size > INDEX_MODULE_LIMIT) errors.push(`bin --tui next index static module count ${indexClosure.size} exceeds ${INDEX_MODULE_LIMIT}`);
108
+ else if (importsIndex && indexClosure.size < INDEX_MODULE_LIMIT) notes.push(`tighten index module cap ${INDEX_MODULE_LIMIT} -> ${indexClosure.size} after entry extraction`);
109
+ else if (!importsIndex) notes.push('bin has no dynamic import of src/index.ts; index fallback budget no longer applies');
110
+ return { errors, notes, entryModules: entryClosure.size, indexModules: indexClosure.size, oversized };
111
+ }
112
+
113
+ if (import.meta.main) {
114
+ try {
115
+ const result = audit(resolve(dirname(new URL(import.meta.url).pathname), '../..'));
116
+ console.log(`NEXT_TUI_ENTRY_BUDGET entryModules=${result.entryModules} indexModules=${result.indexModules} oversized=${result.oversized.length}`);
117
+ for (const note of result.notes) console.log(`NOTE ${note}`);
118
+ for (const error of result.errors) console.error(`FAIL ${error}`);
119
+ process.exitCode = result.errors.length ? 1 : 0;
120
+ } catch (error) {
121
+ console.error(`UNMEASURED ${error instanceof Error ? error.message : String(error)}`);
122
+ process.exitCode = 2;
123
+ }
124
+ }
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env bash
2
- # Train-side sentinel for the eight real HARD 0.2.32 regressions. Run on the
2
+ # Train-side sentinel for the HARD regressions and release-critical invariants. Run on the
3
3
  # merged side tree before the changed-file gate; never interpret a missing test
4
4
  # or an incomplete run as a pass.
5
5
  set -u
6
6
 
7
7
  files=(
8
8
  scripts/ratchets/test-interference-patterns.test.ts
9
+ scripts/ratchets/next-tui-entry-budget.test.ts
9
10
  src/domains/finance-cli.test.ts
10
11
  src/instance/state-dir-provenance-ratchet.test.ts
11
12
  src/self-implement/graph-yaml.test.ts
@@ -13,6 +14,11 @@ files=(
13
14
  test/identity-env.test.ts
14
15
  test/no-absolute-path-imports.test.ts
15
16
  test/scenarios/integration.test.ts
17
+ test/rules-contract.test.ts
18
+ test/hook-order-sweep.test.ts
19
+ src/cli/g6a-commands.test.ts
20
+ test/spawn-sync-max-buffer.test.ts
21
+ test/telegram-coding-model-terra.test.ts
16
22
  )
17
23
 
18
24
  if [[ ${1:-} == --list ]]; then
@@ -6,7 +6,18 @@ import { join, resolve } from 'node:path';
6
6
  import { debug } from '../../src/debug/log.js';
7
7
  import { isReleaseVersion } from './release-version.js';
8
8
 
9
- export interface CutBranchOptions { version: string; base: string; pick: string[]; append?: boolean; dryRun?: boolean; repoRoot?: string; log?: (line: string) => void }
9
+ export interface CutBranchOptions {
10
+ version: string;
11
+ /** Optional only on the --append path (RELEASE-APPEND-BASE-AUTO); required without --append. */
12
+ base?: string;
13
+ pick: string[];
14
+ append?: boolean;
15
+ dryRun?: boolean;
16
+ repoRoot?: string;
17
+ log?: (line: string) => void;
18
+ /** Run ledger's version-release record ({ commit, branch, base? }) — consulted when --append omits --base. */
19
+ ledger?: () => { commit?: unknown; base?: unknown; branch?: unknown } | undefined;
20
+ }
10
21
 
11
22
  // git-spawn-allow: release branch operations happen only in an isolated temporary worktree; main is never checked out or changed.
12
23
  function git(repo: string, args: string[]): string {
@@ -21,24 +32,35 @@ function ancestor(repo: string, sha: string, ref: string): boolean {
21
32
  return result.status === 0;
22
33
  }
23
34
 
35
+ /** RELEASE-APPEND-BASE-AUTO: the first parent of a release-branch tip — the commit main was cut from when the branch carries only release-side commits. */
36
+ function firstParent(repo: string, sha: string): string | undefined {
37
+ const parts = git(repo, ['rev-list', '--parents', '-n', '1', sha]).split(/\s+/);
38
+ const parent = parts[1];
39
+ return parent !== undefined && /^[0-9a-f]{40}$/i.test(parent) ? parent : undefined;
40
+ }
41
+
42
+ /** RELEASE-APPEND-BASE-AUTO: the main cut recorded by the run ledger's version-release node — its base field when present, else the first parent of its commit. Unresolvable records degrade to undefined so the caller keeps its refusal. */
43
+ function ledgerCut(repo: string, recorded: { commit?: unknown; base?: unknown; branch?: unknown } | undefined): string | undefined {
44
+ if (!recorded) return undefined;
45
+ try {
46
+ if (typeof recorded.base === 'string' && /^[0-9a-f]{7,40}$/i.test(recorded.base)) return git(repo, ['rev-parse', '--verify', `${recorded.base}^{commit}`]);
47
+ if (typeof recorded.commit === 'string' && /^[0-9a-f]{7,40}$/i.test(recorded.commit)) return firstParent(repo, git(repo, ['rev-parse', '--verify', `${recorded.commit}^{commit}`]));
48
+ } catch { return undefined; }
49
+ return undefined;
50
+ }
51
+
24
52
  export function cutReleaseBranch(opts: CutBranchOptions): { branch: string; commit: string | null; dryRun: boolean } {
25
53
  const repo = resolve(opts.repoRoot ?? process.cwd());
26
54
  const branch = `release/${opts.version}`;
27
55
  const log = opts.log ?? console.log;
28
- const report = (event: 'created' | 'refused' | 'conflict' | 'appended', reason?: string, commit?: string, extra?: Record<string, string | string[]>) =>
56
+ const report = (event: 'created' | 'refused' | 'conflict' | 'appended' | 'base-resolved' | 'base-corrected', reason?: string, commit?: string, extra?: Record<string, string | string[]>) =>
29
57
  debug.log('release-loop.cut-branch', event, { version: opts.version, branch, ...(commit ? { commit } : {}), ...(reason ? { reason } : {}), ...extra });
30
58
  try {
31
59
  if (!isReleaseVersion(opts.version)) throw new Error(`invalid release version: ${opts.version}`);
32
60
  if (!opts.pick.length) throw new Error('at least one --pick commit is required');
33
- for (const sha of [opts.base, ...opts.pick]) if (!/^[0-9a-f]{7,40}$/i.test(sha)) throw new Error(`invalid commit SHA: ${sha}`);
61
+ if (opts.base === undefined && !opts.append) throw new Error('--base is required without --append');
62
+ for (const sha of [opts.base, ...opts.pick]) if (sha !== undefined && !/^[0-9a-f]{7,40}$/i.test(sha)) throw new Error(`invalid commit SHA: ${sha}`);
34
63
  git(repo, ['fetch', 'origin', 'main']);
35
- const base = git(repo, ['rev-parse', '--verify', `${opts.base}^{commit}`]);
36
- if (!ancestor(repo, base, 'origin/main')) throw new Error(`base ${base} is not an ancestor of origin/main`);
37
- const picks = opts.pick.map((sha) => git(repo, ['rev-parse', '--verify', `${sha}^{commit}`]));
38
- for (const sha of picks) if (!ancestor(repo, sha, 'origin/main')) throw new Error(`pick ${sha} is not an ancestor of origin/main`);
39
- for (const sha of picks) if (ancestor(repo, sha, base)) throw new Error(`pick ${sha} is already in base ${base}`);
40
- if (new Set(picks).size !== picks.length) throw new Error('duplicate --pick commit');
41
- for (const sha of picks) if (git(repo, ['rev-list', '--parents', '-n', '1', sha]).split(' ').length !== 2) throw new Error(`pick ${sha} must have exactly one parent`);
42
64
  const remoteLine = git(repo, ['ls-remote', '--heads', 'origin', `refs/heads/${branch}`]);
43
65
  if (remoteLine && !opts.append) throw new Error(`${branch} already exists on origin — use --append to fast-forward more picks onto it`);
44
66
  if (!remoteLine && opts.append) throw new Error(`${branch} does not exist on origin — omit --append to create it`);
@@ -50,13 +72,40 @@ export function cutReleaseBranch(opts: CutBranchOptions): { branch: string; comm
50
72
  git(repo, ['fetch', 'origin', `refs/heads/${branch}:refs/remotes/origin/${branch}`]);
51
73
  remoteTip = git(repo, ['rev-parse', '--verify', `refs/remotes/origin/${branch}^{commit}`]);
52
74
  if (advertised !== remoteTip) throw new Error(`${branch} remote tip moved — fast-forward refused (no force push)`);
53
- for (const sha of picks) if (ancestor(repo, sha, remoteTip)) throw new Error(`pick ${sha} is already in ${branch}`);
54
75
  }
76
+ // RELEASE-APPEND-BASE-AUTO (OP 0.2.38): a cut commit lives only on the release branch, so the main cut is resolved
77
+ // before the ancestor refusal — from the run ledger's version-release record, else the release tip's first parent.
78
+ let base: string;
79
+ if (opts.base !== undefined) {
80
+ base = git(repo, ['rev-parse', '--verify', `${opts.base}^{commit}`]);
81
+ } else {
82
+ const fromLedger = ledgerCut(repo, opts.ledger?.());
83
+ const ledgerCandidate = fromLedger !== undefined && ancestor(repo, fromLedger, 'origin/main') ? fromLedger : undefined;
84
+ const candidate = ledgerCandidate ?? (remoteTip !== undefined ? firstParent(repo, remoteTip) : undefined);
85
+ if (candidate === undefined || !ancestor(repo, candidate, 'origin/main'))
86
+ throw new Error(`base ${candidate ?? remoteTip ?? branch} is not an ancestor of origin/main`);
87
+ base = candidate;
88
+ report('base-resolved', undefined, base, { source: ledgerCandidate !== undefined ? 'ledger' : 'first-parent' });
89
+ }
90
+ if (!ancestor(repo, base, 'origin/main')) {
91
+ if (!opts.append) throw new Error(`base ${base} is not an ancestor of origin/main`);
92
+ const parent = firstParent(repo, base);
93
+ if (parent === undefined || !ancestor(repo, parent, 'origin/main')) throw new Error(`base ${base} is not an ancestor of origin/main`);
94
+ log(`base ${base} 는 origin/main 에 없다 — 그 부모 ${parent} 를 쓰라 (auto-corrected)`);
95
+ report('base-corrected', `그 부모 ${parent} 를 쓰라 — ${base} 는 origin/main 에 없다`, base, { parent });
96
+ base = parent;
97
+ }
98
+ const picks = opts.pick.map((sha) => git(repo, ['rev-parse', '--verify', `${sha}^{commit}`]));
99
+ for (const sha of picks) if (!ancestor(repo, sha, 'origin/main')) throw new Error(`pick ${sha} is not an ancestor of origin/main`);
100
+ for (const sha of picks) if (ancestor(repo, sha, base)) throw new Error(`pick ${sha} is already in base ${base}`);
101
+ if (new Set(picks).size !== picks.length) throw new Error('duplicate --pick commit');
102
+ for (const sha of picks) if (git(repo, ['rev-list', '--parents', '-n', '1', sha]).split(' ').length !== 2) throw new Error(`pick ${sha} must have exactly one parent`);
103
+ if (opts.append) for (const sha of picks) if (ancestor(repo, sha, remoteTip!)) throw new Error(`pick ${sha} is already in ${branch}`);
55
104
  const versionAt = remoteTip ?? base;
56
105
  const pkg = JSON.parse(git(repo, ['show', `${versionAt}:package.json`])) as { version?: unknown };
57
106
  if (pkg.version !== opts.version) throw new Error(`${opts.append ? 'release branch' : 'base'} package.json version ${pkg.version} is not ${opts.version}`);
58
107
  const start = remoteTip ?? base;
59
- log(`${branch}: ${start} + ${picks.join(' + ')}${opts.append ? ' (append)' : ''}${opts.dryRun ? ' (dry-run)' : ''}`);
108
+ log(`${branch}: ${start} + ${picks.join(' + ')}${opts.append ? ' (append)' : ''}${opts.dryRun ? ' (dry-run)' : ''}${base !== start ? ` · base ${base}` : ''}`);
60
109
  if (opts.dryRun) return { branch, commit: null, dryRun: true };
61
110
  const temp = mkdtempSync(join(tmpdir(), 'release-cut-branch-'));
62
111
  const tree = join(temp, 'tree');
@@ -22,6 +22,7 @@ interface DocsResult {
22
22
  branch?: string;
23
23
  worktree?: string;
24
24
  translationFallbacks?: number;
25
+ artifactOwner?: { runId: string; attempt: number; localBackup?: string; remoteBackup?: string; remoteHead?: string };
25
26
  }
26
27
 
27
28
  type TranslationRunner = (line: string) => string;
@@ -495,6 +496,11 @@ export function joinTui(context: GraphContext, env: NodeJS.ProcessEnv, repo: str
495
496
  export function graphDocs(context: GraphContext, env: NodeJS.ProcessEnv, repo: string, run: Runner = commandRunner,
496
497
  stateRoot = effectiveInstanceRoot()): DocsResult {
497
498
  const version = context.input.version;
499
+ if (context.runId) {
500
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(context.runId))
501
+ return { outcome: 'error', version, error: 'invalid release runId' };
502
+ return graphDocsOwned(context, env, repo, run, stateRoot);
503
+ }
498
504
  let tree: string | undefined;
499
505
  // Before ANY check (and so also on every failure path): only the first docs attempt may consume a staged cache,
500
506
  // and only when the worker won the claim; otherwise this attempt claims the slot so a late worker cannot publish.
@@ -541,6 +547,137 @@ export function graphDocs(context: GraphContext, env: NodeJS.ProcessEnv, repo: s
541
547
  }
542
548
  }
543
549
 
550
+ type DocsOwner = NonNullable<DocsResult['artifactOwner']>;
551
+ type DocsReceipt = { owner: DocsOwner; branch: string; worktree: string; outcome: 'staged' | 'pushed'; result?: DocsResult; head?: string };
552
+
553
+ /** The resume count is part of the artifact key; the first run has attempt zero. */
554
+ function docsAttempt(stateRoot: string, version: string, runId: string): number {
555
+ const path = join(stateRoot, 'release', version, 'resume-attempts', `${runId}.json`);
556
+ if (!existsSync(path)) return 0;
557
+ const value = JSON.parse(readFileSync(path, 'utf8')) as { version?: unknown; runId?: unknown; attempts?: unknown };
558
+ if (value.version !== version || value.runId !== runId || !Array.isArray(value.attempts)
559
+ || value.attempts.some((at) => typeof at !== 'string' || !Number.isFinite(Date.parse(at))))
560
+ throw new Error(`invalid release resume attempts ledger: ${path}`);
561
+ return value.attempts.length;
562
+ }
563
+
564
+ function docsReceipt(path: string): DocsReceipt | null {
565
+ if (!existsSync(path)) return null;
566
+ const value = JSON.parse(readFileSync(path, 'utf8')) as DocsReceipt;
567
+ if (!value || typeof value !== 'object' || !value.owner || typeof value.owner.runId !== 'string'
568
+ || !Number.isSafeInteger(value.owner.attempt) || typeof value.worktree !== 'string'
569
+ || typeof value.branch !== 'string' || !['staged', 'pushed'].includes(value.outcome))
570
+ throw new Error(`invalid docs ownership receipt: ${path}`);
571
+ return value;
572
+ }
573
+
574
+ function remoteBranchHead(run: Runner, repo: string, branch: string): string | null {
575
+ const line = run('git', ['ls-remote', '--heads', 'origin', `refs/heads/${branch}`], repo).trim();
576
+ if (!line) return null;
577
+ const match = /^([0-9a-f]{40})\s+refs\/heads\/[^\s]+$/i.exec(line);
578
+ if (!match) throw new Error(`invalid remote docs branch response: ${line}`);
579
+ return match[1]!;
580
+ }
581
+
582
+ function graphDocsOwned(context: GraphContext, env: NodeJS.ProcessEnv, repo: string, run: Runner, stateRoot: string): DocsResult {
583
+ const version = context.input.version;
584
+ const runId = context.runId!;
585
+ let tree: string | undefined;
586
+ let owner: DocsOwner | undefined;
587
+ let mayConsume = false;
588
+ let cacheDir: string | undefined;
589
+ try {
590
+ cacheDir = runCacheDir(env);
591
+ mkdirSync(cacheDir, { recursive: true });
592
+ const closed = join(cacheDir, 'docs-closed');
593
+ const firstAttempt = !existsSync(closed);
594
+ writeFileSync(closed, `${new Date().toISOString()}\n`);
595
+ const docsWon = claimPrefetch(cacheDir, 'docs');
596
+ mayConsume = firstAttempt && !docsWon && readFileSync(join(cacheDir, 'claim'), 'utf8') === 'worker';
597
+ } catch { /* standalone graph: no prefetch slot */ }
598
+ try {
599
+ for (const node of ['gate', 'prepare', 'upgrade', 'tui']) if (context.outputs[node]?.outcome !== 'ok') throw new Error(`${node} did not pass`);
600
+ const attempt = docsAttempt(stateRoot, version, runId);
601
+ const branch = `release-docs/${version}`;
602
+ const receiptPath = join(stateRoot, 'release', version, 'docs-branch-owner.json');
603
+ const previous = docsReceipt(receiptPath);
604
+ const sameOwner = previous?.owner.runId === runId && previous.owner.attempt === attempt && previous.branch === branch;
605
+ let cached: DocsCache | null = null;
606
+ if (mayConsume && cacheDir) { try { cached = loadCache(cacheDir, cutFor(context, stateRoot)); } catch { cached = null; } }
607
+ run('git', ['fetch', 'origin', 'main'], repo);
608
+ const main = run('git', ['rev-parse', '--verify', 'origin/main^{commit}'], repo);
609
+ if (!SHA.test(main)) throw new Error('invalid origin/main commit');
610
+ let local = '';
611
+ try { local = run('git', ['show-ref', '--verify', '--hash', `refs/heads/${branch}`], repo).trim(); }
612
+ catch { /* No local branch is the normal first-run case. */ }
613
+ const remote = remoteBranchHead(run, repo, branch);
614
+ owner = { runId, attempt };
615
+ if (sameOwner && local && existsSync(previous!.worktree)) {
616
+ tree = previous!.worktree;
617
+ if (run('git', ['rev-parse', '--abbrev-ref', 'HEAD'], tree) !== branch) throw new Error('docs owner worktree changed branch');
618
+ if (previous!.outcome === 'pushed' && previous!.head === local && remote === local && previous!.result?.outcome === 'ok')
619
+ return { ...previous!.result, artifactOwner: previous!.owner };
620
+ if (remote && run('git', ['merge-base', remote, local], repo) !== remote)
621
+ throw new Error(`same-run docs remote diverged: ${branch}`);
622
+ } else {
623
+ const suffix = `${runId}-${attempt}-${randomUUID()}`;
624
+ if (local) {
625
+ const localBackup = `release-docs-backup/${version}/${suffix}`;
626
+ run('git', ['branch', '-m', branch, localBackup], repo);
627
+ owner.localBackup = localBackup;
628
+ }
629
+ if (remote) {
630
+ const remoteBackup = `release-docs-backup/${version}/${suffix}`;
631
+ run('git', ['fetch', 'origin', `refs/heads/${branch}`], repo);
632
+ if (run('git', ['rev-parse', '--verify', 'FETCH_HEAD^{commit}'], repo) !== remote)
633
+ throw new Error(`remote docs branch changed while backing up: ${branch}`);
634
+ const changed = run('git', ['diff', '--name-only', `${main}...${remote}`], repo).split('\n').filter(Boolean);
635
+ if (changed.some((path) => !path.startsWith('release/public/docs/') && path !== 'website/pages.json'))
636
+ throw new Error(`foreign docs branch changes outside public docs: ${changed.join(', ')}`);
637
+ run('git', ['push', 'origin', `${remote}:refs/heads/${remoteBackup}`], repo);
638
+ if (remoteBranchHead(run, repo, remoteBackup) !== remote) throw new Error('remote docs backup not verified');
639
+ owner.remoteBackup = remoteBackup;
640
+ owner.remoteHead = remote;
641
+ }
642
+ const useCache = !remote && cached?.main === main && SHA.test(main);
643
+ if (useCache) {
644
+ tree = cached!.tree;
645
+ run('git', ['-C', tree, 'switch', '-c', branch], repo);
646
+ rmSync(cacheFile(cacheDir!, cached!), { force: true });
647
+ } else {
648
+ const root = mkdtempSync(join(tmpdir(), 'release-docs-'));
649
+ tree = join(root, 'tree');
650
+ run('git', ['worktree', 'add', '-b', branch, tree, main], repo);
651
+ }
652
+ // A foreign ref is incorporated by a normal merge, keeping the original branch fast-forwardable.
653
+ // Restore the docs inputs from main before generating this run's notes: old output is history, not input.
654
+ if (remote) {
655
+ run('git', ['merge', '--no-ff', '--no-edit', remote], tree);
656
+ run('git', ['restore', '--source', main, '--staged', '--worktree', '--', 'release/public/docs', 'website/pages.json'], tree);
657
+ }
658
+ const receipt: DocsReceipt = { owner, branch, worktree: tree, outcome: 'staged' };
659
+ mkdirSync(dirname(receiptPath), { recursive: true });
660
+ publish(receiptPath, receipt);
661
+ if (!useCache) run('bun', ['install', '--frozen-lockfile'], tree);
662
+ }
663
+ const result = cached?.tree === tree && cached.main === main ? cached.docs
664
+ : runDocs(['--version', version, '--base', tree, '--json'], repo, env, { stateRoot });
665
+ if (result.outcome !== 'ok') throw new Error(result.error ?? 'docs generation failed');
666
+ run('git', ['add', 'release/public/docs', 'website/pages.json'], tree);
667
+ const changes = run('git', ['diff', '--cached', '--name-only'], tree).trim();
668
+ if (changes) run('git', ['commit', '-m', `docs: release ${version}`], tree);
669
+ // No force: a concurrent remote update fails and leaves both branch and backup intact.
670
+ run('git', ['push', '-u', 'origin', branch], tree);
671
+ const head = run('git', ['rev-parse', '--verify', 'HEAD'], tree);
672
+ const output: DocsResult = { ...result, branch, worktree: tree, artifactOwner: owner };
673
+ publish(receiptPath, { owner, branch, worktree: tree, outcome: 'pushed', head, result: output } satisfies DocsReceipt);
674
+ return output;
675
+ } catch (error) {
676
+ return { outcome: 'error', version, error: error instanceof Error ? error.message : String(error),
677
+ ...(tree ? { worktree: tree } : {}), ...(owner ? { artifactOwner: owner } : {}) };
678
+ }
679
+ }
680
+
544
681
  /** Detached prefetch worker; an asynchronous spawn failure is logged as a cache miss and never escapes the node. */
545
682
  export function startPrefetchWorker(version: string, commit: string,
546
683
  spawnWorker: () => ReturnType<typeof spawn> = () => spawn(process.execPath, [resolve(import.meta.filename), '--prefetch-worker'], {
@@ -597,6 +734,9 @@ if (import.meta.main) {
597
734
  result = { ...joinTui(context, process.env, process.cwd()), version: context.input.version } as typeof result;
598
735
  } else if (node === 'docs') {
599
736
  result = graphDocs(readGraphContext(), process.env, process.cwd(), commandRunner);
737
+ } else if (node === 'notes-repair') {
738
+ const { runNotesRepair } = await import('./notes-repair.js');
739
+ result = await runNotesRepair(readGraphContext()) as typeof result;
600
740
  } else if (node === null) result = runDocs(process.argv.slice(2));
601
741
  else throw new Error(`unknown release docs node: ${node}`);
602
742
  } catch (error) {
@@ -5,6 +5,7 @@
5
5
  //
6
6
  // Read from the tip commit's git objects, never from the working tree (the resume can run from any checkout).
7
7
  import { spawnSync } from 'node:child_process';
8
+ import { createHash } from 'node:crypto';
8
9
  import { dirname, join, normalize } from 'node:path/posix';
9
10
  import ts from 'typescript';
10
11
  import { sourceCandidates } from '../../src/self-implement/importer-test-index.js';
@@ -230,6 +231,53 @@ export function testsReachingChanged(tree: ClosureTree, changed: readonly string
230
231
  opaqueFiles: [...opaque].filter(([file]) => !preloadClosure.has(file)).map(([file, why]) => `${file}: ${why}`).sort() };
231
232
  }
232
233
 
234
+ // TRAIN-REACH-GROUPING — two PRs whose reach sets share a test ride the same release train (their gates
235
+ // cannot be reused independently); disjoint reach sets stay separate trains. Pure and deterministic: the
236
+ // ledger is derived from content alone — no file, clock, or network effects.
237
+
238
+ /** One PR's reach set for train grouping — the `tests` of a `testsReachingChanged` verdict (`ok: true`). */
239
+ export interface TrainReach {
240
+ /** The PR that owns this reach set (number or url). */
241
+ readonly pr: string;
242
+ /** 도달 시험 집합 — tests reaching the PR's changed files. */
243
+ readonly tests: readonly string[];
244
+ }
245
+
246
+ /** 묶음 원장 — train grouping ledger returned by `defineTrainGrouping`. */
247
+ export interface TrainGrouping {
248
+ /** Train id per PR — both PRs share one id when their reach sets intersect. */
249
+ readonly trainIds: ReadonlyMap<string, string>;
250
+ /** The tests both reach sets share (sorted, deduped) — empty when they stay separate trains. */
251
+ readonly intersection: readonly string[];
252
+ /** True when the reach sets intersect and the two PRs ride the same train. */
253
+ readonly sameTrain: boolean;
254
+ }
255
+
256
+ /** Train id derived from content — same parts give the same id; a sha256 slice keeps the ledger readable. */
257
+ const trainIdOf = (parts: readonly string[]): string =>
258
+ `train-${createHash('sha256').update(parts.join('\u0000')).digest('hex').slice(0, 12)}`;
259
+
260
+ /** Bundle two PRs' reach sets into trains: intersecting reach sets get one shared train id, disjoint reach
261
+ * sets keep separate per-PR ids. Deterministic and side-effect free — same inputs, same ledger. */
262
+ export function defineTrainGrouping(left: TrainReach, right: TrainReach): TrainGrouping {
263
+ const reachOf = (reach: TrainReach): string[] => [...new Set(reach.tests)].sort();
264
+ const leftTests = reachOf(left);
265
+ const rightTests = reachOf(right);
266
+ const rightSet = new Set(rightTests);
267
+ const shared = leftTests.filter((test) => rightSet.has(test));
268
+ const trainIds = new Map<string, string>();
269
+ if (shared.length > 0) {
270
+ const sharedId = trainIdOf(shared);
271
+ trainIds.set(left.pr, sharedId);
272
+ trainIds.set(right.pr, sharedId);
273
+ } else {
274
+ // Disjoint reach sets: mix the PR key into each id so even two empty reach sets stay separate trains.
275
+ trainIds.set(left.pr, trainIdOf([left.pr, ...leftTests]));
276
+ trainIds.set(right.pr, trainIdOf([right.pr, ...rightTests]));
277
+ }
278
+ return { trainIds, intersection: shared, sameTrain: shared.length > 0 };
279
+ }
280
+
233
281
  /** `[test].preload` of a bunfig.toml text (repo-relative). Null when the file has a preload we cannot parse. */
234
282
  export function bunfigPreload(text: string | undefined): string[] | null {
235
283
  if (text === undefined) return [];
@@ -12,7 +12,8 @@ export function parseFailures(output: string): string[] {
12
12
  const line = raw.trim();
13
13
  const header = /^(?:\.\/)?((?:[\w.-]+\/)+[\w.-]+\.test\.tsx?):(?:\s|$)/.exec(line);
14
14
  if (header) { file = header[1]; continue; }
15
- const failed = /^\(fail\)[ \t]+(.+?)(?:[ \t]+\[[\d.]+(?:ms|s)\])?[ \t]*$/.exec(raw);
15
+ // Line-start only: a title/body `(fail)` is not a reporter row. Trailing CR is still a real Bun fail row.
16
+ const failed = /^\(fail\)[ \t]+(.+?)(?:[ \t]+\[[\d.]+(?:ms|s)\])?[ \t]*\r?$/.exec(raw);
16
17
  if (failed && file) failures.add(`${file} > ${failed[1]!.trim()}`);
17
18
  }
18
19
  return [...failures].sort();