elanous 0.2.42 → 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 (685) 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/{X1ucLw10Cds_h614NoEnh → Om5xS9jpjSXJCeTNGYEi4}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{7a98bc80.fa935989e829f9c2.js → 0966f8a1.745fcd44f64a87ea.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{73d2eb0e.4966ad55293c801a.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/{3507.97e1977bc4d5fb0a.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/1961.a81b12872c3e93a9.js +23 -0
  17. package/apps/pwa/out/_next/static/chunks/{53c73f84.373b6160adfa89a4.js → 1970cf59.2d4d8ce5d6c81853.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/1971-8890f3962ba7ee0a.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{9211-330b6736a63d4cb3.js → 2073-ba274e00e4f9efb4.js} +1 -1
  20. package/apps/pwa/out/_next/static/chunks/{7411.9b4b8b747dc7b802.js → 2144.25b292396712196d.js} +2 -2
  21. package/apps/pwa/out/_next/static/chunks/2268-53861f339e0b65a2.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2312.0c8b61e22d3136d7.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6632.0eac1c554f8f2ef3.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/{1262.e804feb8fd1acb8c.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/{2456.b6de0e1c05f28843.js → 3095.dc44586a5f83b86d.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/{3207.a756c95e9ec8c3c8.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/3557ac4a.c8931684475018ad.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{8505.fd803c6c33b54cc3.js → 360.ae9f9f4c33c395e8.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3638.80412ea63aae8f3f.js +286 -0
  35. package/apps/pwa/out/_next/static/chunks/{b450776b.3db34d8d965f82d3.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/{8138.6c10b2a356d52fca.js → 4199.ce86b281fd0a60b7.js} +1 -1
  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/{2690.0521c738b7749931.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/{1945.7b54990d578c119b.js → 4894.fec2ca9e99caefa2.js} +1 -1
  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/{9427.96aa912ddb5801e0.js → 5564.9e72532188f57586.js} +16 -16
  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/{4043.6b91203436c9c86b.js → 5628.6ddb2d5ffba4ff4c.js} +4 -4
  63. package/apps/pwa/out/_next/static/chunks/{1319.b9b815ae0f181e06.js → 5730.43d7ccc09988e646.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/{3482.a9ae9d2ad6a5bd97.js → 5789.2da35c258292e1e5.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5824.da9527b15a3221e5.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5866.366966af47fdde5d.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/{1487.2f67b79444062da6.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/{3347.f846266b5e5f3ede.js → 6540.c7bef57ad8f90a87.js} +3 -3
  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/{8262.ddc03e06b733f184.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/{4770.769c9cd9c7034eba.js → 7483.427a2fe2049e388d.js} +2 -2
  88. package/apps/pwa/out/_next/static/chunks/{1147-5196d19c222051b3.js → 7502-be74718178e13e56.js} +1 -1
  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/{8673-bab689a55f7e13b9.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/868.6e953be05bcf6dca.js +41 -0
  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/{9656-374232558fd528d0.js → 8861-cc1fa1c7b920fa8e.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{5440-4236de26c5ea5856.js → 8967-7dfebf710c9dec9d.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/{1063.2fb8a9dc55c731f2.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/{4320.583cbab64db6be02.js → 923.2034d10ae91e9c20.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/9312.bc1b89c5d4368033.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{1574.878c18ecc97b1bd4.js → 943.39ae5e82f4f1893f.js} +1 -1
  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/aa57532f.510551854ff239b1.js +1 -0
  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-0f291d3c8fd55a3a.js → page-9ee28f7df07428ea.js} +1 -1
  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-79a8b5fee4c20871.js +1 -0
  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-ca2d09128c585ca4.js +1 -0
  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/c7945435-b44d4dbe90ba0dcb.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{3d0154af.5331fec737ffe8c3.js → cb0f8df8.09a4a6be97e3fc5f.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/{e8543907.5b040a5f22a0b0e5.js → d96660fb.cbc21a2a88539dbb.js} +7 -7
  176. package/apps/pwa/out/_next/static/chunks/{50061469.0326382241ef3b2d.js → ea514caa.05a24f78d9dffe5f.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/fb7d20d5-6892502b6ee39ca6.js +1 -0
  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/d1f8bb401740a549.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/catalog/external-commands.yaml +5 -3
  279. package/catalog/meta/catalogVersion.yaml +2 -1
  280. package/catalog/signing/catalog-signing-public.pem +3 -0
  281. package/graphs/intake/intake-daily.yaml +16 -0
  282. package/graphs/intake/news-sources.yaml +1 -0
  283. package/graphs/intake/recipes.yaml +7 -0
  284. package/graphs/overlays/examples/research-runtime-empty-terminal.yaml +28 -0
  285. package/graphs/profiles/local.yaml +5 -0
  286. package/graphs/profiles/pod.yaml +4 -0
  287. package/package.json +6 -2
  288. package/plugins/demo-absorption-briefing/plugin.json +18 -0
  289. package/plugins/demo-absorption-briefing/skills/demo-absorption-briefing/SKILL.md +8 -0
  290. package/plugins/demo-browser-hand/plugin.json +13 -0
  291. package/plugins/demo-browser-hand/skills/demo-browser-hand/SKILL.md +8 -0
  292. package/plugins/demo-linear-secretary/plugin.json +15 -0
  293. package/plugins/demo-linear-secretary/skills/demo-linear-secretary/SKILL.md +8 -0
  294. package/plugins/demo-plugin-wizard/plugin.json +11 -0
  295. package/plugins/demo-plugin-wizard/skills/demo-plugin-wizard/SKILL.md +8 -0
  296. package/plugins/demo-research/plugin.json +16 -0
  297. package/plugins/demo-research/skills/demo-research/SKILL.md +8 -0
  298. package/plugins/demo-video-briefing/plugin.json +15 -0
  299. package/plugins/demo-video-briefing/skills/demo-video-briefing/SKILL.md +8 -0
  300. package/scripts/build-signed-catalog.ts +48 -0
  301. package/scripts/ci-typecheck-main-delta.sh +88 -0
  302. package/scripts/codex-fallback-live-probe.ts +1 -1
  303. package/scripts/demo/demo1104-parallel-scenes.ts +301 -0
  304. package/scripts/demo/demo1104-stage.config.ts +21 -0
  305. package/scripts/demo/demo1104-stage.ts +316 -0
  306. package/scripts/goal-method-audit.ts +17 -1
  307. package/scripts/graph-units/land-enqueue.ts +90 -0
  308. package/scripts/hooks/codex-notify.sh +32 -0
  309. package/scripts/install.sh +10 -38
  310. package/scripts/landing-heal/land-plan.ts +57 -0
  311. package/scripts/release-loop/auto-approve-node.ts +1 -1
  312. package/scripts/release-loop/gate-autoheal-sim-evidence.ts +60 -0
  313. package/scripts/release-loop/gate-method.ts +139 -0
  314. package/scripts/release-loop/gate-node.ts +180 -20
  315. package/scripts/release-loop/gate-traffic-mode.ts +151 -3
  316. package/scripts/release-loop/node-verdict.ts +38 -25
  317. package/scripts/release-loop/preflight.ts +362 -8
  318. package/scripts/release-loop/unattended-release.ts +20 -9
  319. package/scripts/rhythm/daily.ts +36 -4
  320. package/scripts/rhythm/linear-progress-sync.ts +298 -0
  321. package/scripts/video-pipeline.ts +9 -1
  322. package/scripts/warm-pool-provider-config.ts +29 -6
  323. package/src/acp/agent-manager.ts +1 -0
  324. package/src/acp/codex-app-server-agent.ts +33 -0
  325. package/src/acp/codex-app-server-client.ts +153 -16
  326. package/src/acp/core-turn-bridge.ts +17 -12
  327. package/src/acp/event-router.ts +20 -1
  328. package/src/acp/server.ts +6 -0
  329. package/src/agent-mission/browser-roundtrip-coordinator.ts +85 -0
  330. package/src/agent-mission/claude-headless.ts +4 -1
  331. package/src/agent-mission/codex-exec.ts +105 -0
  332. package/src/agent-mission/driver.ts +192 -11
  333. package/src/agent-mission/grok-auth-status.ts +47 -0
  334. package/src/agent-mission/hand-hooks.ts +101 -0
  335. package/src/agent-mission/mission-cli.ts +56 -21
  336. package/src/agent-mission/mission-hand-reply.ts +118 -0
  337. package/src/agent-mission/mission-line.ts +180 -0
  338. package/src/agent-mission/mission-out.ts +256 -18
  339. package/src/agent-mission/tool-install.ts +122 -11
  340. package/src/agents/general-purpose.md +1 -1
  341. package/src/auto-research/research-turn.ts +95 -10
  342. package/src/autopilot/pr-manager.ts +31 -3
  343. package/src/boot/daemon-tools/self-implement.ts +3 -1
  344. package/src/boot/daemon-tools/web-search.ts +1 -2
  345. package/src/briefing/brief-items.ts +55 -11
  346. package/src/cli/agent-cli.ts +2 -1
  347. package/src/cli/catalog-cli.ts +31 -0
  348. package/src/cli/connector-cli.ts +16 -0
  349. package/src/cli/doctor-fix.ts +2 -2
  350. package/src/cli/intake-source-cli.ts +44 -8
  351. package/src/cli/msg-cli.ts +32 -3
  352. package/src/cli/pr-cli.ts +21 -1
  353. package/src/cli/pr-land-heavy-remote.ts +44 -6
  354. package/src/cli/pr-land-overlap-evidence.ts +13 -1
  355. package/src/cli/pr-land-pod-shadow-job.ts +143 -5
  356. package/src/cli/pr-land-pod-shadow.ts +9 -2
  357. package/src/cli/release-checklist-read-cli.ts +44 -16
  358. package/src/cli/release-cli.ts +23 -3
  359. package/src/cli/research-cli.ts +9 -0
  360. package/src/cli/setup-cli.ts +166 -6
  361. package/src/cli/setup-keys.ts +187 -0
  362. package/src/cli/task-plugin-wizard-host.ts +114 -0
  363. package/src/cli/tasks-cli.ts +54 -9
  364. package/src/cli/tui-test-cli.ts +186 -0
  365. package/src/config.ts +4 -2
  366. package/src/connectors/linear-daily-progress.ts +228 -0
  367. package/src/connectors/linear-projector.ts +34 -12
  368. package/src/connectors/linear.ts +151 -7
  369. package/src/core-turn/deep-turn-bloom.ts +67 -0
  370. package/src/core-turn/research-policy.ts +37 -0
  371. package/src/core-turn/run-core-turn.ts +320 -30
  372. package/src/core-turn/types.ts +2 -0
  373. package/src/dashboard/chat/acp-chat.ts +10 -0
  374. package/src/dashboard/classic-sidetab-mission-job.ts +103 -0
  375. package/src/dashboard/classic-sidetab-mission-pair.ts +81 -0
  376. package/src/dashboard/classic-sidetab-mission-trio.ts +219 -0
  377. package/src/dashboard/classic-sidetab-mission.ts +167 -5
  378. package/src/dashboard/index.ts +378 -13
  379. package/src/dashboard/input/chat-main-acp-dispatch.ts +23 -0
  380. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +8 -0
  381. package/src/dashboard/mission-cli-consumer.ts +20 -8
  382. package/src/dashboard/plugin-wizard-runtime.ts +50 -0
  383. package/src/dashboard/plugin-wizard-tool.ts +55 -0
  384. package/src/dashboard/sidetab-runtime.ts +1 -1
  385. package/src/dashboard/terminal-popup-runtime.ts +6 -3
  386. package/src/decisions/linear-progress-summary.ts +78 -0
  387. package/src/decisions/linear-progress-sync.ts +152 -0
  388. package/src/domains/outbound-alert.ts +49 -11
  389. package/src/domains/telegram-kind-route.ts +16 -9
  390. package/src/graph-runner/arg-allowance.ts +13 -0
  391. package/src/graph-runner/graph-run-api.ts +3 -1
  392. package/src/graph-runner/runner.ts +85 -17
  393. package/src/graph-wizard/mission-compose.ts +407 -12
  394. package/src/harness/dispatch-backpressure.ts +54 -1
  395. package/src/harness/dispatch-shadow-compare.ts +74 -0
  396. package/src/harness/harness-cli-command.ts +11 -1
  397. package/src/harness/skill-exec.ts +21 -9
  398. package/src/harness/skill-select.ts +1 -1
  399. package/src/hooks/error-report-cloud.ts +101 -0
  400. package/src/hooks/receiver.ts +29 -2
  401. package/src/index.ts +127 -10
  402. package/src/intake-plane/actions.ts +354 -0
  403. package/src/intake-plane/adapters/telegram-ambient.ts +34 -18
  404. package/src/intake-plane/intake-sources.ts +78 -8
  405. package/src/intake-plane/items.ts +14 -4
  406. package/src/intake-plane/linear-mission-sync.ts +80 -0
  407. package/src/intake-plane/linear-secretary-runtime.ts +178 -0
  408. package/src/intake-plane/linear-wish.ts +227 -1
  409. package/src/life/life-cli.ts +168 -0
  410. package/src/life/life-kinds.ts +160 -0
  411. package/src/live-supply/budget-consumer.ts +78 -0
  412. package/src/live-supply/read.ts +3 -0
  413. package/src/live-supply/snapshot.ts +45 -0
  414. package/src/llm/provider-credentials.ts +8 -2
  415. package/src/llm.ts +2 -1
  416. package/src/maturity/feature-maturity.ts +3 -3
  417. package/src/msg/msg-sse-server.ts +3 -3
  418. package/src/msg/msg-store.ts +177 -19
  419. package/src/native-tool-catalog.ts +36 -2
  420. package/src/nexus/api/http-server.ts +37 -1
  421. package/src/nexus/api/mcp-public-allowlist.ts +2 -0
  422. package/src/nexus/index.ts +7 -2
  423. package/src/nexus/outbound/format.ts +9 -0
  424. package/src/nexus/outbound/router.ts +98 -13
  425. package/src/nexus/setup-status.ts +9 -0
  426. package/src/nexus/state/state.ts +3 -0
  427. package/src/oauth/codex-account-store.ts +20 -7
  428. package/src/oauth/codex-owner-mirror.ts +44 -0
  429. package/src/oauth/codex.ts +17 -2
  430. package/src/oauth/fallback-chain.ts +47 -17
  431. package/src/onboarding/first-run-doctor.ts +8 -1
  432. package/src/onboarding/first-run.ts +85 -26
  433. package/src/onboarding/key-setup.ts +103 -0
  434. package/src/onboarding/menu-answer.ts +13 -0
  435. package/src/onboarding/secret-prompt.ts +37 -0
  436. package/src/plugins/install/plugin-install.ts +59 -0
  437. package/src/pr-tool/census.ts +130 -0
  438. package/src/pty-shell/pty-control-ipc.ts +4 -1
  439. package/src/registry/catalog-server.ts +232 -0
  440. package/src/registry/loader.ts +45 -1
  441. package/src/registry/types.ts +1 -2
  442. package/src/research/axis-fanout.ts +43 -28
  443. package/src/self-dev/ask-launch-flow.ts +72 -1
  444. package/src/self-dev/dev-cli.ts +4 -1
  445. package/src/self-dev/dev-pipeline.ts +5 -0
  446. package/src/self-dev/draft-residue.ts +64 -5
  447. package/src/self-dev/graph-front-nodes.ts +2 -1
  448. package/src/self-dev/graph-journey-route.ts +76 -21
  449. package/src/self-dev/launch-preflight.ts +58 -0
  450. package/src/self-dev/orchestrate.ts +1 -1
  451. package/src/self-dev/shard-aggregate.ts +4 -0
  452. package/src/self-dev/shard-run.ts +36 -15
  453. package/src/self-implement/abandoned-classification.ts +12 -3
  454. package/src/self-implement/budget-gate.ts +7 -0
  455. package/src/self-implement/child-llm-preference.ts +10 -1
  456. package/src/self-implement/doctor-visit.ts +30 -8
  457. package/src/self-implement/elanous-tui-spawn.ts +3 -0
  458. package/src/self-implement/fixtures/tdd-green-missing-passing-child-transcript.txt +2 -0
  459. package/src/self-implement/gate-artifacts.ts +2 -1
  460. package/src/self-implement/goal-author-cli.ts +4 -2
  461. package/src/self-implement/goal-author.ts +358 -4
  462. package/src/self-implement/graph-overlay-yaml.ts +30 -4
  463. package/src/self-implement/graph-overlay.ts +3 -1
  464. package/src/self-implement/graph-profile-yaml.ts +107 -0
  465. package/src/self-implement/graph-yaml.ts +26 -3
  466. package/src/self-implement/off-diff-evidence.ts +249 -5
  467. package/src/self-implement/orchestrator.ts +240 -15
  468. package/src/self-implement/run-chart.ts +6 -3
  469. package/src/self-implement/run-ledger.ts +51 -1
  470. package/src/self-implement/runtime-overlay-run-steps.ts +95 -0
  471. package/src/self-implement/tdd-evidence-tags.ts +9 -0
  472. package/src/self-implement/train-gate-receipt.ts +166 -0
  473. package/src/self-implement/train-gate-remote.ts +62 -18
  474. package/src/session/chat.ts +4 -2
  475. package/src/session/session-fanout.ts +2 -0
  476. package/src/session/streaming/acp-stream-sink.ts +2 -1
  477. package/src/session/streaming/chunk-producer.ts +6 -0
  478. package/src/session/streaming/stream-compositor.ts +3 -2
  479. package/src/session-runtime/index.ts +37 -1
  480. package/src/session-runtime/retry-policy.ts +1 -1
  481. package/src/setup/llm-env-detect.ts +3 -0
  482. package/src/setup/service-key-catalog.ts +46 -0
  483. package/src/setup/service-keys.ts +241 -0
  484. package/src/sidetab-core/visible-agent-mission.ts +98 -22
  485. package/src/skills/tools/agent.ts +23 -4
  486. package/src/skills/tools/omni-search.ts +123 -25
  487. package/src/task-agent/parent-host.ts +10 -0
  488. package/src/task-agent/repair-outcomes.ts +65 -0
  489. package/src/task-agent/task-hand.ts +20 -7
  490. package/src/task-orchestrator/dispatcher.ts +14 -1
  491. package/src/task-orchestrator/linear-capture-events.ts +55 -0
  492. package/src/task-orchestrator/store.ts +16 -5
  493. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +4 -0
  494. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +92 -1
  495. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +113 -14
  496. package/src/task-orchestrator/surfaces/pod-source-receive.ts +23 -11
  497. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +2 -0
  498. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +35 -9
  499. package/src/task-orchestrator/surfaces/self-implement-pod.ts +172 -6
  500. package/src/task-orchestrator/surfaces/self-implement.ts +27 -3
  501. package/src/task-orchestrator/surfaces/warm-reuse-evidence.ts +169 -0
  502. package/src/task-orchestrator/types.ts +14 -0
  503. package/src/telegram.ts +14 -16
  504. package/src/terminal/coding-agent.ts +14 -5
  505. package/src/terminal/session-registry.ts +1 -1
  506. package/src/tool-hints/gate.ts +1 -0
  507. package/src/tool-runtime/agent-runtime.ts +1 -0
  508. package/src/tool-runtime/browser-hand-runtime.ts +381 -0
  509. package/src/tool-runtime/browser-runtime.ts +2 -1
  510. package/src/tool-runtime/elanous-linear-issue-runtime.ts +76 -0
  511. package/src/tool-runtime/elanous-linear-secretary-runtime.ts +57 -0
  512. package/src/tool-runtime/graph-mcp-runtimes.ts +240 -0
  513. package/src/tool-runtime/index.ts +6 -0
  514. package/src/tool-runtime/types.ts +3 -0
  515. package/src/tui/entry.ts +24 -1
  516. package/src/tui/sidetab/attach.ts +140 -11
  517. package/src/tui/sidetab/herdr-portal.ts +225 -0
  518. package/src/user-config.ts +34 -9
  519. package/src/user-intent/types.ts +4 -3
  520. package/src/ux-sim/browser-hand.ts +165 -0
  521. package/src/ux-sim/draft-inventory-builder.ts +198 -0
  522. package/src/ux-sim/fake-browser-page.ts +81 -0
  523. package/src/ux-sim/fake-linear-device.ts +31 -0
  524. package/src/ux-sim/graph-engine-sim.ts +47 -0
  525. package/src/ux-sim/linear-secretary.ts +216 -0
  526. package/src/ux-sim/mock-scenario-catalog.json +75 -23
  527. package/src/ux-sim/mock-scenario-catalog.ts +120 -2
  528. package/src/ux-sim/onboarding-first-run-device.ts +31 -21
  529. package/src/ux-sim/scenario.ts +70 -26
  530. package/src/ux-sim/service-key-setup.ts +50 -0
  531. package/src/ux-sim/term-slash-device.ts +74 -0
  532. package/src/ux-sim/turn-throw-sim.ts +31 -0
  533. package/src/version/packed-revision.json +1 -1
  534. package/src/web-search/exa.ts +77 -0
  535. package/src/web-search/index.ts +30 -9
  536. package/src/web-search/provider.ts +4 -1
  537. package/src/web-search/x-intent.ts +5 -0
  538. package/apps/pwa/out/_next/static/chunks/0244e5b5.6fc7670f8223d82d.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +0 -36
  540. package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/1455-530ca16c7e71baff.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +0 -32
  543. package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +0 -286
  548. package/apps/pwa/out/_next/static/chunks/2160.a097e7b138ae1c55.js +0 -23
  549. package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +0 -34
  552. package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/2974.595d1e29d040cb6a.js +0 -64
  557. package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +0 -93
  558. package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +0 -41
  559. package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +0 -24
  561. package/apps/pwa/out/_next/static/chunks/3741.9cf76acaa2ee5298.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +0 -77
  567. package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/4276.336d76d858fcdf1b.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +0 -74
  572. package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +0 -149
  573. package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +0 -27
  575. package/apps/pwa/out/_next/static/chunks/5431-72a1dbde59400691.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/5885.0a3e52c8faccec98.js +0 -287
  583. package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/6131.348b7d6bdcd267ce.js +0 -226
  586. package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +0 -90
  587. package/apps/pwa/out/_next/static/chunks/6377.bc7df239edbff244.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +0 -104
  594. package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +0 -94
  595. package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +0 -24
  602. package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +0 -8
  610. package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/8546-6f03f8ea34dd61d9.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/9249.976f1e69a9d80754.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/9415.69e4a21c60c7d2db.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/9633.ce5bddc56784da72.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +0 -62
  626. package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/9a852a62-6192a6ea9346ced3.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0e3d7b9421b79dac.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/term/page-bf067887b3307423.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +0 -1
  684. package/apps/pwa/out/_next/static/css/be9019f696217521.css +0 -1
  685. /package/apps/pwa/out/_next/static/{X1ucLw10Cds_h614NoEnh → Om5xS9jpjSXJCeTNGYEi4}/_ssgManifest.js +0 -0
@@ -1,3 +1,5 @@
1
+ import { podChildProviderOf, type PodChildProvider } from './pod-child-providers.js';
2
+
1
3
  /** STOP-RECORD stop_class values used by the card terminal classifier. */
2
4
  export const STOP_CLASS_POD_FAILURE = 'pod-failure' as const;
3
5
  export const STOP_CLASS_NO_LAUNCH = 'no-launch' as const;
@@ -20,12 +22,19 @@ export function nestedPodResult(row: Record<string, unknown>): {
20
22
  const result = row.result as Record<string, unknown>;
21
23
  if (typeof result.stage !== 'string' || typeof result.ok !== 'boolean') return null;
22
24
  if (result.ok) return { stage: result.stage, ok: true };
25
+ // The terminal stage/node/outcome often says only `aborted` or `abandoned`.
26
+ // Keep the child's explicit stop detail (for example a same-cell PR guard
27
+ // failure) while retaining the established node/outcome/classification text.
28
+ // Forward only the typed guard failure this path owns. Other aborted children
29
+ // can carry verbose PTY summaries in `detail`; those are not parent attribution.
30
+ const explicitDetail = result.detailKind === 'blocked-draft-pr-guard' ? ledgerString(result.detail) : '';
23
31
  const classification = result.abandonedClassification;
24
32
  const detail = typeof result.supervisorVerdict === 'string' ? result.supervisorVerdict
25
33
  : classification && typeof classification === 'object' && !Array.isArray(classification)
26
34
  ? (classification as Record<string, unknown>).classification : undefined;
27
35
  const reason = [result.node, result.outcome].filter((part): part is string => typeof part === 'string' && part.length > 0).join(' ');
28
- const error = [reason || (typeof result.error === 'string' ? result.error : ''), typeof detail === 'string' && detail ? detail : ''].filter(Boolean).join(' · ');
36
+ const error = [reason || (typeof result.error === 'string' ? result.error : ''), typeof detail === 'string' && detail ? detail : '', explicitDetail]
37
+ .filter(Boolean).join(' · ');
29
38
  // PREFLIGHT-RESULT-LINE: a nested preflight rejection carries its blockers under result.blockers — the same ledger fields as the flat row.
30
39
  const blockers = result.stage === 'preflight-blocked' ? preflightBlockerText(result.blockers)
31
40
  : { error: '', preflightChecks: [] as PreflightCheck[] };
@@ -121,6 +130,15 @@ export function podTerminalRow(row: Record<string, unknown>): {
121
130
  return nestedPodResult(row);
122
131
  }
123
132
 
133
+ /**
134
+ * OBS-GAP-BATCH-1030 — 자식 LLM 실패의 «누가·어떤 HTTP status 로» 죽었나를 부모 원장에 얹는 두 스칼라.
135
+ * ⛔ 응답 본문·메시지·자격증명은 담지 않는다 — provider 는 정규 id, status 는 4xx/5xx 숫자뿐이다.
136
+ */
137
+ export interface PodProviderFailureFact {
138
+ readonly provider?: PodChildProvider;
139
+ readonly httpStatusCode?: number;
140
+ }
141
+
124
142
  export const POD_EXIT_CLASSES = ['oom-killed', 'deadline-exceeded', 'gh-login-failed', 'pod-secret', 'ask-reprompt', 'provider-error', 'child-unconverged', 'child-error', 'no-result-line', 'unknown'] as const;
125
143
 
126
144
  export type PodExitClass = typeof POD_EXIT_CLASSES[number];
@@ -143,6 +161,8 @@ export function podChildEvidenceLedgerRow(input: {
143
161
  noResultDiagnostic?: string | null;
144
162
  noResultLogEvidence?: Record<string, unknown> | null;
145
163
  podTermination?: PodTermination | null;
164
+ /** OBS-GAP-BATCH-1030 — 실패 행에만 붙는 두 스칼라(provider · HTTP status). 없으면 종전 행 그대로. */
165
+ providerFailure?: PodProviderFailureFact | null;
146
166
  }): Record<string, unknown> | null {
147
167
  const { result } = input;
148
168
  const persist = input.state === 'failed' || input.state === 'aborted' || input.noResultLogEvidence != null
@@ -163,6 +183,8 @@ export function podChildEvidenceLedgerRow(input: {
163
183
  childEvidence,
164
184
  childRunId: input.childRunId,
165
185
  job: input.job,
186
+ ...(input.providerFailure?.provider ? { provider: input.providerFailure.provider } : {}),
187
+ ...(input.providerFailure?.httpStatusCode !== undefined ? { httpStatusCode: input.providerFailure.httpStatusCode } : {}),
166
188
  ...(input.podTermination ? { podTermination: input.podTermination } : {}),
167
189
  ...(childResult && Object.keys(childResult).length > 0 ? { childResult } : {}),
168
190
  };
@@ -195,6 +217,75 @@ function isPodProviderErrorLine(line: string): boolean {
195
217
  return POD_PROVIDER_ERROR_LINE.test(line);
196
218
  }
197
219
 
220
+ /** 401·429·503 같은 «상태 숫자»만 — 응답 본문·메시지는 돌려주지 않는다. 4xx/5xx 밖의 수는 상태가 아니다. */
221
+ function podProviderHttpStatus(line: string): number | undefined {
222
+ const explicit = /"status"\s*:\s*(\d{3})/u.exec(line) ?? /\b(?:LLM API|HTTP|status(?:[ _-]?code)?)\b\s*[:=]?\s*(\d{3})\b/iu.exec(line);
223
+ // 맨숫자 형태는 «상태 자리»에 선 것만 — `500ms`·`1.5e3` 같은 수를 상태로 세지 않는다.
224
+ const digits = (explicit ?? /(?:^|[^\d])([45]\d{2})(?![\d\p{L}.])/u.exec(line))?.[1];
225
+ const value = digits === undefined ? NaN : Number(digits);
226
+ return Number.isSafeInteger(value) && value >= 400 && value <= 599 ? value : undefined;
227
+ }
228
+
229
+ /** 줄이 이름한 provider — `llm.<id>` 접두 우선, 없으면 줄 안의 정식 이름/별칭. 목록 밖 이름은 세지 않는다. */
230
+ function podLineProvider(line: string): PodChildProvider | undefined {
231
+ const scoped = /\bllm\.([a-z0-9_-]+)\b/iu.exec(line)?.[1];
232
+ const scopedProvider = podChildProviderOf(scoped);
233
+ if (scopedProvider) return scopedProvider;
234
+ for (const token of line.match(/[A-Za-z][A-Za-z0-9_-]{1,31}/gu) ?? []) {
235
+ const provider = podChildProviderOf(token);
236
+ if (provider) return provider;
237
+ }
238
+ return undefined;
239
+ }
240
+
241
+ /** provider 실패를 «말하는» 줄 — 분류기가 provider-error 로 읽는 줄, 또는 자식이 낸 `LLM API <status>` 문면. */
242
+ const isPodProviderFailureSource = (line: string): boolean => isPodProviderErrorLine(line) || /\bLLM API\s+\d{3}\b/iu.test(line);
243
+
244
+ /**
245
+ * 마지막 canonical 자식 terminal 과 «그 직전» 구간 — duplicate-cap 귀속의 한 자리(classifyPodExit 과 같은 규칙).
246
+ * terminal 이 없으면 구간은 전체 로그다(결과행 없는 자식도 provider 실패는 귀속된다).
247
+ */
248
+ function podTerminalWindow(logs: string): { terminal: ReturnType<typeof podTerminalRow>; window: string[] } {
249
+ const lines = logs.split(/\r\n|\n|\r/u);
250
+ let terminal: ReturnType<typeof podTerminalRow> = null;
251
+ let lastIndex = -1;
252
+ let previousIndex = -1;
253
+ for (const [index, raw] of lines.entries()) {
254
+ const line = raw.trim();
255
+ if (!line.startsWith('{')) continue;
256
+ let parsed: unknown;
257
+ try { parsed = JSON.parse(line); } catch { continue; }
258
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) continue;
259
+ const row = podTerminalRow(parsed as Record<string, unknown>);
260
+ if (!row) continue;
261
+ previousIndex = lastIndex;
262
+ terminal = row;
263
+ lastIndex = index;
264
+ }
265
+ const window = lines.slice(previousIndex + 1, lastIndex === -1 ? undefined : lastIndex)
266
+ .map((line) => line.trim()).filter(Boolean);
267
+ return { terminal, window };
268
+ }
269
+
270
+ /**
271
+ * OBS-GAP-BATCH-1030 — 자식 실패를 «공급자 + HTTP status» 로 귀속한다(응답 본문·자격증명 제외).
272
+ * 마지막 canonical terminal 이 성공이면 null — 과거(재시도 전) provider 실패를 성공한 결과에 재사용하지 않는다.
273
+ * 줄이 공급자를 이름하지 않으면 호출자가 준 hint(Pod 의 자식 provider)를 정규 id 로만 쓴다.
274
+ */
275
+ export function podChildProviderFailureFact(logs: string, opts?: { providerHint?: string }): PodProviderFailureFact | null {
276
+ const { terminal, window } = podTerminalWindow(logs);
277
+ if (terminal?.ok === true) return null;
278
+ const terminalErrors = typeof terminal?.error === 'string'
279
+ ? terminal.error.split(/\r\n|\n|\r/u).map((line) => line.trim()).filter(Boolean) : [];
280
+ const sources = [...window, ...terminalErrors].filter((line) => isPodProviderFailureSource(line)).reverse();
281
+ if (!sources.length) return null;
282
+ // 마지막 줄이 `LLM API <status>` 만 말할 수 있다 — 공급자는 «이름한» 줄에서 따로 찾는다.
283
+ const provider = sources.map(podLineProvider).find((named) => named !== undefined) ?? podChildProviderOf(opts?.providerHint);
284
+ const httpStatusCode = sources.map(podProviderHttpStatus).find((status) => status !== undefined);
285
+ if (!provider && httpStatusCode === undefined) return null;
286
+ return { ...(provider ? { provider } : {}), ...(httpStatusCode !== undefined ? { httpStatusCode } : {}) };
287
+ }
288
+
198
289
  /**
199
290
  * POD-FAIL-EVIDENCE-CAPTURE-FU — duplicate-cap 귀속: 마지막 «canonical» 자식 terminal 하나에만 실패를 붙인다.
200
291
  * canonical 접두(`self`/`external`)가 아닌 lookalike kind 행은 건너뛰고, 마지막 canonical terminal 이 성공이거나
@@ -1,6 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
3
3
  import { join } from 'node:path';
4
+ import { podTerminalRow } from './pod-failure-reason.js';
4
5
 
5
6
  /** Capture a failed Job against its recorded placement, never the caller's current kubectl context. */
6
7
  export function captureFailedPodJobs(input: {
@@ -39,10 +40,14 @@ export function captureFailedPodJobs(input: {
39
40
  finish('failed', 'placement-conflict'); return;
40
41
  }
41
42
  const location = { host: first.host, context: first.context, namespace: first.namespace, childRunId: first.childRunId, jobUid: first.jobUid };
43
+ const childRows = rows.filter(row => row.event === 'pod-child-run' && row.data?.job === job
44
+ && row.data.childRunId === first.childRunId && Number.isSafeInteger(row.data.attempt)
45
+ && (row.data.attempt as number) > 0);
46
+ const attempt = childRows.length ? childRows[childRows.length - 1]!.data!.attempt as number : undefined;
42
47
  const evidenceDir = join(artifactDir, 'pod-failure-capture', runId, job, first.childRunId as string);
43
48
  // A failed kubectl/SSH read is itself the missing diagnostic. Keep its stderr in
44
49
  // the private artifact directory and put only the path and exit status in the ledger.
45
- const readFailure = (reason: string, result: { status: number | null; stderr: string }, extra: Record<string, unknown> = {}): void => {
50
+ const captureStderr = (reason: string, result: { status: number | null; stderr: string }): Record<string, unknown> => {
46
51
  let stderrEvidence: string | null = null;
47
52
  let stderrCaptureStatus: 'saved' | 'redacted' | 'empty' | 'write-failed' = result.stderr ? 'saved' : 'empty';
48
53
  if (result.stderr) {
@@ -61,19 +66,40 @@ export function captureFailedPodJobs(input: {
61
66
  }
62
67
  } catch { stderrEvidence = null; stderrCaptureStatus = 'write-failed'; }
63
68
  }
64
- finish('failed', reason, { ...location, ...extra, kubectlStatus: result.status, stderrEvidence, stderrCaptureStatus });
69
+ return { kubectlStatus: result.status, stderrEvidence, stderrCaptureStatus };
70
+ };
71
+ const readFailure = (reason: string, result: { status: number | null; stderr: string }, extra: Record<string, unknown> = {}): void => {
72
+ finish('failed', reason, { ...location, ...extra, ...captureStderr(reason, result) });
65
73
  };
66
74
  const previous = rows.find(row => row.event === 'pod-failure-capture' && row.data?.job === job && row.data?.outcome === 'collected'
67
75
  && row.data.childRunId === first.childRunId && row.data.jobUid === first.jobUid
68
76
  && row.data.host === first.host && row.data.context === first.context && row.data.namespace === first.namespace);
77
+ const priorLogEvidence = previous?.data?.logEvidence;
78
+ const priorPreviousLogEvidence = previous?.data?.previousLogEvidence;
79
+ const priorCurrentReadStatus = previous?.data?.currentLogReadStatus;
80
+ const priorPreviousReadStatus = previous?.data?.previousLogReadStatus;
69
81
  // A ledger row describes a prior collection; it does not guarantee that its files survived.
70
- // Check all three expected paths before treating it as complete, then recapture any missing evidence.
71
- if (previous && ([['jobEvidence', 'job.json'], ['podEvidence', 'pods.json'], ['logEvidence', 'child.log']] as const)
82
+ // Validate the required artifacts and every log artifact claimed by the prior row before deduping.
83
+ // Unknown restart count is terminal for this Job snapshot: another identical Pod read cannot recover it.
84
+ const previousReadComplete = priorCurrentReadStatus === 'captured'
85
+ ? ['captured', 'empty', 'not-needed', 'unknown'].includes(String(priorPreviousReadStatus))
86
+ : priorCurrentReadStatus === 'empty' && priorPreviousReadStatus === 'captured';
87
+ const currentLogEvidencePresent = priorCurrentReadStatus === 'captured'
88
+ && priorLogEvidence === join(evidenceDir, 'child.log')
89
+ && (() => { try { return statSync(priorLogEvidence).isFile(); } catch { return false; } })();
90
+ const previousLogEvidencePresent = priorPreviousReadStatus === 'captured'
91
+ && priorPreviousLogEvidence === join(evidenceDir, 'child.previous.log')
92
+ && (() => { try { return statSync(priorPreviousLogEvidence).isFile(); } catch { return false; } })();
93
+ const logEvidenceComplete = currentLogEvidencePresent
94
+ ? priorPreviousReadStatus !== 'captured' || previousLogEvidencePresent
95
+ : priorCurrentReadStatus === 'empty' && previousLogEvidencePresent;
96
+ if (previous && previousReadComplete && ([['jobEvidence', 'job.json'], ['podEvidence', 'pods.json']] as const)
72
97
  .every(([field, filename]) => {
73
98
  const path = join(evidenceDir, filename);
74
99
  if (previous.data?.[field] !== path) return false;
75
100
  try { return statSync(path).isFile(); } catch { return false; }
76
- })) return;
101
+ })
102
+ && logEvidenceComplete) return;
77
103
  const args = ['--context', first.context as string, '-n', first.namespace as string] as const;
78
104
  try {
79
105
  const jobResult = kubectl(first.host as string, [...args, 'get', 'job', job, '-o', 'json']);
@@ -103,23 +129,88 @@ export function captureFailedPodJobs(input: {
103
129
  });
104
130
  const podResult = kubectl(first.host as string, [...args, 'get', 'pods', '-l', `job-name=${job}`, '-o', 'json']);
105
131
  if (podResult.status !== 0) { readFailure('pods-read-failed', podResult, { jobEvidence }); return; }
106
- const pods = JSON.parse(podResult.stdout) as { items?: Array<{ metadata?: { name?: string; ownerReferences?: Array<{ uid?: string }> } }> };
132
+ const pods = JSON.parse(podResult.stdout) as { items?: Array<{
133
+ metadata?: { name?: string; uid?: string; ownerReferences?: Array<{ uid?: string }> };
134
+ status?: { phase?: string; containerStatuses?: Array<{ name?: string; restartCount?: number;
135
+ state?: { terminated?: { reason?: string; exitCode?: number; finishedAt?: string } } }> };
136
+ }> };
107
137
  if (!pods.items?.length || pods.items.some(p => !p.metadata?.ownerReferences?.some(owner => owner.uid === jobBody.metadata?.uid))) {
108
138
  finish('failed', 'pod-owner-mismatch', { ...location, jobEvidence }); return;
109
139
  }
110
140
  const podEvidence = save('pods.json', podResult.stdout);
111
- const podName = pods.items[0]?.metadata?.name;
141
+ const pod = pods.items[0]!;
142
+ const podName = pod.metadata?.name;
112
143
  if (pods.items.length !== 1 || !podName || !/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/.test(podName)) {
113
144
  finish('failed', 'pod-ambiguous', { ...location, jobEvidence, podEvidence }); return;
114
145
  }
146
+ const childStatus = pod.status?.containerStatuses?.find(status => status.name === 'child');
147
+ const terminated = childStatus?.state?.terminated;
148
+ const shortCode = (value: unknown): string | undefined => typeof value === 'string' && /^[A-Za-z0-9_.:-]{1,64}$/.test(value) && !SECRET_VALUE.test(value) ? value : undefined;
149
+ const numeric = (value: unknown): number | undefined => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined;
150
+ const exitCode = (value: unknown): number | undefined => typeof value === 'number' && Number.isSafeInteger(value) ? value : undefined;
151
+ const restartCount = numeric(childStatus?.restartCount);
152
+ const podSummary: Record<string, unknown> = {
153
+ ...location,
154
+ ...(attempt !== undefined ? { attempt } : {}), podName,
155
+ ...(shortCode(pod.metadata?.uid) ? { podUid: shortCode(pod.metadata?.uid) } : {}),
156
+ ...(shortCode(pod.status?.phase) ? { podPhase: shortCode(pod.status?.phase) } : {}),
157
+ ...(shortCode(terminated?.reason) ? { containerReason: shortCode(terminated?.reason) } : {}),
158
+ ...(exitCode(terminated?.exitCode) !== undefined ? { containerExitCode: exitCode(terminated?.exitCode) } : {}),
159
+ ...(typeof terminated?.finishedAt === 'string' && /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?Z$/.test(terminated.finishedAt) ? { containerFinishedAt: terminated.finishedAt } : {}),
160
+ ...(restartCount !== undefined ? { containerRestartCount: restartCount } : {}),
161
+ };
115
162
  const logs = kubectl(first.host as string, [...args, 'logs', `pod/${podName}`, '-c', 'child']);
116
- if (logs.status !== 0) { readFailure('logs-read-failed', logs, { jobEvidence, podEvidence }); return; }
117
- if (!logs.stdout.trim()) { finish('failed', 'logs-empty', { ...location, jobEvidence, podEvidence }); return; }
118
- const logEvidence = save('child.log', logs.stdout);
119
- finish('collected', 'job-failed', { ...location, jobEvidence, podEvidence, logEvidence });
163
+ const currentLogReadStatus = logs.status === 0 ? (logs.stdout.trim() ? 'captured' : 'empty') : 'failed';
164
+ const currentLogBytes = logs.status === 0 ? Buffer.byteLength(logs.stdout) : 0;
165
+ let logEvidence: string | undefined;
166
+ let previousLogEvidence: string | undefined;
167
+ let previousLogReadStatus = restartCount === undefined || restartCount > 0 ? 'unknown' : 'not-needed';
168
+ let previousLogBytes: number | undefined;
169
+ let previousLogFailure: Record<string, unknown> = {};
170
+ let resultMarkerPresent = false;
171
+ if (logs.status === 0 && logs.stdout.trim()) {
172
+ logEvidence = save('child.log', logs.stdout);
173
+ resultMarkerPresent = hasTerminalMarker(logs.stdout);
174
+ }
175
+ if (restartCount !== undefined && restartCount > 0) {
176
+ const previousLogs = kubectl(first.host as string, [...args, 'logs', `pod/${podName}`, '-c', 'child', '--previous']);
177
+ previousLogReadStatus = previousLogs.status === 0 ? (previousLogs.stdout.trim() ? 'captured' : 'empty') : 'failed';
178
+ previousLogBytes = previousLogs.status === 0 ? Buffer.byteLength(previousLogs.stdout) : 0;
179
+ if (previousLogs.status !== 0) {
180
+ const failure = captureStderr('previous-logs-read-failed', previousLogs);
181
+ previousLogFailure = {
182
+ previousLogKubectlStatus: failure.kubectlStatus,
183
+ previousLogStderrEvidence: failure.stderrEvidence,
184
+ previousLogStderrCaptureStatus: failure.stderrCaptureStatus,
185
+ };
186
+ }
187
+ if (previousLogs.status === 0 && previousLogs.stdout.trim()) {
188
+ previousLogEvidence = save('child.previous.log', previousLogs.stdout);
189
+ resultMarkerPresent ||= hasTerminalMarker(previousLogs.stdout);
190
+ }
191
+ }
192
+ const summary = { ...podSummary, jobEvidence, podEvidence, currentLogReadStatus, currentLogBytes,
193
+ previousLogReadStatus, ...(previousLogBytes !== undefined ? { previousLogBytes } : {}), ...previousLogFailure, resultMarkerPresent,
194
+ ...(logEvidence ? { logEvidence } : {}), ...(previousLogEvidence ? { previousLogEvidence } : {}) };
195
+ if (currentLogReadStatus !== 'captured' && previousLogReadStatus !== 'captured') {
196
+ if (logs.status !== 0) { readFailure('logs-read-failed', logs, summary); return; }
197
+ finish('failed', 'logs-empty', summary); return;
198
+ }
199
+ if (logs.status !== 0) finish('collected', 'job-failed', { ...summary, ...captureStderr('logs-read-failed', logs) });
200
+ else finish('collected', 'job-failed', summary);
120
201
  } catch { finish('failed', 'capture-error', location); }
121
202
  }
122
203
 
204
+ function hasTerminalMarker(logs: string): boolean {
205
+ for (const line of logs.split(/\r?\n/)) {
206
+ try {
207
+ const row: unknown = JSON.parse(line);
208
+ if (row && typeof row === 'object' && !Array.isArray(row) && podTerminalRow(row as Record<string, unknown>)) return true;
209
+ } catch { /* ordinary child output is not a terminal result marker */ }
210
+ }
211
+ return false;
212
+ }
213
+
123
214
  const SECRET_FIELD = /token|secret|password|authorization|key/i;
124
215
  const SAFE_FIELD = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
125
216
  const SECRET_VALUE = /(?:\b(?:bearer|basic)\s+\S+|\b(?:token|secret|password|authorization|api[-_]?key|access[-_]?key|private[-_]?key)\b\s*(?:is|[=:])\s*["']?\S+|\b(?:sk-[A-Za-z0-9_-]{8,}|gh[pousr]_[A-Za-z0-9_]{8,}))\b/i;
@@ -127,8 +218,12 @@ const MAX_FIELDS = 32;
127
218
  // Review R2: only lifecycle events the host needs to see, and no free text. Event names must start with a known
128
219
  // lifecycle prefix; string fields survive only when they are short code-like values in a fixed set of keys.
129
220
  const EVENT_ALLOWED = /^(?:gate|gated|review|reviewed|repair|repaired|rework|merge|merged|pr|land|landed|stage|round|supervisor|child|plan|planned|decompose|decomposed|shard|stall|harvest|decision|run|pipeline|progress|human|start|started|finish|finished|done|implement|implemented|commit|test|typecheck)(?:-(?:started|finished|round|opened|closed|failed|passed|blocked|done|entry|node|outcome|delivery|decision|stop|merged|ready|requested|resolved|result|fix|must-fix|verdict|skipped|origin|cleared))*$/;
130
- const CODE_FIELDS = new Set(['stage', 'outcome', 'verdict', 'status', 'kind', 'phase', 'role', 'result']);
221
+ const CODE_FIELDS = new Set(['stage', 'outcome', 'verdict', 'status', 'kind', 'phase', 'role', 'result', 'containerReason',
222
+ 'podPhase', 'currentLogReadStatus', 'previousLogReadStatus', 'previousLogStderrCaptureStatus', 'stderrCaptureStatus']);
131
223
  const CODE_VALUE = /^[a-z0-9_.:-]{1,40}$/i;
224
+ const IDENTITY_FIELDS = new Set(['job', 'jobUid', 'childRunId', 'host', 'context', 'namespace', 'podName', 'podUid']);
225
+ const SAFE_ID_VALUE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
226
+ const SAFE_ISO_TIMESTAMP = /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?Z$/;
132
227
 
133
228
  function secretValues(root: Record<string, unknown>): string[] {
134
229
  const secrets: string[] = [];
@@ -163,7 +258,8 @@ export function ledgerLineToLogEvent(line: string, runId: string): {
163
258
  const sources = [entry, details].filter((source): source is Record<string, unknown> => source !== undefined);
164
259
  const knownSecrets = secretValues(entry);
165
260
  const containsCredential = (value: string) => SECRET_VALUE.test(value) || knownSecrets.some((secret) => value.includes(secret));
166
- if (containsCredential(entry.event) || (!EVENT_ALLOWED.test(entry.event) && entry.event !== 'ask-auto-target-candidates' && entry.event !== 'ask-auto-reauthor')) return undefined;
261
+ if (containsCredential(entry.event) || (!EVENT_ALLOWED.test(entry.event) && entry.event !== 'pod-failure-capture'
262
+ && entry.event !== 'ask-auto-target-candidates' && entry.event !== 'ask-auto-reauthor')) return undefined;
167
263
 
168
264
  const data: Record<string, unknown> = { runId };
169
265
  let fields = 0;
@@ -176,7 +272,10 @@ export function ledgerLineToLogEvent(line: string, runId: string): {
176
272
  if (!SAFE_FIELD.test(outputName) || SECRET_FIELD.test(outputName) || Object.hasOwn(data, outputName)) continue;
177
273
  if (typeof value === 'string') {
178
274
  // Free text (reasons, messages, patches) never leaves the pod ledger; only short code values in known keys.
179
- if (!CODE_FIELDS.has(name) || !CODE_VALUE.test(value) || containsCredential(value)) continue;
275
+ const acceptedCode = CODE_FIELDS.has(name) && CODE_VALUE.test(value);
276
+ const acceptedIdentity = IDENTITY_FIELDS.has(name) && SAFE_ID_VALUE.test(value);
277
+ const acceptedTimestamp = name === 'containerFinishedAt' && SAFE_ISO_TIMESTAMP.test(value);
278
+ if ((!acceptedCode && !acceptedIdentity && !acceptedTimestamp) || containsCredential(value)) continue;
180
279
  data[name] = value;
181
280
  } else if (typeof value === 'number' && Number.isFinite(value) || typeof value === 'boolean' || value === null) {
182
281
  data[name] = value;
@@ -107,6 +107,10 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
107
107
  // Count calls performed by this Pod source stage. Branch validation via
108
108
  // assertRemoteBase runs on the host before Job creation and is outside it.
109
109
  'pod_source_io_origin_calls=0',
110
+ ...(source.kind === 'default' && baseSha ? [
111
+ 'pod_source_base_sha_origin_fallback=false',
112
+ 'pod_source_base_sha_mirror_fetch_attempted=false',
113
+ ] : []),
110
114
  'pod_source_io_started=$(date +%s)',
111
115
  'pod_source_io_reported=0',
112
116
  'pod_source_io_measured=0',
@@ -117,7 +121,9 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
117
121
  ' [ -n "${pod_source_io_seconds:-}" ] || pod_source_io_seconds=$(( $(date +%s) - pod_source_io_started ))',
118
122
  ' [ -n "${pod_source_io_files:-}" ] || pod_source_io_files=null',
119
123
  ' pod_source_io_status=incomplete; if [ "$pod_source_io_measured" -eq 1 ]; then pod_source_io_status=complete; fi',
120
- ' printf \'ELANOUS_POD_SOURCE_IO {"originCalls":%s,"checkoutFiles":%s,"sourceVia":"%s","sourceSeconds":%s,"sourceStatus":"%s","pushCalls":null,"installRan":null,"installSeconds":null}\\n\' "$pod_source_io_origin_calls" "$pod_source_io_files" "${source_via:-unknown}" "$pod_source_io_seconds" "$pod_source_io_status"',
124
+ ...(source.kind === 'default' && baseSha
125
+ ? [' printf \'ELANOUS_POD_SOURCE_IO {"originCalls":%s,"baseShaOriginFallback":%s,"checkoutFiles":%s,"sourceVia":"%s","sourceSeconds":%s,"sourceStatus":"%s","pushCalls":null,"installRan":null,"installSeconds":null}\\n\' "$pod_source_io_origin_calls" "$pod_source_base_sha_origin_fallback" "$pod_source_io_files" "${source_via:-unknown}" "$pod_source_io_seconds" "$pod_source_io_status"']
126
+ : [' printf \'ELANOUS_POD_SOURCE_IO {"originCalls":%s,"checkoutFiles":%s,"sourceVia":"%s","sourceSeconds":%s,"sourceStatus":"%s","pushCalls":null,"installRan":null,"installSeconds":null}\\n\' "$pod_source_io_origin_calls" "$pod_source_io_files" "${source_via:-unknown}" "$pod_source_io_seconds" "$pod_source_io_status"']),
121
127
  ' pod_source_result_emit "$pod_source_exit"',
122
128
  '}',
123
129
  'trap pod_source_io_emit EXIT',
@@ -174,7 +180,7 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
174
180
  `if ! [ -d ${quotedMirror} ]; then mirror_skip=no-mount`,
175
181
  `elif ! git -C ${quotedMirror} rev-parse --verify HEAD >/dev/null 2>&1; then mirror_skip=rev-parse-failed`,
176
182
  ...(source.kind === 'default' && baseSha
177
- ? [`elif ! git init -q -b main repo || ! git -C repo fetch --quiet --no-write-fetch-head ${quotedMirror} '${baseSha}' || ! git -C repo cat-file -e '${baseSha}^{commit}' 2>/dev/null; then mirror_skip=sha-fetch-failed`]
183
+ ? [`elif pod_source_base_sha_mirror_fetch_attempted=true; ! git init -q -b main repo || ! git -C repo fetch --quiet --no-write-fetch-head ${quotedMirror} '${baseSha}' || ! git -C repo cat-file -e '${baseSha}^{commit}' 2>/dev/null; then mirror_skip=sha-fetch-failed`]
178
184
  : [`elif ! git clone -q --shared -- ${quotedMirror} repo || ! git -C repo rev-parse --verify HEAD >/dev/null 2>&1; then mirror_skip=clone-failed`]),
179
185
  'fi',
180
186
  'if [ -z "$mirror_skip" ]; then',
@@ -187,10 +193,9 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
187
193
  " printf 'ELANOUS_POD_SOURCE_MIRROR_SKIP %s\\n' \"$mirror_skip\"",
188
194
  ' if [ -e repo ]; then rm -r -- repo || exit 5; fi',
189
195
  ...(source.kind === 'default' && baseSha ? [] : [' pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))']),
190
- ...(source.kind === 'default' && baseSha ? [
191
- ` pod_source_stage=base-sha; pod_source_failure_code=base-sha-unavailable; printf 'ELANOUS_POD_SOURCE_BASE_SHA_UNAVAILABLE %s\\n' '${baseSha}'`,
192
- ' exit 5',
193
- ] : [` ${clone} || exit 5`]),
196
+ ...(source.kind === 'default' && baseSha
197
+ ? [` git init -q -b main repo && git -C repo remote add origin ${quotedUrl} || exit 5`]
198
+ : [` ${clone} || exit 5`]),
194
199
  ' source_via=github',
195
200
  'fi',
196
201
  'fi',
@@ -209,12 +214,19 @@ export function podSourceScript(source: PodSource, repoUrl: string, mirrorPath =
209
214
  return [
210
215
  ...ioStart,
211
216
  ...start,
212
- // «실제 객체 출처» 마커: image 라우트는 핀 객체, mirror 라우트는 --shared alternates 가
213
- // 해결된 SHA 를 이미 갖고 있으면 그 쪽이 출처다. 어느 쪽에도 없으면 호스트 미러에서
214
- // raw-SHA fetch 로 Pod 전용 object store 에 직접 가져온다(프로덕션 미러 = push 로 심은
215
- // bare 저장소, upload-pack 기본 설정 · refs/브랜치 경유 없음).
217
+ // «실제 객체 출처» 마커: image pin을 우선 쓰고, SHA가 없으면 host mirror 다음 origin에서
218
+ // raw-SHA fetch 해 Pod 전용 object store 에 넣는다. origin 시도 수·성공 여부는 IO summary로
219
+ // debug.log 에 남겨 다음 실패에서 소스 부재와 네트워크 fallback을 구분한다.
216
220
  'pod_source_base_sha_from="$source_via"',
217
- `if ! git cat-file -e '${sha}^{commit}' 2>/dev/null; then pod_source_stage=base-sha; pod_source_failure_code=base-sha-unavailable; printf 'ELANOUS_POD_SOURCE_BASE_SHA_UNAVAILABLE %s\\n' '${sha}'; exit 5; fi`,
221
+ `if ! git cat-file -e '${sha}^{commit}' 2>/dev/null; then`,
222
+ ` if [ "$pod_source_base_sha_mirror_fetch_attempted" = false ] && [ -d ${quotedMirror} ]; then pod_source_base_sha_mirror_fetch_attempted=true; if git fetch --quiet --no-write-fetch-head ${quotedMirror} '${sha}'; then pod_source_base_sha_from=mirror; else printf 'ELANOUS_POD_SOURCE_BASE_SHA_MIRROR_FETCH failed %s\\n' '${sha}'; fi; fi`,
223
+ ` if ! git cat-file -e '${sha}^{commit}' 2>/dev/null; then`,
224
+ ' pod_source_io_origin_calls=$((pod_source_io_origin_calls + 1))',
225
+ ' pod_source_base_sha_origin_fallback=true',
226
+ ` printf 'ELANOUS_POD_SOURCE_BASE_SHA_ORIGIN_FETCH start %s\\n' '${sha}'`,
227
+ ` if git fetch --quiet --no-write-fetch-head origin '${sha}'; then pod_source_base_sha_from=origin; source_via=origin; printf 'ELANOUS_POD_SOURCE_BASE_SHA_ORIGIN_FETCH complete %s\\n' '${sha}'; else pod_source_stage=base-sha; pod_source_failure_code=base-sha-unavailable; printf 'ELANOUS_POD_SOURCE_BASE_SHA_ORIGIN_FETCH failed %s\\n' '${sha}'; printf 'ELANOUS_POD_SOURCE_BASE_SHA_UNAVAILABLE %s\\n' '${sha}'; exit 5; fi`,
228
+ ' fi',
229
+ 'fi',
218
230
  `printf 'ELANOUS_POD_SOURCE_BASE_SHA_FROM %s\\n' "$pod_source_base_sha_from"`,
219
231
  `git checkout -q -B ${quotedBase} '${sha}' || exit 5`,
220
232
  `git update-ref ${quotedTrackingRef} '${sha}' || exit 5`,
@@ -85,6 +85,8 @@ export function warmReuseFlagOn(config: unknown, consumer: WarmReuseConsumer): b
85
85
 
86
86
  function evidenceReason(evidence: WarmReuseEvidence | undefined, minSamples: number): string | null {
87
87
  if (!evidence) return 'evidence-unmeasured';
88
+ // A measured mismatch is the most actionable reason even when it also makes the latest canary fail.
89
+ if (typeof evidence.recentMismatchCount === 'number' && evidence.recentMismatchCount > 0) return 'recent-mismatch';
88
90
  if (evidence.leaseValid !== true) return evidence.leaseValid === false ? 'lease-invalid' : 'lease-unmeasured';
89
91
  if (evidence.canaryPassed !== true) return evidence.canaryPassed === false ? 'canary-failed' : 'canary-unmeasured';
90
92
  for (const field of IDENTITY_FIELDS) {
@@ -62,7 +62,9 @@ export interface WarmPodProviderOptions {
62
62
  transport?: (spec: WarmPodSpec) => Pick<WarmPodTransport, 'request'>;
63
63
  maxShadowMs?: number;
64
64
  now?: () => number;
65
- kubectl?: (args: readonly string[], input?: string) => { status: number | null; stdout: string; stderr: string };
65
+ kubectl?: (args: readonly string[], input?: string) => {
66
+ status: number | null; stdout: string; stderr: string; error?: NodeJS.ErrnoException;
67
+ };
66
68
  /** Private directory for cross-process prepare leases; defaults to a per-user directory under tmpdir(). */
67
69
  prepareLockDirectory?: string;
68
70
  /** Cancels a prepare waiting for another process to finish the same host/worker slot. */
@@ -431,7 +433,8 @@ export class WarmPodProvider {
431
433
  const result = spawnSync('kubectl', argv, { encoding: 'utf8', input, env,
432
434
  timeout: argv[4] === 'wait' ? (POD_READY_WAIT_SECONDS + 30) * 1000 : 360_000,
433
435
  maxBuffer: 2 * 1024 * 1024 });
434
- return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
436
+ return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '',
437
+ error: result.error };
435
438
  };
436
439
  const parse = (result: { status: number | null; stdout: string }) => {
437
440
  if (result.status !== 0) return null;
@@ -483,11 +486,25 @@ export class WarmPodProvider {
483
486
  && Object.entries(metadata.annotations).every(([key, value]) => pod.metadata.annotations?.[key] === value)
484
487
  && pod.spec?.nodeName === nodeName
485
488
  && sameSpec(normalizedSpec(pod.spec), template);
489
+ const skipDiscovery = (reason: string): false => {
490
+ debug.log('pod.warm', 'warm-pod-list-skipped', { reason }, { level: 'warn' });
491
+ return false;
492
+ };
493
+ const kubectlErrorCode = (error: unknown): string | undefined => {
494
+ if (!error || typeof error !== 'object' || !('code' in error)) return undefined;
495
+ return typeof error.code === 'string' ? error.code : undefined;
496
+ };
486
497
  // Resolve the pinned Pod independently; namespace size must not affect this read.
487
- const namedResult = kubectl(['get', 'pods', `--field-selector=metadata.name=${spec.name}`, '-o', 'json']);
498
+ let namedResult: ReturnType<typeof kubectl>;
499
+ try { namedResult = kubectl(['get', 'pods', `--field-selector=metadata.name=${spec.name}`, '-o', 'json']); }
500
+ catch (error) {
501
+ return skipDiscovery(kubectlErrorCode(error) === 'ENOBUFS' ? 'output-too-large' : 'kubectl-failed');
502
+ }
503
+ if (kubectlErrorCode(namedResult.error) === 'ENOBUFS') return skipDiscovery('output-too-large');
504
+ if (namedResult.status !== 0) return skipDiscovery('kubectl-failed');
488
505
  const namedList = parse(namedResult);
489
506
  if (!Array.isArray(namedList?.items) || !namedList.metadata || typeof namedList.metadata !== 'object'
490
- || Array.isArray(namedList.metadata)) return false;
507
+ || Array.isArray(namedList.metadata)) return skipDiscovery('malformed-output');
491
508
  const namedMatches = namedList.items.filter((row: any) => row?.metadata?.name === spec.name);
492
509
  if (namedMatches.length > 1) return false;
493
510
  const namedPod = namedMatches[0] ?? null;
@@ -497,20 +514,29 @@ export class WarmPodProvider {
497
514
  const warmPods: any[] = [];
498
515
  let continuation = '';
499
516
  const seenContinuations = new Set<string>();
517
+ let completedPages = false;
500
518
  for (let page = 0; page < 100; page++) {
501
- const args = ['get', 'pods', '-l', 'elanous.kind=warm-worker', '--limit=10', '-o', 'json'];
519
+ const args = ['get', 'pods', '-l', 'elanous.kind=warm-worker', '--chunk-size=50', '-o', 'json'];
502
520
  if (continuation) args.splice(5, 0, '--continue', continuation);
503
- const result = kubectl(args);
521
+ let result: ReturnType<typeof kubectl>;
522
+ try { result = kubectl(args); }
523
+ catch (error) {
524
+ return skipDiscovery(kubectlErrorCode(error) === 'ENOBUFS' ? 'output-too-large' : 'kubectl-failed');
525
+ }
526
+ if (kubectlErrorCode(result.error) === 'ENOBUFS') return skipDiscovery('output-too-large');
527
+ if (result.status !== 0) return skipDiscovery('kubectl-failed');
504
528
  const listed = parse(result);
505
529
  if (!listed || !Array.isArray(listed.items) || !listed.metadata || typeof listed.metadata !== 'object'
506
530
  || Array.isArray(listed.metadata)
507
- || (listed.metadata.continue !== undefined && typeof listed.metadata.continue !== 'string')) return false;
531
+ || (listed.metadata.continue !== undefined && typeof listed.metadata.continue !== 'string'))
532
+ return skipDiscovery('malformed-output');
508
533
  warmPods.push(...listed.items);
509
534
  continuation = listed.metadata?.continue ?? '';
510
- if (!continuation) break;
511
- if (seenContinuations.has(continuation) || page === 99) return false;
535
+ if (!continuation) { completedPages = true; break; }
536
+ if (seenContinuations.has(continuation) || page === 99) return skipDiscovery('malformed-output');
512
537
  seenContinuations.add(continuation);
513
538
  }
539
+ if (!completedPages) return skipDiscovery('malformed-output');
514
540
  const hostPods = warmPods.filter((row: any) => row?.metadata?.name === spec.name
515
541
  || row?.metadata?.annotations?.['elanous.dev/warm-worker-id'] === spec.workerId);
516
542
  if (namedPod && !hostPods.some((row: any) => row?.metadata?.name === spec.name)) hostPods.push(namedPod);