elanous 0.2.36 → 0.2.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (741) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 1026-44010f405704050c.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
  6. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 1632.7d87f998e714bede.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
  14. package/apps/pwa/out/_next/static/chunks/{7784.1f0ac4a16d190cf4.js → 2104.70e086d5174a4736.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{6566.926a1d1b7c911442.js → 214.186a430da28338f1.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
  18. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
  19. package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 2415.738b777642a02233.js} +1 -1
  20. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 3086.fb14b60ce98b53d3.js} +1 -1
  27. package/apps/pwa/out/_next/static/chunks/{3148-98efd4869d660a87.js → 3124-561f7f037943cde2.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
  31. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 3291.f6c1005387d514bd.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
  34. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
  38. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 3528.e4b8ab70d339f965.js} +2 -2
  40. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
  45. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{3031-85328a92fcce4da6.js → 4199-f7c6eb40cd0322f8.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
  57. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +90 -0
  58. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
  60. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
  63. package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
  65. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
  68. package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 5307.d7328020227880c2.js} +4 -4
  70. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
  73. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5638.107314dc479e2f37.js} +2 -2
  75. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
  80. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/{6925.562d532110879886.js → 6493.27ad77de7aac7966.js} +1 -1
  84. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +62 -0
  88. package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 7161-8f22db3ec5ed005e.js} +3 -3
  89. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 7488.966b116789f3d41a.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/{4116.a84a92a2492c080e.js → 7524.ce973525d30b3d52.js} +1 -1
  94. package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
  95. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 7628.6b16863ac3972333.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 7954.4f7a8832663ee979.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 8019.21ca554a821dad01.js} +16 -16
  102. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 8487.291666583bebe640.js} +1 -1
  107. package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 8879.ac06755bcf3e44a1.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
  111. package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 8911.bf5e712acb25fb6c.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 8994d93e.33ba491f95345fc2.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{599.c39c571b6733f2a2.js → 9223.cbcc88e0e9950426.js} +2 -2
  115. package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
  116. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
  117. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{8037.e254fd797aa224d1.js → 9581.da63ddf41acfad46.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
  121. package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/{page-e7abc34a48a6f71e.js → page-291ab19fe2acb173.js} +1 -1
  153. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-c15958835534404b.js → page-6b140f77593576eb.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → b7459770.6539b11860eb8a9c.js} +7 -7
  174. package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → b7478fef.5917716286213fcc.js} +3 -3
  175. package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/{2812ca6a.3b9f4a7a08885744.js → de8b930d.d94c0f42acf807fc.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → eaad0cba.771200940c529df7.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
  184. package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/graphs/drafts/recipes.yaml +27 -7
  279. package/graphs/release/recipes.yaml +9 -0
  280. package/graphs/release/release-loop.yaml +26 -18
  281. package/graphs/work/draft-close.yaml +54 -0
  282. package/graphs/work/green-close.yaml +37 -0
  283. package/graphs/work/recipes.yaml +46 -1
  284. package/graphs/work/run-research.yaml +35 -0
  285. package/package.json +1 -1
  286. package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
  287. package/scripts/ask-op-inbox-once.ts +17 -0
  288. package/scripts/boundary-proof-mapping-audit.ts +88 -0
  289. package/scripts/brand/check.ts +13 -4
  290. package/scripts/codex-fallback-live-probe.ts +17 -15
  291. package/scripts/fleet/node-setup.sh +32 -2
  292. package/scripts/fleet/run-light-worker.sh +9 -0
  293. package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
  294. package/scripts/gate-0226-failure-census.ts +546 -0
  295. package/scripts/goals/authoring-metrics.ts +258 -0
  296. package/scripts/graph-units/draft-close-node.ts +222 -0
  297. package/scripts/hook-order-sweep.ts +7 -4
  298. package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
  299. package/scripts/land-global-checks.ts +69 -1
  300. package/scripts/measure-nl-routing-corpus.ts +207 -2
  301. package/scripts/provision-export-redactions.ts +15 -0
  302. package/scripts/public-copy-lint.ts +122 -0
  303. package/scripts/public-export.ts +69 -2
  304. package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
  305. package/scripts/ratchets/train-side-invariants.sh +7 -1
  306. package/scripts/release-loop/cut-branch.ts +61 -12
  307. package/scripts/release-loop/docs-node.ts +140 -0
  308. package/scripts/release-loop/gate-closure.ts +48 -0
  309. package/scripts/release-loop/gate-diff.ts +2 -1
  310. package/scripts/release-loop/gate-node.ts +161 -25
  311. package/scripts/release-loop/gate-partial.ts +82 -3
  312. package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
  313. package/scripts/release-loop/gate-radius-live.ts +4 -2
  314. package/scripts/release-loop/known-issues-node.ts +6 -4
  315. package/scripts/release-loop/notes-repair.ts +216 -0
  316. package/scripts/release-loop/prepare-node.ts +61 -5
  317. package/scripts/release-loop/resume-cap.ts +2 -1
  318. package/scripts/release-loop/resume-release.ts +406 -7
  319. package/scripts/release-loop/resume-test-traffic.ts +10 -0
  320. package/scripts/release-loop/resume.ts +13 -5
  321. package/scripts/release-loop/traffic-node.ts +12 -4
  322. package/scripts/release-loop/traffic-transition.ts +53 -13
  323. package/scripts/release-loop/version-node.ts +109 -15
  324. package/scripts/train/green-leg.ts +176 -0
  325. package/scripts/tui-continue-real-evidence.ts +47 -0
  326. package/scripts/ux-sim.ts +1 -1
  327. package/scripts/video-pipeline.ts +2 -2
  328. package/src/acp/client.ts +31 -5
  329. package/src/acp/core-turn-bridge.ts +12 -1
  330. package/src/acp/stderr-summary.ts +49 -0
  331. package/src/agent/monad-agent-turn.ts +1 -0
  332. package/src/agent/run-context.ts +1 -1
  333. package/src/agent/task-notification.ts +3 -1
  334. package/src/agent/terminal-surface.ts +217 -0
  335. package/src/agent-substrate/pr-reviewer.ts +11 -3
  336. package/src/agent-substrate/review-observation.ts +10 -0
  337. package/src/agent-substrate/self-review-cli.ts +537 -57
  338. package/src/auto-research/question-ladder-contract.ts +137 -0
  339. package/src/auto-research/research-turn.ts +134 -0
  340. package/src/autopilot/discovery/doc-lint.ts +1 -1
  341. package/src/autopilot/lineage/sources.ts +1 -1
  342. package/src/autopilot/pr-manager.ts +64 -13
  343. package/src/boot/daemon-runtime.ts +35 -3
  344. package/src/boot/daemon-tools/pty-shell.ts +2 -1
  345. package/src/bots/screen-probe.ts +1 -1
  346. package/src/budget/run-usage-rollup.ts +12 -7
  347. package/src/budget/unified-usage.ts +20 -0
  348. package/src/capture/tui-self-report.ts +42 -5
  349. package/src/chat/index.ts +1 -0
  350. package/src/chat/tool-render/dispatch.ts +8 -1
  351. package/src/cli/autopilot-cli.ts +24 -9
  352. package/src/cli/decisions-cli.ts +7 -4
  353. package/src/cli/doctor-cli.ts +116 -7
  354. package/src/cli/guardian-cli.ts +3 -1
  355. package/src/cli/intake-cli.ts +48 -12
  356. package/src/cli/lesson-cli.ts +69 -9
  357. package/src/cli/logs-cli.ts +357 -2
  358. package/src/cli/memory-cli.ts +30 -1
  359. package/src/cli/msg-cli.ts +15 -11
  360. package/src/cli/pr-granularity.ts +5 -3
  361. package/src/cli/pr-land-overlap-evidence.ts +38 -5
  362. package/src/cli/pr-land-refusal.ts +1 -1
  363. package/src/cli/pty-takeover-cli.ts +58 -5
  364. package/src/cli/release-checklist-read-cli.ts +112 -4
  365. package/src/cli/release-cli.ts +89 -18
  366. package/src/cli/review-carry.ts +77 -0
  367. package/src/cli/self-update.ts +24 -6
  368. package/src/cli/self-utterances-cli.ts +13 -16
  369. package/src/cli/tasks-card-show.ts +31 -1
  370. package/src/cli/tasks-cli.ts +370 -33
  371. package/src/cli/tasks-read-cli.ts +13 -5
  372. package/src/cli/usage-cli.ts +12 -10
  373. package/src/context-bus/claude-memory-import.ts +99 -0
  374. package/src/context-bus/context-now.ts +86 -2
  375. package/src/context-bus/long-term-memory.ts +125 -0
  376. package/src/core-turn/run-core-turn.ts +9 -2
  377. package/src/core-turn/run-goal-loop.ts +5 -2
  378. package/src/core-turn/types.ts +5 -0
  379. package/src/dashboard/chat/acp-chat.ts +9 -0
  380. package/src/dashboard/index.ts +115 -30
  381. package/src/dashboard/input/agent-wake.ts +43 -0
  382. package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
  383. package/src/dashboard/input/terminal-modal-router.ts +8 -159
  384. package/src/dashboard/replay-preview.ts +25 -0
  385. package/src/dashboard/side-basic-runtime.ts +61 -0
  386. package/src/dashboard/slash-runtime/dashboard-handlers.ts +19 -8
  387. package/src/dashboard/synchronized-frame-output.ts +74 -0
  388. package/src/dashboard/term-slash-runtime.ts +2 -0
  389. package/src/dashboard/turn-preamble.ts +28 -4
  390. package/src/display/coordinator.ts +45 -12
  391. package/src/display/resize-listener.ts +41 -20
  392. package/src/display/synchronized-output-region.ts +60 -0
  393. package/src/domains/guardian-tick.ts +9 -0
  394. package/src/domains/surface-events.ts +80 -1
  395. package/src/exec-requests/planner.ts +37 -2
  396. package/src/execution-loop/launch-gate.ts +4 -3
  397. package/src/git-fs/cli-stderr.ts +45 -0
  398. package/src/git-fs/gh-cli.ts +6 -3
  399. package/src/git-fs/git-cli.ts +11 -5
  400. package/src/git-fs/watcher.ts +27 -22
  401. package/src/git-fs/worktree.ts +19 -3
  402. package/src/graph-runner/graph-cli.ts +26 -2
  403. package/src/graph-runner/graph-grow.ts +37 -9
  404. package/src/graph-runner/graph-run-api.ts +3 -2
  405. package/src/graph-runner/runner.ts +34 -7
  406. package/src/graph-wizard/generate.ts +29 -6
  407. package/src/grok/credential.ts +107 -36
  408. package/src/harness/harness-cli-command.ts +179 -33
  409. package/src/harness/review-adapter.ts +26 -6
  410. package/src/hq/fence-wrapper.ts +1 -1
  411. package/src/hq/transfer.ts +1 -1
  412. package/src/index.ts +151 -18
  413. package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
  414. package/src/intake-plane/collect-telegram-saved.ts +54 -5
  415. package/src/interactive-terminal-modal.ts +3 -0
  416. package/src/keybindings.ts +17 -22
  417. package/src/llm/provider-credentials.ts +1 -1
  418. package/src/llm/route-decision.ts +13 -0
  419. package/src/llm-tool-name.ts +37 -0
  420. package/src/llm-tool-schema.ts +55 -0
  421. package/src/llm.ts +203 -21
  422. package/src/loops/checker.ts +100 -0
  423. package/src/loops/consensus.ts +26 -2
  424. package/src/loops/loop-cli.ts +9 -4
  425. package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
  426. package/src/loops/orchestrator/inbox-once.ts +28 -0
  427. package/src/loops/orchestrator/inbox.ts +130 -1
  428. package/src/loops/orchestrator/tick.ts +55 -7
  429. package/src/maturity/feature-maturity.ts +1 -0
  430. package/src/model-tier/llm-tier-map.ts +12 -17
  431. package/src/msg/msg-store.ts +17 -0
  432. package/src/native-tool-catalog.ts +1 -1
  433. package/src/nexus/api/channel-ask-op.ts +96 -0
  434. package/src/nexus/api/discord-trigger-bot.ts +28 -1
  435. package/src/nexus/api/graph-wizard-api.ts +27 -2
  436. package/src/nexus/api/grid.ts +24 -4
  437. package/src/nexus/api/http-server.ts +1 -1
  438. package/src/nexus/api/ops-api.ts +14 -6
  439. package/src/nexus/api/telegram-trigger-bot.ts +24 -0
  440. package/src/nexus/api/terminals.ts +28 -6
  441. package/src/nexus/state/state.ts +7 -1
  442. package/src/oauth/codex-account-store.ts +34 -1
  443. package/src/ops/loops-map.ts +46 -0
  444. package/src/ops/overview-cache.ts +22 -4
  445. package/src/ops/overview.ts +41 -5
  446. package/src/patents/ledger.ts +18 -1
  447. package/src/policy/llm-policy.ts +3 -1
  448. package/src/preview/terminal.ts +4 -2
  449. package/src/prompt-cache/anthropic.ts +2 -0
  450. package/src/prompt-enhance/enhance.ts +9 -4
  451. package/src/pty-shell/availability.ts +7 -0
  452. package/src/pty-shell/herdr-agent-report.ts +40 -31
  453. package/src/pty-shell/herdr-prune-stale.ts +17 -0
  454. package/src/pty-shell/herdr-sequence-lease.ts +60 -0
  455. package/src/pty-shell/pty-control-ipc.ts +187 -18
  456. package/src/pty-shell/pty-manifest.ts +16 -2
  457. package/src/pty-shell/registry.ts +25 -15
  458. package/src/pty-shell/tui-run-state.ts +235 -1
  459. package/src/release-loop/checklist.ts +50 -5
  460. package/src/release-loop/feature-store.ts +9 -9
  461. package/src/release-loop/gate-shards.ts +61 -0
  462. package/src/release-loop/landed-but-yellow.ts +93 -12
  463. package/src/release-loop/light-rc.ts +7 -4
  464. package/src/release-loop/rehearsal.ts +1 -1
  465. package/src/repl/index.ts +18 -0
  466. package/src/research/axis-fanout.ts +133 -0
  467. package/src/research/edge-decision.ts +88 -0
  468. package/src/research/output-router.ts +127 -0
  469. package/src/research-bridge/format.ts +16 -1
  470. package/src/research-bridge/index.ts +1 -0
  471. package/src/research-bridge/invoke.ts +41 -5
  472. package/src/seat-loop/seat-report.ts +1 -0
  473. package/src/self-dev/ask-launch-flow.ts +86 -10
  474. package/src/self-dev/decompose-proposal.ts +29 -18
  475. package/src/self-dev/decompose.ts +45 -9
  476. package/src/self-dev/dev-pipeline.ts +29 -7
  477. package/src/self-dev/draft-residue.ts +221 -2
  478. package/src/self-dev/draft-sweep.ts +254 -16
  479. package/src/self-dev/draft-triage-rules.ts +19 -5
  480. package/src/self-dev/orchestrate.ts +1 -0
  481. package/src/self-dev/review-provider-fallback.ts +45 -7
  482. package/src/self-dev/run-supervisor.ts +22 -7
  483. package/src/self-dev/shard-plan.ts +48 -0
  484. package/src/self-dev/shard-run.ts +310 -6
  485. package/src/self-implement/comment-only-source.ts +54 -0
  486. package/src/self-implement/doctor-visit.ts +108 -0
  487. package/src/self-implement/gate-artifacts.ts +6 -2
  488. package/src/self-implement/gate-baseline.ts +99 -1
  489. package/src/self-implement/gate-cli.ts +231 -82
  490. package/src/self-implement/gate-failure-signature.ts +44 -0
  491. package/src/self-implement/gate-remote.ts +30 -4
  492. package/src/self-implement/gate-scope.ts +13 -1
  493. package/src/self-implement/goal-author.ts +407 -21
  494. package/src/self-implement/goal-doc/section.ts +22 -0
  495. package/src/self-implement/goal-supervisor-fill.ts +110 -27
  496. package/src/self-implement/importer-test-index.ts +215 -2
  497. package/src/self-implement/knowhow-pack.ts +125 -12
  498. package/src/self-implement/l8-merge-queue.ts +198 -32
  499. package/src/self-implement/off-diff-evidence.ts +23 -0
  500. package/src/self-implement/orchestrator.ts +369 -33
  501. package/src/self-implement/pod-inplace-worktree.ts +82 -0
  502. package/src/self-implement/pod-warm-pool-profile.ts +2 -2
  503. package/src/self-implement/premise-review.ts +7 -5
  504. package/src/self-implement/review-round-brief.ts +300 -0
  505. package/src/self-implement/rework-policy.ts +14 -0
  506. package/src/self-implement/run-ledger.ts +428 -6
  507. package/src/self-implement/run-stop.ts +1 -1
  508. package/src/self-implement/running-runs.ts +17 -3
  509. package/src/self-implement/seams.ts +45 -16
  510. package/src/self-implement/self-implement-cli.ts +26 -2
  511. package/src/self-implement/stop-autoheal.ts +1 -0
  512. package/src/self-implement/test-seams.ts +13 -1
  513. package/src/self-implement/train-reach-grouping.ts +8 -2
  514. package/src/session/channel-ask-op-envelope.ts +36 -0
  515. package/src/session/channel-op-reply-route.ts +200 -0
  516. package/src/session/chat.ts +10 -1
  517. package/src/session/id-prefix.ts +60 -0
  518. package/src/session/index.ts +6 -0
  519. package/src/session-runtime/index.ts +18 -23
  520. package/src/skills/runner.ts +7 -3
  521. package/src/skills/tools/dev-harness.ts +2 -2
  522. package/src/skills/tools/pty.ts +5 -0
  523. package/src/skills/tools/schedule-wakeup.ts +1 -6
  524. package/src/status/bar.ts +3 -3
  525. package/src/status/metrics.ts +12 -1
  526. package/src/steward/rejudge-tick.ts +12 -5
  527. package/src/steward/resync-tick.ts +31 -4
  528. package/src/storage/file-lock.ts +17 -4
  529. package/src/task-agent/actions.ts +199 -4
  530. package/src/task-agent/adopt-pr.ts +63 -2
  531. package/src/task-agent/boundary-proof-mapping.ts +12 -0
  532. package/src/task-agent/boundary-proof-producer.ts +147 -0
  533. package/src/task-agent/completion-evidence.ts +2 -1
  534. package/src/task-agent/evidence-command-normalize.ts +42 -0
  535. package/src/task-agent/export-redactions-provision.ts +43 -0
  536. package/src/task-agent/green-close-recipe.ts +239 -0
  537. package/src/task-agent/green-sweep.ts +64 -10
  538. package/src/task-agent/live-moves.ts +48 -3
  539. package/src/task-agent/map-host-adapter.ts +134 -0
  540. package/src/task-agent/map-reduce.ts +158 -0
  541. package/src/task-agent/map-run-ledger.ts +226 -0
  542. package/src/task-agent/parent-host.ts +74 -17
  543. package/src/task-agent/rejudge-on-head.ts +72 -5
  544. package/src/task-agent/repair-cycle.ts +108 -8
  545. package/src/task-agent/repair-next-move.ts +12 -2
  546. package/src/task-agent/repair-worker.ts +37 -1
  547. package/src/task-agent/review-prior-fix.ts +12 -2
  548. package/src/task-agent/shadow.ts +188 -5
  549. package/src/task-agent/task-hand.ts +253 -20
  550. package/src/task-agent/task-parent-role-llm.ts +9 -0
  551. package/src/task-agent/tier-split.ts +40 -5
  552. package/src/task-agent/work-order.ts +53 -2
  553. package/src/task-orchestrator/dispatcher.ts +46 -1
  554. package/src/task-orchestrator/generator-prompt.ts +6 -0
  555. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
  556. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
  557. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
  558. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
  559. package/src/task-orchestrator/surfaces/pod-pool.ts +77 -8
  560. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
  561. package/src/task-orchestrator/surfaces/self-implement-pod.ts +338 -79
  562. package/src/task-orchestrator/surfaces/self-implement.ts +37 -2
  563. package/src/terminal/session-registry.ts +1 -0
  564. package/src/terminal/terminal-modal-router.ts +156 -0
  565. package/src/testing/linux-env.ts +177 -0
  566. package/src/tool-hints/gate.ts +6 -4
  567. package/src/tool-hints/signals.ts +33 -1
  568. package/src/tui/chat/background-job-status.ts +8 -2
  569. package/src/tui/chat/goal-interim.ts +5 -1
  570. package/src/tui/entry.ts +722 -30
  571. package/src/tui/input/at-picker.ts +55 -0
  572. package/src/tui/sidetab/attach.ts +304 -0
  573. package/src/tui/sidetab/list.ts +176 -0
  574. package/src/tui/sidetab/nl-tool.ts +136 -0
  575. package/src/tui/slash/resume-command.ts +23 -0
  576. package/src/tui/slash/resume.ts +38 -35
  577. package/src/tui/slash/signals.ts +114 -0
  578. package/src/tui/slash/term-next.ts +72 -0
  579. package/src/tui-client/local-chat-turn.ts +31 -9
  580. package/src/user-config.ts +30 -3
  581. package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
  582. package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
  583. package/src/ux-sim/fake-gh.ts +174 -0
  584. package/src/ux-sim/fake-kubectl.ts +142 -0
  585. package/src/ux-sim/fake-llm.ts +17 -6
  586. package/src/ux-sim/next-tui-seat-scenarios.ts +176 -6
  587. package/src/ux-sim/resume-picker-device.ts +173 -0
  588. package/src/ux-sim/session-id-seed.ts +60 -0
  589. package/src/ux-sim/skills-tools-shell-device.ts +156 -0
  590. package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
  591. package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
  592. package/src/version/packed-revision.json +1 -1
  593. package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
  594. package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +0 -64
  600. package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
  601. package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
  604. package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
  609. package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
  612. package/apps/pwa/out/_next/static/chunks/2986.45d7652e4f13557e.js +0 -2
  613. package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
  614. package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
  618. package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
  619. package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
  621. package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/3757-180308bc61021b05.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
  625. package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
  629. package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
  632. package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
  634. package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
  636. package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
  641. package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
  653. package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/7481.39f7a4654907bf6e.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
  664. package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
  666. package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
  667. package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
  672. package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/ccae1c4b-0cf414f5eff1b10d.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
  739. package/scripts/migrate-monad-to-elanous.ts +0 -195
  740. package/scripts/rebrand-elanous.ts +0 -242
  741. /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
@@ -21,7 +21,8 @@ import { POD_CREDENTIAL_TOKEN_ENV, POD_CREDENTIAL_URL_ENV } from '../../grok/cre
21
21
  import { isVerifiedOpenGatewayModel } from '../../llm/opengateway-models.js';
22
22
  import { configuredOpenGatewayKeys } from '../../llm/provider-credentials.js';
23
23
  import { collectPodLedgers, createPodLedgerFollower } from './pod-ledger-collect.js';
24
- import { collectPodArtifacts, podNoResultDiagnostic } from './pod-artifact-return.js';
24
+ import { captureFailedPodJobs } from './pod-ledger-events.js';
25
+ import { collectPodArtifacts, podNoResultDiagnostic, POD_SALVAGE_BUNDLE_FILE_LIMIT, POD_SALVAGE_BUNDLE_TOTAL_LIMIT } from './pod-artifact-return.js';
25
26
  import { readPodRepairArtifact } from './pod-repair-commit.js';
26
27
  import { isValidAccountName, resolveCodexAccount } from '../../oauth/codex-account.js';
27
28
  import { createCodexAccessMirror } from '../../oauth/codex-access-mirror.js';
@@ -31,6 +32,8 @@ import { finishPodFragment, writePodFragment } from '../../harness/self-send-tar
31
32
  import { mintRunId, normalizeRunId } from '../../harness/harness-space.js';
32
33
  import { TA_LAND_ENV } from '../../task-agent/task-hand.js';
33
34
  import { appendRunLedgerEntry, loadRunLedger, runLedgerDir, runLedgerPath, type RunLedgerEntry } from '../../self-implement/run-ledger.js';
35
+ import { recordRunStop } from '../../self-implement/run-stop.js';
36
+ import { gateFailureReceipt, gateFailureReceiptLines } from '../../self-implement/gate-failure-signature.js';
34
37
  import { runSuffixKey } from '../../self-implement/salvage-branches.js';
35
38
  import type { GoalExecutionRecord } from '../../self-implement/orchestrator.js';
36
39
  import { hostRepositoryUnavailable, runHostRegate, type HostRegateResult } from '../../self-implement/host-regate.js';
@@ -67,14 +70,14 @@ export const POD_JOB_DEADLINE_SECONDS = 10_800;
67
70
  import { POD_LAUNCH_FINISHED_EVENT, POD_LAUNCH_STARTED_EVENT, provenanceRowFromAnnotations, siTaskPodProvenance } from './pod-launch-history.js';
68
71
  import { podProvenanceMetadata, type PodProvenanceMetadata } from './pod-provenance.js';
69
72
  import { packageVersion } from '../../version/code-revision.js';
70
- import { podWorkLabels, type PodWorkIdentity, type PodPlacement, type PodPlacementKind, type PodPoolMember, type PodPoolScheduler } from './pod-pool.js';
73
+ import { minihLocationFrom, podWorkLabels, type PodWorkIdentity, type PodPlacement, type PodPlacementKind, type PodPoolMember, type PodPoolScheduler } from './pod-pool.js';
71
74
  export { POD_CHILD_REQUESTS } from './pod-lease.js';
72
75
  import { measurePoolLease, recommendConcurrency, POD_CHILD_REQUESTS, POD_SI_ADMISSION_CAP_BYTES, POD_HOST_LEASE_ANNOTATION, POD_JOB_TTL_AFTER_FINISHED_SECONDS, LEASE_KUBECTL_MAX_BUFFER, memoryQuantityBytes } from './pod-lease.js';
73
76
  import { ACTUAL_SUBSTRATE_ENV, RUN_CONTRACT_ENV, carryRunContract, completionFloorFor } from '../../self-implement/graph-run-contract.js';
74
- import { execFile, spawnSync } from 'node:child_process';
77
+ import { execFile, execFileSync, spawnSync } from 'node:child_process';
75
78
  import { createHash } from 'node:crypto';
76
- import { existsSync, mkdirSync, readFileSync, realpathSync } from 'node:fs';
77
- import { homedir } from 'node:os';
79
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, rmSync } from 'node:fs';
80
+ import { homedir, tmpdir } from 'node:os';
78
81
  import { isAbsolute, join, normalize, relative, resolve, sep } from 'node:path';
79
82
  import { findGitDir } from '../../git-fs/locate.js';
80
83
  import { hostLeaseBaseDir } from '../../pod-lease/host-lease.js';
@@ -84,20 +87,21 @@ import { enterJourneyNode, exitJourneyNode, passJourneyNode } from '../../self-d
84
87
  import { routeJourneyEdge } from '../../self-dev/graph-journey-route.js';
85
88
  import { selectLiveDetail } from '../../live/detail-switch.js';
86
89
  import { authStorePath } from '../../oauth/store.js';
87
- import { grokAuthFilePath, isGrokSubscriptionExpiring, refreshGrokSubscriptionToken, resolveGrokCredential, type GrokRefreshOutcome } from '../../grok/credential.js';
90
+ import { grokAuthFilePath, isGrokSubscriptionExpiring, readSelectedGrokScope, refreshGrokSubscriptionToken, resolveGrokCredential, type GrokRefreshOutcome } from '../../grok/credential.js';
88
91
  import { defaultGrokModel } from '../../grok/models.js';
89
92
  import { resolveHostId } from '../../platform/host-id.js';
90
93
  import { BUDGET_SNAPSHOT_ENV, encodeBudgetSnapshot, harnessLaunchBudgetDecision, type BudgetSnapshot } from '../../execution-loop/launch-gate.js';
91
94
  import type { ReadBudgetInputsDeps } from '../../self-implement/budget-gate.js';
92
95
  import { envLiteral } from '../../platform/env-literal.js';
93
96
  import { LLM_TIER_MAP_BY_PROVIDER, lookupLlmTierSpec, type LlmTierProvider } from '../../model-tier/llm-tier-map.js';
94
- import { parseSelfImplementJson, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
97
+ import { parseSelfImplementJson, type SelfImplementDisposition, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
95
98
  import { codexQuotaPolicyFromConfig } from '../../oauth/codex-account-store.js';
96
99
  import { normalizeFallbackChain, type FallbackStep } from '../../oauth/fallback-chain.js';
97
100
  import { goalTypeOf, type GoalType } from '../../../scripts/measure-pod-memory-by-goal.js';
98
101
  import { declaredGoalType, type GoalType as DeclaredGoalType } from '../../self-implement/goal-author.js';
99
102
  import { readPodMemoryAdvice, type PodMemoryAdvice } from '../../cli/pod-memory-advice.js';
100
103
  import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, getUserConfig, roleLlmEnvName, type UserConfig } from '../../user-config.js';
104
+ import { worktreeAddTimeoutSec } from '../../git-fs/worktree.js';
101
105
  import { podChildProviderOf, podChildProviderRefusal, type PodChildProvider } from './pod-child-providers.js';
102
106
  import { BEDROCK_POD_EGRESS_LABEL, bedrockPodEnv, checkBedrockPodSecret, type BedrockPodSpec } from './pod-bedrock-child.js';
103
107
  import { resolveBedrockRegion, validBedrockRegion } from '../../llm/bedrock.js';
@@ -105,7 +109,7 @@ import { ZAI_POD_EGRESS_LABEL, checkZaiPodSecret, countActiveZaiJobs, decideZaiP
105
109
  import { ZAI_CODING_DEFAULT_MODEL, ZAI_OPENROUTER_FALLBACK_MODEL, zaiSettingsFromConfig, type ZaiCodingPlanSettings } from '../../llm/zai-coding-plan.js';
106
110
  import { normalizePlanningFallbackReason, selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
107
111
  import { inferProviderFromModel } from '../../llm.js';
108
- import { classifyPodExit, extractPodFailureReason, podChildFailureAttribution, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
112
+ import { classifyPodExit, extractPodFailureReason, podChildFailureAttribution, podDeadlineResultMarker, podJobConditionReason, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
109
113
  import { kubectlTransientReason, retryKubectlTransient } from './kubectl-transient-retry.js';
110
114
  import { OLD_DOOR_STAMP_ENV } from '../../self-dev/old-door.js';
111
115
  import { resolveDefaultSourceHead, seedMirrorOnce, type MirrorSeedResult } from './pod-mirror-seed.js';
@@ -228,6 +232,8 @@ export interface PodSpawnOptions {
228
232
  /** LAUNCH-STALL: ms a launch may wait in one stage before `launch-stalled` (test seam; default harness.launchStallMinutes · 15 min). */
229
233
  launchStallMs?: number;
230
234
  kubectl?: Kubectl;
235
+ /** Capture SSH transport test seam; host selection and placement validation remain in the production path. */
236
+ failureCaptureRemote?: (host: string, args: readonly string[]) => ReturnType<Kubectl>;
231
237
  /** Host-side regate (injected for Pod tests). */
232
238
  hostRegate?: (input: { prNumber: number; headCommit: string; repoRoot: string; goalFile?: string; noMerge?: true }) => Promise<HostRegateResult>;
233
239
  /** REVIEW-ACP-POD — Pod merge-ready PR 을 호스트 Claude ACP 로 리뷰한 뒤 재게이트(opt-in · 옵션 → env `ELANOUS_POD_HOST_ACP_REVIEW` → config `llm.podHostAcpReview`). */
@@ -522,15 +528,6 @@ export function formatGrokRemaining(ms: number | null): string {
522
528
  return m >= 60 ? `${Math.floor(m / 60)}h${String(m % 60).padStart(2, '0')}m` : `${m}m`;
523
529
  }
524
530
 
525
- /** Latest `expires_at` among scopes that carry an access key (the token the Pod would get). */
526
- function grokSubscriptionExpiresAtMs(home?: string): number | null {
527
- try {
528
- const scopes = JSON.parse(readFileSync(grokAuthFilePath(home), 'utf8')) as Record<string, { key?: unknown; expires_at?: unknown }>;
529
- const all = Object.values(scopes).flatMap((s) => (s && typeof s.key === 'string' && s.key && typeof s.expires_at === 'string' && Number.isFinite(Date.parse(s.expires_at)) ? [Date.parse(s.expires_at)] : []));
530
- return all.length ? Math.max(...all) : null;
531
- } catch { return null; }
532
- }
533
-
534
531
  /** POD-GROK-VALIDITY-FIT — this launch's Job deadline for a refresh-less grok subscription copy.
535
532
  * · relay (the Pod can renew from the host) or unknown expiry → the requested deadline as is.
536
533
  * · otherwise → min(requested, remaining − margin); below the minimum Job (time passed since the credential check)
@@ -570,38 +567,46 @@ export function podGhLoginRetryBackoffMs(job: string): number {
570
567
  export function hostGrokCredentials(opts: {
571
568
  home?: string; env?: NodeJS.ProcessEnv; apiKeyOptIn?: boolean; ghToken?: () => string;
572
569
  /** Test seams — the host refresh (read-only `grok models`) and the expiry probe. */
573
- refresh?: () => void; isExpiring?: () => boolean;
570
+ refresh?: () => void; isExpiring?: () => boolean; grokPath?: string;
574
571
  /** Required remaining token life (default POD_GROK_MIN_VALIDITY_MS) — a caller whose Job is not fitted passes its own deadline. */
575
572
  minValidityMs?: number; now?: () => number;
576
573
  } = {}): { grokAuth?: string; grokApiKey?: string; ghToken: string } {
577
574
  let credential = resolveGrokCredential({ home: opts.home, env: opts.env });
578
575
  if (credential?.kind === 'subscription') {
576
+ const initialScope = readSelectedGrokScope(opts.home);
577
+ if (!initialScope) throw new Error('grok: 선택된 구독 scope 없음 — 발사를 거부');
579
578
  const minValidityMs = opts.minValidityMs ?? POD_GROK_MIN_VALIDITY_MS;
580
- const expiring = opts.isExpiring ?? (() => isGrokSubscriptionExpiring({ home: opts.home, bufferMs: minValidityMs, ...(opts.now ? { now: opts.now } : {}) }));
581
- if (expiring()) {
582
- try { (opts.refresh ?? (() => { refreshGrokSubscriptionToken({ home: opts.home }); }))(); } catch { /* judged below */ }
583
- if (expiring()) {
584
- const at = grokSubscriptionExpiresAtMs(opts.home);
585
- const remainingMs = at === null ? null : at - (opts.now ?? Date.now)();
586
- try { debug.log('pod.grok-credentials', 'refused', { remainingMs, minValidityMs, expiresAt: at === null ? null : new Date(at).toISOString() }); } catch { /* fail-soft */ }
587
- throw new Error(`grok: 구독 access 토큰 남은 시간 ${formatGrokRemaining(remainingMs)} < Pod 발사 기준 ${formatGrokRemaining(minValidityMs)} — 호스트 갱신(grok models)도 못 늘렸다 · 다음: 호스트에서 grok login --device-auth 후 다시`);
579
+ const clock = opts.now ?? Date.now;
580
+ const initialExpiry = initialScope.expiresAt ? Date.parse(initialScope.expiresAt) : NaN;
581
+ const expiring = opts.isExpiring ? opts.isExpiring()
582
+ : !Number.isFinite(initialExpiry) || initialExpiry - clock() < minValidityMs;
583
+ if (expiring) {
584
+ if (!initialScope.hasRefreshToken) {
585
+ throw new Error('grok: 선택된 구독 scope에 refresh token 없음 — 다른 계정으로 대체하지 않고 발사를 거부');
588
586
  }
589
- credential = resolveGrokCredential({ home: opts.home, env: opts.env });
590
- if (credential?.kind !== 'subscription') throw new Error('grok: 갱신 뒤 구독 자격을 다시 읽지 못했다');
587
+ try {
588
+ if (opts.refresh) opts.refresh();
589
+ else refreshGrokSubscriptionToken({ home: opts.home, requireRefreshToken: true,
590
+ requiredValidityMs: minValidityMs, nowMs: clock(), ...(opts.grokPath ? { grokPath: opts.grokPath } : {}) });
591
+ } catch { /* Final snapshot below is the launch decision. */ }
591
592
  }
592
- const scopes = JSON.parse(readFileSync(grokAuthFilePath(opts.home), 'utf8')) as Record<string, unknown>;
593
- const redacted: Record<string, { key: string; expires_at?: string; user_id?: string }> = {};
594
- for (const [name, value] of Object.entries(scopes)) {
595
- if (!value || typeof value !== 'object' || Array.isArray(value)) continue;
596
- const scope = value as Record<string, unknown>;
597
- if (scope.key !== credential.token) continue;
598
- redacted[name] = {
599
- key: scope.key,
600
- ...(typeof scope.expires_at === 'string' ? { expires_at: scope.expires_at } : {}),
601
- ...(typeof scope.user_id === 'string' ? { user_id: scope.user_id } : {}),
602
- };
593
+ const selected = readSelectedGrokScope(opts.home);
594
+ if (!selected || selected.scopeName !== initialScope.scopeName) {
595
+ throw new Error('grok: 자격 확인 중 선택된 구독 scope가 사라졌거나 바뀜 — 발사를 거부');
596
+ }
597
+ const selectedExpiry = selected.expiresAt ? Date.parse(selected.expiresAt) : NaN;
598
+ if (!Number.isFinite(selectedExpiry) || selectedExpiry - clock() < minValidityMs) {
599
+ const remainingMs = Number.isFinite(selectedExpiry) ? selectedExpiry - clock() : null;
600
+ try { debug.log('pod.grok-credentials', 'refused', { remainingMs, minValidityMs, expiresAt: selected.expiresAt }); } catch { /* fail-soft */ }
601
+ throw new Error(`grok: 구독 access 토큰 남은 시간 ${formatGrokRemaining(remainingMs)} < Pod 발사 기준 ${formatGrokRemaining(minValidityMs)} — 호스트 갱신(grok models)도 못 늘렸다 · 다음: 호스트에서 grok login --device-auth 후 다시`);
603
602
  }
604
- if (!Object.keys(redacted).length) throw new Error('grok: 구독 access 토큰 없음');
603
+ const redacted: Record<string, { key: string; expires_at?: string; user_id?: string }> = {
604
+ [selected.scopeName]: {
605
+ key: selected.key,
606
+ ...(selected.expiresAt ? { expires_at: selected.expiresAt } : {}),
607
+ ...(selected.userId ? { user_id: selected.userId } : {}),
608
+ },
609
+ };
605
610
  return { grokAuth: JSON.stringify(redacted), ghToken: (opts.ghToken ?? defaultGhToken)() };
606
611
  }
607
612
  if (credential?.kind === 'api_key' && opts.apiKeyOptIn === true) {
@@ -804,6 +809,48 @@ export function podGithubWatchdogScript(staleSeconds: number, intervalSeconds =
804
809
  ].join('\n');
805
810
  }
806
811
 
812
+ export function podSalvageBundleScript(): string {
813
+ return `if [ "\${rc:-0}" -ne 0 ] && grep -Eq 'draft PR 생성 실패|PR (gh|guard) 실패|same-cell reuse:' "\${ELANOUS_POD_CHILD_OUTPUT:-/tmp/si.out}"; then
814
+ mkdir -p "$HOME/outbox/pod-salvage"
815
+ found_commits=0
816
+ preservation_failed=0
817
+ bundle_bytes=0
818
+ worktree_rows=$(git worktree list --porcelain) || preservation_failed=1
819
+ while IFS= read -r wt; do
820
+ [ -n "$wt" ] || continue
821
+ git -C "$wt" rev-parse --is-inside-work-tree >/dev/null 2>&1 || { preservation_failed=1; continue; }
822
+ wt_name=$(basename -- "$wt")
823
+ case "$wt_name" in ''|.*|*/*|*'..'*) preservation_failed=1; continue ;; esac
824
+ base=$(git -C "$wt" rev-parse --verify '@{u}' 2>/dev/null || git -C "$wt" rev-parse --verify origin/HEAD 2>/dev/null || git -C "$wt" rev-list --max-parents=0 HEAD | tail -n 1)
825
+ head=$(git -C "$wt" rev-parse HEAD) || { preservation_failed=1; continue; }
826
+ [ -n "$base" ] || { preservation_failed=1; continue; }
827
+ commitCount=$(git -C "$wt" rev-list --count "$base..$head") || { preservation_failed=1; continue; }
828
+ if [ "$commitCount" -eq 0 ]; then continue; fi
829
+ found_commits=1
830
+ diffStats=$(git -C "$wt" diff --numstat "$base..$head") || { preservation_failed=1; continue; }
831
+ diffLines=$(printf '%s\\n' "$diffStats" | awk '{added += $1; removed += $2} END {print added + removed}')
832
+ bundle="$HOME/outbox/pod-salvage/$wt_name.bundle"
833
+ branch=$(git -C "$wt" symbolic-ref --quiet --short HEAD) || { preservation_failed=1; continue; }
834
+ if git -C "$wt" bundle create "$bundle" "refs/heads/$branch" && [ -s "$bundle" ]; then
835
+ size=$(( $(wc -c < "$bundle") ))
836
+ if [ "$size" -gt ${POD_SALVAGE_BUNDLE_FILE_LIMIT} ] || [ $((bundle_bytes + size)) -gt ${POD_SALVAGE_BUNDLE_TOTAL_LIMIT} ]; then
837
+ preservation_failed=1
838
+ rm -f -- "$bundle"
839
+ printf 'ELANOUS_POD_SALVAGE_FAILED size-limit %s %s %s\\n' "$wt_name" "$size" "$head"
840
+ else
841
+ bundle_bytes=$((bundle_bytes + size))
842
+ printf 'ELANOUS_POD_SALVAGE_BUNDLE pod-salvage/%s.bundle %s %s %s\\n' "$wt_name" "$commitCount" "$diffLines" "$head"
843
+ fi
844
+ else
845
+ preservation_failed=1
846
+ printf 'ELANOUS_POD_SALVAGE_FAILED bundle-create %s\\n' "$wt_name"
847
+ fi
848
+ done < <(printf '%s\\n' "$worktree_rows" | awk '/^worktree / {sub(/^worktree /, ""); print}')
849
+ if [ "$preservation_failed" -ne 0 ]; then printf 'ELANOUS_POD_SALVAGE_FAILED incomplete\\n'
850
+ elif [ "$found_commits" -eq 0 ]; then printf 'ELANOUS_POD_SALVAGE_NONE no-commits\\n'; fi
851
+ fi`;
852
+ }
853
+
807
854
  export function podSalvageScript(): string {
808
855
  return [
809
856
  'if [ "${rc:-0}" -ne 0 ]; then',
@@ -1146,6 +1193,29 @@ export function podSigtermTrapScript(seqFile: string = POD_USAGE_PARTIAL_SEQ_FIL
1146
1193
  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`;
1147
1194
  }
1148
1195
 
1196
+ /** Leave enough time for the Pod wrapper to print its result and push a salvage branch before Kubernetes kills the Job. */
1197
+ export function podDeadlineWatchdogScript(input: { deadlineSeconds: number; job: string; runId?: string; prNumber?: number }): string {
1198
+ const leadSeconds = Math.max(1, Math.min(600, Math.floor(input.deadlineSeconds / 10)));
1199
+ const waitSeconds = Math.max(1, input.deadlineSeconds - leadSeconds);
1200
+ const job = /^[A-Za-z0-9_.:-]+$/.test(input.job) ? input.job : 'unknown-job';
1201
+ const runId = input.runId && /^[A-Za-z0-9_.:-]+$/.test(input.runId) ? input.runId : 'unknown-run';
1202
+ const pr = input.prNumber && Number.isSafeInteger(input.prNumber) && input.prNumber > 0 ? String(input.prNumber) : 'unknown';
1203
+ const jsonPr = pr === 'unknown' ? 'null' : pr;
1204
+ return `printf 'clone\\n' > /tmp/si.stage
1205
+ (sleep ${waitSeconds}; [ -f /tmp/si.finished ] && exit 0
1206
+ stage=$(cat /tmp/si.stage 2>/dev/null || true); case "$stage" in clone|setup|run) ;; *) stage=unknown;; esac
1207
+ branch=$(git -C repo branch --show-current 2>/dev/null || true); case "$branch" in ''|*[!A-Za-z0-9_./-]*) branch=unknown;; esac
1208
+ [ -f /tmp/si.finished ] && exit 0
1209
+ si_target=$(cat /tmp/si.pid 2>/dev/null || true)
1210
+ case "$si_target" in ''|*[!0-9]*) ;; *) kill -0 "$si_target" 2>/dev/null || exit 0;; esac
1211
+ printf 'ELANOUS_POD_DEADLINE_RESULT ${job} ${runId} stop-cause=deadline stage=%s pr=${pr} branch=%s\\n' "$stage" "$branch" | tee /tmp/si.deadline-marker
1212
+ printf '{"stage":"deadline","ok":false,"error":"Pod deadline preemption","stopCause":"deadline","prNumber":${jsonPr},"branch":"%s"}\\n' "$branch" > /tmp/si.deadline-result
1213
+ case "$si_target" in ''|*[!0-9]*) ;; *) kill -TERM "$si_target" 2>/dev/null || true;; esac
1214
+ ) & si_deadline_watch_pid=$!`;
1215
+ }
1216
+
1217
+ export const POD_DEADLINE_AFTER_WAIT = `if [ "$rc" -ne 0 ] && [ -f /tmp/si.deadline-result ]; then printf '\\n' >> /tmp/si.out; cat /tmp/si.deadline-result >> /tmp/si.out; rc=124; fi`;
1218
+
1149
1219
  export function podJobManifest(o: { name: string; namespace: string; image: string; workIdentity?: PodWorkIdentity; boundPrNumber?: number; /** 레지스트리 이미지면 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; /** Codex Job may use the same named Secret only for an explicitly admitted ZAI fallback. */ zaiFallback?: ZaiPodSpec; fallbackChain?: { steps: readonly FallbackStep[]; source: 'host' | 'default' }; /** TA-POD-WARMBOOT-PARITY — the child's final line (podResultMarkerShellLine), just before `exit $rc`. */ resultMarkerLine?: string; /** POD-LAUNCH-PROVENANCE — the shared provenance set (labels ⊕ annotations ⊕ child env) for this si-task Job. */ provenance?: PodProvenanceMetadata }): Record<string, unknown> {
1150
1220
  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'))) {
1151
1221
  throw new Error('repair commit-only requires matching PR source and no PR/merge flags');
@@ -1206,9 +1276,11 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
1206
1276
  // SI-POD-STAGE-MARKERS — Pod 시계 단계 표지(`ELANOUS_POD_STAGE <stage> <start|end> <epoch초>`): 호스트가 Job 로그에서 읽어
1207
1277
  // pod.lifecycle stages 의 clone · mirror · run 을 채운다. 실패한 단계는 끝 표지가 없다(→ missing · 지어내지 않는다).
1208
1278
  // clone 끝 = podSourceScript 전체가 끝난 뒤(갈래마다 마지막 줄이 `ELANOUS_POD_SOURCE` 또는 `cd repo` — 둘 다 소스 받기의 일부).
1279
+ podDeadlineWatchdogScript({ deadlineSeconds: o.deadlineSeconds, job: o.name, runId: o.runId, prNumber: o.boundPrNumber }),
1209
1280
  siTaskPodStageShell('clone', 'start'),
1210
1281
  podSourceScript(o.source ?? { kind: 'default' }, o.repoUrl, undefined, { stageMarkers: true }),
1211
1282
  siTaskPodStageShell('clone', 'end'),
1283
+ `printf 'setup\\n' > /tmp/si.stage`,
1212
1284
  // This image already contains runtime dependencies; there is no child install command.
1213
1285
  // Record that fact before the main command, without treating clone completion as install completion.
1214
1286
  `printf 'ELANOUS_POD_DEPS skipped %s image-prepared-no-install\\n' "$(date +%s)" || true`,
@@ -1232,15 +1304,19 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
1232
1304
  // 마지막 줄 JSON 이 «맨 끝»이어야 한다(parseSelfImplementJson) — rollup 은 그 앞에.
1233
1305
  // ⛔ `--author-grade` 는 Pod 안 `elanous`(이미지에 깔린 판)가 모를 수 있어 넘기지 않는다 — 10-06 «unknown option» 즉사(#24445 되돌림).
1234
1306
  // AUTHOR-LITE2-POD — 등급은 환경변수 `ELANOUS_AUTHOR_GRADE` 로 싣는다(옛 Pod elanous 는 모르는 환경변수를 무시하고 full 로 돈다).
1307
+ `printf 'run\\n' > /tmp/si.stage`,
1235
1308
  siTaskPodStageShell('run', 'start'),
1236
1309
  o.repairCommitOnly
1237
- ? `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=$?; ${RUN_END}; if elanous self repair-commit-export '${o.repairCommitOnly.pr}' '${o.repairCommitOnly.baseHead}' /tmp/si.out "$PWD" "$HOME/outbox"; then rc=0; elif [ "$rc" -eq 0 ]; then rc=8; fi`
1310
+ ? `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=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; if elanous self repair-commit-export '${o.repairCommitOnly.pr}' '${o.repairCommitOnly.baseHead}' /tmp/si.out "$PWD" "$HOME/outbox"; then rc=0; elif [ "$rc" -eq 0 ]; then rc=8; fi; ${POD_DEADLINE_AFTER_WAIT}`
1238
1311
  : o.authorSentence
1239
- ? `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=$?; ${RUN_END}; echo "ELANOUS_AUTHOR_ON_POD finished host=$(hostname) rc=$rc seconds=$(( $(date +%s) - author_t0 ))"; ${POD_RESULT_FLATTEN}`
1312
+ ? `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=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; echo "ELANOUS_AUTHOR_ON_POD finished host=$(hostname) rc=$rc seconds=$(( $(date +%s) - author_t0 ))"; ${POD_RESULT_FLATTEN}`
1240
1313
  : goalPath
1241
- ? `elanous harness ask ${goalPath} --json${quotedAsk}${quotedChildLlm} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; ${POD_RESULT_FLATTEN}`
1242
- : `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; ${POD_RESULT_FLATTEN}`,
1314
+ ? `elanous harness ask ${goalPath} --json${quotedAsk}${quotedChildLlm} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; ${POD_RESULT_FLATTEN}`
1315
+ : `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; ${POD_RESULT_FLATTEN}`,
1243
1316
  'cat /tmp/si.out',
1317
+ ...(o.appCredential && !o.repairCommitOnly ? ['kill "$gh_watch_pid" 2>/dev/null || true'] : []),
1318
+ ...(o.repairCommitOnly ? [] : [podSalvageScript()]),
1319
+ podSalvageBundleScript(),
1244
1320
  '[ -f scripts/usage-rollup.ts ] && bun scripts/usage-rollup.ts --since 12h || echo "ELANOUS_USAGE_ROLLUP {\"measured\":false,\"reason\":\"no rollup script\"}"',
1245
1321
  // A long run's log export can pass the 5MB artifact limit; skipping it whole left no window into why a
1246
1322
  // 2h+ child failed (🅢 09-27). Keep the newest lines under the limit instead, and say so.
@@ -1257,23 +1333,27 @@ else
1257
1333
  fi`,
1258
1334
  `set -o pipefail
1259
1335
  artifact_bytes=0
1336
+ salvage_bundle_bytes=0
1260
1337
  if [ -d "$HOME/outbox" ]; then
1261
1338
  while IFS= read -r -d '' file; do
1262
1339
  [ -f "$file" ] && [ ! -L "$file" ] || continue
1263
1340
  relative=\${file#"$HOME/outbox/"}
1264
1341
  size=$(( $(wc -c < "$file") ))
1265
- if [ "$size" -gt 5242880 ] || [ $((artifact_bytes + size)) -gt 20971520 ]; then
1342
+ salvage_bundle=0
1343
+ case "$relative" in pod-salvage/*.bundle) salvage_bundle=1 ;; esac
1344
+ if { [ "$salvage_bundle" -eq 0 ] && { [ "$size" -gt 5242880 ] || [ $((artifact_bytes + size)) -gt 20971520 ]; }; } || { [ "$salvage_bundle" -eq 1 ] && { [ "$size" -gt ${POD_SALVAGE_BUNDLE_FILE_LIMIT} ] || [ $((salvage_bundle_bytes + size)) -gt ${POD_SALVAGE_BUNDLE_TOTAL_LIMIT} ]; }; }; then
1266
1345
  printf 'ELANOUS_POD_ARTIFACT_SKIPPED %s %s\\n' "$relative" "$size"
1267
1346
  continue
1268
1347
  fi
1269
1348
  path_token=$(printf '%s' "$relative" | base64 | tr -d '\\n' | tr '+/' '-_' | tr -d '=')
1270
1349
  if encoded=$(gzip -c "$file" | base64 | tr -d '\\n'); then
1271
- artifact_bytes=$((artifact_bytes + size))
1350
+ if [ "$salvage_bundle" -eq 1 ]; then salvage_bundle_bytes=$((salvage_bundle_bytes + size)); else artifact_bytes=$((artifact_bytes + size)); fi
1272
1351
  total=$(( (\${#encoded} + 7999) / 8000 ))
1273
- for ((n=1; n<=total; n++)); do
1274
- chunk=\${encoded:$(( (n-1)*8000 )):8000}
1352
+ n=1
1353
+ while IFS= read -r chunk || [ -n "$chunk" ]; do
1275
1354
  printf 'ELANOUS_POD_ARTIFACT %s %s/%s %s\\n' "$path_token" "$n" "$total" "$chunk"
1276
- done
1355
+ n=$((n + 1))
1356
+ done < <(printf '%s' "$encoded" | fold -w 8000)
1277
1357
  else
1278
1358
  printf 'ELANOUS_POD_ARTIFACT_SKIPPED %s %s\\n' "$relative" "$size"
1279
1359
  fi
@@ -1296,12 +1376,12 @@ for ledger in "\${ELANOUS_STATE_DIR:-$HOME/.elanous}"/run-ledger/*.jsonl; do
1296
1376
  done
1297
1377
  if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
1298
1378
  'kill "$mem_sampler_pid" 2>/dev/null || true',
1299
- ...(o.appCredential && !o.repairCommitOnly ? ['kill "$gh_watch_pid" 2>/dev/null || true'] : []),
1300
1379
  '[ -n "${usage_partial_pid:-}" ] && kill "$usage_partial_pid" 2>/dev/null || true',
1301
1380
  'wait "$mem_sampler_pid" 2>/dev/null || true',
1302
1381
  '[ -n "${usage_partial_pid:-}" ] && wait "$usage_partial_pid" 2>/dev/null || true',
1382
+ 'if [ "$rc" -ne 0 ] && [ -f /tmp/si.deadline-result ]; then rc=124; fi',
1303
1383
  'tail -n 1 /tmp/si.out',
1304
- ...(o.repairCommitOnly ? [] : [podSalvageScript()]),
1384
+ 'touch /tmp/si.finished; kill "$si_deadline_watch_pid" 2>/dev/null || true; [ -f /tmp/si.deadline-marker ] && cat /tmp/si.deadline-marker || true',
1305
1385
  // TA-POD-WARMBOOT-PARITY: the last line says «the child is done» so the host need not wait for the Job condition.
1306
1386
  ...(o.resultMarkerLine ? [o.resultMarkerLine] : []),
1307
1387
  'exit $rc',
@@ -1337,6 +1417,9 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
1337
1417
  ? [{ name: 'ELANOUS_TASK_BOUND_PR', value: String(o.boundPrNumber) }] : []),
1338
1418
  ...(o.workIdentity?.slotId ? [{ name: 'ELANOUS_POD_SLOT_ID', value: o.workIdentity.slotId }] : []),
1339
1419
  { name: 'ELANOUS_SUBSTRATE', value: 'pod' },
1420
+ // POD-INPLACE-WORKTREE: explicit host opt-in only; one Job runs one implementation child.
1421
+ { name: 'ELANOUS_POD_SINGLE_CHILD', value: '1' },
1422
+ { name: 'ELANOUS_POD_INPLACE_WORKTREE', value: process.env.ELANOUS_POD_INPLACE_WORKTREE === '1' ? '1' : '0' },
1340
1423
  ...Object.entries(controlInboxEnv(POD_CONTROL_INBOX_DIR)).map(([name, value]) => ({ name, value })),
1341
1424
  // ⭐ 런 출처(🅣 RFC run-origin §A3 · #20457/#20468 칸 이름) — Pod 는 자기 elanous_id 를 쓰지 않고 «띄운 감독기»의 hostId 를 물려받는다.
1342
1425
  { name: 'ELANOUS_POD_NAME', valueFrom: { fieldRef: { fieldPath: 'metadata.name' } } },
@@ -1897,13 +1980,16 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1897
1980
  const acquireSlot = async (): Promise<PodPoolMember | null> => {
1898
1981
  if (!options.pool) return null;
1899
1982
  const stop = watchStall('pool-slot');
1983
+ // MINIH-MODE (0.2.37): the location is declared by the launch env — absent/unknown keeps the configured
1984
+ // capacities, so this launch path behaves exactly as before unless the declaration is there.
1985
+ const minihLocation = minihLocationFrom(env.ELANOUS_MINIH_LOCATION);
1900
1986
  try {
1901
1987
  for (;;) {
1902
1988
  if (input.signal?.aborted) return null;
1903
1989
  // The reason comes back inside this call, so a concurrent launch cannot overwrite it.
1904
1990
  const kind = podPlacementKind(oomRetried ? retryTier : memoryTier, selectedGoalType, requestKind);
1905
1991
  const acquired = await options.pool.tryAcquire(unfitContexts, (reason) => { stageReason['pool-slot'] = reason; },
1906
- { kind, onPlacement: (placement) => { lastPlacement = placement; } });
1992
+ { kind, ...(minihLocation ? { minihLocation } : {}), onPlacement: (placement) => { lastPlacement = placement; } });
1907
1993
  if (acquired) {
1908
1994
  debug.log('self-implement.pod', 'pool-slot', { spaceId: input.spaceId, context: acquired.context, inflight: options.pool.snapshot(), ...(lastPlacement ? { placement: lastPlacement } : {}) });
1909
1995
  if (lastPlacement) console.warn(`[pod] 배치: ${lastPlacement.reason}`);
@@ -1954,6 +2040,21 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1954
2040
  const currentContext = member ? null : baseKubectl(['config', 'current-context']);
1955
2041
  let context = member?.context ?? (currentContext?.status === 0 ? currentContext.stdout.trim() : '');
1956
2042
  const kubectl: Kubectl = (args, stdin) => baseKubectl(['--context', context, ...args], stdin);
2043
+ const captureKubectl = (host: string, args: readonly string[]): ReturnType<Kubectl> => {
2044
+ if (member?.sshHost ? member.sshHost !== host : host !== resolveHostId(env))
2045
+ return { status: 1, stdout: '', stderr: 'ledger host is not the selected pool host' };
2046
+ if (!member?.sshHost) return baseKubectl(args);
2047
+ if (options.failureCaptureRemote) return options.failureCaptureRemote(host, args);
2048
+ const result = spawnSync('ssh', ['-o', 'BatchMode=yes', '-o', 'ConnectTimeout=5', '--', host, 'kubectl', ...args],
2049
+ { encoding: 'utf8', timeout: 30_000, maxBuffer: LEASE_KUBECTL_MAX_BUFFER });
2050
+ return { status: result.status, stdout: result.stdout ?? '', stderr: (result.stderr ?? '') + (result.error ? String(result.error) : '') };
2051
+ };
2052
+ const captureFailedJob = (childRunId: string): void => {
2053
+ try {
2054
+ captureFailedPodJobs({ runId: ledgerRunId, job: name, childRunId, ledgerPath: runLedgerPath(ledgerRunId, ledgerDir), artifactDir: join(effectiveInstanceRoot(), 'pod-artifacts'),
2055
+ kubectl: captureKubectl, record: (event, data) => appendRunLedgerEntry({ runId: ledgerRunId, event, data }, ledgerDir), now: options.now });
2056
+ } catch (error) { debug.log('self-implement.pod', 'failure-capture-ledger-unavailable', { job: name, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
2057
+ };
1957
2058
  let recorded = false;
1958
2059
  let groundingMinted: string | null = null;
1959
2060
  try {
@@ -1995,6 +2096,44 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1995
2096
  collectPodArtifacts(full.stdout, { dir: join(effectiveInstanceRoot(), 'pod-artifacts'), job: name, log: record });
1996
2097
  }
1997
2098
  catch (error) { record('self-implement.pod', 'artifact-collect-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
2099
+ for (const line of full.stdout.split(/\r?\n/)) {
2100
+ const bundle = /^ELANOUS_POD_SALVAGE_BUNDLE (pod-salvage\/[a-zA-Z0-9._-]+\.bundle) ([0-9]+) ([0-9]+)(?: ([0-9a-f]{40,64}))?$/.exec(line);
2101
+ if (bundle) {
2102
+ const bundlePath = join(effectiveInstanceRoot(), 'pod-artifacts', name, bundle[1]!);
2103
+ if (!existsSync(bundlePath)) {
2104
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: { job: name, disposition: '보존 실패', reason: 'bundle artifact missing' } }, ledgerDir); }
2105
+ catch (error) { record('self-implement.pod', 'salvage-bundle-ledger-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
2106
+ record('self-implement.pod', 'salvage-bundle-collect-incomplete', { job: name, path: bundlePath, reason: 'bundle artifact missing' });
2107
+ continue;
2108
+ }
2109
+ try {
2110
+ const refs = execFileSync('git', ['bundle', 'list-heads', bundlePath], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim().split(/\r?\n/);
2111
+ const [bundleHead, bundleRef] = refs[0]?.trim().split(/\s+/) ?? [];
2112
+ if (!bundleHead || !bundleRef?.startsWith('refs/heads/')) throw new Error('bundle contains no branch ref');
2113
+ const verifyDir = mkdtempSync(join(tmpdir(), 'pod-salvage-verify-'));
2114
+ try {
2115
+ execFileSync('git', ['clone', '--quiet', '--branch', bundleRef.slice('refs/heads/'.length), bundlePath, verifyDir], { stdio: ['ignore', 'pipe', 'pipe'] });
2116
+ const cloneHead = execFileSync('git', ['-C', verifyDir, 'rev-parse', 'HEAD'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
2117
+ if (cloneHead !== bundleHead || (bundle[4] && cloneHead !== bundle[4])) throw new Error('bundle clone HEAD mismatch');
2118
+ } finally { rmSync(verifyDir, { recursive: true, force: true }); }
2119
+ appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: {
2120
+ job: name, path: bundlePath,
2121
+ commitCount: Number(bundle[2]), diffLines: Number(bundle[3]), ...(bundle[4] ? { head: bundle[4] } : {}),
2122
+ } }, ledgerDir);
2123
+ } catch (error) {
2124
+ const reason = error instanceof Error ? error.message : String(error);
2125
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: { job: name, disposition: '보존 실패', reason: `bundle validation failed: ${reason}` } }, ledgerDir); }
2126
+ catch (ledgerError) { record('self-implement.pod', 'salvage-bundle-ledger-incomplete', { job: name, reason: ledgerError instanceof Error ? ledgerError.message : String(ledgerError) }); }
2127
+ record('self-implement.pod', 'salvage-bundle-collect-incomplete', { job: name, reason });
2128
+ }
2129
+ } else if (line === 'ELANOUS_POD_SALVAGE_NONE no-commits') {
2130
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: { job: name, disposition: '보존할 것 없음', commitCount: 0, diffLines: 0 } }, ledgerDir); }
2131
+ catch (error) { record('self-implement.pod', 'salvage-bundle-ledger-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
2132
+ } else if (line.startsWith('ELANOUS_POD_SALVAGE_FAILED ')) {
2133
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-salvage-bundle', data: { job: name, disposition: '보존 실패', reason: line.slice('ELANOUS_POD_SALVAGE_FAILED '.length) } }, ledgerDir); }
2134
+ catch (error) { record('self-implement.pod', 'salvage-bundle-ledger-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
2135
+ }
2136
+ }
1998
2137
  if (options.repairCommitOnly) {
1999
2138
  const artifactDir = join(effectiveInstanceRoot(), 'pod-artifacts', name, 'repair');
2000
2139
  try {
@@ -2022,9 +2161,11 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2022
2161
  // 상한 안 → ZAI(이름 있는 Secret · 없으면 거부) · 넘침 → 정책대로(openrouter·balance = 기존 OpenRouter GLM · stop = 거부 · apply 0).
2023
2162
  let zaiRoute: 'zai' | 'openrouter' | undefined;
2024
2163
  let zaiSpec: ZaiPodSpec | undefined;
2164
+ let zaiLaunchOverage: 'stop' | 'balance' | 'openrouter' | undefined;
2025
2165
  zaiPendingApply.delete(name);
2026
2166
  if (options.provider === 'glm') {
2027
2167
  const settings = (options.zaiSettings ?? (() => zaiSettingsFromConfig(getUserConfig().llm)))();
2168
+ zaiLaunchOverage = settings.overage;
2028
2169
  const poolMembers = (options.pool as { members?: readonly PodPoolMember[] } | undefined)?.members;
2029
2170
  const contexts = Array.isArray(poolMembers) && poolMembers.length > 0 ? poolMembers.map((m) => m.context) : [context];
2030
2171
  let active: number | null = 0;
@@ -2056,6 +2197,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2056
2197
  const anthropic = options.provider === 'anthropic';
2057
2198
  const bedrockChild = options.provider === 'bedrock';
2058
2199
  const zaiChild = zaiRoute === 'zai';
2200
+ /** ZAI 로 입장한 자식도 플랜 한도 오류 뒤 OpenRouter 로 전환할 수 있다. 실행 중 폴백 자격을 발사 전에 확보한다. */
2201
+ const openrouterCredentialRequired = openrouter || (zaiChild && zaiLaunchOverage !== 'stop');
2059
2202
  /** API 키 자식 — codex 계정·자격 파일을 안 쓴다(키는 작업별 creds Secret 의 `env-<KEY>` · bedrock·glm 은 이름 있는 Secret 으로만). */
2060
2203
  const apiKeyChild = openrouter || openGateway || anthropic || bedrockChild || zaiChild;
2061
2204
  const plannedAccount = retryAccount ?? (grok ? 'grok' : openrouter ? 'openrouter' : openGateway ? 'opengateway' : anthropic ? 'anthropic' : bedrockChild ? 'bedrock' : zaiChild ? 'glm' : options.accountBroker?.() ?? options.account ?? 'team');
@@ -2099,8 +2242,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2099
2242
  }
2100
2243
  return credential;
2101
2244
  }) : undefined;
2102
- const openrouterKey = openrouter ? env.OPENROUTER_API_KEY?.trim() || (options.readKeyCache ?? defaultReadKeyCache)('OPENROUTER_API_KEY')?.trim() : undefined;
2103
- if (openrouter && !openrouterKey) throw new Error('pod: Pod 에 openrouter 키 없음 — 호스트 키 캐시 또는 OPENROUTER_API_KEY 필요');
2245
+ const openrouterKey = openrouterCredentialRequired ? env.OPENROUTER_API_KEY?.trim() || (options.readKeyCache ?? defaultReadKeyCache)('OPENROUTER_API_KEY')?.trim() : undefined;
2246
+ if (openrouterCredentialRequired && !openrouterKey) throw new Error('pod: Pod 에 openrouter 키 없음 — 호스트 키 캐시 또는 OPENROUTER_API_KEY 필요');
2104
2247
  const openGatewayEnvKey = openGateway ? env.OPENGATEWAY_API_KEY?.trim() : undefined;
2105
2248
  const openGatewayCachedKey = openGateway ? (options.readKeyCache ?? defaultReadKeyCache)('OPENGATEWAY_API_KEY')?.trim() : undefined;
2106
2249
  if (openGatewayEnvKey && openGatewayCachedKey && openGatewayEnvKey !== openGatewayCachedKey)
@@ -2182,7 +2325,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2182
2325
  }
2183
2326
  }
2184
2327
  // Grok 자격은 전용 Secret 키 하나로만 보낸다 — passEnv 의 API 키 중복 전달은 막는다.
2185
- const passKeys = [...new Set([...(options.passEnv ?? []), ...(openrouter ? ['OPENROUTER_API_KEY'] : []), ...(openGateway ? ['OPENGATEWAY_API_KEY'] : []), ...(anthropic ? ['ANTHROPIC_API_KEY'] : [])])].filter((key) => key !== 'ELANOUS_LIVE_DETAIL_UNTIL'
2328
+ const passKeys = [...new Set([...(options.passEnv ?? []), ...(openrouterCredentialRequired ? ['OPENROUTER_API_KEY'] : []), ...(openGateway ? ['OPENGATEWAY_API_KEY'] : []), ...(anthropic ? ['ANTHROPIC_API_KEY'] : [])])].filter((key) => key !== 'ELANOUS_LIVE_DETAIL_UNTIL'
2186
2329
  && key !== POD_GITHUB_CREDENTIAL_TOKEN_ENV && key !== POD_GITHUB_CREDENTIAL_URL_ENV
2187
2330
  && (!grok || !['XAI_API_KEY', 'GROK_API_KEY', 'GROK_CODE_XAI_API_KEY'].includes(key)));
2188
2331
  const skillEnvs: Record<string, string> = options.skillEnv
@@ -2307,6 +2450,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2307
2450
  if (key.startsWith('ELANOUS_PROMPT_ENHANCE_') && key !== 'ELANOUS_PROMPT_ENHANCE_MODEL' && key !== 'ELANOUS_PROMPT_ENHANCE_EFFORT') delete hostAuthorEnv[key];
2308
2451
  }
2309
2452
  let authorChoice = authorOnPod ? selectEnhanceLlm({ config: (options.authorConfig ?? getUserConfig)() }, hostAuthorEnv) : undefined;
2453
+ // A named child model is this launch's model when planning has no explicit choice.
2454
+ // Relay it to authoring too: the Pod's persistent grounding goal loop otherwise
2455
+ // receives the host's default "better" model and silently spends sol for a luna child.
2456
+ const namedChildModel = podDelegatedChildLlm(jobArgs)?.model;
2457
+ if (authorChoice?.modelSource === 'default' && namedChildModel) {
2458
+ authorChoice = { ...authorChoice, model: namedChildModel, modelSource: 'child' };
2459
+ }
2310
2460
  let authorFallbackReason: string | undefined;
2311
2461
  let authorRequestedModel: string | undefined;
2312
2462
  let authorRequestedSource: string | undefined;
@@ -2328,8 +2478,10 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2328
2478
  authorChoice = { ...authorChoice, model: childModel, modelSource: 'fallback-child' };
2329
2479
  } else debug.log('self-implement.pod', 'role-llm-armed', { job: name, role: 'planning', model: authorChoice.model, source: authorChoice.modelSource, account: roleCodexAccount });
2330
2480
  }
2331
- const hostKey = (k: string): string | undefined => k === 'OPENROUTER_API_KEY' && openrouter ? openrouterKey : k === 'OPENGATEWAY_API_KEY' && openGateway ? openGatewayKey : k === 'ANTHROPIC_API_KEY' && anthropic ? anthropicKey : env[k] ?? (options.readKeyCache ?? defaultReadKeyCache)(k);
2332
- const hostFallbackNames = (options.fallbackConfig ?? getUserConfig)().llm.fallbackChain;
2481
+ const hostKey = (k: string): string | undefined => k === 'OPENROUTER_API_KEY' && openrouterCredentialRequired ? openrouterKey : k === 'OPENGATEWAY_API_KEY' && openGateway ? openGatewayKey : k === 'ANTHROPIC_API_KEY' && anthropic ? anthropicKey : env[k] ?? (options.readKeyCache ?? defaultReadKeyCache)(k);
2482
+ const hostConfig = (options.fallbackConfig ?? getUserConfig)();
2483
+ const hostFallbackNames = hostConfig.llm.fallbackChain;
2484
+ const zaiOverage = zaiLaunchOverage ?? zaiSettingsFromConfig(hostConfig.llm).overage;
2333
2485
  const normalizedFallback = normalizeFallbackChain(hostFallbackNames);
2334
2486
  let fallbackSteps = normalizedFallback.chain;
2335
2487
  let zaiFallbackSpec: ZaiPodSpec | undefined;
@@ -2381,7 +2533,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2381
2533
  ? Object.fromEntries(codexCredentials.map((candidate, i) => [`codex-${i}.json`, JSON.stringify({ elanousAuth: candidate.elanousAuth, codexAuth: candidate.codexAuth })]))
2382
2534
  : { 'elanous-auth.json': (creds as ReturnType<typeof hostCredentials>).elanousAuth, 'codex-auth.json': (creds as ReturnType<typeof hostCredentials>).codexAuth }),
2383
2535
  'gh-token': podGhToken, feature: input.feature,
2384
- 'llm-fallback-config.json': JSON.stringify({ llm: { fallbackChain: fallbackChain.steps } }),
2536
+ 'llm-fallback-config.json': JSON.stringify({ llm: { fallbackChain: fallbackChain.steps, zaiCodingPlan: { overage: zaiOverage } }, harness: { worktreeAddTimeoutSec: worktreeAddTimeoutSec(hostConfig.harness?.worktreeAddTimeoutSec) ?? 1200 } }),
2385
2537
  ...(goalDocument !== undefined ? { 'goal-doc': goalDocument } : {}),
2386
2538
  ...Object.fromEntries(Object.entries(skillEnvs).map(([n, text]) => [`skillenv-${n}`, text])),
2387
2539
  ...(grounding ? { [`env-${GROUNDING_TOKEN_ENV}`]: grounding.token } : {}),
@@ -2448,6 +2600,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2448
2600
  }
2449
2601
  }
2450
2602
  if (failedExisting) {
2603
+ captureFailedJob(liveChildRunId);
2451
2604
  const pods = kubectl(['-n', namespace, 'get', 'pods', '-l', `job-name=${name}`, '-o', 'jsonpath={range .items[*]}{.metadata.creationTimestamp}{"\\t"}{range .status.containerStatuses[?(@.name=="child")]}{.state.terminated.reason}{"\\t"}{.state.terminated.exitCode}{end}{"\\n"}{end}']);
2452
2605
  const latestPod = pods.status === 0 ? pods.stdout.trimEnd().split('\n').map((line) => line.split('\t'))
2453
2606
  .filter(([created]) => created && !Number.isNaN(Date.parse(created)))
@@ -2723,6 +2876,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2723
2876
  }
2724
2877
  try {
2725
2878
  appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-run', data: { childRunId: liveChildRunId, job: name, attempt: oomRetried ? 2 : 1, ...(goalFile ? { goalFile } : {}) } }, ledgerDir);
2879
+ appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-job-applied', data: { job: name, childRunId: liveChildRunId, jobUid: lifecycleJobUid, host: member?.sshHost ?? resolveHostId(env), context, namespace } }, ledgerDir);
2726
2880
  if (lastPlacement) appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-placement', data: { job: name, childRunId: liveChildRunId, attempt: oomRetried ? 2 : 1, member: lastPlacement.member, kind: lastPlacement.kind, outcome: lastPlacement.outcome, preferred: lastPlacement.preferred, reason: lastPlacement.reason } }, ledgerDir);
2727
2881
  appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-memory-selected', data: { job: name, childRunId: liveChildRunId, attempt: oomRetried ? 2 : 1, limit: memoryLimit, ...(appliedMemoryRequest ? { request: appliedMemoryRequest } : {}), tier: oomRetried ? retryTier : memoryTier, source: oomRetried ? 'oom-retry' : memorySource, reason: oomRetried ? 'OOMKilled' : memoryReason, declaredGoalType: selectedGoalType } }, ledgerDir);
2728
2882
  if (oomRetried && retryFromChildRunId) appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-oom-retry', data: { attempt: 2, from: retryFromMemoryLimit ?? selectedMemoryLimit, to: memoryLimit, tier: retryTier, reason: 'OOMKilled', job: name, childRunId: liveChildRunId, fromChildRunId: retryFromChildRunId } }, ledgerDir);
@@ -2734,7 +2888,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2734
2888
  }
2735
2889
  writePodFragment({ spaceId: input.spaceId, context, namespace, job: name, inboxDir: POD_CONTROL_INBOX_DIR, ...(liveChildRunId === normalizeRunId(liveChildRunId) ? { runId: liveChildRunId } : {}), ...(parentRunId && normalizeRunId(parentRunId) === parentRunId ? { parentRunId } : {}) }, env);
2736
2890
  recorded = true;
2737
- debug.log('self-implement.pod', 'job-applied', { job: name, namespace, ...(member ? { context: member.context } : {}), image: jobImage, spaceId: input.spaceId, passEnv, ...(openrouter ? { openrouterKeyPresent: passEnv.includes('OPENROUTER_API_KEY') } : {}), ...(openGateway ? { openGatewayKeyPresent: passEnv.includes('OPENGATEWAY_API_KEY') } : {}), ...(anthropic ? { anthropicKeyPresent: passEnv.includes('ANTHROPIC_API_KEY') } : {}), ...(bedrockSpec ? { bedrockSecret: bedrockSpec.secretName, bedrockSecretKeys: bedrockSpec.keys, bedrockRegionFrom: bedrockSpec.region.from } : {}), ...(zaiRoute ? { zaiRoute, ...(zaiSpec ? { zaiSecret: zaiSpec.secretName } : {}) } : {}), extraArgs: options.extraArgs ?? [], ...(options.armEnv?.ELANOUS_ARM_ID ? { armId: options.armEnv.ELANOUS_ARM_ID } : {}) });
2891
+ debug.log('self-implement.pod', 'job-applied', { job: name, namespace, ...(member ? { context: member.context } : {}), image: jobImage, spaceId: input.spaceId, passEnv, ...(openrouterCredentialRequired ? { openrouterKeyPresent: passEnv.includes('OPENROUTER_API_KEY') } : {}), ...(openGateway ? { openGatewayKeyPresent: passEnv.includes('OPENGATEWAY_API_KEY') } : {}), ...(anthropic ? { anthropicKeyPresent: passEnv.includes('ANTHROPIC_API_KEY') } : {}), ...(bedrockSpec ? { bedrockSecret: bedrockSpec.secretName, bedrockSecretKeys: bedrockSpec.keys, bedrockRegionFrom: bedrockSpec.region.from } : {}), ...(zaiRoute ? { zaiRoute, ...(zaiSpec ? { zaiSecret: zaiSpec.secretName } : {}) } : {}), extraArgs: options.extraArgs ?? [], ...(options.armEnv?.ELANOUS_ARM_ID ? { armId: options.armEnv.ELANOUS_ARM_ID } : {}) });
2738
2892
  let state: 'complete' | 'failed' | 'aborted' = 'failed';
2739
2893
  let failedReason = '';
2740
2894
  let containerReason: string | null = null;
@@ -2742,10 +2896,33 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2742
2896
  // JOB-FAILURE-TERMINATION-CAPTURE — this Job's Kubernetes facts, read once at the failure verdict (before GC).
2743
2897
  // Observation only: failedReason · containerReason · containerExitCode keep driving the classification.
2744
2898
  let podTermination: PodTermination | null = null;
2899
+ const refreshPodTermination = async (): Promise<void> => {
2900
+ if (state !== 'failed' || !podTermination || (podTermination.podLookup === 'terminated'
2901
+ && podTermination.containerReason !== 'unknown' && podTermination.exitCode !== 'unknown'
2902
+ && podTermination.finishedAt !== 'unknown')) return;
2903
+ // The result marker and the Job Failed condition can precede container termination status.
2904
+ // Re-read this launch's Pod once; keep the verdict's Job facts even if the Job has since been GC'd.
2905
+ await sleep(1_000);
2906
+ const retry = readPodTermination({ kubectl, namespace, job: name, path: podTermination.path,
2907
+ jobUid: lifecycleJobUid, jobRead: null });
2908
+ const observed = retry.podLookup === 'unavailable' ? podTermination : retry;
2909
+ const complete = observed.podLookup === 'terminated' && observed.containerReason !== 'unknown'
2910
+ && observed.exitCode !== 'unknown' && observed.finishedAt !== 'unknown';
2911
+ const collectionFailureReason: PodTermination['collectionFailureReason'] | undefined = complete ? undefined
2912
+ : retry.podLookup === 'unavailable' ? 'pod-read-unavailable-after-retry'
2913
+ : retry.podLookup === 'absent' ? 'pod-absent-after-retry'
2914
+ : retry.podLookup === 'running' || retry.podLookup === 'pending' ? 'pod-still-running-after-retry'
2915
+ : retry.podLookup === 'terminated' ? 'terminated-fields-missing-after-retry'
2916
+ : 'pod-state-unknown-after-retry';
2917
+ podTermination = { ...podTermination, observedAt: retry.observedAt,
2918
+ podLookup: observed.podLookup, containerReason: observed.containerReason, exitCode: observed.exitCode,
2919
+ finishedAt: observed.finishedAt, oomKilled: observed.oomKilled, collectionAttempts: 2,
2920
+ ...(collectionFailureReason ? { collectionFailureReason } : {}) };
2921
+ };
2745
2922
  // METER-POD-ROLLUP-GAP — abort 때 Job 삭제 «전»에 거둔 로그 사본(삭제 뒤엔 PARTIAL 줄도 못 읽는다).
2746
2923
  let abortLogs = '';
2747
2924
  // ⭐ 런 «도중» 원장 증분 회수 — 호스트 슈퍼바이저가 Pod 걸음을 실시간으로 본다(🅣 요청 · 힐 루프 runtime 성형의 전제).
2748
- const follower = createPodLedgerFollower({ runId: liveChildRunId, dir: ledgerDir, exec: (script) => kubectl(['-n', namespace, 'exec', `job/${name}`, '-c', 'child', '--', 'sh', '-c', script]) });
2925
+ const follower = createPodLedgerFollower({ runId: liveChildRunId, dir: ledgerDir, now, exec: (script) => kubectl(['-n', namespace, 'exec', `job/${name}`, '-c', 'child', '--', 'sh', '-c', script]) });
2749
2926
  // ⭐ METER-POD-ROLLUP-GAP-3 — 런 «도중» 마지막 PARTIAL 줄을 호스트가 쥔다: Pod 가 지워지면(SIGTERM 등) 종료 로그에서 PARTIAL 이 사라진다.
2750
2927
  let livePartialLine: string | null = null;
2751
2928
  let pollsSinceCapture = 0;
@@ -2774,6 +2951,10 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2774
2951
  const capturePolls = Math.max(1, options.usagePartialCapturePolls ?? Math.round(POD_USAGE_PARTIAL_CAPTURE_MS / Math.max(1, options.pollMs ?? 15_000)));
2775
2952
  const markerWait = markerToken ? await import('./pod-result-marker-wait.js') : null;
2776
2953
  const waitStartedAt = Date.now();
2954
+ let consecutiveJobNotFound = 0;
2955
+ let podVanished = false;
2956
+ let unmeasurableSince: number | null = null;
2957
+ let unmeasurableIncidentRecorded = false;
2777
2958
  for (;;) {
2778
2959
  if (input.signal?.aborted) {
2779
2960
  recordPodImage(true);
@@ -2788,6 +2969,32 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2788
2969
  }
2789
2970
  if (!imageSnapshotRecorded) recordPodImage(false);
2790
2971
  const g = kubectl(['-n', namespace, 'get', 'job', name, '-o', 'jsonpath={.status.conditions[*].type}']);
2972
+ if (g.status !== 0) {
2973
+ // A transport/5xx error says nothing about Job existence. Only Kubernetes Job NotFound counts.
2974
+ const jobNotFound = /\(NotFound\)/i.test(g.stderr) || /\bjobs?(?:\.batch)?\b[^\n]*\bnot found\b/i.test(g.stderr);
2975
+ consecutiveJobNotFound = jobNotFound ? consecutiveJobNotFound + 1 : 0;
2976
+ unmeasurableSince = null;
2977
+ if (consecutiveJobNotFound >= 3) {
2978
+ state = 'failed';
2979
+ failedReason = 'JobNotFound';
2980
+ podVanished = true;
2981
+ const facts = { job: name, childRunId: liveChildRunId, class: 'pod-vanished', consecutiveNotFound: consecutiveJobNotFound };
2982
+ debug.log('self-implement.pod', 'pod-vanished', facts, { level: 'error' });
2983
+ try {
2984
+ recordRunStop({ runId: ledgerRunId, class: 'pod-vanished', site: 'pod-job-poll',
2985
+ cause: `Job ${name} NotFound on ${consecutiveJobNotFound} consecutive polls`,
2986
+ evidenceRef: `run-ledger:${ledgerRunId}:pod-job-applied`,
2987
+ nextMove: 'Inspect Job deletion and child artifacts before relaunch' },
2988
+ (entry) => appendRunLedgerEntry(entry, ledgerDir));
2989
+ } catch (error) {
2990
+ debug.log('self-implement.pod', 'pod-vanished-ledger-unavailable', { ...facts, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
2991
+ }
2992
+ break;
2993
+ }
2994
+ await sleep(options.pollMs ?? 15_000);
2995
+ continue;
2996
+ }
2997
+ consecutiveJobNotFound = 0;
2791
2998
  const types = g.stdout;
2792
2999
  if (/Complete|SuccessCriteriaMet/.test(types)) { releaseAdmission?.observed?.(); state = 'complete'; break; }
2793
3000
  if (/Failed|FailureTarget/.test(types)) {
@@ -2798,7 +3005,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2798
3005
  let jobReadError: unknown;
2799
3006
  try { jobRead = kubectl(['-n', namespace, 'get', 'job', name, '-o', `jsonpath=${POD_TERMINATION_JOB_JSONPATH}`]); }
2800
3007
  catch (error) { jobReadError = error; }
2801
- failedReason = jobRead?.status === 0 ? (jobRead.stdout.split('\t')[0] ?? '').trim() : '';
3008
+ const observedJobReason = jobRead?.status === 0 ? podJobConditionReason(jobRead.stdout.split('\t')[0]) : 'unknown';
3009
+ failedReason = observedJobReason === 'unknown' ? '' : observedJobReason;
2802
3010
  // One Pods read serves both: its first three columns are the classification layout, the rest the termination capture.
2803
3011
  let podsRead: { status: number | null; stdout: string } | null = null;
2804
3012
  try {
@@ -2817,8 +3025,11 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2817
3025
  } catch { /* Pod 가 사라졌거나 조회 불가 — 종료 사유는 미상. */ }
2818
3026
  debug.log('self-implement.pod', 'container-terminated', { job: name, container: 'child', reason: containerReason, exitCode: containerExitCode, jobReason: failedReason || null, memoryLimit });
2819
3027
  podTermination = readPodTermination({ kubectl, namespace, job: name, path: 'job-failed-condition', jobRead, podsRead, jobUid: lifecycleJobUid });
3028
+ // Keep the verdict's single Job read authoritative; collecting files may re-read a Job that GC has removed.
3029
+ captureFailedJob(liveChildRunId);
2820
3030
  if (jobReadError !== undefined) {
2821
3031
  // Today's outcome stays (the throw ends the spawn as pod-error); the capture is in the ledger first.
3032
+ await refreshPodTermination();
2822
3033
  try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-evidence', data: { childEvidence: null, childRunId: liveChildRunId, job: name, podTermination } }, ledgerDir); }
2823
3034
  catch (error) { debug.log('self-implement.pod', 'child-evidence-write-failed', { job: name, childRunId: liveChildRunId, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
2824
3035
  debug.log('self-implement.pod', 'pod-termination-captured', { job: name, podTermination, jobReadThrew: true }, { level: 'warn' });
@@ -2836,6 +3047,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2836
3047
  // The child's own rc (the Pod's terminated state may lag like the condition) — exit-code paths read it as before.
2837
3048
  if (seen !== 0) containerExitCode = seen;
2838
3049
  if (seen !== 0) podTermination = readPodTermination({ kubectl, namespace, job: name, path: 'result-marker', jobUid: lifecycleJobUid });
3050
+ if (seen !== 0) captureFailedJob(liveChildRunId);
2839
3051
  debug.log('self-implement.pod', 'result-marker-early', { job: name, waitedMs: Date.now() - waitStartedAt, rc: seen });
2840
3052
  break;
2841
3053
  }
@@ -2863,7 +3075,19 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2863
3075
  debug.log('self-implement.pod', 'gh-token-refresh-failed', { job: name, reason: 'mint-verification-or-exec-failed' });
2864
3076
  }
2865
3077
  }
2866
- try { follower?.poll(); } catch (e) { debug.log('self-implement.pod', 'ledger-live-unavailable', { job: name, reason: e instanceof Error ? e.message : String(e) }); }
3078
+ let measurement = { ledgerRead: false, activityMeasured: false };
3079
+ try { measurement = follower.poll(); } catch (e) { debug.log('self-implement.pod', 'ledger-live-unavailable', { job: name, reason: e instanceof Error ? e.message : String(e) }); }
3080
+ if (!measurement.ledgerRead && !measurement.activityMeasured) {
3081
+ unmeasurableSince ??= now();
3082
+ const unmeasurableMs = Math.max(0, now() - unmeasurableSince);
3083
+ if (!unmeasurableIncidentRecorded && unmeasurableMs >= 120 * 60_000) {
3084
+ unmeasurableIncidentRecorded = true;
3085
+ const incident = { job: name, childRunId: liveChildRunId, unmeasurableMs, jobStatus: 'alive', ledgerRead: false, activityMeasured: false };
3086
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-stall-unmeasurable-incident', data: incident }, ledgerDir); }
3087
+ catch (error) { debug.log('self-implement.pod', 'pod-stall-incident-ledger-unavailable', { job: name, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
3088
+ debug.log('self-implement.pod', 'pod-stall-unmeasurable-incident', incident, { level: 'warn' });
3089
+ }
3090
+ } else unmeasurableSince = null;
2867
3091
  if (++pollsSinceCapture >= capturePolls) {
2868
3092
  pollsSinceCapture = 0;
2869
3093
  try {
@@ -2878,6 +3102,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2878
3102
  }
2879
3103
  await sleep(options.pollMs ?? 15_000);
2880
3104
  }
3105
+ await refreshPodTermination();
2881
3106
  if (!terminalImageRecorded) recordPodImage(true);
2882
3107
  let logs = '';
2883
3108
  let logTailReason: string | undefined;
@@ -2891,6 +3116,14 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2891
3116
  if (!logs && abortLogs) logs = abortLogs;
2892
3117
  // TA-POD-WARMBOOT-PARITY: the marker line is not child output — remove it so the last-line result parse sees the same bytes.
2893
3118
  if (markerWait && markerToken && logs) logs = markerWait.stripPodResultMarker(logs, markerToken);
3119
+ const deadlineMarker = podDeadlineResultMarker(logs, name, liveChildRunId);
3120
+ if (deadlineMarker && state !== 'aborted' && state !== 'complete') {
3121
+ state = 'failed';
3122
+ failedReason = 'DeadlineExceeded';
3123
+ debug.log('self-implement.pod', 'deadline-result-marker', { job: name, childRunId: liveChildRunId, ...deadlineMarker });
3124
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-deadline-result', data: { job: name, childRunId: liveChildRunId, stopCause: 'deadline', ...deadlineMarker } }, ledgerDir); }
3125
+ catch { /* A full ledger must not hide the Pod's terminal marker. */ }
3126
+ }
2894
3127
  let ledgerReason = '';
2895
3128
  let ledgerCollected = false;
2896
3129
  const collection = collectFullLogs('ledger-collect-incomplete', follower.owned ? new Set([liveChildRunId]) : undefined, (event, data) => {
@@ -2950,7 +3183,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2950
3183
  continue;
2951
3184
  }
2952
3185
  // Pod 안 경로는 호스트에서 쓸 수 없다.
2953
- let disposition = parsed ? { ...parsed, worktreePath: undefined } : undefined;
3186
+ let disposition: SelfImplementDisposition | undefined = parsed ? { ...parsed, worktreePath: undefined } : deadlineMarker
3187
+ ? { stage: 'deadline', ok: false, ...(deadlineMarker.pr ? { prNumber: deadlineMarker.pr } : {}), ...(deadlineMarker.branch ? { branch: deadlineMarker.branch } : {}) }
3188
+ : undefined;
2954
3189
  if (options.repairCommitOnly && state === 'complete' && !repairArtifactReady) {
2955
3190
  disposition = { ...disposition, worktreePath: undefined, ok: false, stage: 'repair-artifact-missing', detail: 'Pod repair result or bundle was not collected' };
2956
3191
  }
@@ -3082,25 +3317,37 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3082
3317
  }
3083
3318
  let noResultDiagnostic: string | null = null;
3084
3319
  // POD-NORESULT: a terminal Job without a parsed disposition is incomplete even when the Job condition says Complete.
3085
- const noResultCandidate = !disposition && !oomKilled && failedReason !== 'DeadlineExceeded' &&
3320
+ const noResultCandidate = !podVanished && !disposition && !oomKilled && failedReason !== 'DeadlineExceeded' &&
3086
3321
  (state === 'complete' || (state === 'failed' && containerExitCode !== 0));
3087
3322
  if (noResultCandidate) {
3088
3323
  try { noResultDiagnostic = podNoResultDiagnostic(readFileSync(runLedgerPath(liveChildRunId, ledgerDir), 'utf8')); }
3089
3324
  catch { /* ledger not returned: do not invent a stage */ }
3090
3325
  noResultDiagnostic ??= 'child terminal result missing; last ledger stage=unknown; round=unknown; mustFix=unknown';
3091
3326
  }
3092
- // POD-NORESULT-LOG-TAIL: the Job runs with backoffLimit 0, so the failed Pod — and its container log —
3093
- // is collected right after this. When the child ledger cannot even name the stage, read the tail here,
3094
- // before deletion, so the parent keeps a maskable reason instead of `childEvidence=null`.
3327
+ // POD-FAIL-EVIDENCE-CAPTURE: failed Pods are collected/deleted immediately after terminal handling.
3328
+ // Preserve a bounded log tail for every non-OOM/non-deadline failure, including known child stages:
3329
+ // the terminal result line can be followed by the useful stderr that explains the actual exit.
3095
3330
  let noResultLogEvidence: Record<string, unknown> | null = null;
3096
- if (noResultDiagnostic?.includes('stage=unknown')) {
3331
+ const shouldCaptureFailureLog = state === 'failed' && !oomKilled && failedReason !== 'DeadlineExceeded';
3332
+ const missingStage = noResultDiagnostic?.includes('stage=unknown') ?? false;
3333
+ if (shouldCaptureFailureLog || missingStage) {
3097
3334
  const logRead = readPodNoResultLogTail({ run: kubectl, namespace, job: name, maxLines: POD_NO_RESULT_LOG_TAIL_LINES });
3098
3335
  if ('tail' in logRead) {
3099
- noResultLogEvidence = { stderr: logRead.tail.join('\n'), logTail: logRead.tail, logTailLines: logRead.tail.length };
3100
- debug.log('self-implement.pod', 'no-result-log-tail', { job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, lines: logRead.tail.length, logTail: logRead.tail }, { compact: { stringMax: 500 } });
3336
+ noResultLogEvidence = missingStage
3337
+ ? { stderr: logRead.tail.join('\n'), logTail: logRead.tail, logTailLines: logRead.tail.length }
3338
+ : { podLogTail: logRead.tail, podLogTailLines: logRead.tail.length };
3339
+ debug.log('self-implement.pod', missingStage ? 'no-result-log-tail' : 'failed-pod-log-tail', {
3340
+ job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, lines: logRead.tail.length, logTail: logRead.tail,
3341
+ }, { compact: { stringMax: 500 } });
3101
3342
  } else {
3102
- noResultLogEvidence = { stderr: `log-unavailable: ${logRead.unavailable}` };
3103
- debug.log('self-implement.pod', 'no-result-log-tail', { job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, logUnavailable: logRead.unavailable }, { level: 'warn' });
3343
+ const unavailable = `log-unavailable: ${logRead.unavailable}`;
3344
+ noResultLogEvidence = missingStage
3345
+ ? { stderr: unavailable }
3346
+ : { podLogUnavailable: logRead.unavailable };
3347
+ debug.log('self-implement.pod', missingStage ? 'no-result-log-tail' : 'failed-pod-log-tail', {
3348
+ job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic,
3349
+ logUnavailable: missingStage ? unavailable : logRead.unavailable,
3350
+ }, { level: 'warn' });
3104
3351
  }
3105
3352
  }
3106
3353
  if (childFailure) debug.log('self-implement.pod', 'child-error', { job: name, stage: childFailure.stage, error: childFailure.error, ...(childPrFailure ?? {}) }, { compact: { stringMax: 500 } });
@@ -3192,7 +3439,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3192
3439
  appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-oom-retry-finished', data: { job: name, executionKey, fromChildRunId: retryFromChildRunId, childRunId: liveChildRunId, state } }, ledgerDir);
3193
3440
  }
3194
3441
  if (goalFile) {
3195
- const noResultOutcome = state === 'failed' && containerExitCode !== null && noResultDiagnostic ? 'abandoned' : 'pod-no-result';
3442
+ const noResultOutcome = podVanished || (state === 'failed' && containerExitCode !== null && noResultDiagnostic) ? 'abandoned' : 'pod-no-result';
3196
3443
  const record: GoalExecutionRecord = {
3197
3444
  runId: liveChildRunId,
3198
3445
  stage: (state === 'aborted' || !disposition ? 'aborted' : disposition.stage) as GoalExecutionRecord['stage'],
@@ -3209,7 +3456,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3209
3456
  if (state === 'failed' || state === 'aborted' || noResultLogEvidence || (state === 'complete' && noResultDiagnostic !== null)) {
3210
3457
  // Every terminal attempt writes a marker, including one with no parseable child facts.
3211
3458
  // The next attempt must never inherit an earlier Pod's classification.
3212
- const childEvidence = noResultLogEvidence ?? disposition?.childEvidence ?? null;
3459
+ const childEvidence = noResultLogEvidence
3460
+ ? { ...(disposition?.childEvidence ?? {}), ...noResultLogEvidence }
3461
+ : disposition?.childEvidence ?? null;
3213
3462
  try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-evidence', data: { childEvidence, childRunId: liveChildRunId, job: name, ...(podTermination ? { podTermination } : {}) } }, ledgerDir); }
3214
3463
  catch (error) { debug.log('self-implement.pod', 'child-evidence-write-failed', { job: name, childRunId: liveChildRunId, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
3215
3464
  }
@@ -3218,7 +3467,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3218
3467
  if (disposition && (state === 'failed' || state === 'aborted' || disposition.ok === false)
3219
3468
  && (!Number.isSafeInteger(disposition.prNumber) || (disposition.prNumber ?? 0) <= 0) && terminalBranch) {
3220
3469
  try { prLookup = await (options.lookupOpenPrByBranch ?? defaultLookupOpenPrByBranch)(terminalBranch, repoUrl); }
3221
- catch { prLookup = { status: 'failed', reason: 'pr-lookup-threw' }; }
3470
+ catch (error) { prLookup = { status: 'failed', reason: `pr-lookup-failed: ${error instanceof Error ? error.message : String(error)}`.slice(0, 200) }; }
3222
3471
  }
3223
3472
  const terminalDisposition = prLookup?.status === 'found' && disposition
3224
3473
  ? { ...disposition, prNumber: prLookup.prNumber, prUrl: prLookup.prUrl } : disposition;
@@ -3262,7 +3511,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3262
3511
  : disposition;
3263
3512
  // A gate environment deficit can exit the child with 1 while still yielding a
3264
3513
  // verified repair bundle. The host rejudges the new PR head after CAS apply.
3265
- const podExitCode = repairPodExitCode({ state, repairCommitOnly: !!options.repairCommitOnly,
3514
+ const podExitCode = podVanished ? 1 : repairPodExitCode({ state, repairCommitOnly: !!options.repairCommitOnly,
3266
3515
  repairArtifactReady, disposition });
3267
3516
  // SCHED-CONTRACT: a failed child must say why outside the Pod, not «no error diagnostic».
3268
3517
  const rawPodReason = podExitCode === 1 ? extractPodFailureReason({ logs, logTailReason, containerReason, jobReason: failedReason || undefined, deadlineSeconds, result: disposition ? { stage: disposition.stage, prUrl: disposition.prUrl ?? null, prNumber: disposition.prNumber ?? null } : null }) : undefined;
@@ -3276,10 +3525,18 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3276
3525
  const salvageOutcome = /^ELANOUS_POD_SALVAGE \S+ \S+$/m.test(logs) ? 'pushed' : logs.includes('ELANOUS_POD_SALVAGE_NONE') ? 'none' : 'unknown';
3277
3526
  passJourneyNode('salvage', { provenance: 'self-implement-pod', outcome: salvageOutcome, data: { job: name } });
3278
3527
  }
3528
+ const repairGateReceipt = disposition?.stage === 'gate-failed' ? gateFailureReceipt(disposition.gate) : null;
3529
+ if (repairGateReceipt) {
3530
+ for (const line of gateFailureReceiptLines(repairGateReceipt)) console.log(line);
3531
+ debug.log('self-implement.pod', 'gate-failure-receipt', { job: name, childRunId: liveChildRunId,
3532
+ signature: repairGateReceipt.signature, tests: repairGateReceipt.tests });
3533
+ }
3279
3534
  return {
3280
3535
  exitCode: podExitCode,
3281
3536
  output: tail,
3282
- ...(deadlineExceeded
3537
+ ...(podVanished
3538
+ ? { error: { code: 'pod-vanished', message: `Job ${name} disappeared after 3 consecutive NotFound polls` } }
3539
+ : deadlineExceeded
3283
3540
  ? { error: { code: 'pod-deadline-exceeded', message: `Job ${name} 이 수명 상한 ${deadlineSeconds}초에 닿았다` } }
3284
3541
  : state === 'failed'
3285
3542
  ? containerExitCode === 7
@@ -3429,7 +3686,9 @@ export function podNoResultLogTailLines(source: string, maxLines: number = POD_N
3429
3686
  let chars = 0;
3430
3687
  for (const line of lines.slice(-Math.max(0, maxLines)).reverse()) {
3431
3688
  if (chars >= POD_NO_RESULT_LOG_TAIL_MAX_CHARS) break;
3432
- const bounded = boundedPodLogText(line, Math.min(POD_NO_RESULT_LOG_TAIL_LINE_CHARS, POD_NO_RESULT_LOG_TAIL_MAX_CHARS - chars));
3689
+ const redacted = redactSecretText(line);
3690
+ const limit = Math.min(POD_NO_RESULT_LOG_TAIL_LINE_CHARS, POD_NO_RESULT_LOG_TAIL_MAX_CHARS - chars);
3691
+ const bounded = redacted.length > limit ? `${redacted.slice(0, limit)}…[truncated]` : redacted;
3433
3692
  if (!bounded) continue;
3434
3693
  result.push(bounded);
3435
3694
  chars += bounded.length;
@@ -3451,7 +3710,7 @@ export function readPodNoResultLogTail(args: {
3451
3710
  }): PodNoResultLogRead {
3452
3711
  const maxLines = args.maxLines ?? POD_NO_RESULT_LOG_TAIL_LINES;
3453
3712
  try {
3454
- const result = args.run(['-n', args.namespace, 'logs', `job/${args.job}`, `--tail=${maxLines}`]);
3713
+ const result = args.run(['-n', args.namespace, 'logs', `job/${args.job}`, '-c', 'child', `--tail=${maxLines}`]);
3455
3714
  if (result.status !== 0) {
3456
3715
  const reason = boundedPodLogText(result.stderr || result.stdout || '', POD_NO_RESULT_LOG_REASON_MAX_CHARS);
3457
3716
  return { unavailable: reason || `kubectl logs exit ${result.status}` };