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
@@ -0,0 +1,159 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { debug } from '../../src/debug/log.js';
4
+ import type { GraphContext } from './node-verdict.js';
5
+ import type { ReleaseLoopConfig } from './unattended-release.js';
6
+
7
+ export type ReleaseTrafficEvent = 'gate-passed' | 'verify-complete';
8
+
9
+ export interface TrafficFile {
10
+ global?: string;
11
+ seats: Record<string, Record<string, unknown>>;
12
+ releaseLifecycle?: { runId: string; version: string; stage: 1 | 2; event: ReleaseTrafficEvent; startedAt?: string; updatedAt: string };
13
+ [key: string]: unknown;
14
+ }
15
+
16
+ type ReleaseTrafficConfig = ReleaseLoopConfig & {
17
+ trafficFile?: string;
18
+ };
19
+
20
+ const SEATS = ['OP', 'TC', 'MK', 'UX'] as const;
21
+ const STAGE: Record<ReleaseTrafficEvent, 1 | 2> = { 'gate-passed': 1, 'verify-complete': 2 };
22
+ const TRAFFIC_PER_CYCLE = { half: 3, full: 6 } as const;
23
+
24
+ export interface TrafficTransitionOptions {
25
+ trafficFile?: string;
26
+ lockTimeoutMs?: number;
27
+ now?: () => Date;
28
+ log?: (event: string, fields: Record<string, unknown>) => void;
29
+ }
30
+
31
+ function waitSync(ms: number): void {
32
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
33
+ }
34
+
35
+ function acquireTrafficLock(path: string, timeoutMs = 10_000): () => void {
36
+ const lock = `${path}.lock.d`;
37
+ const deadline = Date.now() + timeoutMs;
38
+ for (let attempt = 0; ; attempt += 1) {
39
+ try {
40
+ mkdirSync(lock);
41
+ try { writeFileSync(`${lock}/pid`, `${process.pid}\n`, { flag: 'wx', mode: 0o600 }); }
42
+ catch (error) { rmSync(lock, { recursive: true, force: true }); throw error; }
43
+ return () => rmSync(lock, { recursive: true, force: true });
44
+ } catch (error) {
45
+ if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error;
46
+ try {
47
+ // A directory cannot be conditionally renamed by identity. Reclaiming after
48
+ // checking its PID can therefore move a replacement owner's live lock.
49
+ // Fail closed; OP can inspect and remove a stale lock after the warning mail.
50
+ readFileSync(`${lock}/pid`, 'utf8');
51
+ statSync(lock);
52
+ } catch { /* Unknown or concurrently changing locks are left intact. */ }
53
+ if (Date.now() >= deadline) throw new Error(`traffic lock timeout: ${lock}`);
54
+ waitSync(100);
55
+ }
56
+ }
57
+ }
58
+
59
+ function readTrafficFile(path: string): TrafficFile {
60
+ const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));
61
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('traffic file must contain a JSON object');
62
+ const file = parsed as TrafficFile;
63
+ if (!file.seats || typeof file.seats !== 'object' || Array.isArray(file.seats)
64
+ || !SEATS.every((seat) => file.seats[seat] && typeof file.seats[seat] === 'object' && !Array.isArray(file.seats[seat]))) {
65
+ throw new Error('traffic seats object missing');
66
+ }
67
+ return file;
68
+ }
69
+
70
+ function atomicWriteTrafficFile(path: string, file: TrafficFile): void {
71
+ const temp = `${path}.tmp.${process.pid}.${Date.now()}`;
72
+ const mode = statSync(path).mode & 0o777;
73
+ try {
74
+ writeFileSync(temp, `${JSON.stringify(file, null, 2)}\n`, { flag: 'wx', mode });
75
+ renameSync(temp, path);
76
+ } catch (error) {
77
+ rmSync(temp, { force: true });
78
+ throw error;
79
+ }
80
+ }
81
+
82
+ function compareReleaseVersions(left: string, right: string): number {
83
+ const parse = (value: string) => /^(\d+)\.(\d+)\.(\d+)(?:-(alpha|beta|rc)\.(\d+))?$/.exec(value);
84
+ const a = parse(left), b = parse(right);
85
+ if (!a || !b) return left.localeCompare(right);
86
+ for (const index of [1, 2, 3]) {
87
+ const delta = Number(a[index]) - Number(b[index]);
88
+ if (delta) return Math.sign(delta);
89
+ }
90
+ if (!a[4] || !b[4]) return a[4] ? -1 : b[4] ? 1 : 0;
91
+ const rank = { alpha: 0, beta: 1, rc: 2 } as const;
92
+ const kind = rank[a[4] as keyof typeof rank] - rank[b[4] as keyof typeof rank];
93
+ return kind || Math.sign(Number(a[5]) - Number(b[5]));
94
+ }
95
+
96
+ function isLaterRun(current: string | undefined, previous: string | undefined): boolean {
97
+ return Boolean(current && previous && current > previous);
98
+ }
99
+
100
+ /** Apply one monotonic release graph event while preserving unrelated traffic policy fields. */
101
+ export async function applyReleaseTrafficEvent(
102
+ context: GraphContext,
103
+ event: ReleaseTrafficEvent,
104
+ options: TrafficTransitionOptions,
105
+ ): Promise<{ applied: boolean; stage: number; reason?: string }> {
106
+ if (!context.runId) throw new Error('release traffic event requires graph runId');
107
+ if (!options.trafficFile) throw new Error('traffic file path is not configured');
108
+ const runId = context.runId;
109
+ const version = context.input.version;
110
+ const path = resolve(options.trafficFile);
111
+ if (!existsSync(path)) throw new Error(`traffic file does not exist: ${path}`);
112
+ const log = options.log ?? ((name, fields) => debug.log('release-loop.traffic', name, fields));
113
+ const stage = STAGE[event];
114
+ const stamp = (options.now ?? (() => new Date()))().toISOString();
115
+ const rate = event === 'gate-passed' ? TRAFFIC_PER_CYCLE.half : TRAFFIC_PER_CYCLE.full;
116
+ const releaseLifecycle = { runId, version, stage, event, ...(context.startedAt ? { startedAt: context.startedAt } : {}), updatedAt: stamp };
117
+ const release = () => {
118
+ const unlock = acquireTrafficLock(path, options.lockTimeoutMs);
119
+ try {
120
+ const before = readTrafficFile(path);
121
+ const prior = before.releaseLifecycle;
122
+ const sameRun = prior?.runId === runId;
123
+ const newerVersion = !prior?.runId || compareReleaseVersions(version, prior.version) > 0;
124
+ const sameVersionLaterRun = prior?.version === version && isLaterRun(context.startedAt, prior.startedAt);
125
+ if (sameRun && prior.stage >= stage) return { file: before, applied: true, idempotent: true };
126
+ const permitted = sameRun
127
+ ? prior.stage === stage - 1
128
+ : newerVersion || (event === 'gate-passed' && prior?.version === version && (prior.stage ?? 0) < 2 && sameVersionLaterRun)
129
+ || (event === 'verify-complete' && prior?.version === version && sameVersionLaterRun);
130
+ if (!permitted) {
131
+ return { file: before, applied: false, idempotent: false, reason: prior?.runId && prior.runId !== runId ? 'different-run-is-current' : 'event-out-of-order' };
132
+ }
133
+ const after: TrafficFile = {
134
+ ...before,
135
+ ...(event === 'verify-complete' ? { global: 'green' } : {}),
136
+ seats: Object.fromEntries(Object.entries(before.seats).map(([seat, value]) => [
137
+ seat, SEATS.includes(seat as typeof SEATS[number]) ? { ...value, perCycle: rate } : value,
138
+ ])),
139
+ releaseLifecycle,
140
+ };
141
+ atomicWriteTrafficFile(path, after);
142
+ return { file: after, applied: true, idempotent: false };
143
+ } finally { unlock(); }
144
+ };
145
+ const result = release();
146
+ const reason = result.applied && result.idempotent ? 'already-applied' : result.reason;
147
+ log(result.idempotent ? 'already-applied' : result.applied ? 'applied' : 'ignored', {
148
+ runId, version, event, stage, reason, perCycle: rate, ...(event === 'verify-complete' ? { global: 'green' } : {}),
149
+ });
150
+ return { applied: result.applied, stage: result.file.releaseLifecycle?.stage ?? 0, ...(reason ? { reason } : {}) };
151
+ }
152
+
153
+ export function trafficOptionsFromConfig(env: NodeJS.ProcessEnv = process.env, rawConfig: ReleaseLoopConfig = {}): TrafficTransitionOptions {
154
+ const config = rawConfig as ReleaseTrafficConfig;
155
+ const envTrafficFile = env.ELANOUS_RELEASE_TRAFFIC_FILE?.trim();
156
+ const configTrafficFile = typeof config.trafficFile === 'string' ? config.trafficFile.trim() : undefined;
157
+ const trafficFile = envTrafficFile || configTrafficFile;
158
+ return trafficFile ? { trafficFile } : {};
159
+ }
@@ -39,6 +39,8 @@ export interface ReleaseLoopConfig {
39
39
  gatePodCpu?: number | string | { request?: number | string; limit?: number | string };
40
40
  gateRemote?: string;
41
41
  gateRemoteMirror?: string;
42
+ /** RELEASE-PWA-NODE-RESILIENCE ① — SSH host the `pwa` node runs its scenario suite on (e.g. `node-b`); absent = this machine. No fallback. */
43
+ pwaRemote?: string;
42
44
  opsHosts?: string[];
43
45
  internalDist?: string;
44
46
  opsRestart?: boolean;
@@ -15,7 +15,10 @@ import { loopEvent } from '../../src/loops/observe.js';
15
15
  import { kindRouteTarget, mainHomeTarget } from '../../src/domains/telegram-kind-route.js';
16
16
  import { recordOutbound } from '../../src/domains/outbound-alert.js';
17
17
  import { listSelfDevRuns, runSummaryLine, selfDevRunsDir } from '../../src/self-dev/run-store.js';
18
- import { runDraftSweep } from '../../src/self-dev/draft-sweep.js';
18
+ import { runDraftSweep, sweptReasonLabel } from '../../src/self-dev/draft-sweep.js';
19
+ import { LogStore } from '../../src/mss/logging/log-store.js';
20
+ import { BriefItemsLedger } from '../../src/briefing/brief-items.js';
21
+ import { debug } from '../../src/debug/log.js';
19
22
  import { retroBriefingLines } from '../../src/retro/daily.js';
20
23
  import { dispatchCooAdmin } from '../../src/domains/coo-admin-tool.js';
21
24
 
@@ -76,6 +79,133 @@ export function collectRunSummaries(now: Date, root = effectiveInstanceRoot(), l
76
79
  prNumbers }));
77
80
  }
78
81
 
82
+ /**
83
+ * DRAFT-SWEEP-DAILY-SUMMARY — 닫힌 draft 사유를 «하루 한 번 브리핑 원장 1건» 으로 적는다.
84
+ * 사유의 정본은 DRAFT-SWEEP-QUIET 이 닫을 때 남기는 `closed` 로그(PR 댓글 0 계약은 그쪽이 지킨다)이고,
85
+ * 이 경로는 로그 원장 «읽기» ⊕ 브리핑 원장 «쓰기» 만 한다 — GitHub 에 아무것도 쓰지 않는다.
86
+ */
87
+ export const DRAFT_CLOSE_BRIEF_SOURCE = 'rhythm.daily.draft-close';
88
+ /** DRAFT-SWEEP-QUIET 가 닫힌 draft마다 남기는 로그 — 사유의 정본 좌표. */
89
+ const SWEPT_DRAFT_LOG = { category: 'self-dev.draft-sweep', event: 'closed' } as const;
90
+ const SWEPT_LABEL_PREFIX = 'elanous:swept:';
91
+
92
+ export type ClosedDraftReason = { reason: string; count: number };
93
+ export type ClosedDraftCount = { closed: number; reasons: ClosedDraftReason[]; unreadable: number };
94
+ export type DraftCloseSummary = {
95
+ /** 요약이 다루는 날짜(어제, KST). */
96
+ day: string;
97
+ closed: number;
98
+ reasons: ClosedDraftReason[];
99
+ /** 브리핑 원장에 실린 한 줄 — 표본이 없으면 null. */
100
+ text: string | null;
101
+ state: 'recorded' | 'already-recorded' | 'unmeasured' | 'unreadable';
102
+ /** 미측정·실패 사유(한 줄). */
103
+ detail?: string;
104
+ itemId?: number;
105
+ };
106
+
107
+ /** `closed` 로그 한 줄의 `{ reason }` — Pod 전달 래퍼(`originalData`)도 벗긴다. 못 읽으면 null. */
108
+ function closedLogReason(data: string | null): string | null {
109
+ if (typeof data !== 'string' || !data.trim()) return null;
110
+ let payload: unknown;
111
+ try { payload = JSON.parse(data); } catch { return null; }
112
+ let body = record(payload);
113
+ const forwarded = body.originalData;
114
+ if (forwarded !== undefined) {
115
+ if (typeof forwarded !== 'string') body = record(forwarded);
116
+ else { try { body = record(JSON.parse(forwarded)); } catch { return null; } }
117
+ }
118
+ const reason = string(body.reason).trim();
119
+ return reason ? shortReason(reason) : null;
120
+ }
121
+
122
+ /** 사유를 DRAFT-SWEEP-QUIET 의 사유 종류로 접는다(`superseded-by #24123` → `superseded-by`). */
123
+ export function sweptReasonKind(reason: string): string {
124
+ const label = sweptReasonLabel(reason);
125
+ return label.startsWith(SWEPT_LABEL_PREFIX) ? label.slice(SWEPT_LABEL_PREFIX.length) : label;
126
+ }
127
+
128
+ /**
129
+ * 어제(KST 00:00–24:00) 닫힌 draft 사유를 로그 원장에서 센다.
130
+ * ⛔ 원장이 없거나 못 읽으면 null — «0건»이 아니라 «미측정»이다.
131
+ */
132
+ export function collectClosedDrafts(root: string, now: Date): ClosedDraftCount | null {
133
+ const path = join(root, 'logs', 'logs.db');
134
+ if (!existsSync(path)) return null;
135
+ const from = new Date(`${kstDay(new Date(now.getTime() - 86_400_000))}T00:00:00+09:00`);
136
+ const store = LogStore.openReadOnly(path);
137
+ try {
138
+ const rows = store.queryAll({ exactCategories: [SWEPT_DRAFT_LOG.category], events: [SWEPT_DRAFT_LOG.event],
139
+ sinceMs: from.getTime(), untilMs: from.getTime() + 86_400_000 - 1 });
140
+ const counts = new Map<string, number>();
141
+ let unreadable = 0;
142
+ for (const row of rows) {
143
+ const reason = closedLogReason(row.data);
144
+ if (reason === null) { unreadable += 1; continue; }
145
+ const kind = sweptReasonKind(reason);
146
+ counts.set(kind, (counts.get(kind) ?? 0) + 1);
147
+ }
148
+ return { closed: [...counts.values()].reduce((sum, count) => sum + count, 0),
149
+ reasons: [...counts].map(([reason, count]) => ({ reason, count }))
150
+ .sort((a, b) => b.count - a.count || sortNames(a.reason, b.reason)),
151
+ unreadable };
152
+ } finally { store.close(); }
153
+ }
154
+
155
+ /** 브리핑 한 줄 — 사유 종류별 건수, 상위 5종만 적고 나머지는 «외 N종» 으로 접는다. */
156
+ export function composeDraftCloseSummaryText(reasons: readonly ClosedDraftReason[]): string {
157
+ const total = reasons.reduce((sum, item) => sum + item.count, 0);
158
+ const shown = reasons.slice(0, 5).map(item => `${item.reason} ${item.count}`).join(' · ');
159
+ const omitted = Math.max(0, reasons.length - 5);
160
+ return `어제 닫힌 draft ${total}건${shown ? ` — ${shown}` : ''}${omitted > 0 ? ` · 외 ${omitted}종` : ''}`;
161
+ }
162
+
163
+ /**
164
+ * 어제 닫힌 draft 사유를 브리핑 원장(`<state>/briefing/items.sqlite`, `eln brief`)에 **하루 1건** 으로 적는다.
165
+ * 표본이 없거나 원장을 못 읽으면 아무것도 쓰지 않고 `unmeasured`/`unreadable` 로 남긴다(«0건»으로 적지 않는다).
166
+ * 관측은 `deps.log`(루프 tick 전용)가 아니라 로그에 직접 남긴다 — 데일리 tick 의 의미를 바꾸지 않는다.
167
+ */
168
+ export function recordDraftCloseSummary(root: string, now: Date,
169
+ log: (category: string, event: string, data?: unknown) => void = (category, event, data) => debug.log(category, event, data),
170
+ ): DraftCloseSummary {
171
+ const observe = (summary: DraftCloseSummary): DraftCloseSummary => {
172
+ try {
173
+ log('rhythm.daily', 'draft-close-summary', { day: summary.day, closed: summary.closed, state: summary.state,
174
+ reasons: summary.reasons.map(item => `${item.reason} ${item.count}`).join(' · '),
175
+ ...(summary.detail ? { detail: summary.detail } : {}), ...(summary.itemId === undefined ? {} : { itemId: summary.itemId }) });
176
+ } catch { /* 관측 실패가 브리핑을 막지 않는다 */ }
177
+ return summary;
178
+ };
179
+ const day = kstDay(new Date(now.getTime() - 86_400_000));
180
+ let counted: ClosedDraftCount | null;
181
+ try { counted = collectClosedDrafts(root, now); }
182
+ catch (error) { return observe({ day, closed: 0, reasons: [], text: null, state: 'unreadable',
183
+ detail: shortReason(`로그 원장 못 읽음 · ${reasonOf(error)}`) }); }
184
+ if (counted === null) return observe({ day, closed: 0, reasons: [], text: null, state: 'unmeasured', detail: '로그 원장 없음' });
185
+ if (counted.closed === 0) return observe({ day, closed: 0, reasons: [], text: null, state: 'unmeasured',
186
+ detail: counted.unreadable > 0 ? `사유 못 읽은 closed 로그 ${counted.unreadable}건` : '닫힌 draft 없음' });
187
+ // 사유를 못 읽은 closed 로그가 섞이면 읽힌 건수만으로 닫힘 총수를 단정할 수 없다 — 원장에 확정 기록하지 않고 부분 미측정으로 남긴다.
188
+ if (counted.unreadable > 0) return observe({ day, closed: counted.closed, reasons: counted.reasons, text: null,
189
+ state: 'unmeasured',
190
+ detail: `사유 못 읽은 closed 로그 ${counted.unreadable}건 — 읽힌 ${counted.closed}건만 셈(부분 미측정)` });
191
+ const text = composeDraftCloseSummaryText(counted.reasons);
192
+ try {
193
+ const ledger = new BriefItemsLedger({ stateDir: root, now: () => now, log });
194
+ const today = kstDay(now);
195
+ const recorded = ledger.list().find(item => item.source === DRAFT_CLOSE_BRIEF_SOURCE
196
+ && kstDay(new Date(item.created_at)) === today);
197
+ if (recorded) return observe({ day, closed: counted.closed, reasons: counted.reasons, text,
198
+ state: 'already-recorded', itemId: recorded.id });
199
+ const item = ledger.add({ text, domain: '운영', priority: 'P2', source: DRAFT_CLOSE_BRIEF_SOURCE,
200
+ evidence: `elanous logs --category ${SWEPT_DRAFT_LOG.category} --event ${SWEPT_DRAFT_LOG.event} --since 24h`,
201
+ createdAt: now.toISOString(), dedupeKey: `${DRAFT_CLOSE_BRIEF_SOURCE}:${today}`, dedupeWithinMs: 86_400_000 });
202
+ return observe({ day, closed: counted.closed, reasons: counted.reasons, text, state: 'recorded', itemId: item.id });
203
+ } catch (error) {
204
+ return observe({ day, closed: counted.closed, reasons: counted.reasons, text, state: 'unreadable',
205
+ detail: shortReason(`브리핑 원장 못 씀 · ${reasonOf(error)}`) });
206
+ }
207
+ }
208
+
79
209
  /** 기본은 어제 KST 00:00–24:00, 창을 주면 그 안에 실제 병합된 PR만 센다. */
80
210
  export async function collectLandings(now: Date, window?: { from: Date; to: Date }, source?: { repoRoot?: string; repoName?: string; stateRoot?: string }): Promise<Landing[]> {
81
211
  const configuredTree = source?.repoRoot ?? getUserConfig().ops?.cronRepoRoot;
@@ -495,7 +625,8 @@ export async function runDaily(options: { dryRun?: boolean; noNews?: boolean; st
495
625
  else loopEvent('rhythm-daily', 'tick', tick);
496
626
  }
497
627
  }
498
- return { file, markdown, header, risks, sections, sent, ...vault, sendError, recordError, status, deliveryState, deliveryLine };
628
+ return { file, markdown, header, risks, sections, sent, ...vault, sendError, recordError, status, deliveryState, deliveryLine,
629
+ draftCloseSummary: undefined };
499
630
  }
500
631
  const safe = async <T>(fetch: () => Promise<T>): Promise<Section<T>> => {
501
632
  try { return { status: 'ok', value: await fetch() }; } catch (e) { return unreadable(reasonOf(e)); }
@@ -589,6 +720,9 @@ export async function runDaily(options: { dryRun?: boolean; noNews?: boolean; st
589
720
  writeFileSync(file, review.markdown);
590
721
  }
591
722
  const { vaultError, vaultFatal } = options.dryRun ? { vaultError: null, vaultFatal: false } : copyToVault(review.markdown, now, deps);
723
+ // DRAFT-SWEEP-DAILY-SUMMARY — 어제 닫힌 draft 사유를 오늘 브리핑 원장 1건으로 적는다(PR별 댓글 0 유지).
724
+ // --dry-run 은 원장에 쓰지 않는다(다른 산출물과 같은 규칙).
725
+ const draftCloseSummary = options.dryRun ? undefined : recordDraftCloseSummary(root, now);
592
726
  let enabled = deps.sendEnabled === true;
593
727
  let sendError: string | null = null;
594
728
  let deliveryState = options.stage === 'collect' ? 'pending' : options.dryRun ? 'dry-run' : 'send-disabled';
@@ -628,7 +762,7 @@ export async function runDaily(options: { dryRun?: boolean; noNews?: boolean; st
628
762
  else loopEvent('rhythm-daily', 'tick', tick);
629
763
  }
630
764
  }
631
- return { file, ...review, sent, vaultError, vaultFatal, sendError, recordError, status, deliveryState, deliveryLine };
765
+ return { file, ...review, sent, vaultError, vaultFatal, sendError, recordError, status, deliveryState, deliveryLine, draftCloseSummary };
632
766
  }
633
767
 
634
768
  export async function main(args: string[] = process.argv.slice(2), deps: DailyDeps = {}): Promise<Awaited<ReturnType<typeof runDaily>>> {
@@ -93,7 +93,12 @@ export type Verdict = 'keep' | 'failing' | 'review';
93
93
  export type Proposal = 'delete' | 'shrink' | 'rewrite-cheap' | 'move-out-of-gate' | 'investigate';
94
94
  export interface Td1Disposition { disposition: string; alternative: string; guards: string; why_slow: string }
95
95
  export interface Judged extends Measurement { caught90: number; flags: string[]; verdict: Verdict; effectiveness?: Effectiveness; proposal?: Proposal | null; basis?: string | null }
96
- export interface LedgerLine { at: string; range: string; start: number; end: number; next: number; total: number; commit: string; budgetSecs: number; results: Judged[]; sweepVisited?: number; sweepCostSecs?: number; sweepSlices?: number }
96
+ export interface LedgerLine {
97
+ at: string; range: string; start: number; end: number; next: number; total: number; commit: string; budgetSecs: number; results: Judged[];
98
+ /** Exact non-contiguous selection; `range` encodes these indices in selection order. */
99
+ selectedFiles?: string[]; selectedIndices?: number[];
100
+ sweepVisited?: number; sweepCostSecs?: number; sweepSlices?: number;
101
+ }
97
102
 
98
103
  /** `file\tsecs\t…` (TD1 whole-gate TSV) → seconds per file. */
99
104
  export function costTable(tsv: string): Map<string, number> {
@@ -7,12 +7,13 @@ import { appendFileSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSyn
7
7
  import { tmpdir } from 'node:os';
8
8
  import { join } from 'node:path';
9
9
  import { debug } from '../../src/debug/log.js';
10
- import { effectiveInstanceRoot } from '../../src/instance/resolve.js';
10
+ import { effectiveInstanceRoot, releaseLedgerRoot } from '../../src/instance/resolve.js';
11
11
  import { CardStore } from '../../src/task-cards/card-store.js';
12
12
  import { GATE_NIGHTLY_AUDITS } from '../release-loop/gate-node.js';
13
13
  import { isCredentialKey } from '../lib/deterministic-env.js';
14
14
  import { appendLedger, costTable, judge, lastLedgerLine, ledgerPath, mainFailureFiles, nightlyAuditLedgerPath, pickRange, propose, td1Dispositions, writeCardDraft, writeMainFailureDay, type LedgerLine, type MainFailureResult, type Measurement, type Td1Disposition } from './lib.js';
15
15
  import { fixedCountAssertions, flakeVerdict, sweepSlice, unreachableImports, type Mutation, type TestRun } from './effectiveness.js';
16
+ import { gateHistory, type GateHistoryRow } from '../release-loop/gate-history.js';
16
17
 
17
18
  type Context = { graphId?: string; input: Record<string, unknown>; outputs: Record<string, Record<string, unknown> | null> };
18
19
  function context(): Context {
@@ -27,6 +28,129 @@ function emit(result: Record<string, unknown> & { outcome: 'ok' | 'fail' | 'erro
27
28
  }
28
29
  const git = (args: string[]) => spawnSync('git', args, { encoding: 'utf8', maxBuffer: 64 * 1024 * 1024 }).stdout ?? '';
29
30
 
31
+ /**
32
+ * GATE-FAIL-HISTORY → per-file failure likelihood (boundary ①): a file the landed gate already failed on is picked
33
+ * before one it never failed on, and preexisting/knownEnv repeat offenders outrank one-off introduced/load-flaky hits.
34
+ */
35
+ const GATE_FAIL_WEIGHT = { preexisting: 4, knownEnv: 3, flaky: 3, introduced: 2 } as const;
36
+
37
+ /** Only the buckets the pick order and the prescription both read — no write-only fields. */
38
+ export type GateFailWeight = { file: string; weight: number; preexisting: number; knownEnv: number; flaky: number };
39
+
40
+ export function gateFailWeights(rows: readonly GateHistoryRow[]): Map<string, GateFailWeight> {
41
+ const weights = new Map<string, GateFailWeight>();
42
+ for (const row of rows) {
43
+ const weight = row.preexisting * GATE_FAIL_WEIGHT.preexisting + row.env * GATE_FAIL_WEIGHT.knownEnv
44
+ + row.flaky * GATE_FAIL_WEIGHT.flaky + row.introduced * GATE_FAIL_WEIGHT.introduced;
45
+ if (weight <= 0) continue;
46
+ const file = String(row.file);
47
+ weights.set(file, { file, weight, preexisting: row.preexisting, knownEnv: row.env, flaky: row.flaky });
48
+ }
49
+ return weights;
50
+ }
51
+
52
+ /** Reads the gate's own failure ledger; an unreadable ledger is an empty history, never a failed pick. */
53
+ export function loadGateFailWeights(deps: {
54
+ instanceRoots?: readonly string[]; ledgerRoots?: readonly string[]; rows?: readonly GateHistoryRow[];
55
+ } = {}): Map<string, GateFailWeight> {
56
+ if (deps.rows) return gateFailWeights(deps.rows);
57
+ try {
58
+ const report = gateHistory({
59
+ instanceRoots: deps.instanceRoots ?? [effectiveInstanceRoot()],
60
+ ledgerRoots: deps.ledgerRoots ?? [releaseLedgerRoot()],
61
+ }, { mergedPrs: () => [] });
62
+ return gateFailWeights(report.rows);
63
+ } catch (error) {
64
+ debug.log('test-diet', 'history-read-failed', { error: String(error) });
65
+ return new Map();
66
+ }
67
+ }
68
+
69
+ /**
70
+ * `pickRange` with the history-weighted order on top: every gate-failed file that fits the budget comes first
71
+ * (weight desc, then cheaper), the cursor slice fills the rest. Cursor `next` only advances past cursor files the
72
+ * budget actually selected — an unselected cursor file stays before `next`, so no file is skipped in a daily verdict
73
+ * or a sweep.
74
+ */
75
+ export function pickWithHistory(files: readonly string[], start: number, costs: ReadonlyMap<string, number>, budgetSecs: number,
76
+ weights: ReadonlyMap<string, GateFailWeight>): ReturnType<typeof pickRange> & {
77
+ historyFiles: GateFailWeight[]; selectedIndices: number[]; rangeLabel: string; cursorVisitedCount: number;
78
+ } {
79
+ const range = pickRange(files, start, costs, budgetSecs);
80
+ const cost = (file: string) => costs.get(file) ?? 10;
81
+ const historyFiles = [...weights.values()].filter((entry) => files.includes(entry.file))
82
+ .sort((a, b) => b.weight - a.weight || cost(a.file) - cost(b.file) || a.file.localeCompare(b.file));
83
+ const describeSelection = (selectedFiles: string[]) => {
84
+ const selectedIndices = selectedFiles.map((file) => files.indexOf(file));
85
+ const contiguous = selectedIndices.length > 0
86
+ && selectedIndices.every((index, position) => position === 0 || index === selectedIndices[position - 1]! + 1);
87
+ const rangeLabel = selectedIndices.length === 0 ? '#empty'
88
+ : contiguous ? `#${selectedIndices[0]}~#${selectedIndices.at(-1)}`
89
+ : selectedIndices.map((index) => `#${index}`).join(',');
90
+ return { selectedIndices, rangeLabel };
91
+ };
92
+ if (historyFiles.length === 0) return { ...range, historyFiles, cursorVisitedCount: range.files.length, ...describeSelection(range.files) };
93
+ const ordered: string[] = [];
94
+ let estimatedSecs = 0;
95
+ for (const file of [...historyFiles.map((entry) => entry.file), ...range.files]) {
96
+ if (ordered.includes(file)) continue;
97
+ const added = cost(file);
98
+ if (ordered.length > 0 && estimatedSecs + added > budgetSecs) continue;
99
+ ordered.push(file);
100
+ estimatedSecs += added;
101
+ }
102
+ // 예산을 이력 파일로 채웠을 때: 커서는 실제로 선택한 커서 조각까지만 전진한다.
103
+ // 선택되지 않은 커서 파일을 next 너머로 건너뛰면 일일 판정·sweep에서 영구 누락된다.
104
+ const firstUnpicked = range.files.findIndex((file) => !ordered.includes(file));
105
+ const next = firstUnpicked === -1 ? range.next : (range.start + firstUnpicked) % files.length;
106
+ return { ...range, files: ordered, estimatedSecs, historyFiles, next,
107
+ cursorVisitedCount: range.files.filter((file) => ordered.includes(file)).length, ...describeSelection(ordered) };
108
+ }
109
+
110
+ /** MANUAL-gate-regression-response-recipe §2 T1~T7, plus TA for a verdict that is only a draft for the card. */
111
+ export type CleanseRecipeType = 'T1' | 'T2' | 'T3' | 'T4' | 'T5' | 'T6' | 'T7' | 'TA';
112
+ export type CleanseRecipe = { type: CleanseRecipeType; file: string; action: string; basis: string };
113
+
114
+ const RECIPE_ACTIONS: Record<CleanseRecipeType, string> = {
115
+ T1: 'fixture·단언을 새 계약으로 고쳐 쓴다(제품 동작은 그대로)',
116
+ T2: '제품 회귀 — 제품 동작을 고친다(시험 완화 금지)',
117
+ T3: '규칙 문면을 규칙 원본과 맞춘다',
118
+ T4: '시험 문면을 지금 문안으로 맞춘다(프로토콜·기본 동작은 그대로)',
119
+ T5: '빈 환경 의존을 주입으로 없앤다(credential·경로·도구를 명시 주입)',
120
+ T6: '간섭을 격리한다(단독 실행·임시 HOME·동시성 낮춤)',
121
+ T7: '인프라 실패 — 재게이트하고 TA 카드로 사람에게 넘긴다',
122
+ TA: '결과를 TA 카드로 남긴다(지우기·이동은 사람·주인 확인)',
123
+ };
124
+
125
+ export type RecipeInput = { file: string; verdict: string; reason?: string; flaky?: boolean; effectiveness?: { flake?: string };
126
+ history?: { preexisting: number; knownEnv: number; flaky?: number } };
127
+
128
+ /** Exactly one prescription per verdict — the draft only, never a deletion. */
129
+ export function recipeFor(result: RecipeInput): CleanseRecipe {
130
+ const reason = (result.reason ?? '').toLowerCase();
131
+ const flaky = result.flaky === true || result.effectiveness?.flake === 'flaky';
132
+ const history = result.history;
133
+ // The gate ledger's flaky bucket is the same «history» the pick weighs, so a repeat-flaky file that measures
134
+ // keep still gets the isolation prescription (T6) instead of falling through to a bare TA card.
135
+ const historyFlaky = history?.flaky ?? 0;
136
+ const type: CleanseRecipeType = result.verdict === 'failing'
137
+ ? (/enospc|out of memory|cannot allocate|oomkilled|no space|pod .*(restart|terminat)|preempt/.test(reason) ? 'T7'
138
+ : flaky ? 'T6'
139
+ : /enoent|eacces|no llm provider|command not found|cannot find module|credential|api key|not found: |git config/.test(reason) ? 'T5'
140
+ : /timed out|timeout|waitfor|expected text|wording|문면/.test(reason) ? 'T4'
141
+ : /rules-contract|(^|\/)\.rules\//.test(result.file) ? 'T3'
142
+ : /typeerror|referenceerror|is not a function|is not defined|syntaxerror/.test(reason) ? 'T2'
143
+ : 'T1')
144
+ : history?.knownEnv ? 'T5'
145
+ : flaky || history?.preexisting || historyFlaky > 0 ? 'T6'
146
+ : 'TA';
147
+ const tail = reason.split('\n')[0]?.slice(0, 160) ?? '';
148
+ const historyBasis = history && (history.preexisting > 0 || history.knownEnv > 0 || historyFlaky > 0)
149
+ ? ` · gate history preexisting ${history.preexisting} · knownEnv ${history.knownEnv}`
150
+ + `${historyFlaky > 0 ? ` · flaky ${historyFlaky}` : ''}` : '';
151
+ return { type, file: result.file, action: RECIPE_ACTIONS[type], basis: `${result.verdict}${tail ? `: ${tail}` : ''}${historyBasis}` };
152
+ }
153
+
30
154
  function pick(ctx: Context, sweep = false): number {
31
155
  const files = git(['ls-files', '*.test.ts']).split('\n').filter(Boolean).sort();
32
156
  const costs = costTable(readFileSync(join(process.cwd(), 'docs/measurements/td1-whole-gate-mechanical-2026-10-01.tsv'), 'utf8'));
@@ -35,7 +159,7 @@ function pick(ctx: Context, sweep = false): number {
35
159
  const totalCostSecs = sweep ? files.reduce((sum, file) => sum + (costs.get(file) ?? 10), 0) : 0;
36
160
  // `start` re-looks a slice on purpose; otherwise continue from the ledger cursor.
37
161
  const startAt = typeof ctx.input.start === 'number' && ctx.input.start >= 0 ? ctx.input.start : last?.next ?? 0;
38
- const continuing = ctx.input.start === undefined && last?.sweepVisited && last.sweepVisited < files.length && last.next === startAt && last.total === files.length;
162
+ const continuing = ctx.input.start === undefined && typeof last?.sweepVisited === 'number' && last.sweepVisited < files.length && last.next === startAt && last.total === files.length;
39
163
  const remaining = continuing ? files.length - last.sweepVisited! : files.length;
40
164
  const elapsed = continuing ? last.sweepSlices ?? 0 : 0;
41
165
  const slotsLeft = Math.max(1, 28 - elapsed);
@@ -43,8 +167,13 @@ function pick(ctx: Context, sweep = false): number {
43
167
  slotsLeft, minBudgetSecs: continuing ? last.budgetSecs : 0 }) : undefined;
44
168
  const budgetSecs = sweepPlan?.budgetSecs
45
169
  ?? (typeof ctx.input.budgetSecs === 'number' && ctx.input.budgetSecs > 0 ? ctx.input.budgetSecs : 1800);
46
- const range = pickRange(files, startAt, costs, budgetSecs);
47
- return emit({ outcome: 'ok', summary: `test-diet pick #${range.start}~#${range.end} of ${files.length} (≈${Math.round(range.estimatedSecs)}s)`, ...range, total: files.length, budgetSecs,
170
+ const measuredLastSlice = new Set((last?.results ?? []).map((result) => result.file));
171
+ const cursorParked = last?.next === startAt && last.selectedIndices?.every((index) => index !== startAt);
172
+ // When a prior history-only slice left the cursor parked, force the next slice onto the cursor.
173
+ // Suppressing only the last history winner allows two weighted files to alternate forever.
174
+ const availableHistory = cursorParked ? new Map() : new Map([...loadGateFailWeights()].filter(([file]) => !measuredLastSlice.has(file)));
175
+ const range = pickWithHistory(files, startAt, costs, budgetSecs, availableHistory);
176
+ return emit({ outcome: 'ok', summary: `test-diet pick ${range.rangeLabel} of ${files.length} (≈${Math.round(range.estimatedSecs)}s)`, ...range, total: files.length, budgetSecs,
48
177
  ...(sweep ? { sweep: true, totalCostSecs, slicesNeeded: sweepPlan?.slicesNeeded, sweepElapsed: elapsed } : {}) });
49
178
  }
50
179
 
@@ -180,6 +309,23 @@ function recordNightlyAudit(ctx: Context): number {
180
309
  return emit({ outcome: failing ? 'fail' : 'ok', summary: `nightly audit ${results.length} · failing ${failing}${card ? ' · card draft' : ''}`, failing, ledger: path, ...(card ? { card } : {}) });
181
310
  }
182
311
 
312
+ /** The pick's own gate-history snapshot — `record` reads the files `pick` actually selected from, never a fresh
313
+ * ledger query, so the prescription and the ledger line keep the same basis even if the gate ledger changed
314
+ * between the two graph steps. */
315
+ function pickHistoryFiles(p: Record<string, unknown> | null): GateFailWeight[] {
316
+ const raw = p?.historyFiles;
317
+ if (!Array.isArray(raw)) return [];
318
+ const files: GateFailWeight[] = [];
319
+ for (const entry of raw) {
320
+ if (entry === null || typeof entry !== 'object') continue;
321
+ const x = entry as GateFailWeight;
322
+ if (typeof x.file !== 'string' || typeof x.weight !== 'number' || !Number.isFinite(x.weight)
323
+ || typeof x.preexisting !== 'number' || typeof x.knownEnv !== 'number' || typeof x.flaky !== 'number') continue;
324
+ files.push({ file: x.file, weight: x.weight, preexisting: x.preexisting, knownEnv: x.knownEnv, flaky: x.flaky });
325
+ }
326
+ return files;
327
+ }
328
+
183
329
  export function record(ctx: Context, deps: { createStore?: (root: string) => Pick<CardStore, 'createCard' | 'appendSection' | 'close'>; td1?: ReadonlyMap<string, Td1Disposition> } = {}): number {
184
330
  const p = ctx.outputs.pick;
185
331
  const m = ctx.outputs.measure;
@@ -188,27 +334,61 @@ export function record(ctx: Context, deps: { createStore?: (root: string) => Pic
188
334
  const td1 = deps.td1 ?? td1Dispositions(readFileSync(join(process.cwd(), 'docs/measurements/td1-top200-content-review-2026-10-01.tsv'), 'utf8'));
189
335
  const results = measurements.map((x) => propose(judge(x, git(['log', '--since=90.days', '--format=%s', '--', x.file]).split('\n').filter((s) => /^fix\b/i.test(s)).length), td1));
190
336
  const previous = p.sweep === true ? lastLedgerLine(effectiveInstanceRoot()) : null;
191
- const continuing = previous?.sweepVisited && previous.sweepVisited < Number(p.total)
337
+ const continuing = typeof previous?.sweepVisited === 'number' && previous.sweepVisited < Number(p.total)
192
338
  && previous.next === Number(p.start) && previous.total === Number(p.total);
193
- const visited = p.sweep === true ? Math.min(Number(p.total), (continuing ? previous.sweepVisited! : 0) + results.length) : undefined;
339
+ const visited = p.sweep === true ? Math.min(Number(p.total), (continuing ? previous.sweepVisited! : 0) + Number(p.cursorVisitedCount ?? results.length)) : undefined;
194
340
  const sweepCostSecs = p.sweep === true ? (continuing ? previous.sweepCostSecs ?? 0 : 0) + Number(p.estimatedSecs) : undefined;
195
341
  const sweepSlices = p.sweep === true ? Number(p.sweepElapsed ?? (continuing ? previous.sweepSlices ?? 0 : 0)) + 1 : undefined;
342
+ const root = effectiveInstanceRoot();
343
+ const historyFiles = pickHistoryFiles(p);
344
+ const weights = new Map(historyFiles.map((entry) => [entry.file, entry]));
345
+ const historyFailures = results.map((result) => weights.get(result.file))
346
+ .filter((entry): entry is GateFailWeight => entry !== undefined);
347
+ const slicePreexisting = historyFailures.reduce((sum, entry) => sum + entry.preexisting, 0);
348
+ const slicePreexistingKnownEnv = historyFailures.reduce((sum, entry) => sum + entry.knownEnv, 0);
349
+ // Metric (boundary ③): each ledger line carries its slice's preexisting ⊕ knownEnv totals AND their delta
350
+ // against the previous slice line, so «판마다 이월» is readable row by row — even on a zero line.
351
+ const previousHistory = (lastLedgerLine(root) as { gateHistory?: { preexisting?: number; knownEnv?: number } } | null)?.gateHistory;
352
+ const history = {
353
+ preexisting: slicePreexisting,
354
+ knownEnv: slicePreexistingKnownEnv,
355
+ total: slicePreexisting + slicePreexistingKnownEnv,
356
+ files: historyFailures.map((entry) => entry.file),
357
+ deltaPreexisting: slicePreexisting - Number(previousHistory?.preexisting ?? 0),
358
+ deltaKnownEnv: slicePreexistingKnownEnv - Number(previousHistory?.knownEnv ?? 0),
359
+ };
360
+ const selectedFiles = Array.isArray(p.files) ? p.files.filter((file): file is string => typeof file === 'string') : results.map((result) => result.file);
361
+ const selectedIndices = Array.isArray(p.selectedIndices) && p.selectedIndices.every((index) => typeof index === 'number')
362
+ ? p.selectedIndices as number[] : [];
196
363
  const line = {
197
- at: new Date().toISOString(), range: `#${p.start}~#${p.end}`, start: Number(p.start), end: Number(p.end), next: Number(p.next), total: Number(p.total),
364
+ // start/end/next are cursor coordinates; range + selectedIndices describe the exact weighted selection.
365
+ at: new Date().toISOString(), range: typeof p.rangeLabel === 'string' ? p.rangeLabel : `#${p.start}~#${p.end}`,
366
+ start: Number(p.start), end: Number(p.end), next: Number(p.next), total: Number(p.total), selectedFiles, selectedIndices,
198
367
  commit: String(m?.commit ?? '?'), budgetSecs: Number(p.budgetSecs), results, ...(visited === undefined ? {} : { sweepVisited: visited, sweepCostSecs, sweepSlices }),
368
+ gateHistory: { preexisting: history.preexisting, knownEnv: history.knownEnv, total: history.total,
369
+ deltaPreexisting: history.deltaPreexisting, deltaKnownEnv: history.deltaKnownEnv },
199
370
  };
200
- const root = effectiveInstanceRoot();
201
371
  appendLedger(root, line);
202
372
  const card = writeCardDraft(root, line);
373
+ const recipes = new Map(results.map((result) => {
374
+ const entry = weights.get(result.file);
375
+ return [result.file, recipeFor(entry ? { ...result, history: entry } : result)] as const;
376
+ }));
377
+ const recipeCounts: Record<string, number> = {};
378
+ for (const recipe of recipes.values()) recipeCounts[recipe.type] = (recipeCounts[recipe.type] ?? 0) + 1;
203
379
  const proposals: Record<string, number> = {};
204
380
  for (const result of results) {
205
- if (!result.proposal) continue;
206
- proposals[result.proposal] = (proposals[result.proposal] ?? 0) + 1;
381
+ if (td1.get(result.file)?.disposition === 'keep' && result.verdict === 'keep' && !result.proposal) continue;
382
+ const recipe = recipes.get(result.file)!;
383
+ const historyEntry = weights.get(result.file);
384
+ // YAML이 약속한 «판정마다 처방 카드 초안 하나» — 제안·실패·이력이 없는 keep 판정도 카드를 건너뛰지 않는다.
385
+ const proposal = result.proposal ?? (result.verdict === 'failing' ? 'failing' : historyEntry !== undefined ? `gate-history:${recipe.type}` : `verdict:${recipe.type}`);
386
+ proposals[proposal] = (proposals[proposal] ?? 0) + 1;
207
387
  let store: Pick<CardStore, 'createCard' | 'appendSection' | 'close'> | undefined;
208
388
  try {
209
389
  store = deps.createStore?.(root) ?? new CardStore(root);
210
- const task = store.createCard({ goalId: `test-diet:${result.file}:${result.proposal}`, title: `시험 다이어트 제안 — ${result.file} · ${result.proposal}` });
211
- const observation = { proposal: result.proposal, basis: result.basis, guards: td1.get(result.file)?.guards ?? '',
390
+ const task = store.createCard({ goalId: `test-diet:${result.file}:${proposal}`, title: `시험 다이어트 제안 — ${result.file} · ${proposal} · ${recipe.type}` });
391
+ const observation = { proposal: result.proposal, recipe, basis: result.basis, guards: td1.get(result.file)?.guards ?? '',
212
392
  secs: result.secs, rssMb: result.rssMb, caught90: result.caught90, range: line.range, ...(result.effectiveness ? { effectiveness: result.effectiveness } : {}) };
213
393
  const fingerprint = createHash('sha256').update(JSON.stringify(observation)).digest('hex');
214
394
  const key = `test-diet:${line.commit}:${fingerprint}`;
@@ -233,8 +413,9 @@ export function record(ctx: Context, deps: { createStore?: (root: string) => Pic
233
413
  }
234
414
  debug.log('test-diet', 'proposed', { range: line.range, proposals });
235
415
  const counts = { keep: results.filter((r) => r.verdict === 'keep').length, review: results.filter((r) => r.verdict === 'review').length, failing: results.filter((r) => r.verdict === 'failing').length };
416
+ debug.log('test-diet', 'prescriptions', { range: line.range, recipes: recipeCounts, preexisting: history.preexisting, knownEnv: history.knownEnv });
236
417
  debug.log('test-diet', 'recorded', { range: line.range, ...counts, card: card !== null });
237
- return emit({ outcome: 'ok', summary: `test-diet ${line.range} · keep ${counts.keep} · review ${counts.review} · failing ${counts.failing}${card ? ' · card draft' : ''}`, range: line.range, ...counts, ...(card ? { card } : {}) });
418
+ return emit({ outcome: 'ok', summary: `test-diet ${line.range} · keep ${counts.keep} · review ${counts.review} · failing ${counts.failing}${card ? ' · card draft' : ''}`, range: line.range, ...counts, ...(card ? { card } : {}), recipes: recipeCounts, history });
238
419
  }
239
420
 
240
421
  export function mainFailures(ctx: Context, deps: { root?: string; checkout?: string; runFile?: (file: string, cwd: string) => MainFailureResult; now?: Date } = {}): number {