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
@@ -27,7 +27,13 @@ export interface PartialPlan {
27
27
 
28
28
  /** G1: a second measurement of only the failed files on the very same release commit.
29
29
  * This is deliberately separate from PartialPlan, which compares two different commits. */
30
- export interface RecheckPlan extends PartialPlan { kind: 'recheck' }
30
+ export interface RecheckPlan extends PartialPlan {
31
+ kind: 'recheck';
32
+ /** Files from shards that could not produce a measurement; completed shard results remain in priorFailures/errors. */
33
+ stalledFiles?: string[];
34
+ /** Count of complete shards whose measurements are preserved in this recheck. */
35
+ preservedShardCount?: number;
36
+ }
31
37
 
32
38
  const FULL_SHA = /^[0-9a-f]{40}$/i;
33
39
  const RELEASE_VERSION = /^\d+\.\d+\.\d+(?:-(?:rc|alpha|beta)\.\d+)?$/;
@@ -92,13 +98,49 @@ function validateRecheckPlan(raw: Partial<RecheckPlan>, version: string, path: s
92
98
  typeof raw.forCommit !== 'string' || !FULL_SHA.test(raw.forCommit) || raw.priorCommit !== raw.forCommit ||
93
99
  !Array.isArray(raw.priorFailures) || !raw.priorFailures.every((id) => typeof id === 'string') ||
94
100
  !Array.isArray(raw.priorErrors) || !raw.priorErrors.every((id) => typeof id === 'string') ||
95
- !Array.isArray(raw.files) || !raw.files.length || !raw.files.every((file) => typeof file === 'string')) invalid();
101
+ !Array.isArray(raw.files) || !raw.files.length || !raw.files.every((file) => typeof file === 'string') ||
102
+ (raw.preservedShardCount !== undefined && (!Number.isSafeInteger(raw.preservedShardCount) || raw.preservedShardCount < 0))) invalid();
96
103
  let expected: string[] = [];
97
- try { expected = [...new Set([...raw.priorFailures!, ...raw.priorErrors!].map(testFileOfId))].sort(); }
104
+ try {
105
+ const measuredFiles = [...raw.priorFailures!, ...raw.priorErrors!].map(testFileOfId);
106
+ const stalledFiles = raw.stalledFiles === undefined ? [] : raw.stalledFiles;
107
+ if (!Array.isArray(stalledFiles) || !stalledFiles.every((file) => typeof file === 'string' && TEST_FILE.test(file) && !file.split('/').includes('..'))) invalid();
108
+ if (raw.stalledFiles !== undefined && stalledFiles.some((file) => measuredFiles.includes(file))) invalid();
109
+ expected = [...new Set(stalledFiles)].sort();
110
+ // Legacy plans recheck every prior failed file. Stalled plans re-run only files from incomplete shards; all
111
+ // completed shard outcomes, including runtime errors, are preserved for the combined verdict.
112
+ if (raw.stalledFiles === undefined) expected = [...new Set(measuredFiles)].sort();
113
+ }
98
114
  catch { invalid(); }
99
115
  if (JSON.stringify(raw.files) !== JSON.stringify(expected)) invalid();
100
116
  }
101
117
 
118
+ /** Plan a same-commit retry after a Pod sweep reports stalled shards. Reuse completed outcomes and rerun stalled files. */
119
+ export function planStalledShardRecheck(input: { version: string; measuredCommit: string; forCommit: string;
120
+ failures: readonly string[]; errors: readonly string[]; stalledFiles: readonly string[]; preservedShardCount?: number;
121
+ existsAtCommit: (file: string) => boolean }):
122
+ { ok: true; plan: RecheckPlan } | { ok: false; reason: string } {
123
+ if (!RELEASE_VERSION.test(input.version)) return { ok: false, reason: 'invalid release version' };
124
+ if (!FULL_SHA.test(input.measuredCommit) || !FULL_SHA.test(input.forCommit)) return { ok: false, reason: 'commit is not a full sha' };
125
+ if (input.measuredCommit !== input.forCommit) return { ok: false, reason: 'recheck requires the same commit' };
126
+ try { [...input.failures, ...input.errors].forEach(testFileOfId); }
127
+ catch (error) { return { ok: false, reason: String(error instanceof Error ? error.message : error) }; }
128
+ const stalledFiles = [...new Set(input.stalledFiles)].sort();
129
+ if (!stalledFiles.length) return { ok: false, reason: 'no stalled test files to recheck' };
130
+ if (stalledFiles.some((file) => !TEST_FILE.test(file) || file.split('/').includes('..'))) return { ok: false, reason: 'unsafe stalled test path' };
131
+ const measuredFiles = [...new Set([...input.failures, ...input.errors].map(testFileOfId))];
132
+ if (stalledFiles.some((file) => measuredFiles.includes(file)))
133
+ return { ok: false, reason: 'stalled file overlaps a completed shard result' };
134
+ const files = stalledFiles;
135
+ try {
136
+ const missing = files.find((file) => !input.existsAtCommit(file));
137
+ if (missing) return { ok: false, reason: `failed test file missing at commit: ${missing}` };
138
+ } catch (error) { return { ok: false, reason: `test file existence unreadable: ${String(error)}` }; }
139
+ return { ok: true, plan: { kind: 'recheck', version: input.version, priorCommit: input.measuredCommit,
140
+ forCommit: input.forCommit, files, stalledFiles, ...(input.preservedShardCount === undefined ? {} : { preservedShardCount: input.preservedShardCount }),
141
+ priorFailures: [...input.failures], priorErrors: [...input.errors] } };
142
+ }
143
+
102
144
  export const partialPlanPath = (root: string, version: string) => join(root, 'release', version, 'gate-partial.json');
103
145
  /** The same test-file set the gate sweep runs (`git ls-files` filtered by this suffix). */
104
146
  const TEST_FILE = /^(?:[\w.-]+\/)*[\w.-]+\.test\.(?:tsx?|jsx?|mts|cts)$/;
@@ -182,24 +224,32 @@ export function clearPartialPlan(root: string, version: string): void {
182
224
  }
183
225
 
184
226
  /** The plan for exactly this commit, or null. A malformed plan is an error (never silently a full or partial gate). */
185
- export function readPartialPlan(roots: readonly string[], version: string, commit: string): PartialPlan | null {
227
+ export function readPartialPlanResult(roots: readonly string[], version: string, commit: string):
228
+ { plan: PartialPlan | null; fallbackReason: string | null } {
229
+ let fallbackReason: string | null = 'no-applicable-plan';
186
230
  for (const root of roots) {
187
231
  const path = partialPlanPath(root, version);
188
232
  if (!existsSync(path)) continue;
189
233
  const raw = JSON.parse(readFileSync(path, 'utf8')) as Partial<PartialPlan>;
234
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error(`invalid gate partial plan: ${path}`);
190
235
  if ((raw as Partial<RecheckPlan>).kind !== undefined && (raw as Partial<RecheckPlan>).kind !== 'recheck' && raw.kind !== 'carry')
191
236
  throw new Error(`invalid gate partial plan: ${path}`);
192
- // Until the gate consumer connects G1, the opt-in recheck plan is a shadow record.
193
- // A legacy full gate may run, but it must never interpret a same-commit recheck as a changed-tip partial gate.
237
+ // Only a well-formed stalled-shard recheck for this exact release commit enters the same-commit consumer path.
194
238
  if ((raw as Partial<RecheckPlan>).kind === 'recheck') {
195
- validateRecheckPlan(raw as Partial<RecheckPlan>, version, path);
239
+ const recheck = raw as Partial<RecheckPlan>;
240
+ validateRecheckPlan(recheck, version, path);
241
+ if (recheck.forCommit === commit && recheck.stalledFiles !== undefined)
242
+ return { plan: recheck, fallbackReason: null };
243
+ if (recheck.forCommit === commit) { fallbackReason = 'recheck-not-stalled-only'; continue; }
244
+ fallbackReason = 'plan-commit-mismatch';
196
245
  continue;
197
246
  }
198
247
  if (raw.version !== version || typeof raw.priorCommit !== 'string' || !/^[0-9a-f]{40}$/i.test(raw.priorCommit)
199
248
  || typeof raw.forCommit !== 'string' || !/^[0-9a-f]{40}$/i.test(raw.forCommit) || raw.priorCommit === raw.forCommit
200
249
  || !Array.isArray(raw.files) || (raw.files.length === 0) !== (raw.kind === 'carry')
201
250
  || !raw.files.every((file) => typeof file === 'string' && TEST_FILE.test(file) && !file.split('/').includes('..'))
202
- || !Array.isArray(raw.priorFailures) || !Array.isArray(raw.priorErrors)) throw new Error(`invalid gate partial plan: ${path}`);
251
+ || !Array.isArray(raw.priorFailures) || !Array.isArray(raw.priorErrors))
252
+ throw new Error(`invalid gate partial plan: ${path}`);
203
253
  if (raw.kind === 'carry' && (raw.priorFailures.length || raw.priorErrors.length)) throw new Error(`invalid gate partial plan: ${path}`);
204
254
  // Every prior failure's file is re-run (planPartialRegate guarantees it) — a plan that would carry a failure it did
205
255
  // not re-run is malformed, not «partial».
@@ -208,10 +258,14 @@ export function readPartialPlan(roots: readonly string[], version: string, commi
208
258
  try { failureFiles = [...raw.priorFailures, ...raw.priorErrors].map((id) => testFileOfId(String(id))); }
209
259
  catch { throw new Error(`invalid gate partial plan: ${path}`); }
210
260
  if (failureFiles.some((file) => !rerun.has(file))) throw new Error(`invalid gate partial plan (prior failure not re-run): ${path}`);
211
- if (raw.forCommit !== commit) continue;
212
- return raw as PartialPlan;
261
+ if (raw.forCommit !== commit) { fallbackReason = 'plan-commit-mismatch'; continue; }
262
+ return { plan: raw as PartialPlan, fallbackReason: null };
213
263
  }
214
- return null;
264
+ return { plan: null, fallbackReason };
265
+ }
266
+
267
+ export function readPartialPlan(roots: readonly string[], version: string, commit: string): PartialPlan | null {
268
+ return readPartialPlanResult(roots, version, commit).plan;
215
269
  }
216
270
 
217
271
  /** Cut failures after a partial re-run: prior results for files not re-run ⊕ this run's results for the re-run files. */
@@ -0,0 +1,177 @@
1
+ /** A hard rehearsal's immutable gate evidence may select the next release's cut tests, but never authorizes a carry. */
2
+ import { spawnSync } from 'node:child_process';
3
+ import { existsSync, readFileSync, readdirSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { changedFilesBetween, planPartialRegate, testFileOfId, type PartialPlan } from './gate-partial.js';
6
+ import { CODE_FILE, gitClosureTree, testsReachingChanged } from './gate-closure.js';
7
+ import { versionOnlyBumps } from './gate-radius-shadow.js';
8
+ import { gateAssignableTestsAtCommit, gateBaselineReceipt, type GateBaselineReceipt } from './gate-baseline-receipt.js';
9
+ import { parsePodPool, remoteImageId } from '../../src/task-orchestrator/surfaces/pod-pool.js';
10
+ import { podCommandImageFor } from '../../src/task-orchestrator/surfaces/pod-command-job.js';
11
+ import { SPAWN_SYNC_MAX_BUFFER } from '../../src/util/spawn-sync-output.js';
12
+
13
+ const SHA = /^[0-9a-f]{40}$/i;
14
+ const DIGEST = /^sha256:[0-9a-f]{64}$/i;
15
+ const TEST = /\.test\.(?:tsx?|jsx?|mts|cts)$/;
16
+
17
+ export function hardRehearsalGateVersion(version: string, runId: string): string {
18
+ const id = /^hard-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i.exec(runId)?.[1];
19
+ if (!/^\d+\.\d+\.\d+$/.test(version) || !id) throw new Error('invalid hard rehearsal gate identity');
20
+ return `${version}-rc.${BigInt(`0x${id.replaceAll('-', '')}`).toString(10)}`;
21
+ }
22
+
23
+ export function hardRehearsalGateArgs(version: string, runId: string, commit: string, previous: string, pool: string): string[] {
24
+ return ['scripts/release-loop/gate-node.ts', '--commit', commit, '--version', hardRehearsalGateVersion(version, runId),
25
+ '--baseline-version', previous, '--executor', 'pod', '--pod-pool', pool, '--pod-shards', '12', '--rehearsal-baseline', '--json'];
26
+ }
27
+
28
+ export interface LiveRadiusDecision { plan: PartialPlan | null; reason: string; rehearsalRunId?: string }
29
+
30
+ /** Read the image ID on every candidate host before deciding. A later Job must still prove its actual image. */
31
+ export function preflightGateImageDigest(pool: string): string | null {
32
+ try {
33
+ const image = podCommandImageFor([], true);
34
+ const members = parsePodPool(pool);
35
+ if (!members.length) return null;
36
+ const ids = members.map((member) => {
37
+ if (member.sshHost) return remoteImageId(member, image);
38
+ const result = spawnSync('docker', ['image', 'inspect', image, '--format', '{{.Id}}'], { encoding: 'utf8', timeout: 30_000, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
39
+ return result.status === 0 ? result.stdout.trim() : null;
40
+ });
41
+ return ids.every((id) => id && DIGEST.test(id) && id === ids[0]) ? ids[0]! : null;
42
+ } catch { return null; }
43
+ }
44
+
45
+ /** The current sweep ID and exact root inventory prevent stale Pod logs from proving a new partial run's image. */
46
+ export function partialGateImagesMatch(root: string, version: string, digest: string, commit: string,
47
+ sweep: { id: string; shards: number; files: readonly string[] } | undefined): boolean {
48
+ if (!SHA.test(commit) || !sweep || !/^[0-9a-f-]{36}$/i.test(sweep.id)
49
+ || !Number.isSafeInteger(sweep.shards) || sweep.shards < 1) return false;
50
+ try {
51
+ const dir = join(root, 'release', version, 'gate-logs', 'cut-partial');
52
+ const names = readdirSync(dir).filter((name) => /^pod-\d+(?:-[\w-]+)?\.json$/.test(name));
53
+ const allRows = names.map((name) => ({ name, ...JSON.parse(readFileSync(join(dir, name), 'utf8')) as {
54
+ commit?: string; sweepId?: string; shardCount?: number; files?: unknown; imageDigest?: string;
55
+ attemptId?: string; parentAttempt?: string } }));
56
+ const rows = allRows.filter((row) => row.sweepId === sweep.id);
57
+ const roots = rows.filter((row) => /^pod-\d+\.json$/.test(row.name));
58
+ if (roots.length !== sweep.shards || roots.some((row) => row.shardCount !== sweep.shards
59
+ || row.commit !== commit || !Array.isArray(row.files) || !row.attemptId || row.imageDigest !== digest)) return false;
60
+ if (allRows.some((row) => /^pod-\d+\.json$/.test(row.name)
61
+ && row.commit === commit && row.sweepId !== sweep.id)) return false;
62
+ if (allRows.some((row) => row.commit === commit && !row.sweepId)) return false;
63
+ const indices = roots.map((row) => Number(/^pod-(\d+)\.json$/.exec(row.name)![1]));
64
+ if (new Set(indices).size !== sweep.shards || indices.some((index) => index < 0 || index >= sweep.shards)) return false;
65
+ const files = roots.flatMap((row) => row.files as string[]);
66
+ if (files.some((file) => typeof file !== 'string')
67
+ || JSON.stringify(files.sort()) !== JSON.stringify([...sweep.files].sort())) return false;
68
+ const attempts = new Set(roots.map((row) => row.attemptId));
69
+ let pending = allRows.filter((row) => !/^pod-\d+\.json$/.test(row.name));
70
+ for (let count = 0; pending.length && count < allRows.length; count++) {
71
+ const connected = pending.filter((row) => row.parentAttempt && attempts.has(row.parentAttempt));
72
+ if (!connected.length) break;
73
+ if (connected.some((row) => row.sweepId !== sweep.id || row.commit !== commit
74
+ || !row.attemptId || row.imageDigest !== digest)) return false;
75
+ for (const row of connected) attempts.add(row.attemptId);
76
+ pending = pending.filter((row) => !connected.includes(row));
77
+ }
78
+ return !pending.some((row) => row.sweepId === sweep.id || (row.commit === commit && !row.sweepId));
79
+ } catch { return false; }
80
+ }
81
+
82
+ /** Every missing or mismatched proof returns a full gate. The caller uses this only when no explicit resume plan exists. */
83
+ export function planHardRehearsalRadius(input: { root: string; repo: string; version: string; forCommit: string;
84
+ graphPins: { graphSha: string; recipeSha: string } | null; envFingerprint: string;
85
+ imageDigest: string | null }): LiveRadiusDecision {
86
+ const full = (reason: string): LiveRadiusDecision => ({ plan: null, reason });
87
+ if (!/^\d+\.\d+\.\d+$/.test(input.version) || !SHA.test(input.forCommit)) return full('invalid release identity');
88
+ if (!input.graphPins || !/^[0-9a-f]{64}$/i.test(input.envFingerprint) || !input.imageDigest || !DIGEST.test(input.imageDigest))
89
+ return full('current graph, environment or Pod image identity unmeasured');
90
+ try {
91
+ const stamps = ['hard-5h', 'hard-mid'].map((step) => {
92
+ const path = join(input.root, 'release', input.version, 'rehearsal', `${step}.json`);
93
+ if (!existsSync(path)) return null;
94
+ const stamp = JSON.parse(readFileSync(path, 'utf8')) as {
95
+ version?: string; step?: string; outcome?: string; sha?: string; endedAt?: string; hardGateRunId?: string;
96
+ hardGate?: { commit?: string; executor?: string; outcome?: string; introduced?: unknown[] };
97
+ };
98
+ return { step, stamp, ended: Date.parse(stamp.endedAt ?? '') };
99
+ }).filter((row): row is NonNullable<typeof row> => row !== null);
100
+ if (!stamps.length) return full('no clean hard rehearsal receipt');
101
+ if (stamps.some((row) => !Number.isFinite(row.ended))) return full('hard rehearsal completion time unmeasured');
102
+ stamps.sort((a, b) => b.ended - a.ended);
103
+ if (stamps.length > 1 && stamps[0]!.ended === stamps[1]!.ended) return full('hard rehearsal order ambiguous');
104
+ for (const { step, stamp } of stamps.slice(0, 1)) {
105
+ if (stamp.version !== input.version || stamp.step !== step || stamp.outcome !== 'ok' || !stamp.sha || !SHA.test(stamp.sha)
106
+ || stamp.hardGate?.outcome !== 'ok' || stamp.hardGate.commit !== stamp.sha || stamp.hardGate.executor !== 'pod'
107
+ || !Array.isArray(stamp.hardGate.introduced) || stamp.hardGate.introduced.length)
108
+ return full('latest hard rehearsal is not clean');
109
+ let gateVersion: string;
110
+ try { gateVersion = hardRehearsalGateVersion(input.version, stamp.hardGateRunId ?? ''); }
111
+ catch { return full('hard rehearsal run identity invalid'); }
112
+ const dir = join(input.root, 'release', gateVersion);
113
+ const verdict = JSON.parse(readFileSync(join(dir, 'gate-verdict.json'), 'utf8')) as {
114
+ commit?: string; outcome?: string; baselineReceipt?: GateBaselineReceipt };
115
+ const failures = JSON.parse(readFileSync(join(dir, 'gate-failures.json'), 'utf8')) as {
116
+ commit?: string; failures?: string[]; errors?: string[] };
117
+ const receipt = verdict.baselineReceipt;
118
+ if (verdict.commit !== stamp.sha || verdict.outcome !== 'ok' || failures.commit !== stamp.sha
119
+ || !Array.isArray(failures.failures) || failures.failures.length !== 0
120
+ || !Array.isArray(failures.errors) || failures.errors.length !== 0
121
+ || !receipt || receipt.schema !== 1 || !receipt.valid || receipt.version !== gateVersion || receipt.commit !== stamp.sha
122
+ || receipt.graphSha !== input.graphPins.graphSha || receipt.recipeSha !== input.graphPins.recipeSha
123
+ || receipt.envFingerprint !== input.envFingerprint || receipt.imageDigest !== input.imageDigest.toLowerCase()
124
+ || !Number.isSafeInteger(receipt.files) || receipt.files < 1 || !Number.isSafeInteger(receipt.shards) || receipt.shards < 1)
125
+ return full('hard rehearsal receipt or current execution identity differs');
126
+ const recomputed = gateBaselineReceipt({ root: input.root, version: gateVersion, commit: stamp.sha,
127
+ fullSweep: true, graphPins: input.graphPins, envFingerprint: input.envFingerprint });
128
+ if (!recomputed.valid || recomputed.imageDigest !== receipt.imageDigest || recomputed.files !== receipt.files
129
+ || recomputed.shards !== receipt.shards) return full(`hard rehearsal Pod proof differs: ${recomputed.reason}`);
130
+ const ancestor = spawnSync('git', ['merge-base', '--is-ancestor', stamp.sha, input.forCommit], { cwd: input.repo, maxBuffer: SPAWN_SYNC_MAX_BUFFER });
131
+ if (ancestor.status !== 0 || ancestor.error) return full('hard rehearsal commit is not an ancestor');
132
+ const expectedFiles = gateAssignableTestsAtCommit(input.repo, stamp.sha);
133
+ const measuredFiles = readdirSync(join(dir, 'gate-logs', 'cut')).filter((name) => /^pod-\d+\.json$/.test(name))
134
+ .flatMap((name) => {
135
+ const row = JSON.parse(readFileSync(join(dir, 'gate-logs', 'cut', name), 'utf8')) as { files?: unknown };
136
+ return Array.isArray(row.files) ? row.files : [];
137
+ });
138
+ if (!expectedFiles || JSON.stringify(measuredFiles.sort()) !== JSON.stringify(expectedFiles)
139
+ || measuredFiles.length !== receipt.files)
140
+ return full('hard rehearsal file inventory differs from receipt');
141
+ const tree = gitClosureTree(input.repo, input.forCommit);
142
+ const tests = tree.files.filter((file) => TEST.test(file));
143
+ const changed = changedFilesBetween(input.repo, stamp.sha, input.forCommit);
144
+ const bumps = versionOnlyBumps(input.repo, stamp.sha, input.forCommit, input.version, changed);
145
+ const effective = changed.filter((file) => !bumps.includes(file));
146
+ // A version-only JSON/lock bump is still observable to tests that read it. Follow those literal readers and
147
+ // opaque tests before removing the bump from the ordinary code-only partial planner.
148
+ const versionEnvReaders = bumps.includes('package.json')
149
+ ? tree.files.filter((file) => CODE_FILE.test(file) && tree.read(file)?.includes('npm_package_version')) : [];
150
+ const bumpRadius = bumps.length ? testsReachingChanged(tree, [...bumps, ...versionEnvReaders], tests) : null;
151
+ if (bumpRadius && !bumpRadius.ok) return full(bumpRadius.reason);
152
+ const planned = planPartialRegate({ version: input.version, priorCommit: stamp.sha, forCommit: input.forCommit,
153
+ changedFiles: effective, priorFailures: failures.failures, priorErrors: failures.errors ?? [],
154
+ existsAtTip: (file) => tree.files.includes(file),
155
+ closure: (code) => testsReachingChanged(tree, code, tests) });
156
+ if (!planned.ok && effective.length) return full(planned.reason);
157
+ let fileSet: string[];
158
+ let base: PartialPlan;
159
+ if (planned.ok) {
160
+ if (planned.plan.kind === 'carry' && !bumpRadius?.ok) return full('docs-only carry requires full gate across releases');
161
+ base = planned.plan.kind === 'carry' ? { ...planned.plan, kind: undefined } : planned.plan;
162
+ fileSet = planned.plan.files;
163
+ } else {
164
+ let priorFiles: string[];
165
+ try { priorFiles = [...failures.failures, ...(failures.errors ?? [])].map(testFileOfId); }
166
+ catch { return full('hard rehearsal failure ids unreadable'); }
167
+ base = { version: input.version, priorCommit: stamp.sha, forCommit: input.forCommit,
168
+ files: [], priorFailures: failures.failures, priorErrors: failures.errors ?? [] };
169
+ fileSet = priorFiles;
170
+ }
171
+ const files = [...new Set([...fileSet, ...(bumpRadius?.ok ? bumpRadius.tests : [])])].sort();
172
+ if (!files.length || files.some((file) => !tests.includes(file))) return full('empty or missing rehearsal radius requires full gate');
173
+ return { plan: { ...base, files }, reason: 'hard rehearsal receipt and import radius verified', rehearsalRunId: stamp.hardGateRunId };
174
+ }
175
+ return full('no clean hard rehearsal receipt');
176
+ } catch (error) { return full(`hard rehearsal evidence unreadable: ${String(error)}`); }
177
+ }
@@ -38,7 +38,7 @@ function blob(repo: string, commit: string, file: string): unknown {
38
38
  }
39
39
 
40
40
  /** Remove only the fields version-node itself changes; any other JSON difference leaves a full shadow plan. */
41
- function versionOnlyBumps(repo: string, from: string, to: string, version: string, changed: readonly string[]): string[] {
41
+ export function versionOnlyBumps(repo: string, from: string, to: string, version: string, changed: readonly string[]): string[] {
42
42
  if (!changed.includes('package.json')) return [];
43
43
  const prior = blob(repo, from, 'package.json') as Record<string, unknown>;
44
44
  const next = blob(repo, to, 'package.json') as Record<string, unknown>;
@@ -9,6 +9,7 @@ export type NodeVerdict = 'pass' | 'flaky' | 'fail';
9
9
  export interface GraphContext {
10
10
  nodeId?: string;
11
11
  runId?: string;
12
+ startedAt?: string;
12
13
  input: { version: string; previousVersion: string; [key: string]: unknown };
13
14
  outputs: Record<string, Record<string, unknown>>;
14
15
  }
@@ -24,6 +25,7 @@ export function readGraphContext(env: NodeJS.ProcessEnv = process.env): GraphCon
24
25
  || typeof input.previousVersion !== 'string' || !/^\d+\.\d+\.\d+$/.test(input.previousVersion)) throw new Error('version and previousVersion required');
25
26
  return { ...(typeof context.nodeId === 'string' ? { nodeId: context.nodeId } : {}),
26
27
  ...(typeof context.runId === 'string' ? { runId: context.runId } : {}),
28
+ ...(typeof context.startedAt === 'string' ? { startedAt: context.startedAt } : {}),
27
29
  input: input as GraphContext['input'], outputs: context.outputs && typeof context.outputs === 'object' ? context.outputs as GraphContext['outputs'] : {} };
28
30
  }
29
31
 
@@ -72,6 +74,17 @@ export function cutoffNotesEmpty(data: Record<string, unknown> | undefined): boo
72
74
  return Array.isArray(data?.escalate) && (data.escalate as Array<{ kind?: string }>).some((item) => item?.kind === 'notes-empty');
73
75
  }
74
76
 
77
+ /**
78
+ * RELEASE-PWA-NODE-RESILIENCE ① — the pwa node's argv. `release.loop.pwaRemote` (copied into the run input) picks
79
+ * the SSH host the suite runs on; absent = this machine (today's argv, byte-identical). One setting, like `gateRemote`.
80
+ */
81
+ export function pwaNodeArgs(commit: string, input: Record<string, unknown>): string[] {
82
+ const remote = input.pwaRemote;
83
+ if (remote !== undefined && (typeof remote !== 'string' || !remote.trim())) throw new Error(`release.loop.pwaRemote must be an ssh host: ${String(remote)}`);
84
+ return ['scripts/release-loop/pwa-scenarios-node.ts', '--commit', commit, '--with-costly', '--json',
85
+ ...(typeof remote === 'string' ? ['--remote', remote.trim()] : [])];
86
+ }
87
+
75
88
  // Existing cutoff/PWA/TUI programs have different output conventions; normalize them at the graph boundary.
76
89
  if (import.meta.main) {
77
90
  const node = process.argv[2];
@@ -84,7 +97,7 @@ if (import.meta.main) {
84
97
  const predecessor = node === 'pwa' ? 'gate' : node === 'tui' ? 'upgrade' : 'version-release';
85
98
  if (context.outputs[predecessor]?.outcome !== 'ok') throw new Error(`${predecessor} did not pass`);
86
99
  const args = node === 'cutoff' ? ['scripts/release-loop/cutoff.ts', '--version', version, '--cutoff', commit, '--baseline', `v${context.input.previousVersion}`, '--json']
87
- : node === 'pwa' ? ['scripts/release-loop/pwa-scenarios-node.ts', '--commit', commit, '--with-costly', '--json']
100
+ : node === 'pwa' ? pwaNodeArgs(commit, context.input)
88
101
  : node === 'tui' ? ['scripts/release-loop/tui-sim-node.ts', '--commit', commit, '--json'] : (() => { throw new Error(`unknown node: ${node}`); })();
89
102
  const run = runCommand('bun', args);
90
103
  if (run.stderr) process.stderr.write(run.stderr);
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env bun
2
2
  import { spawnSync } from 'node:child_process';
3
- import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
4
4
  import { tmpdir } from 'node:os';
5
- import { join } from 'node:path';
5
+ import { basename, dirname, join, resolve } from 'node:path';
6
6
  import { debug } from '../../src/debug/log.js';
7
7
  import { sendOutbound } from '../../src/domains/outbound-alert.js';
8
8
  import { effectiveInstanceRoot, prodInstanceRoot } from '../../src/instance/resolve.js';
@@ -10,8 +10,11 @@ import { emitNodeResult, readGraphContext, type GraphContext } from './node-verd
10
10
  import { prereleaseKind } from './release-version.js';
11
11
 
12
12
  type Result = { outcome: 'ok' | 'fail'; verdict: 'pass' | 'fail'; summary: string; npm?: 'published' | 'already-published' | 'staged-not-visible'; humanAction?: 'npm-support' };
13
- type Exec = (command: string, args: string[], env?: NodeJS.ProcessEnv) => { status: number | null; stdout: string; stderr: string };
13
+ type ExecResult = { status: number | null; stdout: string; stderr: string; durationMs?: number; signal?: NodeJS.Signals | null };
14
+ type Exec = (command: string, args: string[], env?: NodeJS.ProcessEnv) => ExecResult;
14
15
  type Registry = (url: string) => Promise<{ status: number; body: unknown }>;
16
+ const REGISTRY_FETCH_TIMEOUT_MS = 15_000;
17
+ type PublishSpawn = { version: string; durationMs: number; status: number | null; signal: NodeJS.Signals | null };
15
18
  export interface NpmPublishDeps {
16
19
  exec?: Exec;
17
20
  registry?: Registry;
@@ -21,16 +24,27 @@ export interface NpmPublishDeps {
21
24
  productionRoot?: string;
22
25
  alert?: (text: string, kind: string) => boolean;
23
26
  log?: (version: string, waitedMinutes: number) => void;
27
+ publishSpawn?: (event: PublishSpawn) => void;
24
28
  }
25
29
 
26
30
  const exec: Exec = (command, args, env) => {
31
+ const startedAt = performance.now();
27
32
  const result = spawnSync(command, args, { encoding: 'utf8', env: env ?? process.env, maxBuffer: 1024 * 1024, timeout: 300_000 });
28
- return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? String(result.error ?? '') };
29
- };
30
- const registry: Registry = async (url) => {
31
- const response = await fetch(url, { headers: { accept: 'application/json' }, signal: AbortSignal.timeout(15_000) });
32
- return { status: response.status, body: response.ok ? await response.json() : null };
33
+ return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? String(result.error ?? ''), durationMs: Math.ceil(performance.now() - startedAt), signal: result.signal };
33
34
  };
35
+ export async function fetchNpmRegistry(url: string, timeoutMs = REGISTRY_FETCH_TIMEOUT_MS): Promise<{ status: number; body: unknown }> {
36
+ const timeout = AbortSignal.timeout(timeoutMs);
37
+ let response: Response;
38
+ try {
39
+ response = await fetch(url, { headers: { accept: 'application/json' }, signal: timeout });
40
+ return { status: response.status, body: response.ok ? await response.json() : null };
41
+ }
42
+ catch (error) {
43
+ if (timeout.aborted) throw Object.assign(new Error(`registry request exceeded ${timeoutMs}ms`), { name: 'NpmRegistryFetchTimeoutError', timeoutMs });
44
+ throw error;
45
+ }
46
+ }
47
+ const registry: Registry = fetchNpmRegistry;
34
48
  const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));
35
49
  const PACKAGE_URL = 'https://registry.npmjs.org/elanous';
36
50
 
@@ -44,6 +58,33 @@ function metadata(value: unknown): { name?: string; version?: string } {
44
58
  if (!value || typeof value !== 'object') return {};
45
59
  return value as { name?: string; version?: string };
46
60
  }
61
+ function registryFailure(error: unknown, url: string): Error {
62
+ const name = error instanceof Error ? error.name : '';
63
+ const message = error instanceof Error ? error.message : String(error);
64
+ const endpoint = (() => { try { return new URL(url).pathname; } catch { return url; } })();
65
+ if (name === 'NpmRegistryFetchTimeoutError') {
66
+ const timeoutMs = error && typeof error === 'object' && 'timeoutMs' in error && typeof error.timeoutMs === 'number' ? error.timeoutMs : REGISTRY_FETCH_TIMEOUT_MS;
67
+ return new Error(`npm registry fetch timeout after ${timeoutMs}ms (${endpoint || '/'})`);
68
+ }
69
+ return new Error(`npm registry fetch failed (${endpoint || '/'}): ${message}`);
70
+ }
71
+ function publishLogDirectory(context: GraphContext, stateDir: string): string {
72
+ const contextLocation = process.env.ELANOUS_GRAPH_CONTEXT;
73
+ if (contextLocation && !contextLocation.trimStart().startsWith('{')) {
74
+ const contextPath = resolve(contextLocation);
75
+ const runDirectory = dirname(contextPath);
76
+ const runDirectoryName = basename(runDirectory);
77
+ if (basename(contextPath).endsWith('.json') && runDirectoryName.endsWith('.json.contexts')) {
78
+ const pathRunId = runDirectoryName.slice(0, -'.json.contexts'.length);
79
+ if (context.runId && pathRunId !== context.runId) throw new Error('npm publish graph context runId/path mismatch');
80
+ return join(runDirectory, 'npm-publish');
81
+ }
82
+ }
83
+ if (context.runId && /^[a-zA-Z0-9._-]+$/.test(context.runId))
84
+ return join(stateDir, 'graph-runs', 'release-loop', `${context.runId}.json.contexts`, 'npm-publish');
85
+ // Direct non-graph calls have no run folder; retain compatibility in their version output directory.
86
+ return join(stateDir, 'release', context.input.version, 'npm-publish');
87
+ }
47
88
 
48
89
  export async function runNpmPublish(context: GraphContext = readGraphContext(), deps: NpmPublishDeps = {}): Promise<Result> {
49
90
  const version = context.input.version;
@@ -68,9 +109,16 @@ export async function runNpmPublish(context: GraphContext = readGraphContext(),
68
109
  const pkg = metadata(JSON.parse(archive.stdout));
69
110
  if (pkg.name !== 'elanous' || pkg.version !== version) throw new Error('npm archive package name/version mismatch');
70
111
  const inspect = async (): Promise<{ visible: boolean; tagged: boolean }> => {
71
- const [manifest, tags] = await Promise.all([readRegistry(`${PACKAGE_URL}/${version}`), readRegistry(PACKAGE_URL)]);
72
- if (manifest.status !== 200 && manifest.status !== 404) throw new Error(`npm registry version lookup failed (${manifest.status})`);
73
- if (tags.status !== 200) throw new Error(`npm registry tags lookup failed (${tags.status})`);
112
+ const versionUrl = `${PACKAGE_URL}/${version}`;
113
+ const tagsUrl = PACKAGE_URL;
114
+ let manifest: { status: number; body: unknown };
115
+ let tags: { status: number; body: unknown };
116
+ const read = (url: string) => readRegistry(url).catch((error: unknown) => { throw registryFailure(error, url); });
117
+ [manifest, tags] = await Promise.all([read(versionUrl), read(tagsUrl)]);
118
+ if (manifest.status !== 200 && manifest.status !== 404)
119
+ throw new Error(`npm registry version lookup failed (${manifest.status}; ${new URL(versionUrl).pathname})`);
120
+ if (tags.status !== 200)
121
+ throw new Error(`npm registry tags lookup failed (${tags.status}; ${new URL(tagsUrl).pathname})`);
74
122
  const tagged = tags.body && typeof tags.body === 'object' && 'dist-tags' in tags.body
75
123
  ? (tags.body as { 'dist-tags'?: Record<string, unknown> })['dist-tags']?.[distTag] : undefined;
76
124
  if (manifest.status === 200 && (metadata(manifest.body).name !== 'elanous' || metadata(manifest.body).version !== version))
@@ -90,7 +138,13 @@ export async function runNpmPublish(context: GraphContext = readGraphContext(),
90
138
  try {
91
139
  const npmrc = join(dir, 'npmrc');
92
140
  writeFileSync(npmrc, `//registry.npmjs.org/:_authToken=${token}\n`, { mode: 0o600, flag: 'wx' });
93
- published = run('npm', ['publish', candidate, '--ignore-scripts', '--tag', distTag, '--access', 'public'], { ...process.env, NPM_CONFIG_USERCONFIG: npmrc });
141
+ const logDir = publishLogDirectory(context, stateDir);
142
+ mkdirSync(logDir, { recursive: true, mode: 0o700 });
143
+ chmodSync(logDir, 0o700);
144
+ const publishStartedAt = performance.now();
145
+ published = run('npm', ['publish', candidate, '--ignore-scripts', '--tag', distTag, '--access', 'public', '--logs-dir', logDir], { ...process.env, NPM_CONFIG_USERCONFIG: npmrc });
146
+ const durationMs = published.durationMs ?? Math.ceil(performance.now() - publishStartedAt);
147
+ try { (deps.publishSpawn ?? ((event) => debug.log('release-loop.npm', 'publish-spawn', event)))({ version, durationMs, status: published.status, signal: published.signal ?? null }); } catch { /* telemetry must not mask publish result */ }
94
148
  } finally { rmSync(dir, { recursive: true, force: true }); }
95
149
  const output = `${published.stdout}\n${published.stderr}`;
96
150
  const staged = published.status !== 0 && /\bE409\b/i.test(output) && /previously staged/i.test(output);
@@ -20,6 +20,8 @@ function option(name: string, fallback?: string): string {
20
20
  }
21
21
 
22
22
  async function main(): Promise<void> {
23
+ const actor = process.env.ELANOUS_SEAT?.trim() || process.env.USER?.trim() || process.env.LOGNAME?.trim();
24
+ if (!actor) throw new Error('pod provenance actor missing: ELANOUS_SEAT or USER/LOGNAME required');
23
25
  const context = option('context');
24
26
  const host = option('host');
25
27
  const cluster = option('cluster', 'elanous-pool');
@@ -51,6 +53,9 @@ async function main(): Promise<void> {
51
53
  let completed = false;
52
54
  try {
53
55
  const result = await runPodCommand({
56
+ provenance: { actorKind: process.env.ELANOUS_SEAT?.trim() ? 'seat' : 'human', actor, character: 'host-dirs-probe',
57
+ entrance: 'probe', kind: 'probe', run: name, phase: 'exec', requestedAt: new Date().toISOString(),
58
+ reason: `host directory probe ${arm}` },
54
59
  command: ['sh', '-c', 'printf cache-ok > /bun-cache/.host-dir-probe && printf slots-ok > /gate-install-slots/.host-dir-probe && test "$(cat /bun-cache/.host-dir-probe)" = cache-ok && test "$(cat /gate-install-slots/.host-dir-probe)" = slots-ok && rm /bun-cache/.host-dir-probe /gate-install-slots/.host-dir-probe && echo HOST_DIRS_WRITTEN'],
55
60
  name,
56
61
  namespace, image, imageCommit: null, deadlineSeconds: 120, pollMs: 1_000, statusUnreadableMs: 30_000,