elanous 0.2.40 → 0.2.41

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 (558) hide show
  1. package/README.md +7 -7
  2. package/apps/pwa/out/404/index.html +1 -1
  3. package/apps/pwa/out/404.html +1 -1
  4. package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → GiOLWmt4MqDZePubBjA4Q}/_buildManifest.js +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +149 -0
  6. package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +36 -0
  7. package/apps/pwa/out/_next/static/chunks/{9184.45afbf44fec87574.js → 1178.1aa9cad0e7695427.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/{2829-734fe8bf2eee7347.js → 1197-54da59d250a6e476.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/{6749.0744ce6eb08d40e9.js → 1219.7e17964e0e7cd8e5.js} +3 -3
  10. package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +287 -0
  11. package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +90 -0
  16. package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1765.679b29625c8e88d4.js +77 -0
  18. package/apps/pwa/out/_next/static/chunks/{2226.2cf61ec781827219.js → 1800.f7ff51dc4978a958.js} +2 -2
  19. package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{9175.2de5209a5ce6f68a.js → 2073.689dcb2680113d76.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{5383.bdfa5d886e39a826.js → 2263.e09b6edea33bad2d.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{9069.657590a84afb8fac.js → 2743.5d3f76948be32b34.js} +2 -2
  31. package/apps/pwa/out/_next/static/chunks/{6624.981ef7caeb680560.js → 2773.0e80b9d325fb5635.js} +2 -2
  32. package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{4864a2ca.1c1c280a7772c5e5.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/{9189505a.980427ac048c8c60.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/{9992.07ce73c10bd5e6a1.js → 3097.864e92bdaa2f4d15.js} +2 -2
  36. package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3230-49298c3b73ef2268.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +74 -0
  41. package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{b84cad00.594027ebe0531fe2.js → 385e4574.e9886ab32759eda3.js} +3 -3
  46. package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4133.2056bb4d78f621af.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/{8086.1ab9103c41be884f.js → 4156.ba4de4a3664f04b4.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +148 -0
  53. package/apps/pwa/out/_next/static/chunks/{1281.d81877e35b9068f4.js → 4527.a69f2894d1bc9f4a.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +226 -0
  55. package/apps/pwa/out/_next/static/chunks/{8357.1aaa713b052a78b1.js → 4667.97e31aa38c95c475.js} +4 -4
  56. package/apps/pwa/out/_next/static/chunks/{5436.fdf6fa8ae3e9588d.js → 4702.4a4adc1f16d7c93b.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +94 -0
  64. package/apps/pwa/out/_next/static/chunks/{4769.9fd582071301f382.js → 5159.115f1c2ca471386c.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/530.d26346e18089640a.js +115 -0
  67. package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +8 -0
  68. package/apps/pwa/out/_next/static/chunks/{d8de0de2-dd0f4ac8e5ab1832.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
  69. package/apps/pwa/out/_next/static/chunks/{6257.c0037b8949239f5e.js → 5471.1e611302ed3a7c53.js} +2 -2
  70. package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/{2566.beaffc3a5e1fcd2e.js → 5574.f35accf4f132b29d.js} +1 -1
  73. package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/{2066.a77257c8c350770a.js → 5744.b9415e18ad623100.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/{4351.0f37a6db2b34d50b.js → 5937.c2df9e3447e1f667.js} +1 -1
  77. package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
  78. package/apps/pwa/out/_next/static/chunks/{6051-0ae955eedb10adb9.js → 5947-135e26537d80a6b9.js} +3 -3
  79. package/apps/pwa/out/_next/static/chunks/{3746-f80a78f220bf37b5.js → 5964-7e21164a8f2cf0ce.js} +1 -1
  80. package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +27 -0
  84. package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +62 -0
  86. package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +24 -0
  87. package/apps/pwa/out/_next/static/chunks/{2047.8f23e210995d4548.js → 6874.d5cf7eb8edb2cabe.js} +2 -2
  88. package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +122 -0
  90. package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7191.fdc955f7d96064a4.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{8272-025653884f9645d2.js → 8050-9b364bdef8f71927.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/83184dcd-0ee6247ff41eb3f2.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +104 -0
  103. package/apps/pwa/out/_next/static/chunks/{2281-b8cede695c6c650e.js → 8464-e24f10451b658aac.js} +1 -1
  104. package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/{5622.94893f5aea7185d0.js → 8880.64c445592f04acaf.js} +1 -1
  108. package/apps/pwa/out/_next/static/chunks/{1452.162bb2d9d699e82a.js → 8981.c706964c8ba27aff.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{470.51a72a2348306455.js → 9048.212083de42d25be3.js} +2 -2
  110. package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{2177.df8547f9d7215c4e.js → 9507.7026657a2f47eb64.js} +16 -16
  117. package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +93 -0
  118. package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{7515.1ad6efe157fa4448.js → 9579.4a8169600fff2058.js} +1 -1
  120. package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +34 -0
  123. package/apps/pwa/out/_next/static/chunks/{2499.02fbfd18126c10c0.js → 9834.63ab2bbc3153172e.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/{409c787b.e48c5bec8ec10456.js → a0a01613.6d1cca322238d7fe.js} +1 -1
  126. package/apps/pwa/out/_next/static/chunks/{6cc1d1d6.9a98dd4622f1afc6.js → addc2b32.8c4ff8f0aefe987d.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-ba957ff875a026a0.js → page-14949db884bfa672.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-40f9e19149024298.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a142dfb0331a05f5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/{c696986b.5dc8bb1143af16d1.js → b2271e54.c1de3347976e90b0.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/{ca3702f8.2913182e73889fa2.js → c0c1a699.0ba79f97005965d4.js} +1 -1
  180. package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +1 -0
  185. package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +1 -0
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +22 -22
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +22 -22
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +22 -22
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +21 -21
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +21 -21
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +22 -22
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +21 -21
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +22 -22
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +22 -22
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +21 -21
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +22 -22
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +22 -22
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +22 -22
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +22 -22
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +21 -21
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +21 -21
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +22 -22
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +22 -22
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +22 -22
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +21 -21
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +21 -21
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +22 -22
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +22 -22
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +21 -21
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +21 -21
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +21 -21
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +22 -22
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +22 -22
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +21 -21
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +22 -22
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +22 -22
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +22 -22
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +22 -22
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +22 -22
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +21 -21
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +22 -22
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +22 -22
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +22 -22
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +22 -22
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +22 -22
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +22 -22
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +22 -22
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +22 -22
  279. package/bin/elanous.mjs +6 -1
  280. package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
  281. package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
  282. package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
  283. package/graphs/demo/persona-teacher/recipes.yaml +17 -0
  284. package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
  285. package/graphs/overlays/stop-heal-ladder.yaml +23 -2
  286. package/graphs/release/release-loop.yaml +3 -1
  287. package/graphs/units/gate/gate.yaml +20 -0
  288. package/graphs/units/git/git.yaml +26 -0
  289. package/graphs/units/implement/implement.yaml +19 -0
  290. package/graphs/units/landing/landing.yaml +18 -0
  291. package/graphs/units/review/review.yaml +20 -0
  292. package/graphs/units/verbs/recipes.yaml +3 -0
  293. package/graphs/units/verbs/research.yaml +20 -0
  294. package/graphs/work/research-report.yaml +11 -1
  295. package/package.json +1 -1
  296. package/scripts/disk-steward.ts +46 -0
  297. package/scripts/fleet/node-setup.sh +50 -0
  298. package/scripts/graph-units/verbs/research.ts +55 -0
  299. package/scripts/llm-cost-ledger.ts +179 -8
  300. package/scripts/measure-nl-routing-corpus.ts +10 -2
  301. package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
  302. package/scripts/public-copy-lint.ts +163 -19
  303. package/scripts/ratchets/train-side-invariants.sh +0 -1
  304. package/scripts/release-loop/gate-autoheal.ts +117 -0
  305. package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
  306. package/scripts/release-loop/gate-diff.ts +22 -3
  307. package/scripts/release-loop/gate-node.ts +205 -17
  308. package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
  309. package/scripts/release-loop/gate-triage-node.ts +70 -10
  310. package/scripts/release-loop/resume-release.ts +247 -15
  311. package/scripts/release-loop/traffic-node.ts +6 -3
  312. package/scripts/release-loop/unattended-release.ts +4 -2
  313. package/scripts/shadow-authoring-probe.ts +20 -0
  314. package/scripts/ux-sim.ts +19 -2
  315. package/src/acp/core-turn-bridge.ts +86 -4
  316. package/src/agent-substrate/self-review-cli.ts +91 -29
  317. package/src/auto-research/research-turn.ts +10 -1
  318. package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
  319. package/src/boot/daemon-tools/self-implement.ts +46 -9
  320. package/src/budget/shadow-arms.ts +52 -0
  321. package/src/chat/pickers/state.ts +7 -1
  322. package/src/cli/log-event-names.ts +5 -0
  323. package/src/cli/mcp-login.ts +8 -18
  324. package/src/cli/msg-cli.ts +57 -1
  325. package/src/cli/pr-land-heavy-remote.ts +15 -9
  326. package/src/cli/release-cli.ts +27 -1
  327. package/src/cli/sim-cli.ts +7 -1
  328. package/src/cli/tasks-cli.ts +5 -4
  329. package/src/codex/models.ts +30 -15
  330. package/src/core-turn/run-core-turn.ts +3 -0
  331. package/src/core-turn/run-goal-loop.ts +88 -2
  332. package/src/dashboard/acp-boot.ts +72 -3
  333. package/src/dashboard/index.ts +6 -0
  334. package/src/dashboard/turn-preamble.ts +12 -1
  335. package/src/disk-steward/judge.ts +73 -0
  336. package/src/disk-steward/ledger.ts +122 -0
  337. package/src/disk-steward/steward.ts +373 -0
  338. package/src/domains/guardian-tick.ts +191 -2
  339. package/src/graph-runner/graph-cli.ts +21 -0
  340. package/src/graph-runner/in-process-registry.ts +37 -0
  341. package/src/graph-runner/runner.ts +33 -3
  342. package/src/grounding/ref-index.ts +19 -0
  343. package/src/grounding/sources-cli.ts +9 -1
  344. package/src/harness/harness-cli-command.ts +267 -14
  345. package/src/harness/harness-incidents.ts +312 -7
  346. package/src/harness/harness-space.ts +15 -1
  347. package/src/harness/progress-worker-entry.ts +59 -0
  348. package/src/harness/progress-worker-runtime.ts +11 -0
  349. package/src/index.ts +18 -2
  350. package/src/instance/dev-project.ts +25 -0
  351. package/src/intelligence-map/model-alias.ts +6 -5
  352. package/src/intelligence-map/model-catalog.ts +59 -2
  353. package/src/llm/model-defaults.ts +4 -4
  354. package/src/llm.ts +42 -11
  355. package/src/loops/orchestrator/tick.ts +48 -0
  356. package/src/mcp/mcp-oauth.ts +3 -1
  357. package/src/model-tier/llm-tier-map.ts +9 -9
  358. package/src/model-tier/turn-tier.ts +1 -1
  359. package/src/msg/msg-mirror-github.ts +80 -0
  360. package/src/msg/msg-mirror-policy.ts +61 -0
  361. package/src/msg/msg-mirror-runner.ts +219 -0
  362. package/src/msg/msg-mirror-state.ts +33 -0
  363. package/src/msg/msg-store.ts +11 -0
  364. package/src/output-truncation.ts +41 -12
  365. package/src/project/project-store.ts +48 -1
  366. package/src/release-loop/gate-host-reservation.ts +144 -0
  367. package/src/release-loop/release-schedule.ts +90 -1
  368. package/src/research/bloom-exemplars.ts +135 -0
  369. package/src/self-dev/ask-launch-flow.ts +39 -25
  370. package/src/self-dev/dev-cli.ts +17 -17
  371. package/src/self-dev/graph-front-nodes.ts +23 -0
  372. package/src/self-dev/launch-preflight.ts +9 -4
  373. package/src/self-dev/orchestrate.ts +15 -0
  374. package/src/self-dev/run-supervisor.ts +185 -3
  375. package/src/self-dev/run-types.ts +3 -0
  376. package/src/self-implement/gate-artifacts.ts +13 -0
  377. package/src/self-implement/gate-cli.ts +54 -24
  378. package/src/self-implement/gate-remote.ts +23 -5
  379. package/src/self-implement/goal-author-clarification.ts +31 -12
  380. package/src/self-implement/goal-author.ts +77 -5
  381. package/src/self-implement/graph-stage-units.ts +172 -0
  382. package/src/self-implement/graph-templates.ts +162 -1
  383. package/src/self-implement/graph-variant.ts +37 -4
  384. package/src/self-implement/host-regate.ts +4 -4
  385. package/src/self-implement/knowhow-pack.ts +38 -0
  386. package/src/self-implement/orchestrator.ts +235 -21
  387. package/src/self-implement/run-ledger.ts +64 -6
  388. package/src/self-implement/run-stop.ts +21 -2
  389. package/src/self-implement/running-runs.ts +35 -12
  390. package/src/self-implement/self-implement-cli.ts +36 -4
  391. package/src/self-implement/stop-autoheal-operational.ts +43 -0
  392. package/src/self-implement/stop-autoheal.ts +15 -6
  393. package/src/session/chat.ts +31 -54
  394. package/src/session/request-size-guard.ts +123 -0
  395. package/src/sidetab-core/model.ts +136 -0
  396. package/src/task-agent/parent-host.ts +14 -1
  397. package/src/task-agent/task-hand.ts +4 -1
  398. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +43 -0
  399. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
  400. package/src/task-orchestrator/surfaces/self-implement-pod.ts +116 -16
  401. package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
  402. package/src/tui/entry.ts +10 -3
  403. package/src/tui/sidetab/list.ts +45 -0
  404. package/src/tui/sidetab/nl-tool.ts +2 -136
  405. package/src/tui/sidetab/peek.ts +52 -0
  406. package/src/tui-client/dashboard-session.ts +3 -0
  407. package/src/user-config.ts +11 -5
  408. package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
  409. package/src/ux-sim/fault-pod-child-result.ts +42 -0
  410. package/src/ux-sim/release-sim-rig.ts +262 -0
  411. package/src/ux-sim/seminar-rehearsal.ts +109 -0
  412. package/src/ux-sim/subagent-tools-device.ts +2 -2
  413. package/src/version/packed-revision.json +1 -1
  414. package/apps/pwa/out/_next/static/chunks/1060.014f1f01a17aec26.js +0 -115
  415. package/apps/pwa/out/_next/static/chunks/1350.59f40e39e02d91b1.js +0 -1
  416. package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +0 -1
  417. package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +0 -286
  418. package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +0 -1
  419. package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +0 -149
  420. package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +0 -1
  421. package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +0 -90
  422. package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +0 -104
  423. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +0 -1
  424. package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +0 -1
  425. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +0 -1
  426. package/apps/pwa/out/_next/static/chunks/2522.f2766b76d22c8bdf.js +0 -34
  427. package/apps/pwa/out/_next/static/chunks/261.0d471e8aded799f3.js +0 -226
  428. package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +0 -1
  429. package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +0 -1
  430. package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +0 -27
  431. package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +0 -1
  432. package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +0 -1
  433. package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +0 -1
  434. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +0 -1
  435. package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +0 -1
  436. package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +0 -1
  437. package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +0 -1
  438. package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +0 -1
  439. package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +0 -1
  440. package/apps/pwa/out/_next/static/chunks/3330.7443183b7e6fdbdf.js +0 -1
  441. package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +0 -1
  442. package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +0 -1
  443. package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +0 -24
  444. package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +0 -77
  445. package/apps/pwa/out/_next/static/chunks/3b355b3d.6f73c98bf6f9c749.js +0 -122
  446. package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +0 -36
  447. package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +0 -1
  448. package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +0 -1
  449. package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +0 -287
  450. package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +0 -1
  451. package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +0 -1
  452. package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +0 -1
  453. package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +0 -1
  454. package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +0 -1
  455. package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +0 -1
  456. package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +0 -74
  457. package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +0 -1
  458. package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +0 -1
  459. package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +0 -1
  460. package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +0 -8
  461. package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +0 -62
  463. package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +0 -1
  465. package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +0 -1
  466. package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +0 -94
  467. package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +0 -1
  468. package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +0 -148
  477. package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +0 -1
  479. package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +0 -93
  482. package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +0 -24
  485. package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/app/term/page-139d722de1dcd6c1.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +0 -1
  557. package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
  558. /package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
@@ -8,11 +8,14 @@ import { tmpdir } from 'node:os';
8
8
  import { dirname, join, resolve } from 'node:path';
9
9
  import { debug } from '../../src/debug/log.js';
10
10
  import { effectiveInstanceRoot, releaseLedgerRoot } from '../../src/instance/resolve.js';
11
+ import { acquireLockAsync } from '../../src/storage/file-lock.js';
11
12
  import { lastJsonObject, runGraph, verifyReleaseCommandRoot, verifyReleaseRecipeSnapshot, type GraphRunState } from '../../src/graph-runner/runner.js';
12
13
  import { withOpSeatFlock } from '../../src/steward/resync-tick.js';
13
14
  import { releaseRunUniverse } from './release-universe.js';
14
15
  import { isReleaseVersion } from './release-version.js';
15
- import { changedFilesBetween, clearPartialPlan, collectExecutedPodShardImages, planPartialRegate, planStalledShardRecheck, writePartialPlan, writeRecheckPlan } from './gate-partial.js';
16
+ import { changedFilesBetween, clearPartialPlan, collectExecutedPodShardImages, planPartialRegate, planSameCommitRecheck, planStalledShardRecheck, testFileOfId, writePartialPlan, writeRecheckPlan } from './gate-partial.js';
17
+ import { gateAssignableTestsAtCommit, gateEnvFingerprint } from './gate-baseline-receipt.js';
18
+ import { readGateShardManifest, readGateShardResult } from './gate-shard-receipts.js';
16
19
  import { gitClosureTree, testsReachingChanged, TRACEABLE_RELEASE_JSON, type ClosureTree } from './gate-closure.js';
17
20
  import { assertReleaseResumeApprovalBoundary, releaseResumeAcceptedRegressions, releaseResumeGateExecutor, releaseResumeGatePodPool, releaseResumeGateShardReroute, releaseResumeWaiver, type AcceptedRegression } from './resume.js';
18
21
  import { reserveReleaseResumeAttempt } from './resume-cap.js';
@@ -46,6 +49,8 @@ export interface ResumeReleaseDeps {
46
49
  ledgerRoot?: string;
47
50
  /** GATE-REUSE-BY-DIFF: the tip tree for the import closure — default read from git objects of the tip commit. */
48
51
  closureTree?: (commit: string) => ClosureTree;
52
+ /** Test seam for the pinned Pod gate selection; production reads the selected test universe at the cut commit. */
53
+ gateTestsAtCommit?: (commit: string) => string[] | null;
49
54
  /** Source observation before the first resumed node. */
50
55
  onSource?: (line: string) => void;
51
56
  /** Test seam; production resolves this from ELANOUS_RELEASE_TRAFFIC_FILE / release.loop.trafficFile. */
@@ -293,14 +298,111 @@ function verifyResumePreflight(run: GraphRunState, opts: ResumeReleaseOptions, d
293
298
  }
294
299
  }
295
300
 
296
- /** GATE-PARTIAL outcome of a resume — applied (plan written) or the reason it fell back to a full gate. `auto` marks the
297
- * default plan of `--from gate` (GATE-REUSE-BY-DIFF); `closure` is set when code changes were followed. */
301
+ /** GATE-PARTIAL outcome of a resume — applied (with its exact remeasure selection) or the reason it fell back to a full gate.
302
+ * `auto` marks the default plan of `--from gate` (GATE-REUSE-BY-DIFF); `closure` is set when code changes were followed. */
298
303
  export type PartialOutcome = { requested: false }
299
- | { requested: true; applied: true; files: number; priorCommit: string; auto?: true; closure?: { reached: number; opaque: number } }
304
+ | { requested: true; applied: true; files: number; plannedFiles: string[]; priorCommit: string; auto?: true; closure?: { reached: number; opaque: number } }
300
305
  | { requested: true; applied: false; reason: string; auto?: true };
301
306
 
302
307
  /** Build (or clear) the partial re-gate plan for the new tip. Fail-closed: any doubt leaves a full gate.
303
308
  * GATE-REUSE-BY-DIFF: `--from gate` on a moved tip plans by default (`partial: undefined`); `partial: false` opts out. */
309
+ type StalledGateEvidence = {
310
+ stalledShards: Array<{ shard: number; files: string[]; reason: string }>;
311
+ partialSummary: { pass: number; fail: number; errors: number; ran: number; files: number };
312
+ partialFailures: { failures: string[]; errors: string[] };
313
+ preservedShardCount: number;
314
+ };
315
+
316
+ /** Recover an interrupted Pod sweep from its atomic shard receipts. No receipt or identity doubt authorizes a partial gate. */
317
+ function stalledGateEvidence(input: { version: string; commit: string; repo: string; roots: string[];
318
+ gateOutput?: Record<string, unknown>; expectedBase40?: string; expectedTests?: (commit: string) => string[] | null }):
319
+ { ok: true; evidence: StalledGateEvidence } | { ok: false; reason: string } {
320
+ const fail = (reason: string) => ({ ok: false as const, reason });
321
+ if (input.gateOutput && (input.gateOutput.outcome !== 'error' || input.gateOutput.commit !== input.commit))
322
+ return fail('saved gate result is not an error for the recorded cut');
323
+ if (!/^[a-f0-9]{40}$/i.test(input.expectedBase40 ?? ''))
324
+ return fail('saved cutoff baseline is absent or invalid');
325
+ const fingerprint = gateEnvFingerprint(process.env);
326
+ let receiptDir: string | undefined;
327
+ for (const root of input.roots) {
328
+ const candidate = join(root, 'release', input.version, 'gate-logs', 'cut', 'receipts');
329
+ if (existsSync(candidate)) { receiptDir = candidate; break; }
330
+ }
331
+ if (!receiptDir) return fail('stalled gate receipts are absent');
332
+ const names = readdirSync(receiptDir).filter((name) => /^pod-\d+\.receipt\.json$/.test(name)).sort((a, b) =>
333
+ Number(/^pod-(\d+)/.exec(a)![1]) - Number(/^pod-(\d+)/.exec(b)![1]));
334
+ if (!names.length || names.some((name, index) => Number(/^pod-(\d+)/.exec(name)![1]) !== index))
335
+ return fail('stalled gate receipt shard set is incomplete');
336
+ const allFiles: string[] = [];
337
+ const failures: string[] = [];
338
+ const errors: string[] = [];
339
+ const stalledShards: StalledGateEvidence['stalledShards'] = [];
340
+ const imageDigests = new Set<string>();
341
+ let pass = 0, failCount = 0, errorCount = 0, ran = 0, files = 0, preservedShardCount = 0;
342
+ let base40: string | undefined;
343
+ for (const name of names) {
344
+ const id = name.slice(0, -'.receipt.json'.length);
345
+ const receipt = readGateShardManifest(receiptDir, id);
346
+ if (!receipt || receipt.head40 !== input.commit || !/^[a-f0-9]{40}$/i.test(receipt.base40)
347
+ || !receipt.files.length
348
+ || receipt.files.some((file) => typeof file !== 'string'
349
+ || !/^(?:[\w.-]+\/)*[\w.-]+\.test\.(?:tsx?|jsx?|mts|cts)$/.test(file) || file.split('/').includes('..'))
350
+ || typeof receipt.envKey !== 'string' || typeof receipt.host !== 'string')
351
+ return fail(`stalled gate receipt identity or file list is invalid: ${id}`);
352
+ if (receipt.base40 !== input.expectedBase40)
353
+ return fail(`stalled gate receipt baseline differs from saved cutoff baseline: ${id}`);
354
+ if (base40 && receipt.base40 !== base40) return fail(`stalled gate receipts disagree on baseline: ${id}`);
355
+ base40 = receipt.base40;
356
+ allFiles.push(...receipt.files);
357
+ if (receipt.status === 'unmeasured') {
358
+ stalledShards.push({ shard: Number(id.slice(4)), files: [...receipt.files], reason: 'incomplete' });
359
+ continue;
360
+ }
361
+ if (!receipt.envKey.startsWith(`${fingerprint}:`)) return fail(`stalled gate receipt environment mismatch: ${id}`);
362
+ const imageDigest = receipt.envKey.slice(fingerprint.length + 1);
363
+ if (!/^sha256:[a-f0-9]{64}$/i.test(imageDigest)) return fail(`stalled gate receipt image identity is missing: ${id}`);
364
+ imageDigests.add(imageDigest.toLowerCase());
365
+ const result = readGateShardResult(receiptDir, { shard: { id, files: receipt.files }, head40: input.commit,
366
+ base40: receipt.base40, envKey: receipt.envKey });
367
+ if (!result) return fail(`stalled gate receipt payload is incomplete or corrupt: ${id}`);
368
+ const totals = result.runs.reduce((sum, run) => ({ pass: sum.pass + run.pass, fail: sum.fail + run.fail,
369
+ errors: sum.errors + run.errors, ran: sum.ran + run.ran, files: sum.files + run.files }),
370
+ { pass: 0, fail: 0, errors: 0, ran: 0, files: 0 });
371
+ if (!Object.values(totals).every(Number.isSafeInteger) || receipt.failureIds.length !== totals.fail
372
+ || receipt.errorIds.length !== totals.errors)
373
+ return fail(`stalled gate receipt counts do not reconcile: ${id}`);
374
+ pass += totals.pass; failCount += totals.fail; errorCount += totals.errors; ran += totals.ran; files += totals.files;
375
+ failures.push(...receipt.failureIds); errors.push(...receipt.errorIds); preservedShardCount++;
376
+ }
377
+ if (!stalledShards.length) return fail('no incomplete shard receipt identifies the interrupted work');
378
+ if (new Set(allFiles).size !== allFiles.length) return fail('stalled gate receipt file assignments overlap');
379
+ if (imageDigests.size !== 1) return fail('stalled gate completed shards do not share one executed image');
380
+ const expected = (input.expectedTests ?? ((commit) => gateAssignableTestsAtCommit(input.repo, commit)))(input.commit);
381
+ if (!expected || JSON.stringify([...expected].sort()) !== JSON.stringify([...allFiles].sort()))
382
+ return fail('stalled gate receipts do not cover the pinned test selection');
383
+ const partialSummary = { pass, fail: failCount, errors: errorCount, ran, files };
384
+ const partialFailures = { failures: [...new Set(failures)].sort(), errors: [...new Set(errors)].sort() };
385
+ const gate = input.gateOutput;
386
+ if (gate) {
387
+ const savedSummary = gate.partialSummary as Partial<StalledGateEvidence['partialSummary']> | undefined;
388
+ const savedFailures = gate.partialFailures as Partial<StalledGateEvidence['partialFailures']> | undefined;
389
+ if (savedSummary && JSON.stringify(savedSummary) !== JSON.stringify(partialSummary))
390
+ return fail('saved gate summary disagrees with shard receipts');
391
+ if (savedFailures && (JSON.stringify([...((savedFailures.failures as string[] | undefined) ?? [])].sort()) !== JSON.stringify(partialFailures.failures)
392
+ || JSON.stringify([...((savedFailures.errors as string[] | undefined) ?? [])].sort()) !== JSON.stringify(partialFailures.errors)))
393
+ return fail('saved gate failures disagree with shard receipts');
394
+ if (gate.preservedShardCount !== undefined && gate.preservedShardCount !== preservedShardCount)
395
+ return fail('saved preserved shard count disagrees with shard receipts');
396
+ if (Array.isArray(gate.stalledShards)) {
397
+ const savedStalled = gate.stalledShards.flatMap((item) => item && typeof item === 'object'
398
+ && Array.isArray((item as { files?: unknown }).files) ? (item as { files: string[] }).files : []).sort();
399
+ if (JSON.stringify(savedStalled) !== JSON.stringify(stalledShards.flatMap((item) => item.files).sort()))
400
+ return fail('saved stalled shard list disagrees with shard receipts');
401
+ }
402
+ }
403
+ return { ok: true, evidence: { stalledShards, partialSummary, partialFailures, preservedShardCount } };
404
+ }
405
+
304
406
  function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean; gateExecutor?: string }, deps: ResumeReleaseDeps, dryRun = false): PartialOutcome {
305
407
  const root = deps.root ?? effectiveInstanceRoot();
306
408
  // Any resume starts from no plan: one without a partial plan (from whatever node) never inherits an older plan.
@@ -356,9 +458,11 @@ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean
356
458
  debug.log('release-loop.resume', 'stalled-recheck-planned', { version: tip.version, commit: tip.to,
357
459
  planKind: planned.plan.kind, remeasureFileCount: planned.plan.files.length,
358
460
  preservedShardCount: planned.plan.preservedShardCount ?? 0, fallbackReason: null, path });
359
- return { requested: true, applied: true, files: planned.plan.files.length, priorCommit: tip.to, ...(auto ? { auto: true as const } : {}) };
461
+ return { requested: true, applied: true, files: planned.plan.files.length, plannedFiles: [...planned.plan.files], priorCommit: tip.to,
462
+ ...(auto ? { auto: true as const } : {}) };
360
463
  }
361
464
  let prior: { commit?: unknown; failures?: unknown; errors?: unknown } | undefined;
465
+ let movedStalledEvidence: StalledGateEvidence | undefined;
362
466
  for (const location of [...new Set([deps.ledgerRoot ?? releaseLedgerRoot(), root])]) {
363
467
  const path = join(location, 'release', tip.version, 'gate-failures.json');
364
468
  if (!existsSync(path)) continue;
@@ -368,7 +472,19 @@ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean
368
472
  if (record?.commit === tip.from) { prior = record; break; }
369
473
  }
370
474
  if (!prior || !Array.isArray(prior.failures) || !(prior.errors === undefined || Array.isArray(prior.errors))) {
371
- return fallback(`no complete gate record for ${tip.from.slice(0, 12)} (a stalled or errored gate keeps none)`);
475
+ const gateRecord = saved.nodes.find((node) => node.nodeId === 'gate');
476
+ const gateOutput = gateRecord ? lastJsonObject(gateRecord.output) as Record<string, unknown> | undefined : undefined;
477
+ const cutoffRecord = saved.nodes.find((node) => node.nodeId === 'cutoff');
478
+ const cutoffOutput = cutoffRecord ? lastJsonObject(cutoffRecord.output) as Record<string, unknown> | undefined : undefined;
479
+ const expectedBase40 = (cutoffOutput?.baseline as { sha?: unknown } | undefined)?.sha;
480
+ const evidence = stalledGateEvidence({ version: tip.version, commit: tip.from, repo: deps.repo ?? process.cwd(),
481
+ roots: [...new Set([deps.ledgerRoot ?? releaseLedgerRoot(), root])], gateOutput,
482
+ ...(typeof expectedBase40 === 'string' ? { expectedBase40 } : {}),
483
+ expectedTests: deps.gateTestsAtCommit });
484
+ if (!evidence.ok) return fallback(`no complete gate record for ${tip.from.slice(0, 12)}; ${evidence.reason}`);
485
+ movedStalledEvidence = evidence.evidence;
486
+ prior = { commit: tip.from, failures: movedStalledEvidence.partialFailures.failures,
487
+ errors: movedStalledEvidence.partialFailures.errors };
372
488
  }
373
489
  // Both sides of a rename count (`--no-renames`): a source moved to a test/Markdown name is still a source change.
374
490
  let changed: string[];
@@ -404,10 +520,11 @@ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean
404
520
  const savedInput = saved.input as { gateExecutor?: unknown; gatePodPool?: unknown };
405
521
  const podGate = (opts.gateExecutor ?? savedInput.gateExecutor ?? (savedInput.gatePodPool ? 'pod' : undefined)) === 'pod';
406
522
  const priorShards = priorCutLogs ? collectExecutedPodShardImages(priorCutLogs, tip.from) : undefined;
407
- const planned = planPartialRegate({ version: tip.version, priorCommit: tip.from, forCommit: tip.to, changedFiles: changed,
523
+ const stalledFiles = movedStalledEvidence?.stalledShards.flatMap((shard) => shard.files) ?? [];
524
+ const planned = planPartialRegate({ version: tip.version, priorCommit: tip.from, forCommit: tip.to, changedFiles: [...changed, ...stalledFiles],
408
525
  priorFailures: prior.failures as string[], priorErrors: (prior.errors ?? []) as string[],
409
526
  existsAtTip: (file) => tracked.has(file),
410
- ...(podGate ? { priorShards: priorShards ?? [] } : {}),
527
+ ...((podGate || movedStalledEvidence) ? { priorShards: priorShards ?? [] } : {}),
411
528
  closure: (changedCode) => testsReachingChanged(tree, changedCode, tests, { cliEntries: CLI_ENTRIES }) });
412
529
  if (!planned.ok) return fallback(planned.reason);
413
530
  if (planned.plan.files.length >= tests.length) return fallback(`every test is re-run (${tests.length}) — full gate`);
@@ -427,7 +544,7 @@ function preparePartial(tip: TipRefresh, opts: { from: string; partial?: boolean
427
544
  const path = dryRun ? undefined : writePartialPlan(root, planned.plan);
428
545
  debug.log('release-loop.resume', 'partial-planned', { version: tip.version, priorCommit: tip.from, commit: tip.to, files: planned.plan.files.length,
429
546
  tests: tests.length, auto, ...(path ? { path } : {}), dryRun, ...(planned.closure ? { reached: planned.closure.reached, opaque: planned.closure.opaque } : {}) });
430
- return { requested: true, applied: true, files: planned.plan.files.length, priorCommit: tip.from,
547
+ return { requested: true, applied: true, files: planned.plan.files.length, plannedFiles: [...planned.plan.files], priorCommit: tip.from,
431
548
  ...(auto ? { auto: true as const } : {}), ...(planned.closure ? { closure: planned.closure } : {}) };
432
549
  }
433
550
 
@@ -604,6 +721,23 @@ export interface RecoverReleaseResult {
604
721
  resume?: { status: string; tip: TipRefresh; partial: PartialOutcome };
605
722
  }
606
723
 
724
+ export interface RecoverReleaseLandingOptions {
725
+ runId: string;
726
+ /** The landed repair commit on main; this is the idempotency key for a landing notification. */
727
+ mergeSha: string;
728
+ from?: string;
729
+ commandRoot?: string;
730
+ partial?: boolean;
731
+ repoRoot?: string;
732
+ }
733
+
734
+ export type RecoverReleaseLandingResult = RecoverReleaseResult & { duplicate: boolean };
735
+
736
+ /** Commander represents `--no-partial` as false and its default (flag omitted) as true. */
737
+ export function recoverLandingPartialOption(optionValue?: boolean): boolean | undefined {
738
+ return optionValue === false ? false : undefined;
739
+ }
740
+
607
741
  export interface RecoverReleaseDeps extends ResumeReleaseDeps {
608
742
  /** `release cut-branch --append` — tests record the plan instead of pushing the branch. */
609
743
  cutBranch?: typeof cutReleaseBranch;
@@ -619,11 +753,19 @@ export class ReleaseRecoverStopped extends Error {
619
753
  }
620
754
  }
621
755
 
756
+ function readRecoverJson(path: string, label: string): unknown {
757
+ try { return JSON.parse(readFileSync(path, 'utf8')) as unknown; }
758
+ catch (error) {
759
+ const detail = error instanceof Error ? error.message : String(error);
760
+ throw new Error(`release ${label} JSON을 읽을 수 없다: ${path} (${detail}) — 파일을 보존하고 원장을 올바른 JSON으로 복구한 뒤 재시도하라.`);
761
+ }
762
+ }
763
+
622
764
  /** Append one stage result to the resume-attempts ledger. `attempts[]` keeps its shape — the stage results are added. */
623
765
  function recordRecoverStage(entry: { root: string; runId: string; version: string; priorCountKnown: boolean; stage: RecoverStageRecord }): void {
624
766
  const path = join(entry.root, 'release', entry.version, 'resume-attempts', `${entry.runId}.json`);
625
767
  const saved = existsSync(path)
626
- ? JSON.parse(readFileSync(path, 'utf8')) as { attempts?: unknown; recoveries?: unknown; priorCountKnown?: unknown }
768
+ ? readRecoverJson(path, 'resume attempts 원장') as { attempts?: unknown; recoveries?: unknown; priorCountKnown?: unknown }
627
769
  : undefined;
628
770
  if (saved !== undefined && (!saved || typeof saved !== 'object' || Array.isArray(saved) || !Array.isArray(saved.attempts)
629
771
  || (saved.recoveries !== undefined && !Array.isArray(saved.recoveries)))) throw new Error('release resume attempts ledger invalid');
@@ -637,16 +779,39 @@ function recordRecoverStage(entry: { root: string; runId: string; version: strin
637
779
  renameSync(temporary, path);
638
780
  }
639
781
 
782
+ async function acquireReleaseRecoveryLock(root: string, runId: string) {
783
+ const lockDir = join(root, 'release', 'recovery-locks');
784
+ mkdirSync(lockDir, { recursive: true });
785
+ // A full-gate subprocess can block this process's event loop, delaying the async lock heartbeat.
786
+ // The observed release gate reached 2h20m; leave a finite four-hour stale/wait window for one recovery.
787
+ const lock = await acquireLockAsync(join(lockDir, `${runId}.lock`), {
788
+ staleMs: 4 * 60 * 60_000, retryBusyMs: 1_000, maxTries: 14_400,
789
+ });
790
+ if (!lock.stillHeld()) {
791
+ lock.release();
792
+ throw new Error(`release recovery lock was lost for ${runId} — retry after inspecting the recovery ledger`);
793
+ }
794
+ return lock;
795
+ }
796
+
640
797
  /**
641
798
  * Repair a failed release run in one command: append dry-run (plan only) → append (fast-forward release/<v> onto the
642
799
  * picked repairs) → resume --from export-check (preflight plan, then the graph). A failing stage stops the command:
643
800
  * the later stages never run, and the stage results are already in the ledger for the human to read.
644
801
  */
645
802
  export async function recoverReleaseRun(opts: RecoverReleaseOptions, deps: RecoverReleaseDeps = {}): Promise<RecoverReleaseResult> {
646
- if (!Array.isArray(opts.pick) || !opts.pick.length) throw new Error('release recover requires at least one --pick commit');
647
803
  const root = releaseRunUniverse({ root: deps.root });
804
+ const runId = safeRunId(opts.runId);
805
+ const lock = await acquireReleaseRecoveryLock(root, runId);
806
+ try {
807
+ return await recoverReleaseRunLocked(opts, deps, root);
808
+ } finally { lock.release(); }
809
+ }
810
+
811
+ async function recoverReleaseRunLocked(opts: RecoverReleaseOptions, deps: RecoverReleaseDeps, root: string): Promise<RecoverReleaseResult> {
812
+ if (!Array.isArray(opts.pick) || !opts.pick.length) throw new Error('release recover requires at least one --pick commit');
648
813
  const statePath = join(root, 'graph-runs', 'release-loop', `${safeRunId(opts.runId)}.json`);
649
- const savedRun = JSON.parse(readFileSync(statePath, 'utf8')) as GraphRunState;
814
+ const savedRun = readRecoverJson(statePath, 'release run 상태') as GraphRunState;
650
815
  if (savedRun.graphId !== 'release-loop' || savedRun.runId !== opts.runId) throw new Error(`run identity mismatch: ${statePath}`);
651
816
  // The saved version-release record names what to repair: the release branch and the commit the run cut.
652
817
  const versionRecord = savedRun.nodes.find((node) => node.nodeId === 'version-release');
@@ -707,8 +872,9 @@ export async function recoverReleaseRun(opts: RecoverReleaseOptions, deps: Recov
707
872
  const now = (): string => (deps.now?.() ?? new Date()).toISOString();
708
873
  const stages: RecoverStageRecord[] = [];
709
874
  const record = (stage: RecoverStageRecord): void => {
710
- stages.push(stage);
711
- recordRecoverStage({ root, runId: opts.runId, version, priorCountKnown: !savedRun.resume, stage });
875
+ const withPick = { ...stage, pick: stage.pick ?? [...opts.pick] };
876
+ stages.push(withPick);
877
+ recordRecoverStage({ root, runId: opts.runId, version, priorCountKnown: !savedRun.resume, stage: withPick });
712
878
  };
713
879
  const stop = (stage: RecoverStageName, error: unknown): never => {
714
880
  throw new ReleaseRecoverStopped(stage, stages, RECOVER_STAGES.slice(RECOVER_STAGES.indexOf(stage) + 1),
@@ -733,7 +899,7 @@ export async function recoverReleaseRun(opts: RecoverReleaseOptions, deps: Recov
733
899
  };
734
900
  const ledgerPath = join(root, 'release', version, 'resume-attempts', `${opts.runId}.json`);
735
901
  const recoveries: RecoverStageRecord[] = existsSync(ledgerPath)
736
- ? ((JSON.parse(readFileSync(ledgerPath, 'utf8')) as { recoveries?: unknown[] }).recoveries ?? []) as RecoverStageRecord[]
902
+ ? ((readRecoverJson(ledgerPath, 'resume attempts 원장') as { recoveries?: unknown[] }).recoveries ?? []) as RecoverStageRecord[]
737
903
  : [];
738
904
  let appendedCommit: string | undefined;
739
905
  for (let index = recoveries.length - 1; index >= 0; index -= 1) {
@@ -843,3 +1009,69 @@ export async function recoverReleaseRun(opts: RecoverReleaseOptions, deps: Recov
843
1009
  }
844
1010
  }
845
1011
  }
1012
+
1013
+ /**
1014
+ * Manual landing-event entrypoint. The event's merge SHA is the dedupe key; once that repair has completed its
1015
+ * resume stage, a redelivered event returns the recorded result without appending or running the graph again.
1016
+ * The event producer can call this after its own hook lands; this function does not subscribe to PR-land events.
1017
+ */
1018
+ export async function recoverReleaseRunFromLanding(opts: RecoverReleaseLandingOptions,
1019
+ deps: RecoverReleaseDeps = {}): Promise<RecoverReleaseLandingResult> {
1020
+ if (!/^[0-9a-f]{40}$/i.test(opts.mergeSha)) throw new Error('release recover-landing requires a full 40-hex merge SHA');
1021
+ const root = releaseRunUniverse({ root: deps.root });
1022
+ const runId = safeRunId(opts.runId);
1023
+ // Share one run-scoped lock with manual `release recover`: the dedupe read, append, and resume must not race.
1024
+ const landingLock = await acquireReleaseRecoveryLock(root, runId);
1025
+ try {
1026
+ return await recoverReleaseRunFromLandingLocked(opts, deps, root, runId);
1027
+ } finally { landingLock.release(); }
1028
+ }
1029
+
1030
+ async function recoverReleaseRunFromLandingLocked(opts: RecoverReleaseLandingOptions, deps: RecoverReleaseDeps,
1031
+ root: string, runId: string): Promise<RecoverReleaseLandingResult> {
1032
+ const pick = [opts.mergeSha.toLowerCase()];
1033
+ const statePath = join(root, 'graph-runs', 'release-loop', `${runId}.json`);
1034
+ if (existsSync(statePath)) {
1035
+ const savedRun = readRecoverJson(statePath, 'release run 상태') as GraphRunState;
1036
+ const versionNode = savedRun.nodes.find((node) => node.nodeId === 'version-release');
1037
+ const recorded = lastJsonObject(versionNode?.output);
1038
+ const version = typeof recorded?.version === 'string' ? recorded.version : '';
1039
+ if (savedRun.graphId === 'release-loop' && savedRun.runId === runId && isReleaseVersion(version)) {
1040
+ const ledgerPath = join(root, 'release', version, 'resume-attempts', `${runId}.json`);
1041
+ if (existsSync(ledgerPath)) {
1042
+ const ledger = readRecoverJson(ledgerPath, 'resume attempts 원장') as { recoveries?: unknown };
1043
+ if (ledger.recoveries !== undefined && !Array.isArray(ledger.recoveries)) throw new Error(`release resume attempts ledger invalid: ${ledgerPath}`);
1044
+ const records = (ledger.recoveries ?? []) as RecoverStageRecord[];
1045
+ const matchesPick = (entry: RecoverStageRecord): boolean => Array.isArray(entry.pick)
1046
+ && entry.pick.some((sha) => typeof sha === 'string' && sha.toLowerCase() === pick[0]);
1047
+ let completedIndex = -1;
1048
+ for (let index = records.length - 1; index >= 0; index -= 1) {
1049
+ const entry = records[index]!;
1050
+ if (matchesPick(entry) && entry.stage === 'resume' && entry.outcome === 'ok') {
1051
+ completedIndex = index;
1052
+ break;
1053
+ }
1054
+ }
1055
+ if (completedIndex >= 0) {
1056
+ let cycleStart = completedIndex;
1057
+ for (let index = completedIndex; index >= 0; index -= 1) {
1058
+ const entry = records[index]!;
1059
+ if (matchesPick(entry) && entry.stage === 'append-dry-run') {
1060
+ cycleStart = index;
1061
+ break;
1062
+ }
1063
+ }
1064
+ const completed = records[completedIndex]!;
1065
+ return { runId, version, branch: `release/${version}`, fromNode: completed.from ?? opts.from ?? RECOVER_FIRST_NODE,
1066
+ stages: records.slice(cycleStart, completedIndex + 1).filter(matchesPick), duplicate: true };
1067
+ }
1068
+ }
1069
+ }
1070
+ }
1071
+ const result = await recoverReleaseRunLocked({ runId, pick,
1072
+ ...(opts.from === undefined ? {} : { from: opts.from }),
1073
+ ...(opts.commandRoot === undefined ? {} : { commandRoot: opts.commandRoot }),
1074
+ ...(opts.partial === undefined ? {} : { partial: opts.partial }),
1075
+ ...(opts.repoRoot === undefined ? {} : { repoRoot: opts.repoRoot }) }, deps, root);
1076
+ return { ...result, duplicate: false };
1077
+ }
@@ -42,7 +42,10 @@ export async function runTrafficNode(node = process.argv[2], env: NodeJS.Process
42
42
  return finishNode(node!, version, { outcome: 'fail', verdict: 'fail', summary });
43
43
  }
44
44
  const result = await applyReleaseTrafficEvent(context, event, options);
45
- if (!result.applied) {
45
+ // Replaying the terminal restore after this run already restored its pre-cut traffic is a successful no-op.
46
+ const alreadyRestored = event === 'failed' && result.reason === 'already-restored';
47
+ const applied = result.applied || alreadyRestored;
48
+ if (!applied) {
46
49
  const consequence = event === 'failed' && result.reason === 'published-keeps-full'
47
50
  ? 'npm 발행은 완료됐으므로 전체 트래픽을 유지합니다. 후속 발행 단계 실패를 확인하세요.'
48
51
  : event === 'verify-complete' || event === 'npm-published'
@@ -52,8 +55,8 @@ export async function runTrafficNode(node = process.argv[2], env: NodeJS.Process
52
55
  : 'gate는 성공했으나 트래픽 감속이 적용되지 않았습니다.';
53
56
  (deps.report ?? reportFailure)(`RELEASE-POSTPUB-TRAFFIC ${version} ${runId || 'unknown'} ${node} 무시 — ${result.reason ?? 'traffic state unchanged'}. ${consequence}`);
54
57
  }
55
- return finishNode(node!, version, { outcome: result.applied ? 'ok' : 'fail', verdict: result.applied ? 'pass' : 'fail',
56
- summary: `${event} ${result.applied ? 'applied' : result.reason ?? 'ignored'}` });
58
+ return finishNode(node!, version, { outcome: applied ? 'ok' : 'fail', verdict: applied ? 'pass' : 'fail',
59
+ summary: `${event} ${alreadyRestored ? 'already-restored' : applied ? 'applied' : result.reason ?? 'ignored'}` });
57
60
  } catch (error) {
58
61
  const detail = errorResult(error).summary;
59
62
  const isLockTimeout = detail.startsWith('traffic lock timeout:');
@@ -49,6 +49,7 @@ export interface ReleaseLoopConfig {
49
49
  export interface ReleaseRunInput extends ReleaseLoopConfig {
50
50
  version: string;
51
51
  previousVersion: string;
52
+ triggerEvent?: { id: string; type: 'release.cut.due'; version: string; cutAt: string; at: string };
52
53
  cutCommit?: string;
53
54
  /** Required for the pod executor (the default); a host-executor run may have none. */
54
55
  gatePodPool?: string;
@@ -143,7 +144,7 @@ export function buildReleaseRunInput(version: string, deps: UnattendedReleaseDep
143
144
 
144
145
  /** Fail closed at the entry boundary, before any graph node can change a release. */
145
146
  export async function runUnattendedRelease(
146
- opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; forceNew?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string },
147
+ opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; forceNew?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string; triggerEvent?: ReleaseRunInput['triggerEvent'] },
147
148
  deps: UnattendedReleaseDeps = {},
148
149
  ): Promise<{ input: ReleaseRunInput; dryRun: boolean; state?: GraphRunState }> {
149
150
  // A dry run only builds the input and mutates nothing, so it neither creates nor waits on the OP-seat lock.
@@ -154,7 +155,7 @@ export async function runUnattendedRelease(
154
155
  }
155
156
 
156
157
  async function runUnattendedReleaseLocked(
157
- opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; forceNew?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string },
158
+ opts: { version: string; dryRun?: boolean; cutCommit?: string; forceFreeze?: boolean; forceNew?: boolean; mainCut?: boolean; prerelease?: PrereleaseKind; publishAt?: string; gateExecutor?: string; gateHost?: string; triggerEvent?: ReleaseRunInput['triggerEvent'] },
158
159
  deps: UnattendedReleaseDeps,
159
160
  ): Promise<{ input: ReleaseRunInput; dryRun: boolean; state?: GraphRunState }> {
160
161
  // RELEASE-BRANCH (10-06): the default cut is a release branch, so main keeps landing and the run no longer needs a
@@ -171,6 +172,7 @@ async function runUnattendedReleaseLocked(
171
172
  }
172
173
  const version = resolveRunVersion(opts.version, opts.prerelease, deps);
173
174
  const input = buildReleaseRunInput(version, deps, opts.cutCommit, { executor: opts.gateExecutor, host: opts.gateHost });
175
+ if (opts.triggerEvent) input.triggerEvent = opts.triggerEvent;
174
176
  if (opts.publishAt !== undefined) {
175
177
  const invalid = publishAtError(opts.publishAt);
176
178
  if (invalid) throw new Error(invalid);
@@ -0,0 +1,20 @@
1
+ /**
2
+ * SHADOW-MODEL-ARMS(0.2.44 칸) · 저작 단계 그림자 «1팔» probe — 명시 실행 전용 스크립트.
3
+ *
4
+ * 저작(goal-author) 단계 그림자 1팔을 `planShadowArms` 일일 상한 안에서 «실제 호출»해
5
+ * 난이도·모델·예상/실제 비용·결과를 한 줄 원장 형식으로 stdout 에 출력한다.
6
+ * ⛔ 관측만 한다 — 라이브 LLM(Claude 구독) 호출 0 · 골/PR/착지 파일 쓰기 0.
7
+ * ⛔ 자동 런 훅과 다른 단계(implement·review·judge) 팔은 후속 조각이다.
8
+ *
9
+ * 사용(저장소 루트에서): bun scripts/shadow-authoring-probe.ts
10
+ */
11
+ import { probeAuthoringShadowArm } from '../src/self-implement/goal-author.js';
12
+
13
+ /** 명시 실행 probe — 생산 저작 probe 경로(probeAuthoringShadowArm ⊕ probeShadowArm ⊕ planShadowArms)를 그대로 지나 한 줄을 낸다. */
14
+ export function runShadowAuthoringProbe(authorRunId = `shadow-authoring-probe-${new Date().toISOString().slice(0, 10)}`): string {
15
+ return probeAuthoringShadowArm(authorRunId).line;
16
+ }
17
+
18
+ if (import.meta.main) {
19
+ console.log(runShadowAuthoringProbe());
20
+ }
package/scripts/ux-sim.ts CHANGED
@@ -15,6 +15,7 @@
15
15
  // bun scripts/ux-sim.ts --list-trajectories # 저장한 궤적과 출처 목록
16
16
  // bun scripts/ux-sim.ts --fault cred-expiry # 결함 주입: grok 구독 만료 임박 × 갱신 결과 → 디스패처·발사 판정
17
17
  // bun scripts/ux-sim.ts --fault pod-death # 결함 주입: PARTIAL 줄을 남긴 Pod 가 SIGTERM 으로 지워짐 → 호스트 재방출 판정
18
+ // bun scripts/ux-sim.ts --fault pod-child-result # 결함 주입: Completed Pod 안의 report-deficit child 결과 보존
18
19
  // bun scripts/ux-sim.ts --fault pool-cap # 결함 주입: --pod-pool 에 :N 이 빠진 풀 → 승인 판정(limitedBy)
19
20
  // bun scripts/ux-sim.ts --fault sqlite-busy # 결함 주입: 실제 SQLite 잠금 → 로그 배치 버퍼·복구
20
21
  // bun scripts/ux-sim.ts emit child-error-long --json # 사건 주입(L0): 격리 우주 원장에 주입 줄 → 소비자 목록
@@ -128,7 +129,7 @@ if (argv[0] === 'seat-seq') {
128
129
  // ***영영 모른다*** — 오늘 이 저장소가 같은 함정을 다른 도구에서 이미 한 번 고쳤다.
129
130
  // ⛔ 그래서 「알려진 플래그」를 «한 곳»에 두고, 그 밖의 `--` 인자는 거부한다.
130
131
  const KNOWN_FLAGS = new Set([
131
- '--list', '--list-trajectories', '--computer-use', '--trajectory', '--from-run',
132
+ '--list', '--list-trajectories', '--computer-use', '--trajectory', '--from-run', '--seminar-rehearsal',
132
133
  '--save-trajectory', '--esc', '--queue', '--width', '--height', '--draft', '--fault',
133
134
  ]);
134
135
  {
@@ -142,6 +143,17 @@ const KNOWN_FLAGS = new Set([
142
143
  }
143
144
  if (argv.includes('--list')) { console.log([...PHASES, 'computer-use: normal | capture-stalls | capture-fails | target-missing'].join('\n')); process.exit(0); }
144
145
 
146
+ if (argv.includes('--seminar-rehearsal')) {
147
+ if (argv.length !== 1) {
148
+ console.error('⛔ --seminar-rehearsal 는 단독 모드다');
149
+ process.exit(2);
150
+ }
151
+ const { renderSeminarRehearsal, seminarRehearsalSweep } = await import('../src/ux-sim/seminar-rehearsal.js');
152
+ const result = seminarRehearsalSweep();
153
+ console.log(renderSeminarRehearsal(result).join('\n'));
154
+ process.exit(result.verdict === 'pass' ? 0 : 1);
155
+ }
156
+
145
157
  {
146
158
  // `--fault=<이름>` 꼴도 받는다 — KNOWN_FLAGS 는 등호 꼴을 통과시키므로 여기서 놓치면 조용히 기본 국면으로 빠진다.
147
159
  const eq = argv.find((a) => a.startsWith('--fault='));
@@ -159,6 +171,11 @@ if (argv.includes('--fault')) {
159
171
  console.log(renderPodDeath(simPodDeath()).join('\n'));
160
172
  process.exit(0);
161
173
  }
174
+ if (fault === 'pod-child-result') {
175
+ const { podChildResultScenario, renderPodChildResult } = await import('../src/ux-sim/fault-pod-child-result.js');
176
+ console.log(renderPodChildResult(podChildResultScenario()).join('\n'));
177
+ process.exit(0);
178
+ }
162
179
  if (fault === 'pool-cap') {
163
180
  const { poolCapSweep, renderPoolCap } = await import('../src/ux-sim/fault-pool-cap.js');
164
181
  console.log(renderPoolCap(poolCapSweep()).join('\n'));
@@ -169,7 +186,7 @@ if (argv.includes('--fault')) {
169
186
  console.log(renderSqliteBusy(simSqliteBusy()).join('\n'));
170
187
  process.exit(0);
171
188
  }
172
- console.error(`⛔ 모르는 결함이다: ${fault ?? '(없음)'} — 아는 것: cred-expiry · pod-death · pool-cap · sqlite-busy`);
189
+ console.error(`⛔ 모르는 결함이다: ${fault ?? '(없음)'} — 아는 것: cred-expiry · pod-death · pod-child-result · pool-cap · sqlite-busy`);
173
190
  process.exit(2);
174
191
  }
175
192
 
@@ -57,6 +57,13 @@ import { resolveSessionSurfaceProfile } from '../session-runtime/index.js';
57
57
  import { classifyTuiChatIntent, formatTuiRouteLine, isSeatOpsDirective, type TuiChatRoute } from '../core-turn/short-question.js';
58
58
  import { HARNESS_ROLE_ENV } from '../harness/harness-space.js';
59
59
  import { createReasoningThoughtBuffer } from './reasoning-thought-buffer.js';
60
+ import {
61
+ REQUEST_SIZE_MAX_CHARS,
62
+ createRequestSizeGuard,
63
+ estimateRequestChars,
64
+ formatRequestSizeStatus,
65
+ type RequestSizeGuard,
66
+ } from '../session/request-size-guard.js';
60
67
 
61
68
  const FACT_QUESTION_INSTRUCTION = '사실·최신 정보 질문이다. WebSearch 를 1~2회 쓰고 검색 결과(제목·스니펫·URL)로 답하라. 출처 링크를 붙여라. 셸·브라우저·파일 도구는 검색 결과로 부족할 때만. 도구 예산에 닿으면 지금까지 근거로 답하고 끝에 «더 찾아볼까요?»를 붙여라.';
62
69
 
@@ -143,6 +150,18 @@ export interface CoreTurnBridgeDeps {
143
150
  /** TUI-H1-SEAT-GOALLOOP — the seat this TUI works for (`detectSeatTui`), read per turn. null/absent = a human
144
151
  * conversation TUI (routing unchanged). A seat TUI sends operational directives to the goal loop. */
145
152
  resolveSeat?: () => string | null;
153
+ /** TUI-TOKEN-GUARD-WIRE — host write-back for the #32254 request-size cap.
154
+ * Compacts the host's own history store (the one `getMessages` reads) in place
155
+ * so the next prompt does not reload the original. The bridge re-reads
156
+ * `getMessages` after `fired:true`. Only consulted on `tuiRouting` turns. */
157
+ compactPersistedHistory?: (ctx: {
158
+ sessionId: string;
159
+ userText: string;
160
+ requestChars: number;
161
+ maxChars: number;
162
+ }) => Promise<{ fired: boolean; reason: string }>;
163
+ /** Override the request-size cap (tests). Defaults to `REQUEST_SIZE_MAX_CHARS`. */
164
+ requestSizeMaxChars?: number;
146
165
  }
147
166
 
148
167
  /** Default abort-poll cadence. 50ms = 20 Hz: responsive without
@@ -224,7 +243,7 @@ export function bridgeCoreTurnToAcp(
224
243
  (poll as unknown as { unref?: () => void }).unref?.();
225
244
 
226
245
  try {
227
- const messages = await Promise.resolve(
246
+ let messages = await Promise.resolve(
228
247
  deps.getMessages({
229
248
  sessionId: turnCtx.sessionId,
230
249
  userText: turnCtx.userText,
@@ -318,9 +337,71 @@ export function bridgeCoreTurnToAcp(
318
337
  }
319
338
  const explicitMaxToolTurns = deps.resolveMaxToolTurns?.({ sessionId: turnCtx.sessionId });
320
339
  const maxToolTurns = explicitMaxToolTurns ?? (factQuestion ? getUserConfig().chat.factQuestion.maxToolTurns : undefined);
321
- const turnMessages: LLMMessage[] = factQuestion
322
- ? [{ role: 'system', content: FACT_QUESTION_INSTRUCTION }, ...messages]
323
- : messages;
340
+ const withFactInstruction = (seed: LLMMessage[]): LLMMessage[] => factQuestion
341
+ ? [{ role: 'system', content: FACT_QUESTION_INSTRUCTION }, ...seed]
342
+ : seed;
343
+ let turnMessages: LLMMessage[] = withFactInstruction(messages);
344
+ // TUI-TOKEN-GUARD-WIRE — exact serialized provider measurement owns
345
+ // first-request compaction; the seed estimate is telemetry only. This
346
+ // keeps turn-0 history untouched until compactFirstRequest writes back.
347
+ let requestSizeGuard: RequestSizeGuard | undefined;
348
+ if (deps.tuiRouting === true) {
349
+ const maxChars = deps.requestSizeMaxChars ?? REQUEST_SIZE_MAX_CHARS;
350
+ let historyCompacted = false;
351
+ const compactHistory = async (requestChars: number, stage: 'first-request') => {
352
+ if (!deps.compactPersistedHistory || historyCompacted) return false;
353
+ let fired = false;
354
+ let reason = 'no-op';
355
+ try {
356
+ const result = await deps.compactPersistedHistory({
357
+ sessionId: turnCtx.sessionId, userText: turnCtx.userText, requestChars, maxChars,
358
+ });
359
+ fired = result.fired;
360
+ reason = result.reason;
361
+ historyCompacted = fired;
362
+ } catch (error) {
363
+ reason = 'compaction-error';
364
+ debug.log('llm.request', 'request-size-compact-error', {
365
+ stage, requestChars, maxChars, message: error instanceof Error ? error.message : String(error),
366
+ }, { level: 'warn' });
367
+ }
368
+ return { fired, reason };
369
+ };
370
+ const estimatedSeedChars = estimateRequestChars(turnMessages, tools);
371
+ debug.log('llm.request', 'request-size-compact', {
372
+ stage: 'estimate', sessionId: turnCtx.sessionId,
373
+ beforeChars: estimatedSeedChars, maxChars,
374
+ compacted: false, reason: 'awaiting-exact-wire-measurement',
375
+ });
376
+ requestSizeGuard = createRequestSizeGuard({
377
+ maxChars,
378
+ compactOptions: () => {
379
+ const guardModel = modelOverride ?? getUserConfig().llm?.model;
380
+ const guardConfig = getUserConfig().chat;
381
+ const preserveLastN = guardConfig?.autoCompact?.preserveLastN;
382
+ const archiveEnabled = guardConfig?.compact?.archiveEnabled;
383
+ return {
384
+ sessionId: turnCtx.sessionId,
385
+ ...(guardModel ? { activeModelId: guardModel } : {}),
386
+ ...(preserveLastN !== undefined ? { preserveLastN } : {}),
387
+ ...(archiveEnabled !== undefined ? { archiveEnabled } : {}),
388
+ };
389
+ },
390
+ // The preflight estimate missed (wire over cap, seed under): still write the
391
+ // compaction back so the next prompt starts small, then compact this request live.
392
+ compactFirstRequest: async (_current, info) => {
393
+ await compactHistory(info.requestChars, 'first-request');
394
+ return null;
395
+ },
396
+ onMeasured: (measurement) => {
397
+ if (!measurement.compacted) return;
398
+ void turnCtx.pushSessionUpdate(
399
+ { sessionUpdate: 'agent_thought_chunk', content: { type: 'text', text: formatRequestSizeStatus(measurement) } },
400
+ { status: true },
401
+ );
402
+ },
403
+ });
404
+ }
324
405
  let toolCallCount = 0;
325
406
  const toolKinds = new Set<string>();
326
407
  const observeToolBudget = () => {
@@ -434,6 +515,7 @@ export function bridgeCoreTurnToAcp(
434
515
  ...(modelOverride !== undefined ? { modelOverride } : {}),
435
516
  ...(autohealProvider ?? {}),
436
517
  ...(maxToolTurns !== undefined ? { maxToolTurns } : {}),
518
+ ...(requestSizeGuard ? { requestSizeGuard } : {}),
437
519
  ...((!factQuestion || explicitMaxToolTurns !== undefined) && deps.budgetGrant !== undefined ? { budgetGrant: deps.budgetGrant } : {}),
438
520
  callbacks: {
439
521
  onStatus: (line) => {