elanous 0.2.35 → 0.2.36

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 (686) 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/chunks/{d06f9160.a3d9062f95de8ad7.js → 053a429e.9a63436527cc751c.js} +1 -1
  4. package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +287 -0
  5. package/apps/pwa/out/_next/static/chunks/{4346.8601952e73bf5803.js → 1201.afbfc5b1c5e5cbe4.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +64 -0
  11. package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +36 -0
  12. package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +149 -0
  15. package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{3103.0df8da390948bb84.js → 2500.cbc1257b774aae52.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/{7644.17e37ba6f1d4226e.js → 2683.c9773a0c589b031b.js} +3 -3
  20. package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +24 -0
  21. package/apps/pwa/out/_next/static/chunks/{4718-17d2af636796a330.js → 275-02ea4c2a33980422.js} +3 -3
  22. package/apps/pwa/out/_next/static/chunks/2812ca6a.3b9f4a7a08885744.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{8714.ff0b7ce3ec3e3ae2.js → 2941.3c3546f96bc6efa7.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +24 -0
  26. package/apps/pwa/out/_next/static/chunks/{9214.63a510d39178e997.js → 2986.45d7652e4f13557e.js} +2 -2
  27. package/apps/pwa/out/_next/static/chunks/3031-85328a92fcce4da6.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/3136.30aaaa5fa03662a3.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{3677-4215f826f6aa68e5.js → 3148-98efd4869d660a87.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +226 -0
  31. package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3324.a09703033abcbd2f.js +34 -0
  34. package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +8 -0
  36. package/apps/pwa/out/_next/static/chunks/3410.7f9af5ab77cbe65f.js +115 -0
  37. package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +32 -0
  38. package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +286 -0
  40. package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/{9512.5a76207a730e0491.js → 3727.7949ccaacaa71242.js} +2 -2
  42. package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/{8557-e7898769499cd56f.js → 3757-180308bc61021b05.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +74 -0
  45. package/apps/pwa/out/_next/static/chunks/{359-2250789a2d3499e7.js → 3840-5825d56d46976a92.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{da5176c6.6773b6c5994e1d99.js → 3a3d9966.cc4d4585a2708e7c.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4116.a84a92a2492c080e.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +104 -0
  51. package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/{9952.5daf5f94063a2b3e.js → 4286.b70c4520306817e8.js} +1 -1
  53. package/apps/pwa/out/_next/static/chunks/4304.e9b2512834a9e23e.js +23 -0
  54. package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{938.66ad1ef0e5abae1c.js → 4615.8525eb0add35eba6.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +148 -0
  57. package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +93 -0
  59. package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/{6236.e18cced2d5ba6afb.js → 528.38ce20ef8aa251ff.js} +16 -16
  61. package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +122 -0
  62. package/apps/pwa/out/_next/static/chunks/{3408.21d1570602f4b6c0.js → 552.b7d061ad91eeac51.js} +2 -2
  63. package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5711.957b095705c12560.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/{1530.0e612369b6fd7ea0.js → 575.d929793a53f27c4b.js} +1 -1
  66. package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/599.c39c571b6733f2a2.js +41 -0
  70. package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +79 -0
  71. package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/6566.926a1d1b7c911442.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +27 -0
  84. package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/6925.562d532110879886.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/{7385.50a308a477bdfc21.js → 6943.c6b24124853a47b2.js} +1 -1
  87. package/apps/pwa/out/_next/static/chunks/{630.fe5a46428d63b013.js → 727.7deb87749b0a343a.js} +1 -1
  88. package/apps/pwa/out/_next/static/chunks/{2018.a741297bce759490.js → 7481.39f7a4654907bf6e.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/{8444.4c26b379ca2b9596.js → 771.c3cdb6c1f7f47c02.js} +17 -17
  92. package/apps/pwa/out/_next/static/chunks/7784.1f0ac4a16d190cf4.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{3589.5444a06bcf6e775c.js → 7891.03f910124a737985.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8037.e254fd797aa224d1.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +62 -0
  100. package/apps/pwa/out/_next/static/chunks/{b2f6ba4d.fb56fdbbf798df33.js → 873d6c12.09bd499f57171543.js} +1 -1
  101. package/apps/pwa/out/_next/static/chunks/{5101.e32282718f99ed6f.js → 8904.7d51af2dc033965c.js} +2 -2
  102. package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +90 -0
  104. package/apps/pwa/out/_next/static/chunks/{5637.281e5dec4ea6ecf1.js → 914.8abefd48d579547b.js} +2 -2
  105. package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/{4705-194e64e47ca0fbdb.js → 9250-072df22eaadaa6b5.js} +1 -1
  107. package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +77 -0
  111. package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{8637.47f5b35afcae5e6b.js → 9514.131c52cc75fe6439.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{1674.2a65fd5668e1cc5f.js → 9789.60f723d18097ec30.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9f31e478.fefcbcd3c388ebc5.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-e7abc34a48a6f71e.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-c15958835534404b.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{0368f25d-ad84af92fefee68f.js → ccae1c4b-0cf414f5eff1b10d.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/{cbe38a15.5a032598e39970c6.js → ceba0382.650712b56b85b582.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/{b6705a4f-b9a9047de9eecfd0.js → da5ecc5c-b005ad8cac737d57.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{56d372f2.681ab4ec4c998fae.js → f9a61e4d.1fc2c1dbdd49fe46.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +1 -0
  183. package/apps/pwa/out/_next/static/{T1mBQqmkwKDLGtyisDCOd → uC-N0emedeNOFuaBQFv-I}/_buildManifest.js +1 -1
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +22 -22
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +22 -22
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +22 -22
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +21 -21
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +21 -21
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +22 -22
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +21 -21
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +22 -22
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +22 -22
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +21 -21
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +22 -22
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +22 -22
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +22 -22
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +22 -22
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +21 -21
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +21 -21
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +22 -22
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +22 -22
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +22 -22
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +21 -21
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +21 -21
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +22 -22
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +22 -22
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +21 -21
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +21 -21
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +21 -21
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +22 -22
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +22 -22
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +21 -21
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +22 -22
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +22 -22
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +22 -22
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +22 -22
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +22 -22
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +21 -21
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +22 -22
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +22 -22
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +22 -22
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +22 -22
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +22 -22
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +22 -22
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +22 -22
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +22 -22
  277. package/docs/goal-context/05-authoring-lessons.jsonl +47 -0
  278. package/docs/goal-context/README.md +3 -0
  279. package/graphs/default-loop.yaml +6 -1
  280. package/graphs/implement-loop.yaml +24 -0
  281. package/graphs/release/recipes.yaml +6 -0
  282. package/graphs/release/release-loop.yaml +17 -4
  283. package/graphs/wizard/recipes.yaml +44 -0
  284. package/graphs/wizard/wizard-loop.yaml +44 -0
  285. package/graphs/work/research-report.yaml +2 -0
  286. package/package.json +1 -1
  287. package/scripts/ci-typecheck-changed.ts +139 -5
  288. package/scripts/coord-role-pack.ts +1 -1
  289. package/scripts/first10-gate.ts +416 -0
  290. package/scripts/fleet/wsl-node-setup.sh +432 -0
  291. package/scripts/release-loop/docs-node.ts +204 -8
  292. package/scripts/release-loop/gate-node.ts +249 -53
  293. package/scripts/release-loop/node-verdict.ts +2 -0
  294. package/scripts/release-loop/resume-cap.ts +14 -34
  295. package/scripts/release-loop/resume-release.ts +37 -11
  296. package/scripts/release-loop/traffic-node.ts +59 -0
  297. package/scripts/release-loop/traffic-transition.ts +159 -0
  298. package/scripts/rhythm/daily.ts +137 -3
  299. package/scripts/ux-sim.ts +53 -0
  300. package/skills/README.md +1 -0
  301. package/src/acp/core-turn-bridge.ts +48 -6
  302. package/src/agent/delegate-hint.ts +16 -0
  303. package/src/agent/runner.ts +82 -2
  304. package/src/agent/task-notification.ts +56 -10
  305. package/src/agent/types.ts +4 -0
  306. package/src/agent-substrate/pr-reviewer.ts +55 -3
  307. package/src/agent-substrate/review-intent.ts +29 -2
  308. package/src/agent-substrate/review-observation.ts +3 -0
  309. package/src/agent-substrate/self-review-cli.ts +168 -16
  310. package/src/autopilot/mission-codebase-gate.ts +141 -12
  311. package/src/autopilot/pr-manager.ts +25 -5
  312. package/src/boot/daemon-tools/self-implement.ts +1 -0
  313. package/src/budget/usage-outcomes.ts +8 -4
  314. package/src/capture/tui-self-report.ts +102 -0
  315. package/src/chat/goal-continue-verdict.ts +41 -0
  316. package/src/chat/index.ts +30 -4
  317. package/src/chat/internal-turn-origin.ts +1 -0
  318. package/src/chat/paste-fold.ts +86 -0
  319. package/src/chat/tool-render/block.ts +32 -0
  320. package/src/chat/tool-render/dispatch.ts +2 -20
  321. package/src/chat/tool-render/result-text.ts +98 -0
  322. package/src/chat/turn-typeahead.ts +70 -7
  323. package/src/cli/config-audit.ts +119 -0
  324. package/src/cli/doctor-cli.ts +22 -0
  325. package/src/cli/guardian-cli.ts +10 -0
  326. package/src/cli/herdr-cli.ts +34 -0
  327. package/src/cli/light-entry-route.ts +6 -3
  328. package/src/cli/log-event-names.ts +2 -0
  329. package/src/cli/make-cli.ts +247 -11
  330. package/src/cli/msg-cli.ts +117 -3
  331. package/src/cli/pr-cli.ts +29 -16
  332. package/src/cli/pr-land-base-read.ts +11 -2
  333. package/src/cli/pr-land-heavy-remote.ts +6 -3
  334. package/src/cli/pr-land-overlap-evidence.ts +23 -4
  335. package/src/cli/pr-land-recovery.ts +117 -1
  336. package/src/cli/pty-takeover-cli.ts +8 -7
  337. package/src/cli/release-cli.ts +21 -5
  338. package/src/cli/release-single-flight.ts +1 -1
  339. package/src/cli/tasks-card-show.ts +162 -0
  340. package/src/cli/tasks-cli.ts +574 -356
  341. package/src/cli/tasks-read-cli.ts +197 -0
  342. package/src/core-turn/run-core-turn.ts +4 -2
  343. package/src/core-turn/run-goal-loop.ts +73 -16
  344. package/src/core-turn/types.ts +6 -1
  345. package/src/dashboard/context/keys.ts +8 -31
  346. package/src/dashboard/index.ts +202 -49
  347. package/src/dashboard/input/agent-wake.ts +7 -1
  348. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +146 -3
  349. package/src/dashboard/input/chat-main-slash-command.ts +4 -2
  350. package/src/dashboard/input/goal-continue.ts +210 -0
  351. package/src/dashboard/input/goal-interim.ts +2 -0
  352. package/src/dashboard/input/internal-turn.ts +2 -8
  353. package/src/dashboard/input/seat-autowake.ts +9 -7
  354. package/src/dashboard/input/turn-autoheal.ts +52 -0
  355. package/src/dashboard/seat-boot-preamble.ts +132 -5
  356. package/src/dashboard/slash-runtime/chat-persona.ts +65 -8
  357. package/src/dashboard/slash-runtime/dashboard-handlers.ts +3 -2
  358. package/src/dashboard/slash-runtime/model-choices.ts +15 -0
  359. package/src/dashboard/stale-install-check.ts +3 -99
  360. package/src/debug/batch-queue.ts +119 -0
  361. package/src/debug/tui-log-tag.ts +67 -0
  362. package/src/display/agent-surface.ts +7 -0
  363. package/src/domains/standalone-log-sink.ts +15 -2
  364. package/src/esc-abort-gate.ts +69 -0
  365. package/src/git-fs/worktree.ts +95 -1
  366. package/src/graph-runner/graph-cli.ts +18 -0
  367. package/src/graph-runner/runner.ts +20 -11
  368. package/src/graph-wizard/generate.ts +108 -4
  369. package/src/graph-wizard/steps.ts +15 -0
  370. package/src/grounding/proactive-ground.ts +86 -0
  371. package/src/harness/control-inbox.ts +49 -1
  372. package/src/harness/harness-cli-command.ts +51 -7
  373. package/src/harness/harness-incidents.ts +52 -1
  374. package/src/harness/pod-control-send.ts +33 -5
  375. package/src/harness/self-send-remote.ts +69 -0
  376. package/src/harness/self-send-routing-guard.ts +6 -0
  377. package/src/harness/self-send-target.ts +4 -3
  378. package/src/index.ts +327 -12
  379. package/src/input-core/context-key-runtime.ts +21 -0
  380. package/src/light-cli.ts +6 -1
  381. package/src/llm-wellformed.ts +70 -0
  382. package/src/llm.ts +35 -4
  383. package/src/loops/msg-wake.ts +35 -39
  384. package/src/loops/orchestrator/inbox.ts +59 -11
  385. package/src/loops/orchestrator/knowhow-pack.ts +364 -0
  386. package/src/loops/orchestrator/tick.ts +5 -1
  387. package/src/maturity/feature-maturity.ts +1 -1
  388. package/src/models/prompts.ts +17 -2
  389. package/src/msg/msg-post-office.ts +116 -0
  390. package/src/mss/logging/log-store.ts +79 -22
  391. package/src/nexus/api/decisions-route.ts +38 -18
  392. package/src/nexus/api/graph-wizard-api.ts +20 -2
  393. package/src/nexus/boot/register-mcp-clients.ts +263 -38
  394. package/src/nexus/onboarding/first-boot-wizard.ts +56 -8
  395. package/src/onboarding/first-run.ts +37 -6
  396. package/src/onboarding/web-first.ts +43 -11
  397. package/src/ops/overview-collect.ts +12 -6
  398. package/src/ops/overview.ts +3 -3
  399. package/src/persona/loader.ts +11 -0
  400. package/src/persona/types.ts +8 -0
  401. package/src/prompt-library/session-guidance.ts +14 -0
  402. package/src/provider-summary.ts +8 -0
  403. package/src/pty-shell/herdr-agent-report.ts +118 -9
  404. package/src/pty-shell/herdr-prompt.ts +266 -0
  405. package/src/pty-shell/pty-control-ipc.ts +151 -8
  406. package/src/pty-shell/pty-special-keys.ts +42 -2
  407. package/src/pty-shell/stale-install-check.ts +99 -0
  408. package/src/pty-shell/tui-run-state.ts +14 -2
  409. package/src/release-loop/auto-start.ts +20 -2
  410. package/src/release-loop/checklist.ts +76 -4
  411. package/src/release-loop/rehearsal.ts +36 -20
  412. package/src/repl/index.ts +19 -1
  413. package/src/seat-loop/knowhow-lint.ts +1 -1
  414. package/src/self-dev/decompose-proposal.ts +172 -20
  415. package/src/self-dev/decompose.ts +61 -0
  416. package/src/self-dev/dev-cli.ts +37 -3
  417. package/src/self-dev/dev-pipeline.ts +8 -2
  418. package/src/self-dev/draft-triage-rules.ts +31 -0
  419. package/src/self-dev/glm-credential-guard.ts +77 -0
  420. package/src/self-dev/graph-journey-nodes.ts +1 -0
  421. package/src/self-dev/graph-journey-route.ts +12 -2
  422. package/src/self-dev/orchestrate-cli.ts +68 -3
  423. package/src/self-dev/orchestrate.ts +116 -17
  424. package/src/self-dev/run-supervisor.ts +55 -2
  425. package/src/self-dev/run-types.ts +1 -1
  426. package/src/self-health/autoheal.ts +153 -0
  427. package/src/self-health/signatures.ts +6 -0
  428. package/src/self-implement/device-first.ts +116 -0
  429. package/src/self-implement/doctor-visit.ts +239 -1
  430. package/src/self-implement/evidence-command-budget.ts +80 -0
  431. package/src/self-implement/goal-author-cli.ts +1 -0
  432. package/src/self-implement/goal-author-decompose.ts +265 -4
  433. package/src/self-implement/goal-author.ts +33 -8
  434. package/src/self-implement/goal-elaborate.ts +176 -22
  435. package/src/self-implement/goal-refine.ts +3 -0
  436. package/src/self-implement/graph-variant.ts +40 -6
  437. package/src/self-implement/headless-elanous-driver.ts +19 -3
  438. package/src/self-implement/off-diff-evidence.ts +58 -6
  439. package/src/self-implement/orchestrator.ts +222 -21
  440. package/src/self-implement/pod-warm-pool-profile.ts +1 -0
  441. package/src/self-implement/pwa-import-graph.ts +1 -1
  442. package/src/self-implement/rework-policy.ts +30 -0
  443. package/src/self-implement/run-ledger.ts +108 -0
  444. package/src/self-implement/run-ttl.ts +38 -24
  445. package/src/self-implement/scope-adjacency.ts +3 -1
  446. package/src/self-implement/seams.ts +60 -4
  447. package/src/self-implement/wiring-check.ts +358 -0
  448. package/src/shell-env-bootstrap.ts +11 -4
  449. package/src/skills/runner.ts +4 -2
  450. package/src/skills/tools/agent.ts +290 -48
  451. package/src/skills/tools/schedule-wakeup.ts +23 -4
  452. package/src/skills/tools/shell.ts +61 -6
  453. package/src/skills/tools/terminal-modal-inject.ts +1 -2
  454. package/src/skills/tools/terminal-modal.ts +10 -8
  455. package/src/skills/url-router.ts +41 -1
  456. package/src/smart-wizard/run.ts +66 -0
  457. package/src/status/bar.ts +34 -6
  458. package/src/status/status-provider-info.ts +37 -6
  459. package/src/steward/rejudge-tick.ts +10 -2
  460. package/src/steward/ta-repair-event-collect.ts +17 -6
  461. package/src/task-agent/actions.ts +3 -1
  462. package/src/task-agent/land-queue.ts +21 -8
  463. package/src/task-agent/live-moves.ts +22 -6
  464. package/src/task-agent/mission.ts +30 -0
  465. package/src/task-agent/rejudge-on-head.ts +15 -0
  466. package/src/task-agent/repair-cycle.ts +138 -32
  467. package/src/task-agent/repair-next-move.ts +31 -3
  468. package/src/task-agent/repair-outcomes.ts +29 -0
  469. package/src/task-agent/repair-worker.ts +14 -4
  470. package/src/task-agent/shadow.ts +41 -3
  471. package/src/task-agent/task-card-prefix.ts +2 -0
  472. package/src/task-agent/task-hand.ts +477 -22
  473. package/src/task-agent/task-parent-role-llm.ts +36 -0
  474. package/src/task-agent/tier-split.ts +78 -9
  475. package/src/task-orchestrator/surfaces/pod-account-broker.ts +9 -0
  476. package/src/task-orchestrator/surfaces/pod-child-reuse.ts +146 -0
  477. package/src/task-orchestrator/surfaces/pod-command-job.ts +86 -5
  478. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +215 -3
  479. package/src/task-orchestrator/surfaces/pod-launch-history.ts +133 -0
  480. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +11 -0
  481. package/src/task-orchestrator/surfaces/pod-pool.ts +76 -4
  482. package/src/task-orchestrator/surfaces/pod-provenance.ts +8 -2
  483. package/src/task-orchestrator/surfaces/pod-repair-commit.ts +18 -3
  484. package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +16 -0
  485. package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +224 -0
  486. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +201 -0
  487. package/src/task-orchestrator/surfaces/pod-si-warm-provider.ts +444 -0
  488. package/src/task-orchestrator/surfaces/pod-si-warm-runner.ts +387 -0
  489. package/src/task-orchestrator/surfaces/pod-si-warm-transport.ts +157 -0
  490. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +4 -0
  491. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +485 -36
  492. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +3 -0
  493. package/src/task-orchestrator/surfaces/self-implement-pod.ts +396 -19
  494. package/src/task-orchestrator/surfaces/self-implement.ts +42 -2
  495. package/src/tool-runtime/index.ts +15 -2
  496. package/src/tool-runtime/mcp-proxy-bootstrap.ts +29 -0
  497. package/src/tty-foreground.ts +155 -0
  498. package/src/tui/chat/goal-interim.ts +173 -0
  499. package/src/tui/chat/log-view.ts +205 -18
  500. package/src/tui/chat/self-health-status.ts +232 -0
  501. package/src/tui/entry.ts +370 -81
  502. package/src/tui/input/composer.ts +8 -1
  503. package/src/tui/slash/compact-command.ts +7 -0
  504. package/src/tui/slash/compact.ts +1 -7
  505. package/src/tui/slash/resume.ts +75 -0
  506. package/src/tui-client/local-chat-turn.ts +45 -2
  507. package/src/tui-client/next-dashboard-runtime.ts +8 -0
  508. package/src/tui-client/next-loop-command.ts +70 -0
  509. package/src/tui-client/next-wakeup.ts +191 -0
  510. package/src/tui.ts +37 -0
  511. package/src/ui/modal-adapter.ts +2 -2
  512. package/src/ux-sim/classic-tui-seat-scenarios.ts +516 -0
  513. package/src/ux-sim/cli-config-audit-device.ts +121 -0
  514. package/src/ux-sim/dashboard-event-loop-stall-monitor-device.ts +238 -0
  515. package/src/ux-sim/event-monkey.ts +3 -2
  516. package/src/ux-sim/fake-bin.ts +45 -0
  517. package/src/ux-sim/fake-herdr.ts +238 -0
  518. package/src/ux-sim/fake-llm.ts +111 -6
  519. package/src/ux-sim/fault-glm-no-credential.ts +116 -0
  520. package/src/ux-sim/fault-nextmove-dispatch.ts +102 -1
  521. package/src/ux-sim/fault-scope-escape-lift.ts +33 -6
  522. package/src/ux-sim/fault-tui-400-autoheal.ts +297 -0
  523. package/src/ux-sim/goal-device.ts +619 -0
  524. package/src/ux-sim/in-process-cli.ts +22 -5
  525. package/src/ux-sim/mock-authoring-first-run-child.ts +35 -0
  526. package/src/ux-sim/mock-authoring-first-run.ts +97 -0
  527. package/src/ux-sim/mock-seat-pty-frame-child.ts +29 -0
  528. package/src/ux-sim/mock-seat-pty-frame.ts +297 -0
  529. package/src/ux-sim/mock-seat-pty-sequence-child.ts +21 -0
  530. package/src/ux-sim/mock-seat-pty-sequence.ts +206 -0
  531. package/src/ux-sim/next-tui-seat-scenarios.ts +631 -0
  532. package/src/ux-sim/onboarding-first-run-device.ts +269 -0
  533. package/src/ux-sim/pty-key-modifiers-device.ts +85 -0
  534. package/src/ux-sim/subagent-tools-device.ts +81 -0
  535. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +250 -0
  536. package/src/ux-sim/tty-foreground-steal-child.ts +21 -0
  537. package/src/version/packed-revision.json +1 -1
  538. package/apps/pwa/out/_next/static/chunks/1165.bad13fc9151a7288.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/13.02a07436dec15f89.js +0 -32
  540. package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +0 -41
  541. package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +0 -24
  542. package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +0 -74
  543. package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/1993-c0007b7ad0c0ef41.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/1c735de4.f993a30bbd3c57c4.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +0 -148
  553. package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/2625.5d870aa999f33db1.js +0 -34
  555. package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +0 -77
  556. package/apps/pwa/out/_next/static/chunks/2833-0fe47af99ed13c29.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +0 -62
  559. package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +0 -90
  560. package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +0 -36
  563. package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +0 -79
  565. package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/3f7c4ee5.3dde54f01a816613.js +0 -122
  567. package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/4441-875b97f5821ed58a.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +0 -286
  570. package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +0 -24
  573. package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/5154.a118f3957ed14e36.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +0 -23
  582. package/apps/pwa/out/_next/static/chunks/5483-dd5d7697f6bdb106.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/5852.db1f7449f4f74612.js +0 -287
  586. package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +0 -8
  593. package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +0 -27
  595. package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +0 -93
  597. package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/6866-79aa5b4e47cac6aa.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/6b89c8bd.24df687a820500b3.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +0 -149
  604. package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +0 -104
  605. package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/8219.baa715d1deee80e2.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/8256.e3ac8421a71f82f4.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/8437-8d5492094b166cfa.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +0 -226
  615. package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +0 -64
  617. package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +0 -115
  622. package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/967-2aa39b2d04b4c690.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/app/control/page-406b47745b53f269.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/live-run/page-26e6c18a1a750cf6.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/morning/page-47c5d4db587266bd.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1f5a60f70cb4dd0c.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/outputs/page-bac7dee94e5eae4a.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/term/page-dc0a532f5b9196ec.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.js +0 -1
  686. /package/apps/pwa/out/_next/static/{T1mBQqmkwKDLGtyisDCOd → uC-N0emedeNOFuaBQFv-I}/_ssgManifest.js +0 -0
@@ -96,7 +96,7 @@ export function podTerminalRow(row: Record<string, unknown>): {
96
96
  return nestedPodResult(row);
97
97
  }
98
98
 
99
- export const POD_EXIT_CLASSES = ['oom-killed', 'deadline-exceeded', 'gh-login-failed', 'pod-secret', 'ask-reprompt', 'child-unconverged', 'child-error', 'no-result-line', 'unknown'] as const;
99
+ 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;
100
100
 
101
101
  export type PodExitClass = typeof POD_EXIT_CLASSES[number];
102
102
 
@@ -108,6 +108,51 @@ const isPodErrorLine = (line: string): boolean =>
108
108
 
109
109
  const normalizePodLogLine = (line: string): string => line.replace(/\/home\/[^/\s]+\//gu, '~/').slice(0, 240);
110
110
 
111
+ /**
112
+ * PROVIDER-ERROR-PRIORITY: 모델 호출 쪽이 죽은 줄(자격증명·쿼터·과부하·업스트림 5xx).
113
+ * 자식이 스스로 수렴 못 한 것과 사유가 다르므로 generic 실패(child-error/unknown)보다 먼저 분류한다.
114
+ */
115
+ const POD_PROVIDER_ERROR_LINE =
116
+ /\bllm\.[a-z0-9_-]+ (?:credential|response|stream)\b.*\b(?:error|fail(?:ed|ure)?|denied|unavailable|overloaded|exhausted)\b|\b(?:rate[_ -]?limit|quota|credits?)\b.*\b(?:exceeded|exhausted|insufficient|hit)\b|\b(?:provider|upstream)\b.*\b(?:error|overloaded|unavailable|timed? out|5\d\d)\b|(?:프로바이더|제공자|모델)\s*(?:오류|호출 실패|한도 초과)/iu;
117
+
118
+ /** provider error 줄인가 — bookkeeping 줄과 «파싱되는 JSON 줄»은 세지 않는다(classifyPodExit 의 줄 기준과 같다). */
119
+ function isPodProviderErrorLine(line: string): boolean {
120
+ if (!line || isPodBookkeepingLine(line)) return false;
121
+ if (line.startsWith('{')) {
122
+ try {
123
+ const parsed: unknown = JSON.parse(line);
124
+ if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) return false;
125
+ } catch { /* 일반 줄이 중괄호로 시작할 수 있다. */ }
126
+ }
127
+ return POD_PROVIDER_ERROR_LINE.test(line);
128
+ }
129
+
130
+ /**
131
+ * POD-FAIL-EVIDENCE-CAPTURE-FU — duplicate-cap 귀속: 마지막 «canonical» 자식 terminal 하나에만 실패를 붙인다.
132
+ * canonical 접두(`self`/`external`)가 아닌 lookalike kind 행은 건너뛰고, 마지막 canonical terminal 이 성공이거나
133
+ * 읽을 오류 줄이 bookkeeping 뿐이면 null — 더 오래된(다른 terminal 의) 실패를 재사용하지 않는다.
134
+ */
135
+ export function podChildFailureAttribution(logs: string): { stage: string; error: string } | null {
136
+ for (const line of logs.split('\n').reverse()) {
137
+ if (!line.trimStart().startsWith('{')) continue;
138
+ let parsed: unknown;
139
+ try { parsed = JSON.parse(line); } catch { continue; }
140
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) continue;
141
+ const row = parsed as Record<string, unknown>;
142
+ const terminal = podTerminalRow(row);
143
+ if (!terminal) continue;
144
+ if (terminal.ok !== false || typeof terminal.error !== 'string') return null;
145
+ const errorLines = terminal.error.replace(/\/home\/[^/\s]+\//gu, '~/').split(/\r\n|\n|\r/u)
146
+ .map((part) => part.trim())
147
+ .filter((part) => part.length > 0 && !isPodBookkeepingLine(part));
148
+ if (!errorLines.length) return null;
149
+ const first = errorLines[0]!.slice(0, 240);
150
+ const last = errorLines.at(-1)!.slice(0, 240);
151
+ return { stage: terminal.stage, error: first === last ? first : `${first}\n${last}` };
152
+ }
153
+ return null;
154
+ }
155
+
111
156
  /** Classify a failed Pod using its terminal metadata and child output, without side effects. */
112
157
  export function classifyPodExit(input: {
113
158
  errorCode?: string | null;
@@ -131,12 +176,19 @@ export function classifyPodExit(input: {
131
176
  } {
132
177
  const logLines = input.logs.split(/\r\n|\n|\r/u).map((line) => line.trim()).filter(Boolean);
133
178
  let terminalResult: ReturnType<typeof podTerminalRow> = null;
134
- for (const line of logLines) {
179
+ let lastTerminalIndex = -1;
180
+ let previousTerminalIndex = -1;
181
+ for (const [index, line] of logLines.entries()) {
135
182
  if (!line.startsWith('{')) continue;
136
183
  let parsed: unknown;
137
184
  try { parsed = JSON.parse(line); } catch { continue; }
138
185
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) continue;
139
- terminalResult = podTerminalRow(parsed as Record<string, unknown>) ?? terminalResult;
186
+ const terminal = podTerminalRow(parsed as Record<string, unknown>);
187
+ if (!terminal) continue;
188
+ // 마지막 canonical terminal 만 유지 — 앞선 terminal 의 실패를 재사용하지 않는다(duplicate-cap).
189
+ previousTerminalIndex = lastTerminalIndex;
190
+ terminalResult = terminal;
191
+ lastTerminalIndex = index;
140
192
  }
141
193
  const hasResultLine = terminalResult !== null;
142
194
  if (!terminalResult && input.result) terminalResult = podTerminalRow(input.result);
@@ -148,12 +200,19 @@ export function classifyPodExit(input: {
148
200
  try { const parsed = JSON.parse(line); return !!parsed && typeof parsed === 'object' && !Array.isArray(parsed); } catch { return false; }
149
201
  };
150
202
  const hasErrorLine = logLines.some((line) => !isPodBookkeepingLine(line) && !isParsedJsonLine(line) && isPodErrorLine(line));
203
+ // 동일 terminal 직전만: 마지막 canonical terminal 에 딸린 구간(직전 terminal 다음 ~ 마지막 terminal)의 줄만
204
+ // provider error 근거로 쓴다 — 오래된 terminal 의 실패를 재사용하지 않는다(duplicate-cap).
205
+ const attributionLines = lastTerminalIndex === -1
206
+ ? logLines
207
+ : logLines.slice(previousTerminalIndex + 1, lastTerminalIndex);
208
+ const providerError = attributionLines.some((line) => isPodProviderErrorLine(line));
151
209
  let exitClass: PodExitClass;
152
210
  if (input.errorCode === 'pod-secret') exitClass = 'pod-secret';
153
211
  else if (input.jobReason === 'DeadlineExceeded') exitClass = 'deadline-exceeded';
154
212
  else if (input.containerReason === 'OOMKilled') exitClass = 'oom-killed';
155
213
  else if (input.containerExitCode === 7) exitClass = 'gh-login-failed';
156
214
  else if (askReprompt) exitClass = 'ask-reprompt';
215
+ else if (providerError) exitClass = 'provider-error';
157
216
  else if (terminalResult?.stage && terminalResult.ok === false) exitClass = 'child-unconverged';
158
217
  else if (!hasResultLine && hasErrorLine) exitClass = 'child-error';
159
218
  else if (!hasResultLine) exitClass = 'no-result-line';
@@ -245,3 +304,156 @@ export function extractPodFailureReason(input: {
245
304
  const why = input.logTailReason?.trim() || (input.logs.trim() ? '로그에 읽을 수 있는 오류 줄 없음' : '자식 로그 비어 있음');
246
305
  return `사유 못 읽음: ${normalizePodLogLine(why)}`;
247
306
  }
307
+
308
+ // JOB-FAILURE-TERMINATION-CAPTURE — the Kubernetes facts of a failed Job, read once at the failure verdict
309
+ // (Job Failed condition · result marker early exit) before GC removes the Job and its Pod. Unobserved stays
310
+ // `unknown` — `no-result-line` is never promoted to OOM or deadline here. Only these scalar fields are kept:
311
+ // no Pod env, Secret, or describe output.
312
+ export type PodTerminationPath = 'job-failed-condition' | 'result-marker';
313
+ export type PodTerminationUnknown = 'unknown';
314
+
315
+ export interface PodTermination {
316
+ job: string;
317
+ path: PodTerminationPath;
318
+ observedAt: string;
319
+ /** `ok` only when the Job read names this launch's uid · `unavailable`: failed (NotFound after GC · API error),
320
+ * a different or missing uid, or no launch uid to attribute it to. */
321
+ jobLookup: 'ok' | 'unavailable';
322
+ /** This launch's Job uid (the attribution key) — `unknown` when the launcher had none, and then nothing is attributed. */
323
+ jobUid: string | PodTerminationUnknown;
324
+ jobConditionReason: string | PodTerminationUnknown;
325
+ /** The Job's configured `spec.activeDeadlineSeconds` — a setting, not evidence the deadline fired. */
326
+ activeDeadlineSeconds: number | PodTerminationUnknown;
327
+ /** From the Job Failed condition reason `DeadlineExceeded` only. */
328
+ deadlineExceeded: boolean | PodTerminationUnknown;
329
+ /** `terminated`: the latest child container of this uid has a terminated state · without one, the Pod phase
330
+ * (`running` · `pending`) or `unknown` (any other or unread phase) · `absent`: no Pod of this uid. */
331
+ podLookup: 'terminated' | 'running' | 'pending' | 'unknown' | 'absent' | 'unavailable';
332
+ containerReason: string | PodTerminationUnknown;
333
+ exitCode: number | PodTerminationUnknown;
334
+ finishedAt: string | PodTerminationUnknown;
335
+ /** From `state.terminated.reason === 'OOMKilled'` only (never from exit code 137). */
336
+ oomKilled: boolean | PodTerminationUnknown;
337
+ }
338
+
339
+ /** Job Failed condition reason first: the classification takes column one, the capture all three, from one read. */
340
+ export const POD_TERMINATION_JOB_JSONPATH = '{.status.conditions[?(@.type=="Failed")].reason}{"\\t"}{.spec.activeDeadlineSeconds}{"\\t"}{.metadata.uid}';
341
+ /**
342
+ * One row per Pod of this Job name. The first three columns keep the classification read's layout
343
+ * (`creation · terminated.reason · terminated.exitCode`, empty when the child has no status yet), so the
344
+ * Failed-condition path reads Pods once for both; `finishedAt` follows, then `|phase · owner Job uid`.
345
+ */
346
+ export const POD_TERMINATION_PODS_JSONPATH = '{range .items[*]}{.metadata.creationTimestamp}{"\\t"}{range .status.containerStatuses[?(@.name=="child")]}{.state.terminated.reason}{"\\t"}{.state.terminated.exitCode}{"\\t"}{.state.terminated.finishedAt}{end}{"\\t"}{"\\t"}{"\\t"}{"|"}{.status.phase}{"\\t"}{.metadata.ownerReferences[?(@.kind=="Job")].uid}{"\\n"}{end}';
347
+
348
+ type PodTerminationKubectl = (args: readonly string[]) => { status: number | null; stdout: string; stderr: string };
349
+
350
+ const POD_TERMINATION_WORD = /^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/;
351
+ const JOB_UID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu;
352
+ const terminationWord = (value: string | undefined): string => {
353
+ const text = value?.trim() ?? '';
354
+ return POD_TERMINATION_WORD.test(text) ? text : 'unknown';
355
+ };
356
+ const terminationCount = (value: string | undefined): number | PodTerminationUnknown => {
357
+ const text = value?.trim() ?? '';
358
+ return /^\d{1,10}$/.test(text) ? Number(text) : 'unknown';
359
+ };
360
+ const terminationInstant = (value: string | undefined): string => {
361
+ const text = value?.trim() ?? '';
362
+ return /^\d{4}-\d{2}-\d{2}T[\d:.]+Z$/.test(text) && Number.isFinite(Date.parse(text)) ? text : 'unknown';
363
+ };
364
+
365
+ /** Two reads (the Job · its Pods), each fail-soft: a failed or thrown read is `unavailable`, never an inferred value. */
366
+ export function readPodTermination(input: { kubectl: PodTerminationKubectl; namespace: string; job: string; path: PodTerminationPath;
367
+ /** This launch's Job uid — the only attribution key. A same-name Job of another round (OOM retry · relaunch)
368
+ * is not this verdict's state; without it every Job/Pod fact stays unobserved. */
369
+ jobUid: string | undefined;
370
+ /** The Failed-condition path's own Job read of `POD_TERMINATION_JOB_JSONPATH` (null: it threw) — not read again,
371
+ * so a GC between the verdict and the capture cannot turn an observed reason into `unknown`. */
372
+ jobRead?: { status: number | null; stdout: string } | null;
373
+ /** The Failed-condition path's own Pods read of `POD_TERMINATION_PODS_JSONPATH` (null: it threw) — not read again. */
374
+ podsRead?: { status: number | null; stdout: string } | null;
375
+ now?: () => Date }): PodTermination {
376
+ const { kubectl, namespace, job, path } = input;
377
+ const read = (args: readonly string[]): { status: number | null; stdout: string } | null => {
378
+ try { return kubectl(args); } catch { return null; }
379
+ };
380
+ const jobRead = 'jobRead' in input ? input.jobRead ?? null
381
+ : read(['-n', namespace, 'get', 'job', job, '-o', `jsonpath=${POD_TERMINATION_JOB_JSONPATH}`]);
382
+ const [reasonText, deadlineText, uidText] = jobRead?.status === 0 ? jobRead.stdout.replace(/\r?\n$/, '').split('\t') : [];
383
+ const readUid = JOB_UID.test(uidText?.trim() ?? '') ? uidText!.trim() : undefined;
384
+ const jobUid = input.jobUid && JOB_UID.test(input.jobUid) ? input.jobUid : undefined;
385
+ // A read without a uid, or with another uid, is not this launch's Job.
386
+ const jobOk = jobRead?.status === 0 && jobUid !== undefined && readUid === jobUid;
387
+ const jobConditionReason = jobOk ? terminationWord(reasonText) : 'unknown';
388
+ const podsRead = 'podsRead' in input ? input.podsRead ?? null
389
+ : read(['-n', namespace, 'get', 'pods', '-l', `job-name=${job}`, '-o', `jsonpath=${POD_TERMINATION_PODS_JSONPATH}`]);
390
+ let podLookup: PodTermination['podLookup'] = 'unavailable';
391
+ let containerReason = 'unknown';
392
+ let exitCode: PodTermination['exitCode'] = 'unknown';
393
+ let finishedAt = 'unknown';
394
+ // Without a uid the rows cannot be attributed to this Job — they stay unread rather than borrowed from another round.
395
+ if (podsRead?.status === 0 && jobUid) {
396
+ // The latest Pod owned by this Job uid only.
397
+ const rows = podsRead.stdout.split('\n').map((line) => {
398
+ const cut = line.lastIndexOf('\t|');
399
+ const [created, reason, exit, finished] = (cut >= 0 ? line.slice(0, cut) : line).split('\t');
400
+ const [phase, owner] = cut >= 0 ? line.slice(cut + 2).split('\t') : [];
401
+ return { created: created ?? '', reason, exit, finished, phase: phase?.trim(), owner: owner?.trim() };
402
+ });
403
+ const owned = rows.filter((row) => row.created && Number.isFinite(Date.parse(row.created)) && row.owner === jobUid)
404
+ .sort((a, b) => Date.parse(b.created) - Date.parse(a.created));
405
+ const latest = owned[0];
406
+ // Two Pods of this uid created at the same instant (a Job retry): which one is «this» failure is not knowable.
407
+ const tied = latest !== undefined && owned.length > 1 && Date.parse(owned[1]!.created) === Date.parse(latest.created);
408
+ if (!latest) podLookup = 'absent';
409
+ else if (tied) podLookup = 'unknown';
410
+ else {
411
+ const { reason, exit, finished, phase } = latest;
412
+ containerReason = terminationWord(reason);
413
+ exitCode = terminationCount(exit);
414
+ finishedAt = terminationInstant(finished);
415
+ podLookup = containerReason !== 'unknown' || exitCode !== 'unknown' ? 'terminated'
416
+ : phase === 'Running' ? 'running' : phase === 'Pending' ? 'pending' : 'unknown';
417
+ }
418
+ }
419
+ return {
420
+ job, path, observedAt: (input.now?.() ?? new Date()).toISOString(),
421
+ jobLookup: jobOk ? 'ok' : 'unavailable',
422
+ jobUid: jobUid ?? 'unknown',
423
+ jobConditionReason,
424
+ activeDeadlineSeconds: jobOk ? terminationCount(deadlineText) : 'unknown',
425
+ deadlineExceeded: jobConditionReason === 'unknown' ? 'unknown' : jobConditionReason === 'DeadlineExceeded',
426
+ podLookup, containerReason, exitCode, finishedAt,
427
+ oomKilled: podLookup === 'terminated' && containerReason !== 'unknown' ? containerReason === 'OOMKilled' : 'unknown',
428
+ };
429
+ }
430
+
431
+ /** Ledger → incident: only a well-formed record of `job` (the current attempt's Job) is carried; anything else is dropped. */
432
+ export function parsePodTermination(value: unknown, job: string): PodTermination | undefined {
433
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
434
+ const row = value as Record<string, unknown>;
435
+ const oneOf = (v: unknown, allowed: readonly unknown[]) => allowed.includes(v);
436
+ const wordOrUnknown = (v: unknown) => typeof v === 'string' && (v === 'unknown' || POD_TERMINATION_WORD.test(v));
437
+ const numberOrUnknown = (v: unknown) => v === 'unknown' || (typeof v === 'number' && Number.isSafeInteger(v) && v >= 0);
438
+ const boolOrUnknown = (v: unknown) => v === 'unknown' || typeof v === 'boolean';
439
+ if (row.job !== job || !oneOf(row.path, ['job-failed-condition', 'result-marker'])
440
+ || typeof row.observedAt !== 'string' || !Number.isFinite(Date.parse(row.observedAt))
441
+ || !oneOf(row.jobLookup, ['ok', 'unavailable']) || !wordOrUnknown(row.jobConditionReason)
442
+ || !(row.jobUid === 'unknown' || (typeof row.jobUid === 'string' && JOB_UID.test(row.jobUid)))
443
+ || !numberOrUnknown(row.activeDeadlineSeconds) || !boolOrUnknown(row.deadlineExceeded)
444
+ || !oneOf(row.podLookup, ['terminated', 'running', 'pending', 'unknown', 'absent', 'unavailable'])
445
+ || !wordOrUnknown(row.containerReason) || !numberOrUnknown(row.exitCode)
446
+ || !(row.finishedAt === 'unknown' || (typeof row.finishedAt === 'string' && terminationInstant(row.finishedAt) !== 'unknown'))
447
+ || !boolOrUnknown(row.oomKilled)) return undefined;
448
+ // Facts are attributed through the uid only: a record claiming Job or Pod facts without one is contradictory.
449
+ if (row.jobUid === 'unknown' && (row.jobLookup !== 'unavailable' || row.podLookup !== 'unavailable')) return undefined;
450
+ return {
451
+ job, path: row.path as PodTerminationPath, observedAt: row.observedAt,
452
+ jobLookup: row.jobLookup as PodTermination['jobLookup'], jobUid: row.jobUid as string, jobConditionReason: row.jobConditionReason as string,
453
+ activeDeadlineSeconds: row.activeDeadlineSeconds as PodTermination['activeDeadlineSeconds'],
454
+ deadlineExceeded: row.deadlineExceeded as PodTermination['deadlineExceeded'],
455
+ podLookup: row.podLookup as PodTermination['podLookup'], containerReason: row.containerReason as string,
456
+ exitCode: row.exitCode as PodTermination['exitCode'], finishedAt: row.finishedAt as string,
457
+ oomKilled: row.oomKilled as PodTermination['oomKilled'],
458
+ };
459
+ }
@@ -0,0 +1,133 @@
1
+ /**
2
+ * POD-LAUNCH-PROVENANCE slice 2 — TA/harness si-task Jobs.
3
+ *
4
+ * ① `siTaskPodProvenance` fills the shared provenance set (pod-provenance.ts · #29650) for a si-task Job from the
5
+ * launch env the parent already has (owner · seat · task card · checklist slot · entrance stamp). It never builds
6
+ * labels itself — `podProvenanceMetadata` stays the one builder.
7
+ * ② The history is append-only rows on the parent's existing run ledger (`pod-launch-started` when the Job is
8
+ * applied, `pod-launch-finished` at the terminal verdict) — no new store. `readPodLaunchHistory(runId)` answers
9
+ * «who launched which Pod, when and why, and how did it end» from that ledger alone.
10
+ */
11
+ import { userInfo } from 'node:os';
12
+ import { LAUNCH_SEATS, resolveLaunchStamp } from '../../harness/launch-stamp.js';
13
+ import { loadRunLedger, runLedgerDir, type RunLedgerEntry } from '../../self-implement/run-ledger.js';
14
+ import type { PodProvenance } from './pod-provenance.js';
15
+ import type { PodWorkIdentity } from './pod-pool.js';
16
+
17
+ export const POD_LAUNCH_STARTED_EVENT = 'pod-launch-started';
18
+ export const POD_LAUNCH_FINISHED_EVENT = 'pod-launch-finished';
19
+
20
+ export interface SiTaskProvenanceInput {
21
+ env: NodeJS.ProcessEnv | Readonly<Record<string, string | undefined>>;
22
+ /** The child runId this Job runs as (`ELANOUS_RUN_ID` inside the Pod). */
23
+ runId: string;
24
+ parentRunId?: string;
25
+ workIdentity: PodWorkIdentity;
26
+ /** ISO-8601 UTC. */
27
+ requestedAt: string;
28
+ feature: string;
29
+ launchHost?: string;
30
+ commit?: string | null;
31
+ version?: string;
32
+ memReq?: string;
33
+ shard?: string;
34
+ }
35
+
36
+ const text = (value: string | undefined | null): string | undefined => {
37
+ const trimmed = value?.trim();
38
+ return trimmed ? trimmed : undefined;
39
+ };
40
+
41
+ function osUser(): string | undefined {
42
+ try { return text(userInfo().username); } catch { return undefined; }
43
+ }
44
+
45
+ /**
46
+ * The si-task identity. Actor order: the Job owner the dispatcher named → the launch stamp actor (seat · session · loop)
47
+ * → the OS user. `pool` is deliberately absent: `ELANOUS_POD_POOL` is read as pool config by the child harness.
48
+ */
49
+ export function siTaskPodProvenance(input: SiTaskProvenanceInput): Partial<PodProvenance> {
50
+ const env = input.env as NodeJS.ProcessEnv;
51
+ const identity = input.workIdentity;
52
+ const stamp = resolveLaunchStamp({}, env);
53
+ const ownerId = text(identity.ownerId);
54
+ const stampActor = text(stamp.actor);
55
+ const user = text(env.USER) ?? text(env.LOGNAME) ?? osUser();
56
+ const actor = ownerId ?? stampActor ?? user;
57
+ const actorKind = ownerId && identity.ownerKind
58
+ ? (identity.ownerKind === 'steward' || identity.ownerKind === 'orchestrator' ? 'loop' : identity.ownerKind)
59
+ : stampActor && (LAUNCH_SEATS as readonly string[]).includes(stampActor) ? 'seat'
60
+ : stampActor && stampActor === text(env.ELANOUS_LOOP_NAME) ? 'loop'
61
+ : actor ? 'human' : undefined;
62
+ const authoring = identity.work === 'authoring';
63
+ const entrance = stamp.entrance !== 'unknown' ? stamp.entrance : identity.taskCard ? 'tasks-hand' : undefined;
64
+ const firstLine = input.feature.split('\n', 1)[0]?.trim().slice(0, 160) ?? '';
65
+ const reason = [identity.taskCard ? `TA ${identity.taskCard}` : undefined, firstLine || undefined].filter(Boolean).join(' · ');
66
+ return {
67
+ ...(actorKind ? { actorKind } : {}),
68
+ ...(actor ? { actor } : {}),
69
+ kind: 'si-task',
70
+ run: input.runId,
71
+ phase: authoring ? 'authoring' : 'impl',
72
+ requestedAt: input.requestedAt,
73
+ character: identity.taskCard ? 'ta-child' : authoring ? 'author-child' : 'harness-child',
74
+ ...(entrance ? { entrance } : {}),
75
+ ...(text(identity.slotId) ? { cell: identity.slotId } : {}),
76
+ ...(text(input.version) ? { version: input.version } : {}),
77
+ ...(text(input.commit) ? { commit: input.commit! } : {}),
78
+ ...(text(input.launchHost) ? { launchHost: input.launchHost } : {}),
79
+ ...(text(input.shard) ? { shard: input.shard } : {}),
80
+ ...(text(input.memReq) ? { memReq: input.memReq } : {}),
81
+ ...(text(input.parentRunId) ? { parent: input.parentRunId } : {}),
82
+ ...(reason ? { reason } : {}),
83
+ };
84
+ }
85
+
86
+ /** `elanous.ai/<key>` annotations → `{ <key>: value }` for the started row (full values, not the 63-char labels). */
87
+ export function provenanceRowFromAnnotations(annotations: Readonly<Record<string, string>>): Record<string, string> {
88
+ const row: Record<string, string> = {};
89
+ for (const [key, value] of Object.entries(annotations)) if (key.startsWith('elanous.ai/')) row[key.slice('elanous.ai/'.length)] = value;
90
+ return row;
91
+ }
92
+
93
+ export interface PodLaunchRecord {
94
+ job: string;
95
+ run: string;
96
+ attempt: number | null;
97
+ startedAt: string | null;
98
+ provenance: Record<string, string>;
99
+ finished: { at: string | null; phase: string; exitCode: number | null; reason: string } | null;
100
+ }
101
+
102
+ const str = (value: unknown): string | undefined => (typeof value === 'string' && value ? value : undefined);
103
+
104
+ /** Rebuild launch records from one run ledger. Rows pair on job·run; an unpaired row stays visible (never dropped). */
105
+ export function readPodLaunchHistory(runId: string, dir: string = runLedgerDir()): PodLaunchRecord[] {
106
+ const entries: RunLedgerEntry[] = loadRunLedger(runId, dir) ?? [];
107
+ const records: PodLaunchRecord[] = [];
108
+ const open = new Map<string, PodLaunchRecord>();
109
+ for (const entry of entries) {
110
+ if (entry.event !== POD_LAUNCH_STARTED_EVENT && entry.event !== POD_LAUNCH_FINISHED_EVENT) continue;
111
+ const job = str(entry.data.job) ?? 'unknown';
112
+ const run = str(entry.data.run) ?? 'unknown';
113
+ const key = `${job}\u0000${run}`;
114
+ if (entry.event === POD_LAUNCH_STARTED_EVENT) {
115
+ const provenance: Record<string, string> = {};
116
+ const raw = entry.data.provenance;
117
+ if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
118
+ for (const [name, value] of Object.entries(raw as Record<string, unknown>)) if (typeof value === 'string') provenance[name] = value;
119
+ }
120
+ const record: PodLaunchRecord = { job, run, attempt: typeof entry.data.attempt === 'number' ? entry.data.attempt : null,
121
+ startedAt: entry.timestamp ?? null, provenance, finished: null };
122
+ records.push(record);
123
+ open.set(key, record);
124
+ continue;
125
+ }
126
+ const finished = { at: entry.timestamp ?? null, phase: str(entry.data.phase) ?? 'unknown',
127
+ exitCode: typeof entry.data.exitCode === 'number' ? entry.data.exitCode : null, reason: str(entry.data.reason) ?? 'unknown' };
128
+ const started = open.get(key);
129
+ if (started && !started.finished) { started.finished = finished; open.delete(key); continue; }
130
+ records.push({ job, run, attempt: typeof entry.data.attempt === 'number' ? entry.data.attempt : null, startedAt: null, provenance: {}, finished });
131
+ }
132
+ return records;
133
+ }
@@ -12,6 +12,17 @@ export function stablePodManifestText(applied: Array<Record<string, any>>): stri
12
12
  let snapshots = 0;
13
13
  for (const manifest of manifests) {
14
14
  if (manifest.kind !== 'Job') continue;
15
+ // POD-LAUNCH-PROVENANCE — the request time and the 8-char run/parent labels are per launch like the run id.
16
+ for (const meta of [manifest.metadata, manifest.spec?.template?.metadata]) {
17
+ for (const bag of [meta?.labels, meta?.annotations]) {
18
+ if (!bag) continue;
19
+ if (bag['elanous.ai/requested-at'] !== undefined) bag['elanous.ai/requested-at'] = '<requested-at>';
20
+ if (meta?.labels === bag) for (const key of ['elanous.ai/run', 'elanous.ai/parent']) if (bag[key] !== undefined) bag[key] = '<run-label>';
21
+ }
22
+ }
23
+ for (const container of manifest.spec?.template?.spec?.containers ?? []) {
24
+ for (const entry of container.env ?? []) if (entry.name === 'ELANOUS_POD_REQUESTED_AT') entry.value = '<requested-at>';
25
+ }
15
26
  for (const container of manifest.spec?.template?.spec?.containers ?? []) {
16
27
  for (const entry of container.env ?? []) {
17
28
  if (entry.name !== BUDGET_SNAPSHOT_ENV) continue;
@@ -89,14 +89,29 @@ function defaultLocalImageInspect(image: string): { status: number | null; stdou
89
89
  return { status: r.status, stdout: r.stdout ?? '' };
90
90
  }
91
91
 
92
+ /** 레지스트리 안 이미지 이름 — `docker/harness/build.sh` 의 full/lite 규칙 그대로. */
93
+ function podRegistryImageName(image: string): string {
94
+ return image === 'elanous-harness-lite:local' ? 'elanous-harness-lite' : 'elanous-harness';
95
+ }
96
+
97
+ /** 레지스트리 태그 = 커밋 앞 12자리 (build.sh:295 와 같은 규칙). */
98
+ function podRegistryTag(commit: string): string {
99
+ return commit.slice(0, 12);
100
+ }
101
+
102
+ /** 노드 로컬 레지스트리의 HTTP 포트 — 호스트에서는 같은 포트의 localhost 로 조회한다. */
103
+ function memberRegistryPort(member: PodPoolMember): string {
104
+ const registry = memberRegistry(member);
105
+ return registry.slice(registry.lastIndexOf(':') + 1);
106
+ }
107
+
92
108
  /** 이 커밋의 이미지가 노드 레지스트리에 있나 — 있으면 클러스터 안 이미지 주소. */
93
109
  export function registryImageRef(member: PodPoolMember, commit: string | null, run: RemoteRun = defaultRemoteRun, image = 'elanous-harness:local'): string | null {
94
110
  if (!member.sshHost || !commit) return null;
95
- const imageName = image === 'elanous-harness-lite:local' ? 'elanous-harness-lite' : 'elanous-harness';
96
- const tag = commit.slice(0, 12);
111
+ const imageName = podRegistryImageName(image);
112
+ const tag = podRegistryTag(commit);
97
113
  const registry = memberRegistry(member);
98
- const port = registry.slice(registry.lastIndexOf(':') + 1);
99
- const r = run(member.sshHost, `curl -fsS --max-time 5 http://localhost:${port}/v2/${imageName}/tags/list 2>/dev/null`);
114
+ const r = run(member.sshHost, `curl -fsS --max-time 5 http://localhost:${memberRegistryPort(member)}/v2/${imageName}/tags/list 2>/dev/null`);
100
115
  if (r.status !== 0) return null;
101
116
  try {
102
117
  const tags = (JSON.parse(r.stdout) as { tags?: string[] }).tags ?? [];
@@ -104,6 +119,54 @@ export function registryImageRef(member: PodPoolMember, commit: string | null, r
104
119
  } catch { return null; }
105
120
  }
106
121
 
122
+ /** 레지스트리 HTTP 한 번 — 노드에서 `curl -fsS --max-time 5`(registryImageRef 와 같은 규칙). 실패면 null. */
123
+ function registryHttpGet(member: PodPoolMember, path: string, run: RemoteRun, accept?: string): string | null {
124
+ if (!member.sshHost) return null;
125
+ const header = accept ? `-H 'Accept: ${accept}' ` : '';
126
+ const r = run(member.sshHost, `curl -fsS --max-time 5 ${header}http://localhost:${memberRegistryPort(member)}/v2/${path} 2>/dev/null`);
127
+ return r.status === 0 && r.stdout.trim() ? r.stdout : null;
128
+ }
129
+
130
+ function registryLabelValue(raw: unknown): string | null {
131
+ return typeof raw === 'string' && raw.trim() && raw !== '<no value>' ? raw.trim() : null;
132
+ }
133
+
134
+ /**
135
+ * GATE-REGISTRY-IMAGE-FASTPATH (0.2.36): 레지스트리 HTTP 만으로 이 커밋 태그 이미지의 config label 을 읽는다 —
136
+ * 노드 Docker 데몬(`docker image inspect`)을 부르지 않는다. 태그 결손 · HTTP 오류 · manifest list(단일 config 없음) ·
137
+ * 비JSON 은 null 이다(판정하지 않고 종전 경로로 떨어진다).
138
+ * GET /v2/<이미지>/manifests/<커밋12> → config.digest → GET /v2/<이미지>/blobs/<digest> → config.Labels
139
+ */
140
+ export function registryImageLabels(member: PodPoolMember, image: string, commit: string | null, run: RemoteRun = defaultRemoteRun): { commit: string | null; skills: string | null } | null {
141
+ if (!member.sshHost || !commit) return null;
142
+ const imageName = podRegistryImageName(image);
143
+ const manifest = registryHttpGet(member, `${imageName}/manifests/${podRegistryTag(commit)}`, run, 'application/vnd.docker.distribution.manifest.v2+json');
144
+ if (!manifest) return null;
145
+ let digest: string | undefined;
146
+ try { digest = (JSON.parse(manifest) as { config?: { digest?: string } }).config?.digest; } catch { return null; }
147
+ if (!digest) return null;
148
+ // config digest 는 `sha256:<64 hex>` — 이 형태가 아니면 경로에 넣지 않는다.
149
+ if (!/^sha256:[0-9a-f]{64}$/u.test(digest)) return null;
150
+ const blob = registryHttpGet(member, `${imageName}/blobs/${digest}`, run);
151
+ if (!blob) return null;
152
+ let labels: Record<string, unknown> | undefined;
153
+ try { labels = (JSON.parse(blob) as { config?: { Labels?: Record<string, unknown> } }).config?.Labels; } catch { return null; }
154
+ if (!labels || typeof labels !== 'object') return null;
155
+ return { commit: registryLabelValue(labels['elanous.commit']), skills: registryLabelValue(labels['elanous.pod-skills']) };
156
+ }
157
+
158
+ /**
159
+ * 이 커밋 태그의 이미지 label 이 이번 발사 값과 모두 맞나 — 맞으면 Docker 조회 없이 그 판을 쓸 수 있다.
160
+ * 커밋 label 은 발사 커밋과 «정확히» 같아야 한다(태그가 다른 판을 가리키는 경우를 거른다).
161
+ * `localSkillsDigest` 가 없으면(모르는 값) 커밋 label 만 본다 — syncPoolImages 의 종전 skillsSame 과 같은 뜻.
162
+ */
163
+ export function registryImageLabelsMatch(member: PodPoolMember, image: string, commit: string | null, opts: { localSkillsDigest?: string | null; run?: RemoteRun } = {}): boolean {
164
+ if (!commit) return false;
165
+ const labels = registryImageLabels(member, image, commit, opts.run ?? defaultRemoteRun);
166
+ if (!labels || labels.commit !== commit) return false;
167
+ return opts.localSkillsDigest == null || labels.skills === opts.localSkillsDigest;
168
+ }
169
+
107
170
  /** IMAGE-ONE-SOURCE: 이 멤버의 노드에 레지스트리 컨테이너가 있나(syncPoolImages 의 판정과 같은 명령). 로컬 멤버는 false. */
108
171
  export function memberHasRegistry(member: PodPoolMember, run: RemoteRun = defaultRemoteRun): boolean {
109
172
  if (!member.sshHost) return false;
@@ -873,6 +936,15 @@ export async function syncPoolImages(members: readonly PodPoolMember[], image: s
873
936
  await Promise.all(members.map(async (m) => {
874
937
  const t0 = Date.now();
875
938
  if (!m.sshHost) { results.set(m.context, { ok: true, action: 'local', detail: 'this machine', ms: 0 }); return; }
939
+ // ⭐ GATE-REGISTRY-IMAGE-FASTPATH (0.2.36 · OP): 레지스트리 커밋 태그의 config label(commit ⊕ pod-skills)이 이번 발사
940
+ // 값과 같으면 노드 Docker 데몬을 «한 번도» 부르지 않고 그 커밋 ref 로 끝난다 — 데몬 조회가 느려도 gate 첫 Pod 이 뜬다.
941
+ // 태그 결손 · label 불일치 · HTTP 오류면 아래 종전 경로(원격 inspect → 노드 빌드 → 통째 전송)가 그대로 판정한다.
942
+ if (localCommit && registryImageLabelsMatch(m, image, localCommit, { ...(deps.localSkillsDigest !== undefined ? { localSkillsDigest: deps.localSkillsDigest } : {}), run })) {
943
+ const imageRef = `${memberRegistry(m)}/${podRegistryImageName(image)}:${podRegistryTag(localCommit)}`;
944
+ debug.log('pod.pool', 'image-fresh-registry-label', { context: m.context, host: m.sshHost, commit: localCommit, imageRef, skills: deps.localSkillsDigest ?? null, waitedMs: 0 });
945
+ results.set(m.context, { ok: true, action: 'fresh', detail: localCommit.slice(0, 12), ms: Date.now() - t0, imageRef });
946
+ return;
947
+ }
876
948
  const before = remoteImageCommit(m, image, run);
877
949
  const skillsNow = deps.localSkillsDigest;
878
950
  const refBefore = registryImageRef(m, localCommit, run, image);
@@ -17,6 +17,8 @@ export interface PodProvenance {
17
17
  commit?: string;
18
18
  shard?: string;
19
19
  reason?: string;
20
+ /** Parent runId / lease id — whose child this Pod is. Label keeps the first 8 characters like run/commit. */
21
+ parent?: string;
20
22
  pool?: string;
21
23
  cpuReq?: string;
22
24
  memReq?: string;
@@ -28,11 +30,15 @@ const required = ['actorKind', 'actor', 'kind', 'run', 'phase', 'requestedAt'] a
28
30
  const names: Record<keyof PodProvenance, string> = {
29
31
  actorKind: 'actor-kind', actor: 'actor', kind: 'kind', run: 'run', phase: 'phase', requestedAt: 'requested-at',
30
32
  character: 'character', launchHost: 'launch-host', entrance: 'entrance', graphNode: 'graph-node', cell: 'cell',
31
- version: 'version', commit: 'commit', shard: 'shard', reason: 'reason',
33
+ version: 'version', commit: 'commit', shard: 'shard', reason: 'reason', parent: 'parent',
32
34
  pool: 'pool', cpuReq: 'cpu-req', memReq: 'mem-req',
33
35
  warmReused: 'warm-reused', argv: 'argv',
34
36
  };
35
37
 
38
+ /** Every child env name the set can carry (`ELANOUS_POD_<KEY>`). */
39
+ export const POD_PROVENANCE_ENV_NAMES: readonly string[] = Object.values(names)
40
+ .map((name) => `ELANOUS_POD_${name.toUpperCase().replaceAll('-', '_')}`);
41
+
36
42
  const labelValue = (value: string): string => {
37
43
  const cleaned = value.toLowerCase().replace(/[^a-z0-9._-]/g, '-').replace(/^[^a-z0-9]+|[^a-z0-9]+$/g, '');
38
44
  return cleaned.slice(0, 63).replace(/[^a-z0-9]+$/g, '') || 'unknown';
@@ -67,7 +73,7 @@ export function podProvenanceMetadata(input: Partial<PodProvenance> | undefined,
67
73
  const annotations: Record<string, string> = {};
68
74
  const env: Array<{ name: string; value: string }> = [];
69
75
  for (const [name, value] of Object.entries(values)) {
70
- const label = name === 'run' || name === 'commit' ? value.slice(0, 8) : value;
76
+ const label = name === 'run' || name === 'commit' || name === 'parent' ? value.slice(0, 8) : value;
71
77
  if (name !== 'reason' && name !== 'argv') labels[`elanous.ai/${name}`] = labelValue(label);
72
78
  annotations[`elanous.ai/${name}`] = value;
73
79
  env.push({ name: `ELANOUS_POD_${name.toUpperCase().replaceAll('-', '_')}`, value });
@@ -3,6 +3,7 @@ import { execFileSync } from 'node:child_process';
3
3
  import { createHash } from 'node:crypto';
4
4
  import { mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from 'node:fs';
5
5
  import { isAbsolute, join, resolve } from 'node:path';
6
+ import { classifyGateEnvDeficit, GATE_ENV_DEFICIT_HARVESTABLE_MARK } from '../../self-implement/gate-env-retry.js';
6
7
 
7
8
  export const REPAIR_REF = 'refs/elanous/repair/result';
8
9
  export const REPAIR_BUNDLE_MAX_BYTES = 5 * 1024 * 1024;
@@ -39,15 +40,29 @@ function completedWorktree(output: string): { path: string; runId: string } {
39
40
  let value: Record<string, unknown>;
40
41
  try { value = JSON.parse(line) as Record<string, unknown>; } catch { continue; }
41
42
  if (value.kind === 'self' && value.result && typeof value.result === 'object') value = value.result as Record<string, unknown>;
42
- if (value.stage !== 'worktree-completed' || value.ok !== true || typeof value.worktreePath !== 'string'
43
+ const completed = value.stage === 'worktree-completed' && value.ok === true;
44
+ // The gate could not measure an environmental failure. Keep the implementation as a
45
+ // bundle for the pinned PR; the parent still has to review and rejudge that head.
46
+ const gate = value.gate && typeof value.gate === 'object' && !Array.isArray(value.gate)
47
+ ? value.gate as { passed?: unknown; log?: unknown; reflectGateFacts?: { introduced?: number; unknownReason?: string; childResponsibility?: string } }
48
+ : null;
49
+ const environmentHarvest = value.stage === 'gate-failed' && value.ok === false
50
+ && value.harvestable === true && typeof value.detail === 'string'
51
+ && value.detail.includes(GATE_ENV_DEFICIT_HARVESTABLE_MARK)
52
+ && gate?.passed === false
53
+ && gate.reflectGateFacts?.introduced === 0
54
+ && gate.reflectGateFacts?.childResponsibility === 'none'
55
+ && classifyGateEnvDeficit({ passed: false, ...(typeof gate.log === 'string' ? { log: gate.log } : {}),
56
+ ...(gate.reflectGateFacts ? { reflectGateFacts: gate.reflectGateFacts } : {}) }).envDeficit;
57
+ if ((!completed && !environmentHarvest) || typeof value.worktreePath !== 'string'
43
58
  || typeof value.runId !== 'string' || !value.runId)
44
- throw new Error('repair child final result is not a successful worktree-only result');
59
+ throw new Error('repair child final result is neither successful worktree-only nor environment-deficit harvestable');
45
60
  return { path: value.worktreePath, runId: value.runId };
46
61
  }
47
62
  throw new Error('repair child did not return a successful worktree-only result');
48
63
  }
49
64
 
50
- /** Called in the Pod after the child exits successfully and before artifact export. */
65
+ /** Called in the Pod after a successful child or a verified environment-deficit harvest. */
51
66
  export function writePodRepairCommit(input: { pr: number; baseHead: string; runId: string; output: string; repo: string; outbox: string }): PodRepairResult {
52
67
  if (!Number.isSafeInteger(input.pr) || input.pr < 1 || !SHA40.test(input.baseHead)) throw new Error('invalid repair PR or base head');
53
68
  if (!input.runId.trim()) throw new Error('repair parent run id missing');
@@ -0,0 +1,16 @@
1
+ /** Opt-in SI warm entry; the ordinary Pod spawn remains the default. */
2
+ import { podSelfImplementSpawn, type PodSpawnOptions } from './self-implement-pod.js';
3
+
4
+ export async function podSpawnWithSiWarm(base: PodSpawnOptions,
5
+ env: NodeJS.ProcessEnv = process.env) {
6
+ if (env.ELANOUS_SI_WARM_REUSE !== '1') return podSelfImplementSpawn(base);
7
+ const { acquireSiWarmChild, postprocessSiWarmChild } = await import('./pod-si-warm-host.js');
8
+ return podSelfImplementSpawn({ ...base,
9
+ siWarmAttempt: async input => {
10
+ const result = await acquireSiWarmChild(input, base);
11
+ return result.status === 'acquired' ? result.attempt : null;
12
+ },
13
+ siWarmHostPostprocess: (result, attempt, input) =>
14
+ postprocessSiWarmChild(input, result, attempt, base),
15
+ });
16
+ }