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
@@ -374,6 +374,21 @@ export function decideNextRun(input: {
374
374
  const deployFindings = input.deployFindings === undefined ? undefined
375
375
  : new Map([...input.deployFindings].filter(([taskId]) => !handedOffIds.has(taskId)));
376
376
  const t = triageRun(activeResults, deployFindings, observation === 'failed', undefined, mainSyncRelaunchSpent(history));
377
+ const revisionUnobserved = activeResults.filter((result) => result.harvestable === true && !!result.branch
378
+ && result.goalPlanRevision?.status !== 'read');
379
+ const revisionUnobservedIds = new Set(revisionUnobserved.map((result) => result.taskId));
380
+ for (const classification of t.classifications) {
381
+ if (classification.kind !== 'main-sync-blocked' || classification.action !== 'relaunch-on-main'
382
+ || !revisionUnobservedIds.has(classification.taskId)) continue;
383
+ // Keep history's «already spent» predicate separate from this independent safety block.
384
+ classification.action = 'needs-human';
385
+ t.relaunchOnMain = t.relaunchOnMain.filter((taskId) => taskId !== classification.taskId);
386
+ if (!t.needsHuman.includes(classification.taskId)) t.needsHuman.push(classification.taskId);
387
+ }
388
+ t.actionable = countActionable(t) > 0;
389
+ const revisionHoldNote = revisionUnobserved.length > 0
390
+ ? ` · 골 개정 관측 미확인 — 같은 골 재발사 보류(${revisionUnobserved.map((result) => result.taskId).join(', ')})`
391
+ : '';
377
392
  const relaunchGoals: Record<string, string> = Object.fromEntries(activeResults.flatMap((result) =>
378
393
  t.relaunchOnMain.includes(result.taskId) && result.branch
379
394
  ? [[result.taskId, mainSyncRelaunchGoal(result.feature, result.branch)]] : []));
@@ -438,7 +453,7 @@ export function decideNextRun(input: {
438
453
  ...base,
439
454
  action: 'stop',
440
455
  stopReason: 'harvestable-awaiting-human',
441
- why: withGoalPlanRevisionObservation(`구현 완료 · 수확 대기 — ${harvestable.map((result) => result.branch).join(' · ')}`),
456
+ why: `${withGoalPlanRevisionObservation(`구현 완료 · 수확 대기 — ${harvestable.map((result) => result.branch).join(' · ')}`)}${revisionHoldNote}`,
442
457
  };
443
458
  }
444
459
 
@@ -604,7 +619,7 @@ export function decideNextRun(input: {
604
619
  ...base,
605
620
  action: 'stop',
606
621
  stopReason: 'no-progress',
607
- why: withNoProgressGoalPlanRevisionObservation(`${stallRounds}라운드 연속 제자리 — base=${completionBase ?? 'main'} 기준 완료 ${baseCompleted} · 착지 ${landed} · 남은 조각도 안 줄었다(${actionable}). 골·불변식을 의심할 자리`),
622
+ why: `${withNoProgressGoalPlanRevisionObservation(`${stallRounds}라운드 연속 제자리 — base=${completionBase ?? 'main'} 기준 완료 ${baseCompleted} · 착지 ${landed} · 남은 조각도 안 줄었다(${actionable}). 골·불변식을 의심할 자리`)}${revisionHoldNote}`,
608
623
  };
609
624
  }
610
625
  }
@@ -733,10 +748,10 @@ export function decideNextRun(input: {
733
748
  ...(action === 'add-repair-task' && held.length ? { heldTaskIds: held } : {}) },
734
749
  pendingDecision: 'attempt-care-escalation',
735
750
  why: fresh.length === 0
736
- ? `리뷰 진동 반복 — ${signatureOf(oscillating)} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}`
751
+ ? `리뷰 진동 반복 — ${signatureOf(oscillating)} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}${revisionHoldNote}`
737
752
  : cannotRepair
738
- ? `리뷰 진동 — ${signatureOf(oscillating)} · ${input.repairGoalExecution === false ? '이 감독 경로가 수리 골 실행을 선언하지 않았다(미선언 또는 불가)' : '수리 원문/PR 관측 불가'} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}`
739
- : `리뷰 진동 — ${signatureOf(fresh)} · review-oscillation 수리 조각을 한 번 붙인다${input.repairGoalExecution === true ? '' : '(실행 배선 미선언 — 결정 칸만)'}${repairedHeld.length ? ` · 이미 수리한 조각 ${repairedHeld.join(', ')} 은 사람 결정 대기` : ''}${classHeld.length ? ` · 분류로 보류한 조각 ${classHeld.join(', ')}` : ''}${heldReasonSuffix}`,
753
+ ? `리뷰 진동 — ${signatureOf(oscillating)} · ${input.repairGoalExecution === false ? '이 감독 경로가 수리 골 실행을 선언하지 않았다(미선언 또는 불가)' : '수리 원문/PR 관측 불가'} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}${revisionHoldNote}`
754
+ : `리뷰 진동 — ${signatureOf(fresh)} · review-oscillation 수리 조각을 한 번 붙인다${input.repairGoalExecution === true ? '' : '(실행 배선 미선언 — 결정 칸만)'}${repairedHeld.length ? ` · 이미 수리한 조각 ${repairedHeld.join(', ')} 은 사람 결정 대기` : ''}${classHeld.length ? ` · 분류로 보류한 조각 ${classHeld.join(', ')}` : ''}${heldReasonSuffix}${revisionHoldNote}`,
740
755
  };
741
756
  }
742
757
 
@@ -746,14 +761,14 @@ export function decideNextRun(input: {
746
761
  return {
747
762
  ...base,
748
763
  action: 'add-repair-task',
749
- why: `수리 조각을 붙인다 — 수리 ${t.repairable.length} · 그대로 재실행 ${t.rerunnable.length} · 재작업 ${t.reworkable.length} · 분해 ${t.decomposable.length} · 라운드 ${round + 1}/${maxRounds}`,
764
+ why: `수리 조각을 붙인다 — 수리 ${t.repairable.length} · 그대로 재실행 ${t.rerunnable.length} · 재작업 ${t.reworkable.length} · 분해 ${t.decomposable.length} · 라운드 ${round + 1}/${maxRounds}${revisionHoldNote}`,
750
765
  };
751
766
  }
752
767
 
753
768
  return {
754
769
  ...base,
755
770
  action: 'relaunch',
756
- why: `다시 건다 — 그대로 재실행 ${t.rerunnable.length} · 재작업 ${t.reworkable.length} · 분해 ${t.decomposable.length} · 수리 ${t.repairable.length}${t.relaunchOnMain.length > 0 ? ` · main 위 재발사 ${t.relaunchOnMain.length}` : ''} · 라운드 ${round + 1}/${maxRounds}`,
771
+ why: `다시 건다 — 그대로 재실행 ${t.rerunnable.length} · 재작업 ${t.reworkable.length} · 분해 ${t.decomposable.length} · 수리 ${t.repairable.length}${t.relaunchOnMain.length > 0 ? ` · main 위 재발사 ${t.relaunchOnMain.length}` : ''} · 라운드 ${round + 1}/${maxRounds}${revisionHoldNote}`,
757
772
  };
758
773
  }
759
774
 
@@ -105,3 +105,51 @@ export function planFixedGateTestShards(files: readonly string[], shardCount: nu
105
105
  }
106
106
  return groups.map((group, index) => ({ id: `shard-${index + 1}`, files: group, plannedRssMb: 0, plannedSeconds: 0 }));
107
107
  }
108
+
109
+ /** GATE-REMOTE-SHARD-PLAN — one remote shard carrying its orchestration identity; introducedFiles are this shard's own
110
+ * files, so introduced attribution stays file-level (a shard never inherits another shard's introduced files). */
111
+ export interface GateRemoteShard {
112
+ orchestrationId: string;
113
+ shardId: string;
114
+ totalShards: number;
115
+ position: number;
116
+ files: string[];
117
+ introducedFiles: string[];
118
+ }
119
+
120
+ /** Deterministic orchestration id for a changed-file list: same files in any order produce the same id, so re-plans stay joinable. */
121
+ export function shardPlanOrchestrationId(files: readonly string[]): string {
122
+ const sorted = [...new Set(files)].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
123
+ let hash = 0x811c9dc5;
124
+ for (const file of sorted) {
125
+ for (let index = 0; index < file.length; index += 1) {
126
+ hash ^= file.charCodeAt(index);
127
+ hash = Math.imul(hash, 0x01000193) >>> 0;
128
+ }
129
+ }
130
+ return `gate-${sorted.length}-${hash.toString(16).padStart(8, '0')}`;
131
+ }
132
+
133
+ /** Split a changed-file list (e.g. 183 files) into identity-carrying shards; every file is introduced by its own shard.
134
+ * Contiguous slices keep each shard's files in input order, so concatenating shards reproduces the input list. */
135
+ export function planGateRemoteShards(files: readonly string[], shardCount: number, orchestrationId: string): GateRemoteShard[] {
136
+ if (!Number.isSafeInteger(shardCount) || shardCount < 1) throw new Error('invalid shard count');
137
+ const sorted = [...new Set(files)].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
138
+ if (!sorted.length) throw new Error('no files to shard');
139
+ if (shardCount > sorted.length) throw new Error(`shard count ${shardCount} exceeds file count ${sorted.length}`);
140
+ const base = Math.floor(sorted.length / shardCount);
141
+ const extra = sorted.length % shardCount;
142
+ return Array.from({ length: shardCount }, (_, index) => {
143
+ const start = index * base + Math.min(index, extra);
144
+ const size = base + (index < extra ? 1 : 0);
145
+ const shardFiles = sorted.slice(start, start + size);
146
+ return {
147
+ orchestrationId,
148
+ shardId: `${orchestrationId}/shard-${index + 1}`,
149
+ totalShards: shardCount,
150
+ position: index + 1,
151
+ files: shardFiles,
152
+ introducedFiles: [...shardFiles],
153
+ };
154
+ });
155
+ }
@@ -1,10 +1,10 @@
1
1
  import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statfsSync, statSync, writeFileSync } from 'node:fs';
2
- import { availableParallelism, freemem, tmpdir } from 'node:os';
2
+ import { availableParallelism, freemem, loadavg, tmpdir, totalmem } from 'node:os';
3
3
  import { join } from 'node:path';
4
4
  import { debug, redactSecretText } from '../debug/log.js';
5
5
  import { prepareDeterministicChildEnvironment } from '../../scripts/lib/deterministic-env.js';
6
6
  import { withGateTestEnv } from '../../scripts/lib/gate-test-env.js';
7
- import { withBaselineWorktree } from '../self-implement/gate-baseline.js';
7
+ import { withBaselineWorktree, withBaselineWorktreeAsync } from '../self-implement/gate-baseline.js';
8
8
  import { aggregateGateTestShards, type GateShardAttempt, type GateShardAggregate } from './shard-aggregate.js';
9
9
  import { GateShardCapacityError, planFixedGateTestShards, planSelfGateSpawnSeparatedShards, type GateTestShard } from './shard-plan.js';
10
10
  import { isGateSpawnLaneFile } from './spawn-lane-files.js';
@@ -27,6 +27,15 @@ export interface ShardRunResult {
27
27
  unmeasuredByShard?: Record<string, string>;
28
28
  /** git stderr tail (redacted · ≤2KB · one line) when the baseline worktree could not be added. */
29
29
  baselineStderrTail?: string;
30
+ /** Effective live pool width and its host-load/memory decision, for gate artifacts and diagnosis. */
31
+ concurrency?: number;
32
+ concurrencyReason?: string;
33
+ /** Wall time spent in singleton RSS samples and current+baseline bundles, respectively. */
34
+ measurementMs?: number;
35
+ bundleMs?: number;
36
+ /** Sum of process wall times across bundles (overlaps under concurrency). */
37
+ currentProcessMs?: number;
38
+ baselineProcessMs?: number;
30
39
  }
31
40
 
32
41
  /** What a failed shard process leaves behind so «test failure vs runner error» can be told apart after the fact. */
@@ -50,7 +59,19 @@ export interface ShardRunMode {
50
59
  /** OP FU — sorted round-robin into `count` shards, zero pre-measurement runs. Default off: the measured planner. */
51
60
  fixedDistribution?: boolean;
52
61
  /** Measured on the executing host; override only for deterministic planning tests. */
53
- hostResources?: { cores: number; freeMemoryGiB: number; freeTmpGiB: number };
62
+ hostResources?: { cores: number; freeMemoryGiB: number; freeTmpGiB: number; load1?: number };
63
+ /** Observation after each bundle's first current+baseline attempt; never controls retries or verdict. */
64
+ onShardComplete?: (progress: ShardRunProgress) => void;
65
+ /** Maximum concurrently active shard bundles. The default is three, bounded to one through four. */
66
+ concurrency?: number;
67
+ }
68
+
69
+ export interface ShardRunProgress {
70
+ shardId: string;
71
+ completedShards: number;
72
+ totalShards: number;
73
+ completedFiles: number;
74
+ totalFiles: number;
54
75
  }
55
76
 
56
77
  function hostResources(): ShardRunMode['hostResources'] | undefined {
@@ -63,14 +84,37 @@ function hostResources(): ShardRunMode['hostResources'] | undefined {
63
84
  const availableKiB = /^MemAvailable:\s+(\d+)\s+kB/m.exec(readFileSync('/proc/meminfo', 'utf8'))?.[1];
64
85
  if (availableKiB) freeMemoryGiB = Number(availableKiB) / (1024 ** 2);
65
86
  }
87
+ if (process.platform === 'darwin') {
88
+ // macOS freemem excludes reclaimable cache; node-b reported 5 GiB free of 512 GiB while
89
+ // memory_pressure reported 91% available. A freemem cap would silently serialize the gate.
90
+ const pressure = Bun.spawnSync(['memory_pressure', '-Q'], { stdout: 'pipe', stderr: 'ignore', timeout: 2_000 });
91
+ const percent = /System-wide memory free percentage:\s*(\d+(?:\.\d+)?)%/.exec(Buffer.from(pressure.stdout).toString('utf8'))?.[1];
92
+ if (pressure.exitCode === 0 && percent !== undefined && Number(percent) >= 0 && Number(percent) <= 100) {
93
+ freeMemoryGiB = totalmem() / (1024 ** 3) * Number(percent) / 100;
94
+ }
95
+ }
66
96
  return {
67
97
  cores: availableParallelism(),
68
98
  freeMemoryGiB,
69
99
  freeTmpGiB: Number(tmp.bavail) * Number(tmp.bsize) / (1024 ** 3),
100
+ load1: loadavg()[0],
70
101
  };
71
102
  } catch { return undefined; }
72
103
  }
73
104
 
105
+ /** A conservative snapshot taken before sampling. Explicit 1 preserves the old serial child order. */
106
+ export function resolveShardConcurrency(configured: number | undefined, resources: ShardRunMode['hostResources'], budgetGiB: number): { count: number; reason: string } {
107
+ if (!resources || !Number.isFinite(resources.cores) || resources.cores < 1) return { count: Math.max(1, Math.min(4, configured ?? 3)), reason: configured === undefined ? 'default; host load unavailable' : 'configured; host load unavailable' };
108
+ const loadRatio = Number.isFinite(resources.load1) ? resources.load1! / resources.cores : null;
109
+ const target = configured ?? (loadRatio !== null && loadRatio >= 0.8 ? 2
110
+ : loadRatio !== null && loadRatio <= 0.35 && resources.cores >= 8 ? 4 : 3);
111
+ const cpuCap = Math.max(1, Math.floor(resources.cores));
112
+ const memoryCap = Number.isFinite(resources.freeMemoryGiB) && Number.isFinite(budgetGiB) && budgetGiB > 0
113
+ ? Math.max(1, Math.floor(resources.freeMemoryGiB / budgetGiB)) : 4;
114
+ const count = Math.max(1, Math.min(4, target, cpuCap, memoryCap));
115
+ return { count, reason: `${configured === undefined ? 'adaptive' : `configured ${configured}`} · host load/cores ${loadRatio === null ? '?' : loadRatio.toFixed(2)} · free ${resources.freeMemoryGiB.toFixed(1)} GiB · shard budget ${budgetGiB} GiB` };
116
+ }
117
+
74
118
  /** One expansion slot needs one CPU, one shard memory budget, and 1 GiB of free tmp space.
75
119
  * Explicitly requested shards remain the caller's choice; this only limits automatic growth. */
76
120
  export function maxAutomaticShardCount(requested: number, budgetGiB: number, resources: ShardRunMode['hostResources']): number {
@@ -94,6 +138,7 @@ export type ShardProcess = (cwd: string, files: readonly string[]) => {
94
138
  /** Present only when the process failed (exit≠0 · signal · no JUnit) — observation only, never part of the verdict. */
95
139
  failure?: ShardFailureOutput;
96
140
  };
141
+ export type AsyncShardProcess = (cwd: string, files: readonly string[]) => Promise<ReturnType<ShardProcess>>;
97
142
 
98
143
  export const SHARD_FAILURE_TAIL_BYTES = 64 * 1024;
99
144
 
@@ -103,6 +148,29 @@ function outputTail(bytes: Uint8Array | undefined): string {
103
148
  return redactSecretText(Buffer.from(tail).toString('utf8'));
104
149
  }
105
150
 
151
+ /** Drain a child pipe without retaining its entire output. Diagnostics need the opening context and failure tail. */
152
+ async function boundedChildOutput(stream: ReadableStream<Uint8Array>, abort: AbortSignal): Promise<Uint8Array> {
153
+ const reader = stream.getReader();
154
+ const cancel = () => { void reader.cancel('child output drain timed out').catch(() => {}); };
155
+ abort.addEventListener('abort', cancel, { once: true });
156
+ const headLimit = 1024;
157
+ let head = new Uint8Array(0);
158
+ let tail = new Uint8Array(0);
159
+ let total = 0;
160
+ try {
161
+ for (;;) {
162
+ const { done, value } = await reader.read();
163
+ if (done) break;
164
+ total += value.byteLength;
165
+ if (head.byteLength < headLimit) head = Buffer.concat([head, value.subarray(0, headLimit - head.byteLength)]);
166
+ tail = value.byteLength >= SHARD_FAILURE_TAIL_BYTES
167
+ ? value.slice(-SHARD_FAILURE_TAIL_BYTES)
168
+ : Buffer.concat([tail, value]).subarray(-SHARD_FAILURE_TAIL_BYTES);
169
+ }
170
+ } finally { abort.removeEventListener('abort', cancel); reader.releaseLock(); }
171
+ return total <= SHARD_FAILURE_TAIL_BYTES ? tail : Buffer.concat([head, tail]);
172
+ }
173
+
106
174
  /** `<shardId>.failure.json` per failed shard (shard ids are already `shard-<n>`). Top level = the latest current-side
107
175
  * failure (else the latest baseline one); `failures` keeps every failed side/attempt. Returns the written paths. */
108
176
  export function writeShardFailureEvidence(dir: string, evidence: readonly ShardFailureEvidence[]): string[] {
@@ -162,7 +230,7 @@ export function runShardedGateTests(
162
230
  try { fixed = planFixedGateTestShards(files, count); }
163
231
  catch (error) { return { aggregate: { status: 'unmeasured', retryShardIds: [] }, shards: [], attempts: [], reason: String(error), distribution: 'fixed' }; }
164
232
  debug.log('self-dev.shard', 'fixed-distribution', { shards: fixed.length, files: fixed.reduce((sum, shard) => sum + shard.files.length, 0) });
165
- return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree), distribution: 'fixed' };
233
+ return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree, mode.onShardComplete), distribution: 'fixed' };
166
234
  }
167
235
  const rss = new Map<string, number>();
168
236
  const seconds = new Map<string, number>();
@@ -199,7 +267,7 @@ export function runShardedGateTests(
199
267
  const fixed = planFixedGateTestShards(files, maxCount);
200
268
  debug.log('self-dev.shard', 'host-cap-fixed-fallback', { requested: count, cap: maxCount,
201
269
  files: new Set(files).size, reason, measurementFailures: measurementFailures ?? 0 });
202
- return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree), distribution: 'fixed-cap-fallback',
270
+ return { ...runPlannedShards(cwd, fixed, baseRef, run, baselineWorktree, mode.onShardComplete), distribution: 'fixed-cap-fallback',
203
271
  fallbackReason: reason, ...(measurementFailures ? { measurementFailures } : {}) };
204
272
  } catch (error) {
205
273
  return { aggregate: { status: 'unmeasured', retryShardIds: [] }, shards: [], attempts: [],
@@ -232,7 +300,7 @@ export function runShardedGateTests(
232
300
  requested: count, planned: shards.length, files: new Set(files).size, budgetGiB,
233
301
  measurementFailures: measurementFailures ?? 0,
234
302
  });
235
- return { ...runPlannedShards(cwd, shards, baseRef, run, baselineWorktree), ...(plannedCount > count ? { expandedFrom: count } : {}), ...(measurementFailures ? { measurementFailures } : {}) };
303
+ return { ...runPlannedShards(cwd, shards, baseRef, run, baselineWorktree, mode.onShardComplete), ...(plannedCount > count ? { expandedFrom: count } : {}), ...(measurementFailures ? { measurementFailures } : {}) };
236
304
  }
237
305
 
238
306
  /** Shared by the measured and the fixed planner: current + baseline per shard, one retry round, one aggregate. */
@@ -242,6 +310,7 @@ function runPlannedShards(
242
310
  baseRef: string,
243
311
  run: ShardProcess,
244
312
  baselineWorktree: typeof withBaselineWorktree,
313
+ onShardComplete?: ShardRunMode['onShardComplete'],
245
314
  ): ShardRunResult {
246
315
  const attempts: GateShardAttempt[] = [];
247
316
  const failureEvidence: ShardFailureEvidence[] = [];
@@ -256,6 +325,8 @@ function runPlannedShards(
256
325
  const treeReadable = (() => { try { return statSync(dir).isDirectory(); } catch { return false; } })();
257
326
  const atBase = (shard: GateTestShard) => treeReadable ? shard.files.filter((file) => !absentAtBaseline(join(dir, file))) : [...shard.files];
258
327
  let pending = shards;
328
+ let completedFiles = 0;
329
+ const totalFiles = new Set(shards.flatMap((shard) => shard.files)).size;
259
330
  for (let round = 1; round <= 2 && pending.length; round++) {
260
331
  for (const shard of pending) {
261
332
  const runSafely = (location: string, selected: readonly string[]): ReturnType<ShardProcess> => {
@@ -279,6 +350,13 @@ function runPlannedShards(
279
350
  baselineFiles,
280
351
  currentRoot: cwd, baselineRoot: dir,
281
352
  });
353
+ if (round === 1 && onShardComplete) {
354
+ completedFiles += shard.files.length;
355
+ try {
356
+ onShardComplete({ shardId: shard.id, completedShards: attempts.length,
357
+ totalShards: shards.length, completedFiles, totalFiles });
358
+ } catch { /* progress is observation only */ }
359
+ }
282
360
  }
283
361
  const retry = new Set(aggregateGateTestShards(shards, attempts).retryShardIds);
284
362
  pending = shards.filter((shard) => retry.has(shard.id));
@@ -301,6 +379,146 @@ function runPlannedShards(
301
379
  };
302
380
  }
303
381
 
382
+ /** Runs planned bundles concurrently while retaining plan order in attempts and aggregate evidence. */
383
+ export async function runShardedGateTestsAsync(
384
+ cwd: string,
385
+ files: readonly string[],
386
+ baseRef: string,
387
+ count = 2,
388
+ run: AsyncShardProcess = runBunShardAsync,
389
+ baselineWorktree: typeof withBaselineWorktreeAsync = withBaselineWorktreeAsync,
390
+ budgetGiB = 8,
391
+ mode: ShardRunMode = {},
392
+ measure: AsyncShardProcess = run,
393
+ ): Promise<ShardRunResult> {
394
+ if (mode.concurrency !== undefined && (!Number.isSafeInteger(mode.concurrency) || mode.concurrency < 1 || mode.concurrency > 4)) throw new Error('invalid shard concurrency (expected 1–4)');
395
+ const resources = mode.hostResources ?? hostResources();
396
+ const selectedConcurrency = resolveShardConcurrency(mode.concurrency, resources, budgetGiB);
397
+ const concurrency = selectedConcurrency.count;
398
+ debug.log('self-dev.shard', 'concurrency', { concurrency, reason: selectedConcurrency.reason });
399
+ const measurementStartedAt = performance.now();
400
+ const samples = new Map<string, ReturnType<ShardProcess>>();
401
+ if (!mode.fixedDistribution) {
402
+ const unique = [...new Set(files)];
403
+ let nextSample = 0;
404
+ const sampleWorker = async () => {
405
+ for (;;) {
406
+ const index = nextSample++;
407
+ if (index >= unique.length) return;
408
+ const file = unique[index]!;
409
+ try { samples.set(file, await measure(cwd, [file])); }
410
+ catch (error) {
411
+ debug.log('self-dev.shard', 'rss-measurement-failed', { file, error: redactSecretText(String(error)).slice(0, 500) });
412
+ samples.set(file, { exitCode: null });
413
+ }
414
+ }
415
+ };
416
+ await Promise.all(Array.from({ length: Math.min(concurrency, unique.length) }, () => sampleWorker()));
417
+ }
418
+ const measurementMs = Math.round(performance.now() - measurementStartedAt);
419
+ // Reuse the established measured/fixed planner and its host-cap fallback. The callback supplies a
420
+ // planning-only aggregate, so this phase never launches a shard or creates a baseline worktree.
421
+ const planningOnlyBaseline = (() => ({ status: 'passed' as const, retryShardIds: [] })) as unknown as typeof withBaselineWorktree;
422
+ const planned = runShardedGateTests(cwd, files, baseRef, count, (_cwd, selected) => samples.get(selected[0]!) ?? { exitCode: null },
423
+ planningOnlyBaseline, budgetGiB, { ...mode, ...(resources ? { hostResources: resources } : {}) });
424
+ if (planned.reason) return { ...planned, concurrency, concurrencyReason: selectedConcurrency.reason, measurementMs, bundleMs: 0 };
425
+ const shards = planned.shards;
426
+ const attempts: GateShardAttempt[] = [];
427
+ const failureEvidence: ShardFailureEvidence[] = [];
428
+ const bundlesStartedAt = performance.now();
429
+ let currentProcessMs = 0;
430
+ let baselineProcessMs = 0;
431
+ const baseline = await baselineWorktree(cwd, baseRef, async (dir) => {
432
+ const treeReadable = (() => { try { return statSync(dir).isDirectory(); } catch { return false; } })();
433
+ // Baseline membership is invariant for both rounds. Cache it before launching children.
434
+ const atBase = new Map(shards.map((shard) => [shard.id,
435
+ treeReadable ? shard.files.filter((file) => !absentAtBaseline(join(dir, file))) : [...shard.files]]));
436
+ const baselinePassCache = new Map<string, ReturnType<ShardProcess>>();
437
+ const totalFiles = new Set(shards.flatMap((shard) => shard.files)).size;
438
+ let completedShards = 0;
439
+ let completedFiles = 0;
440
+ let pending = shards;
441
+ for (let round = 1; round <= 2 && pending.length; round++) {
442
+ const roundAttempts = new Array<GateShardAttempt>(pending.length);
443
+ const roundEvidence = new Array<ShardFailureEvidence[]>(pending.length);
444
+ let next = 0;
445
+ const runSafely = async (location: string, selected: readonly string[]): Promise<ReturnType<ShardProcess>> => {
446
+ try { return await run(location, selected); }
447
+ catch (error) {
448
+ debug.log('self-dev.shard', 'bundle-runner-failed', { location, files: selected,
449
+ error: redactSecretText(String(error)).slice(0, 500) });
450
+ return { exitCode: null };
451
+ }
452
+ };
453
+ const worker = async () => {
454
+ for (;;) {
455
+ const index = next++;
456
+ if (index >= pending.length) return;
457
+ const shard = pending[index]!;
458
+ const baselineFiles = atBase.get(shard.id)!;
459
+ if (baselineFiles.length < shard.files.length) {
460
+ debug.log('self-dev.shard', 'baseline-files-absent', { shardId: shard.id, round,
461
+ absent: shard.files.filter((file) => !baselineFiles.includes(file)) });
462
+ }
463
+ const currentStartedAt = performance.now();
464
+ const current = await runSafely(cwd, shard.files);
465
+ currentProcessMs += performance.now() - currentStartedAt;
466
+ const cached = concurrency > 1 && round > 1 ? baselinePassCache.get(shard.id) : undefined;
467
+ if (cached) debug.log('self-dev.shard', 'baseline-cache-hit', { shardId: shard.id, round });
468
+ const baselineStartedAt = performance.now();
469
+ const base = cached ?? (baselineFiles.length ? await runSafely(dir, baselineFiles) : { exitCode: 0 });
470
+ baselineProcessMs += performance.now() - baselineStartedAt;
471
+ if (concurrency > 1 && baselineFiles.length && base.exitCode === 0 && !base.signal && base.junit) baselinePassCache.set(shard.id, base);
472
+ roundAttempts[index] = {
473
+ shardId: shard.id, attempt: round, currentJUnit: current.junit, baselineJUnit: base.junit,
474
+ currentExitCode: current.exitCode, baselineExitCode: base.exitCode,
475
+ currentSignal: current.signal, baselineSignal: base.signal,
476
+ currentDiagnostic: current.diagnostic, baselineDiagnostic: base.diagnostic,
477
+ baselineFiles, currentRoot: cwd, baselineRoot: dir,
478
+ };
479
+ roundEvidence[index] = [];
480
+ for (const [side, result, selected] of [
481
+ ['current', current, shard.files], ['baseline', base, baselineFiles],
482
+ ] as const) {
483
+ if (result.failure) roundEvidence[index]!.push({ shardId: shard.id, side, attempt: round,
484
+ files: [...selected], exitCode: result.exitCode, signal: result.signal ?? null, ...result.failure });
485
+ }
486
+ if (round === 1 && mode.onShardComplete) {
487
+ completedShards++;
488
+ completedFiles += shard.files.length;
489
+ try { mode.onShardComplete({ shardId: shard.id, completedShards, totalShards: shards.length,
490
+ completedFiles, totalFiles }); } catch { /* observation only */ }
491
+ }
492
+ }
493
+ };
494
+ await Promise.all(Array.from({ length: Math.min(concurrency, pending.length) }, () => worker()));
495
+ attempts.push(...roundAttempts);
496
+ for (const evidence of roundEvidence) failureEvidence.push(...evidence);
497
+ const retry = new Set(aggregateGateTestShards(shards, attempts).retryShardIds);
498
+ pending = shards.filter((shard) => retry.has(shard.id));
499
+ }
500
+ return aggregateGateTestShards(shards, attempts);
501
+ });
502
+ const evidence = failureEvidence.length ? { failureEvidence } : {};
503
+ const bundleMs = Math.round(performance.now() - bundlesStartedAt);
504
+ if ('retryShardIds' in baseline) return {
505
+ ...planned, aggregate: baseline, attempts, ...evidence, concurrency, concurrencyReason: selectedConcurrency.reason, measurementMs, bundleMs,
506
+ currentProcessMs: Math.round(currentProcessMs), baselineProcessMs: Math.round(baselineProcessMs),
507
+ ...(baseline.retryShardIds.length ? { unmeasuredByShard: incompleteShardReasons(baseline.retryShardIds, attempts) } : {}),
508
+ };
509
+ const retryShardIds = shards.map((shard) => shard.id);
510
+ const stderrTail = baseline.gitStderrTail;
511
+ const stderrPart = stderrTail ? ` · git stderr: ${stderrTail}` : '';
512
+ return {
513
+ ...planned, aggregate: { status: 'unmeasured', retryShardIds }, attempts, concurrency, concurrencyReason: selectedConcurrency.reason, measurementMs, bundleMs,
514
+ currentProcessMs: Math.round(currentProcessMs), baselineProcessMs: Math.round(baselineProcessMs),
515
+ reason: baseline.log, ...evidence,
516
+ unmeasuredByShard: Object.fromEntries(retryShardIds.map((id) => [id,
517
+ `baseline worktree: ${redactSecretText(baseline.log).replace(/[\r\n\t\x00-\x1f\x7f]+/g, ' ').slice(0, 500)}${stderrPart}`])),
518
+ ...(stderrTail ? { baselineStderrTail: stderrTail } : {}),
519
+ };
520
+ }
521
+
304
522
  function incompleteShardReasons(shardIds: readonly string[], attempts: readonly GateShardAttempt[]): Record<string, string> {
305
523
  return Object.fromEntries(shardIds.map((id) => {
306
524
  const latest = attempts.filter((attempt) => attempt.shardId === id).at(-1);
@@ -360,3 +578,89 @@ export function runBunShardWithSpawn(cwd: string, files: readonly string[], spaw
360
578
  rmSync(dir, { recursive: true, force: true });
361
579
  }
362
580
  }
581
+
582
+ /** Nonblocking child runner; each bundle still owns its own deterministic environment and JUnit path. */
583
+ export async function runBunShardAsync(cwd: string, files: readonly string[], drainTimeoutMs = 5_000): Promise<ReturnType<ShardProcess>> {
584
+ const timeout = selfGateShardTimeoutMs(files);
585
+ const spawnLane = timeout === 120_000;
586
+ const dir = mkdtempSync(join(tmpdir(), 'elanous-shard-junit-'));
587
+ const report = join(dir, 'result.xml');
588
+ const isolated = prepareDeterministicChildEnvironment('elanous-shard-test-env-', { env: withGateTestEnv(process.env) });
589
+ let timer: ReturnType<typeof setTimeout> | undefined;
590
+ let drainTimer: ReturnType<typeof setTimeout> | undefined;
591
+ const drainAbort = new AbortController();
592
+ try {
593
+ const args = ['test', ...(spawnLane ? ['--timeout=120000'] : []), '--reporter=junit', `--reporter-outfile=${report}`, ...files];
594
+ const started = performance.now();
595
+ const child = Bun.spawn(['bun', ...args], { cwd, env: isolated.env, stdout: 'pipe', stderr: 'pipe' });
596
+ let timedOut = false;
597
+ let drainTimedOut = false;
598
+ timer = setTimeout(() => { timedOut = true; child.kill('SIGKILL'); }, timeout);
599
+ const stdoutOutput = boundedChildOutput(child.stdout, drainAbort.signal);
600
+ const stderrOutput = boundedChildOutput(child.stderr, drainAbort.signal);
601
+ const exited = child.exited.then((code) => {
602
+ // Pipe draining can continue after process exit; a late timer must not relabel a clean exit as SIGKILL.
603
+ if (timer) clearTimeout(timer);
604
+ timer = undefined;
605
+ drainTimer = setTimeout(() => {
606
+ drainTimedOut = true;
607
+ debug.log('self-dev.shard', 'output-drain-timeout', { cwd, files, drainTimeoutMs });
608
+ drainAbort.abort();
609
+ }, drainTimeoutMs);
610
+ return code;
611
+ });
612
+ const [exitCode, stdoutBuffer, stderrBuffer] = await Promise.all([
613
+ exited,
614
+ stdoutOutput,
615
+ stderrOutput,
616
+ ]);
617
+ if (drainTimer) clearTimeout(drainTimer);
618
+ drainTimer = undefined;
619
+ const stdout = stdoutBuffer;
620
+ const stderr = stderrBuffer;
621
+ const durationMs = performance.now() - started;
622
+ const usage = child.resourceUsage();
623
+ const junit = existsSync(report) ? readFileSync(report, 'utf8') : undefined;
624
+ const signal = drainTimedOut ? 'DRAIN_TIMEOUT' : timedOut ? 'SIGKILL' : child.signalCode ? String(child.signalCode) : undefined;
625
+ const failed = exitCode !== 0 || !!signal || junit === undefined;
626
+ return {
627
+ exitCode, signal, junit,
628
+ ...(files.length === 1 ? { rssMb: usage ? usage.maxRSS / (1024 * 1024) : undefined, seconds: durationMs / 1000 } : {}),
629
+ ...(junit === undefined && (exitCode !== 0 || signal) ? { diagnostic: boundedDiagnostic(stdout, stderr) } : {}),
630
+ ...(failed ? { failure: { durationMs: Math.round(durationMs), stdoutTail: outputTail(stdout), stderrTail: outputTail(stderr) } } : {}),
631
+ };
632
+ } finally {
633
+ if (timer) clearTimeout(timer);
634
+ if (drainTimer) clearTimeout(drainTimer);
635
+ drainAbort.abort();
636
+ isolated.cleanup();
637
+ rmSync(dir, { recursive: true, force: true });
638
+ }
639
+ }
640
+
641
+ /** GATE-REMOTE-SHARD-PLAN — identity of one remote shard. files/introducedFiles are optional: a caller that only relays
642
+ * identity (CLI wiring) passes none, while a planner-produced shard carries its file-level attribution. */
643
+ export interface RemoteShardSpec {
644
+ orchestrationId: string;
645
+ shardId: string;
646
+ totalShards: number;
647
+ position: number;
648
+ files?: readonly string[];
649
+ introducedFiles?: readonly string[];
650
+ }
651
+
652
+ /** The identity slice that rides a remote gate command line — validated so a dropped flag fails loudly, not silently. */
653
+ export function remoteShardArgArgs(shard: RemoteShardSpec, options?: { planFile?: string }): string[] {
654
+ if (!shard.orchestrationId.trim()) throw new Error('orchestration id must be non-empty');
655
+ if (!shard.shardId.trim()) throw new Error('shard id must be non-empty');
656
+ if (!Number.isSafeInteger(shard.totalShards) || shard.totalShards < 1) throw new Error('shard total must be a positive integer');
657
+ if (!Number.isSafeInteger(shard.position) || shard.position < 1) throw new Error('shard position must be a positive integer');
658
+ const args = ['--orchestration-id', shard.orchestrationId, '--shard-id', shard.shardId, '--shard-position', String(shard.position)];
659
+ if (options?.planFile !== undefined && options.planFile !== '') args.push('--shard-plan', options.planFile);
660
+ return args;
661
+ }
662
+
663
+ /** Full remote command for one shard — the exact argv a remote host (e.g. an node-b pod shard) would run. */
664
+ export function remoteShardArgv(shard: RemoteShardSpec, options?: { planFile?: string }): string[] {
665
+ return ['bun', 'bin/elanous.mjs', '--test', 'self', 'gate', '--changed', '--shards', String(shard.totalShards), ...remoteShardArgArgs(shard, options)];
666
+ }
@@ -0,0 +1,54 @@
1
+ import ts from 'typescript';
2
+
3
+ /** Exclude importer expansion only when non-comment bytes and comment boundaries
4
+ * are identical. The TypeScript parser finds comments within JSDoc that a bare
5
+ * scanner can misread because their prose contains backticks. */
6
+ export function isCommentOnlySourceChange(before: string, after: string, path: string): boolean {
7
+ if (before === after || !/\.(?:[cm]?[jt]sx?)$/.test(path)) return false;
8
+ const kind = /\.(?:[cm]?[jt]sx)$/.test(path) ? ts.ScriptKind.TSX
9
+ : /\.(?:[cm]?js)$/.test(path) ? ts.ScriptKind.JS : ts.ScriptKind.TS;
10
+ const collect = (source: string): { masked: string; comments: string[] } | null => {
11
+ const file = ts.createSourceFile(path, source, ts.ScriptTarget.Latest, true, kind);
12
+ if (file.parseDiagnostics.length) return null;
13
+ const ranges = new Map<number, ts.CommentRange>();
14
+ const add = (found: ts.CommentRange[] | undefined) => {
15
+ for (const range of found ?? []) ranges.set(range.pos, range);
16
+ };
17
+ const visit = (node: ts.Node) => {
18
+ add(ts.getLeadingCommentRanges(source, node.getFullStart()));
19
+ add(ts.getTrailingCommentRanges(source, node.getEnd()));
20
+ ts.forEachChild(node, visit);
21
+ };
22
+ visit(file);
23
+ const comments: string[] = [];
24
+ let masked = '';
25
+ let end = 0;
26
+ for (const range of [...ranges.values()].sort((left, right) => left.pos - right.pos)) {
27
+ if (range.pos < end) return null;
28
+ const comment = source.slice(range.pos, range.end);
29
+ comments.push(comment);
30
+ masked += source.slice(end, range.pos) + `\u0000C${range.kind}:${comment.match(/\r\n|\r|\n/g)?.join('') ?? ''}\u0000`;
31
+ end = range.end;
32
+ }
33
+ return { masked: masked + source.slice(end), comments };
34
+ };
35
+ const old = collect(before);
36
+ const current = collect(after);
37
+ if (!old || !current || old.masked !== current.masked || old.comments.length !== current.comments.length) return false;
38
+ const directive = /^(?:\/\/\/|\/\/[#@])|@|(?:eslint|istanbul|coverage|#__PURE__|__NO_SIDE_EFFECTS__)/i;
39
+ // Any unquoted @ may be a TypeScript/JSDoc tag, including newly introduced ones.
40
+ // A backticked example username such as `@example_bot` is prose, not a tag.
41
+ const semanticText = (comment: string) => comment.trim().replace(/`[^`\r\n]*`/g, '');
42
+ let changed = false;
43
+ for (let index = 0; index < old.comments.length; index++) {
44
+ const prior = old.comments[index]!;
45
+ const next = current.comments[index]!;
46
+ if (prior === next) continue;
47
+ changed = true;
48
+ // Ordinary inline block comments and line comments stay in the importer set.
49
+ // This exemption is intentionally limited to JSDoc prose edits.
50
+ if (!prior.startsWith('/**') || !next.startsWith('/**')) return false;
51
+ if (directive.test(semanticText(prior)) || directive.test(semanticText(next))) return false;
52
+ }
53
+ return changed;
54
+ }