elanous 0.2.40 → 0.2.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (685) hide show
  1. package/README.md +7 -7
  2. package/apps/pwa/out/404/index.html +1 -1
  3. package/apps/pwa/out/404.html +1 -1
  4. package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → X1ucLw10Cds_h614NoEnh}/_buildManifest.js +1 -1
  5. package/apps/pwa/out/_next/static/chunks/0244e5b5.6fc7670f8223d82d.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/{4769.9fd582071301f382.js → 1063.2fb8a9dc55c731f2.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +36 -0
  8. package/apps/pwa/out/_next/static/chunks/1147-5196d19c222051b3.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{470.51a72a2348306455.js → 1262.e804feb8fd1acb8c.js} +2 -2
  10. package/apps/pwa/out/_next/static/chunks/1319.b9b815ae0f181e06.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/{7219-15bdd9a80661af8e.js → 1455-530ca16c7e71baff.js} +1 -1
  13. package/apps/pwa/out/_next/static/chunks/{1281.d81877e35b9068f4.js → 1487.2f67b79444062da6.js} +1 -1
  14. package/apps/pwa/out/_next/static/chunks/1574.878c18ecc97b1bd4.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +32 -0
  16. package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1945.7b54990d578c119b.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +286 -0
  22. package/apps/pwa/out/_next/static/chunks/2160.a097e7b138ae1c55.js +23 -0
  23. package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +34 -0
  26. package/apps/pwa/out/_next/static/chunks/{1350.59f40e39e02d91b1.js → 2456.b6de0e1c05f28843.js} +1 -1
  27. package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2690.0521c738b7749931.js +115 -0
  32. package/apps/pwa/out/_next/static/chunks/{5436.fdf6fa8ae3e9588d.js → 2974.595d1e29d040cb6a.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/{5383.bdfa5d886e39a826.js → 3207.a756c95e9ec8c3c8.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +93 -0
  35. package/apps/pwa/out/_next/static/chunks/{2177.df8547f9d7215c4e.js → 3347.f846266b5e5f3ede.js} +3 -3
  36. package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +41 -0
  37. package/apps/pwa/out/_next/static/chunks/{9184.45afbf44fec87574.js → 3482.a9ae9d2ad6a5bd97.js} +1 -1
  38. package/apps/pwa/out/_next/static/chunks/3507.97e1977bc4d5fb0a.js +2 -0
  39. package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +24 -0
  41. package/apps/pwa/out/_next/static/chunks/{8099.1cccf31c1baa7e1c.js → 3741.9cf76acaa2ee5298.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{4864a2ca.1c1c280a7772c5e5.js → 3d0154af.5331fec737ffe8c3.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4043.6b91203436c9c86b.js +309 -0
  48. package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +77 -0
  49. package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/{3330.7443183b7e6fdbdf.js → 4276.336d76d858fcdf1b.js} +1 -1
  51. package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4320.583cbab64db6be02.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4770.769c9cd9c7034eba.js +148 -0
  55. package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +74 -0
  56. package/apps/pwa/out/_next/static/chunks/{3b355b3d.6f73c98bf6f9c749.js → 50061469.0326382241ef3b2d.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +149 -0
  58. package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +27 -0
  60. package/apps/pwa/out/_next/static/chunks/{8d173e38.18a2f7b4e1848bdb.js → 53c73f84.373b6160adfa89a4.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{1537-6bb97b5214928ea9.js → 5431-72a1dbde59400691.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5440-4236de26c5ea5856.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/5885.0a3e52c8faccec98.js +287 -0
  70. package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/{261.0d471e8aded799f3.js → 6131.348b7d6bdcd267ce.js} +3 -3
  73. package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +90 -0
  74. package/apps/pwa/out/_next/static/chunks/{9175.2de5209a5ce6f68a.js → 6377.bc7df239edbff244.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{2226.2cf61ec781827219.js → 6632.0eac1c554f8f2ef3.js} +2 -2
  78. package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +104 -0
  82. package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +94 -0
  83. package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/{b84cad00.594027ebe0531fe2.js → 73d2eb0e.4966ad55293c801a.js} +3 -3
  90. package/apps/pwa/out/_next/static/chunks/{6257.c0037b8949239f5e.js → 7411.9b4b8b747dc7b802.js} +2 -2
  91. package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +24 -0
  92. package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/{9189505a.980427ac048c8c60.js → 7a98bc80.fa935989e829f9c2.js} +1 -1
  98. package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8138.6c10b2a356d52fca.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/{2566.beaffc3a5e1fcd2e.js → 8262.ddc03e06b733f184.js} +1 -1
  101. package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +8 -0
  103. package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8505.fd803c6c33b54cc3.js +79 -0
  105. package/apps/pwa/out/_next/static/chunks/{8272-025653884f9645d2.js → 8546-6f03f8ea34dd61d9.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/{6051-0ae955eedb10adb9.js → 8673-bab689a55f7e13b9.js} +3 -3
  107. package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/9211-330b6736a63d4cb3.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{4351.0f37a6db2b34d50b.js → 9249.976f1e69a9d80754.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9415.69e4a21c60c7d2db.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{6749.0744ce6eb08d40e9.js → 9427.96aa912ddb5801e0.js} +16 -16
  119. package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{7611.85f045bf232053ac.js → 9633.ce5bddc56784da72.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/{3746-f80a78f220bf37b5.js → 9656-374232558fd528d0.js} +1 -1
  123. package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +62 -0
  124. package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/9a852a62-6192a6ea9346ced3.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live-run/{page-83d27757e2b8060a.js → page-0e3d7b9421b79dac.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/morning/page-0f291d3c8fd55a3a.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/term/{page-139d722de1dcd6c1.js → page-bf067887b3307423.js} +1 -1
  170. package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{409c787b.e48c5bec8ec10456.js → b450776b.3db34d8d965f82d3.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/{ca3702f8.2913182e73889fa2.js → e8543907.5b040a5f22a0b0e5.js} +7 -7
  179. package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +1 -0
  185. package/apps/pwa/out/_next/static/css/{b9d8151e48998417.css → 62c858ad53854f47.css} +1 -1
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +22 -22
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +22 -22
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +22 -22
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +21 -21
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +21 -21
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +22 -22
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +21 -21
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +22 -22
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +22 -22
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +21 -21
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +22 -22
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +23 -24
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +22 -22
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +22 -22
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +21 -21
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +22 -22
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +22 -22
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +23 -24
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +23 -24
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +21 -21
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +21 -21
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +22 -22
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +22 -22
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +21 -21
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +21 -21
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +21 -21
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +22 -22
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +22 -22
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +21 -21
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +22 -22
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +22 -22
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +22 -22
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +22 -22
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +22 -22
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +21 -21
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +22 -22
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +22 -22
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +22 -22
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +22 -22
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +22 -22
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +22 -22
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +22 -22
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +22 -22
  279. package/bin/elanous.mjs +6 -1
  280. package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
  281. package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
  282. package/docs/goal-context/04-mock-scenarios.md +13 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
  285. package/graphs/demo/persona-teacher/recipes.yaml +17 -0
  286. package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
  287. package/graphs/heal/heal-loop.yaml +1 -0
  288. package/graphs/overlays/stop-heal-ladder.yaml +136 -2
  289. package/graphs/release/release-loop.yaml +3 -1
  290. package/graphs/units/gate/gate.yaml +20 -0
  291. package/graphs/units/git/git.yaml +26 -0
  292. package/graphs/units/implement/implement.yaml +19 -0
  293. package/graphs/units/landing/landing.yaml +18 -0
  294. package/graphs/units/review/review.yaml +20 -0
  295. package/graphs/units/verbs/recipes.yaml +13 -10
  296. package/graphs/units/verbs/research.yaml +20 -0
  297. package/graphs/work/research-report.yaml +21 -3
  298. package/package.json +1 -1
  299. package/scripts/disk-steward.ts +46 -0
  300. package/scripts/fleet/node-setup.sh +50 -0
  301. package/scripts/graph-units/verbs/research.ts +55 -0
  302. package/scripts/heal/run-role.ts +99 -5
  303. package/scripts/land-global-checks.ts +6 -1
  304. package/scripts/lib/decompose-ab.ts +1 -0
  305. package/scripts/lib/fixtures/tui-regress/help-insufficient-commands.txt +15 -0
  306. package/scripts/lib/fixtures/tui-regress/help-live.txt +42 -0
  307. package/scripts/lib/fixtures/tui-regress/help-missing-keys.txt +21 -0
  308. package/scripts/lib/fixtures/tui-regress/help-original.txt +51 -0
  309. package/scripts/lib/fixtures/tui-regress/help-shifted-input.txt +26 -0
  310. package/scripts/lib/tui-regress-checks.ts +33 -13
  311. package/scripts/llm-cost-ledger.ts +179 -8
  312. package/scripts/measure-nl-routing-corpus.ts +10 -2
  313. package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
  314. package/scripts/public-copy-lint.ts +163 -19
  315. package/scripts/ratchets/train-side-invariants.sh +0 -1
  316. package/scripts/release-loop/gate-autoheal.ts +117 -0
  317. package/scripts/release-loop/gate-baseline-receipt.ts +55 -10
  318. package/scripts/release-loop/gate-diff.ts +22 -3
  319. package/scripts/release-loop/gate-image-pin.ts +81 -0
  320. package/scripts/release-loop/gate-node-sim.ts +207 -0
  321. package/scripts/release-loop/gate-node.ts +489 -62
  322. package/scripts/release-loop/gate-pod-image-sticky-plan.ts +99 -0
  323. package/scripts/release-loop/gate-radius-live.ts +97 -13
  324. package/scripts/release-loop/gate-shard-dispatch.ts +43 -0
  325. package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
  326. package/scripts/release-loop/gate-train-receipts.ts +122 -0
  327. package/scripts/release-loop/gate-triage-node.ts +70 -10
  328. package/scripts/release-loop/resume-release.ts +330 -23
  329. package/scripts/release-loop/traffic-node.ts +6 -3
  330. package/scripts/release-loop/unattended-release.ts +4 -2
  331. package/scripts/shadow-authoring-probe.ts +20 -0
  332. package/scripts/ux-sim.ts +37 -3
  333. package/scripts/warm-pool-provider-config.ts +263 -0
  334. package/skills/omni-crawl/SKILL.md +5 -2
  335. package/skills/omni-crawl/scripts/main.ts +84 -23
  336. package/src/acp/core-turn-bridge.ts +99 -4
  337. package/src/agent/registry.ts +2 -0
  338. package/src/agent/task-notification.ts +25 -5
  339. package/src/agent/types.ts +6 -0
  340. package/src/agent-mission/mission-cli.ts +24 -0
  341. package/src/agent-mission/mission-out.ts +595 -0
  342. package/src/agent-mission/tool-install.ts +88 -2
  343. package/src/agent-substrate/context-strategy.ts +4 -4
  344. package/src/agent-substrate/self-review-cli.ts +267 -40
  345. package/src/auto-research/research-turn.ts +133 -51
  346. package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
  347. package/src/autopilot/pr-manager.ts +38 -7
  348. package/src/autopilot/pty-control-loop.ts +2 -0
  349. package/src/boot/daemon-tools/self-implement.ts +46 -9
  350. package/src/budget/shadow-arms.ts +52 -0
  351. package/src/capture/tui-self-report.ts +22 -6
  352. package/src/chat/index.ts +1 -1
  353. package/src/chat/pickers/state.ts +7 -1
  354. package/src/cli/fixtures/review-loop-breaker/opwaiver-32646-1694ccc7a170.json +1 -0
  355. package/src/cli/fixtures/review-loop-breaker/opwaiver-32853-bd8f73595c83.json +1 -0
  356. package/src/cli/fixtures/review-loop-breaker/opwaiver-33097-1cc85900413c.json +1 -0
  357. package/src/cli/fixtures/review-loop-breaker/opwaiver-33106-972f31e4a3ca.json +1 -0
  358. package/src/cli/fixtures/review-loop-breaker/opwaiver-33113-3ab51f05968f.json +1 -0
  359. package/src/cli/fixtures/review-loop-breaker/pr-33097-1cc85900413c.json +1 -0
  360. package/src/cli/log-event-names.ts +5 -0
  361. package/src/cli/mcp-login.ts +8 -18
  362. package/src/cli/msg-cli.ts +57 -1
  363. package/src/cli/pr-land-heavy-remote.ts +47 -9
  364. package/src/cli/pr-land-overlap-evidence.ts +100 -1
  365. package/src/cli/pr-land-pod-shadow-job.ts +60 -0
  366. package/src/cli/release-checklist-read-cli.ts +20 -10
  367. package/src/cli/release-cli.ts +27 -1
  368. package/src/cli/research-cli.ts +4 -5
  369. package/src/cli/sim-cli.ts +7 -1
  370. package/src/cli/tasks-cli.ts +12 -4
  371. package/src/codex/models.ts +30 -15
  372. package/src/compact/auto.ts +8 -1
  373. package/src/control-plane/ledger.ts +52 -2
  374. package/src/control-plane/server.ts +16 -2
  375. package/src/core-turn/run-core-turn.ts +313 -89
  376. package/src/core-turn/run-goal-loop.ts +106 -2
  377. package/src/core-turn/types.ts +2 -0
  378. package/src/dashboard/acp-boot.ts +72 -3
  379. package/src/dashboard/classic-sidetab-mission-job.ts +58 -0
  380. package/src/dashboard/classic-sidetab-mission.ts +185 -0
  381. package/src/dashboard/index.ts +155 -15
  382. package/src/dashboard/input/agent-wake.ts +23 -1
  383. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +9 -0
  384. package/src/dashboard/mission-cli-consumer.ts +153 -0
  385. package/src/dashboard/seat-boot-preamble.ts +171 -1
  386. package/src/dashboard/side-basic-runtime.ts +54 -1
  387. package/src/dashboard/sidetab-runtime.ts +90 -1
  388. package/src/dashboard/skill-catalog-preamble.ts +101 -0
  389. package/src/dashboard/skill-detection-runtime.ts +55 -15
  390. package/src/dashboard/slash-runtime/dashboard-handlers.ts +15 -0
  391. package/src/dashboard/turn-preamble.ts +65 -16
  392. package/src/dashboard/turn-prompt-runtime.ts +4 -2
  393. package/src/disk-steward/judge.ts +73 -0
  394. package/src/disk-steward/ledger.ts +122 -0
  395. package/src/disk-steward/steward.ts +373 -0
  396. package/src/domains/guardian-tick.ts +191 -2
  397. package/src/graph-runner/graph-cli.ts +44 -7
  398. package/src/graph-runner/graph-tick.ts +10 -2
  399. package/src/graph-runner/in-process-registry.ts +37 -0
  400. package/src/graph-runner/runner.ts +34 -4
  401. package/src/grok/agent-search.ts +14 -4
  402. package/src/grok/credential.ts +28 -11
  403. package/src/grounding/ref-index.ts +19 -0
  404. package/src/grounding/sources-cli.ts +9 -1
  405. package/src/harness/harness-cli-command.ts +267 -14
  406. package/src/harness/harness-incidents.ts +312 -7
  407. package/src/harness/harness-pod-dispatch.ts +81 -15
  408. package/src/harness/harness-space.ts +15 -1
  409. package/src/harness/harness-stop.ts +155 -11
  410. package/src/harness/progress-worker-entry.ts +59 -0
  411. package/src/harness/progress-worker-runtime.ts +11 -0
  412. package/src/index.ts +52 -7
  413. package/src/instance/dev-project.ts +25 -0
  414. package/src/instance/spawn-elanous.ts +6 -4
  415. package/src/intelligence-map/model-alias.ts +6 -5
  416. package/src/intelligence-map/model-catalog.ts +59 -2
  417. package/src/llm/model-defaults.ts +4 -4
  418. package/src/llm.ts +208 -19
  419. package/src/loops/orchestrator/coordinator-shadow.ts +226 -0
  420. package/src/loops/orchestrator/tick.ts +61 -0
  421. package/src/maturity/feature-maturity.ts +1 -1
  422. package/src/mcp/mcp-oauth.ts +3 -1
  423. package/src/model-tier/llm-tier-map.ts +9 -9
  424. package/src/model-tier/turn-tier.ts +1 -1
  425. package/src/msg/msg-mirror-github.ts +80 -0
  426. package/src/msg/msg-mirror-policy.ts +61 -0
  427. package/src/msg/msg-mirror-runner.ts +219 -0
  428. package/src/msg/msg-mirror-state.ts +33 -0
  429. package/src/msg/msg-store.ts +11 -0
  430. package/src/native-tool-catalog.ts +2 -2
  431. package/src/nexus/api/harness-traversal.ts +11 -0
  432. package/src/output-truncation.ts +41 -12
  433. package/src/pr-tool/census.ts +3 -2
  434. package/src/project/project-store.ts +48 -1
  435. package/src/pty-shell/tui-run-state.ts +188 -2
  436. package/src/release-loop/checklist-target-path-hint.ts +13 -0
  437. package/src/release-loop/checklist.ts +9 -1
  438. package/src/release-loop/gate-host-reservation.ts +144 -0
  439. package/src/release-loop/release-schedule.ts +90 -1
  440. package/src/repl/index.ts +43 -2
  441. package/src/research/axis-fanout.ts +121 -16
  442. package/src/research/bloom-exemplars.ts +137 -0
  443. package/src/research/gap-followup.ts +13 -1
  444. package/src/research/plugin-discovery.ts +36 -14
  445. package/src/research-bridge/invoke.ts +22 -5
  446. package/src/research-bridge/types.ts +2 -0
  447. package/src/self-dev/ask-launch-flow.ts +39 -25
  448. package/src/self-dev/decompose.ts +119 -5
  449. package/src/self-dev/dev-cli.ts +17 -17
  450. package/src/self-dev/graph-front-nodes.ts +23 -0
  451. package/src/self-dev/launch-preflight-text.ts +5 -6
  452. package/src/self-dev/launch-preflight.ts +9 -4
  453. package/src/self-dev/orchestrate.ts +27 -2
  454. package/src/self-dev/review-provider-fallback.ts +9 -2
  455. package/src/self-dev/run-supervisor.ts +226 -6
  456. package/src/self-dev/run-types.ts +7 -0
  457. package/src/self-implement/doctor-visit.ts +88 -0
  458. package/src/self-implement/gate-artifacts.ts +13 -0
  459. package/src/self-implement/gate-cli.ts +54 -24
  460. package/src/self-implement/gate-remote.ts +23 -5
  461. package/src/self-implement/goal-author-clarification.ts +31 -12
  462. package/src/self-implement/goal-author.ts +403 -8
  463. package/src/self-implement/graph-overlay-yaml.ts +7 -0
  464. package/src/self-implement/graph-stage-units.ts +172 -0
  465. package/src/self-implement/graph-templates.ts +162 -1
  466. package/src/self-implement/graph-variant.ts +37 -4
  467. package/src/self-implement/headless-elanous-driver.ts +31 -2
  468. package/src/self-implement/heal-intake.ts +112 -4
  469. package/src/self-implement/heal-triage.ts +20 -0
  470. package/src/self-implement/host-regate.ts +31 -8
  471. package/src/self-implement/knowhow-pack.ts +38 -0
  472. package/src/self-implement/merge-train.ts +5 -0
  473. package/src/self-implement/orchestrator.ts +359 -30
  474. package/src/self-implement/regate-detail.ts +38 -1
  475. package/src/self-implement/rework-child-provider.ts +25 -0
  476. package/src/self-implement/run-chart.ts +119 -0
  477. package/src/self-implement/run-ledger.ts +176 -17
  478. package/src/self-implement/run-stop.ts +208 -5
  479. package/src/self-implement/running-runs.ts +35 -12
  480. package/src/self-implement/self-implement-cli.ts +36 -4
  481. package/src/self-implement/stop-autoheal-operational.ts +43 -0
  482. package/src/self-implement/stop-autoheal.ts +28 -6
  483. package/src/session/chat.ts +69 -58
  484. package/src/session/request-size-guard.ts +123 -0
  485. package/src/session-runtime/index.ts +98 -4
  486. package/src/session-runtime/tier-flip.ts +3 -3
  487. package/src/sidetab-core/model.ts +150 -0
  488. package/src/sidetab-core/visible-agent-mission.ts +186 -0
  489. package/src/skills/name-match.ts +20 -0
  490. package/src/skills/tools/agent.ts +30 -2
  491. package/src/skills/tools/omni-search.ts +67 -5
  492. package/src/task-agent/parent-host.ts +14 -1
  493. package/src/task-agent/pod-distributor-entry.ts +3 -0
  494. package/src/task-agent/task-hand.ts +31 -1
  495. package/src/task-orchestrator/surfaces/pod-distributor.ts +48 -0
  496. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +43 -0
  497. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +38 -1
  498. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
  499. package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +33 -6
  500. package/src/task-orchestrator/surfaces/pod-source-bundle.ts +45 -9
  501. package/src/task-orchestrator/surfaces/pod-source-receive.ts +163 -13
  502. package/src/task-orchestrator/surfaces/pod-source-spec.ts +3 -3
  503. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +209 -39
  504. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +80 -3
  505. package/src/task-orchestrator/surfaces/self-implement-pod.ts +280 -60
  506. package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
  507. package/src/tokens.ts +35 -2
  508. package/src/tool-runtime/agent-runtime.ts +1 -0
  509. package/src/tool-runtime/elanous-skills-list-runtime.ts +5 -1
  510. package/src/tool-runtime/skill-exec-runtime.ts +33 -13
  511. package/src/tool-runtime/types.ts +1 -0
  512. package/src/tui/entry.ts +24 -7
  513. package/src/tui/sidetab/attach.ts +47 -0
  514. package/src/tui/sidetab/list.ts +45 -0
  515. package/src/tui/sidetab/nl-tool.ts +2 -136
  516. package/src/tui/sidetab/peek.ts +52 -0
  517. package/src/tui-client/dashboard-session.ts +3 -0
  518. package/src/tui-client/local-chat-turn.ts +26 -13
  519. package/src/tui.ts +22 -0
  520. package/src/user-config.ts +11 -5
  521. package/src/ux-sim/fake-kubectl.ts +37 -3
  522. package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
  523. package/src/ux-sim/fault-pod-child-result.ts +42 -0
  524. package/src/ux-sim/fault-pool-cap.ts +11 -6
  525. package/src/ux-sim/mock-scenario-catalog.json +41 -0
  526. package/src/ux-sim/mock-scenario-catalog.ts +156 -0
  527. package/src/ux-sim/release-sim-rig.ts +262 -0
  528. package/src/ux-sim/scenario.ts +116 -23
  529. package/src/ux-sim/seminar-rehearsal.ts +109 -0
  530. package/src/ux-sim/subagent-tools-device.ts +2 -2
  531. package/src/version/packed-revision.json +1 -1
  532. package/src/voice/voice-tts-singleton.ts +18 -3
  533. package/src/web-search/grok.ts +5 -9
  534. package/apps/pwa/out/_next/static/chunks/1060.014f1f01a17aec26.js +0 -115
  535. package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/1452.162bb2d9d699e82a.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +0 -286
  538. package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +0 -149
  539. package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +0 -90
  541. package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +0 -104
  542. package/apps/pwa/out/_next/static/chunks/2047.8f23e210995d4548.js +0 -2
  543. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/2066.a77257c8c350770a.js +0 -23
  545. package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/2281-b8cede695c6c650e.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/2499.02fbfd18126c10c0.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/2522.f2766b76d22c8bdf.js +0 -34
  550. package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +0 -27
  553. package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/2829-734fe8bf2eee7347.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +0 -24
  566. package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +0 -77
  567. package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +0 -36
  568. package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +0 -287
  571. package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +0 -74
  578. package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/5622.94893f5aea7185d0.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +0 -8
  583. package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +0 -62
  585. package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +0 -94
  589. package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/6624.981ef7caeb680560.js +0 -32
  596. package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +0 -148
  600. package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/6cc1d1d6.9a98dd4622f1afc6.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +0 -93
  605. package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/7515.1ad6efe157fa4448.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +0 -24
  609. package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/8086.1ab9103c41be884f.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/8357.1aaa713b052a78b1.js +0 -309
  616. package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/9069.657590a84afb8fac.js +0 -41
  620. package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/9992.07ce73c10bd5e6a1.js +0 -79
  625. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ba957ff875a026a0.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/c696986b.5dc8bb1143af16d1.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/d8de0de2-dd0f4ac8e5ab1832.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +0 -1
  683. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +0 -1
  684. package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
  685. /package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → X1ucLw10Cds_h614NoEnh}/_ssgManifest.js +0 -0
@@ -4,6 +4,7 @@ import { join } from 'node:path';
4
4
  import { runPodCommand, type RunPodCommandOptions, type PodCommandResult } from '../task-orchestrator/surfaces/pod-command-job.js';
5
5
  import { redactSecretText } from '../debug/log.js';
6
6
  import type { RootPlanSummary } from './pr-land-heavy-remote.js';
7
+ import type { WarmReuseEvidence, WarmReuseEvidenceByConsumer } from '../task-orchestrator/surfaces/pod-warm-switch.js';
7
8
 
8
9
  const SHA = /^[0-9a-f]{40}$/i;
9
10
  const MARKER = 'ELANOUS_PRLAND_SHADOW';
@@ -107,3 +108,62 @@ export async function runLandingPodShadowJob(input: LandingPodShadowInput, deps:
107
108
  const gateRc = Number(match[2]);
108
109
  return { measured: true, ok: tscRc === 0 && gateRc === 0, rootPlan, tscRc, gateRc, job: job.job };
109
110
  }
111
+
112
+ /** WARM-REUSE-LAND-CONSUMER-WIRE — land shadow Job 결과 표본(착지쌍·lock·lease·카나리아·그림자 일치). */
113
+ export interface LandingShadowSample {
114
+ /** shadow Job 이 잰 착지쌍 — 원격 게이트가 잰 head/main 와 정확히 같아야 표본으로 센다. */
115
+ head: string;
116
+ main: string;
117
+ /** shadow Job 이 돈 Pod generation lock — 원값 그대로 대조한다. */
118
+ lock: string;
119
+ /** shadow Job 이 lease 를 잡고 끝까지 쟀나. */
120
+ leaseValid: boolean;
121
+ /** shadow Job 카나리아(착지 tsc+gate) 통과. */
122
+ canaryPassed: boolean;
123
+ /** 같은 착지의 fresh(원격 게이트) 판정과 그림자 비교 일치 — 불일치 표본은 최근 mismatch 로 센다. */
124
+ agree: boolean;
125
+ }
126
+
127
+ /** land 소비자 판정 증거 입력 — 최근 창 표본 ⊕ 이번 착지가 기대하는 warm 워커 lock ⊕ 선행 소비자 증거. */
128
+ export interface LandShadowSampleWindow {
129
+ /** 최근 창 — 마지막 원소가 가장 최근 shadow 결과다. */
130
+ samples: LandingShadowSample[];
131
+ /** 이번 착지가 기대하는 warm 워커 lock(현재 Pod generation). */
132
+ lock: string;
133
+ /** 선행 소비자(gate-recheck)의 자기 증거 — land 는 이 칸이 live 여야 live 가 될 수 있다(비면 off). */
134
+ gateRecheck?: WarmReuseEvidence;
135
+ }
136
+
137
+ /**
138
+ * WARM-REUSE-LAND-CONSUMER-WIRE — land shadow Job 결과에서 소비자('land') 판정 증거를 만든다.
139
+ * 판정 본체는 pod-warm-switch.ts `decideWarmReuse` — 이 모듈은 증거의 산지만 담당한다.
140
+ * 창이 없거나 비면 land 증거 칸이 비어 off 다 — 못 잰 증거는 통과가 아니다.
141
+ * 원값은 고쳐 읽지 않고 정확히 비교한다(신원 형식 어긋남은 pod-warm-switch 판정이 끊는다).
142
+ */
143
+ export function buildLandWarmEvidence(
144
+ window: LandShadowSampleWindow | undefined,
145
+ expected: { head: string; main: string },
146
+ ): WarmReuseEvidenceByConsumer {
147
+ const evidence: WarmReuseEvidenceByConsumer = window?.gateRecheck ? { 'gate-recheck': window.gateRecheck } : {};
148
+ if (!window || window.samples.length === 0) return evidence;
149
+ const latest = window.samples[window.samples.length - 1]!;
150
+ let consecutiveMatchSamples = 0;
151
+ for (let index = window.samples.length - 1; index >= 0; index--) {
152
+ const sample = window.samples[index]!;
153
+ if (sample.head !== expected.head || sample.main !== expected.main || sample.lock !== window.lock
154
+ || sample.leaseValid !== true || sample.canaryPassed !== true || sample.agree !== true) break;
155
+ consecutiveMatchSamples++;
156
+ }
157
+ const recentMismatchCount = window.samples.filter((sample) => sample.agree === false).length;
158
+ return {
159
+ ...evidence,
160
+ land: {
161
+ consecutiveMatchSamples,
162
+ recentMismatchCount,
163
+ leaseValid: latest.leaseValid,
164
+ canaryPassed: latest.canaryPassed,
165
+ expected: { head: expected.head, main: expected.main, lock: window.lock },
166
+ worker: { head: latest.head, main: latest.main, lock: latest.lock },
167
+ },
168
+ };
169
+ }
@@ -109,8 +109,11 @@ export function collectChecklistEvidenceStages(item: ReturnType<typeof listCheck
109
109
  const origin = run('git', ['remote', 'get-url', 'origin']);
110
110
  const pinObject = run('git', ['cat-file', '-e', `${pinSha}^{commit}`]);
111
111
  const repoUrl = origin.stdout.trim().replace(/^git@github\.com:/i, 'https://github.com/').replace(/\.git$/i, '').replace(/\/$/u, '').toLowerCase();
112
- const expectedRepo = 'https://github.com/elanvitalai/elanous';
113
- if (repoRoot.status !== 0 || !repoRoot.stdout.trim() || origin.status !== 0 || repoUrl !== expectedRepo || pinObject.status !== 0) {
112
+ const expectedRepos = new Set([
113
+ 'https://github.com/elanvitalai/elanous',
114
+ 'https://github.com/ElanvitalAI/elanous',
115
+ ]);
116
+ if (repoRoot.status !== 0 || !repoRoot.stdout.trim() || origin.status !== 0 || !expectedRepos.has(repoUrl) || pinObject.status !== 0) {
114
117
  e3.reason = '현재 git 저장소가 elanous 원본이 아니거나 설치본 pin 객체가 없어 조상 관계를 판정할 수 없다';
115
118
  } else {
116
119
  const ancestry = run('git', ['merge-base', '--is-ancestor', mergeSha, pinSha]);
@@ -122,11 +125,15 @@ export function collectChecklistEvidenceStages(item: ReturnType<typeof listCheck
122
125
  }
123
126
  }
124
127
 
125
- const runId = /\b(run-[a-f0-9]{8}-[a-f0-9-]{27,})\b/i.exec(evidence)?.[1]
126
- ?? /\b([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})\b/i.exec(evidence)?.[1];
128
+ const identityToken = '(?:run-[a-f0-9]{8}-[a-f0-9-]{27,}|[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}|[a-z0-9][a-z0-9._:-]{2,})';
129
+ const labelledIdentity = new RegExp(`\\b(runId|missionId|taskId)\\s*[:=]?\\s*(${identityToken})\\b`, 'i').exec(evidence);
130
+ const runId = labelledIdentity?.[2]
131
+ ?? /\b(run-[a-f0-9]{8}-[a-f0-9-]{27,}|[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})\b/i.exec(evidence)?.[1];
132
+ const identityLabel = labelledIdentity?.[1]?.toLowerCase();
133
+ const identityField = identityLabel === 'missionid' ? 'missionId' : identityLabel === 'taskid' ? 'taskId' : 'runId';
127
134
  const event = /(?:event|이벤트)\s*[:=]\s*([A-Za-z0-9_.:-]+)/iu.exec(evidence)?.[1];
128
135
  const verificationCommand = /(?:완료 경계 증거 명령|증거 명령|verification command)\s*[:=]\s*([^\r\n]+)/iu.exec(`${item.title}\n${evidence}`)?.[1]?.trim() ?? null;
129
- const e4: ChecklistEvidenceStage = { id: 'E4', state: 'missing', source: null, measuredAt, verificationCommand, reason: '근거에 runId·event·원문 검증 명령이 모두 필요하다' };
136
+ const e4: ChecklistEvidenceStage = { id: 'E4', state: 'missing', source: null, measuredAt, verificationCommand, reason: '근거에 runId·missionId·taskId 중 하나와 event·원문 검증 명령이 모두 필요하다' };
130
137
  if (runId && event && verificationCommand) {
131
138
  const logs = run('eln', ['logs', '--grep', runId, '--since', '365d', '--all', '--include-test', '--limit', '1000', '--json'], 30_000);
132
139
  if (logs.status !== 0) { e4.state = 'unmeasurable'; e4.reason = `runId 로그 조회 실패${logs.error ? `: ${logs.error}` : ''}`; }
@@ -135,16 +142,19 @@ export function collectChecklistEvidenceStages(item: ReturnType<typeof listCheck
135
142
  const truncated = rows.length >= 1000 || rows.some((row) => row._meta && typeof row._meta === 'object' && (row._meta as { limitReached?: unknown }).limitReached === true);
136
143
  const observed = rows.some((row) => {
137
144
  if (row.event !== event || typeof row.data !== 'string') return false;
138
- try { return (JSON.parse(row.data) as { runId?: unknown }).runId === runId; } catch { return false; }
145
+ try {
146
+ const data = JSON.parse(row.data) as { runId?: unknown; missionId?: unknown; taskId?: unknown };
147
+ return data[identityField] === runId;
148
+ } catch { return false; }
139
149
  });
140
- e4.source = `eln logs --grep ${runId} --since 365d --all --include-test --limit 1000 --json (event=${event})`;
141
- if (observed) { e4.state = 'observed'; e4.reason = `같은 runId의 ${event} 실물 이벤트를 찾았다`; }
150
+ e4.source = `eln logs --grep ${runId} --since 365d --all --include-test --limit 1000 --json (${identityField}=${runId}, event=${event})`;
151
+ if (observed) { e4.state = 'observed'; e4.reason = `같은 ${identityField}의 ${event} 실물 이벤트를 찾았다`; }
142
152
  else if (truncated) { e4.state = 'unmeasurable'; e4.reason = '로그 결과가 잘려 사건 부재를 판정할 수 없다'; }
143
- else { e4.reason = `같은 runId의 ${event} 이벤트가 없다`; }
153
+ else { e4.reason = `같은 ${identityField}의 ${event} 이벤트가 없다`; }
144
154
  }
145
155
  }
146
156
 
147
- const acceptance = /- 완료 경계 실물:([^\r\n]+)/u.exec(item.title)?.[1]?.trim();
157
+ const acceptance = /^\s*(?:[-*]\s*)?완료 경계 실물\s*:\s*([^\r\n]+)/mu.exec(item.title)?.[1]?.trim();
148
158
  const e5Observed = Boolean(acceptance && evidence.includes(acceptance));
149
159
  const e5: ChecklistEvidenceStage = { id: 'E5', state: e5Observed ? 'observed' : 'missing', source: 'checklist title/evidence exact acceptance-text comparison', measuredAt,
150
160
  reason: e5Observed ? '완료 경계 실물 문구가 기록된 근거와 일치한다' : '완료 경계 실물 문구와 일치하는 근거가 없다' };
@@ -9,6 +9,7 @@
9
9
  // elanous release resume --run <runId> --from <node> [--waive <node> --reason <text>] [--accepted-regressions <json>] [--gate-executor <pod|host> [--gate-host <ssh-host>]] [--gate-pod-pool <pool>] [--json]
10
10
  // elanous release auto-start [--window-minutes <n>] [--apply] [--json]
11
11
  // elanous release recover --run <runId> --pick <sha...> [--from export-check] [--command-root <path>] [--repo-root <path>] [--no-partial] [--json]
12
+ // elanous release recover-landing --run <runId> --merge <full-sha> [--from export-check] [--repo-root <path>] [--no-partial] [--json]
12
13
  // elanous release rehearsal tick [--apply] [--checkout <dir>] [--shards <n>] [--remote <host>] [--recovery-run <id>] [--json]
13
14
  // elanous release preflight --version <x.y.z> [--publish-at <iso>] [--json] (컷 − 60분 main export 포함 사전 점검 · 읽기 전용 · ⛔ 있으면 exit 1)
14
15
  // elanous release cut-branch --version <x.y.z> [--base <sha>] --pick <sha>... [--append] [--dry-run]
@@ -45,7 +46,7 @@ import { isIsolatedLedgerWriteRoot } from '../hq/ledger-write-target.js';
45
46
  import { runUnattendedRelease, type UnattendedReleaseDeps } from '../../scripts/release-loop/unattended-release.js';
46
47
  import { publishAtError } from '../../scripts/release-loop/publish-at.js';
47
48
  import { cutReleaseBranch } from '../../scripts/release-loop/cut-branch.js';
48
- import { planResumeReleaseRun, recoverReleaseRun, resumeReleaseRun, ReleaseRecoverStopped, type RecoverReleaseDeps } from '../../scripts/release-loop/resume-release.js';
49
+ import { planResumeReleaseRun, recoverLandingPartialOption, recoverReleaseRun, recoverReleaseRunFromLanding, resumeReleaseRun, ReleaseRecoverStopped, type RecoverReleaseDeps } from '../../scripts/release-loop/resume-release.js';
49
50
  import type { AcceptedRegression } from '../../scripts/release-loop/resume.js';
50
51
  import type { PrereleaseKind } from '../../scripts/release-loop/release-version.js';
51
52
  import { releaseReadiness } from '../../scripts/release-loop/release-readiness.js';
@@ -1388,6 +1389,31 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1388
1389
  }
1389
1390
  }, (r) => r.stages.every((stage) => stage.outcome === 'ok'));
1390
1391
  });
1392
+ release.command('recover-landing')
1393
+ .description('착지 알림 수동 재생 입구 — merge SHA로 중복을 억제하고 append → tip 고정 → export-check 재개를 수행한다. release-loop event hook 착지 전에는 사람이 직접 호출한다')
1394
+ .requiredOption('--run <runId>', '실패한 release-loop 런 ID')
1395
+ .requiredOption('--merge <sha>', 'main에 착지한 수리 커밋의 전체 40자리 SHA')
1396
+ .option('--from <node>', '재개 시작 노드 — 기본 export-check')
1397
+ .option('--command-root <path>', '재개 명령을 실행할 checkout — 생략 시 append tip 임시 checkout')
1398
+ .option('--repo-root <path>', 'append를 실행할 checkout — origin remote 필요')
1399
+ .option('--no-partial', 'Pod image digest 등이 맞지 않으면 전체 gate를 실행하며 부분 재검을 사용하지 않음')
1400
+ .option('--json', '결과 한 줄 JSON(stdout) · 사람 줄은 stderr')
1401
+ .action(async (o: { run: string; merge: string; from?: string; commandRoot?: string; repoRoot?: string; partial?: boolean; json?: boolean }) => {
1402
+ await jsonAction(o.json, async (log) => {
1403
+ try {
1404
+ const partial = recoverLandingPartialOption(o.partial);
1405
+ return await recoverReleaseRunFromLanding({ runId: o.run, mergeSha: o.merge,
1406
+ ...(o.from === undefined ? {} : { from: o.from }),
1407
+ ...(o.commandRoot === undefined ? {} : { commandRoot: o.commandRoot }),
1408
+ ...(o.repoRoot === undefined ? {} : { repoRoot: o.repoRoot }),
1409
+ ...(partial === undefined ? {} : { partial }) },
1410
+ { ...resumeDeps, onSource: log });
1411
+ } catch (caught) {
1412
+ if (!(caught instanceof ReleaseRecoverStopped)) throw caught;
1413
+ return { ok: false as const, error: caught.message, stages: [...caught.stages], notRun: [...caught.notRun], duplicate: false };
1414
+ }
1415
+ }, (r) => r.duplicate || r.stages.every((stage) => stage.outcome === 'ok'));
1416
+ });
1391
1417
  release.command('gate-history')
1392
1418
  .description('GATE-FAIL-HISTORY (0.2.29) — 판을 넘는 게이트 실패 표 — 모든 release-loop·light-rc 런 원장 ⊕ gate-verdict 에서 시험 파일별 introduced·preexisting·env·flaky 횟수 · 마지막 실패 판 · 원인 PR(수리 PR 본문 «원인 #N»)')
1393
1419
  .option('--since <판|일>', '이 판(x.y.z)부터 · 또는 그 날(YYYY-MM-DD) 이후 시작된 런부터')
@@ -1,12 +1,11 @@
1
1
  import type { Command } from 'commander';
2
2
  import { debug } from '../debug/log.js';
3
3
  import { isLiveDetailOn } from '../live/detail-switch.js';
4
- import { dispatchOmniSearch } from '../skills/tools/omni-search.js';
5
- import { getAvailableWebSearchProviders } from '../web-search/index.js';
4
+ import { dispatchResearchOmniSearch, getAvailableResearchSearchEngineIds } from '../skills/tools/omni-search.js';
6
5
 
7
6
  export interface ResearchCliDeps {
8
7
  readonly out?: { log: (line: string) => void; error: (line: string) => void };
9
- readonly search?: typeof dispatchOmniSearch;
8
+ readonly search?: typeof dispatchResearchOmniSearch;
10
9
  readonly availableEngines?: () => string[];
11
10
  readonly maxDetailOn?: (runId?: string) => boolean;
12
11
  readonly log?: typeof debug.log;
@@ -23,7 +22,7 @@ export function registerResearchCommand(program: Command, deps: ResearchCliDeps
23
22
  const query = parts.join(' ').trim();
24
23
  const limit = Number(opts.limit);
25
24
  const engines = opts.engines?.split(',').map(id => id.trim()).filter(Boolean);
26
- const available = (deps.availableEngines ?? (() => getAvailableWebSearchProviders().map(p => p.id)))();
25
+ const available = (deps.availableEngines ?? getAvailableResearchSearchEngineIds)();
27
26
  const unknown = engines?.filter(id => !available.some(p => p.toLowerCase() === id.toLowerCase())) ?? [];
28
27
  if (!query || !Number.isInteger(limit) || limit < 1 || limit > 20 || (opts.engines !== undefined && !engines?.length) || unknown.length) {
29
28
  out.error(unknown.length ? `research: 사용할 수 없는 엔진: ${unknown.join(', ')} (사용 가능: ${available.join(', ') || '없음'})`
@@ -41,7 +40,7 @@ export function registerResearchCommand(program: Command, deps: ResearchCliDeps
41
40
  if (!wanted.length) log('research.query', 'query', { query, engines: [], limit });
42
41
  for (const engine of wanted) log('research.query', 'query', { query, engine, limit });
43
42
  try {
44
- const result = await (deps.search ?? dispatchOmniSearch)({ query, ...(engines?.length ? { engines } : {}), limit }, {
43
+ const result = await (deps.search ?? dispatchResearchOmniSearch)({ query, ...(engines?.length ? { engines } : {}), limit }, {
45
44
  onEngine: event => {
46
45
  if (event.phase === 'complete') log('research.result', 'result', { query, engine: event.engine, hits: event.hits, durationMs: event.durationMs, ...(event.error ? { error: event.error } : {}) });
47
46
  },
@@ -1,4 +1,6 @@
1
1
  import type { Command } from 'commander';
2
+ import { getTestStateRoot } from '../nexus/paths.js';
3
+ import { runReleaseSimRigIfFile } from '../ux-sim/release-sim-rig.js';
2
4
  import { runScenarioFile } from '../ux-sim/scenario.js';
3
5
 
4
6
  export function registerSimCommands(program: Command): void {
@@ -7,7 +9,11 @@ export function registerSimCommands(program: Command): void {
7
9
  .description('등록된 UX simulation 시나리오를 test 우주에서 실행한다')
8
10
  .action(async (scenarioFile: string) => {
9
11
  try {
10
- const result = await runScenarioFile(scenarioFile);
12
+ // Enforce isolation before either runner inspects the supplied path. Otherwise
13
+ // release-graph dispatch can leak a path-validation error outside test mode.
14
+ if (!getTestStateRoot()) throw new Error('scenario runner requires --test isolated mode');
15
+ const releaseResult = await runReleaseSimRigIfFile(scenarioFile);
16
+ const result = releaseResult ?? await runScenarioFile(scenarioFile);
11
17
  console.log(JSON.stringify(result));
12
18
  if (!result.pass) process.exitCode = 1;
13
19
  } catch (error) {
@@ -66,6 +66,10 @@ export interface TasksCliDeps {
66
66
  taskStatePath?: string;
67
67
  /** 조합 선택 시험에서만 그래프 저장소 루트를 바꾼다. */
68
68
  taskCompositionRoot?: string;
69
+ /** COORD-ENTRANCE-FOLD test seam; production uses the invoking repository root. */
70
+ coordinatorShadowRoot?: string;
71
+ /** Deterministic task-hand time in isolated tests. */
72
+ taskNow?: () => Date;
69
73
  /** DRAFT-CLAIM-AUTO-2-FU — `tasks hand --draft-claim <pr>` 의 관측·게시·수확 리뷰 포트(시험 주입). 기본 = `defaultDraftClaimGhPorts()`(gh CLI ⊕ 생산 리뷰 러너). */
70
74
  draftClaimGh?: DraftClaimGhPorts;
71
75
  /** logs.db 싱크 등록(시험 주입). 기본 = `registerStandaloneLogSink`. `hand`·`show` 가 부른다. */
@@ -473,14 +477,15 @@ async function tryRemoteParent(args: string[], cwd: string | undefined, context:
473
477
  return null;
474
478
  }
475
479
 
476
- /** stderr 파일의 첫 비어 있지 않은 줄(최대 4KB 만 읽는다 — 원 로그 꼬리를 싣지 않는다). */
477
- function firstStderrLine(path: string): string {
480
+ /** Advisory lines may precede the actual fatal error. Keep the full stderr as evidence. */
481
+ function actionableStderrLine(path: string): string {
478
482
  try {
479
483
  const fd = openSync(path, 'r');
480
484
  try {
481
485
  const buf = Buffer.alloc(4096);
482
486
  const n = readSync(fd, buf, 0, buf.length, 0);
483
- return buf.subarray(0, n).toString('utf8').split(/\r?\n/).map((line) => line.trim()).find((line) => line.length > 0) ?? '';
487
+ const lines = buf.subarray(0, n).toString('utf8').split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
488
+ return lines.find((line) => /^(?:❌|error:|fatal:)/i.test(line)) ?? lines[0] ?? '';
484
489
  } finally { closeSync(fd); }
485
490
  } catch { return ''; }
486
491
  }
@@ -529,7 +534,7 @@ export async function defaultTaskLauncher(args: string[], cwd?: string, context?
529
534
  : undefined;
530
535
  if (timer) clearTimeout(timer);
531
536
  if (early && early.code !== 0) {
532
- const first = firstStderrLine(stderrPath);
537
+ const first = actionableStderrLine(stderrPath);
533
538
  const cause = `child rc=${early.code ?? early.signal ?? 'unknown'}${first ? `: ${first}` : ''}`;
534
539
  const { boundRunStopCause, recordRunStop, runStopRecorded, RUN_STOP_EVENT } = await import('../self-implement/run-stop.js');
535
540
  const hasStop = deps.hasStop ?? ((id: string) => {
@@ -2335,6 +2340,9 @@ export function registerTasksCommands(program: Command, deps: TasksCliDeps = {})
2335
2340
  }
2336
2341
  const handOpts = {
2337
2342
  text: resolved.text,
2343
+ ...(resolved.kind === 'work-order' ? { workOrder: resolved.order } : {}),
2344
+ ...(deps.coordinatorShadowRoot ? { coordinatorShadowRoot: deps.coordinatorShadowRoot } : {}),
2345
+ ...(deps.taskNow ? { now: deps.taskNow } : {}),
2338
2346
  ...(opts.project !== undefined && opts.target !== undefined ? { project: { id: opts.project, target: opts.target } } : {}),
2339
2347
  ...(opts.goal !== undefined ? { goal: opts.goal } : {}),
2340
2348
  ...(opts.milestone !== undefined ? { milestone: opts.milestone } : {}),
@@ -1,8 +1,7 @@
1
1
  // ── OpenAI Codex model catalog ──
2
2
  //
3
- // Curated subset of the full OpenAI Codex CLI model roster — the six
4
- // options that cover the most common use cases without overwhelming
5
- // the onboarding picker. Source: omni-crawl sweep on 2026-04-14 across
3
+ // Curated subset of the full OpenAI Codex CLI model roster, covering
4
+ // common use cases without overwhelming the onboarding picker. Source: omni-crawl sweep on 2026-04-14 across
6
5
  // - developers.openai.com/api/docs/models/{all,codex-mini-latest,gpt-5-codex}
7
6
  // - developers.openai.com/codex/models
8
7
  // - platform.openai.com/docs/models
@@ -20,10 +19,9 @@
20
19
  // 2026-09-09 refresh (live 1차 대조 — developers.openai.com/api/내부 문서 `gpt-6-astra`
21
20
  // ⊕ openai.com/api/pricing/ ⊕ `codex exec --model gpt-6-astra` 실호출):
22
21
  // + gpt-6-astra (2026-09-03 출시 · 현 최상단)
23
- // + gpt-5.6-terra (elanous 가 «실제로» 기본으로 쓰는 모델 — llm.model 이 이 값이다)
24
- // ⛔ recommended 를 gpt-5.5 → gpt-5.6-terra 로 옮겼다. 이 표의 recommended 는 「가장 센 것」이
25
- // 아니라 「기본으로 골라도 되는 것」이고, 그 자리에 두 세대 전 모델이 앉아 있었다.
26
- // astra 는 recommended 가 «아니다» — terra 대비 input 4배·output 3.3배라 기본값이 될 수 없다.
22
+ // + gpt-5.6-terra (at the time, the configured `llm.model` default)
23
+ // GPT-6.1 refresh (2026-10-28): recommended is GPT-6.1 Terra; Sol is available for higher-cost deep work.
24
+ // `recommended` means a safe default, not the strongest model; Astra remains opt-in due to its higher cost.
27
25
 
28
26
  export type CodexModelTier = 'flagship' | 'balanced' | 'cheap' | 'specialist' | 'legacy';
29
27
 
@@ -44,11 +42,21 @@ export interface CodexModel {
44
42
  recommended?: boolean;
45
43
  }
46
44
 
47
- /** Six curated models for the 1-point setup picker. Ordering
48
- * reflects the UI: recommended first, then by descending tier. */
45
+ /** Curated models for the 1-point setup picker. Ordering reflects the UI:
46
+ * recommended first, then by descending tier. */
49
47
  export const CODEX_MODELS: CodexModel[] = [
50
48
  {
51
- // 📏 2026-09-25 캐시 읽기 단가 = 입력의 10%(OpenRouter 목록 gpt-6-astra 1.0 · sol 0.2 · luna 0.01) — 없으면 캐시분이 입력 단가로 10배 매겨졌다.
49
+ id: 'gpt-6.1-terra',
50
+ label: 'GPT-6.1 Terra',
51
+ tier: 'balanced',
52
+ description: 'Recommended everyday Codex model. 500K context; $1/$5 per million tokens, cached input $0.05.',
53
+ contextWindow: 500_000,
54
+ pricingUsd: { inputPerM: 1.0, outputPerM: 5.0, cacheReadPerM: 0.05 },
55
+ recommended: true,
56
+ },
57
+ {
58
+ // Cache-read rates: Astra $1.00/M, GPT-6.1 Sol $0.10/M, Terra $0.05/M, Luna $0.01/M.
59
+ // Per OP 2026-10-28 price direction, legacy GPT-6 Sol also uses $0.10/M for cost estimates.
52
60
  id: 'gpt-6-astra',
53
61
  label: 'GPT-6 Astra (frontier)',
54
62
  tier: 'flagship',
@@ -56,14 +64,21 @@ export const CODEX_MODELS: CodexModel[] = [
56
64
  contextWindow: 1_050_000,
57
65
  pricingUsd: { inputPerM: 10.0, outputPerM: 50.0, cacheReadPerM: 1.0 },
58
66
  },
67
+ {
68
+ id: 'gpt-6.1-sol',
69
+ label: 'GPT-6.1 Sol',
70
+ tier: 'flagship',
71
+ description: 'Higher-capability reasoning and coding model. 500K context; $2/$10 per million tokens, cached input $0.10.',
72
+ contextWindow: 500_000,
73
+ pricingUsd: { inputPerM: 2.0, outputPerM: 10.0, cacheReadPerM: 0.1 },
74
+ },
59
75
  {
60
76
  id: 'gpt-6-sol',
61
- label: 'GPT-6 Sol', // «recommended» 표시는 목록이 `recommended: true` 로 붙인다 — 라벨에도 쓰면 두 번 뜬다(UX 8)
62
- tier: 'balanced',
63
- description: 'elanous 운영 기본(대표 2026-09-23). 복합 코딩·agentic 워크플로. Reasoning «Highest» 인데 가격은 5.6 Terra 와 같은 입력·더 싼 출력. 1.05M ctx, effort none..max(기본 medium).',
77
+ label: 'GPT-6 Sol',
78
+ tier: 'legacy',
79
+ description: 'Legacy GPT-6 Sol retained for compatibility; GPT-6.1 Sol is its higher-performing successor at the same price, while Terra is a lower-cost default.',
64
80
  contextWindow: 1_050_000,
65
- pricingUsd: { inputPerM: 2.0, outputPerM: 10.0, cacheReadPerM: 0.2 },
66
- recommended: true,
81
+ pricingUsd: { inputPerM: 2.0, outputPerM: 10.0, cacheReadPerM: 0.1 },
67
82
  },
68
83
  {
69
84
  id: 'gpt-6-luna',
@@ -31,8 +31,15 @@ export function shouldAutoCompact(
31
31
  messages: MessageLike[],
32
32
  modelId: string | undefined,
33
33
  config: ChatAutoCompactConfig,
34
+ observedInputTokens?: number,
34
35
  ): AutoCompactDecision {
35
- const usedTokens = estimateMessagesTokens(messages);
36
+ const hasObservedInputTokens = typeof observedInputTokens === 'number'
37
+ && Number.isFinite(observedInputTokens)
38
+ && observedInputTokens >= 0;
39
+ const estimatedTokens = estimateMessagesTokens(messages);
40
+ // Provider usage captures model/tokenizer overhead; current history also
41
+ // includes tool output appended since that provider response.
42
+ const usedTokens = hasObservedInputTokens ? Math.max(observedInputTokens, estimatedTokens) : estimatedTokens;
36
43
  const windowTokens = resolveModelContextWindow(modelId) ?? inferContextWindow(modelId);
37
44
  const configuredBudget = config.workingBudgetTokens;
38
45
  const budgetTokens = typeof configuredBudget === 'number'
@@ -20,7 +20,7 @@ export interface ResourceRecord {
20
20
  export type ResourceView = ResourceRecord & { ageMs: number; expired: boolean };
21
21
 
22
22
  export interface PodWorkerKey { context: string; imageDigest: string; lockHash: string; architecture: string }
23
- type PodWorkerState = 'idle' | 'leased' | 'sanitizing' | 'quarantined';
23
+ type PodWorkerState = 'idle' | 'leased' | 'sanitizing' | 'timeout-fenced' | 'quarantined';
24
24
  interface PodWorkerLeaseAttrs {
25
25
  key: PodWorkerKey;
26
26
  podUid: string;
@@ -32,6 +32,9 @@ interface PodWorkerLeaseAttrs {
32
32
  /** The just-sanitized generation remains fenceable until the next acquisition. */
33
33
  lastLeaseId?: string;
34
34
  lastLeaseOwner?: string;
35
+ timeoutFenceUntil?: number;
36
+ timeoutRunId?: string;
37
+ timeoutAttemptId?: string;
35
38
  runId?: string;
36
39
  attemptId?: string;
37
40
  reason?: string;
@@ -231,17 +234,35 @@ export class ResourceLedger {
231
234
  return this.mutate(() => {
232
235
  const at = now ?? Date.now();
233
236
  const rows = this.read();
237
+ let expiredFenceChanged = false;
238
+ for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
239
+ const candidate = rows[rowIndex]!;
240
+ if (candidate.kind !== 'pod-worker-lease') continue;
241
+ const candidateAttrs = workerAttrs(candidate);
242
+ if (candidateAttrs.state !== 'timeout-fenced' || candidateAttrs.timeoutFenceUntil === undefined
243
+ || candidateAttrs.timeoutFenceUntil > at || candidateAttrs.leaseId) continue;
244
+ const idleAttrs: PodWorkerLeaseAttrs = { ...candidateAttrs, state: 'idle' };
245
+ delete idleAttrs.leaseId; delete idleAttrs.leaseOwner; delete idleAttrs.runId; delete idleAttrs.attemptId;
246
+ delete idleAttrs.timeoutFenceUntil; delete idleAttrs.timeoutRunId; delete idleAttrs.timeoutAttemptId;
247
+ rows[rowIndex] = { ...candidate, attrs: idleAttrs as unknown as Record<string, unknown>, observedAt: at,
248
+ ttlMs: candidateAttrs.idleTtlMs };
249
+ expiredFenceChanged = true;
250
+ }
234
251
  const index = rows.findIndex(row => row.kind === 'pod-worker-lease' && (!request.machine || row.machine === request.machine)
235
252
  && Math.max(0, at - row.observedAt) < row.ttlMs && workerAttrs(row).state === 'idle'
236
253
  && typeof workerAttrs(row).podUid === 'string' && workerAttrs(row).podUid.trim().length > 0
237
254
  && sameWorkerKey(workerAttrs(row).key, request.key));
238
- if (index < 0) throw new ResourceLedgerError(409, 'no-warm-worker');
255
+ if (index < 0) {
256
+ if (expiredFenceChanged) this.write(rows);
257
+ throw new ResourceLedgerError(409, 'no-warm-worker');
258
+ }
239
259
  const row = rows[index]!;
240
260
  const attrs = workerAttrs(row);
241
261
  const nextAttrs: PodWorkerLeaseAttrs = { ...attrs, state: 'leased', generation: attrs.generation + 1,
242
262
  leaseId: randomUUID(), leaseOwner: request.owner, runId: request.runId, attemptId: request.attemptId };
243
263
  delete nextAttrs.lastLeaseId;
244
264
  delete nextAttrs.lastLeaseOwner;
265
+ delete nextAttrs.timeoutFenceUntil; delete nextAttrs.timeoutRunId; delete nextAttrs.timeoutAttemptId;
245
266
  const next: ResourceRecord = { ...row, attrs: nextAttrs as unknown as Record<string, unknown>,
246
267
  observedAt: at, ttlMs: request.ttlMs };
247
268
  rows[index] = next;
@@ -250,6 +271,31 @@ export class ResourceLedger {
250
271
  });
251
272
  }
252
273
 
274
+ fenceTimedOutPodWorker(id: string, request: { owner: string; runId: string; attemptId: string; fenceMs: number }, now?: number): ResourceRecord {
275
+ return this.mutate(() => {
276
+ const at = now ?? Date.now();
277
+ const rows = this.read();
278
+ const index = rows.findIndex(row => row.id === id && row.kind === 'pod-worker-lease');
279
+ if (index < 0) throw new ResourceLedgerError(404, 'not-found');
280
+ const row = rows[index]!;
281
+ const attrs = workerAttrs(row);
282
+ const sameFence = attrs.state === 'timeout-fenced' && attrs.timeoutRunId === request.runId
283
+ && attrs.timeoutAttemptId === request.attemptId;
284
+ const sameLease = attrs.state === 'leased' && attrs.leaseOwner === request.owner
285
+ && attrs.runId === request.runId && attrs.attemptId === request.attemptId;
286
+ const available = attrs.state === 'idle';
287
+ if (!request.owner || !request.runId || !request.attemptId || !Number.isSafeInteger(request.fenceMs)
288
+ || request.fenceMs < 1 || !(sameFence || sameLease || available))
289
+ throw new ResourceLedgerError(409, 'stale-timeout-fence');
290
+ const nextAttrs: PodWorkerLeaseAttrs = { ...attrs, state: 'timeout-fenced',
291
+ timeoutFenceUntil: at + request.fenceMs, timeoutRunId: request.runId, timeoutAttemptId: request.attemptId };
292
+ const next: ResourceRecord = { ...row, attrs: nextAttrs as unknown as Record<string, unknown>, observedAt: at };
293
+ rows[index] = next;
294
+ this.write(rows);
295
+ return next;
296
+ });
297
+ }
298
+
253
299
  transitionPodWorker(id: string, request: { owner: string; leaseId: string; generation: number; action: 'renew' | 'release' | 'sanitize' | 'quarantine'; ttlMs?: number; reason?: string }, now?: number): ResourceRecord {
254
300
  return this.mutate(() => {
255
301
  now ??= Date.now();
@@ -260,11 +306,14 @@ export class ResourceLedger {
260
306
  const attrs = workerAttrs(row);
261
307
  const lateIdleQuarantine = request.action === 'quarantine' && attrs.state === 'idle'
262
308
  && attrs.lastLeaseId === request.leaseId && attrs.generation === request.generation;
309
+ const timeoutFencedQuarantine = request.action === 'quarantine' && attrs.state === 'timeout-fenced'
310
+ && attrs.leaseId === request.leaseId && attrs.generation === request.generation;
263
311
  if (!request.leaseId || (attrs.leaseId !== request.leaseId && !lateIdleQuarantine)
264
312
  || attrs.generation !== request.generation) throw new ResourceLedgerError(409, 'stale-worker-lease');
265
313
  const permitted = request.action === 'sanitize' ? row.owner === request.owner
266
314
  : request.action === 'quarantine' ? row.owner === request.owner || attrs.leaseOwner === request.owner
267
315
  || (lateIdleQuarantine && attrs.lastLeaseOwner === request.owner)
316
+ || (timeoutFencedQuarantine && attrs.leaseOwner === request.owner)
268
317
  : attrs.leaseOwner === request.owner;
269
318
  if (!permitted) {
270
319
  throw new ResourceLedgerError(403, 'not-owner');
@@ -283,6 +332,7 @@ export class ResourceLedger {
283
332
  } else if (state === 'quarantined') {
284
333
  delete nextAttrs.lastLeaseId;
285
334
  delete nextAttrs.lastLeaseOwner;
335
+ delete nextAttrs.timeoutFenceUntil; delete nextAttrs.timeoutRunId; delete nextAttrs.timeoutAttemptId;
286
336
  }
287
337
  const ttlMs = state === 'idle' ? attrs.idleTtlMs : request.ttlMs ?? row.ttlMs;
288
338
  const next: ResourceRecord = { ...row, attrs: nextAttrs as unknown as Record<string, unknown>, observedAt: now, ttlMs };
@@ -10,6 +10,7 @@ import type { LeaseHolderView } from './lease-holder.js';
10
10
  export const DEFAULT_CONTROL_PORT = PORT_BANDS.reserved[0];
11
11
  export const CONTROL_HOSTNAME = '127.0.0.1';
12
12
  const MAX_POD_WORKER_TTL_MS = 24 * 60 * 60 * 1000;
13
+ const POD_WORKER_TIMEOUT_FENCE_MS = 150_000;
13
14
 
14
15
  export function allowedControlHostname(hostname: string): boolean {
15
16
  if (hostname === '127.0.0.1' || hostname === '::1') return true;
@@ -126,7 +127,7 @@ export function startControlServer(opts: ControlServerOptions = {}): {
126
127
  const leaseRenewal = /^\/v1\/leases\/port\/([^/]+)\/heartbeat$/.exec(path);
127
128
  const workerRegister = path === '/v1/workers/pod' && method === 'POST';
128
129
  const workerAcquire = path === '/v1/leases/pod-worker' && method === 'POST';
129
- const workerTransition = /^\/v1\/leases\/pod-worker\/([^/]+)\/(renew|release|sanitize|quarantine)$/.exec(path);
130
+ const workerTransition = /^\/v1\/leases\/pod-worker\/([^/]+)\/(renew|release|sanitize|quarantine|timeout)$/.exec(path);
130
131
  if (!resourcePath && !registerPath && !leaseRequest && !workerRegister && !workerAcquire && !(workerTransition && method === 'POST') && !(leaseDeletion && method === 'DELETE') && !(leaseRenewal && method === 'POST') && !(heartbeat && method === 'POST') && !(deletion && method === 'DELETE')) {
131
132
  return json({ error: 'not-found' }, 404);
132
133
  }
@@ -191,7 +192,20 @@ export function startControlServer(opts: ControlServerOptions = {}): {
191
192
  if (workerTransition) {
192
193
  const workerId = decodeURIComponent(workerTransition[1]!);
193
194
  if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,95}$/.test(workerId)) throw new ResourceLedgerError(400, 'invalid-worker-id');
194
- const action = workerTransition[2] as 'renew' | 'release' | 'sanitize' | 'quarantine';
195
+ const action = workerTransition[2] as 'renew' | 'release' | 'sanitize' | 'quarantine' | 'timeout';
196
+ if (action === 'timeout') {
197
+ if (scope !== 'member') throw new ResourceLedgerError(403, 'worker-timeout-scope');
198
+ const body = podWorkerBody(await req.json());
199
+ const { runId, attemptId } = body;
200
+ if (typeof runId !== 'string' || !runId.trim() || typeof attemptId !== 'string' || !attemptId.trim())
201
+ throw new ResourceLedgerError(400, 'invalid-pod-worker-timeout');
202
+ const id = `pod-worker-lease:${workerId}`;
203
+ requireTarget(id);
204
+ const stale = await currentWorkerPrimary();
205
+ if (stale) return stale;
206
+ return json(await ledger.withGuardedWorkerMutation(async () => !(await currentWorkerPrimary()),
207
+ () => ledger.fenceTimedOutPodWorker(id, { owner, runId, attemptId, fenceMs: POD_WORKER_TIMEOUT_FENCE_MS })));
208
+ }
195
209
  if (action === 'sanitize' ? !machine : (action === 'renew' || action === 'release') && scope !== 'member') {
196
210
  throw new ResourceLedgerError(403, 'worker-scope');
197
211
  }