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
@@ -5,7 +5,7 @@ import { opSeatStatePath, readTrafficSignal } from '../seat-loop/traffic-signal.
5
5
 
6
6
  const SEATS = ['OP', 'MK', 'TC', 'UX'] as const;
7
7
  type Seat = typeof SEATS[number];
8
- export type HygieneCell = { id: string; owner?: string | null; status: string };
8
+ export type HygieneCell = { id: string; owner?: string | null; status: string; title?: string };
9
9
  export type HygieneNotice = { to: Seat; key: string; body: string };
10
10
  export type HygieneDeps = {
11
11
  root: string;
@@ -45,7 +45,7 @@ export function starvingCycles(log: string): { reasons: Record<string, number> }
45
45
  return { reasons };
46
46
  }
47
47
 
48
- type HoldMeta = { id?: unknown; op?: unknown; reason?: unknown; until?: unknown };
48
+ type HoldMeta = { id?: unknown; op?: unknown; reason?: unknown; until?: unknown; kind?: unknown; confirmedAt?: unknown; at?: unknown; title?: unknown };
49
49
  function holdMetadata(path: string): Map<string, HoldMeta> {
50
50
  const latest = new Map<string, HoldMeta>();
51
51
  for (const line of (readOptional(path) ?? '').split(/\r?\n/)) {
@@ -65,6 +65,10 @@ function untilTime(value: unknown): number | null {
65
65
  return Number.isFinite(time) ? time : null;
66
66
  }
67
67
 
68
+ function confirmedTime(value: unknown): number | null {
69
+ return typeof value === 'string' && /^\d{12}$/.test(value) ? untilTime(value) : null;
70
+ }
71
+
68
72
  export function inspectHoldHygiene(deps: HygieneDeps): HygieneNotice[] {
69
73
  const notices: HygieneNotice[] = [];
70
74
  const dir = deps.dispatcherDir ?? opSeatStatePath('feeder');
@@ -88,11 +92,25 @@ export function inspectHoldHygiene(deps: HygieneDeps): HygieneNotice[] {
88
92
  if (!SEATS.some(seat => seat === owner)) continue;
89
93
  const meta = metadata.get(cell.id);
90
94
  const reason = meta?.op === 'add' && typeof meta.reason === 'string' ? meta.reason.trim() : '';
91
- const expiry = untilTime(meta?.until);
92
- const expired = typeof meta?.until === 'string' && meta.until.trim() !== '' && (expiry === null || expiry <= deps.now.getTime());
93
- if (reason && !expired) continue;
95
+ let attention = '';
96
+ if (meta?.kind === '손작업') {
97
+ const confirmed = confirmedTime(meta.confirmedAt ?? meta.at);
98
+ if (confirmed === null) attention = '재확인 시각 없음';
99
+ else if (deps.now.getTime() - confirmed >= 24 * 60 * 60_000) attention = '24h 재확인 지연';
100
+ } else if (meta?.kind === '재발사금지') {
101
+ if (typeof meta.title !== 'string' || !meta.title || typeof cell.title !== 'string' || !cell.title) attention = '제목 기준 확인 불가';
102
+ else if (cell.title !== meta.title) attention = '칸 제목 변경';
103
+ } else if (meta?.kind === '선행대기' || meta?.kind === undefined || meta?.kind === '') {
104
+ const expiry = untilTime(meta?.until);
105
+ if (expiry === null) attention = 'until 확인 불가';
106
+ else if (expiry <= deps.now.getTime()) attention = `until ${String(meta?.until)} 지남`;
107
+ } else attention = 'hold 종류 확인 불가';
108
+ if (reason && !attention) continue;
109
+ const guidance = meta?.kind === '손작업' ? '재확인 시각·사유를 판단해 OP에 알려 주세요.'
110
+ : meta?.kind === '재발사금지' ? '칸 제목과 기준 제목·사유를 대조해 OP에 알려 주세요.'
111
+ : '풀기/유지(사유·until)를 판단해 OP에 알려 주세요.';
94
112
  notices.push({ to: owner as Seat, key: `hold:${cell.id}:${owner}`,
95
- body: `노랑 칸 ${cell.id} traffic hold: ${!reason ? '사유 없음' : `사유 ${reason}`} ${expired ? `· until ${String(meta?.until)} 지남` : ''}. 풀기/유지(사유·until)를 판단해 OP에 알려 주세요. 자동 해제하지 않습니다.` });
113
+ body: `노랑 칸 ${cell.id} traffic hold: ${!reason ? '사유 없음' : `사유 ${reason}`} ${attention ? `· ${attention}` : ''}. ${guidance} 자동 해제하지 않습니다.` });
96
114
  }
97
115
  return notices;
98
116
  }
@@ -63,8 +63,16 @@ function defaultStampPath(): string {
63
63
  function readStamp(path: string): string | null {
64
64
  try {
65
65
  const value = (JSON.parse(readFileSync(path, 'utf8')) as { startedAt?: unknown }).startedAt;
66
- return typeof value === 'string' && Number.isFinite(Date.parse(value)) ? value : null;
67
- } catch { return null; }
66
+ if (typeof value !== 'string' || !Number.isFinite(Date.parse(value))) {
67
+ throw new Error(`invalid steward stamp startedAt: ${path}`);
68
+ }
69
+ return value;
70
+ } catch (error) {
71
+ // A missing stamp is the first tick. A corrupt or unreadable existing stamp is not:
72
+ // claiming it would overwrite the evidence and could launch an overlapping rejudge.
73
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return null;
74
+ throw error;
75
+ }
68
76
  }
69
77
 
70
78
  /** Same universe as this process (env inherited) · same installed version (entry next to this module). */
@@ -7,6 +7,7 @@ import { acquireLockSync } from '../storage/file-lock.js';
7
7
  import { subscribeInsideEvent, type InsideLiveEvent } from '../nexus/api/inside-events.js';
8
8
  import type { NexusEventBus } from '../nexus/api/event-bus.js';
9
9
  import { parseRepairWorkerResult } from '../task-agent/repair-worker.js';
10
+ import { pairMoveId } from '../task-agent/repair-next-move.js';
10
11
  import { readTaskCard, taskAgentStatePath } from '../task-agent/task-hand.js';
11
12
 
12
13
  const SHA40 = /^[0-9a-f]{40}$/i;
@@ -17,6 +18,8 @@ const OUTPUT_LIMIT = 1024 * 1024;
17
18
  export interface TaRepairCompleted {
18
19
  kind: 'ta.repair.completed'; schema: 1; card: string; pr: number; head: string;
19
20
  runId: string; resultPath: string; completedAt: string;
21
+ /** HARNESS-FULL-GRAPH-NEXTMOVE — worker 가 받은 수 id(옛 worker 는 없다 · 꼴이 틀려도 사건을 버리지 않고 짝짓기에서 «못 짝지음»으로 남긴다). */
22
+ moveId?: string;
20
23
  }
21
24
 
22
25
  export function parseTaRepairCompleted(value: unknown): TaRepairCompleted | null {
@@ -102,14 +105,22 @@ export async function collectTaRepairCompleted(input: unknown, deps: TaRepairCol
102
105
  let card;
103
106
  try { card = readTaskCard(event.card, statePath); } catch { emit('deferred', { reason: 'card unreadable' }); return 'deferred'; }
104
107
  const repair = Array.isArray(card?.repairs) ? card.repairs.find(entry => entry && typeof entry === 'object' && entry.runId === event.runId) : undefined;
108
+ // NEXTMOVE-GENERAL-RELAUNCH-MOVEID — 사건의 수 id 를 카드(발사 순간 적은 값)와 짝짓는다. 결과는 관측 칸에만 싣는다(fail-soft · 수거 판단은 그대로).
109
+ const observedMoveId: unknown = (event as { moveId?: unknown }).moveId;
110
+ const pairing = pairMoveId(repair?.moveId, observedMoveId);
111
+ const moveFields: Record<string, unknown> = pairing.kind === 'legacy' ? {}
112
+ : { moveId: pairing.kind === 'paired' ? pairing.moveId : typeof observedMoveId === 'string' ? observedMoveId : null,
113
+ moveIdPaired: pairing.kind === 'paired', ...(pairing.kind === 'unpaired' ? { expectedMoveId: pairing.expected } : {}) };
114
+ const emitPaired = (outcome: string, extra: Record<string, unknown> = {}) => emit(outcome, { ...moveFields, ...extra });
105
115
  if (!repair || repair.pr !== event.pr || typeof repair.head !== 'string' || repair.head.toLowerCase() !== event.head.toLowerCase()
106
116
  || typeof repair.resultPath !== 'string' || !repair.resultPath.startsWith('/')
117
+ // 카드 귀속이 안 맞는 사건엔 짝짓기 칸을 싣지 않는다 — 남의 수리와 대조한 값이 관측에 섞이지 않게(r1 should-fix).
107
118
  || resolve(repair.resultPath) !== resolve(event.resultPath)) { emit('invalid', { reason: 'event differs from card binding' }); return 'invalid'; }
108
- if (repair.status !== 'requested') { emit('duplicate', { reason: `repair ${repair.status}` }); return 'duplicate'; }
119
+ if (repair.status !== 'requested') { emitPaired('duplicate', { reason: `repair ${repair.status}` }); return 'duplicate'; }
109
120
  let result;
110
121
  try { result = parseRepairWorkerResult((deps.read ?? ((path) => readFileSync(path, 'utf8')))(repair.resultPath), event.pr, event.head, event.runId); }
111
122
  catch { /* periodic tick can recover a missing result */ }
112
- if (!result) { emit('deferred', { reason: 'worker result missing or invalid' }); return 'deferred'; }
123
+ if (!result) { emitPaired('deferred', { reason: 'worker result missing or invalid' }); return 'deferred'; }
113
124
 
114
125
  // Existing PID-aware lock recovers a dead daemon without making later events wait forever.
115
126
  // A live holder keeps the lock through the child process; the card CAS covers periodic-tick races.
@@ -119,25 +130,25 @@ export async function collectTaRepairCompleted(input: unknown, deps: TaRepairCol
119
130
  mkdirSync(dirname(lock), { recursive: true });
120
131
  release = acquireLockSync(lock, { breakDeadHolder: true, staleMs: TIMEOUT_MS + 60_000, maxTries: 2 });
121
132
  }
122
- catch { emit('deferred', { reason: 'collector busy; periodic fallback remains' }); return 'deferred'; }
133
+ catch { emitPaired('deferred', { reason: 'collector busy; periodic fallback remains' }); return 'deferred'; }
123
134
  try {
124
135
  // Recheck after claiming: another collector or the periodic tick may have consumed the file.
125
136
  const current = readTaskCard(event.card, statePath);
126
137
  const latest = Array.isArray(current?.repairs) ? current.repairs.find(entry => entry && typeof entry === 'object' && entry.runId === event.runId) : undefined;
127
138
  if (!latest || latest.status !== 'requested' || latest.pr !== event.pr || typeof latest.head !== 'string'
128
139
  || latest.head.toLowerCase() !== event.head.toLowerCase() || typeof latest.resultPath !== 'string'
129
- || !latest.resultPath.startsWith('/') || resolve(latest.resultPath) !== resolve(event.resultPath)) { emit('duplicate'); return 'duplicate'; }
140
+ || !latest.resultPath.startsWith('/') || resolve(latest.resultPath) !== resolve(event.resultPath)) { emitPaired('duplicate'); return 'duplicate'; }
130
141
  const child = await (deps.run ?? ((card) => defaultRun(card, statePath, deps.cliBin)))(event.card);
131
142
  const after = readTaskCard(event.card, statePath)?.repairs?.find(entry => entry.runId === event.runId);
132
143
  const consumed = child.code === 0 && !child.truncated && after?.status !== 'requested' && after !== undefined
133
144
  && childConsumedRepair(child.output, event);
134
145
  const outcome = consumed ? 'collected' : child.truncated ? 'deferred' : after && after.status !== 'requested' ? 'duplicate' : 'deferred';
135
- emit(outcome, { rc: child.code, repairStatus: after?.status,
146
+ emitPaired(outcome, { rc: child.code, repairStatus: after?.status,
136
147
  ...(child.truncated ? { reason: 'rejudge output exceeded 1 MiB; event attribution unmeasured' } : {}),
137
148
  detail: child.output.slice(-300) });
138
149
  return consumed ? 'collected' : outcome === 'duplicate' ? 'duplicate' : 'deferred';
139
150
  } catch (error) {
140
- emit('deferred', { reason: String(error).slice(-300) });
151
+ emitPaired('deferred', { reason: String(error).slice(-300) });
141
152
  return 'deferred';
142
153
  } finally { release(); }
143
154
  }
@@ -1,4 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
+ import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
2
4
  import { debug } from '../debug/log.js';
3
5
  import type { TriageDecision, TriageIssue } from './triage.js';
4
6
  import { InvalidWorkingBackwardsDraft } from './working-backwards.js';
@@ -187,3 +189,195 @@ export async function draftWithinBudget<T>({ wishes, draft, concurrency = 4, per
187
189
  debug.log('steward.triage', 'draft-budget', stats);
188
190
  return { ...result, stats };
189
191
  }
192
+
193
+ /** Consecutive healthy shadow ticks before a live move is safe to record. */
194
+ export const LIVE_AFTER_TICKS = 3;
195
+
196
+ /** Reasons a decision is a placeholder, not a judgment — they must never be reused as if they were fresh. */
197
+ const TEMPORARY_WHYS = ['triage deferred — deadline', 'triage judgment timed out — human review',
198
+ 'triage judgment unavailable — human review'];
199
+
200
+ export function isTemporaryDecision(decision: TriageDecision): boolean {
201
+ return decision.rung === 'hitl' && decision.hitlReason === 'other' && TEMPORARY_WHYS.includes(decision.why);
202
+ }
203
+
204
+ export interface TriageTickCycle {
205
+ /** sha256 of this tick's sorted issue identifiers — the batch fingerprint. */
206
+ key: string;
207
+ /** Consecutive ticks (this one included) that carried the same fingerprint. */
208
+ ticks: number;
209
+ }
210
+
211
+ export interface TriageTickBudget {
212
+ cycle: TriageTickCycle;
213
+ deadlineMs: number;
214
+ perIssueMs: number;
215
+ concurrency: number;
216
+ /** `repeat-tick` when the same batch already arrived in the previous tick. */
217
+ basis: 'first-tick' | 'repeat-tick';
218
+ }
219
+
220
+ export type TriageItemOutcome = 'reused' | 'judged' | 'timed-out' | 'unavailable' | 'deferred';
221
+
222
+ export interface TriageItemEvent {
223
+ /** 1-based position of the issue in this tick's batch. */
224
+ index: number;
225
+ /** Which tick cycle the item was judged in. */
226
+ cycle: number;
227
+ issue: string;
228
+ outcome: TriageItemOutcome;
229
+ /** No fresh judgment backs this item — the next tick (or a human) must pick it up. */
230
+ degraded: boolean;
231
+ why: string;
232
+ }
233
+
234
+ export interface TriageItemMetrics {
235
+ items: number;
236
+ fresh: number;
237
+ reused: number;
238
+ degraded: number;
239
+ byOutcome: Record<TriageItemOutcome, number>;
240
+ }
241
+
242
+ export interface TriageTickHealth {
243
+ degraded: string[];
244
+ /** Degraded last tick, freshly judged this tick. */
245
+ healed: string[];
246
+ health: 'healthy' | 'healing' | 'degraded';
247
+ /** Consecutive non-degraded shadow ticks. */
248
+ liveStreak: number;
249
+ /** Shadow has stayed healthy long enough that a live move is safe; the mode itself is not flipped here. */
250
+ liveEligible: boolean;
251
+ transition?: 'shadow→live' | 'live→shadow';
252
+ }
253
+
254
+ export interface TriageTickRecord extends TriageTickHealth {
255
+ at: string;
256
+ mode: string;
257
+ key: string;
258
+ ticks: number;
259
+ issues: number;
260
+ deadlineMs: number;
261
+ perIssueMs: number;
262
+ concurrency: number;
263
+ reused: number;
264
+ judged: number;
265
+ timedOut: number;
266
+ deferred: number;
267
+ events: TriageItemEvent[];
268
+ }
269
+
270
+ export function triageTickKey(issues: TriageIssue[]): string {
271
+ return createHash('sha256').update(JSON.stringify(issues.map(issue => issue.identifier).sort())).digest('hex').slice(0, 16);
272
+ }
273
+
274
+ /** The tick cycle: a batch that keeps re-arriving is the same cycle, counted up; a changed batch starts at 1. */
275
+ export function triageTickCycle(previous: Pick<TriageTickRecord, 'key' | 'ticks'> | undefined, key: string): TriageTickCycle {
276
+ const ticks = previous && previous.key === key && Number.isFinite(previous.ticks) ? Math.max(1, previous.ticks) + 1 : 1;
277
+ return { key, ticks };
278
+ }
279
+
280
+ /**
281
+ * Budget derived from the tick cycle: the stage deadline is fixed per tick, but a repeat cycle widens each issue's
282
+ * slice (up to 3×) instead of re-running the same timeout on the batch that already ran out of window last tick.
283
+ */
284
+ export function triageTickBudget({ cycle, issueCount, deadlineMs = 240_000, basePerIssueMs = 90_000, maxConcurrency = 8 }: {
285
+ cycle: TriageTickCycle;
286
+ issueCount: number;
287
+ deadlineMs?: number;
288
+ basePerIssueMs?: number;
289
+ maxConcurrency?: number;
290
+ }): TriageTickBudget {
291
+ const count = Math.max(1, Math.floor(issueCount));
292
+ const concurrency = Math.max(1, Math.min(Math.max(1, Math.floor(maxConcurrency)), count));
293
+ const stretch = Math.min(Math.max(1, Math.floor(cycle.ticks)), 3);
294
+ return { cycle, deadlineMs, perIssueMs: Math.min(deadlineMs, basePerIssueMs * stretch), concurrency,
295
+ basis: cycle.ticks > 1 ? 'repeat-tick' : 'first-tick' };
296
+ }
297
+
298
+ /** One event per item: what actually happened to it this tick and whether that leaves it degraded. */
299
+ export function triageItemEvents({ cycle, issues, decisions, previous = [] }: {
300
+ cycle: TriageTickCycle;
301
+ issues: TriageIssue[];
302
+ decisions: Array<TriageDecision & { inputHash?: string; deferred?: true }>;
303
+ previous?: Array<TriageDecision & { inputHash?: string }>;
304
+ }): TriageItemEvent[] {
305
+ const judged = new Map(decisions.map(decision => [decision.issue, decision]));
306
+ const earlier = new Map(previous.map(decision => [decision.issue, decision]));
307
+ const events: TriageItemEvent[] = [];
308
+ for (const [index, issue] of issues.entries()) {
309
+ const decision = judged.get(issue.identifier);
310
+ const before = earlier.get(issue.identifier);
311
+ let outcome: TriageItemOutcome;
312
+ if (!decision) outcome = 'unavailable';
313
+ else if (decision.deferred === true) outcome = 'deferred';
314
+ else if (decision.why === 'triage judgment timed out — human review') outcome = 'timed-out';
315
+ else if (decision.why === 'triage judgment unavailable — human review') outcome = 'unavailable';
316
+ else if (before && before.inputHash !== undefined && before.inputHash === decision.inputHash &&
317
+ !before.deferred && !isTemporaryDecision(before)) outcome = 'reused';
318
+ else outcome = 'judged';
319
+ events.push({ index: index + 1, cycle: cycle.ticks, issue: issue.identifier, outcome,
320
+ degraded: outcome !== 'judged' && outcome !== 'reused',
321
+ why: decision?.why ?? 'triage decision missing' });
322
+ }
323
+ return events;
324
+ }
325
+
326
+ export function triageItemMetrics(events: TriageItemEvent[]): TriageItemMetrics {
327
+ const byOutcome: Record<TriageItemOutcome, number> = { reused: 0, judged: 0, 'timed-out': 0, unavailable: 0, deferred: 0 };
328
+ for (const event of events) byOutcome[event.outcome]++;
329
+ const reused = byOutcome.reused;
330
+ return { items: events.length, fresh: byOutcome.judged, reused,
331
+ degraded: events.filter(event => event.degraded).length, byOutcome };
332
+ }
333
+
334
+ /** Healing and the shadow→live transition, read off the previous real tick — never off an assumed one. */
335
+ export function triageTickHealth({ previous, mode, events }: {
336
+ previous?: Pick<TriageTickRecord, 'mode' | 'degraded' | 'liveStreak'>;
337
+ mode: string;
338
+ events: TriageItemEvent[];
339
+ }): TriageTickHealth {
340
+ const degraded = events.filter(event => event.degraded).map(event => event.issue);
341
+ const healed = (previous?.degraded ?? []).filter(issue => !degraded.includes(issue)).sort();
342
+ const health = healed.length ? 'healing' : degraded.length ? 'degraded' : 'healthy';
343
+ // Any degradation still present this tick resets the streak — a healed item next to a degraded one is not a healthy tick.
344
+ const liveStreak = mode === 'shadow' ? (degraded.length ? 0 : (previous?.mode === 'shadow' ? previous.liveStreak + 1 : 1)) : 0;
345
+ const transition = previous && previous.mode !== mode
346
+ ? (mode === 'live' && previous.mode === 'shadow' ? 'shadow→live'
347
+ : mode === 'shadow' && previous.mode === 'live' ? 'live→shadow' : undefined)
348
+ : undefined;
349
+ return { degraded, healed, health, liveStreak, liveEligible: mode === 'shadow' && liveStreak >= LIVE_AFTER_TICKS,
350
+ ...(transition ? { transition } : {}) };
351
+ }
352
+
353
+ export function triageTickLedgerPath(root: string): string {
354
+ return join(root, 'steward', 'triage-ticks.jsonl');
355
+ }
356
+
357
+ /** The real ticks that already ran, oldest first. A torn line is not a tick. */
358
+ export function readTriageTicks(root: string, limit = 24): TriageTickRecord[] {
359
+ let text: string;
360
+ try { text = readFileSync(triageTickLedgerPath(root), 'utf8'); } catch { return []; }
361
+ const records: TriageTickRecord[] = [];
362
+ for (const line of text.split('\n')) {
363
+ if (!line.trim()) continue;
364
+ try {
365
+ const parsed: unknown = JSON.parse(line);
366
+ if (parsed && typeof parsed === 'object' && typeof (parsed as { mode?: unknown }).mode === 'string' &&
367
+ typeof (parsed as { key?: unknown }).key === 'string' && typeof (parsed as { ticks?: unknown }).ticks === 'number' &&
368
+ Array.isArray((parsed as { degraded?: unknown }).degraded) && Array.isArray((parsed as { events?: unknown }).events)) {
369
+ records.push(parsed as TriageTickRecord);
370
+ }
371
+ } catch { /* torn line */ }
372
+ }
373
+ return records.slice(-Math.max(1, limit));
374
+ }
375
+
376
+ export function appendTriageTick(root: string, record: TriageTickRecord): void {
377
+ try {
378
+ mkdirSync(join(root, 'steward'), { recursive: true });
379
+ appendFileSync(triageTickLedgerPath(root), `${JSON.stringify(record)}\n`);
380
+ } catch (error) {
381
+ debug.log('steward.triage', 'tick-ledger-failed', { reason: String(error) }, { level: 'warn' });
382
+ }
383
+ }
@@ -130,7 +130,7 @@ export function trackTablePrompt(tracks?: Record<string, string>): string {
130
130
  return `\n담당 트랙(owner) — 아래 중 하나(${keys.map(k => JSON.stringify(k)).join('|')}) · 이슈가 어느 트랙 일인지:\n${keys.map(k => `- ${k}: ${tracks[k]}`).join('\n')}`;
131
131
  }
132
132
 
133
- export async function triageIssues(issues: TriageIssue[], judge?: NonNullable<StewardDeps['judge']>, decide: typeof emitDecision = emitDecision, tracks?: Record<string, string>, previous: Array<TriageDecision & { inputHash?: string }> = [], ask: StewardAsk = askSteward): Promise<TriageDecision[]> {
133
+ export async function triageIssues(issues: TriageIssue[], judge?: NonNullable<StewardDeps['judge']>, decide: typeof emitDecision = emitDecision, tracks?: Record<string, string>, previous: Array<TriageDecision & { inputHash?: string }> = [], ask: StewardAsk = askSteward, budget?: { deadlineMs: number; perIssueMs: number; concurrency: number }): Promise<TriageDecision[]> {
134
134
  const started = judge ? 0 : Date.now();
135
135
  const classified: ClassifiedIssue[] = [];
136
136
  const classifiedIds = new Set<string>();
@@ -144,7 +144,7 @@ export async function triageIssues(issues: TriageIssue[], judge?: NonNullable<St
144
144
  decide({ kind: result.rung === 'hitl' ? 'ESCALATE' : 'ROUTE', what: result.issue, reason: result.why,
145
145
  purpose: 'steward triage', target: result.owner ? `${result.rung} · ${result.owner}` : String(result.rung), refs: { issue: result.issue } });
146
146
  };
147
- const { decisions } = await triageWithinBudget({ issues, previous, tracks, judge: async (issue, observedIssues) => {
147
+ const { decisions } = await triageWithinBudget({ issues, previous, tracks, ...(budget ?? {}), judge: async (issue, observedIssues) => {
148
148
  try {
149
149
  if (judge) return parseJudgment(issue, await judge(issue, observedIssues ?? issues, tracks), tracks);
150
150
  const byRule = ruleJudgment(issue, observedIssues ?? issues);
@@ -487,7 +487,24 @@ export async function runStewardStage(stage: 'sync' | 'triage' | 'schedule' | 'r
487
487
  Array.isArray(item.dependsOn) && item.dependsOn.every((dep: unknown) => typeof dep === 'string') &&
488
488
  typeof item.priority === 'number' && Number.isFinite(item.priority) && typeof item.why === 'string')) previous = parsed;
489
489
  } catch { /* Missing or corrupt previous judgments are an empty cache. */ }
490
- writeFileSync(judgments, JSON.stringify(await triageIssues(issues, judge, deps.decide, settings.tracks, previous, deps.ask)));
490
+ const { appendTriageTick, readTriageTicks, triageItemEvents, triageItemMetrics, triageTickBudget, triageTickCycle,
491
+ triageTickHealth, triageTickKey } = await import('./triage-budget.js');
492
+ const ticks = readTriageTicks(root);
493
+ const cycle = triageTickCycle(ticks.at(-1), triageTickKey(issues));
494
+ const budget = triageTickBudget({ cycle, issueCount: issues.length });
495
+ const decisions = await triageIssues(issues, judge, deps.decide, settings.tracks, previous, deps.ask, budget);
496
+ writeFileSync(judgments, JSON.stringify(decisions));
497
+ const events = triageItemEvents({ cycle, issues, decisions, previous });
498
+ const metrics = triageItemMetrics(events);
499
+ const mode = settings.mode ?? 'shadow';
500
+ const health = triageTickHealth({ previous: ticks.at(-1), mode, events });
501
+ for (const event of events) debug.log('steward.triage', 'item-event', { ...event, health: health.health });
502
+ debug.log('steward.triage', 'tick', { cycle, basis: budget.basis, perIssueMs: budget.perIssueMs,
503
+ concurrency: budget.concurrency, ...metrics, ...health });
504
+ appendTriageTick(root, { at: new Date().toISOString(), mode, key: cycle.key, ticks: cycle.ticks, issues: issues.length,
505
+ deadlineMs: budget.deadlineMs, perIssueMs: budget.perIssueMs, concurrency: budget.concurrency,
506
+ reused: metrics.byOutcome.reused, judged: metrics.byOutcome.judged, timedOut: metrics.byOutcome['timed-out'],
507
+ deferred: metrics.byOutcome.deferred, ...health, events });
491
508
  } else if (stage === 'schedule') {
492
509
  const decisions = JSON.parse(readFileSync(judgments, 'utf8')) as TriageDecision[];
493
510
  const pending = new Set(decisions.flatMap(decision => decision.dependsOn));
@@ -48,6 +48,8 @@ export interface NextAction {
48
48
  cwd?: string;
49
49
  risk?: 'money' | 'security' | 'irreversible-publication';
50
50
  delivery?: { kind: DeliveryKind; worktreePath: string; projectTarget: string; files: string[] };
51
+ /** NEXTMOVE-GENERAL-RELAUNCH-MOVEID — 이 재발사를 고른 next-move 결정의 수 id(결정 순간 한 번 · 다시 만들지 않는다). 있으면 `harness say --move-id` 로 싣는다. */
52
+ moveId?: string;
51
53
  }
52
54
  export interface ActionDeps {
53
55
  command(args: string[]): Promise<{ status: number; stdout: string; stderr?: string }>;
@@ -64,7 +66,7 @@ export interface ActionDeps {
64
66
  releaseLanding?(day: string): void;
65
67
  /** 실패 한 번을 잠금 안에서 디스크에 더한다(다른 프로세스의 실패를 덮지 않게) · 더한 뒤의 값을 돌려준다. */
66
68
  incrementFailure?(key: string): number;
67
- observe(event: 'task-agent.action', data: { taskId: string; kind: NextActionKind; result: string; reason: string }): void;
69
+ observe(event: 'task-agent.action' | 'task-agent.entrance-denominator', data: ActionObservation): void;
68
70
  /** 사다리 R4 — 실제로 할 재발사 수의 허용 목록(`taskAgent.liveMoves` 어휘). 없으면 종전 그대로(재발사에 목록 검사 없음) · 목록에 없는 수는 shadow. */
69
71
  liveMoves?: ReadonlySet<string>;
70
72
  /** 한 판단 회차의 발사 칸 — 호출부가 회차마다 새로 준다. 없으면 회당 상한 없음(종전). 발사를 시도할 때마다 `count` 가 오른다. */
@@ -76,6 +78,49 @@ export interface ActionDeps {
76
78
  /** 재발사는 한 판단 회차에 한 건만 발사한다. */
77
79
  export const RETRY_LAUNCHES_PER_CYCLE = 1;
78
80
 
81
+ export interface ActionObservation {
82
+ taskId: string;
83
+ kind: NextActionKind | 'entrance-tick';
84
+ result: string;
85
+ reason: string;
86
+ reviewed?: number;
87
+ allowed?: number;
88
+ refused?: number;
89
+ reasons?: Record<string, number>;
90
+ }
91
+
92
+ export interface EntranceCandidateReview {
93
+ taskId: string;
94
+ kind: NextActionKind;
95
+ refusal?: string;
96
+ }
97
+
98
+ export interface EntranceTickCandidate {
99
+ action: NextAction;
100
+ refusal?: string;
101
+ }
102
+
103
+ export interface EntranceRefusalDenominator {
104
+ reviewed: number;
105
+ allowed: number;
106
+ refused: number;
107
+ reasons: Record<string, number>;
108
+ }
109
+
110
+ /** Count a tick's candidate refusals without confusing special object keys with prototypes. */
111
+ export function buildEntranceRefusalDenominator(reviews: readonly EntranceCandidateReview[]): EntranceRefusalDenominator {
112
+ const reasonCounts = new Map<string, number>();
113
+ let refused = 0;
114
+ for (const review of reviews) {
115
+ const reason = typeof review.refusal === 'string' ? review.refusal.trim() : '';
116
+ if (!reason) continue;
117
+ refused += 1;
118
+ reasonCounts.set(reason, (reasonCounts.get(reason) ?? 0) + 1);
119
+ }
120
+ const reasons = Object.fromEntries(reasonCounts) as Record<string, number>;
121
+ return { reviewed: reviews.length, allowed: reviews.length - refused, refused, reasons };
122
+ }
123
+
79
124
  /** live 인데도 shadow 로 내릴 사유 — 없으면 발사해도 된다(재발사 아닌 수는 늘 없다). 기다림(wait)은 발사가 아니라 부하·회당 상한을 보지 않는다. */
80
125
  function retryShadowReason(action: NextAction, deps: ActionDeps): string | undefined {
81
126
  if (action.kind !== 'retry') return undefined;
@@ -230,7 +275,7 @@ export async function executeNextAction(action: NextAction, deps: ActionDeps): P
230
275
  return card('review verdict or must-fix unavailable');
231
276
  }
232
277
  // 여기 닿는 종류는 land · retry 둘뿐이다(green·decision·review 는 위에서 끝난다).
233
- const args = action.kind === 'land' ? ['pr', 'land', '--cwd', action.cwd!] : ['harness', 'say', retryText(action)];
278
+ const args = action.kind === 'land' ? ['pr', 'land', '--cwd', action.cwd!] : ['harness', 'say', retryText(action), ...(action.moveId ? ['--move-id', action.moveId] : [])];
234
279
  const day = deps.landingDay ?? new Date().toLocaleDateString('en-CA', { timeZone: 'Asia/Seoul' });
235
280
  if (action.kind === 'retry' && deps.retryLaunches) deps.retryLaunches.count++;
236
281
  const outcome = await deps.command(args);
@@ -264,6 +309,31 @@ export async function executeNextAction(action: NextAction, deps: ActionDeps): P
264
309
  return record('done', action.rationale);
265
310
  }
266
311
 
312
+ /** Execute the allowed candidates in a caller-supplied tick and emit one isolated denominator event. */
313
+ export async function executeEntranceTick(candidates: readonly EntranceTickCandidate[], deps: ActionDeps): Promise<string[]> {
314
+ const denominator = buildEntranceRefusalDenominator(candidates.map(({ action, refusal }) => ({
315
+ taskId: action.taskId,
316
+ kind: action.kind,
317
+ ...(typeof refusal === 'string' ? { refusal } : {}),
318
+ })));
319
+ const observeDenominator = (result: string) => {
320
+ try {
321
+ deps.observe('task-agent.entrance-denominator', {
322
+ taskId: candidates[0]?.action.taskId ?? 'entrance-tick',
323
+ kind: 'entrance-tick', result, reason: 'entrance refusal denominator', ...denominator,
324
+ });
325
+ } catch { /* Logging must not change the actions selected for this tick. */ }
326
+ };
327
+ const results: string[] = [];
328
+ for (const { action, refusal } of candidates) {
329
+ if (typeof refusal === 'string' && refusal.trim()) continue;
330
+ try { results.push(await executeNextAction(action, deps)); }
331
+ catch (error) { observeDenominator('failed'); throw error; }
332
+ }
333
+ observeDenominator(results.at(-1) ?? 'refused-all');
334
+ return results;
335
+ }
336
+
267
337
  /** 재발사 문면 — 원문은 고치지 않고 앞에 둔다 · 갈래 문면 · must-fix · 직전 런 순서. */
268
338
  export function retryText(action: NextAction): string {
269
339
  const sections = [action.original];
@@ -28,6 +28,8 @@ export interface GreenSweepDecision {
28
28
  source: GreenSweepCandidate['source'];
29
29
  verdict: GreenSweepVerdict;
30
30
  reason: string;
31
+ /** Present when traffic hold state could not be read; preserves the decision reason while exposing its cause. */
32
+ holdDiagnostic?: string;
31
33
  evidence: string;
32
34
  existingEvidence: string;
33
35
  /** Preview only; a later live operation may persist this complete value. */
@@ -107,6 +109,7 @@ export function decideGreenSweep(input: {
107
109
  pr: GreenSweepPr | null;
108
110
  ancestor: boolean | null;
109
111
  hold: boolean | null;
112
+ holdDiagnostic?: string;
110
113
  repositoryMatches?: boolean | null;
111
114
  ambiguousAcrossCells?: boolean;
112
115
  }): GreenSweepDecision {
@@ -116,6 +119,7 @@ export function decideGreenSweep(input: {
116
119
  const landing = pr?.viaTrain ? ` via train #${pr.viaTrain.integrationPr}` : '';
117
120
  const evidence = `GREEN-FROM-LEDGER: PR #${candidate.pr}${landing}${mergeSha ? ` merged ${mergeSha}` : ''} · ${verdict} · ${reason}`;
118
121
  return { cell: item.id, pr: candidate.pr, mergeSha, source: candidate.source, verdict, reason,
122
+ ...(reason === 'hold-state-unreadable' && input.holdDiagnostic ? { holdDiagnostic: input.holdDiagnostic } : {}),
119
123
  evidence, existingEvidence: item.evidence ?? '', plannedEvidence: appendGreenSweepEvidence(item.evidence, evidence) };
120
124
  };
121
125
  if (item.status !== 'yellow' && item.status !== 'red') return result('skip', 'cell-not-yellow');
@@ -4,6 +4,7 @@ import { mkdirSync, readFileSync } from 'node:fs';
4
4
  import { dirname, isAbsolute, join } from 'node:path';
5
5
  import { randomUUID } from 'node:crypto';
6
6
  import { parseReviewResultOutput } from './review-result-capture.js';
7
+ import { executeBoundPrLandRecover, PR_LAND_CARD_ID_ENV } from '../cli/pr-land-recovery.js';
7
8
 
8
9
  type CommandResult = { status: number; stdout: string; stderr: string };
9
10
  export interface QueueLandingInput {
@@ -13,6 +14,8 @@ export interface QueueLandingInput {
13
14
  export interface QueueLandingDeps {
14
15
  run?: (command: string, args: string[], cwd: string, env?: NodeJS.ProcessEnv) => Promise<CommandResult>;
15
16
  read?: (path: string) => string;
17
+ /** LAND-REFUSAL-EXEC — observe a refusal on the recover@1 edge and run that unit once (never an effect). */
18
+ recover?: typeof executeBoundPrLandRecover;
16
19
  }
17
20
 
18
21
  async function run(command: string, args: string[], cwd: string, env?: NodeJS.ProcessEnv): Promise<CommandResult> {
@@ -31,14 +34,24 @@ export async function runQueuedLanding(input: QueueLandingInput, deps: QueueLand
31
34
  const invoke = deps.run ?? run;
32
35
  const read = deps.read ?? ((path: string) => readFileSync(path, 'utf8'));
33
36
  const fail = (stage: string, reason: string): CommandResult => ({ status: 1, stdout: '', stderr: `${stage}: ${reason.slice(-500)}` });
37
+ // LAND-REFUSAL-EXEC — a judged refusal (not an unmeasured prerequisite) is bound to recover@1 with this card
38
+ // and that unit runs once. The returned refusal is unchanged; recovery observation never replaces it.
39
+ const refuse = async (stage: string, reason: string): Promise<CommandResult> => {
40
+ const refused = fail(stage, reason);
41
+ try { await (deps.recover ?? executeBoundPrLandRecover)({ refusal: refused.stderr, pr: input.pr, head: input.head, cardId: input.card }, { root: dirname(input.statePath) }); }
42
+ catch { /* fail-soft */ }
43
+ return refused;
44
+ };
45
+ // The card rides along to every child that may land or record this PR (same env as TA defaultLand).
46
+ const cardEnv = (extra: Record<string, string> = {}): NodeJS.ProcessEnv => ({ ...process.env, ...extra, [PR_LAND_CARD_ID_ENV]: input.card });
34
47
  if (!/^[a-f0-9]{40}$/i.test(input.head) || !Number.isSafeInteger(input.pr) || input.pr < 1) return fail('input', 'invalid PR/head');
35
48
  if (!isAbsolute(input.command) || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(input.remote)) return fail('config', 'land queue command/remote invalid');
36
49
  let review: ReturnType<typeof parseReviewResultOutput>;
37
50
  try { review = parseReviewResultOutput(read(input.reviewResult)); }
38
- catch (error) { return fail('review', String(error)); }
51
+ catch (error) { return refuse('review', String(error)); }
39
52
  if (!review || review.pr !== input.pr || review.head?.toLowerCase() !== input.head.toLowerCase()
40
53
  || review.reviewed !== true || !['pass', 'warn'].includes(review.verdict ?? '') || review.mustFix !== 0 || review.error) {
41
- return fail('review', `exact head #${input.pr} ${input.head.slice(0, 12)} PASS/WARN mf0 not proven`);
54
+ return refuse('review', `exact head #${input.pr} ${input.head.slice(0, 12)} PASS/WARN mf0 not proven`);
42
55
  }
43
56
  const git = async (args: string[]) => invoke(process.execPath, [input.entry, '--config-dir', input.configDir, 'git', ...args], input.cwd);
44
57
  const fetched = await git(['fetch', '--quiet', 'origin', 'main']);
@@ -52,15 +65,15 @@ export async function runQueuedLanding(input: QueueLandingInput, deps: QueueLand
52
65
  const artifact = join(dirname(input.statePath), 'land-queue-gates', `${safeCard}-${input.pr}-${input.head.slice(0, 12)}-${randomUUID()}`);
53
66
  mkdirSync(artifact, { recursive: true });
54
67
  const gate = await invoke(process.execPath, [input.entry, '--config-dir', input.configDir,
55
- 'self', 'gate', '--changed', '--base', baseHead!, '--remote', input.remote, '--shards', '4', '--artifact-dir', artifact], input.cwd);
56
- if (gate.status !== 0) return fail('remote-changed-gate', gate.stderr || gate.stdout || `exit ${gate.status}`);
68
+ 'self', 'gate', '--changed', '--base', baseHead!, '--remote', input.remote, '--shards', '4', '--artifact-dir', artifact], input.cwd, cardEnv());
69
+ if (gate.status !== 0) return refuse('remote-changed-gate', gate.stderr || gate.stdout || `exit ${gate.status}`);
57
70
  let summary: Record<string, unknown>;
58
71
  try { summary = JSON.parse(read(join(artifact, 'summary.json'))) as Record<string, unknown>; }
59
72
  catch (error) { return fail('remote-changed-gate', `summary unreadable: ${String(error)}`); }
60
73
  if (summary.head40 !== input.head || summary.base40 !== baseHead || summary.remoteHost !== input.remote
61
74
  || summary.verdict !== 'passed' || summary.exitCode !== 0 || summary.introduced !== 0
62
75
  || summary.unknown !== 0 || summary.preconditionUnmet !== 0) {
63
- return fail('remote-changed-gate', 'summary does not prove this head/base/remote passed with zero unknown');
76
+ return refuse('remote-changed-gate', 'summary does not prove this head/base/remote passed with zero unknown');
64
77
  }
65
78
  const fresh = await invoke('gh', ['pr', 'view', String(input.pr), '--json', 'headRefOid,state,isDraft'], input.cwd);
66
79
  let latest: { headRefOid?: unknown; state?: unknown; isDraft?: unknown };
@@ -68,12 +81,12 @@ export async function runQueuedLanding(input: QueueLandingInput, deps: QueueLand
68
81
  catch { return fail('pr-head', `current PR state unreadable: ${fresh.stderr || fresh.stdout || fresh.status}`); }
69
82
  if (fresh.status !== 0 || latest.state !== 'OPEN' || latest.isDraft !== false
70
83
  || typeof latest.headRefOid !== 'string' || latest.headRefOid.toLowerCase() !== input.head.toLowerCase()) {
71
- return fail('pr-head', `PR #${input.pr} changed after gate or is not ready`);
84
+ return refuse('pr-head', `PR #${input.pr} changed after gate or is not ready`);
72
85
  }
73
86
  const enrolled = await invoke(input.command, [String(input.pr), input.cwd, '--review', input.reviewResult, '--expected-head', input.head], input.cwd,
74
- { ...process.env, LAND_RR_DIR: dirname(input.reviewResult) });
87
+ cardEnv({ LAND_RR_DIR: dirname(input.reviewResult) }));
75
88
  if (enrolled.status !== 0 || !new RegExp(`^OK #${input.pr} head=${input.head.slice(0, 12)}(?:\\s|$)`, 'm').test(enrolled.stdout)) {
76
- return fail('land-enqueue-refused', enrolled.stdout || enrolled.stderr || `exit ${enrolled.status}`);
89
+ return refuse('land-enqueue-refused', enrolled.stdout || enrolled.stderr || `exit ${enrolled.status}`);
77
90
  }
78
91
  return { status: 0, stdout: `queued #${input.pr} head ${input.head.slice(0, 12)} gate ${artifact} · ${enrolled.stdout.slice(-250)}`, stderr: '' };
79
92
  }