elanous 0.2.34 → 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 (802) 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/{abb4b98b.163e0f56e84ae35d.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/1201.afbfc5b1c5e5cbe4.js +1 -0
  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/2500.cbc1257b774aae52.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{6086.913a69e6fa3e4a8b.js → 2683.c9773a0c589b031b.js} +4 -4
  20. package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +24 -0
  21. package/apps/pwa/out/_next/static/chunks/{5576-82d3703636d5c4b9.js → 275-02ea4c2a33980422.js} +3 -3
  22. package/apps/pwa/out/_next/static/chunks/{ffdc3a04.b9c23c1b28dd4a96.js → 2812ca6a.3b9f4a7a08885744.js} +1 -1
  23. package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +24 -0
  26. package/apps/pwa/out/_next/static/chunks/{9550.d5f76828f972058c.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/{8817.61bb7ffbba502ecb.js → 3136.30aaaa5fa03662a3.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/{9131-fce7256c4180c4a5.js → 3148-98efd4869d660a87.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/{3498.cf2a15a8a9e5b926.js → 3155.2587a55196ecb394.js} +3 -3
  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/{3103.84470c8445962f04.js → 3324.a09703033abcbd2f.js} +1 -1
  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/{3819.163d4777f0a597f6.js → 3538.a445e50bb359d068.js} +2 -2
  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/{3414.172ad4ca2d9b08e8.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/3757-180308bc61021b05.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +74 -0
  45. package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{9b48c871.204d5d13e7809bd0.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/{6740.43de73fc427c9fe2.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/{8548.036c344973968847.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/{3411-f87314c6c66ebc73.js → 5085-bce4904931767ca6.js} +1 -1
  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/{3110.0a7065f25c841818.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/{1644.35dd25240ae24e4b.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/{3837.722e053fb9f321ad.js → 5711.957b095705c12560.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/{2124.ed5bf480cea7f85b.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/{7562.948255cbc3e79d33.js → 599.c39c571b6733f2a2.js} +2 -2
  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/{5446.edf141cff9ef647d.js → 6925.562d532110879886.js} +1 -1
  86. package/apps/pwa/out/_next/static/chunks/{7005.1623d2aea78eb85f.js → 6943.c6b24124853a47b2.js} +1 -1
  87. package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/{8368.014caa8de2f5af34.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/{2554.3b5e200f5f5cfcd6.js → 771.c3cdb6c1f7f47c02.js} +16 -16
  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/{3121.779fafe3e44612c5.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/{9a8cb466.cc9fc9e6e46038aa.js → 873d6c12.09bd499f57171543.js} +1 -1
  101. package/apps/pwa/out/_next/static/chunks/{7431.3051e9b8a4372d2d.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/914.8abefd48d579547b.js +94 -0
  105. package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/{1895-60ed0e341c658bd4.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/{2547.dd27303624cb4da8.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/9789.60f723d18097ec30.js +1 -0
  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-4fb31eb476dcbad3.js → page-083747f1d4518f61.js} +1 -1
  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/{5014f970-22bef0b5210f7d60.js → ccae1c4b-0cf414f5eff1b10d.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/{4fa33ebd.21c1bd5b294496e6.js → ceba0382.650712b56b85b582.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/da5ecc5c-b005ad8cac737d57.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +1 -0
  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/{L04y73dlwKeTW-GetaTF3 → 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/bin/elanous.mjs +3 -2
  278. package/catalog/providers/opengateway.yaml +25 -0
  279. package/docs/goal-context/01-goal-authoring-checks.md +8 -0
  280. package/docs/goal-context/03-verification-menu.md +24 -0
  281. package/docs/goal-context/04-mock-scenarios.md +100 -0
  282. package/docs/goal-context/05-authoring-lessons.jsonl +47 -0
  283. package/docs/goal-context/README.md +7 -0
  284. package/graphs/catalog/catalog.yaml +1 -1
  285. package/graphs/default-loop.yaml +63 -4
  286. package/graphs/document-loop.yaml +51 -3
  287. package/graphs/implement-loop.yaml +77 -4
  288. package/graphs/journey/ta-journey.yaml +11 -1
  289. package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
  290. package/graphs/journey/units/author-dialogue/observe.ts +96 -0
  291. package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
  292. package/graphs/operate-loop.yaml +51 -3
  293. package/graphs/release/recipes.yaml +6 -0
  294. package/graphs/release/release-loop.yaml +17 -4
  295. package/graphs/research-loop.yaml +137 -3
  296. package/graphs/test-diet/test-diet.yaml +3 -0
  297. package/graphs/wizard/recipes.yaml +44 -0
  298. package/graphs/wizard/wizard-loop.yaml +44 -0
  299. package/graphs/work/research-report.yaml +2 -0
  300. package/package.json +1 -1
  301. package/scripts/ci-typecheck-changed.ts +139 -5
  302. package/scripts/coord-role-pack.ts +19 -6
  303. package/scripts/first10-gate.ts +416 -0
  304. package/scripts/fleet/wsl-node-setup.sh +432 -0
  305. package/scripts/hq/standby-snapshot.ts +17 -12
  306. package/scripts/release-loop/docs-land-node.ts +21 -5
  307. package/scripts/release-loop/docs-node.ts +204 -8
  308. package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
  309. package/scripts/release-loop/gate-node.ts +427 -72
  310. package/scripts/release-loop/gate-partial.ts +65 -11
  311. package/scripts/release-loop/gate-radius-live.ts +177 -0
  312. package/scripts/release-loop/gate-radius-shadow.ts +1 -1
  313. package/scripts/release-loop/node-verdict.ts +14 -1
  314. package/scripts/release-loop/npm-publish-node.ts +66 -12
  315. package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
  316. package/scripts/release-loop/pwa-remote.ts +166 -0
  317. package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
  318. package/scripts/release-loop/resume-cap.ts +14 -34
  319. package/scripts/release-loop/resume-release.ts +78 -15
  320. package/scripts/release-loop/traffic-node.ts +59 -0
  321. package/scripts/release-loop/traffic-transition.ts +159 -0
  322. package/scripts/release-loop/unattended-release.ts +2 -0
  323. package/scripts/rhythm/daily.ts +137 -3
  324. package/scripts/test-diet/lib.ts +6 -1
  325. package/scripts/test-diet/node.ts +194 -13
  326. package/scripts/ux-sim.ts +92 -0
  327. package/skills/README.md +1 -0
  328. package/src/acp/core-turn-bridge.ts +48 -6
  329. package/src/agent/delegate-hint.ts +16 -0
  330. package/src/agent/runner.ts +82 -2
  331. package/src/agent/self-ambient-cache.ts +8 -0
  332. package/src/agent/task-notification.ts +56 -10
  333. package/src/agent/types.ts +4 -0
  334. package/src/agent-substrate/acp-reviewer.ts +39 -4
  335. package/src/agent-substrate/pr-reviewer.ts +72 -3
  336. package/src/agent-substrate/review-intent.ts +29 -2
  337. package/src/agent-substrate/review-observation.ts +3 -0
  338. package/src/agent-substrate/self-review-cli.ts +229 -28
  339. package/src/autopilot/mission-codebase-gate.ts +141 -12
  340. package/src/autopilot/pr-manager.ts +240 -41
  341. package/src/boot/daemon-tools/self-implement.ts +1 -0
  342. package/src/budget/run-usage-rollup.ts +1 -0
  343. package/src/budget/usage-outcomes.ts +8 -4
  344. package/src/capture/tui-self-report.ts +102 -0
  345. package/src/chat/goal-continue-verdict.ts +41 -0
  346. package/src/chat/index.ts +30 -6
  347. package/src/chat/internal-turn-origin.ts +1 -0
  348. package/src/chat/paste-fold.ts +86 -0
  349. package/src/chat/pickers/modal-runtime.ts +10 -27
  350. package/src/chat/tool-render/block.ts +32 -0
  351. package/src/chat/tool-render/dispatch.ts +2 -20
  352. package/src/chat/tool-render/result-text.ts +98 -0
  353. package/src/chat/turn-typeahead.ts +70 -7
  354. package/src/cli/agent-cli.ts +13 -2
  355. package/src/cli/config-audit.ts +119 -0
  356. package/src/cli/doctor-cli.ts +26 -1
  357. package/src/cli/guardian-cli.ts +10 -0
  358. package/src/cli/herdr-cli.ts +34 -0
  359. package/src/cli/light-entry-route.ts +50 -7
  360. package/src/cli/log-event-names.ts +2 -0
  361. package/src/cli/make-cli.ts +247 -11
  362. package/src/cli/msg-cli.ts +117 -3
  363. package/src/cli/pod-cli.ts +77 -3
  364. package/src/cli/pr-cli.ts +34 -18
  365. package/src/cli/pr-land-base-read.ts +11 -2
  366. package/src/cli/pr-land-heavy-remote.ts +6 -3
  367. package/src/cli/pr-land-overlap-evidence.ts +23 -4
  368. package/src/cli/pr-land-pod-shadow-job.ts +3 -0
  369. package/src/cli/pr-land-recovery.ts +117 -1
  370. package/src/cli/pty-takeover-cli.ts +8 -7
  371. package/src/cli/release-checklist-read-cli.ts +79 -0
  372. package/src/cli/release-cli.ts +92 -106
  373. package/src/cli/release-single-flight.ts +1 -1
  374. package/src/cli/remote-resolve.ts +1 -1
  375. package/src/cli/root-tui-entry.ts +48 -0
  376. package/src/cli/sim-cli.ts +22 -0
  377. package/src/cli/tasks-card-show.ts +162 -0
  378. package/src/cli/tasks-cli.ts +1065 -338
  379. package/src/cli/tasks-read-cli.ts +197 -0
  380. package/src/cli/usage-cli.ts +13 -11
  381. package/src/clipboard/history.ts +179 -13
  382. package/src/config.ts +8 -1
  383. package/src/core-turn/run-core-turn.ts +4 -2
  384. package/src/core-turn/run-goal-loop.ts +73 -16
  385. package/src/core-turn/types.ts +6 -1
  386. package/src/dashboard/chat/acp-chat.ts +8 -0
  387. package/src/dashboard/context/keys.ts +8 -31
  388. package/src/dashboard/index.ts +280 -59
  389. package/src/dashboard/input/agent-wake.ts +7 -1
  390. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +146 -3
  391. package/src/dashboard/input/chat-main-slash-command.ts +4 -2
  392. package/src/dashboard/input/goal-continue.ts +210 -0
  393. package/src/dashboard/input/goal-interim.ts +2 -0
  394. package/src/dashboard/input/internal-turn.ts +2 -8
  395. package/src/dashboard/input/seat-autowake.ts +9 -7
  396. package/src/dashboard/input/turn-autoheal.ts +52 -0
  397. package/src/dashboard/render/theme-resolver.ts +33 -4
  398. package/src/dashboard/seat-boot-preamble.ts +132 -5
  399. package/src/dashboard/slash-runtime/chat-persona.ts +65 -8
  400. package/src/dashboard/slash-runtime/dashboard-handlers.ts +3 -2
  401. package/src/dashboard/slash-runtime/model-choices.ts +15 -0
  402. package/src/dashboard/stale-install-check.ts +3 -99
  403. package/src/debug/batch-queue.ts +119 -0
  404. package/src/debug/tui-log-tag.ts +67 -0
  405. package/src/display/agent-surface.ts +7 -0
  406. package/src/domains/schedule-registry.ts +16 -2
  407. package/src/domains/standalone-log-sink.ts +15 -2
  408. package/src/esc-abort-gate.ts +69 -0
  409. package/src/git-fs/idle-refresh.ts +76 -0
  410. package/src/git-fs/index.ts +18 -7
  411. package/src/git-fs/worktree.ts +137 -5
  412. package/src/graph-kinds/registry.ts +2 -2
  413. package/src/graph-runner/graph-cli.ts +18 -0
  414. package/src/graph-runner/runner.ts +173 -21
  415. package/src/graph-wizard/generate.ts +108 -4
  416. package/src/graph-wizard/steps.ts +15 -0
  417. package/src/grok/credential.ts +10 -3
  418. package/src/grounding/proactive-ground.ts +86 -0
  419. package/src/harness/control-inbox.ts +49 -1
  420. package/src/harness/harness-cli-command.ts +163 -35
  421. package/src/harness/harness-incidents.ts +85 -1
  422. package/src/harness/launch-utterance-ledger.ts +208 -0
  423. package/src/harness/pod-control-send.ts +33 -5
  424. package/src/harness/self-send-remote.ts +69 -0
  425. package/src/harness/self-send-routing-guard.ts +6 -0
  426. package/src/harness/self-send-target.ts +4 -3
  427. package/src/impl-discipline/detector.ts +16 -4
  428. package/src/impl-discipline/system-prompt.ts +11 -0
  429. package/src/impl-discipline/types.ts +2 -2
  430. package/src/index.ts +822 -154
  431. package/src/input-core/context-key-runtime.ts +21 -0
  432. package/src/intake-plane/already-built-hint.ts +4 -2
  433. package/src/intake-plane/requirement-funnel.ts +29 -1
  434. package/src/light-cli.ts +32 -11
  435. package/src/llm/opengateway-models.ts +11 -0
  436. package/src/llm/provider-credentials.ts +14 -0
  437. package/src/llm/provider-detect.ts +8 -1
  438. package/src/llm/runtime-model-family.ts +2 -1
  439. package/src/llm-wellformed.ts +70 -0
  440. package/src/llm.ts +247 -59
  441. package/src/loops/msg-wake.ts +35 -39
  442. package/src/loops/orchestrator/inbox.ts +59 -11
  443. package/src/loops/orchestrator/knowhow-pack.ts +364 -0
  444. package/src/loops/orchestrator/tick.ts +5 -1
  445. package/src/maturity/feature-maturity.ts +1 -1
  446. package/src/model-tier/llm-tier-map.ts +15 -1
  447. package/src/models/prompts.ts +17 -2
  448. package/src/msg/msg-post-office.ts +116 -0
  449. package/src/mss/logging/log-store.ts +79 -22
  450. package/src/native-tool-catalog.ts +15 -1
  451. package/src/nexus/api/decisions-route.ts +38 -18
  452. package/src/nexus/api/graph-wizard-api.ts +20 -2
  453. package/src/nexus/api/loop-resources.ts +13 -1
  454. package/src/nexus/boot/register-mcp-clients.ts +263 -38
  455. package/src/nexus/onboarding/first-boot-wizard.ts +56 -8
  456. package/src/oauth/codex.ts +7 -0
  457. package/src/onboarding/first-run.ts +37 -6
  458. package/src/onboarding/web-first.ts +43 -11
  459. package/src/ops/overview-collect.ts +30 -9
  460. package/src/ops/overview.ts +22 -9
  461. package/src/persona/loader.ts +11 -0
  462. package/src/persona/types.ts +8 -0
  463. package/src/pr-tool/census.ts +261 -27
  464. package/src/prompt-library/session-guidance.ts +14 -0
  465. package/src/provider-summary.ts +8 -0
  466. package/src/pty-shell/herdr-agent-report.ts +118 -9
  467. package/src/pty-shell/herdr-prompt.ts +266 -0
  468. package/src/pty-shell/pty-control-ipc.ts +151 -8
  469. package/src/pty-shell/pty-manifest.ts +7 -0
  470. package/src/pty-shell/pty-special-keys.ts +42 -2
  471. package/src/pty-shell/stale-install-check.ts +99 -0
  472. package/src/pty-shell/tui-run-state.ts +14 -2
  473. package/src/release-loop/auto-start.ts +20 -2
  474. package/src/release-loop/checklist.ts +100 -4
  475. package/src/release-loop/landed-but-yellow.ts +129 -5
  476. package/src/release-loop/light-rc.ts +1 -0
  477. package/src/release-loop/rehearsal.ts +37 -21
  478. package/src/repl/index.ts +192 -17
  479. package/src/repl/ops-msg-bridge.ts +32 -0
  480. package/src/seat-loop/knowhow-lint.ts +1 -1
  481. package/src/self-dev/ask-launch-flow.ts +44 -5
  482. package/src/self-dev/cli-help-text.ts +17 -0
  483. package/src/self-dev/decompose-proposal.ts +172 -20
  484. package/src/self-dev/decompose.ts +61 -0
  485. package/src/self-dev/dev-cli.ts +48 -12
  486. package/src/self-dev/dev-pipeline.ts +8 -2
  487. package/src/self-dev/draft-residue.ts +37 -1
  488. package/src/self-dev/draft-sweep.ts +137 -11
  489. package/src/self-dev/draft-triage-rules.ts +138 -0
  490. package/src/self-dev/fleet-reduce.ts +3 -2
  491. package/src/self-dev/glm-credential-guard.ts +77 -0
  492. package/src/self-dev/graph-front-nodes.ts +112 -0
  493. package/src/self-dev/graph-journey-nodes.ts +2 -0
  494. package/src/self-dev/graph-journey-route.ts +12 -2
  495. package/src/self-dev/harness-run-cli.ts +3 -15
  496. package/src/self-dev/orchestrate-cli-text.ts +10 -0
  497. package/src/self-dev/orchestrate-cli.ts +68 -3
  498. package/src/self-dev/orchestrate.ts +116 -17
  499. package/src/self-dev/review-provider-fallback.ts +35 -1
  500. package/src/self-dev/run-supervisor.ts +55 -2
  501. package/src/self-dev/run-types.ts +1 -1
  502. package/src/self-dev/self-orchestrate-runtime.ts +1 -11
  503. package/src/self-dev/shard-aggregate.ts +42 -5
  504. package/src/self-dev/shard-run.ts +8 -1
  505. package/src/self-health/autoheal.ts +153 -0
  506. package/src/self-health/signatures.ts +6 -0
  507. package/src/self-implement/blocked-draft-policy.ts +20 -0
  508. package/src/self-implement/classify-shadow.ts +3 -7
  509. package/src/self-implement/device-first.ts +116 -0
  510. package/src/self-implement/doctor-visit.ts +257 -2
  511. package/src/self-implement/evidence-command-budget.ts +80 -0
  512. package/src/self-implement/gate-baseline.ts +56 -17
  513. package/src/self-implement/gate-cli.ts +1 -0
  514. package/src/self-implement/gate-remote.ts +31 -20
  515. package/src/self-implement/goal-author-cli.ts +1 -0
  516. package/src/self-implement/goal-author-decompose.ts +534 -45
  517. package/src/self-implement/goal-author.ts +282 -7
  518. package/src/self-implement/goal-elaborate.ts +449 -0
  519. package/src/self-implement/goal-refine.ts +273 -0
  520. package/src/self-implement/graph-overlay-yaml.ts +14 -3
  521. package/src/self-implement/graph-variant.ts +40 -6
  522. package/src/self-implement/headless-elanous-driver.ts +19 -3
  523. package/src/self-implement/off-diff-evidence.ts +58 -6
  524. package/src/self-implement/orchestrator.ts +370 -62
  525. package/src/self-implement/pod-warm-pool-profile.ts +1 -0
  526. package/src/self-implement/pwa-import-graph.ts +1 -1
  527. package/src/self-implement/rework-budget-judgment.ts +5 -8
  528. package/src/self-implement/rework-policy.ts +30 -0
  529. package/src/self-implement/run-ledger.ts +108 -0
  530. package/src/self-implement/run-stop.ts +10 -1
  531. package/src/self-implement/run-ttl.ts +38 -24
  532. package/src/self-implement/running-runs.ts +29 -1
  533. package/src/self-implement/scope-adjacency.ts +115 -0
  534. package/src/self-implement/seams.ts +187 -28
  535. package/src/self-implement/stop-autoheal.ts +87 -1
  536. package/src/self-implement/wiring-check.ts +358 -0
  537. package/src/session-runtime/index.ts +1 -1
  538. package/src/setup/llm-env-detect.ts +5 -0
  539. package/src/shell-env-bootstrap.ts +11 -4
  540. package/src/skills/runner.ts +4 -2
  541. package/src/skills/tools/agent.ts +408 -40
  542. package/src/skills/tools/msg-ask.ts +100 -0
  543. package/src/skills/tools/ops-ledger.ts +2 -1
  544. package/src/skills/tools/schedule-wakeup.ts +23 -4
  545. package/src/skills/tools/shell.ts +61 -6
  546. package/src/skills/tools/terminal-modal-inject.ts +1 -2
  547. package/src/skills/tools/terminal-modal.ts +10 -8
  548. package/src/skills/url-router.ts +41 -1
  549. package/src/smart-wizard/run.ts +66 -0
  550. package/src/status/bar.ts +34 -6
  551. package/src/status/status-provider-info.ts +37 -6
  552. package/src/steward/hold-hygiene.ts +24 -6
  553. package/src/steward/rejudge-tick.ts +10 -2
  554. package/src/steward/ta-repair-event-collect.ts +17 -6
  555. package/src/steward/triage-budget.ts +194 -0
  556. package/src/steward/triage.ts +20 -3
  557. package/src/task-agent/actions.ts +72 -2
  558. package/src/task-agent/green-sweep.ts +4 -0
  559. package/src/task-agent/land-queue.ts +21 -8
  560. package/src/task-agent/live-moves.ts +182 -10
  561. package/src/task-agent/mission.ts +30 -0
  562. package/src/task-agent/parent-host.ts +123 -3
  563. package/src/task-agent/rejudge-on-head.ts +15 -0
  564. package/src/task-agent/repair-cycle.ts +138 -32
  565. package/src/task-agent/repair-next-move.ts +31 -3
  566. package/src/task-agent/repair-outcomes.ts +29 -0
  567. package/src/task-agent/repair-worker.ts +14 -4
  568. package/src/task-agent/shadow.ts +48 -4
  569. package/src/task-agent/task-card-prefix.ts +2 -0
  570. package/src/task-agent/task-hand.ts +525 -57
  571. package/src/task-agent/task-parent-role-llm.ts +36 -0
  572. package/src/task-agent/tier-split.ts +196 -0
  573. package/src/task-agent/work-order-build.ts +2 -0
  574. package/src/task-agent/work-order.ts +3 -2
  575. package/src/task-orchestrator/generator-prompt.ts +60 -11
  576. package/src/task-orchestrator/surfaces/pod-account-broker.ts +42 -0
  577. package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
  578. package/src/task-orchestrator/surfaces/pod-child-reuse.ts +146 -0
  579. package/src/task-orchestrator/surfaces/pod-command-job.ts +130 -11
  580. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +215 -3
  581. package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
  582. package/src/task-orchestrator/surfaces/pod-launch-history.ts +133 -0
  583. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
  584. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +19 -2
  585. package/src/task-orchestrator/surfaces/pod-pool.ts +76 -4
  586. package/src/task-orchestrator/surfaces/pod-provenance.ts +82 -0
  587. package/src/task-orchestrator/surfaces/pod-repair-commit.ts +18 -3
  588. package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +16 -0
  589. package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +224 -0
  590. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +201 -0
  591. package/src/task-orchestrator/surfaces/pod-si-warm-provider.ts +444 -0
  592. package/src/task-orchestrator/surfaces/pod-si-warm-runner.ts +387 -0
  593. package/src/task-orchestrator/surfaces/pod-si-warm-transport.ts +157 -0
  594. package/src/task-orchestrator/surfaces/pod-source-receive.ts +18 -0
  595. package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
  596. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +6 -2
  597. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +7 -0
  598. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +521 -40
  599. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +3 -0
  600. package/src/task-orchestrator/surfaces/self-implement-pod.ts +759 -50
  601. package/src/task-orchestrator/surfaces/self-implement.ts +65 -2
  602. package/src/tool-runtime/index.ts +15 -2
  603. package/src/tool-runtime/mcp-proxy-bootstrap.ts +29 -0
  604. package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
  605. package/src/tty-foreground.ts +155 -0
  606. package/src/tui/README.md +2 -0
  607. package/src/tui/chat/background-job-status.ts +54 -0
  608. package/src/tui/chat/goal-interim.ts +173 -0
  609. package/src/tui/chat/log-view.ts +267 -0
  610. package/src/tui/chat/self-health-status.ts +232 -0
  611. package/src/tui/entry.ts +695 -0
  612. package/src/tui/input/composer.ts +151 -0
  613. package/src/tui/seat-mail-boot.ts +59 -0
  614. package/src/tui/slash/compact-command.ts +7 -0
  615. package/src/tui/slash/compact.ts +94 -0
  616. package/src/tui/slash/new-session.ts +35 -0
  617. package/src/tui/slash/resume.ts +75 -0
  618. package/src/tui-client/local-chat-turn.ts +282 -0
  619. package/src/tui-client/local-harness-command.ts +63 -0
  620. package/src/tui-client/local-provider-command.ts +184 -0
  621. package/src/tui-client/next-dashboard-runtime.ts +8 -0
  622. package/src/tui-client/next-loop-command.ts +70 -0
  623. package/src/tui-client/next-wakeup.ts +191 -0
  624. package/src/tui.ts +37 -0
  625. package/src/ui/modal-adapter.ts +2 -2
  626. package/src/user-config.ts +4 -2
  627. package/src/ux-sim/classic-tui-seat-scenarios.ts +516 -0
  628. package/src/ux-sim/cli-config-audit-device.ts +121 -0
  629. package/src/ux-sim/dashboard-event-loop-stall-monitor-device.ts +238 -0
  630. package/src/ux-sim/event-monkey.ts +379 -0
  631. package/src/ux-sim/fake-bin.ts +87 -7
  632. package/src/ux-sim/fake-herdr.ts +238 -0
  633. package/src/ux-sim/fake-llm.ts +111 -6
  634. package/src/ux-sim/fault-glm-no-credential.ts +116 -0
  635. package/src/ux-sim/fault-nextmove-dispatch.ts +367 -0
  636. package/src/ux-sim/fault-pod-codex-503.ts +211 -0
  637. package/src/ux-sim/fault-scope-escape-lift.ts +216 -0
  638. package/src/ux-sim/fault-tui-400-autoheal.ts +297 -0
  639. package/src/ux-sim/goal-device.ts +619 -0
  640. package/src/ux-sim/in-process-cli.ts +22 -5
  641. package/src/ux-sim/mock-authoring-first-run-child.ts +35 -0
  642. package/src/ux-sim/mock-authoring-first-run.ts +97 -0
  643. package/src/ux-sim/mock-seat-pty-frame-child.ts +29 -0
  644. package/src/ux-sim/mock-seat-pty-frame.ts +297 -0
  645. package/src/ux-sim/mock-seat-pty-sequence-child.ts +21 -0
  646. package/src/ux-sim/mock-seat-pty-sequence.ts +206 -0
  647. package/src/ux-sim/next-tui-seat-scenarios.ts +631 -0
  648. package/src/ux-sim/onboarding-first-run-device.ts +269 -0
  649. package/src/ux-sim/pty-key-modifiers-device.ts +85 -0
  650. package/src/ux-sim/subagent-tools-device.ts +81 -0
  651. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +250 -0
  652. package/src/ux-sim/tty-foreground-steal-child.ts +21 -0
  653. package/src/version/packed-revision.json +1 -1
  654. package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +0 -79
  655. package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +0 -94
  658. package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +0 -23
  660. package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +0 -115
  662. package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +0 -8
  663. package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/2987-30cf9c2eb7b8bdd5.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/3001-5a52788c813b6113.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +0 -104
  681. package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +0 -286
  682. package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +0 -149
  683. package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +0 -148
  684. package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +0 -64
  685. package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +0 -74
  688. package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/5028-f0722e6114c313e7.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/5249.96a848656b582a93.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +0 -62
  695. package/apps/pwa/out/_next/static/chunks/5489.ec2dd1b5272a19dc.js +0 -24
  696. package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +0 -77
  708. package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +0 -90
  711. package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +0 -287
  717. package/apps/pwa/out/_next/static/chunks/7448.478958ffbbba0ac0.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +0 -27
  722. package/apps/pwa/out/_next/static/chunks/7952.b192c31b6a0e00cc.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +0 -36
  725. package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +0 -93
  738. package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +0 -24
  740. package/apps/pwa/out/_next/static/chunks/9739.8d5f36ac67a3b236.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-398c0faa173203f7.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/term/page-df3445b207ceceab.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +0 -122
  795. package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +0 -1
  802. /package/apps/pwa/out/_next/static/{L04y73dlwKeTW-GetaTF3 → uC-N0emedeNOFuaBQFv-I}/_ssgManifest.js +0 -0
@@ -14,9 +14,12 @@
14
14
  * 이미지는 표준판(elanous-harness)만 — 이 발사 경로는 lite 를 쓰지 않는다.
15
15
  */
16
16
  import { spawnSync } from 'node:child_process';
17
+ import { mkdtempSync, rmSync } from 'node:fs';
18
+ import { tmpdir } from 'node:os';
19
+ import { join } from 'node:path';
17
20
  import { SPAWN_SYNC_MAX_BUFFER } from '../../util/spawn-sync-output.js';
18
21
  import { debug } from '../../debug/log.js';
19
- import { memberHasRegistry, registryImageRef, type RemoteRun } from './pod-pool.js';
22
+ import { memberHasRegistry, registryImageRef, syncPoolImages, parsePodPool, type PodPoolMember, type RemoteRun } from './pod-pool.js';
20
23
 
21
24
  const POD_IMAGE = 'elanous-harness';
22
25
 
@@ -59,6 +62,91 @@ export function resolvePodImageSource(
59
62
  return { kind: 'pinned', ref: podImageRef(registry, commit), commit, registry };
60
63
  }
61
64
 
65
+ export interface PodShelfImage { readonly commit: string; readonly image: string; readonly action: 'fresh' | 'built' }
66
+
67
+ export function resolvePodShelfRef(ref: string, cwd = process.cwd(), exec = spawnSync): string {
68
+ const requested = ref.trim();
69
+ if (!requested || requested.startsWith('-') || /[\s\x00-\x1f]/u.test(requested)) throw new Error('pod shelf: invalid ref');
70
+ const spec = /^#?(\d+)$/u.exec(requested);
71
+ if (spec) {
72
+ const pr = exec('gh', ['pr', 'view', spec[1]!, '--json', 'headRefOid', '--jq', '.headRefOid'], { cwd, encoding: 'utf8', timeout: 30_000 });
73
+ const sha = String(pr.stdout ?? '').trim().toLowerCase();
74
+ if (pr.status !== 0 || !/^[0-9a-f]{40}$/u.test(sha)) throw new Error(`pod shelf: PR head unavailable: ${requested}`);
75
+ return sha;
76
+ }
77
+ const git = exec('git', ['rev-parse', '--verify', `${requested}^{commit}`], { cwd, encoding: 'utf8', timeout: 30_000 });
78
+ const sha = String(git.stdout ?? '').trim().toLowerCase();
79
+ if (git.status !== 0 || !/^[0-9a-f]{40}$/u.test(sha)) throw new Error(`pod shelf: ref unavailable: ${requested}`);
80
+ return sha;
81
+ }
82
+
83
+ /** Checkout only the requested commit; syncPoolImages retains its per-host build lock and SHA12 registry check. */
84
+ export async function putPodShelfImage(ref: string, pool: string, deps: {
85
+ resolve?: (ref: string) => string;
86
+ sync?: typeof syncPoolImages;
87
+ checkout?: (commit: string, dir: string) => void;
88
+ tempDir?: () => string;
89
+ remove?: (dir: string) => void;
90
+ hasRegistry?: (member: PodPoolMember) => boolean;
91
+ } = {}): Promise<PodShelfImage> {
92
+ const members = parsePodPool(pool);
93
+ if (members.length !== 1 || !members[0]!.sshHost) throw new Error('pod shelf: one remote registry pool member is required');
94
+ const member: PodPoolMember = members[0]!;
95
+ if (!(deps.hasRegistry ?? memberHasRegistry)(member)) throw new Error('pod shelf: remote registry unavailable');
96
+ const commit = (deps.resolve ?? resolvePodShelfRef)(ref);
97
+ if (!/^[0-9a-f]{40}$/u.test(commit)) throw new Error('pod shelf: full commit required');
98
+ const registry = member.registry ?? podImageRegistry();
99
+ const image = podImageRef(registry, commit);
100
+ if (!deps.sync && registryImageRef(member, commit) === image) return { commit, image, action: 'fresh' };
101
+ const dir = (deps.tempDir ?? (() => mkdtempSync(join(tmpdir(), 'pod-shelf-'))))();
102
+ try {
103
+ if (deps.checkout) deps.checkout(commit, dir);
104
+ else {
105
+ const clone = spawnSync('git', ['clone', '-q', '--no-checkout', process.cwd(), dir], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
106
+ if (clone.status !== 0) throw new Error(`pod shelf: clone failed: ${clone.stderr}`);
107
+ const fetch = spawnSync('git', ['-C', dir, 'fetch', '-q', 'origin', commit], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
108
+ if (fetch.status !== 0) {
109
+ const remote = spawnSync('git', ['remote', 'get-url', 'origin'], { encoding: 'utf8', timeout: 10_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
110
+ if (remote.status !== 0) throw new Error(`pod shelf: fetch failed: ${fetch.stderr}`);
111
+ const fromOrigin = spawnSync('git', ['-C', dir, 'fetch', '-q', String(remote.stdout).trim(), commit], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
112
+ if (fromOrigin.status !== 0) throw new Error(`pod shelf: fetch failed: ${fromOrigin.stderr}`);
113
+ }
114
+ const checkout = spawnSync('git', ['-C', dir, 'checkout', '--detach', commit], { encoding: 'utf8', timeout: 120_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
115
+ if (checkout.status !== 0) throw new Error(`pod shelf: checkout failed: ${checkout.stderr}`);
116
+ }
117
+ const sync = deps.sync ?? syncPoolImages;
118
+ const results = await sync([member], 'elanous-harness:local', commit, {
119
+ buildScript: join(dir, 'docker/harness/build.sh'),
120
+ ...(deps.sync ? {} : { ship: () => ({ ok: false, action: 'failed' as const, detail: 'shelf build failed; local image fallback prohibited' }) }),
121
+ remoteBuild: deps.sync ? undefined : async (host, cluster, registry) => {
122
+ const { spawn } = await import('node:child_process');
123
+ return new Promise((done) => {
124
+ const child = spawn('bash', [join(dir, 'docker/harness/build.sh')], { env: { ...process.env, ELANOUS_BUILD_REMOTE: host, ELANOUS_L2_CLUSTER: cluster, ...(registry ? { ELANOUS_BUILD_REGISTRY: registry } : {}) }, stdio: ['ignore', 'pipe', 'pipe'] });
125
+ let output = '';
126
+ child.stdout.on('data', (chunk) => { output += chunk; });
127
+ child.stderr.on('data', (chunk) => { output += chunk; });
128
+ child.on('close', (code) => done({ ok: code === 0, detail: output.slice(-300) }));
129
+ child.on('error', (error) => done({ ok: false, detail: error.message }));
130
+ });
131
+ },
132
+ });
133
+ const result = results.get(member.context);
134
+ if (!result?.ok || result.imageRef !== image) throw new Error(`pod shelf: image unavailable: ${result?.detail ?? image}`);
135
+ return { commit, image, action: result.action === 'fresh' ? 'fresh' : 'built' };
136
+ } finally { (deps.remove ?? ((path) => rmSync(path, { recursive: true, force: true })))(dir); }
137
+ }
138
+
139
+ export function listPodShelfImages(pool: string, run: RemoteRun): string[] {
140
+ const member = parsePodPool(pool)[0];
141
+ if (!member?.sshHost) throw new Error('pod shelf: remote pool member required');
142
+ const registry = member.registry ?? podImageRegistry();
143
+ const port = registry.slice(registry.lastIndexOf(':') + 1);
144
+ const result = run(member.sshHost, `curl -fsS --max-time 5 http://localhost:${port}/v2/elanous-harness/tags/list 2>/dev/null`);
145
+ if (result.status !== 0) throw new Error(`pod shelf: registry unavailable: ${result.stderr}`);
146
+ const tags: unknown = JSON.parse(result.stdout).tags;
147
+ return Array.isArray(tags) ? tags.filter((tag): tag is string => typeof tag === 'string' && /^[0-9a-f]{12}$/u.test(tag)).map((tag) => `${registry}/elanous-harness:${tag}`) : [];
148
+ }
149
+
62
150
  export function podImageMissingMessage(ref: string): string {
63
151
  return `기준 이미지 ${ref} 가 레지스트리에 없다 — 레일이 굽기 전이다`;
64
152
  }
@@ -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
+ }
@@ -236,6 +236,10 @@ export interface ExternalGitHubProbe {
236
236
  githubHttps: boolean | null;
237
237
  measuredAt: string | null;
238
238
  reason: string | null;
239
+ /** Name of the disposable Pod for matching this reading with its Kubernetes logs. */
240
+ podName?: string;
241
+ /** Unmodified stdout from `kubectl logs` for this Pod (only present when readable). */
242
+ podLog?: string;
239
243
  }
240
244
  const DNS_CACHE_MS = 10 * 60_000;
241
245
  const DNS_STALE_OK_MS = 30 * 60_000;
@@ -261,9 +265,11 @@ export function probePoolGitHub(context: string, kubectl: PoolKubectl = leaseKub
261
265
  if (typeof record?.at !== 'number' || now() < record.at || now() - record.at >= 60_000) return null;
262
266
  if (typeof record.measuredAt !== 'string' || ![true, false].includes(record.externalDns as boolean) ||
263
267
  ![true, false, null].includes(record.githubHttps as boolean | null) ||
264
- !(record.reason === null || typeof record.reason === 'string')) return null;
268
+ !(record.reason === null || typeof record.reason === 'string') ||
269
+ typeof record.podName !== 'string' || typeof record.podLog !== 'string') return null;
265
270
  return { externalDns: record.externalDns as boolean, githubHttps: record.githubHttps as boolean | null,
266
- measuredAt: record.measuredAt, reason: record.reason as string | null };
271
+ measuredAt: record.measuredAt, reason: record.reason as string | null,
272
+ podName: record.podName, podLog: record.podLog };
267
273
  } catch { return null; }
268
274
  };
269
275
  const fresh = cached();
@@ -285,6 +291,7 @@ export function probePoolGitHub(context: string, kubectl: PoolKubectl = leaseKub
285
291
  const shared = cached();
286
292
  if (shared) return shared;
287
293
  const result = runPoolGitHubProbe(context, kubectl, new Date(now()).toISOString());
294
+ debug.log('pod.lease', 'github-egress-probe', { context, ...result });
288
295
  if (result.measuredAt !== null) {
289
296
  const temp = `${cache}.${randomUUID()}.tmp`;
290
297
  try { writeFileSync(temp, JSON.stringify({ ...result, at: now() }), { mode: 0o600 }); renameSync(temp, cache); }
@@ -300,16 +307,18 @@ export function probePoolGitHub(context: string, kubectl: PoolKubectl = leaseKub
300
307
  function runPoolGitHubProbe(context: string, kubectl: PoolKubectl, measuredAt: string): ExternalGitHubProbe {
301
308
  const name = `elanous-egress-${randomUUID().slice(0, 12)}`;
302
309
  const base = ['--context', context, '--request-timeout=15s'];
303
- const unknown = (reason: string): ExternalGitHubProbe => ({ externalDns: null, githubHttps: null, measuredAt: null, reason });
304
310
  let created = false;
311
+ const unknown = (reason: string): ExternalGitHubProbe => ({ externalDns: null, githubHttps: null, measuredAt: null, reason,
312
+ ...(created ? { podName: name } : {}) });
305
313
  try {
306
314
  const manifest = JSON.stringify({ apiVersion: 'v1', kind: 'Pod', metadata: { name, namespace: 'elanous-test', labels: { 'elanous.probe': 'github-egress' } }, spec: {
307
315
  restartPolicy: 'Never', activeDeadlineSeconds: 35, automountServiceAccountToken: false,
308
316
  containers: [{ name: 'probe', image: 'busybox:1.36', command: ['sh', '-c',
309
- 'if nslookup github.com >/dev/null 2>&1; then echo EXTERNAL_DNS_OK; if wget -q -T 8 -O /dev/null https://github.com/; then echo GITHUB_HTTPS_OK; else echo GITHUB_HTTPS_FAILED; fi; else echo EXTERNAL_DNS_FAILED; fi'],
317
+ 'if nslookup github.com 2>&1; then echo EXTERNAL_DNS_OK; if wget -T 8 -O /dev/null https://github.com/ 2>&1; then echo GITHUB_HTTPS_OK; else echo GITHUB_HTTPS_FAILED; fi; else echo EXTERNAL_DNS_FAILED; fi'],
310
318
  resources: { requests: { cpu: '0', memory: '16Mi' }, limits: { cpu: '100m', memory: '64Mi' } } }],
311
319
  } });
312
- if (kubectl([...base, 'create', '-f', '-'], manifest).status !== 0) return unknown('probe create failed');
320
+ const createdPod = kubectl([...base, 'create', '-f', '-'], manifest);
321
+ if (createdPod.status !== 0) return unknown(`probe create failed${createdPod.stderr.trim() ? `: ${createdPod.stderr.trim().split('\n').pop()!.slice(0, 160)}` : ''}`);
313
322
  created = true;
314
323
  const waited = kubectl([...base, '-n', 'elanous-test', 'wait', '--for=jsonpath={.status.phase}=Succeeded', `pod/${name}`, '--timeout=25s']);
315
324
  const podResult = kubectl([...base, '-n', 'elanous-test', 'get', `pod/${name}`, '-o', 'json']);
@@ -327,10 +336,10 @@ function runPoolGitHubProbe(context: string, kubectl: PoolKubectl, measuredAt: s
327
336
  const httpsOk = markers.includes('GITHUB_HTTPS_OK');
328
337
  const httpsFail = markers.includes('GITHUB_HTTPS_FAILED');
329
338
  if (dnsFail && !dnsOk && !httpsOk && !httpsFail)
330
- return { externalDns: false, githubHttps: null, measuredAt, reason: 'external DNS failed' };
339
+ return { externalDns: false, githubHttps: null, measuredAt, reason: 'external DNS failed', podName: name, podLog: logs.stdout };
331
340
  if (dnsOk && !dnsFail && httpsOk !== httpsFail)
332
- return { externalDns: true, githubHttps: httpsOk, measuredAt, reason: httpsFail ? 'GitHub HTTPS failed' : null };
333
- return unknown(waited.status === 0 ? 'probe output unavailable' : 'probe timeout');
341
+ return { externalDns: true, githubHttps: httpsOk, measuredAt, reason: httpsFail ? 'GitHub HTTPS failed' : null, podName: name, podLog: logs.stdout };
342
+ return { ...unknown(waited.status === 0 ? 'probe output unavailable' : 'probe timeout'), podLog: logs.stdout };
334
343
  } catch { return unknown('probe failed'); }
335
344
  finally {
336
345
  if (created) try { kubectl([...base, '-n', 'elanous-test', 'delete', `pod/${name}`, '--ignore-not-found=true', '--wait=false']); }
@@ -1,11 +1,28 @@
1
1
  import { BUDGET_SNAPSHOT_ENV } from '../../execution-loop/launch-gate.js';
2
2
 
3
- // Preserve the manifest contract except for two values generated per launch.
3
+ /** The Pod push fence embeds a different six-hex run key in each independent launch. */
4
+ export function stablePodRunGuard(text: string): string {
5
+ return text.replace(/pr-create-r[0-9a-f]{6}-/g, 'pr-create-r<run>-')
6
+ .replace(/-r[0-9a-f]{6}(?=[-|*])/g, '-r<run>');
7
+ }
8
+
9
+ // Preserve the manifest contract except for the budget timestamp and run identities generated per launch.
4
10
  export function stablePodManifestText(applied: Array<Record<string, any>>): string {
5
11
  const manifests = structuredClone(applied.filter((entry) => entry.kind === 'Job' || entry.kind === 'Secret'));
6
12
  let snapshots = 0;
7
13
  for (const manifest of manifests) {
8
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
+ }
9
26
  for (const container of manifest.spec?.template?.spec?.containers ?? []) {
10
27
  for (const entry of container.env ?? []) {
11
28
  if (entry.name !== BUDGET_SNAPSHOT_ENV) continue;
@@ -19,5 +36,5 @@ export function stablePodManifestText(applied: Array<Record<string, any>>): stri
19
36
  }
20
37
  }
21
38
  if (snapshots === 0) throw new Error('manifest comparison requires a budget snapshot');
22
- return JSON.stringify(manifests).replace(/run-[0-9a-f-]{36}/g, 'run-<id>');
39
+ return stablePodRunGuard(JSON.stringify(manifests).replace(/run-[0-9a-f-]{36}/g, 'run-<id>'));
23
40
  }
@@ -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);
@@ -0,0 +1,82 @@
1
+ import { redactSecretText } from '../../debug/log.js';
2
+
3
+ /** The work that owns a Pod. Job metadata is the current view; pod.provenance events retain history. */
4
+ export interface PodProvenance {
5
+ actorKind: string;
6
+ actor: string;
7
+ kind: string;
8
+ run: string;
9
+ phase: string;
10
+ requestedAt: string;
11
+ character?: string;
12
+ launchHost?: string;
13
+ entrance?: string;
14
+ graphNode?: string;
15
+ cell?: string;
16
+ version?: string;
17
+ commit?: string;
18
+ shard?: string;
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;
22
+ pool?: string;
23
+ cpuReq?: string;
24
+ memReq?: string;
25
+ warmReused?: boolean;
26
+ argv?: string;
27
+ }
28
+
29
+ const required = ['actorKind', 'actor', 'kind', 'run', 'phase', 'requestedAt'] as const;
30
+ const names: Record<keyof PodProvenance, string> = {
31
+ actorKind: 'actor-kind', actor: 'actor', kind: 'kind', run: 'run', phase: 'phase', requestedAt: 'requested-at',
32
+ character: 'character', launchHost: 'launch-host', entrance: 'entrance', graphNode: 'graph-node', cell: 'cell',
33
+ version: 'version', commit: 'commit', shard: 'shard', reason: 'reason', parent: 'parent',
34
+ pool: 'pool', cpuReq: 'cpu-req', memReq: 'mem-req',
35
+ warmReused: 'warm-reused', argv: 'argv',
36
+ };
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
+
42
+ const labelValue = (value: string): string => {
43
+ const cleaned = value.toLowerCase().replace(/[^a-z0-9._-]/g, '-').replace(/^[^a-z0-9]+|[^a-z0-9]+$/g, '');
44
+ return cleaned.slice(0, 63).replace(/[^a-z0-9]+$/g, '') || 'unknown';
45
+ };
46
+
47
+ export interface PodProvenanceMetadata {
48
+ labels: Record<string, string>;
49
+ annotations: Record<string, string>;
50
+ env: Array<{ name: string; value: string }>;
51
+ missing: string[];
52
+ }
53
+
54
+ /** A gate reports missing identity as `unknown`; every other launch refuses it before kubectl apply. */
55
+ export function podProvenanceMetadata(input: Partial<PodProvenance> | undefined, gate = false): PodProvenanceMetadata {
56
+ const missing = required.filter((key) => typeof input?.[key] !== 'string' || !input?.[key]?.trim());
57
+ if (missing.length && !gate) throw new Error(`pod provenance missing: ${missing.map((key) => names[key]).join(', ')}`);
58
+ const values: Record<string, string> = {};
59
+ for (const [key, name] of Object.entries(names) as Array<[keyof PodProvenance, string]>) {
60
+ const raw = input?.[key];
61
+ if (raw === undefined || raw === null || raw === '') continue;
62
+ const value = String(raw).trim();
63
+ if (!value) continue;
64
+ // Metadata and env are observable by many users. Never carry a raw secret through an identity field.
65
+ const redacted = redactSecretText(value);
66
+ if (redacted !== value && key !== 'reason' && key !== 'argv') throw new Error(`pod provenance secret in ${name}`);
67
+ values[name] = redacted;
68
+ }
69
+ for (const key of missing) values[names[key]] = 'unknown';
70
+ // The launch reason is observable even when the caller cannot supply one.
71
+ values.reason ??= 'unknown';
72
+ const labels: Record<string, string> = {};
73
+ const annotations: Record<string, string> = {};
74
+ const env: Array<{ name: string; value: string }> = [];
75
+ for (const [name, value] of Object.entries(values)) {
76
+ const label = name === 'run' || name === 'commit' || name === 'parent' ? value.slice(0, 8) : value;
77
+ if (name !== 'reason' && name !== 'argv') labels[`elanous.ai/${name}`] = labelValue(label);
78
+ annotations[`elanous.ai/${name}`] = value;
79
+ env.push({ name: `ELANOUS_POD_${name.toUpperCase().replaceAll('-', '_')}`, value });
80
+ }
81
+ return { labels, annotations, env, missing: missing.map((key) => names[key]) };
82
+ }
@@ -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
+ }