elanous 0.2.27 → 0.2.29

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 (700) 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/{Ev2jivDMTSoEc-5rIXdcy → cIpv5nU9AycwYWZI9H589}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{ab4d57c2.e90bc2cb31949045.js → 058a98ba.7eb28d5e6dc03565.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{4565-67e4c620597965c8.js → 1015-9cba22a5a4554797.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +8 -0
  9. package/apps/pwa/out/_next/static/chunks/{1516.83dd2c1b86b4e507.js → 1142.65d002789ab3af7d.js} +2 -2
  10. package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +34 -0
  12. package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1516.dfaceff3fd2d0e0d.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +286 -0
  16. package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +24 -0
  17. package/apps/pwa/out/_next/static/chunks/1782-59db1b5aa06df38a.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{1743.563d3168e95825ef.js → 1852.7f7b53991fcb99ef.js} +2 -2
  19. package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +36 -0
  22. package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +64 -0
  24. package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{65ebff95.081daeff622d238e.js → 285adb1a.5654e605dddf86d2.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +115 -0
  31. package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3160-95c96f4d2a21dd26.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +90 -0
  36. package/apps/pwa/out/_next/static/chunks/328bb3ab-6628a1114fe3fb3b.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{9917-9e26abc5f7772735.js → 3396-97b97928c49190c9.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/{6196.34d6b229079e9e28.js → 3403.7199205e65124486.js} +1 -1
  40. package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/419.736c0d6f426249a7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{6def8a8e.c81f9ca41028eccf.js → 425cfc4d.fb91158e3971c39f.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/{16e57f67.3ea19e893461e611.js → 46bd8bea.2f4b4099172fcdb7.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/{5081.a240b63fad28663a.js → 4759.1f76713aefb87db5.js} +1 -1
  51. package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +94 -0
  54. package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +62 -0
  60. package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +27 -0
  63. package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +104 -0
  64. package/apps/pwa/out/_next/static/chunks/{9974.e77b4ff4884557b3.js → 5591.a35e7a217734a8b9.js} +2 -2
  65. package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +93 -0
  66. package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/{5492-e05e26a033ba80d2.js → 6013-2f769370d8b4c2c6.js} +3 -3
  69. package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +24 -0
  70. package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +2 -0
  72. package/apps/pwa/out/_next/static/chunks/{5408.377c8c543635b81f.js → 6534.1ab00f370db7b105.js} +1 -1
  73. package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +148 -0
  74. package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +149 -0
  75. package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +79 -0
  77. package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/{8578.dff22d988cc2b106.js → 6767.1fcfc9b8be83975f.js} +16 -16
  79. package/apps/pwa/out/_next/static/chunks/6776.06ff1e3b464cc607.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/{9311.24c8f5ea793253dd.js → 6853.cc5174a9dee59593.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +287 -0
  86. package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/{94.4cfed21c0b781a06.js → 7375.050ea0d72968e49f.js} +16 -16
  92. package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +77 -0
  94. package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +74 -0
  97. package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7725-4f83d5541fbdb81b.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8332.6f0f49df772e163b.js +23 -0
  102. package/apps/pwa/out/_next/static/chunks/{7483.ba01c6c209b81bba.js → 8398.73a19b39715eda04.js} +1 -1
  103. package/apps/pwa/out/_next/static/chunks/{2846.d6a433b8663819a5.js → 8471.8d2a8c74f09c36ff.js} +3 -3
  104. package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +226 -0
  106. package/apps/pwa/out/_next/static/chunks/{5785-ea8d2c633b6688e3.js → 8767-2f6a634f5abeaa01.js} +1 -1
  107. package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +32 -0
  109. package/apps/pwa/out/_next/static/chunks/8795.32573a185af18c7b.js +41 -0
  110. package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{4593.10f5b9bd702d4a6c.js → 9143.ff14585db1d275ff.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{4204.a409ab6250c0f6a8.js → 9907.49be0fcadaf214b5.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{973cbf1b.3bbcf2b41548eca7.js → a435ad95.577add051b4facb2.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-a5635eba0d73b84e.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/{page-ff27902d0b11ef4f.js → page-8aaa6dedc4c10dfb.js} +1 -1
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/{page-25a302273b054fd7.js → page-33bf667a5fb297bf.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-29900ed0011b2c83.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-87b88f551f421d8b.js → page-9eb56166774eb256.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9f92737b8766009a.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{f4dfbfc0.a69fb12f854882aa.js → bc324b7c.02a09dd93f6a399b.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +122 -0
  177. package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +1 -0
  183. package/apps/pwa/out/approvals/index.html +1 -1
  184. package/apps/pwa/out/approvals/index.txt +22 -22
  185. package/apps/pwa/out/autopilot/index.html +1 -1
  186. package/apps/pwa/out/autopilot/index.txt +22 -22
  187. package/apps/pwa/out/board/index.html +1 -1
  188. package/apps/pwa/out/board/index.txt +22 -22
  189. package/apps/pwa/out/botlab/index.html +1 -1
  190. package/apps/pwa/out/botlab/index.txt +21 -21
  191. package/apps/pwa/out/bots/index.html +1 -1
  192. package/apps/pwa/out/bots/index.txt +21 -21
  193. package/apps/pwa/out/ceo/index.html +1 -1
  194. package/apps/pwa/out/ceo/index.txt +22 -22
  195. package/apps/pwa/out/chat/index.html +1 -1
  196. package/apps/pwa/out/chat/index.txt +21 -21
  197. package/apps/pwa/out/consult/index.html +1 -1
  198. package/apps/pwa/out/consult/index.txt +22 -22
  199. package/apps/pwa/out/control/index.html +1 -1
  200. package/apps/pwa/out/control/index.txt +22 -22
  201. package/apps/pwa/out/decisions/index.html +1 -1
  202. package/apps/pwa/out/decisions/index.txt +21 -21
  203. package/apps/pwa/out/design-check/index.html +1 -1
  204. package/apps/pwa/out/design-check/index.txt +22 -22
  205. package/apps/pwa/out/editor/index.html +1 -1
  206. package/apps/pwa/out/editor/index.txt +22 -22
  207. package/apps/pwa/out/exec/index.html +1 -1
  208. package/apps/pwa/out/exec/index.txt +22 -22
  209. package/apps/pwa/out/field/index.html +1 -1
  210. package/apps/pwa/out/field/index.txt +22 -22
  211. package/apps/pwa/out/healthz +1 -1
  212. package/apps/pwa/out/index.html +1 -1
  213. package/apps/pwa/out/index.txt +21 -21
  214. package/apps/pwa/out/inside/index.html +1 -1
  215. package/apps/pwa/out/inside/index.txt +21 -21
  216. package/apps/pwa/out/intake/index.html +1 -1
  217. package/apps/pwa/out/intake/index.txt +22 -22
  218. package/apps/pwa/out/live/index.html +1 -1
  219. package/apps/pwa/out/live/index.txt +22 -22
  220. package/apps/pwa/out/live-run/index.html +1 -1
  221. package/apps/pwa/out/live-run/index.txt +22 -22
  222. package/apps/pwa/out/loops/index.html +1 -1
  223. package/apps/pwa/out/loops/index.txt +21 -21
  224. package/apps/pwa/out/market/index.html +1 -1
  225. package/apps/pwa/out/market/index.txt +21 -21
  226. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  227. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  228. package/apps/pwa/out/morning/index.html +1 -1
  229. package/apps/pwa/out/morning/index.txt +22 -22
  230. package/apps/pwa/out/observatory/index.html +1 -1
  231. package/apps/pwa/out/observatory/index.txt +22 -22
  232. package/apps/pwa/out/ops/checklist/index.html +1 -1
  233. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  234. package/apps/pwa/out/ops/release/index.html +1 -1
  235. package/apps/pwa/out/ops/release/index.txt +21 -21
  236. package/apps/pwa/out/ops/seats/index.html +1 -1
  237. package/apps/pwa/out/ops/seats/index.txt +21 -21
  238. package/apps/pwa/out/outputs/index.html +1 -1
  239. package/apps/pwa/out/outputs/index.txt +21 -21
  240. package/apps/pwa/out/reflection/index.html +1 -1
  241. package/apps/pwa/out/reflection/index.txt +22 -22
  242. package/apps/pwa/out/scheduler/index.html +1 -1
  243. package/apps/pwa/out/scheduler/index.txt +22 -22
  244. package/apps/pwa/out/sessions/index.html +1 -1
  245. package/apps/pwa/out/sessions/index.txt +21 -21
  246. package/apps/pwa/out/settings/devices/index.html +1 -1
  247. package/apps/pwa/out/settings/devices/index.txt +22 -22
  248. package/apps/pwa/out/settings/index.html +1 -1
  249. package/apps/pwa/out/settings/index.txt +22 -22
  250. package/apps/pwa/out/setup/done/index.html +1 -1
  251. package/apps/pwa/out/setup/done/index.txt +22 -22
  252. package/apps/pwa/out/setup/index.html +1 -1
  253. package/apps/pwa/out/setup/index.txt +22 -22
  254. package/apps/pwa/out/share/index.html +1 -1
  255. package/apps/pwa/out/share/index.txt +22 -22
  256. package/apps/pwa/out/showroom/index.html +1 -1
  257. package/apps/pwa/out/showroom/index.txt +21 -21
  258. package/apps/pwa/out/tasks/index.html +1 -1
  259. package/apps/pwa/out/tasks/index.txt +22 -22
  260. package/apps/pwa/out/term/index.html +1 -1
  261. package/apps/pwa/out/term/index.txt +22 -22
  262. package/apps/pwa/out/today/index.html +1 -1
  263. package/apps/pwa/out/today/index.txt +22 -22
  264. package/apps/pwa/out/trace/index.html +1 -1
  265. package/apps/pwa/out/trace/index.txt +22 -22
  266. package/apps/pwa/out/vault/index.html +1 -1
  267. package/apps/pwa/out/vault/index.txt +22 -22
  268. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  269. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  270. package/apps/pwa/out/workflows/index.html +1 -1
  271. package/apps/pwa/out/workflows/index.txt +22 -22
  272. package/apps/pwa/out/workspace/index.html +1 -1
  273. package/apps/pwa/out/workspace/index.txt +22 -22
  274. package/apps/pwa/out/worktrees/index.html +1 -1
  275. package/apps/pwa/out/worktrees/index.txt +22 -22
  276. package/graphs/implement-loop.yaml +38 -1
  277. package/graphs/release/release-loop.yaml +6 -2
  278. package/graphs/steward/recipes.yaml +6 -0
  279. package/graphs/steward/release-day.yaml +23 -0
  280. package/graphs/steward/steward.yaml +9 -1
  281. package/graphs/work/code-pr.yaml +23 -0
  282. package/package.json +1 -1
  283. package/plugins/agent-team/agents/research.md +1 -0
  284. package/scripts/browser-observe-cycle.ts +76 -2
  285. package/scripts/ci-typecheck-changed.ts +53 -19
  286. package/scripts/coord-channel-watch.sh +26 -6
  287. package/scripts/coord-role-pack.ts +143 -0
  288. package/scripts/detect-test-interference.ts +31 -1
  289. package/scripts/lib/morning-report-options.ts +41 -0
  290. package/scripts/pr-land-extra-remote-gates.ts +49 -0
  291. package/scripts/release-loop/docs-node.ts +51 -22
  292. package/scripts/release-loop/gate-batch-safe.ts +23 -0
  293. package/scripts/release-loop/gate-history.ts +422 -0
  294. package/scripts/release-loop/gate-node.ts +336 -39
  295. package/scripts/release-loop/gate-triage-node.ts +190 -0
  296. package/scripts/release-loop/node-verdict.ts +3 -1
  297. package/scripts/release-loop/publish-node.ts +3 -0
  298. package/scripts/release-loop/spawn-lane.ts +68 -0
  299. package/scripts/release-loop/tui-node-checks.ts +28 -2
  300. package/scripts/release-loop/version-node.ts +62 -4
  301. package/scripts/skills/public-check.ts +5 -2
  302. package/scripts/test-deterministic.ts +549 -37
  303. package/scripts/usage-rollup.ts +11 -3
  304. package/scripts/ux-sim.ts +7 -1
  305. package/scripts/verify-kpack6-live.ts +230 -0
  306. package/src/acp/codex-plugins.ts +17 -0
  307. package/src/acp/core-turn-bridge.ts +98 -22
  308. package/src/acp/elanous-extensions.ts +2 -0
  309. package/src/acp/server.ts +2 -0
  310. package/src/agent/ref-grounding.ts +18 -0
  311. package/src/agent/task-notification.ts +2 -1
  312. package/src/agent-mission/in-agent-plugin.ts +8 -3
  313. package/src/agent-substrate/pr-reviewer.ts +29 -21
  314. package/src/agent-substrate/self-review-cli.ts +34 -10
  315. package/src/briefing/brief-items.ts +151 -35
  316. package/src/budget/llm-cost.ts +25 -2
  317. package/src/budget/pty-usage-reemit.ts +7 -0
  318. package/src/budget/run-usage-rollup.ts +9 -0
  319. package/src/budget/usage-daily-store.ts +98 -0
  320. package/src/budget/usage-outcomes.ts +32 -0
  321. package/src/capture/tui-self-report.ts +22 -4
  322. package/src/chat/index.ts +31 -10
  323. package/src/chat/pickers/modal-runtime.ts +1 -0
  324. package/src/chat/pickers/modals.ts +3 -1
  325. package/src/chat/turn-typeahead.ts +123 -16
  326. package/src/claims/claims-ledger.ts +23 -0
  327. package/src/claims/claims-render.ts +22 -2
  328. package/src/cli/brief-cli.ts +131 -10
  329. package/src/cli/claims-cli.ts +24 -4
  330. package/src/cli/dashboard-name-flag.ts +48 -0
  331. package/src/cli/doctor-cli.ts +80 -0
  332. package/src/cli/log-event-names.ts +12 -0
  333. package/src/cli/msg-cli.ts +210 -11
  334. package/src/cli/plugin-cli.ts +11 -3
  335. package/src/cli/pr-cli.ts +443 -104
  336. package/src/cli/pr-land-heavy-remote.ts +233 -0
  337. package/src/cli/pr-land-overlap-evidence.ts +104 -5
  338. package/src/cli/pr-land-refusal.ts +20 -0
  339. package/src/cli/pty-takeover-cli.ts +125 -16
  340. package/src/cli/release-cli.ts +46 -2
  341. package/src/cli/remote-resolve.ts +2 -1
  342. package/src/cli/rfc-cli.ts +24 -0
  343. package/src/cli/seat-cli.ts +26 -16
  344. package/src/cli/tailscale-serve.ts +5 -8
  345. package/src/cli/tasks-cli.ts +400 -27
  346. package/src/cli/usage-cli.ts +155 -16
  347. package/src/cli/usage-daily-cli.ts +84 -0
  348. package/src/context-bus/context-now.ts +82 -5
  349. package/src/core-turn/auth-rejected-notice.ts +41 -0
  350. package/src/core-turn/run-core-turn.ts +13 -2
  351. package/src/core-turn/run-goal-loop.ts +17 -1
  352. package/src/core-turn/short-question.ts +45 -12
  353. package/src/core-turn/types.ts +7 -0
  354. package/src/dashboard/acp-active-model.ts +40 -0
  355. package/src/dashboard/auto-compact-runtime.ts +2 -0
  356. package/src/dashboard/boot-banner.ts +80 -0
  357. package/src/dashboard/dashboard-status-lines.ts +11 -0
  358. package/src/dashboard/detail-viewer-runtime.ts +15 -2
  359. package/src/dashboard/event-loop-stall-monitor.ts +4 -0
  360. package/src/dashboard/first-screen-band.ts +63 -13
  361. package/src/dashboard/goal-loop-thinking.ts +16 -0
  362. package/src/dashboard/hitl-boot.ts +9 -4
  363. package/src/dashboard/index.ts +235 -389
  364. package/src/dashboard/input/chat-main-entry-runtime.ts +2 -0
  365. package/src/dashboard/input/chat-main-log-actions.ts +4 -0
  366. package/src/dashboard/input/chat-main-log-command.ts +12 -1
  367. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +172 -3
  368. package/src/dashboard/input/chat-main-session.ts +6 -2
  369. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  370. package/src/dashboard/input/chat-main-turn.ts +2 -1
  371. package/src/dashboard/input/compact-prepass-recovery.ts +97 -0
  372. package/src/dashboard/input/dashboard-chord-actions.ts +10 -1
  373. package/src/dashboard/input/dashboard-chord-runtime.ts +2 -0
  374. package/src/dashboard/input/external-input-host.ts +45 -0
  375. package/src/dashboard/input/log-fold-binding.ts +18 -0
  376. package/src/dashboard/input/mouse-wiring.ts +17 -4
  377. package/src/dashboard/input/turn-steer-bridge.ts +94 -0
  378. package/src/dashboard/log-click-runtime.ts +5 -3
  379. package/src/dashboard/running-build-status.ts +74 -0
  380. package/src/dashboard/seat-boot-preamble.ts +113 -0
  381. package/src/dashboard/seat-local-instructions.ts +305 -0
  382. package/src/dashboard/skill-detection-runtime.ts +24 -4
  383. package/src/dashboard/slash-runtime/dashboard-handlers.ts +100 -28
  384. package/src/dashboard/slash-runtime/model-choices.ts +35 -0
  385. package/src/dashboard/term-slash-runtime.ts +15 -0
  386. package/src/dashboard/turn-preamble.ts +30 -2
  387. package/src/dashboard/turn-session-layers.ts +176 -0
  388. package/src/dashboard/turn-stream-formatter.ts +14 -6
  389. package/src/dashboard/turn-stream-presentation-applier.ts +8 -0
  390. package/src/domains/morning-report.ts +3 -1
  391. package/src/domains/release-tool.ts +8 -9
  392. package/src/domains/surface-events.ts +4 -1
  393. package/src/domains/watch-default-scheduler.ts +8 -9
  394. package/src/fold-stack.ts +24 -1
  395. package/src/git-fs/dirty.ts +32 -4
  396. package/src/git-fs/index.ts +43 -1
  397. package/src/github/pr-labels.ts +10 -4
  398. package/src/graph-runner/runner.ts +102 -14
  399. package/src/harness/harness-clean.ts +21 -3
  400. package/src/harness/harness-cli-command.ts +22 -6
  401. package/src/harness/harness-gc.ts +32 -5
  402. package/src/harness/harness-pod-dispatch.ts +11 -4
  403. package/src/hq/seats.ts +17 -3
  404. package/src/index.ts +48 -6
  405. package/src/input/external-input-queue.ts +219 -0
  406. package/src/intelligence-map/model-bench-scores.ts +102 -0
  407. package/src/interactive-terminal-modal.ts +13 -0
  408. package/src/llm/route-decision.ts +25 -0
  409. package/src/llm-stream-retry-display.ts +59 -0
  410. package/src/llm.ts +253 -55
  411. package/src/log-entry.ts +3 -3
  412. package/src/log-pane/search.ts +29 -4
  413. package/src/loops/agent-reply.ts +256 -0
  414. package/src/loops/budget.ts +37 -7
  415. package/src/loops/loop-cli.ts +3 -2
  416. package/src/loops/msg-address.ts +57 -0
  417. package/src/loops/msg-wake.ts +282 -0
  418. package/src/loops/orchestrator/inbox.ts +130 -0
  419. package/src/loops/orchestrator/resync-shadow.ts +100 -12
  420. package/src/loops/orchestrator/tick.ts +94 -3
  421. package/src/loops/registry.ts +42 -4
  422. package/src/maturity/feature-maturity.ts +1 -1
  423. package/src/memory.ts +20 -5
  424. package/src/msg/msg-sse-server.ts +141 -0
  425. package/src/msg/msg-store.ts +84 -14
  426. package/src/native-tool-catalog.ts +125 -0
  427. package/src/nexus/api/http-server.ts +5 -0
  428. package/src/nexus/api/ops-api.ts +2 -0
  429. package/src/nexus/api/project-autopsy.ts +127 -0
  430. package/src/nexus/api/terminals.ts +3 -0
  431. package/src/nexus/api/workflow-approvals.ts +2 -0
  432. package/src/nexus/onboarding/first-boot-wizard.ts +56 -2
  433. package/src/oauth/codex-account-store.ts +15 -3
  434. package/src/oauth/codex-billing-route.ts +31 -0
  435. package/src/ops/overview-collect.ts +19 -2
  436. package/src/panes/log-pane.ts +67 -8
  437. package/src/patents/ledger.ts +128 -0
  438. package/src/persona/presets.ts +44 -0
  439. package/src/plugins/install/market-fetch.ts +32 -1
  440. package/src/plugins/maker/wizard-generate.ts +6 -4
  441. package/src/pod-lease/admission.ts +116 -41
  442. package/src/preview/terminal.ts +14 -1
  443. package/src/prompt-cache/types.ts +2 -0
  444. package/src/prompt-enhance/enhance.ts +24 -8
  445. package/src/prompt-library/universal-preamble.ts +273 -56
  446. package/src/pty-shell/pty-control-ipc.ts +4 -1
  447. package/src/pty-shell/pty-manifest.ts +77 -5
  448. package/src/pty-shell/registry.ts +19 -2
  449. package/src/pty-shell/tui-run-state.ts +253 -0
  450. package/src/release-loop/checklist.ts +11 -0
  451. package/src/release-loop/light-rc.ts +28 -3
  452. package/src/release-loop/merged-pr-checklist.ts +24 -5
  453. package/src/release-loop/rehearsal.ts +1 -1
  454. package/src/release-loop/rubric.ts +70 -0
  455. package/src/render.ts +5 -1
  456. package/src/rfc-registry/registry.ts +88 -0
  457. package/src/seat-dispatch/seat-request-ledger.ts +4 -0
  458. package/src/seat-loop/knowhow-lint.ts +233 -0
  459. package/src/seat-loop/seat-pack.ts +16 -4
  460. package/src/seat-loop/seat-report.ts +42 -2
  461. package/src/seat-loop/traffic-signal.ts +7 -0
  462. package/src/self-dev/ask-launch-flow.ts +48 -8
  463. package/src/self-dev/ask-path-candidates.ts +69 -14
  464. package/src/self-dev/decompose-proposal.ts +43 -1
  465. package/src/self-dev/graph-journey-nodes.ts +2 -0
  466. package/src/self-dev/launch-preflight-text.ts +5 -1
  467. package/src/self-dev/launch-preflight.ts +143 -10
  468. package/src/self-dev/run-supervisor.ts +71 -5
  469. package/src/self-dev/shard-aggregate.ts +2 -0
  470. package/src/self-dev/shard-run.ts +23 -2
  471. package/src/self-health/signatures.ts +132 -0
  472. package/src/self-implement/doctor-visit.ts +118 -0
  473. package/src/self-implement/gate-cli.ts +17 -4
  474. package/src/self-implement/goal-author-decompose.ts +80 -16
  475. package/src/self-implement/goal-author.ts +116 -73
  476. package/src/self-implement/goal-authoring-grounding.ts +1 -1
  477. package/src/self-implement/goal-file-name.ts +65 -0
  478. package/src/self-implement/goal-new-paths.ts +4 -5
  479. package/src/self-implement/graph-authority.ts +17 -3
  480. package/src/self-implement/graph-yaml.ts +15 -7
  481. package/src/self-implement/ground-goal.ts +2 -1
  482. package/src/self-implement/headless-elanous-driver.ts +16 -1
  483. package/src/self-implement/host-regate.ts +58 -9
  484. package/src/self-implement/orchestrator.ts +3 -10
  485. package/src/self-implement/review-mustfix-class.ts +115 -0
  486. package/src/self-implement/rework-policy.ts +80 -2
  487. package/src/self-implement/run-ledger.ts +111 -7
  488. package/src/self-implement/running-runs.ts +10 -6
  489. package/src/self-implement/self-implement-runtime.ts +32 -0
  490. package/src/self-implement/speed-claims.ts +145 -6
  491. package/src/session/pending-input.ts +62 -11
  492. package/src/session-runtime/index.ts +7 -1
  493. package/src/skills/tools/ops-ledger.ts +707 -0
  494. package/src/skills/tools/persistent-grounding.ts +103 -8
  495. package/src/skills/tools/shell.ts +196 -2
  496. package/src/status/bar.ts +32 -2
  497. package/src/status/status-provider-info.ts +58 -0
  498. package/src/steward/rejudge-tick.ts +12 -1
  499. package/src/steward/release-day.ts +158 -0
  500. package/src/steward/resync-tick.ts +123 -0
  501. package/src/task-agent/actions.ts +1 -0
  502. package/src/task-agent/adopt-pr.ts +140 -0
  503. package/src/task-agent/board.ts +11 -1
  504. package/src/task-agent/card-evidence.ts +37 -5
  505. package/src/task-agent/cover.ts +84 -17
  506. package/src/task-agent/failure-notify.ts +61 -0
  507. package/src/task-agent/green-sweep.ts +170 -0
  508. package/src/task-agent/land-worktree.ts +52 -5
  509. package/src/task-agent/live-move-history.ts +1 -0
  510. package/src/task-agent/live-moves.ts +43 -12
  511. package/src/task-agent/parent-host.ts +1 -1
  512. package/src/task-agent/postland-card.ts +139 -0
  513. package/src/task-agent/rejudge-on-head.ts +109 -7
  514. package/src/task-agent/remote-rejudge-bind.ts +91 -0
  515. package/src/task-agent/repair-branch-cas.ts +182 -0
  516. package/src/task-agent/repair-cycle.ts +288 -0
  517. package/src/task-agent/repair-next-move.ts +31 -0
  518. package/src/task-agent/repair-review.ts +24 -0
  519. package/src/task-agent/repair-worker.ts +87 -0
  520. package/src/task-agent/review-result-capture.ts +2 -1
  521. package/src/task-agent/shadow.ts +13 -7
  522. package/src/task-agent/task-hand.ts +115 -6
  523. package/src/task-orchestrator/surfaces/kubectl-transient-retry.ts +51 -0
  524. package/src/task-orchestrator/surfaces/pod-command-job.ts +63 -7
  525. package/src/task-orchestrator/surfaces/pod-install-slots.ts +6 -11
  526. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +76 -0
  527. package/src/task-orchestrator/surfaces/pod-repair-commit.ts +96 -0
  528. package/src/task-orchestrator/surfaces/self-implement-pod.ts +175 -43
  529. package/src/telegram.ts +30 -1
  530. package/src/terminal/session-registry.ts +6 -0
  531. package/src/thinking-line.ts +12 -3
  532. package/src/tool-runtime/index.ts +4 -0
  533. package/src/tool-runtime/ops-ledger-runtimes.ts +84 -0
  534. package/src/tool-runtime/ref-consult-runtime.ts +17 -2
  535. package/src/tool-runtime/run-shell-runtime.ts +4 -1
  536. package/src/tool-runtime/self-cognition-runtimes.ts +5 -1
  537. package/src/tui.ts +5 -0
  538. package/src/user-config.ts +62 -7
  539. package/src/ux-sim/fake-llm.ts +29 -0
  540. package/src/ux-sim/fault-sqlite-busy.ts +50 -0
  541. package/src/ux-sim/in-process-cli.ts +175 -0
  542. package/src/version/packed-revision.json +1 -1
  543. package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +0 -36
  548. package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +0 -148
  550. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/1454-a9c338f5bb556f42.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +0 -27
  557. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +0 -24
  562. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +0 -32
  565. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +0 -34
  567. package/apps/pwa/out/_next/static/chunks/3259-86f3be56e43eaf6a.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +0 -287
  572. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/4084.15ecaf4240bd9e77.js +0 -286
  577. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +0 -8
  582. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +0 -104
  584. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +0 -149
  586. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/599-a914cc0468f56143.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +0 -23
  596. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +0 -77
  600. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +0 -64
  602. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +0 -2
  604. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +0 -62
  612. package/apps/pwa/out/_next/static/chunks/7752.5cbdd0b433c54af9.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/8085-1e5fce59500a2cc2.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +0 -226
  621. package/apps/pwa/out/_next/static/chunks/83a80514-b897b64df43ce108.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +0 -93
  623. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +0 -24
  624. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +0 -115
  627. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +0 -41
  629. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +0 -74
  630. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +0 -94
  631. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +0 -90
  635. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +0 -79
  639. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/app/approvals/page-a1ce306364f08da9.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-07110da72c45e68f.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/app/board/page-d2d76d4a7eae91bd.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/app/bots/page-e5a9302c105725a3.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/consult/page-20662900d6b4b455.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/control/page-f707a509515ac50c.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/decisions/page-6a16a48d1aa6e91f.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/design-check/page-fcb06e305f515527.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/exec/page-39f82acf619cca23.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/field/page-7c2c8f81b185f9c0.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/inside/page-ae7aff07e32676bb.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/intake/page-482c60c1bc540d0a.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/layout-7cb996c1aa08b6f5.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/live/page-623e08fe4477d606.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/live-run/page-db460cd8aecb8490.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/market/page-8397a5c6ca569bf4.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1917ea87ea71ab6b.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/not-found-670510eda8b9443f.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4bb7556e2e97a750.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/outputs/page-15c0a4095baddfba.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/page-4eb96fc7241c2456.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d64ff212dc55d03.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/sessions/page-7f096248993fc2d4.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e47fc72049149a38.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/settings/page-f7d808e31e005895.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-5c2b24b5496dad73.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/setup/page-76cdb531668b5191.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/showroom/page-d376e0c83edc041a.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/today/page-dab163b338e3b966.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/trace/page-08019efef111ed2e.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/vault/page-0260ffc7eda50db1.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-980ce6fe36ad95eb.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/workflows/page-99c4e6c7345a9156.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/workspace/page-0ab42e0f05823013.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/e117f801.e92bf10242653497.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +0 -122
  690. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +0 -1
  696. package/src/dashboard/bench-slash-runtime.ts +0 -40
  697. package/src/dashboard/input/search-modal-router.ts +0 -9
  698. package/src/dashboard/modals/pane-key-router.ts +0 -27
  699. package/src/dashboard/view-slash-runtime.ts +0 -48
  700. /package/apps/pwa/out/_next/static/{Ev2jivDMTSoEc-5rIXdcy → cIpv5nU9AycwYWZI9H589}/_ssgManifest.js +0 -0
@@ -0,0 +1,96 @@
1
+ /** Pod repair result: a commit based on the exact PR head, returned without opening a PR. */
2
+ import { execFileSync } from 'node:child_process';
3
+ import { createHash } from 'node:crypto';
4
+ import { mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from 'node:fs';
5
+ import { isAbsolute, join, resolve } from 'node:path';
6
+
7
+ export const REPAIR_REF = 'refs/elanous/repair/result';
8
+ export const REPAIR_BUNDLE_MAX_BYTES = 5 * 1024 * 1024;
9
+ const SHA40 = /^[0-9a-f]{40}$/;
10
+
11
+ export interface PodRepairResult {
12
+ pr: number;
13
+ baseHead: string;
14
+ runId: string;
15
+ commit: string;
16
+ bundleSha256: string;
17
+ }
18
+
19
+ /** Host-side receipt gate. A missing, mismatched, or truncated return is never a repair result. */
20
+ export function readPodRepairArtifact(artifactDir: string, expected: { pr: number; baseHead: string; runId?: string }): PodRepairResult {
21
+ const result = JSON.parse(readFileSync(join(artifactDir, 'result.json'), 'utf8')) as Partial<PodRepairResult>;
22
+ if (result.pr !== expected.pr || result.baseHead !== expected.baseHead || (expected.runId && result.runId !== expected.runId)
23
+ || !result.runId || !SHA40.test(result.commit ?? '') || !/^[0-9a-f]{64}$/.test(result.bundleSha256 ?? '')) {
24
+ throw new Error('repair result mismatch');
25
+ }
26
+ const bundle = readFileSync(join(artifactDir, 'commit.bundle'));
27
+ if (bundle.length > REPAIR_BUNDLE_MAX_BYTES) throw new Error('repair bundle too large');
28
+ if (createHash('sha256').update(bundle).digest('hex') !== result.bundleSha256) throw new Error('repair bundle checksum mismatch');
29
+ return result as PodRepairResult;
30
+ }
31
+
32
+ function git(cwd: string, ...args: string[]): string {
33
+ return execFileSync('git', ['-C', cwd, ...args], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
34
+ }
35
+
36
+ function completedWorktree(output: string): { path: string; runId: string } {
37
+ for (const line of output.trimEnd().split(/\r?\n/).reverse()) {
38
+ if (!line.startsWith('{')) continue;
39
+ let value: Record<string, unknown>;
40
+ try { value = JSON.parse(line) as Record<string, unknown>; } catch { continue; }
41
+ if (value.kind === 'self' && value.result && typeof value.result === 'object') value = value.result as Record<string, unknown>;
42
+ if (value.stage !== 'worktree-completed' || value.ok !== true || typeof value.worktreePath !== 'string'
43
+ || typeof value.runId !== 'string' || !value.runId)
44
+ throw new Error('repair child final result is not a successful worktree-only result');
45
+ return { path: value.worktreePath, runId: value.runId };
46
+ }
47
+ throw new Error('repair child did not return a successful worktree-only result');
48
+ }
49
+
50
+ /** Called in the Pod after the child exits successfully and before artifact export. */
51
+ export function writePodRepairCommit(input: { pr: number; baseHead: string; runId: string; output: string; repo: string; outbox: string }): PodRepairResult {
52
+ if (!Number.isSafeInteger(input.pr) || input.pr < 1 || !SHA40.test(input.baseHead)) throw new Error('invalid repair PR or base head');
53
+ if (!input.runId.trim()) throw new Error('repair parent run id missing');
54
+ const { path, runId: childRunId } = completedWorktree(input.output);
55
+ if (!isAbsolute(path)) throw new Error('repair worktree path is not absolute');
56
+ const worktree = realpathSync(path);
57
+ const repo = realpathSync(input.repo);
58
+ if (worktree === repo) throw new Error('repair result must be a separate worktree');
59
+ if (git(worktree, 'rev-parse', '--is-inside-work-tree') !== 'true') throw new Error('repair result is not a git worktree');
60
+ const commonDir = (cwd: string) => realpathSync(resolve(cwd, git(cwd, 'rev-parse', '--git-common-dir')));
61
+ if (commonDir(worktree) !== commonDir(repo)) throw new Error('repair worktree belongs to another repository');
62
+ if (git(worktree, 'config', '--worktree', '--get', 'elanous.harness.owner') !== `dev:${childRunId}`
63
+ || git(worktree, 'config', '--worktree', '--get', 'elanous.harness.command') !== 'elanous dev')
64
+ throw new Error('repair worktree is not owned by the completed child run');
65
+ if (git(repo, 'rev-parse', 'HEAD') !== input.baseHead) throw new Error('Pod source head changed before repair export');
66
+ git(worktree, 'cat-file', '-e', `${input.baseHead}^{commit}`);
67
+ execFileSync('git', ['-C', worktree, 'add', '-A', '--', '.'], { stdio: ['ignore', 'pipe', 'pipe'] });
68
+ const staged = git(worktree, 'diff', '--cached', '--name-only');
69
+ if (staged) git(worktree, 'commit', '-m', `repair: PR #${input.pr} from ${input.baseHead.slice(0, 12)}`);
70
+ const commit = git(worktree, 'rev-parse', 'HEAD');
71
+ if (!SHA40.test(commit) || commit === input.baseHead) throw new Error('repair made no new commit');
72
+ execFileSync('git', ['-C', worktree, 'merge-base', '--is-ancestor', input.baseHead, commit], { stdio: ['ignore', 'pipe', 'pipe'] });
73
+ git(worktree, 'update-ref', REPAIR_REF, commit);
74
+ const dir = join(input.outbox, 'repair');
75
+ mkdirSync(dir, { recursive: true });
76
+ const bundle = join(dir, 'commit.bundle');
77
+ execFileSync('git', ['-C', worktree, 'bundle', 'create', bundle, REPAIR_REF, `^${input.baseHead}`], { stdio: ['ignore', 'pipe', 'pipe'] });
78
+ const size = statSync(bundle).size;
79
+ if (size > REPAIR_BUNDLE_MAX_BYTES) throw new Error(`repair bundle too large: ${size} > ${REPAIR_BUNDLE_MAX_BYTES}`);
80
+ const bundleSha256 = createHash('sha256').update(readFileSync(bundle)).digest('hex');
81
+ const result = { pr: input.pr, baseHead: input.baseHead, runId: input.runId, commit, bundleSha256 };
82
+ writeFileSync(join(dir, 'result.json'), JSON.stringify(result) + '\n', { flag: 'wx', mode: 0o600 });
83
+ return result;
84
+ }
85
+
86
+ if (import.meta.main) {
87
+ try {
88
+ const [pr, baseHead, outputPath, repo, outbox] = process.argv.slice(2);
89
+ if (!pr || !baseHead || !outputPath || !repo || !outbox) throw new Error('usage: pod-repair-commit <pr> <base-head> <child-output> <repo> <outbox>');
90
+ const result = writePodRepairCommit({ pr: Number(pr), baseHead, runId: process.env.ELANOUS_PARENT_RUN_ID ?? '', output: readFileSync(outputPath, 'utf8'), repo, outbox });
91
+ console.log(`ELANOUS_POD_REPAIR_COMMIT ${result.pr} ${result.baseHead} ${result.commit}`);
92
+ } catch (error) {
93
+ console.error(`ELANOUS_POD_REPAIR_FAILED ${error instanceof Error ? error.message : String(error)}`);
94
+ process.exitCode = 1;
95
+ }
96
+ }
@@ -19,6 +19,7 @@ import { coalescedInstallationCredential } from '../../auth/github-app-token.js'
19
19
  import { POD_CREDENTIAL_TOKEN_ENV, POD_CREDENTIAL_URL_ENV } from '../../grok/credential.js';
20
20
  import { collectPodLedgers, createPodLedgerFollower } from './pod-ledger-collect.js';
21
21
  import { collectPodArtifacts, podNoResultDiagnostic } from './pod-artifact-return.js';
22
+ import { readPodRepairArtifact } from './pod-repair-commit.js';
22
23
  import { isValidAccountName, resolveCodexAccount } from '../../oauth/codex-account.js';
23
24
  import { effectiveInstanceRoot } from '../../instance/resolve.js';
24
25
  import { controlInboxEnv } from '../../harness/control-inbox.js';
@@ -27,7 +28,7 @@ import { mintRunId, normalizeRunId } from '../../harness/harness-space.js';
27
28
  import { TA_LAND_ENV } from '../../task-agent/task-hand.js';
28
29
  import { appendRunLedgerEntry, loadRunLedger, runLedgerDir, runLedgerPath } from '../../self-implement/run-ledger.js';
29
30
  import type { GoalExecutionRecord } from '../../self-implement/orchestrator.js';
30
- import { runHostRegate, type HostRegateResult } from '../../self-implement/host-regate.js';
31
+ import { hostRepositoryUnavailable, runHostRegate, type HostRegateResult } from '../../self-implement/host-regate.js';
31
32
  import { resolvePodHostAcpReview, runPodHostAcpReview, type PodHostAcpReviewOutcome } from './pod-host-acp-review.js';
32
33
  import { REVIEW_DEFERRED_TO_HOST_ENV, REVIEW_DEFERRED_TO_HOST_MERGE_REASON } from '../../self-implement/review-deferred-to-host.js';
33
34
  import { classifyPodTerminal, applyPodTerminal, podTerminalPrBody, type PrTerminalRecord, type DraftResidueContext } from '../../self-dev/draft-residue.js';
@@ -78,17 +79,20 @@ import { envLiteral } from '../../platform/env-literal.js';
78
79
  import { LLM_TIER_MAP_BY_PROVIDER, lookupLlmTierSpec, type LlmTierProvider } from '../../model-tier/llm-tier-map.js';
79
80
  import { parseSelfImplementJson, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
80
81
  import { codexQuotaPolicyFromConfig } from '../../oauth/codex-account-store.js';
82
+ import { normalizeFallbackChain, type FallbackStep } from '../../oauth/fallback-chain.js';
81
83
  import { goalTypeOf, type GoalType } from '../../../scripts/measure-pod-memory-by-goal.js';
82
84
  import { declaredGoalType, type GoalType as DeclaredGoalType } from '../../self-implement/goal-author.js';
83
85
  import { readPodMemoryAdvice, type PodMemoryAdvice } from '../../cli/pod-memory-advice.js';
84
- import { getUserConfig, roleLlmEnvName, type UserConfig } from '../../user-config.js';
86
+ import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, getUserConfig, roleLlmEnvName, type UserConfig } from '../../user-config.js';
85
87
  import { podChildProviderOf, podChildProviderRefusal, type PodChildProvider } from './pod-child-providers.js';
86
88
  import { BEDROCK_POD_EGRESS_LABEL, bedrockPodEnv, checkBedrockPodSecret, type BedrockPodSpec } from './pod-bedrock-child.js';
87
89
  import { resolveBedrockRegion, validBedrockRegion } from '../../llm/bedrock.js';
88
90
  import { ZAI_POD_EGRESS_LABEL, checkZaiPodSecret, countActiveZaiJobs, decideZaiPodSlot, zaiOverflowChildArgs, zaiPodEnv, type ZaiPodSpec } from './pod-zai-child.js';
89
91
  import { ZAI_CODING_DEFAULT_MODEL, ZAI_OPENROUTER_FALLBACK_MODEL, zaiSettingsFromConfig, type ZaiCodingPlanSettings } from '../../llm/zai-coding-plan.js';
90
- import { selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
92
+ import { normalizePlanningFallbackReason, selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
93
+ import { inferProviderFromModel } from '../../llm.js';
91
94
  import { classifyPodExit, extractPodFailureReason, podTerminalRow, type PodExitClass } from './pod-failure-reason.js';
95
+ import { kubectlTransientReason, retryKubectlTransient } from './kubectl-transient-retry.js';
92
96
  import { OLD_DOOR_STAMP_ENV } from '../../self-dev/old-door.js';
93
97
 
94
98
  export type Kubectl = (args: readonly string[], input?: string) => { status: number | null; stdout: string; stderr: string };
@@ -118,6 +122,8 @@ export interface PodSpawnOptions {
118
122
  budgetSnapshot?: (childLlm: PodBudgetChildLlm) => Promise<BudgetSnapshot | undefined> | BudgetSnapshot | undefined;
119
123
  /** Input reader seam; the host still runs its normal budget decision and Job propagation. */
120
124
  budgetInputDeps?: ReadBudgetInputsDeps & { readLiveGrok?: () => Promise<number | undefined> };
125
+ /** Test seam for the planning Codex quota check; production reads the existing budget-gate candidates. */
126
+ planningCodexQuota?: (account: string) => { usable: boolean; reason?: string };
121
127
  /** Child model/effort chosen at launch (`--child-llm-model/--child-llm-effort`) — carried into the Pod child. */
122
128
  childModel?: string;
123
129
  childEffort?: string;
@@ -135,8 +141,12 @@ export interface PodSpawnOptions {
135
141
  configHostMirror?: () => string | undefined;
136
142
  /** AUTHOR-POD2 host config seam; Pod itself has no host config. */
137
143
  authorConfig?: () => UserConfig;
144
+ /** Host fallback chain seam; a Pod has no access to the host config. */
145
+ fallbackConfig?: () => UserConfig;
138
146
  /** 원천 — 없으면 종전 `git clone --depth 50`. bundle 이면 apply 뒤 kubectl cp 로 싣는다. */
139
147
  source?: PodSource;
148
+ /** Existing PR repair: pin the source head and export a commit bundle instead of opening a PR. */
149
+ repairCommitOnly?: { pr: number; baseHead: string };
140
150
  /** 호스트 환경에서 읽어 Pod env 로 넣을 키 이름(예: OPENROUTER_API_KEY · ANTHROPIC_API_KEY) — 벤치마크 과금 경로. */
141
151
  passEnv?: readonly string[];
142
152
  /** 호스트가 재발사를 소유하면 Pod 자식의 자체 감독을 끈다. 독립 호출 기본 true; 실제 CLI 호스트는 자기 감독 상태를 명시한다. */
@@ -281,6 +291,20 @@ async function measureHostBudgetSnapshot(childLlm: PodBudgetChildLlm, env: NodeJ
281
291
  };
282
292
  }
283
293
 
294
+ /** Planning uses a subscription account inside an OpenRouter Pod. Credits are not a silent fallback for this role. */
295
+ async function hostPlanningCodexQuota(account: string, deps?: ReadBudgetInputsDeps): Promise<{ usable: boolean; reason?: string }> {
296
+ try {
297
+ const { readBudgetInputs } = await import('../../self-implement/budget-gate.js');
298
+ const inputs = readBudgetInputs(deps);
299
+ const candidate = inputs.codexCandidates.find((item) => item.name === account);
300
+ const configuredCap = inputs.maxUsedPercent['openai-codex'];
301
+ const cap = typeof configuredCap === 'number' && Number.isFinite(configuredCap) ? configuredCap : DEFAULT_BUDGET_GATE_MAX_USED_PERCENT['openai-codex']!;
302
+ if (!candidate || typeof candidate.usedPercent !== 'number' || !Number.isFinite(candidate.usedPercent)) return { usable: false, reason: 'quota-unmeasured' };
303
+ if (candidate.reached === true || candidate.usedPercent >= cap) return { usable: false, reason: 'quota-exhausted' };
304
+ return { usable: true };
305
+ } catch { return { usable: false, reason: 'quota-unavailable' }; }
306
+ }
307
+
284
308
  /** «3시간 안 만료» — 선갱신 대상이라는 표지(다른 자격 오류와 구분한다). */
285
309
  export class PodCodexExpiringError extends Error {
286
310
  constructor(readonly account: string, readonly hoursLeft: number) {
@@ -953,7 +977,10 @@ export function podSigtermTrapScript(seqFile: string = POD_USAGE_PARTIAL_SEQ_FIL
953
977
  return `trap '{ [ -n "$si_pid" ] && kill "$si_pid" 2>/dev/null || true; [ -n "\${usage_partial_pid:-}" ] && kill "$usage_partial_pid" 2>/dev/null || true; si_seq=$(cat ${seqFile} 2>/dev/null || true); case "$si_seq" in ""|*[!0-9]*) si_seq=0;; esac; si_seq=$((10#$si_seq + 1)); { [ -f scripts/usage-rollup.ts ] && bun scripts/usage-rollup.ts --since 12h --partial --seq "$si_seq"; } & si_rollup_pid=$!; for si_i in 1 2 3 4 5 6 7 8; do kill -0 "$si_rollup_pid" 2>/dev/null || break; sleep 1; done; kill "$si_rollup_pid" 2>/dev/null || true; wait "$si_rollup_pid" 2>/dev/null || true; exit 143; }' TERM`;
954
978
  }
955
979
 
956
- export function podJobManifest(o: { name: string; namespace: string; image: string; workIdentity?: PodWorkIdentity; /** 레지스트리 이미지면 IfNotPresent(노드가 pull) · 반입 이미지면 Never. */ imagePullPolicy?: 'Never' | 'IfNotPresent'; repoUrl: string; source?: PodSource; hostMirror?: string; args: readonly string[]; passEnv: readonly string[]; deadlineSeconds: number; runId?: string; parentRunId?: string; armEnv?: Readonly<Record<string, string>>; hostId?: string; imageCommit?: string | null; skillEnvs?: readonly string[]; memoryLimit?: string; memoryRequest?: string; goalDoc?: string; /** AUTHOR-POD2 — run `harness say` on /creds/feature inside the Pod (authoring happens off the host). */ authorSentence?: boolean; authorGrade?: 'full' | 'lite'; grokCredential?: 'subscription' | 'api_key'; codexAccounts?: readonly string[]; appCredential?: boolean; /** Test seam — default POD_GH_STALE_SECONDS. */ githubStaleSeconds?: number; /** Which goal execution and attempt this Job is — a resumed host verifies it before following the Job (POD9). */ execution?: { key: string; attempt: number }; hostLeaseAdmitted?: boolean; /** POD-ROLE-LLM — OpenRouter 자식 Pod 에 리뷰어용 codex 자격을 깐다. */ reviewerCodexAuth?: boolean; /** BEDROCK-PROVIDER ② — bedrock 자식만: 이름 있는 AWS Secret 의 키(secretKeyRef) ⊕ 리전 ⊕ 이그레스 라벨. */ bedrock?: BedrockPodSpec; /** ZAI-POD-CHILD — glm(ZAI) 자식만: 이름 있는 ZAI Secret 의 키(secretKeyRef) ⊕ 이그레스·동시 상한 라벨(Pod ⊕ Job). */ zai?: ZaiPodSpec }): Record<string, unknown> {
980
+ export function podJobManifest(o: { name: string; namespace: string; image: string; workIdentity?: PodWorkIdentity; /** 레지스트리 이미지면 IfNotPresent(노드가 pull) · 반입 이미지면 Never. */ imagePullPolicy?: 'Never' | 'IfNotPresent'; repoUrl: string; source?: PodSource; repairCommitOnly?: { pr: number; baseHead: string }; hostMirror?: string; args: readonly string[]; passEnv: readonly string[]; deadlineSeconds: number; runId?: string; parentRunId?: string; armEnv?: Readonly<Record<string, string>>; hostId?: string; imageCommit?: string | null; skillEnvs?: readonly string[]; memoryLimit?: string; memoryRequest?: string; goalDoc?: string; /** AUTHOR-POD2 — run `harness say` on /creds/feature inside the Pod (authoring happens off the host). */ authorSentence?: boolean; authorGrade?: 'full' | 'lite'; grokCredential?: 'subscription' | 'api_key'; codexAccounts?: readonly string[]; appCredential?: boolean; /** Test seam — default POD_GH_STALE_SECONDS. */ githubStaleSeconds?: number; /** Which goal execution and attempt this Job is — a resumed host verifies it before following the Job (POD9). */ execution?: { key: string; attempt: number }; hostLeaseAdmitted?: boolean; /** POD-ROLE-LLM — OpenRouter 자식 Pod 에 리뷰어용 codex 자격을 깐다. */ reviewerCodexAuth?: boolean; /** BEDROCK-PROVIDER ② — bedrock 자식만: 이름 있는 AWS Secret 의 키(secretKeyRef) ⊕ 리전 ⊕ 이그레스 라벨. */ bedrock?: BedrockPodSpec; /** ZAI-POD-CHILD — glm(ZAI) 자식만: 이름 있는 ZAI Secret 의 키(secretKeyRef) ⊕ 이그레스·동시 상한 라벨(Pod ⊕ Job). */ zai?: ZaiPodSpec; fallbackChain?: { steps: readonly FallbackStep[]; source: 'host' | 'default' } }): Record<string, unknown> {
981
+ if (o.repairCommitOnly && (o.source?.kind !== 'pr' || o.source.number !== o.repairCommitOnly.pr || !/^[0-9a-f]{40}$/.test(o.repairCommitOnly.baseHead) || o.args.includes('--open-pr') || o.args.includes('--merge-by-host') || o.args.includes('--auto-merge'))) {
982
+ throw new Error('repair commit-only requires matching PR source and no PR/merge flags');
983
+ }
957
984
  const quoted = o.args.map((a) => `'${a.replace(/'/g, `'\\''`)}'`).join(' ');
958
985
  const childProviderIndex = o.args.indexOf('--child-llm-provider');
959
986
  const childModelIndex = o.args.indexOf('--child-llm-model');
@@ -962,7 +989,7 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
962
989
  // POD-ANTHROPIC-PROVIDER — anthropic 자식은 키(env · secretKeyRef)만 쓴다. codex·grok 자격 파일을 깔지 않는다.
963
990
  const anthropicChild = childProviderIndex >= 0 && o.args[childProviderIndex + 1] === 'anthropic';
964
991
  const goalPath = o.goalDoc ? `'${(o.goalDoc.startsWith('-') ? `./${o.goalDoc}` : o.goalDoc).replace(/'/g, `'\\''`)}'` : undefined;
965
- const delegated = Boolean(o.goalDoc) || o.authorSentence === true;
992
+ const delegated = !o.repairCommitOnly && (Boolean(o.goalDoc) || o.authorSentence === true);
966
993
  const askBaseIndex = delegated ? o.args.indexOf('--base') : -1;
967
994
  const quotedAsk = (askBaseIndex >= 0 && o.args[askBaseIndex + 1]
968
995
  ? ` '--base' '${o.args[askBaseIndex + 1]!.replace(/'/g, `'\\''`)}'`
@@ -975,6 +1002,10 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
975
1002
  : '';
976
1003
  const script = [
977
1004
  'set -u',
1005
+ ...(o.fallbackChain ? [
1006
+ 'mkdir -p "$HOME/.elanous" && install -m 600 /creds/llm-fallback-config.json "$HOME/.elanous/config.json" || exit 6',
1007
+ `echo "ELANOUS_POD_FALLBACK_CHAIN source=${o.fallbackChain.source} steps=${o.fallbackChain.steps.join(',')}"`,
1008
+ ] : []),
978
1009
  openrouterModel
979
1010
  ? o.reviewerCodexAuth
980
1011
  ? 'mkdir -p ~/.elanous ~/.codex && cp /creds/elanous-auth.json ~/.elanous/auth.json && cp /creds/codex-auth.json ~/.codex/auth.json && chmod 600 ~/.elanous/auth.json ~/.codex/auth.json && export ELANOUS_LLM_PROVIDER=openrouter'
@@ -997,12 +1028,13 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
997
1028
  podGitPushGuardScript(),
998
1029
  'curl -s -m 3 -o /dev/null http://host.orb.internal:31415/health && { echo "[pod] ISOLATION FAIL"; exit 3; }',
999
1030
  podSourceScript(o.source ?? { kind: 'default' }, o.repoUrl),
1031
+ ...(o.repairCommitOnly ? [`[ "$(git rev-parse HEAD)" = '${o.repairCommitOnly.baseHead}' ] || { echo 'ELANOUS_POD_REPAIR_FAILED source-head-mismatch'; exit 8; }`] : []),
1000
1032
  ...(goalPath ? [
1001
1033
  `mkdir -p -- "$(dirname -- ${goalPath})" && cp -- /creds/goal-doc ${goalPath} || exit 6`,
1002
1034
  ] : []),
1003
1035
  // Only fixed command shapes leave the Pod; arbitrary argv (including shell -c text) is never emitted.
1004
1036
  `(while :; do { mem=$(if [ -r /sys/fs/cgroup/memory.current ]; then cat /sys/fs/cgroup/memory.current; elif [ -r /sys/fs/cgroup/memory/memory.usage_in_bytes ]; then cat /sys/fs/cgroup/memory/memory.usage_in_bytes; else printf -- -; fi); top=$(ps -eo rss=,comm=,args= --sort=-rss | head -5 | awk 'function encode(s) { gsub(/%/, "%25", s); gsub(/:/, "%3A", s); gsub(/ /, "%20", s); gsub(/\\t/, "%09", s); return s } { rss=$1; name=$2; sub(/^[[:space:]]*[0-9]+[[:space:]]+[^[:space:]]+[[:space:]]*/, ""); n=split($0, a, /[[:space:]]+/); cmd="<redacted>"; if (name=="sleep" && a[2]=="30") cmd="sleep 30" (n>2 ? " <redacted>" : ""); else if (name=="bun") { cmd="bun <redacted>"; if (a[2]=="test") cmd="bun test <redacted>"; else if (a[2]=="run") cmd="bun run <redacted>"; else if ((a[2]=="x" || a[2]=="exec") && a[3]=="tsc") cmd="bun x tsc <redacted>" } else if (name=="tsc") cmd="tsc <redacted>"; else if (name=="elanous") { cmd="elanous <redacted>"; if (a[2]=="self") cmd="elanous self <redacted>"; else if (a[2]=="harness") cmd="elanous harness <redacted>" } else if (name=="node") cmd="node <redacted>"; if (name=="sleep" && cmd=="<redacted>") cmd="sleep <redacted>"; else if (cmd=="<redacted>" && name!="bash" && name!="sh") name="other"; printf " %s:%s:%s", rss, encode(name), encode(substr(cmd,1,120)) }'); printf "ELANOUS_MEM %s %s%s\\n" "$(date +%s)" "$mem" "$top"; } || true; sleep 15 || break; done) & mem_sampler_pid=$!`,
1005
- ...(o.appCredential ? [podGithubWatchdogScript(o.githubStaleSeconds ?? POD_GH_STALE_SECONDS)] : []),
1037
+ ...(o.appCredential && !o.repairCommitOnly ? [podGithubWatchdogScript(o.githubStaleSeconds ?? POD_GH_STALE_SECONDS)] : []),
1006
1038
  // METER-POD-ROLLUP-GAP — 부분 롤업 표본기: 최종 줄까지 못 사는 Pod 도 N 분마다(기본 5 · ELANOUS_USAGE_PARTIAL_MINUTES) PARTIAL 줄을 하나씩 남긴다.
1007
1039
  `(usage_partial_seq=0; while :; do { usage_partial_seq=$((usage_partial_seq+1)); printf '%s\\n' "$usage_partial_seq" > ${POD_USAGE_PARTIAL_SEQ_FILE} 2>/dev/null || true; [ -f scripts/usage-rollup.ts ] && bun scripts/usage-rollup.ts --since 12h --partial --seq "$usage_partial_seq" || true; } || true; usage_partial_sleep=$(( \${ELANOUS_USAGE_PARTIAL_MINUTES:-5} * 60 )); sleep "$usage_partial_sleep" || break; done) & usage_partial_pid=$!`,
1008
1040
  // ⭐ MF-d3b5a70f — si_pid 초기화 + trap: 메인 명령을 아래에서 `& si_pid=$!` 로 띄우고 `wait "$si_pid"` 로
@@ -1013,7 +1045,9 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
1013
1045
  // 마지막 줄 JSON 이 «맨 끝»이어야 한다(parseSelfImplementJson) — rollup 은 그 앞에.
1014
1046
  // ⛔ `--author-grade` 는 Pod 안 `elanous`(이미지에 깔린 판)가 모를 수 있어 넘기지 않는다 — 10-06 «unknown option» 즉사(#24445 되돌림).
1015
1047
  // AUTHOR-LITE2-POD — 등급은 환경변수 `ELANOUS_AUTHOR_GRADE` 로 싣는다(옛 Pod elanous 는 모르는 환경변수를 무시하고 full 로 돈다).
1016
- o.authorSentence
1048
+ o.repairCommitOnly
1049
+ ? `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json --no-open-pr ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; if [ "$rc" -eq 0 ]; then elanous self repair-commit-export '${o.repairCommitOnly.pr}' '${o.repairCommitOnly.baseHead}' /tmp/si.out "$PWD" "$HOME/outbox" || rc=8; fi`
1050
+ : o.authorSentence
1017
1051
  ? `echo "ELANOUS_AUTHOR_ON_POD started host=$(hostname) at=$(date -u +%Y-%m-%dT%H:%M:%SZ)"; author_t0=$(date +%s); ${o.authorGrade === 'lite' || o.authorGrade === 'full' ? `ELANOUS_AUTHOR_GRADE=${o.authorGrade} ` : ''}elanous harness say --substrate local --json${quotedAsk}${quotedChildLlm} -- "$(cat /creds/feature)" > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; echo "ELANOUS_AUTHOR_ON_POD finished host=$(hostname) rc=$rc seconds=$(( $(date +%s) - author_t0 ))"; ${POD_RESULT_FLATTEN}`
1018
1052
  : goalPath
1019
1053
  ? `elanous harness ask ${goalPath} --json${quotedAsk}${quotedChildLlm} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${POD_RESULT_FLATTEN}`
@@ -1074,12 +1108,12 @@ for ledger in "\${ELANOUS_STATE_DIR:-$HOME/.elanous}"/run-ledger/*.jsonl; do
1074
1108
  done
1075
1109
  if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
1076
1110
  'kill "$mem_sampler_pid" 2>/dev/null || true',
1077
- ...(o.appCredential ? ['kill "$gh_watch_pid" 2>/dev/null || true'] : []),
1111
+ ...(o.appCredential && !o.repairCommitOnly ? ['kill "$gh_watch_pid" 2>/dev/null || true'] : []),
1078
1112
  '[ -n "${usage_partial_pid:-}" ] && kill "$usage_partial_pid" 2>/dev/null || true',
1079
1113
  'wait "$mem_sampler_pid" 2>/dev/null || true',
1080
1114
  '[ -n "${usage_partial_pid:-}" ] && wait "$usage_partial_pid" 2>/dev/null || true',
1081
1115
  'tail -n 1 /tmp/si.out',
1082
- podSalvageScript(),
1116
+ ...(o.repairCommitOnly ? [] : [podSalvageScript()]),
1083
1117
  'exit $rc',
1084
1118
  ].join('\n');
1085
1119
  return {
@@ -1149,6 +1183,9 @@ function defaultGhComment(prNumber: number, body: string): void {
1149
1183
  }
1150
1184
 
1151
1185
  export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplementJobSpawn {
1186
+ if (options.repairCommitOnly && (options.source?.kind !== 'pr' || options.source.number !== options.repairCommitOnly.pr || !/^[0-9a-f]{40}$/.test(options.repairCommitOnly.baseHead))) {
1187
+ throw new Error('repair commit-only requires a matching PR source and exact head');
1188
+ }
1152
1189
  const baseKubectl = options.kubectl ?? defaultKubectl;
1153
1190
  const sleep = options.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));
1154
1191
  const namespace = options.namespace ?? 'elanous-test';
@@ -1160,6 +1197,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1160
1197
  if (hostMirror && !isAbsolute(hostMirror)) throw new Error('pod.hostMirror must be an absolute directory path');
1161
1198
  const hostSupervised = options.hostSupervised ?? true;
1162
1199
  return (input) => {
1200
+ if (options.repairCommitOnly && (input.autoMerge || input.openPr || input.base !== `pr-${options.repairCommitOnly.pr}`)) {
1201
+ throw new Error('repair commit-only refuses auto merge, new PR, or a different base');
1202
+ }
1163
1203
  const name = podJobName(input.spaceId);
1164
1204
  let parentGoal: string | undefined;
1165
1205
  let parentGoalUnreadable = false;
@@ -1212,6 +1252,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1212
1252
  const childRunId = mintRunId();
1213
1253
  const executionKey = createHash('sha256').update(JSON.stringify({ spaceId: input.spaceId, feature: input.feature, base: input.base, autoMerge: input.autoMerge, autoReview: input.autoReview, openPr: input.openPr, draft: input.draft })).digest('hex');
1214
1254
  const parentRunId = env.ELANOUS_RUN_ID?.trim();
1255
+ if (options.repairCommitOnly && !parentRunId) throw new Error('repair commit-only requires a parent run id');
1215
1256
  // Standalone callers journal retries without altering the existing Pod manifest.
1216
1257
  const ledgerRunId = parentRunId || `run-${executionKey.slice(0, 8)}-${executionKey.slice(8, 12)}-${executionKey.slice(12, 16)}-${executionKey.slice(16, 20)}-${executionKey.slice(20, 32)}`;
1217
1258
  const address = `self-impl:${input.spaceId}`;
@@ -1237,7 +1278,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1237
1278
  ...(input.autoReview ? ['--auto-review'] : []),
1238
1279
  // ⭐ 계약이 미래 노드를 바꾼다(첫 규칙): Pod 는 끝나면 사라지므로 완료 하한 = PR. 작업 트리로만 끝나면 결과가 Pod 와 함께 없어진다.
1239
1280
  // ⚠️ 임시 안전망(🅢 2026-09-26) — 🅣 의 «종결 하한 오버레이»(그래프 쪽)가 서면 이 줄을 지우고 그것으로 바꾼다(채널 합의).
1240
- ...(input.openPr || (!input.autoMerge && completionFloorFor({ substrate: 'pod' }) === 'pr') ? ['--open-pr'] : []),
1281
+ ...(!options.repairCommitOnly && (input.openPr || (!input.autoMerge && completionFloorFor({ substrate: 'pod' }) === 'pr')) ? ['--open-pr'] : []),
1241
1282
  ...(input.draft === false ? ['--no-draft'] : []),
1242
1283
  ...(hostSupervised ? ['--no-supervise'] : []),
1243
1284
  ...(options.extraArgs ?? []),
@@ -1327,7 +1368,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1327
1368
  if (unfitDone) return unfitDone;
1328
1369
  // HARNESS-FULL-GRAPH — Pod 입장(입장 관문 ⊕ 멤버 슬롯)은 그래프 노드 pool-admit 이다.
1329
1370
  // 2판: decompose →(substrate=pod) pool-admit 간선은 «여기»(Pod 입장 직전 · 실제 단계 경계)에서 남긴다.
1330
- routeJourneyEdge('decompose', 'pod', { substrate: 'pod' });
1371
+ if (options.repairCommitOnly) routeJourneyEdge('dispatch', 'pr-source', { source: 'pr', substrate: 'pod' });
1372
+ else routeJourneyEdge('decompose', 'pod', { substrate: 'pod' });
1331
1373
  enterJourneyNode('pool-admit', { provenance: 'self-implement-pod', data: { spaceId: input.spaceId } });
1332
1374
  // ⛔ 감싸는 함수(async 래퍼)를 쓰지 않는다 — 마이크로태스크가 늘면 Job apply 순서가 밀린다(시험이 잡았다). 같은 자리 try/catch 로.
1333
1375
  const podAdmitError = (error: unknown): void => {
@@ -1354,6 +1396,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1354
1396
  try {
1355
1397
  if (!context) return { exitCode: 1, output: '', error: { code: 'pod-context', message: 'Pod Job context를 확인할 수 없다' } };
1356
1398
  const cleanupSecret = () => { kubectl(['-n', namespace, 'delete', 'secret', `${name}-creds`, '--ignore-not-found']); };
1399
+ let repairResultAnnounced = false;
1400
+ let repairArtifactReady = false;
1357
1401
  const collectFullLogs = (unavailableEvent: string, replace?: ReadonlySet<string>, onEvent?: (event: string, data: Record<string, unknown>) => void, childId?: string): { status: 'ok' | 'unavailable' | 'incomplete'; childLedgerIncomplete: boolean; samples: ReturnType<typeof parseMemSamples> } => {
1358
1402
  let full: ReturnType<Kubectl>;
1359
1403
  try {
@@ -1384,6 +1428,20 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1384
1428
  collectPodArtifacts(full.stdout, { dir: join(effectiveInstanceRoot(), 'pod-artifacts'), job: name, log: record });
1385
1429
  }
1386
1430
  catch (error) { record('self-implement.pod', 'artifact-collect-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
1431
+ if (options.repairCommitOnly) {
1432
+ const artifactDir = join(effectiveInstanceRoot(), 'pod-artifacts', name, 'repair');
1433
+ try {
1434
+ const result = readPodRepairArtifact(artifactDir, { ...options.repairCommitOnly, runId: parentRunId });
1435
+ repairArtifactReady = true;
1436
+ if (!repairResultAnnounced) {
1437
+ console.log(`ELANOUS_POD_REPAIR_RESULT ${JSON.stringify({ job: name, artifactDir, pr: result.pr, baseHead: result.baseHead, runId: result.runId, commit: result.commit, bundleSha256: result.bundleSha256 })}`);
1438
+ repairResultAnnounced = true;
1439
+ }
1440
+ } catch (error) {
1441
+ repairArtifactReady = false;
1442
+ record('self-implement.pod', 'repair-artifact-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) });
1443
+ }
1444
+ }
1387
1445
  return { status: ledgerIncomplete || artifactIncomplete ? 'incomplete' : 'ok', childLedgerIncomplete, samples: parseMemSamples(full.stdout) };
1388
1446
  };
1389
1447
  let retryAccount: string | undefined;
@@ -1500,8 +1558,23 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1500
1558
  ? (options.grokCredentials ?? (() => hostGrokCredentials({ env, apiKeyOptIn: options.grokApiKeyOptIn })))()
1501
1559
  : apiKeyChild ? { ghToken: (options.openrouterGhToken ?? defaultGhToken)() }
1502
1560
  : codexCredentials?.[0] ?? usable[0]!.credential;
1503
- // POD-ROLE-LLM — OpenRouter 자식만 리뷰어를 고정한다. 기본 glm(새 자격 0) · codex-sol 은 선택이고 자격 한 벌이 필요하다 — 못 얻으면 고정을 건너뛴다(종전 kimi 리뷰어 그대로).
1561
+ // POD-ROLE-LLM — OpenRouter 자식의 Codex 역할(리뷰·저작 grounding)은 별도 access 자격을 검증해 싣는다.
1504
1562
  // ⛔ kubectl 주입(=시험)이면 호스트 자격 스토어를 읽지 않는다 — 시험은 credentials 를 명시한다.
1563
+ const roleCodexAccount = options.account ?? 'team';
1564
+ const loadRoleCodexCredential = async (): Promise<{ credential?: { elanousAuth: string; codexAuth: string }; skipped?: string }> => {
1565
+ const credentialSource = options.credentials ?? (options.kubectl ? undefined : (account: string) => hostCredentials(account, authStorePath(), () => ''));
1566
+ if (!credentialSource) return { skipped: 'no-credential-source' };
1567
+ try {
1568
+ const got = await podCodexCredentialWithPrerefresh(roleCodexAccount, { ...prerefreshDeps, credentials: credentialSource });
1569
+ if (!got) return { skipped: 'expiring' };
1570
+ const elanous = JSON.parse(got.elanousAuth) as { providers?: Record<string, { tokens?: { accessToken?: unknown; refreshToken?: unknown } }> };
1571
+ const codex = JSON.parse(got.codexAuth) as { tokens?: { access_token?: unknown; refresh_token?: unknown } };
1572
+ const elanousTokens = elanous.providers?.['openai-codex']?.tokens;
1573
+ const nonEmpty = (v: unknown): boolean => typeof v === 'string' && v.trim().length > 0;
1574
+ if (!elanousTokens || !nonEmpty(elanousTokens.accessToken) || elanousTokens.refreshToken || !codex.tokens || !nonEmpty(codex.tokens.access_token) || codex.tokens.refresh_token) return { skipped: 'credential-shape' };
1575
+ return { credential: { elanousAuth: got.elanousAuth, codexAuth: got.codexAuth } };
1576
+ } catch { return { skipped: 'credential-error' }; } // 자격 오류 원문에는 토큰이 섞일 수 있다.
1577
+ };
1505
1578
  let reviewerCredential: { elanousAuth: string; codexAuth: string } | undefined;
1506
1579
  let reviewerPin: string | undefined;
1507
1580
  const reviewerPick = openrouter ? resolvePodOpenRouterReviewer(options.openrouterReviewer, env) : undefined;
@@ -1511,29 +1584,12 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1511
1584
  } else if (reviewerPick?.choice === 'off') {
1512
1585
  debug.log('self-implement.pod', 'role-llm-skipped', { job: name, role: 'review', choice: 'off', source: reviewerPick.source, reason: 'off' });
1513
1586
  } else if (reviewerPick?.choice === 'codex-sol') {
1514
- const reviewerAccount = options.account ?? 'team';
1515
- const reviewerCredentials = options.credentials ?? (options.kubectl ? undefined : (account: string) => hostCredentials(account, authStorePath(), () => ''));
1516
- let skipped: string | undefined;
1517
- if (!reviewerCredentials) skipped = 'no-credential-source';
1518
- else {
1519
- try {
1520
- const got = await podCodexCredentialWithPrerefresh(reviewerAccount, { ...prerefreshDeps, credentials: reviewerCredentials });
1521
- if (!got) skipped = 'expiring';
1522
- else {
1523
- const elanous = JSON.parse(got.elanousAuth) as { providers?: Record<string, { tokens?: { accessToken?: unknown; refreshToken?: unknown } }> };
1524
- const codex = JSON.parse(got.codexAuth) as { tokens?: { access_token?: unknown; refresh_token?: unknown } };
1525
- const elanousTokens = elanous.providers?.['openai-codex']?.tokens;
1526
- const nonEmpty = (v: unknown): boolean => typeof v === 'string' && v.trim().length > 0;
1527
- // 불완전한 자격(access 비었음·refresh 있음)이면 고정을 켜지 않는다 — 켜면 Pod 리뷰가 인증 실패로 no-real-review 가 된다.
1528
- if (!elanousTokens || !nonEmpty(elanousTokens.accessToken) || elanousTokens.refreshToken || !codex.tokens || !nonEmpty(codex.tokens.access_token) || codex.tokens.refresh_token) skipped = 'credential-shape';
1529
- else reviewerCredential = { elanousAuth: got.elanousAuth, codexAuth: got.codexAuth };
1530
- }
1531
- } catch { skipped = 'credential-error'; } // ⛔ 원문 메시지는 싣지 않는다 — 자격 오류 문면에 토큰이 섞일 수 있다(비밀 0)
1532
- }
1587
+ const { credential, skipped } = await loadRoleCodexCredential();
1588
+ reviewerCredential = credential;
1533
1589
  if (reviewerCredential) {
1534
1590
  reviewerPin = POD_OPENROUTER_REVIEWER_PINS['codex-sol'];
1535
- debug.log('self-implement.pod', 'role-llm-armed', { job: name, role: 'review', env: roleLlmEnvName('review'), value: reviewerPin, choice: 'codex-sol', source: reviewerPick.source, account: reviewerAccount });
1536
- } else debug.log('self-implement.pod', 'role-llm-skipped', { job: name, role: 'review', choice: 'codex-sol', source: reviewerPick.source, account: reviewerAccount, reason: skipped });
1591
+ debug.log('self-implement.pod', 'role-llm-armed', { job: name, role: 'review', env: roleLlmEnvName('review'), value: reviewerPin, choice: 'codex-sol', source: reviewerPick.source, account: roleCodexAccount });
1592
+ } else debug.log('self-implement.pod', 'role-llm-skipped', { job: name, role: 'review', choice: 'codex-sol', source: reviewerPick.source, account: roleCodexAccount, reason: skipped });
1537
1593
  }
1538
1594
  if (grok && !('grokAuth' in creds && creds.grokAuth) && !('grokApiKey' in creds && creds.grokApiKey && options.grokApiKeyOptIn === true)) {
1539
1595
  throw new Error('grok: 구독 자격 없음 · API 키 opt-in 꺼짐 또는 키 없음');
@@ -1664,13 +1720,48 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1664
1720
  debug.log('self-implement.pod', 'goal-doc-mode', { spaceId: input.spaceId, mode, reason: shard ? 'shard-identity' : requestedPath ? 'goal-doc-env' : 'no-goal-doc' });
1665
1721
  const goalDoc = shard ? undefined : requestedPath;
1666
1722
  const goalDocument = goalDoc ? originalGoal : undefined;
1723
+ const authorOnPod = env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !goalDoc && !shard;
1724
+ // Relay provenance is set by this host after selection; caller env cannot assert it.
1725
+ const hostAuthorEnv = { ...env };
1726
+ for (const key of Object.keys(hostAuthorEnv)) {
1727
+ if (key.startsWith('ELANOUS_PROMPT_ENHANCE_') && key !== 'ELANOUS_PROMPT_ENHANCE_MODEL' && key !== 'ELANOUS_PROMPT_ENHANCE_EFFORT') delete hostAuthorEnv[key];
1728
+ }
1729
+ let authorChoice = authorOnPod ? selectEnhanceLlm({ config: (options.authorConfig ?? getUserConfig)() }, hostAuthorEnv) : undefined;
1730
+ let authorFallbackReason: string | undefined;
1731
+ let authorRequestedModel: string | undefined;
1732
+ let authorRequestedSource: string | undefined;
1733
+ let roleCodexCredential = reviewerCredential;
1734
+ if (openrouter && authorChoice && inferProviderFromModel(authorChoice.model) === 'openai-codex') {
1735
+ const quota = options.planningCodexQuota?.(roleCodexAccount) ?? await hostPlanningCodexQuota(roleCodexAccount, options.budgetInputDeps);
1736
+ if (!quota.usable) authorFallbackReason = normalizePlanningFallbackReason(quota.reason ?? 'quota-unavailable');
1737
+ else if (!roleCodexCredential) {
1738
+ const { credential, skipped } = await loadRoleCodexCredential();
1739
+ if (credential) roleCodexCredential = credential;
1740
+ else authorFallbackReason = normalizePlanningFallbackReason(skipped ?? 'credential-unavailable');
1741
+ }
1742
+ if (authorFallbackReason) {
1743
+ const childModel = podDelegatedChildLlm(jobArgs)?.model;
1744
+ if (!childModel || inferProviderFromModel(childModel) !== 'openrouter') throw new Error(`pod: planning sol·자식 모델 모두 불가 (${authorFallbackReason})`);
1745
+ authorRequestedModel = authorChoice.model;
1746
+ authorRequestedSource = authorChoice.modelSource;
1747
+ debug.log('self-implement.pod', 'planning-model-fallback', { job: name, provider: 'openrouter', model: childModel, reason: authorFallbackReason, requestedModel: authorChoice.model, account: roleCodexAccount });
1748
+ authorChoice = { ...authorChoice, model: childModel, modelSource: 'fallback-child' };
1749
+ } else debug.log('self-implement.pod', 'role-llm-armed', { job: name, role: 'planning', model: authorChoice.model, source: authorChoice.modelSource, account: roleCodexAccount });
1750
+ }
1667
1751
  const hostKey = (k: string): string | undefined => k === 'OPENROUTER_API_KEY' && openrouter ? openrouterKey : k === 'ANTHROPIC_API_KEY' && anthropic ? anthropicKey : env[k] ?? (options.readKeyCache ?? defaultReadKeyCache)(k);
1752
+ const hostFallbackNames = (options.fallbackConfig ?? getUserConfig)().llm.fallbackChain;
1753
+ const normalizedFallback = normalizeFallbackChain(hostFallbackNames);
1754
+ const fallbackChain = { steps: normalizedFallback.chain, source: normalizedFallback.usedDefault ? 'default' as const : 'host' as const };
1755
+ debug.log('self-implement.pod', 'fallback-chain-carried', {
1756
+ job: name, source: fallbackChain.source, steps: fallbackChain.steps,
1757
+ ...(normalizedFallback.dropped.length ? { droppedCount: normalizedFallback.dropped.length } : {}),
1758
+ });
1668
1759
  const secret = {
1669
1760
  apiVersion: 'v1', kind: 'Secret', type: 'Opaque',
1670
1761
  metadata: { name: `${name}-creds`, namespace, labels: { 'elanous.job': name } },
1671
1762
  stringData: {
1672
1763
  ...(anthropic || bedrockChild || zaiChild ? {}
1673
- : openrouter ? (reviewerCredential ? { 'elanous-auth.json': reviewerCredential.elanousAuth, 'codex-auth.json': reviewerCredential.codexAuth } : {})
1764
+ : openrouter ? (roleCodexCredential ? { 'elanous-auth.json': roleCodexCredential.elanousAuth, 'codex-auth.json': roleCodexCredential.codexAuth } : {})
1674
1765
  : grok
1675
1766
  ? ('grokAuth' in creds && creds.grokAuth
1676
1767
  ? { 'grok-auth.json': creds.grokAuth }
@@ -1679,6 +1770,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1679
1770
  ? Object.fromEntries(codexCredentials.map((candidate, i) => [`codex-${i}.json`, JSON.stringify({ elanousAuth: candidate.elanousAuth, codexAuth: candidate.codexAuth })]))
1680
1771
  : { 'elanous-auth.json': (creds as ReturnType<typeof hostCredentials>).elanousAuth, 'codex-auth.json': (creds as ReturnType<typeof hostCredentials>).codexAuth }),
1681
1772
  'gh-token': podGhToken, feature: input.feature,
1773
+ 'llm-fallback-config.json': JSON.stringify({ llm: { fallbackChain: fallbackChain.steps } }),
1682
1774
  ...(goalDocument !== undefined ? { 'goal-doc': goalDocument } : {}),
1683
1775
  ...Object.fromEntries(Object.entries(skillEnvs).map(([n, text]) => [`skillenv-${n}`, text])),
1684
1776
  ...(grounding ? { [`env-${GROUNDING_TOKEN_ENV}`]: grounding.token } : {}),
@@ -1775,7 +1867,10 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1775
1867
  const removed = kubectl(['-n', namespace, 'delete', 'job', name, '--ignore-not-found', '--wait=true']);
1776
1868
  if (removed.status !== 0) return { exitCode: 1, output: removed.stderr, error: { code: 'pod-delete', message: removed.stderr.trim() } };
1777
1869
  }
1778
- const s = kubectl(['apply', '-f', '-'], JSON.stringify(secret));
1870
+ const applySecret = () => kubectl(['apply', '-f', '-'], JSON.stringify(secret));
1871
+ let s = applySecret();
1872
+ // K3S-SECRET-DB-LOCK-RETRY — k3s sqlite «database is locked» 는 백오프 재시도 · 소진 시에만 아래 pod-secret 실패.
1873
+ if (kubectlTransientReason(s)) s = await retryKubectlTransient(applySecret, s, { sleep, category: 'pod.secret', data: { job: name, namespace, context } });
1779
1874
  if (s.status !== 0) return { exitCode: 1, output: s.stderr, error: { code: 'pod-secret', message: s.stderr.trim() } };
1780
1875
  const jobPassEnv = [
1781
1876
  ...passEnv,
@@ -1786,12 +1881,16 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1786
1881
  const detail = selectLiveDetail(options.liveDetailFile ? { path: options.liveDetailFile } : {}).state;
1787
1882
  const detailUntil = detail && (detail.scope === 'all' || detail.scope === parentRunId || detail.scope === launchRunId) && detail.until > Date.now()
1788
1883
  ? String(detail.until) : undefined;
1789
- const armEnv = Object.fromEntries(Object.entries(options.armEnv ?? {}).filter(([key]) => key !== 'ELANOUS_LIVE_DETAIL_UNTIL' && key !== 'ELANOUS_PROMPT_ENHANCE_MODEL' && key !== 'ELANOUS_PROMPT_ENHANCE_EFFORT' && key !== POD_GITHUB_CREDENTIAL_TOKEN_ENV && key !== POD_GITHUB_CREDENTIAL_URL_ENV && (!hostRefresh || !['GH_TOKEN', 'GITHUB_TOKEN', 'GH_CONFIG_DIR'].includes(key))));
1884
+ const armEnv = Object.fromEntries(Object.entries(options.armEnv ?? {}).filter(([key]) => key !== 'ELANOUS_LIVE_DETAIL_UNTIL' && !key.startsWith('ELANOUS_PROMPT_ENHANCE_') && key !== POD_GITHUB_CREDENTIAL_TOKEN_ENV && key !== POD_GITHUB_CREDENTIAL_URL_ENV && (!hostRefresh || !['GH_TOKEN', 'GITHUB_TOKEN', 'GH_CONFIG_DIR'].includes(key))));
1790
1885
  const seat = env.ELANOUS_HARNESS_SEAT;
1791
- const authorOnPod = env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !goalDoc && !shard;
1792
- const authorChoice = authorOnPod ? selectEnhanceLlm({ config: (options.authorConfig ?? getUserConfig)() }, env) : undefined;
1793
1886
  const authorEnv = authorChoice ? {
1794
- ...(authorChoice.modelSource !== 'default' ? { ELANOUS_PROMPT_ENHANCE_MODEL: authorChoice.model } : {}),
1887
+ ...(authorChoice.modelSource !== 'default' || inferProviderFromModel(authorChoice.model) === 'openai-codex' ? {
1888
+ ELANOUS_PROMPT_ENHANCE_MODEL: authorChoice.model,
1889
+ ELANOUS_PROMPT_ENHANCE_MODEL_RELAY: 'pod',
1890
+ ELANOUS_PROMPT_ENHANCE_MODEL_SOURCE: authorChoice.modelSource,
1891
+ ...(authorFallbackReason ? { ELANOUS_PROMPT_ENHANCE_MODEL_FALLBACK_REASON: authorFallbackReason } : {}),
1892
+ ...(authorRequestedModel ? { ELANOUS_PROMPT_ENHANCE_REQUESTED_MODEL: authorRequestedModel, ELANOUS_PROMPT_ENHANCE_REQUESTED_SOURCE: authorRequestedSource! } : {}),
1893
+ } : {}),
1795
1894
  ...(authorChoice.effortSource !== 'default' ? { ELANOUS_PROMPT_ENHANCE_EFFORT: authorChoice.effort } : {}),
1796
1895
  } : {};
1797
1896
  const budgetRead = hostBudgetSnapshot(podDelegatedChildLlm(jobArgs) ?? {}, options, env, name);
@@ -1839,7 +1938,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1839
1938
  slotId: env.ELANOUS_POD_SLOT_ID,
1840
1939
  work: !goalDoc && env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'authoring' : (oomRetried ? retryTier : memoryTier) === 'lite' ? 'lite' : 'harness',
1841
1940
  };
1842
- const job = podJobManifest({ name, namespace, image: jobImage, workIdentity, ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...(options.source ? { source: options.source } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: options.deadlineSeconds ?? POD_JOB_DEADLINE_SECONDS, ...(goalDoc ? { goalDoc } : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? { authorSentence: true, ...(env.ELANOUS_POD_AUTHOR_GRADE === 'lite' || env.ELANOUS_POD_AUTHOR_GRADE === 'full' ? { authorGrade: env.ELANOUS_POD_AUTHOR_GRADE } : {}) } : {}), runId: launchRunId, ...(parentRunId ? { parentRunId } : {}), ...(jobArmEnv ? { armEnv: jobArmEnv } : {}), hostId: resolveHostId(env), skillEnvs: Object.keys(skillEnvs), memoryLimit, memoryRequest, imageCommit: options.imageCommit !== undefined ? options.imageCommit : options.kubectl ? null : podImageFreshness({ image }).imageCommit, ...(grok ? { grokCredential: 'grokAuth' in creds && creds.grokAuth ? 'subscription' as const : 'api_key' as const } : {}), ...(codexAccounts ? { codexAccounts } : {}), ...(hostRefresh ? { appCredential: true } : {}), execution: { key: executionKey, attempt: oomRetried ? 2 : 1 }, hostLeaseAdmitted: !!releaseAdmission, ...(reviewerCredential ? { reviewerCodexAuth: true } : {}), ...(bedrockSpec ? { bedrock: bedrockSpec } : {}), ...(zaiSpec ? { zai: zaiSpec } : {}) }); // kubectl 주입(=시험)이면 docker 를 부르지 않는다
1941
+ const job = podJobManifest({ name, namespace, fallbackChain, image: jobImage, workIdentity, ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...(options.source ? { source: options.source } : {}), ...(options.repairCommitOnly ? { repairCommitOnly: options.repairCommitOnly } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: options.deadlineSeconds ?? POD_JOB_DEADLINE_SECONDS, ...(goalDoc ? { goalDoc } : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? { authorSentence: true, ...(env.ELANOUS_POD_AUTHOR_GRADE === 'lite' || env.ELANOUS_POD_AUTHOR_GRADE === 'full' ? { authorGrade: env.ELANOUS_POD_AUTHOR_GRADE } : {}) } : {}), runId: launchRunId, ...(parentRunId ? { parentRunId } : {}), ...(jobArmEnv ? { armEnv: jobArmEnv } : {}), hostId: resolveHostId(env), skillEnvs: Object.keys(skillEnvs), memoryLimit, memoryRequest, imageCommit: options.imageCommit !== undefined ? options.imageCommit : options.kubectl ? null : podImageFreshness({ image }).imageCommit, ...(grok ? { grokCredential: 'grokAuth' in creds && creds.grokAuth ? 'subscription' as const : 'api_key' as const } : {}), ...(codexAccounts ? { codexAccounts } : {}), ...(hostRefresh ? { appCredential: true } : {}), execution: { key: executionKey, attempt: oomRetried ? 2 : 1 }, hostLeaseAdmitted: !!releaseAdmission, ...(roleCodexCredential ? { reviewerCodexAuth: true } : {}), ...(bedrockSpec ? { bedrock: bedrockSpec } : {}), ...(zaiSpec ? { zai: zaiSpec } : {}) }); // kubectl 주입(=시험)이면 docker 를 부르지 않는다
1843
1942
  const carriedBranch = goalDoc ? 'goal-doc' as const : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'author' as const : undefined;
1844
1943
  const carriedChildLlm = carriedBranch ? podDelegatedChildLlm(jobArgs) : undefined;
1845
1944
  const a = kubectl(['apply', '-f', '-'], JSON.stringify(job));
@@ -2047,6 +2146,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2047
2146
  }
2048
2147
  // Pod 안 경로는 호스트에서 쓸 수 없다.
2049
2148
  let disposition = parsed ? { ...parsed, worktreePath: undefined } : undefined;
2149
+ if (options.repairCommitOnly && state === 'complete' && !repairArtifactReady) {
2150
+ disposition = { ...disposition, worktreePath: undefined, ok: false, stage: 'repair-artifact-missing', detail: 'Pod repair result or bundle was not collected' };
2151
+ }
2050
2152
  if (input.autoMerge && state === 'complete' && disposition?.stage === 'merge-ready') {
2051
2153
  const prNumber = disposition.prNumber;
2052
2154
  const headCommit = disposition.checkedHeadCommit;
@@ -2097,13 +2199,35 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2097
2199
  debug.log('harness.host-regate', 'unmeasured', { pr: prNumber ?? null, files: [], os: process.platform, failedStep: 'pod-result' });
2098
2200
  regate = { passed: false, failures: [{ step: 'pod-result', detail: 'missing PR number or checked head commit' }], os: process.platform };
2099
2201
  } else {
2202
+ let hostRoot: string | undefined;
2203
+ let hostCwd: string | undefined;
2100
2204
  try {
2101
- const hostRoot = findGitDir(process.cwd())?.root;
2205
+ hostCwd = process.cwd();
2206
+ hostRoot = findGitDir(hostCwd)?.root;
2102
2207
  if (!hostRoot) throw new Error('host repository unavailable');
2103
2208
  regate = await (options.hostRegate ?? runHostRegate)({ prNumber, headCommit, repoRoot: hostRoot, ...(goalFile ? { goalFile } : {}), ...(taLandOwner ? { noMerge: true as const } : {}) });
2104
2209
  } catch (error) {
2105
2210
  debug.log('harness.host-regate', 'unmeasured', { pr: prNumber, files: [], os: process.platform, failedStep: 'host-regate' });
2106
- regate = { passed: false, failures: [{ step: 'host-regate', detail: error instanceof Error ? error.message : String(error) }], os: process.platform };
2211
+ regate = { passed: false, ...(taLandOwner ? { status: 'unmeasured' as const } : {}), failures: [{ step: 'host-regate', detail: error instanceof Error ? error.message : String(error) }], os: process.platform };
2212
+ }
2213
+ if (taLandOwner && !hostRoot && hostRepositoryUnavailable(regate)) {
2214
+ let recordedRoot: string | undefined;
2215
+ try {
2216
+ const recorded = loadRunLedger(ledgerRunId, ledgerDir)?.find((entry) => entry.event === 'start')?.data.targetRoot;
2217
+ if (typeof recorded === 'string' && isAbsolute(recorded)) {
2218
+ const foundRoot = findGitDir(recorded)?.root;
2219
+ // The recorded path must itself name the repository root, including symlink aliases.
2220
+ if (foundRoot && realpathSync(foundRoot) === realpathSync(recorded)) recordedRoot = foundRoot;
2221
+ }
2222
+ } catch { /* unreadable ledger or path leaves the original unmeasured result intact */ }
2223
+ if (recordedRoot) {
2224
+ try {
2225
+ regate = await (options.hostRegate ?? runHostRegate)({ prNumber, headCommit, repoRoot: recordedRoot, ...(goalFile ? { goalFile } : {}), noMerge: true });
2226
+ } catch (error) {
2227
+ regate = { passed: false, status: 'unmeasured', failures: [{ step: 'host-regate', detail: error instanceof Error ? error.message : String(error) }], os: process.platform };
2228
+ }
2229
+ debug.log('harness.host-regate', 'regate-retry', { pr: prNumber, from: hostCwd, to: recordedRoot, result: regate.status ?? (regate.passed ? 'passed' : 'failed') });
2230
+ }
2107
2231
  }
2108
2232
  }
2109
2233
  // runHostRegate comments on its own failures; these two paths never reached it.
@@ -2410,8 +2534,16 @@ export function reemitPodUsage(logs: string, job: string, log: (category: string
2410
2534
  const rows = parsed.rows ?? [];
2411
2535
  for (const r of rows) {
2412
2536
  const cost = podRowCost(r, reprice);
2537
+ const role = typeof r.role === 'string' && r.role.trim() ? r.role : undefined;
2538
+ const stage = typeof r.stage === 'string' && r.stage.trim() ? r.stage : undefined;
2539
+ const account = typeof r.account === 'string' && r.account.trim() ? r.account : undefined;
2413
2540
  log('llm.usage', 'llm-usage', {
2414
2541
  site: `pod-rollup:${String(r.site)}`, provider: r.provider, model: r.model, calls: r.calls,
2542
+ // Preserve only source-observed dimensions. A Pod bucket can contain the
2543
+ // same model under several roles, so these also distinguish dedup keys.
2544
+ ...(role !== undefined ? { role } : {}),
2545
+ ...(stage !== undefined ? { stage } : {}),
2546
+ ...(account !== undefined ? { account } : {}),
2415
2547
  inputTokens: r.inputTokens, outputTokens: r.outputTokens, cacheReadInputTokens: r.cacheReadInputTokens,
2416
2548
  // ⭐ 캐시 쓰기 — 옛 Pod 이미지 rollup 엔 칸이 없다 ⇒ 없으면 «잰 0» 으로 꾸미지 않고 뺀다.
2417
2549
  ...(r.cacheCreationInputTokens !== undefined ? { cacheCreationInputTokens: r.cacheCreationInputTokens } : {}),
@@ -2424,7 +2556,7 @@ export function reemitPodUsage(logs: string, job: string, log: (category: string
2424
2556
  // 부분(seq 달라도)·최종·abort⊕resume 재방출이 몇 번 만나도 집계(rollup)에서 한 번만 센다. 키 없는 기존 행은 종전대로.
2425
2557
  // ⭐ METER-POD-ROLLUP-GAP-2 — podName 을 키에 넣는다: gh-login·usage-limit 재시도는 «같은 job 이름·runId» 로 새 Pod 를 띄우므로
2426
2558
  // (podJobName 은 spaceId 결정적) 그것 없이는 서로 다른 시도의 사용량이 한 번으로 접혀 앞 시도분이 사라진다.
2427
- podRollupKey: `${job}|${parsed.podName ?? ''}|${parsed.runId ?? ''}|pod-rollup:${String(r.site)}|${String(r.provider)}|${String(r.model)}`,
2559
+ podRollupKey: `${job}|${parsed.podName ?? ''}|${parsed.runId ?? ''}|pod-rollup:${String(r.site)}|${String(r.provider)}|${String(r.model)}${role !== undefined || stage !== undefined || account !== undefined ? `|${JSON.stringify([role ?? null, stage ?? null, account ?? null])}` : ''}`,
2428
2560
  ...(parsed.podName ? { podName: parsed.podName } : {}), ...(parsed.nodeName ? { nodeName: parsed.nodeName } : {}), ...(parsed.hostId ? { podHostId: parsed.hostId } : {}),
2429
2561
  // ⭐ PARTIAL 폴백 재방출 꼬리표 — 최종 줄 행은 그대로(부분이 아님을 꾸미지 않는다).
2430
2562
  ...(partialLine ? { partial: true, ...(parsed.seq !== undefined ? { partialSeq: parsed.seq } : {}), ...(parsed.at !== undefined ? { partialAt: parsed.at } : {}), ...(livePartial ? { partialSource: 'live-capture' } : {}) } : {}),