elanous 0.2.41 → 0.2.43

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 (796) 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/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{2fe2c302.41b517f88d6fe502.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{385e4574.e9886ab32759eda3.js → 0ad6802e.ae7afb63fdcb4491.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/114.2b90424d1a3ce84c.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1151-5c2bb8f002ca2dd6.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1200.6a37c202f9f17e9a.js +226 -0
  9. package/apps/pwa/out/_next/static/chunks/1261-a616d5728e02e624.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1313-19f737e0222c4444.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1357.3bbef3976c37f94a.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1362-20adddfaf662b0fa.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/{6874.d5cf7eb8edb2cabe.js → 1406.a1dc2ab6f8449374.js} +2 -2
  14. package/apps/pwa/out/_next/static/chunks/1737-9491fc6ab29b9ec6.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1803-4f91a8e7dcaf042c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{5744.b9415e18ad623100.js → 1961.a81b12872c3e93a9.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/1970cf59.2d4d8ce5d6c81853.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/2073-ba274e00e4f9efb4.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/{5471.1e611302ed3a7c53.js → 2144.25b292396712196d.js} +2 -2
  21. package/apps/pwa/out/_next/static/chunks/{3230-49298c3b73ef2268.js → 2268-53861f339e0b65a2.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/{9834.63ab2bbc3153172e.js → 2312.0c8b61e22d3136d7.js} +1 -1
  23. package/apps/pwa/out/_next/static/chunks/{1800.f7ff51dc4978a958.js → 2573.387a707f6f9d720c.js} +2 -2
  24. package/apps/pwa/out/_next/static/chunks/273.f156eee28f11af77.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2873.d2140e5a82546401.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/{9048.212083de42d25be3.js → 3072.01338851ca21a6f7.js} +2 -2
  27. package/apps/pwa/out/_next/static/chunks/3091.a5a4143dea33d197.js +90 -0
  28. package/apps/pwa/out/_next/static/chunks/3095.dc44586a5f83b86d.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{2263.e09b6edea33bad2d.js → 3113.d7472bbc27d580c7.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/3228-9650b6447b6fa288.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/3402.44b565b314f2263c.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{addc2b32.8c4ff8f0aefe987d.js → 3557ac4a.c8931684475018ad.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/360.ae9f9f4c33c395e8.js +79 -0
  34. package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
  35. package/apps/pwa/out/_next/static/chunks/{a0a01613.6d1cca322238d7fe.js → 363bfab3.9623b9f89363541f.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/3694.e0099884345f0198.js +64 -0
  37. package/apps/pwa/out/_next/static/chunks/3744.54f87db52acfd1ab.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3903.3ef4656c67572764.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3935.16701e33f8982dc9.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3955.6922286237f2ac2b.js +24 -0
  41. package/apps/pwa/out/_next/static/chunks/3969.272ee7f9fd6c62e5.js +34 -0
  42. package/apps/pwa/out/_next/static/chunks/4199.ce86b281fd0a60b7.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4311-6dd3144002cc0c2d.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4426-2b230fad00c88930.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{530.d26346e18089640a.js → 4445.7990c76b3751a918.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4447-14c5161fa59166c7.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4856-b0b8075bba8c53f4.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4870-de370d65e73c0bb5.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4885-2c989165c4b29fad.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4894.fec2ca9e99caefa2.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/5093.8f04b7f8cb899a95.js +94 -0
  52. package/apps/pwa/out/_next/static/chunks/5122-2bb177cebf89e19a.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/5154.5f56dc3902e3d275.js +36 -0
  54. package/apps/pwa/out/_next/static/chunks/529.64ff7257180b2ac9.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5394.5dabeb0c62293a28.js +93 -0
  56. package/apps/pwa/out/_next/static/chunks/5461.08bf2404ff38ec85.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5474-22e08a85583209b2.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{1219.7e17964e0e7cd8e5.js → 5564.9e72532188f57586.js} +3 -3
  59. package/apps/pwa/out/_next/static/chunks/5567-265df39ed8fe9dcb.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5570-a94ae19811cb2046.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5574-b47c9ef2dceff1fd.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5628.6ddb2d5ffba4ff4c.js +309 -0
  63. package/apps/pwa/out/_next/static/chunks/5730.43d7ccc09988e646.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{1178.1aa9cad0e7695427.js → 5789.2da35c258292e1e5.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/{4133.2056bb4d78f621af.js → 5824.da9527b15a3221e5.js} +1 -1
  66. package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/{4527.a69f2894d1bc9f4a.js → 5930.8b4df3b46c32b05a.js} +1 -1
  68. package/apps/pwa/out/_next/static/chunks/5963-c4d8469c52a0828b.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/6001.ec4049ceb3c43418.js +27 -0
  70. package/apps/pwa/out/_next/static/chunks/6120-471f03db1e299c0c.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6175-41479e643aca1878.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6291.a2de4f9787637075.js +104 -0
  73. package/apps/pwa/out/_next/static/chunks/6400-6699907c3537436a.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/6428.1f4327d6ae5fdf9a.js +287 -0
  75. package/apps/pwa/out/_next/static/chunks/644.02cb026fa44bcd0a.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6466-6c87d60d3dd174fb.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{9507.7026657a2f47eb64.js → 6540.c7bef57ad8f90a87.js} +16 -16
  78. package/apps/pwa/out/_next/static/chunks/6773.d4264665ab31bec0.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6822.3c789f1a8443e774.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/{5574.f35accf4f132b29d.js → 6944.309f4e3ea54d1537.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/7261-8ff69d3b2ee671fd.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7266.084c6bbc70035140.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7271.5c0100e7320aa856.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7429-bf5731358c8f2f68.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7464.01f7a0ae1215fbe7.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7479.0fcad5f37eb64f0c.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7483.427a2fe2049e388d.js +148 -0
  88. package/apps/pwa/out/_next/static/chunks/7502-be74718178e13e56.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7530.0889722b19572065.js +24 -0
  90. package/apps/pwa/out/_next/static/chunks/7645.5b2ee3ad45c55ea3.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7788.7d1c79f1a8e18946.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7900.096f455c7c1efc53.js +77 -0
  93. package/apps/pwa/out/_next/static/chunks/7910-6f139bcafd238b9f.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7966.f71c8958d1637548.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{5947-135e26537d80a6b9.js → 8062-7cd0bcc7f01455ba.js} +3 -3
  96. package/apps/pwa/out/_next/static/chunks/8073.f6cf2f2c71aafbd0.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8201.190b94088980f430.js +74 -0
  98. package/apps/pwa/out/_next/static/chunks/8205.282ca4bb62d54a0a.js +62 -0
  99. package/apps/pwa/out/_next/static/chunks/8313-dfa1021bb58a46d6.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/837-81336ebaca8198a8.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8447.7963352ef5f71b76.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8574-868e8129525ef6d9.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8588.d1c6a2903727ce87.js +149 -0
  104. package/apps/pwa/out/_next/static/chunks/8637.90f92d5c8db4732c.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{2743.5d3f76948be32b34.js → 868.6e953be05bcf6dca.js} +2 -2
  106. package/apps/pwa/out/_next/static/chunks/8706-e1fe0309343a2273.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8749-06384cdfc4520add.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{5964-7e21164a8f2cf0ce.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/8967-7dfebf710c9dec9d.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{5159.115f1c2ca471386c.js → 8986.8e2e4efbfa655c59.js} +1 -1
  111. package/apps/pwa/out/_next/static/chunks/8997-3c564dbb3b58b055.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/923.2034d10ae91e9c20.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/943.39ae5e82f4f1893f.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9469.0500480de55fb205.js +32 -0
  116. package/apps/pwa/out/_next/static/chunks/9770.5f75bc6088b16109.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9810-2543267050e58b82.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9870.8419702475254745.js +8 -0
  119. package/apps/pwa/out/_next/static/chunks/9941-376d1b74d51b01a4.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9958.385434ab04241758.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{b2271e54.c1de3347976e90b0.js → aa57532f.510551854ff239b1.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-deea1450b17cb8dc.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-70985b904f8650ef.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a2e15e33e56a4353.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-fc72ce2db12d6ca9.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-be03e41f9436ebd9.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-35a35999382da3f2.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-3ff5b1e6ca88b848.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-a65101300a0ee5c1.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-3aca5b6d67dba511.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-45b8ab0a71e61314.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-53046e282d4cda8e.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-17809e60e8354c17.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-fd2442d347bf5898.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-e9d720d6fc082e21.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-6b8b4267bab0a677.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-deea1450b17cb8dc.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-8bcf6233ac7c17af.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-7cc25591cfc2126f.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-053e871f35c9beba.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-eff819f0c2d5e084.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-4d7e9d8db5274a87.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-2b2d8f5aa5f69ad4.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-0b8f92c5062e68b1.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1bd9d0fdac2ced3d.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-9ee28f7df07428ea.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-44b7a1ff468c6648.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-cbc6523711dc1b65.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-fdad47899c2695be.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-40f9e19149024298.js → page-79a8b5fee4c20871.js} +1 -1
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-03e8ac9606aeaffb.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-4cd55c55ec287e2f.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-db17b4305404161e.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-30041d848350fd02.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c540da022dbf86b0.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9399efc538da057f.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-a142dfb0331a05f5.js → page-ca2d09128c585ca4.js} +1 -1
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-0e2635aecd343038.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ef7f4399b6b7726e.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-deea1450b17cb8dc.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-caf530535b875468.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-eaa20c1543a5fd8e.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c541eb1b75120f61.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-ab5e213eda9479f4.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-0a815f34367b6db6.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-e858ba0ed9393b68.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-1638ee9dd6e0582f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-4cf5a399109391f2.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-b4396321238798ec.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-cb72bfd21006781a.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6135d0242afbc434.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a1dccf907eddb856.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{53aeb4ee-51c92f8d683f5220.js → c7945435-b44d4dbe90ba0dcb.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/{2fdf2931.b431eee4fb468bc3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/{c0c1a699.0ba79f97005965d4.js → d96660fb.cbc21a2a88539dbb.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/ea514caa.05a24f78d9dffe5f.js +122 -0
  177. package/apps/pwa/out/_next/static/chunks/{83184dcd-0ee6247ff41eb3f2.js → fb7d20d5-6892502b6ee39ca6.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-e8a911e19b1be41f.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-7022f418fabba021.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-e5f15df755756a1e.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-4525f91e36940c9b.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-140f0e519c085b0f.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-8f22ef63dcb865b1.js +1 -0
  184. package/apps/pwa/out/_next/static/css/{b9d8151e48998417.css → 62c858ad53854f47.css} +1 -1
  185. package/apps/pwa/out/_next/static/css/d1f8bb401740a549.css +1 -0
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +23 -23
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +23 -23
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +23 -23
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +22 -22
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +22 -22
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +23 -23
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +22 -22
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +23 -23
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +23 -23
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +22 -22
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +23 -23
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +24 -25
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +23 -23
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +23 -23
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +22 -22
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +23 -23
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +23 -23
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +24 -25
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +24 -25
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +22 -22
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +22 -22
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +23 -23
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +23 -23
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +22 -22
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +22 -22
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +22 -22
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +23 -23
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +23 -23
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +22 -22
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +23 -23
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +23 -23
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +23 -23
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +23 -23
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +23 -23
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +22 -22
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +23 -23
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +23 -23
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +23 -23
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +23 -23
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +23 -23
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +23 -23
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +23 -23
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +23 -23
  279. package/catalog/external-commands.yaml +5 -3
  280. package/catalog/meta/catalogVersion.yaml +2 -1
  281. package/catalog/signing/catalog-signing-public.pem +3 -0
  282. package/docs/goal-context/04-mock-scenarios.md +13 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/heal/heal-loop.yaml +1 -0
  285. package/graphs/intake/intake-daily.yaml +16 -0
  286. package/graphs/intake/news-sources.yaml +1 -0
  287. package/graphs/intake/recipes.yaml +7 -0
  288. package/graphs/overlays/examples/research-runtime-empty-terminal.yaml +28 -0
  289. package/graphs/overlays/stop-heal-ladder.yaml +113 -0
  290. package/graphs/profiles/local.yaml +5 -0
  291. package/graphs/profiles/pod.yaml +4 -0
  292. package/graphs/units/verbs/recipes.yaml +11 -11
  293. package/graphs/work/research-report.yaml +10 -2
  294. package/package.json +6 -2
  295. package/plugins/demo-absorption-briefing/plugin.json +18 -0
  296. package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
  297. package/plugins/demo-browser-hand/plugin.json +13 -0
  298. package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
  299. package/plugins/demo-linear-secretary/plugin.json +15 -0
  300. package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
  301. package/plugins/demo-plugin-wizard/plugin.json +11 -0
  302. package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
  303. package/plugins/demo-research/plugin.json +16 -0
  304. package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
  305. package/plugins/demo-video-briefing/plugin.json +15 -0
  306. package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
  307. package/scripts/build-signed-catalog.ts +48 -0
  308. package/scripts/ci-typecheck-main-delta.sh +88 -0
  309. package/scripts/codex-fallback-live-probe.ts +1 -1
  310. package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
  311. package/scripts/demo/demo1104-stage.config.ts +21 -0
  312. package/scripts/demo/demo1104-stage.ts +316 -0
  313. package/scripts/goal-method-audit.ts +17 -1
  314. package/scripts/graph-units/land-enqueue.ts +90 -0
  315. package/scripts/heal/run-role.ts +99 -5
  316. package/scripts/hooks/codex-notify.sh +32 -0
  317. package/scripts/install.sh +10 -38
  318. package/scripts/land-global-checks.ts +6 -1
  319. package/scripts/landing-heal/land-plan.ts +57 -0
  320. package/scripts/lib/decompose-ab.ts +1 -0
  321. package/scripts/lib/fixtures/tui-regress/help-insufficient-commands.txt +15 -0
  322. package/scripts/lib/fixtures/tui-regress/help-live.txt +42 -0
  323. package/scripts/lib/fixtures/tui-regress/help-missing-keys.txt +21 -0
  324. package/scripts/lib/fixtures/tui-regress/help-original.txt +51 -0
  325. package/scripts/lib/fixtures/tui-regress/help-shifted-input.txt +26 -0
  326. package/scripts/lib/tui-regress-checks.ts +33 -13
  327. package/scripts/release-loop/auto-approve-node.ts +1 -1
  328. package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
  329. package/scripts/release-loop/gate-baseline-receipt.ts +47 -9
  330. package/scripts/release-loop/gate-image-pin.ts +81 -0
  331. package/scripts/release-loop/gate-method.ts +139 -0
  332. package/scripts/release-loop/gate-node-sim.ts +207 -0
  333. package/scripts/release-loop/gate-node.ts +463 -64
  334. package/scripts/release-loop/gate-pod-image-sticky-plan.ts +99 -0
  335. package/scripts/release-loop/gate-radius-live.ts +97 -13
  336. package/scripts/release-loop/gate-shard-dispatch.ts +43 -0
  337. package/scripts/release-loop/gate-traffic-mode.ts +151 -3
  338. package/scripts/release-loop/gate-train-receipts.ts +122 -0
  339. package/scripts/release-loop/node-verdict.ts +38 -25
  340. package/scripts/release-loop/preflight.ts +362 -8
  341. package/scripts/release-loop/resume-release.ts +83 -8
  342. package/scripts/release-loop/unattended-release.ts +20 -9
  343. package/scripts/rhythm/daily.ts +36 -4
  344. package/scripts/rhythm/linear-progress-sync.ts +298 -0
  345. package/scripts/ux-sim.ts +18 -1
  346. package/scripts/video-pipeline.ts +9 -1
  347. package/scripts/warm-pool-provider-config.ts +286 -0
  348. package/skills/omni-crawl/SKILL.md +5 -2
  349. package/skills/omni-crawl/scripts/main.ts +84 -23
  350. package/src/acp/agent-manager.ts +1 -0
  351. package/src/acp/codex-app-server-agent.ts +33 -0
  352. package/src/acp/codex-app-server-client.ts +153 -16
  353. package/src/acp/core-turn-bridge.ts +27 -9
  354. package/src/acp/event-router.ts +20 -1
  355. package/src/acp/server.ts +6 -0
  356. package/src/agent/registry.ts +2 -0
  357. package/src/agent/task-notification.ts +25 -5
  358. package/src/agent/types.ts +6 -0
  359. package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
  360. package/src/agent-mission/claude-headless.ts +4 -1
  361. package/src/agent-mission/codex-exec.ts +105 -0
  362. package/src/agent-mission/driver.ts +192 -11
  363. package/src/agent-mission/grok-auth-status.ts +47 -0
  364. package/src/agent-mission/hand-hooks.ts +101 -0
  365. package/src/agent-mission/mission-cli.ts +63 -4
  366. package/src/agent-mission/mission-hand-reply.ts +118 -0
  367. package/src/agent-mission/mission-line.ts +180 -0
  368. package/src/agent-mission/mission-out.ts +833 -0
  369. package/src/agent-mission/tool-install.ts +200 -3
  370. package/src/agent-substrate/context-strategy.ts +4 -4
  371. package/src/agent-substrate/self-review-cli.ts +178 -13
  372. package/src/agents/general-purpose.md +1 -1
  373. package/src/auto-research/research-turn.ts +211 -53
  374. package/src/autopilot/pr-manager.ts +69 -10
  375. package/src/autopilot/pty-control-loop.ts +2 -0
  376. package/src/boot/daemon-tools/self-implement.ts +3 -1
  377. package/src/boot/daemon-tools/web-search.ts +1 -2
  378. package/src/briefing/brief-items.ts +55 -11
  379. package/src/capture/tui-self-report.ts +22 -6
  380. package/src/chat/index.ts +1 -1
  381. package/src/cli/agent-cli.ts +2 -1
  382. package/src/cli/catalog-cli.ts +31 -0
  383. package/src/cli/connector-cli.ts +16 -0
  384. package/src/cli/doctor-fix.ts +2 -2
  385. package/src/cli/fixtures/review-loop-breaker/opwaiver-32646-1694ccc7a170.json +1 -0
  386. package/src/cli/fixtures/review-loop-breaker/opwaiver-32853-bd8f73595c83.json +1 -0
  387. package/src/cli/fixtures/review-loop-breaker/opwaiver-33097-1cc85900413c.json +1 -0
  388. package/src/cli/fixtures/review-loop-breaker/opwaiver-33106-972f31e4a3ca.json +1 -0
  389. package/src/cli/fixtures/review-loop-breaker/opwaiver-33113-3ab51f05968f.json +1 -0
  390. package/src/cli/fixtures/review-loop-breaker/pr-33097-1cc85900413c.json +1 -0
  391. package/src/cli/intake-source-cli.ts +44 -8
  392. package/src/cli/msg-cli.ts +32 -3
  393. package/src/cli/pr-cli.ts +21 -1
  394. package/src/cli/pr-land-heavy-remote.ts +75 -5
  395. package/src/cli/pr-land-overlap-evidence.ts +113 -2
  396. package/src/cli/pr-land-pod-shadow-job.ts +202 -4
  397. package/src/cli/pr-land-pod-shadow.ts +9 -2
  398. package/src/cli/release-checklist-read-cli.ts +57 -19
  399. package/src/cli/release-cli.ts +23 -3
  400. package/src/cli/research-cli.ts +13 -5
  401. package/src/cli/setup-cli.ts +166 -6
  402. package/src/cli/setup-keys.ts +187 -0
  403. package/src/cli/task-plugin-wizard-host.ts +114 -0
  404. package/src/cli/tasks-cli.ts +61 -9
  405. package/src/cli/tui-test-cli.ts +186 -0
  406. package/src/compact/auto.ts +8 -1
  407. package/src/config.ts +4 -2
  408. package/src/connectors/linear-daily-progress.ts +228 -0
  409. package/src/connectors/linear-projector.ts +34 -12
  410. package/src/connectors/linear.ts +151 -7
  411. package/src/control-plane/ledger.ts +52 -2
  412. package/src/control-plane/server.ts +16 -2
  413. package/src/core-turn/deep-turn-bloom.ts +67 -0
  414. package/src/core-turn/research-policy.ts +37 -0
  415. package/src/core-turn/run-core-turn.ts +606 -95
  416. package/src/core-turn/run-goal-loop.ts +18 -0
  417. package/src/core-turn/types.ts +4 -0
  418. package/src/dashboard/chat/acp-chat.ts +10 -0
  419. package/src/dashboard/classic-sidetab-mission-job.ts +161 -0
  420. package/src/dashboard/classic-sidetab-mission-pair.ts +81 -0
  421. package/src/dashboard/classic-sidetab-mission-trio.ts +219 -0
  422. package/src/dashboard/classic-sidetab-mission.ts +347 -0
  423. package/src/dashboard/index.ts +517 -18
  424. package/src/dashboard/input/agent-wake.ts +23 -1
  425. package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
  426. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +17 -0
  427. package/src/dashboard/mission-cli-consumer.ts +165 -0
  428. package/src/dashboard/plugin-wizard-runtime.ts +50 -0
  429. package/src/dashboard/plugin-wizard-tool.ts +55 -0
  430. package/src/dashboard/seat-boot-preamble.ts +171 -1
  431. package/src/dashboard/side-basic-runtime.ts +54 -1
  432. package/src/dashboard/sidetab-runtime.ts +90 -1
  433. package/src/dashboard/skill-catalog-preamble.ts +101 -0
  434. package/src/dashboard/skill-detection-runtime.ts +55 -15
  435. package/src/dashboard/slash-runtime/dashboard-handlers.ts +15 -0
  436. package/src/dashboard/terminal-popup-runtime.ts +6 -3
  437. package/src/dashboard/turn-preamble.ts +53 -15
  438. package/src/dashboard/turn-prompt-runtime.ts +4 -2
  439. package/src/decisions/linear-progress-summary.ts +78 -0
  440. package/src/decisions/linear-progress-sync.ts +152 -0
  441. package/src/domains/outbound-alert.ts +49 -11
  442. package/src/domains/telegram-kind-route.ts +16 -9
  443. package/src/graph-runner/arg-allowance.ts +13 -0
  444. package/src/graph-runner/graph-cli.ts +23 -7
  445. package/src/graph-runner/graph-run-api.ts +3 -1
  446. package/src/graph-runner/graph-tick.ts +10 -2
  447. package/src/graph-runner/runner.ts +86 -18
  448. package/src/graph-wizard/mission-compose.ts +407 -12
  449. package/src/grok/agent-search.ts +14 -4
  450. package/src/grok/credential.ts +28 -11
  451. package/src/harness/dispatch-backpressure.ts +54 -1
  452. package/src/harness/dispatch-shadow-compare.ts +74 -0
  453. package/src/harness/harness-cli-command.ts +11 -1
  454. package/src/harness/harness-pod-dispatch.ts +81 -15
  455. package/src/harness/harness-stop.ts +155 -11
  456. package/src/harness/skill-exec.ts +21 -9
  457. package/src/harness/skill-select.ts +1 -1
  458. package/src/hooks/error-report-cloud.ts +101 -0
  459. package/src/hooks/receiver.ts +29 -2
  460. package/src/index.ts +159 -13
  461. package/src/instance/spawn-elanous.ts +6 -4
  462. package/src/intake-plane/actions.ts +354 -0
  463. package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
  464. package/src/intake-plane/intake-sources.ts +78 -8
  465. package/src/intake-plane/items.ts +14 -4
  466. package/src/intake-plane/linear-mission-sync.ts +80 -0
  467. package/src/intake-plane/linear-secretary-runtime.ts +178 -0
  468. package/src/intake-plane/linear-wish.ts +227 -1
  469. package/src/life/life-cli.ts +168 -0
  470. package/src/life/life-kinds.ts +160 -0
  471. package/src/live-supply/budget-consumer.ts +78 -0
  472. package/src/live-supply/read.ts +3 -0
  473. package/src/live-supply/snapshot.ts +45 -0
  474. package/src/llm/provider-credentials.ts +8 -2
  475. package/src/llm.ts +168 -9
  476. package/src/loops/orchestrator/coordinator-shadow.ts +226 -0
  477. package/src/loops/orchestrator/tick.ts +13 -0
  478. package/src/maturity/feature-maturity.ts +4 -4
  479. package/src/msg/msg-sse-server.ts +3 -3
  480. package/src/msg/msg-store.ts +177 -19
  481. package/src/native-tool-catalog.ts +38 -4
  482. package/src/nexus/api/harness-traversal.ts +11 -0
  483. package/src/nexus/api/http-server.ts +37 -1
  484. package/src/nexus/api/mcp-public-allowlist.ts +2 -0
  485. package/src/nexus/index.ts +7 -2
  486. package/src/nexus/outbound/format.ts +9 -0
  487. package/src/nexus/outbound/router.ts +98 -13
  488. package/src/nexus/setup-status.ts +9 -0
  489. package/src/nexus/state/state.ts +3 -0
  490. package/src/oauth/codex-account-store.ts +20 -7
  491. package/src/oauth/codex-owner-mirror.ts +44 -0
  492. package/src/oauth/codex.ts +17 -2
  493. package/src/oauth/fallback-chain.ts +47 -17
  494. package/src/onboarding/first-run-doctor.ts +8 -1
  495. package/src/onboarding/first-run.ts +85 -26
  496. package/src/onboarding/key-setup.ts +103 -0
  497. package/src/onboarding/menu-answer.ts +13 -0
  498. package/src/onboarding/secret-prompt.ts +37 -0
  499. package/src/plugins/install/plugin-install.ts +59 -0
  500. package/src/pr-tool/census.ts +133 -2
  501. package/src/pty-shell/pty-control-ipc.ts +4 -1
  502. package/src/pty-shell/tui-run-state.ts +188 -2
  503. package/src/registry/catalog-server.ts +232 -0
  504. package/src/registry/loader.ts +45 -1
  505. package/src/registry/types.ts +1 -2
  506. package/src/release-loop/checklist-target-path-hint.ts +13 -0
  507. package/src/release-loop/checklist.ts +9 -1
  508. package/src/repl/index.ts +43 -2
  509. package/src/research/axis-fanout.ts +136 -16
  510. package/src/research/bloom-exemplars.ts +3 -1
  511. package/src/research/gap-followup.ts +13 -1
  512. package/src/research/plugin-discovery.ts +36 -14
  513. package/src/research-bridge/invoke.ts +22 -5
  514. package/src/research-bridge/types.ts +2 -0
  515. package/src/self-dev/ask-launch-flow.ts +72 -1
  516. package/src/self-dev/decompose.ts +119 -5
  517. package/src/self-dev/dev-cli.ts +4 -1
  518. package/src/self-dev/dev-pipeline.ts +5 -0
  519. package/src/self-dev/draft-residue.ts +64 -5
  520. package/src/self-dev/graph-front-nodes.ts +2 -1
  521. package/src/self-dev/graph-journey-route.ts +76 -21
  522. package/src/self-dev/launch-preflight-text.ts +5 -6
  523. package/src/self-dev/launch-preflight.ts +58 -0
  524. package/src/self-dev/orchestrate.ts +13 -3
  525. package/src/self-dev/review-provider-fallback.ts +9 -2
  526. package/src/self-dev/run-supervisor.ts +42 -4
  527. package/src/self-dev/run-types.ts +4 -0
  528. package/src/self-dev/shard-aggregate.ts +4 -0
  529. package/src/self-dev/shard-run.ts +36 -15
  530. package/src/self-implement/abandoned-classification.ts +12 -3
  531. package/src/self-implement/budget-gate.ts +7 -0
  532. package/src/self-implement/child-llm-preference.ts +10 -1
  533. package/src/self-implement/doctor-visit.ts +118 -8
  534. package/src/self-implement/elanous-tui-spawn.ts +3 -0
  535. package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
  536. package/src/self-implement/gate-artifacts.ts +2 -1
  537. package/src/self-implement/goal-author-cli.ts +4 -2
  538. package/src/self-implement/goal-author.ts +684 -7
  539. package/src/self-implement/graph-overlay-yaml.ts +37 -4
  540. package/src/self-implement/graph-overlay.ts +3 -1
  541. package/src/self-implement/graph-profile-yaml.ts +107 -0
  542. package/src/self-implement/graph-yaml.ts +26 -3
  543. package/src/self-implement/headless-elanous-driver.ts +31 -2
  544. package/src/self-implement/heal-intake.ts +112 -4
  545. package/src/self-implement/heal-triage.ts +20 -0
  546. package/src/self-implement/host-regate.ts +27 -4
  547. package/src/self-implement/merge-train.ts +5 -0
  548. package/src/self-implement/off-diff-evidence.ts +249 -5
  549. package/src/self-implement/orchestrator.ts +365 -25
  550. package/src/self-implement/regate-detail.ts +38 -1
  551. package/src/self-implement/rework-child-provider.ts +25 -0
  552. package/src/self-implement/run-chart.ts +122 -0
  553. package/src/self-implement/run-ledger.ts +162 -11
  554. package/src/self-implement/run-stop.ts +188 -4
  555. package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
  556. package/src/self-implement/stop-autoheal.ts +13 -0
  557. package/src/self-implement/tdd-evidence-tags.ts +9 -0
  558. package/src/self-implement/train-gate-receipt.ts +166 -0
  559. package/src/self-implement/train-gate-remote.ts +62 -18
  560. package/src/session/chat.ts +40 -4
  561. package/src/session/session-fanout.ts +2 -0
  562. package/src/session/streaming/acp-stream-sink.ts +2 -1
  563. package/src/session/streaming/chunk-producer.ts +6 -0
  564. package/src/session/streaming/stream-compositor.ts +3 -2
  565. package/src/session-runtime/index.ts +135 -5
  566. package/src/session-runtime/retry-policy.ts +1 -1
  567. package/src/session-runtime/tier-flip.ts +3 -3
  568. package/src/setup/llm-env-detect.ts +3 -0
  569. package/src/setup/service-key-catalog.ts +46 -0
  570. package/src/setup/service-keys.ts +241 -0
  571. package/src/sidetab-core/model.ts +19 -5
  572. package/src/sidetab-core/visible-agent-mission.ts +262 -0
  573. package/src/skills/name-match.ts +20 -0
  574. package/src/skills/tools/agent.ts +53 -6
  575. package/src/skills/tools/omni-search.ts +173 -13
  576. package/src/task-agent/parent-host.ts +10 -0
  577. package/src/task-agent/pod-distributor-entry.ts +3 -0
  578. package/src/task-agent/repair-outcomes.ts +65 -0
  579. package/src/task-agent/task-hand.ts +47 -7
  580. package/src/task-orchestrator/dispatcher.ts +14 -1
  581. package/src/task-orchestrator/linear-capture-events.ts +55 -0
  582. package/src/task-orchestrator/store.ts +16 -5
  583. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +4 -0
  584. package/src/task-orchestrator/surfaces/pod-distributor.ts +48 -0
  585. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +92 -1
  586. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +38 -1
  587. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
  588. package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +33 -6
  589. package/src/task-orchestrator/surfaces/pod-source-bundle.ts +45 -9
  590. package/src/task-orchestrator/surfaces/pod-source-receive.ts +178 -16
  591. package/src/task-orchestrator/surfaces/pod-source-spec.ts +3 -3
  592. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
  593. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +237 -41
  594. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +80 -3
  595. package/src/task-orchestrator/surfaces/self-implement-pod.ts +337 -51
  596. package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
  597. package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
  598. package/src/task-orchestrator/types.ts +14 -0
  599. package/src/telegram.ts +14 -16
  600. package/src/terminal/coding-agent.ts +14 -5
  601. package/src/terminal/session-registry.ts +1 -1
  602. package/src/tokens.ts +35 -2
  603. package/src/tool-hints/gate.ts +1 -0
  604. package/src/tool-runtime/agent-runtime.ts +2 -0
  605. package/src/tool-runtime/browser-hand-runtime.ts +381 -0
  606. package/src/tool-runtime/browser-runtime.ts +2 -1
  607. package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
  608. package/src/tool-runtime/elanous-linear-secretary-runtime.ts +57 -0
  609. package/src/tool-runtime/elanous-skills-list-runtime.ts +5 -1
  610. package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
  611. package/src/tool-runtime/index.ts +6 -0
  612. package/src/tool-runtime/skill-exec-runtime.ts +33 -13
  613. package/src/tool-runtime/types.ts +4 -0
  614. package/src/tui/entry.ts +38 -5
  615. package/src/tui/sidetab/attach.ts +177 -1
  616. package/src/tui/sidetab/herdr-portal.ts +225 -0
  617. package/src/tui-client/local-chat-turn.ts +26 -13
  618. package/src/tui.ts +22 -0
  619. package/src/user-config.ts +34 -9
  620. package/src/user-intent/types.ts +4 -3
  621. package/src/ux-sim/browser-hand.ts +165 -0
  622. package/src/ux-sim/draft-inventory-builder.ts +198 -0
  623. package/src/ux-sim/fake-browser-page.ts +81 -0
  624. package/src/ux-sim/fake-kubectl.ts +37 -3
  625. package/src/ux-sim/fake-linear-device.ts +31 -0
  626. package/src/ux-sim/fault-pool-cap.ts +11 -6
  627. package/src/ux-sim/graph-engine-sim.ts +47 -0
  628. package/src/ux-sim/linear-secretary.ts +216 -0
  629. package/src/ux-sim/mock-scenario-catalog.json +93 -0
  630. package/src/ux-sim/mock-scenario-catalog.ts +274 -0
  631. package/src/ux-sim/onboarding-first-run-device.ts +31 -21
  632. package/src/ux-sim/scenario.ts +185 -48
  633. package/src/ux-sim/service-key-setup.ts +50 -0
  634. package/src/ux-sim/term-slash-device.ts +74 -0
  635. package/src/ux-sim/turn-throw-sim.ts +31 -0
  636. package/src/version/packed-revision.json +1 -1
  637. package/src/voice/voice-tts-singleton.ts +18 -3
  638. package/src/web-search/exa.ts +77 -0
  639. package/src/web-search/grok.ts +5 -9
  640. package/src/web-search/index.ts +30 -9
  641. package/src/web-search/provider.ts +4 -1
  642. package/src/web-search/x-intent.ts +5 -0
  643. package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +0 -149
  644. package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +0 -36
  645. package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +0 -287
  647. package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +0 -90
  652. package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/1765.679b29625c8e88d4.js +0 -77
  654. package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +0 -32
  665. package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +0 -79
  667. package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +0 -74
  671. package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +0 -148
  681. package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +0 -226
  682. package/apps/pwa/out/_next/static/chunks/4667.97e31aa38c95c475.js +0 -309
  683. package/apps/pwa/out/_next/static/chunks/4702.4a4adc1f16d7c93b.js +0 -64
  684. package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +0 -94
  691. package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +0 -8
  693. package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +0 -24
  696. package/apps/pwa/out/_next/static/chunks/5892.2526d962339662d8.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +0 -286
  699. package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +0 -27
  703. package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +0 -62
  705. package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +0 -24
  706. package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +0 -122
  708. package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/7191.fdc955f7d96064a4.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/8050-9b364bdef8f71927.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +0 -104
  720. package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +0 -93
  733. package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +0 -34
  738. package/apps/pwa/out/_next/static/chunks/9869.81a1e24ca682d5a0.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/botlab/page-14949db884bfa672.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +0 -1
  794. package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
  795. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +0 -1
  796. /package/apps/pwa/out/_next/static/{GiOLWmt4MqDZePubBjA4Q → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
@@ -79,6 +79,39 @@ export function recordPodSourceIoSummary(logs: string, job: string, runId: strin
79
79
  }
80
80
  }
81
81
 
82
+ export type PodSourceAttemptOutcome = {
83
+ classification: 'explicit-source-failure' | 'source-complete' | 'status-not-recorded';
84
+ sourceStage: string | null;
85
+ sourceKind: string | null;
86
+ sourceVia: string | null;
87
+ sourceStatus: string | null;
88
+ baseSha: string | null;
89
+ exitCode: number | null;
90
+ failureCode: string | null;
91
+ };
92
+
93
+ /** Keep missing telemetry distinct from an observed source-stage failure. */
94
+ export function parsePodSourceAttemptOutcome(logs: string | null, fallback: { sourceKind?: string | null; baseSha?: string | null } = {}): PodSourceAttemptOutcome {
95
+ const resultLine = logs ? /^ELANOUS_POD_SOURCE_RESULT (\{[^\r\n]+\})\r?$/m.exec(logs)?.[1] : undefined;
96
+ const result = resultLine ? (() => { try { return JSON.parse(resultLine) as Record<string, unknown>; } catch { return null; } })() : null;
97
+ const explicitBaseFailure = !!logs && /^ELANOUS_POD_SOURCE_BASE_SHA_UNAVAILABLE [^\r\n]+\r?$/m.test(logs);
98
+ const ioLine = logs ? /^ELANOUS_POD_SOURCE_IO (\{[^\r\n]+\})\r?$/m.exec(logs)?.[1] : undefined;
99
+ const io = ioLine ? (() => { try { return JSON.parse(ioLine) as Record<string, unknown>; } catch { return null; } })() : null;
100
+ const validString = (value: unknown): string | null => typeof value === 'string' && value.length > 0 ? value : null;
101
+ const resultFailure = validString(result?.failureCode) ?? (explicitBaseFailure ? 'base-sha-unavailable' : null);
102
+ const status = validString(result?.sourceStatus) ?? (io?.sourceStatus === 'complete' || io?.sourceStatus === 'incomplete' ? io.sourceStatus : null);
103
+ return {
104
+ classification: resultFailure || explicitBaseFailure ? 'explicit-source-failure' : status === 'complete' ? 'source-complete' : 'status-not-recorded',
105
+ sourceStage: validString(result?.sourceStage) ?? (explicitBaseFailure ? 'base-sha' : null),
106
+ sourceKind: validString(result?.sourceKind) ?? fallback.sourceKind ?? null,
107
+ sourceVia: validString(result?.sourceVia) ?? validString(io?.sourceVia) ?? (/^ELANOUS_POD_SOURCE_VIA (image|mirror|github|bundle|min-sync)\r?$/m.exec(logs ?? '')?.[1] ?? null),
108
+ sourceStatus: status,
109
+ baseSha: validString(result?.baseSha) ?? fallback.baseSha ?? null,
110
+ exitCode: typeof result?.exitCode === 'number' && Number.isInteger(result.exitCode) ? result.exitCode : null,
111
+ failureCode: resultFailure,
112
+ };
113
+ }
114
+
82
115
  /** Select a timestamp for a DeadlineExceeded observation without making detector time look like Job completion.
83
116
  * `podFinishedAt` must come from readPodTermination for the same verified Job uid. */
84
117
  export function podJobFinishedTiming(input: { jobCreatedAt: string | null; jobCompletedAt: string | null;
@@ -102,6 +135,7 @@ import { POD_LAUNCH_FINISHED_EVENT, POD_LAUNCH_STARTED_EVENT, provenanceRowFromA
102
135
  import { podProvenanceMetadata, type PodProvenanceMetadata } from './pod-provenance.js';
103
136
  import { packageVersion } from '../../version/code-revision.js';
104
137
  import { minihLocationFrom, podWorkLabels, type PodWorkIdentity, type PodPlacement, type PodPlacementKind, type PodPoolMember, type PodPoolScheduler } from './pod-pool.js';
138
+ import { acquirePodPoolSlot, POD_DISTRIBUTOR_ENTRY_ENV, type PodDistributorAdapter } from './pod-distributor.js';
105
139
  export { POD_CHILD_REQUESTS } from './pod-lease.js';
106
140
  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';
107
141
  import { ACTUAL_SUBSTRATE_ENV, RUN_CONTRACT_ENV, carryRunContract, completionFloorFor } from '../../self-implement/graph-run-contract.js';
@@ -131,7 +165,7 @@ import { normalizeFallbackChain, type FallbackStep } from '../../oauth/fallback-
131
165
  import { goalTypeOf, type GoalType } from '../../../scripts/measure-pod-memory-by-goal.js';
132
166
  import { declaredGoalType, type GoalType as DeclaredGoalType } from '../../self-implement/goal-author.js';
133
167
  import { readPodMemoryAdvice, type PodMemoryAdvice } from '../../cli/pod-memory-advice.js';
134
- import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, getUserConfig, roleLlmEnvName, type UserConfig } from '../../user-config.js';
168
+ import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, getUserConfig, resolveRoleLlm, roleLlmEnvName, type UserConfig } from '../../user-config.js';
135
169
  import { worktreeAddTimeoutSec } from '../../git-fs/worktree.js';
136
170
  import { podChildProviderOf, podChildProviderRefusal, type PodChildProvider } from './pod-child-providers.js';
137
171
  import { BEDROCK_POD_EGRESS_LABEL, bedrockPodEnv, checkBedrockPodSecret, type BedrockPodSpec } from './pod-bedrock-child.js';
@@ -140,7 +174,7 @@ import { ZAI_POD_EGRESS_LABEL, checkZaiPodSecret, countActiveZaiJobs, decideZaiP
140
174
  import { ZAI_CODING_DEFAULT_MODEL, ZAI_OPENROUTER_FALLBACK_MODEL, zaiSettingsFromConfig, type ZaiCodingPlanSettings } from '../../llm/zai-coding-plan.js';
141
175
  import { normalizePlanningFallbackReason, selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
142
176
  import { inferProviderFromModel } from '../../llm.js';
143
- import { classifyPodExit, extractPodFailureReason, podChildEvidenceLedgerRow, podChildFailureAttribution, podDeadlineResultMarker, podJobConditionReason, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
177
+ import { classifyPodExit, extractPodFailureReason, podChildEvidenceLedgerRow, podChildFailureAttribution, podChildProviderFailureFact, podDeadlineResultMarker, podJobConditionReason, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
144
178
  import { kubectlTransientReason, retryKubectlTransient } from './kubectl-transient-retry.js';
145
179
  import { OLD_DOOR_STAMP_ENV } from '../../self-dev/old-door.js';
146
180
  import { resolveDefaultSourceHead, seedMirrorOnce, type MirrorSeedResult } from './pod-mirror-seed.js';
@@ -288,6 +322,8 @@ export interface PodSpawnOptions {
288
322
  readSkillEnv?: () => Record<string, string>;
289
323
  /** ☸️ 여러 클러스터 풀(pod-pool.ts) — Job 마다 우선순위 순 첫 빈 자리로. 없으면 현재 컨텍스트 하나. */
290
324
  pool?: PodPoolScheduler;
325
+ /** POD-DISTRIBUTOR-WIRE — replaceable admission seam; tasks-hand only in the first wire slice. */
326
+ podDistributorAdapter?: PodDistributorAdapter;
291
327
  /** ☸️ 원격 그라운딩 주소(P13) — 없으면 호스트 env ELANOUS_GROUNDING_URL → 설정 pod.groundingUrl. 셋 다 없으면 토큰을 안 만든다. */
292
328
  groundingUrl?: string;
293
329
  /** 시험 심 — 토큰 발급·회수. GitHub credential 토큰에는 호스트가 검증한 저장소를 서명한다. */
@@ -373,7 +409,8 @@ async function measureHostBudgetSnapshot(childLlm: PodBudgetChildLlm, env: NodeJ
373
409
  const host = resolveHostId(env);
374
410
  const measuredAt = Date.now();
375
411
  const { readBudgetInputsLive, CODEX_PROVIDER, GROK_PROVIDER } = await import('../../self-implement/budget-gate.js');
376
- const inputs = await readBudgetInputsLive(inputDeps);
412
+ const { budgetInputsWithLiveSupply } = await import('../../live-supply/budget-consumer.js');
413
+ const inputs = budgetInputsWithLiveSupply(await readBudgetInputsLive(inputDeps));
377
414
  const { decision } = harnessLaunchBudgetDecision(inputs, { ...(childLlm.provider ? { childLlmProvider: childLlm.provider } : {}), ...(childLlm.model ? { childLlmModel: childLlm.model } : {}) });
378
415
  const provider = decision.provider ?? childLlm.provider ?? 'chain';
379
416
  const used = provider === GROK_PROVIDER
@@ -1582,6 +1619,22 @@ export function repairPodExitCode(input: { state: string; repairCommitOnly: bool
1582
1619
  return input.disposition?.stage !== 'host-regate-failed' && input.disposition?.ok !== false ? 0 : 1;
1583
1620
  }
1584
1621
 
1622
+ export function parsePodRepairExportEvidence(output: string): { exportExitCode: number | null; podExitCode: number | null; exported: boolean;
1623
+ reasonCode: 'none' | 'no-new-commit' | 'source-head-mismatch' | 'export-failed' } | null {
1624
+ const outcomes = [
1625
+ ...[...output.matchAll(/^ELANOUS_POD_REPAIR_FAILED ([^\r\n]+)$/gm)].map((match) => ({ index: match.index!, failure: match[1]! })),
1626
+ ...[...output.matchAll(/^ELANOUS_POD_REPAIR_COMMIT ([1-9]\d*) ([0-9a-f]{40}) ([0-9a-f]{40})$/gm)].map((match) => ({ index: match.index!, failure: null })),
1627
+ ].sort((a, b) => a.index - b.index);
1628
+ const outcome = outcomes.at(-1);
1629
+ if (!outcome) return null;
1630
+ const podRc = [...output.matchAll(/__ELANOUS_POD_DONE__[^\r\n]*\brc=(\d+)/g)].at(-1)?.[1];
1631
+ const reasonCode = outcome.failure === null ? 'none' : outcome.failure === 'repair made no new commit' ? 'no-new-commit'
1632
+ : outcome.failure === 'source-head-mismatch' ? 'source-head-mismatch' : 'export-failed';
1633
+ const exported = outcome.failure === null;
1634
+ return { exportExitCode: exported ? 0 : reasonCode === 'source-head-mismatch' ? null : 1,
1635
+ podExitCode: podRc === undefined ? null : Number(podRc), exported, reasonCode };
1636
+ }
1637
+
1585
1638
  export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplementJobSpawn {
1586
1639
  if (options.repairCommitOnly && (options.source?.kind !== 'pr' || options.source.number !== options.repairCommitOnly.pr || !/^[0-9a-f]{40}$/.test(options.repairCommitOnly.baseHead))) {
1587
1640
  throw new Error('repair commit-only requires a matching PR source and exact head');
@@ -1599,6 +1652,46 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1599
1652
  const resultMarkerOn = options.resultMarker ?? !options.kubectl;
1600
1653
  const writeWarmLedger = options.siWarmLedger
1601
1654
  ?? ((entry: RunLedgerEntry) => appendRunLedgerEntry(entry, runLedgerDir(env.ELANOUS_STATE_DIR)));
1655
+ const recordFinalTaskFailure = (input: Parameters<SelfImplementJobSpawn>[0], result: SelfImplementJobDone,
1656
+ ledgerStartIndex: number): SelfImplementJobDone => {
1657
+ // Match createSelfImplementAdapter: a nonzero process exit is failed even if it also emitted an ok disposition.
1658
+ if (result.error?.code === 'aborted' || (result.exitCode === 0 && result.disposition?.ok !== false)) return result;
1659
+ const ledgerRunId = env.ELANOUS_RUN_ID ?? input.spaceId;
1660
+ const ledgerDir = runLedgerDir(env.ELANOUS_STATE_DIR);
1661
+ const job = podJobName(input.spaceId);
1662
+ try {
1663
+ const entries = loadRunLedger(ledgerRunId, ledgerDir) ?? [];
1664
+ const currentEntries = entries.slice(ledgerStartIndex);
1665
+ const childStart = currentEntries.slice().reverse().find((entry) => entry.event === 'pod-child-run' && entry.data?.job === job);
1666
+ const childRunId = typeof childStart?.data?.childRunId === 'string' ? childStart.data.childRunId : null;
1667
+ const attemptValue = childStart?.data?.attempt;
1668
+ const attempt = typeof attemptValue === 'number' && Number.isSafeInteger(attemptValue) && attemptValue > 0 ? attemptValue : 1;
1669
+ const evidence = childRunId ? currentEntries.slice().reverse().find((entry) => entry.event === 'pod-child-evidence'
1670
+ && entry.data?.job === job && entry.data?.childRunId === childRunId) : undefined;
1671
+ const childResult = evidence?.data?.childResult && typeof evidence.data.childResult === 'object'
1672
+ ? evidence.data.childResult as Record<string, unknown> : undefined;
1673
+ const rawError = typeof result.disposition?.error === 'string' && result.disposition.error.trim() ? result.disposition.error
1674
+ : typeof childResult?.error === 'string' && childResult.error.trim() ? childResult.error
1675
+ : result.error?.message ?? result.output;
1676
+ const podTermination = evidence?.data?.podTermination && typeof evidence.data.podTermination === 'object'
1677
+ ? evidence.data.podTermination : null;
1678
+ appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-task-failure', data: {
1679
+ spaceId: input.spaceId,
1680
+ taskId: input.taskId ?? null,
1681
+ job,
1682
+ attempt,
1683
+ childRunId,
1684
+ childStage: typeof result.disposition?.stage === 'string' ? result.disposition.stage
1685
+ : typeof childResult?.stage === 'string' ? childResult.stage : 'unknown',
1686
+ childError: redactSecretText(rawError).replace(/\s+/gu, ' ').trim().slice(0, 500) || 'unknown',
1687
+ podTermination,
1688
+ } }, ledgerDir);
1689
+ } catch (error) {
1690
+ debug.log('self-implement.pod', 'task-failure-write-failed', { job, childRunId: null,
1691
+ reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
1692
+ }
1693
+ return result;
1694
+ };
1602
1695
  return (input) => {
1603
1696
  if (options.repairCommitOnly && (input.autoMerge || input.openPr || input.base !== `pr-${options.repairCommitOnly.pr}`)) {
1604
1697
  throw new Error('repair commit-only refuses auto merge, new PR, or a different base');
@@ -1606,7 +1699,39 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1606
1699
  if (options.siWarmAttempt && !options.siWarmHostPostprocess) {
1607
1700
  throw new Error('si-v1 warm execution requires cold-path host postprocess parity');
1608
1701
  }
1609
- if (options.siWarmAttempt) {
1702
+ const taskLedgerDir = runLedgerDir(env.ELANOUS_STATE_DIR);
1703
+ let taskLedgerStartIndex = Number.MAX_SAFE_INTEGER;
1704
+ try { taskLedgerStartIndex = (loadRunLedger(env.ELANOUS_RUN_ID ?? input.spaceId, taskLedgerDir) ?? []).length; }
1705
+ catch (error) { debug.log('self-implement.pod', 'task-failure-baseline-unavailable', {
1706
+ spaceId: input.spaceId, reason: error instanceof Error ? error.message : String(error),
1707
+ }, { level: 'warn' }); }
1708
+ const recordFailure = (result: SelfImplementJobDone) => recordFinalTaskFailure(input, result, taskLedgerStartIndex);
1709
+ const recordRejectedFailure = (error: unknown): never => {
1710
+ if (!input.signal?.aborted && !(error instanceof Error && error.name === 'AbortError')) {
1711
+ recordFailure({ exitCode: 1, output: '', error: { code: 'pod-promise-rejected', message: error instanceof Error ? error.message : String(error) } });
1712
+ }
1713
+ throw error;
1714
+ };
1715
+ let siWarmEnabled = true;
1716
+ const taskCard = env.ELANOUS_POD_TASK_CARD ?? env.ELANOUS_TASK_CARD_ID;
1717
+ if (taskCard) {
1718
+ let stage: 'config' | 'evidence' | 'decision' = 'config';
1719
+ try {
1720
+ const config = options.warmReuseConfig?.();
1721
+ stage = 'evidence';
1722
+ const evidence = options.warmReuseEvidence?.();
1723
+ stage = 'decision';
1724
+ const decision = decideWarmReuse('ta', config, evidence);
1725
+ siWarmEnabled = decision.live;
1726
+ debug.log('pod.warm', 'ta-admission-decision', { ...decision,
1727
+ execution: decision.live ? 'warm-attempt' : 'fresh-job' });
1728
+ } catch {
1729
+ siWarmEnabled = false;
1730
+ debug.log('pod.warm', 'ta-admission-unavailable', { spaceId: input.spaceId,
1731
+ reason: stage === 'decision' ? 'warm-decision-failed' : `injected-${stage}-failed`, execution: 'fresh-job' }, { level: 'warn' });
1732
+ }
1733
+ }
1734
+ if (options.siWarmAttempt && siWarmEnabled) {
1610
1735
  const done = (async (): Promise<SelfImplementJobDone> => {
1611
1736
  // POD-REUSE-REQUEST-CLEAN-FU — one fail-soft row per request decision. `runId` is the
1612
1737
  // ledger partition (warm child, then parent run, then the legacy spaceId fallback);
@@ -1901,7 +2026,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1901
2026
  return { exitCode: 1, output: log.slice(-4096), disposition: hostDisposition,
1902
2027
  error: { code: 'si-warm-host-postprocess-failed', message } };
1903
2028
  }
1904
- })();
2029
+ })().then(recordFailure, recordRejectedFailure);
1905
2030
  return { address: `self-impl:${input.spaceId}`, done };
1906
2031
  }
1907
2032
  const name = podJobName(input.spaceId);
@@ -2067,6 +2192,23 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2067
2192
  const detail = unfit.map((u) => `${u.context} ${Math.round(u.allocatableMemoryBytes / 2 ** 30 * 10) / 10}GiB`).join(' · ');
2068
2193
  return { exitCode: 1, output: '', error: { code: 'pod-pool-unfit', message: `모든 풀 멤버의 할당 가능 메모리가 이 Job 의 한도 ${memoryLimit} 보다 작다 — 영원히 배치될 수 없다(${detail}) · --pod-memory 를 낮추거나 다른 풀로` } };
2069
2194
  };
2195
+ // PRLAND-OOM-RETRY-POOL-FIT: whether the NEXT memory limit can ever be placed decides the retry before
2196
+ // anything is written or deleted. Read-only — an all-unfit pool ends the run here, so no retry intent
2197
+ // is journaled, the OOM Job stays, and no second Job is applied. A fit member leaves the single retry intact.
2198
+ const retryPoolFit = async (nextLimit: string, from: string): Promise<SelfImplementJobDone | null> => {
2199
+ const pool = options.pool as { unfitMembers?: (b: number) => Promise<Array<{ context: string; allocatableMemoryBytes: number }>>; members?: readonly PodPoolMember[] } | undefined;
2200
+ if (!pool || typeof pool.unfitMembers !== 'function' || !Array.isArray(pool.members) || !pool.members.length) return null;
2201
+ const limitBytes = memoryQuantityBytes(nextLimit);
2202
+ if (limitBytes === null) return null;
2203
+ const unfit = await pool.unfitMembers(limitBytes);
2204
+ const unfitContextsForRetry = new Set(unfit.map((u) => u.context));
2205
+ const fit = pool.members.filter((m) => !unfitContextsForRetry.has(m.context)).map((m) => m.context);
2206
+ debug.log('self-implement.pod', 'oom-retry-pool-fit', { job: name, from, to: nextLimit, fit, unfit: unfit.map((u) => u.context) }, { level: fit.length ? 'info' : 'warn' });
2207
+ if (fit.length) return null;
2208
+ const detail = unfit.map((u) => `${u.context} ${Math.round(u.allocatableMemoryBytes / 2 ** 30 * 10) / 10}GiB`).join(' · ');
2209
+ const poolLimit = `${Math.round(Math.max(...unfit.map((u) => u.allocatableMemoryBytes)) / 2 ** 30 * 10) / 10}GiB`;
2210
+ return { exitCode: 1, output: '', error: { code: 'pod-pool-unfit', message: `Job ${name} 이 OOMKilled(137) 로 ${from} 에서 죽었고 다음 한도는 ${nextLimit} 이지만 어느 풀 멤버도 그 한도를 받을 수 없다 — 재시도 Job 을 만들 수 없다(필요 ${nextLimit} · 풀 한계 ${poolLimit} · ${detail}) · --pod-memory 를 낮추거나 다른 풀로` } };
2211
+ };
2070
2212
  const acquireSlot = async (): Promise<PodPoolMember | null> => {
2071
2213
  if (!options.pool) return null;
2072
2214
  // Each actual acquisition is a separate observation, including the OOM retry in this
@@ -2087,11 +2229,15 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2087
2229
  if (input.signal?.aborted) return null;
2088
2230
  // The reason comes back inside this call, so a concurrent launch cannot overwrite it.
2089
2231
  const kind = podPlacementKind(oomRetried ? retryTier : memoryTier, selectedGoalType, requestKind);
2090
- const acquired = await options.pool.tryAcquire(unfitContexts, (reason) => {
2091
- stageReason['pool-slot'] = reason;
2092
- firstSlotReasonCode ??= slotReasonCode(reason);
2093
- },
2094
- { kind, ...(minihLocation ? { minihLocation } : {}), onPlacement: (placement) => { lastPlacement = placement; } });
2232
+ const acquired = await acquirePodPoolSlot({ entry: env[POD_DISTRIBUTOR_ENTRY_ENV], pool: options.pool,
2233
+ ...(options.podDistributorAdapter ? { adapter: options.podDistributorAdapter } : {}),
2234
+ request: { requestId: attempt.observationKey, idempotencyKey: attempt.observationKey,
2235
+ owner: { runId: childRunId, ...(env.ELANOUS_TASK_CARD_ID ? { cardId: env.ELANOUS_TASK_CARD_ID } : {}),
2236
+ ...(env.ELANOUS_POD_OWNER_KIND === 'seat' && env.ELANOUS_POD_OWNER_ID ? { seat: env.ELANOUS_POD_OWNER_ID } : {}) },
2237
+ lane: 'ta', workload: { memoryLimit, kind }, skip: unfitContexts, onEmpty: (reason) => {
2238
+ stageReason['pool-slot'] = reason;
2239
+ firstSlotReasonCode ??= slotReasonCode(reason);
2240
+ }, mode: { kind, ...(minihLocation ? { minihLocation } : {}), onPlacement: (placement) => { lastPlacement = placement; } } } });
2095
2241
  if (acquired) {
2096
2242
  recordSlotObservation(attempt, 'admitted', firstSlotReasonCode ?? 'admitted');
2097
2243
  debug.log('self-implement.pod', 'pool-slot', { spaceId: input.spaceId, context: acquired.context, inflight: options.pool.snapshot(), ...(lastPlacement ? { placement: lastPlacement } : {}) });
@@ -2125,8 +2271,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2125
2271
  if (unfitDone) return unfitDone;
2126
2272
  // HARNESS-FULL-GRAPH — Pod 입장(입장 관문 ⊕ 멤버 슬롯)은 그래프 노드 pool-admit 이다.
2127
2273
  // 2판: decompose →(substrate=pod) pool-admit 간선은 «여기»(Pod 입장 직전 · 실제 단계 경계)에서 남긴다.
2128
- if (options.repairCommitOnly) routeJourneyEdge('dispatch', 'pr-source', { source: 'pr', substrate: 'pod' });
2129
- else routeJourneyEdge('decompose', 'pod', { substrate: 'pod' });
2274
+ const journeyRunId = parentRunId ?? childRunId;
2275
+ if (options.repairCommitOnly) routeJourneyEdge('dispatch', 'pr-source', { source: 'pr', substrate: 'pod' }, { runId: journeyRunId });
2276
+ else routeJourneyEdge('decompose', 'pod', { substrate: 'pod' }, { runId: journeyRunId });
2130
2277
  enterJourneyNode('pool-admit', { provenance: 'self-implement-pod', data: { spaceId: input.spaceId } });
2131
2278
  // ⛔ 감싸는 함수(async 래퍼)를 쓰지 않는다 — 마이크로태스크가 늘면 Job apply 순서가 밀린다(시험이 잡았다). 같은 자리 try/catch 로.
2132
2279
  const podAdmitError = (error: unknown): void => {
@@ -2168,14 +2315,41 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2168
2315
  } catch (error) { debug.log('self-implement.pod', 'failure-capture-ledger-unavailable', { job: name, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
2169
2316
  };
2170
2317
  let recorded = false;
2318
+ let jobApplied = false;
2171
2319
  let groundingMinted: string | null = null;
2172
2320
  try {
2173
2321
  if (!context) return { exitCode: 1, output: '', error: { code: 'pod-context', message: 'Pod Job context를 확인할 수 없다' } };
2174
- const cleanupSecret = () => { kubectl(['-n', namespace, 'delete', 'secret', `${name}-creds`, '--ignore-not-found']); };
2322
+ const cleanupSecret = () => {
2323
+ // Once the Job exists, its credential Secret must live at least as long as the Job.
2324
+ // Early error/abort paths may run while the Pod is still reading /creds; leave cleanup
2325
+ // to the Job ownerReference/TTL until Kubernetes reports this Job terminal or absent.
2326
+ if (jobApplied) {
2327
+ const lifecycle = kubectl(['-n', namespace, 'get', 'job', name, '-o', 'jsonpath={.metadata.uid} {.status.active} {.status.succeeded} {.status.failed}']);
2328
+ const [uid, , succeeded, failed] = lifecycle.stdout.trim().split(/\s+/u);
2329
+ const terminal = Number(succeeded) > 0 || Number(failed) > 0;
2330
+ if (lifecycle.status === 0 && uid && !terminal) {
2331
+ debug.log('self-implement.pod', 'secret-cleanup-deferred-job-live', { job: name });
2332
+ return;
2333
+ }
2334
+ if (lifecycle.status !== 0 && !/notfound/iu.test(lifecycle.stderr)) {
2335
+ debug.log('self-implement.pod', 'secret-cleanup-deferred-job-unmeasured', { job: name }, { level: 'warn' });
2336
+ return;
2337
+ }
2338
+ }
2339
+ kubectl(['-n', namespace, 'delete', 'secret', `${name}-creds`, '--ignore-not-found']);
2340
+ };
2175
2341
  let repairResultAnnounced = false;
2176
2342
  let repairArtifactReady = false;
2177
2343
  let hostOriginCalls: number | null = 0;
2178
2344
  let sourceBaseSha: string | undefined;
2345
+ const recordSourceAttemptOutcome = (logs: string | null, captureStatus: 'captured' | 'logs-unavailable', observedChildRunId?: string) => {
2346
+ const optionBaseSha = options.source && 'baseSha' in options.source ? options.source.baseSha : undefined;
2347
+ const outcome = parsePodSourceAttemptOutcome(logs, { sourceKind: options.source?.kind ?? 'default', baseSha: sourceBaseSha ?? optionBaseSha });
2348
+ const data = { job: name, childRunId: observedChildRunId ?? childRunId ?? null, attempt: oomRetried ? 2 : 1, captureStatus, ...outcome };
2349
+ debug.log('pod.source', 'attempt-outcome', data, outcome.classification === 'status-not-recorded' ? { level: 'warn' } : undefined);
2350
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-source-attempt-outcome', data }, ledgerDir); }
2351
+ catch (error) { debug.log('pod.source', 'attempt-outcome-ledger-unavailable', { job: name, childRunId: childRunId ?? null, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
2352
+ };
2179
2353
  const collectFullLogs = (unavailableEvent: string, replace?: ReadonlySet<string>, onEvent?: (event: string, data: Record<string, unknown>) => void, childId?: string): { status: 'ok' | 'unavailable' | 'incomplete'; childLedgerIncomplete: boolean; samples: ReturnType<typeof parseMemSamples> } => {
2180
2354
  let full: ReturnType<Kubectl>;
2181
2355
  try {
@@ -2184,8 +2358,10 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2184
2358
  if (!full.stdout && unavailableEvent === 'failed-job-logs-unavailable') throw new Error('empty child logs');
2185
2359
  } catch (error) {
2186
2360
  debug.log('self-implement.pod', unavailableEvent, { job: name, reason: error instanceof Error ? error.message : String(error) });
2361
+ recordSourceAttemptOutcome(null, 'logs-unavailable', childId);
2187
2362
  return { status: 'unavailable', childLedgerIncomplete: false, samples: [] };
2188
2363
  }
2364
+ recordSourceAttemptOutcome(full.stdout, 'captured', childId);
2189
2365
  const via = /^ELANOUS_POD_SOURCE_VIA (image|mirror|github)\r?$/m.exec(full.stdout)?.[1];
2190
2366
  // #28246 names why the mirror was skipped on the line before `VIA github`; carry it on the same event.
2191
2367
  const mirrorSkip = /^ELANOUS_POD_SOURCE_MIRROR_SKIP (no-mount|rev-parse-failed|clone-failed)\r?$/m.exec(full.stdout)?.[1];
@@ -2212,6 +2388,11 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2212
2388
  collectPodArtifacts(full.stdout, { dir: join(effectiveInstanceRoot(), 'pod-artifacts'), job: name, log: record });
2213
2389
  }
2214
2390
  catch (error) { record('self-implement.pod', 'artifact-collect-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
2391
+ const repairExportEvidence = options.repairCommitOnly ? parsePodRepairExportEvidence(full.stdout) : null;
2392
+ if (repairExportEvidence) {
2393
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-repair-export', data: { job: name, ...repairExportEvidence } }, ledgerDir); }
2394
+ catch (error) { record('self-implement.pod', 'repair-export-ledger-incomplete', { job: name, reason: error instanceof Error ? error.message : String(error) }); }
2395
+ }
2215
2396
  for (const line of full.stdout.split(/\r?\n/)) {
2216
2397
  const bundle = /^ELANOUS_POD_SALVAGE_BUNDLE (pod-salvage\/[a-zA-Z0-9._-]+\.bundle) ([0-9]+) ([0-9]+)(?: ([0-9a-f]{40,64}))?$/.exec(line);
2217
2398
  if (bundle) {
@@ -2308,13 +2489,22 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2308
2489
  /** 넘친 glm Pod 는 자식 인자도 OpenRouter GLM 으로 — Job 스크립트·리뷰어 고정·키 전달이 openrouter 갈래를 그대로 탄다. */
2309
2490
  const jobArgs = zaiRoute === 'openrouter' ? zaiOverflowChildArgs(args, ZAI_OPENROUTER_FALLBACK_MODEL) : args;
2310
2491
  const grok = options.provider === 'grok';
2311
- const openrouter = options.provider === 'openrouter' || zaiRoute === 'openrouter';
2492
+ // The delegated child provider is also a launch source. Callers that carry
2493
+ // --child-llm-provider in args must not leave the host's Secret wiring on
2494
+ // the default provider path.
2495
+ const delegatedChildProvider = podDelegatedChildLlm(jobArgs)?.provider;
2496
+ const openrouter = options.provider === 'openrouter' || zaiRoute === 'openrouter' || delegatedChildProvider === 'openrouter';
2312
2497
  const openGateway = options.provider === 'opengateway';
2313
2498
  const anthropic = options.provider === 'anthropic';
2314
2499
  const bedrockChild = options.provider === 'bedrock';
2315
2500
  const zaiChild = zaiRoute === 'zai';
2316
2501
  /** ZAI 로 입장한 자식도 플랜 한도 오류 뒤 OpenRouter 로 전환할 수 있다. 실행 중 폴백 자격을 발사 전에 확보한다. */
2317
2502
  const openrouterCredentialRequired = openrouter || (zaiChild && zaiLaunchOverage !== 'stop');
2503
+ const hostConfig = (options.fallbackConfig ?? getUserConfig)();
2504
+ const reviewProvider = resolveRoleLlm('review', { config: hostConfig, env: { ...env, ...options.armEnv } }).provider;
2505
+ // A non-OpenRouter child can still run a review role pinned to OpenRouter. Pass that
2506
+ // credential through the same Secret path, but don't make it a launch requirement.
2507
+ const openrouterCredentialNeeded = openrouterCredentialRequired || reviewProvider === 'openrouter';
2318
2508
  /** API 키 자식 — codex 계정·자격 파일을 안 쓴다(키는 작업별 creds Secret 의 `env-<KEY>` · bedrock·glm 은 이름 있는 Secret 으로만). */
2319
2509
  const apiKeyChild = openrouter || openGateway || anthropic || bedrockChild || zaiChild;
2320
2510
  const plannedAccount = retryAccount ?? (grok ? 'grok' : openrouter ? 'openrouter' : openGateway ? 'opengateway' : anthropic ? 'anthropic' : bedrockChild ? 'bedrock' : zaiChild ? 'glm' : options.accountBroker?.() ?? options.account ?? 'team');
@@ -2358,7 +2548,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2358
2548
  }
2359
2549
  return credential;
2360
2550
  }) : undefined;
2361
- const openrouterKey = openrouterCredentialRequired ? env.OPENROUTER_API_KEY?.trim() || (options.readKeyCache ?? defaultReadKeyCache)('OPENROUTER_API_KEY')?.trim() : undefined;
2551
+ const openrouterKey = openrouterCredentialNeeded ? env.OPENROUTER_API_KEY?.trim() || (options.readKeyCache ?? defaultReadKeyCache)('OPENROUTER_API_KEY')?.trim() : undefined;
2362
2552
  if (openrouterCredentialRequired && !openrouterKey) throw new Error('pod: Pod 에 openrouter 키 없음 — 호스트 키 캐시 또는 OPENROUTER_API_KEY 필요');
2363
2553
  const openGatewayEnvKey = openGateway ? env.OPENGATEWAY_API_KEY?.trim() : undefined;
2364
2554
  const openGatewayCachedKey = openGateway ? (options.readKeyCache ?? defaultReadKeyCache)('OPENGATEWAY_API_KEY')?.trim() : undefined;
@@ -2441,7 +2631,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2441
2631
  }
2442
2632
  }
2443
2633
  // Grok 자격은 전용 Secret 키 하나로만 보낸다 — passEnv 의 API 키 중복 전달은 막는다.
2444
- 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'
2634
+ const passKeys = [...new Set([...(options.passEnv ?? []), ...(openrouterCredentialNeeded && openrouterKey ? ['OPENROUTER_API_KEY'] : []), ...(openGateway ? ['OPENGATEWAY_API_KEY'] : []), ...(anthropic ? ['ANTHROPIC_API_KEY'] : [])])].filter((key) => key !== 'ELANOUS_LIVE_DETAIL_UNTIL'
2445
2635
  && key !== POD_GITHUB_CREDENTIAL_TOKEN_ENV && key !== POD_GITHUB_CREDENTIAL_URL_ENV
2446
2636
  && (!grok || !['XAI_API_KEY', 'GROK_API_KEY', 'GROK_CODE_XAI_API_KEY'].includes(key)));
2447
2637
  const skillEnvs: Record<string, string> = options.skillEnv
@@ -2618,8 +2808,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2618
2808
  authorChoice = { ...authorChoice, model: childModel, modelSource: 'fallback-child' };
2619
2809
  } else debug.log('self-implement.pod', 'role-llm-armed', { job: name, role: 'planning', model: authorChoice.model, source: authorChoice.modelSource, account: roleCodexAccount });
2620
2810
  }
2621
- 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);
2622
- const hostConfig = (options.fallbackConfig ?? getUserConfig)();
2811
+ const hostKey = (k: string): string | undefined => k === 'OPENROUTER_API_KEY' && openrouterCredentialNeeded ? openrouterKey : k === 'OPENGATEWAY_API_KEY' && openGateway ? openGatewayKey : k === 'ANTHROPIC_API_KEY' && anthropic ? anthropicKey : env[k] ?? (options.readKeyCache ?? defaultReadKeyCache)(k);
2623
2812
  const hostFallbackNames = hostConfig.llm.fallbackChain;
2624
2813
  const zaiOverage = zaiLaunchOverage ?? zaiSettingsFromConfig(hostConfig.llm).overage;
2625
2814
  const normalizedFallback = normalizeFallbackChain(hostFallbackNames);
@@ -2876,22 +3065,6 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2876
3065
  slotId: env.ELANOUS_POD_SLOT_ID,
2877
3066
  work: !goalDoc && env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'authoring' : (oomRetried ? retryTier : memoryTier) === 'lite' ? 'lite' : 'harness',
2878
3067
  };
2879
- // TA-POD-WARMBOOT-PARITY shadow only: read injected evidence, then keep the fresh-Job path.
2880
- // This boundary must not open host configuration or credential files for a warm decision.
2881
- if (workIdentity.taskCard) {
2882
- let stage: 'config' | 'evidence' | 'decision' = 'config';
2883
- try {
2884
- const config = options.warmReuseConfig?.();
2885
- stage = 'evidence';
2886
- const evidence = options.warmReuseEvidence?.();
2887
- stage = 'decision';
2888
- const decision = decideWarmReuse('ta', config, evidence);
2889
- debug.log('pod.warm', 'ta-shadow-observation', { ...decision, execution: 'fresh-job' });
2890
- } catch {
2891
- debug.log('pod.warm', 'ta-shadow-unavailable', { spaceId: input.spaceId,
2892
- reason: stage === 'decision' ? 'warm-decision-failed' : `injected-${stage}-failed`, execution: 'fresh-job' }, { level: 'warn' });
2893
- }
2894
- }
2895
3068
  // TA-POD-WARMBOOT-PARITY (GATE-WARM-BOOT parity · #27805): a commit-pinned source on a pool host — put that commit into
2896
3069
  // the host mirror first (once per host·commit in this process) so podSourceScript finds it instead of fetching
2897
3070
  // from GitHub. Best effort: a failed seed only logs; the Job is applied either way.
@@ -2968,6 +3141,19 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2968
3141
  const a = kubectl(['apply', '-f', '-'], JSON.stringify(job));
2969
3142
  zaiPendingApply.delete(name); // apply 뒤엔 Job 라벨이 센다(성공) · 실패면 셀 것이 없다
2970
3143
  if (a.status !== 0) { cleanupSecret(); return { exitCode: 1, output: a.stderr, error: { code: 'pod-apply', message: a.stderr.trim() } }; }
3144
+ jobApplied = true;
3145
+ // Bind the credential Secret immediately after Job creation, before waiting for a Pod
3146
+ // or doing any other fallible work. Kubernetes then removes both on Job TTL cleanup.
3147
+ const jobUid = kubectl(['-n', namespace, 'get', 'job', name, '-o', 'jsonpath={.metadata.uid}']);
3148
+ const uid = jobUid.status === 0 ? jobUid.stdout.trim() : '';
3149
+ lifecycleJobUid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(uid) ? uid : undefined;
3150
+ if (lifecycleJobUid) {
3151
+ const owned = kubectl(['-n', namespace, 'patch', 'secret', `${name}-creds`, '--type=merge', '-p', JSON.stringify({ metadata: { ownerReferences: [{ apiVersion: 'batch/v1', kind: 'Job', name, uid: lifecycleJobUid }] } })]);
3152
+ if (owned.status !== 0) debug.log('self-implement.pod', 'secret-owner-failed', { job: name, stderr: owned.stderr.trim() }, { level: 'warn' });
3153
+ else debug.log('self-implement.pod', 'secret-owner-attached', { job: name, owner: 'job' });
3154
+ } else {
3155
+ debug.log('self-implement.pod', 'secret-owner-job-uid-unavailable', { job: name }, { level: 'warn' });
3156
+ }
2971
3157
  releaseAdmission?.applied?.(name, context, namespace);
2972
3158
  try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-config-snapshot', data: {
2973
3159
  job: name, hash: configSnapshot.hash, keyCount: configSnapshot.keyCount,
@@ -3030,13 +3216,6 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3030
3216
  }
3031
3217
  debug.log('self-implement.pod', 'source-delivered', { job: name, kind: 'bundle', headCommit: options.source.headCommit });
3032
3218
  }
3033
- // ☸️ P2: 비밀의 소유자 = Job — 호스트가 죽어도 Job 의 TTL 삭제와 함께 k8s 가 비밀을 거둔다(자격 사본이 클러스터에 남지 않는다).
3034
- const uid = kubectl(['-n', namespace, 'get', 'job', name, '-o', 'jsonpath={.metadata.uid}']).stdout.trim();
3035
- lifecycleJobUid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(uid) ? uid : undefined;
3036
- if (uid) {
3037
- const owned = kubectl(['-n', namespace, 'patch', 'secret', `${name}-creds`, '--type=merge', '-p', JSON.stringify({ metadata: { ownerReferences: [{ apiVersion: 'batch/v1', kind: 'Job', name, uid }] } })]);
3038
- if (owned.status !== 0) debug.log('self-implement.pod', 'secret-owner-failed', { job: name, stderr: owned.stderr.trim() }, { level: 'warn' });
3039
- }
3040
3219
  }
3041
3220
  try {
3042
3221
  appendRunLedgerEntry({ runId: ledgerRunId, timestamp: new Date((options.now ?? Date.now)()).toISOString(),
@@ -3216,11 +3395,11 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3216
3395
  if (seen !== null) {
3217
3396
  releaseAdmission?.observed?.();
3218
3397
  state = seen === 0 ? 'complete' : 'failed';
3219
- // The child's own rc is the parent's exit code even when 0 — the condition path below yields none here.
3398
+ // The shared marker is authoritative while Pod status lags; preserve the child's rc, including 0, on the parent.
3220
3399
  containerExitCode = seen;
3221
3400
  if (seen !== 0) podTermination = readPodTermination({ kubectl, namespace, job: name, path: 'result-marker', jobUid: lifecycleJobUid });
3222
3401
  if (seen !== 0) captureFailedJob(liveChildRunId);
3223
- debug.log('self-implement.pod', 'result-marker-early', { job: name, waitedMs: Date.now() - waitStartedAt, rc: seen });
3402
+ debug.log('self-implement.pod', 'result-marker-early', { job: name, runId: liveChildRunId, waitedMs: Date.now() - waitStartedAt, rc: seen });
3224
3403
  break;
3225
3404
  }
3226
3405
  }
@@ -3327,6 +3506,32 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3327
3506
  for (const row of usagePlan.rows) debug.log(row.category, row.event, row.data);
3328
3507
  const parsed = parseSelfImplementJson(logs);
3329
3508
  const terminal = parseSelfImplementJson(logs.trimEnd().split('\n').at(-1) ?? '');
3509
+ const terminalObservation = podChildTerminalResultObservation(logs);
3510
+ const providerSignature = {
3511
+ grokUnavailableCount: logs.match(/Grok unavailable:\s*run `grok login`/gu)?.length ?? 0,
3512
+ structuredProviderErrors: terminal?.providerErrors ?? parsed?.providerErrors ?? null,
3513
+ };
3514
+ const childResultObservation = {
3515
+ job: name,
3516
+ childRunId: liveChildRunId,
3517
+ jobState: state,
3518
+ containerExitCode: containerExitCode ?? null,
3519
+ ledgerCompleteness,
3520
+ terminalResultObserved: terminalObservation.observed,
3521
+ terminalStage: terminalObservation.stage,
3522
+ terminalOk: terminalObservation.ok,
3523
+ terminalOutcome: terminalObservation.outcome,
3524
+ terminalFailureClassification: terminalObservation.failureClassification,
3525
+ providerSignature,
3526
+ };
3527
+ debug.log('self-implement.pod', 'child-terminal-result-observed', childResultObservation);
3528
+ try {
3529
+ appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-terminal-result-observation', data: childResultObservation }, ledgerDir);
3530
+ } catch (error) {
3531
+ debug.log('self-implement.pod', 'child-terminal-result-observation-write-failed', {
3532
+ job: name, childRunId: liveChildRunId, reason: error instanceof Error ? error.message : String(error),
3533
+ }, { level: 'warn' });
3534
+ }
3330
3535
  const nextAccount = codexAccounts?.find((candidate) => candidate !== account);
3331
3536
  if (state === 'failed' && containerExitCode === 7 && !input.signal?.aborted) {
3332
3537
  debug.log('self-implement.pod', 'gh-login-failed', { job: name, attempt: ghLoginRetried ? 2 : 1, tokenExpiresInSec: ghTokenExpiresAt === null ? null : Math.floor((ghTokenExpiresAt - now()) / 1000) });
@@ -3487,11 +3692,24 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3487
3692
  };
3488
3693
  }
3489
3694
  let noResultDiagnostic: string | null = null;
3695
+ let noResultLedgerObservation: { available: boolean; bytes: number; rows: number; lastEvent: string | null } = {
3696
+ available: false, bytes: 0, rows: 0, lastEvent: null,
3697
+ };
3490
3698
  // POD-NORESULT: a terminal Job without a parsed disposition is incomplete even when the Job condition says Complete.
3491
3699
  const noResultCandidate = !podVanished && !disposition && !oomKilled && failedReason !== 'DeadlineExceeded' &&
3492
3700
  (state === 'complete' || (state === 'failed' && containerExitCode !== 0));
3493
3701
  if (noResultCandidate) {
3494
- try { noResultDiagnostic = podNoResultDiagnostic(readFileSync(runLedgerPath(liveChildRunId, ledgerDir), 'utf8')); }
3702
+ try {
3703
+ const ledgerText = readFileSync(runLedgerPath(liveChildRunId, ledgerDir), 'utf8');
3704
+ const ledgerRows = ledgerText.split('\n').filter(Boolean);
3705
+ let lastEvent: string | null = null;
3706
+ try {
3707
+ const parsed = JSON.parse(ledgerRows.at(-1) ?? 'null') as { event?: unknown } | null;
3708
+ lastEvent = typeof parsed?.event === 'string' ? parsed.event : null;
3709
+ } catch { /* Keep counts when the last ledger row is malformed. */ }
3710
+ noResultLedgerObservation = { available: true, bytes: Buffer.byteLength(ledgerText), rows: ledgerRows.length, lastEvent };
3711
+ noResultDiagnostic = podNoResultDiagnostic(ledgerText);
3712
+ }
3495
3713
  catch { /* ledger not returned: do not invent a stage */ }
3496
3714
  noResultDiagnostic ??= 'child terminal result missing; last ledger stage=unknown; round=unknown; mustFix=unknown';
3497
3715
  }
@@ -3503,20 +3721,41 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3503
3721
  const missingStage = noResultDiagnostic?.includes('stage=unknown') ?? false;
3504
3722
  if (shouldCaptureFailureLog || missingStage) {
3505
3723
  const logRead = readPodNoResultLogTail({ run: kubectl, namespace, job: name, maxLines: POD_NO_RESULT_LOG_TAIL_LINES });
3724
+ const logObservation = 'tail' in logRead
3725
+ ? { available: true, readState: 'tail-read', lines: logRead.tail.length, normalizedTailBytes: Buffer.byteLength(logRead.tail.join('\n')) }
3726
+ : { available: false, readState: logRead.unavailable === 'empty log output' ? 'empty' : 'read-failed', reason: logRead.unavailable, lines: 0, normalizedTailBytes: 0 };
3727
+ const childLedgerResultMissing = noResultCandidate && Boolean(noResultDiagnostic?.includes('child terminal result missing'));
3728
+ const observation = {
3729
+ classification: disposition ? 'result-parsed' : 'insufficient-evidence',
3730
+ noResultCandidate,
3731
+ launchRunIdPresent: Boolean(liveChildRunId),
3732
+ childLedger: noResultCandidate ? noResultLedgerObservation : null,
3733
+ childLedgerResultPresent: noResultCandidate ? !childLedgerResultMissing : null,
3734
+ resultParsed: Boolean(disposition),
3735
+ resultLineObserved: Boolean(terminal),
3736
+ pod: { jobReason: failedReason ?? null, containerReason: containerReason ?? null, exitCode: containerExitCode ?? null },
3737
+ childLog: logObservation,
3738
+ missing: [
3739
+ ...(noResultCandidate && !noResultLedgerObservation.available ? ['child-ledger'] : []),
3740
+ ...(childLedgerResultMissing ? ['child-ledger-result'] : []),
3741
+ ...(!disposition ? ['child-result-line', 'child-result-classification'] : []),
3742
+ ...(!logObservation.available ? ['child-log-cause-lines'] : []),
3743
+ ],
3744
+ };
3506
3745
  if ('tail' in logRead) {
3507
3746
  noResultLogEvidence = missingStage
3508
- ? { stderr: logRead.tail.join('\n'), logTail: logRead.tail, logTailLines: logRead.tail.length }
3509
- : { podLogTail: logRead.tail, podLogTailLines: logRead.tail.length };
3747
+ ? { stderr: logRead.tail.join('\n'), logTail: logRead.tail, logTailLines: logRead.tail.length, observation }
3748
+ : { podLogTail: logRead.tail, podLogTailLines: logRead.tail.length, observation };
3510
3749
  debug.log('self-implement.pod', missingStage ? 'no-result-log-tail' : 'failed-pod-log-tail', {
3511
- job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, lines: logRead.tail.length, logTail: logRead.tail,
3750
+ job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, ...observation, lines: logRead.tail.length, logTail: logRead.tail,
3512
3751
  }, { compact: { stringMax: 500 } });
3513
3752
  } else {
3514
3753
  const unavailable = `log-unavailable: ${logRead.unavailable}`;
3515
3754
  noResultLogEvidence = missingStage
3516
- ? { stderr: unavailable }
3517
- : { podLogUnavailable: logRead.unavailable };
3755
+ ? { stderr: unavailable, observation }
3756
+ : { podLogUnavailable: logRead.unavailable, observation };
3518
3757
  debug.log('self-implement.pod', missingStage ? 'no-result-log-tail' : 'failed-pod-log-tail', {
3519
- job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic,
3758
+ job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, ...observation,
3520
3759
  logUnavailable: missingStage ? unavailable : logRead.unavailable,
3521
3760
  }, { level: 'warn' });
3522
3761
  }
@@ -3631,6 +3870,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3631
3870
  }
3632
3871
  if (actual < (memoryGi(nextLimit) ?? actual)) {
3633
3872
  const from = reattachedMemoryLimit ?? memoryLimit;
3873
+ // A retry nobody can place is not a retry: decide pool fitness for the next limit first.
3874
+ const retryUnfit = await retryPoolFit(nextLimit, from);
3875
+ if (retryUnfit) return retryUnfit;
3634
3876
  appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-oom-retry-intent', data: { attempt: 2, from, to: nextLimit, tier: nextTier, reason: 'OOMKilled', job: name, executionKey, fromChildRunId: liveChildRunId } }, ledgerDir);
3635
3877
  debug.log('self-implement.pod', 'oom-retry', { from, to: nextLimit, tier: nextTier, reason: 'OOMKilled', job: name });
3636
3878
  const deleted = kubectl(['-n', namespace, 'delete', 'job', name, '--ignore-not-found', '--wait=true']);
@@ -3678,6 +3920,12 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3678
3920
  }
3679
3921
  // The host still has the complete Pod log here. The CLI only retains a short stdout tail,
3680
3922
  // so preserve the parsed child facts in the parent ledger before that tail is returned.
3923
+ // OBS-GAP-BATCH-1030 — 자식 LLM 실패의 공급자·HTTP status 를 부모 원장 행에 붙인다.
3924
+ // 줄이 공급자를 이름하지 않으면 이 Pod 의 자식 provider(Pod 옵션 ⊕ 위임 플래그)를 정규 id 로만 쓴다.
3925
+ // ⛔ 본문·자격증명은 담지 않는다 — 귀속은 두 스칼라뿐이다.
3926
+ const childProviderFailure = podChildProviderFailureFact(logs, {
3927
+ providerHint: options.provider ?? podChildProviderOf(podDelegatedChildLlm(jobArgs)?.provider),
3928
+ });
3681
3929
  const childEvidenceRow = podChildEvidenceLedgerRow({
3682
3930
  job: name,
3683
3931
  childRunId: liveChildRunId,
@@ -3686,6 +3934,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3686
3934
  noResultDiagnostic,
3687
3935
  noResultLogEvidence,
3688
3936
  podTermination,
3937
+ providerFailure: childProviderFailure,
3689
3938
  });
3690
3939
  if (childEvidenceRow) {
3691
3940
  // Every terminal attempt writes a marker, including one with no parseable child facts.
@@ -3807,7 +4056,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3807
4056
  } finally {
3808
4057
  releaseAdmission?.();
3809
4058
  }
3810
- })();
4059
+ })().then(recordFailure, recordRejectedFailure);
3811
4060
  return { address, done };
3812
4061
  };
3813
4062
  }
@@ -3975,6 +4224,43 @@ export function readPodNoResultLogTail(args: {
3975
4224
  }
3976
4225
  }
3977
4226
 
4227
+ /** Keep the terminal result row separate from provider-error text in the same child log. */
4228
+ function podChildTerminalResultObservation(logs: string): {
4229
+ observed: boolean;
4230
+ stage: string | null;
4231
+ ok: boolean | null;
4232
+ outcome: string | null;
4233
+ failureClassification: string | null;
4234
+ } {
4235
+ const lines = logs.split(/\r\n|\n|\r/u);
4236
+ for (let index = lines.length - 1; index >= 0; index--) {
4237
+ const line = lines[index]!.trim();
4238
+ if (!line.startsWith('{')) continue;
4239
+ let value: unknown;
4240
+ try { value = JSON.parse(line); } catch { continue; }
4241
+ if (!value || typeof value !== 'object' || Array.isArray(value)) continue;
4242
+ const row = value as Record<string, unknown>;
4243
+ const terminal = podTerminalRow(row);
4244
+ if (!terminal) continue;
4245
+ const nested = (row.kind === 'self' || row.kind === 'external')
4246
+ && row.result && typeof row.result === 'object' && !Array.isArray(row.result)
4247
+ ? row.result as Record<string, unknown> : row;
4248
+ const abandoned = nested.abandonedClassification && typeof nested.abandonedClassification === 'object'
4249
+ && !Array.isArray(nested.abandonedClassification) ? nested.abandonedClassification as Record<string, unknown> : null;
4250
+ return {
4251
+ observed: true,
4252
+ stage: terminal.stage,
4253
+ ok: terminal.ok,
4254
+ outcome: typeof nested.outcome === 'string' ? nested.outcome
4255
+ : typeof nested.completionDisposition === 'string' ? nested.completionDisposition
4256
+ : typeof nested.terminationReason === 'string' ? nested.terminationReason : null,
4257
+ failureClassification: typeof nested.failureClassification === 'string' ? nested.failureClassification
4258
+ : typeof abandoned?.classification === 'string' ? abandoned.classification : null,
4259
+ };
4260
+ }
4261
+ return { observed: false, stage: null, ok: null, outcome: null, failureClassification: null };
4262
+ }
4263
+
3978
4264
  /** 사람용 런 결과 한 줄 — 수확 브랜치가 있으면 «수확할 브랜치: …» 를 붙인다. */
3979
4265
  export function podRunResultLine(logs: string, branches: readonly string[]): string {
3980
4266
  const result = logs.split('\n').filter((line) => !line.startsWith('ELANOUS_MEM ')).join('\n').slice(-4000);