elanous 0.2.32 → 0.2.35

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 (753) 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/{IVKr3AlRUVLKsw2fh7eXF → T1mBQqmkwKDLGtyisDCOd}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 0368f25d-ad84af92fefee68f.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1165.bad13fc9151a7288.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/13.02a07436dec15f89.js +32 -0
  7. package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 1530.0e612369b6fd7ea0.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +41 -0
  9. package/apps/pwa/out/_next/static/chunks/{7391.ebae168025c91b6a.js → 1674.2a65fd5668e1cc5f.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +24 -0
  11. package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +74 -0
  12. package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{7947-d0759430f8042240.js → 1993-c0007b7ad0c0ef41.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{60fb96c9.360b01d8d4927b7b.js → 1c735de4.f993a30bbd3c57c4.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 2018.a741297bce759490.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +148 -0
  23. package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{3902.e1e71aaac850a045.js → 2625.5d870aa999f33db1.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +77 -0
  26. package/apps/pwa/out/_next/static/chunks/2833-0fe47af99ed13c29.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +62 -0
  29. package/apps/pwa/out/_next/static/chunks/3103.0df8da390948bb84.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +90 -0
  31. package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 3408.21d1570602f4b6c0.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3589.5444a06bcf6e775c.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/359-2250789a2d3499e7.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +36 -0
  37. package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 3677-4215f826f6aa68e5.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +79 -0
  40. package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3f7c4ee5.3dde54f01a816613.js +122 -0
  42. package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/{7371.80c05c653b08e907.js → 4346.8601952e73bf5803.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/4441-875b97f5821ed58a.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +286 -0
  46. package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +24 -0
  49. package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 4705-194e64e47ca0fbdb.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 4718-17d2af636796a330.js} +3 -3
  51. package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 5101.e32282718f99ed6f.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/{2001.6c7e0fd02190886c.js → 5154.a118f3957ed14e36.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +23 -0
  61. package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 5483-dd5d7697f6bdb106.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5637.281e5dec4ea6ecf1.js +94 -0
  63. package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{3267c0e6.d34854e7b3984a6e.js → 56d372f2.681ab4ec4c998fae.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5852.db1f7449f4f74612.js +287 -0
  67. package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 6236.e18cced2d5ba6afb.js} +17 -17
  74. package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +8 -0
  75. package/apps/pwa/out/_next/static/chunks/630.fe5a46428d63b013.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +27 -0
  78. package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +93 -0
  80. package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6866-79aa5b4e47cac6aa.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/{6544cb48.a87fe20ddf137be2.js → 6b89c8bd.24df687a820500b3.js} +1 -1
  83. package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +149 -0
  87. package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +104 -0
  88. package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7385.50a308a477bdfc21.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 7644.17e37ba6f1d4226e.js} +4 -4
  90. package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/{8018.a32663f04a6fc5f9.js → 8219.baa715d1deee80e2.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/{4111.2bfedbb233ad206b.js → 8256.e3ac8421a71f82f4.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8437-8d5492094b166cfa.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 8444.4c26b379ca2b9596.js} +17 -17
  100. package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +226 -0
  101. package/apps/pwa/out/_next/static/chunks/8557-e7898769499cd56f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +64 -0
  104. package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 8637.47f5b35afcae5e6b.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8714.ff0b7ce3ec3e3ae2.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9214.63a510d39178e997.js} +2 -2
  111. package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +115 -0
  112. package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 938.66ad1ef0e5abae1c.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 9512.5a76207a730e0491.js} +2 -2
  115. package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{69-0a2c8209c6d4a158.js → 967-2aa39b2d04b4c690.js} +1 -1
  117. package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 9952.5daf5f94063a2b3e.js} +1 -1
  120. package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/{page-a27b1e5a0d1b308f.js → page-406b47745b53f269.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-26e6c18a1a750cf6.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/{page-32866485913d6a04.js → page-47c5d4db587266bd.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1f5a60f70cb4dd0c.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-bac7dee94e5eae4a.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-04d00ae9b0890349.js → page-dc0a532f5b9196ec.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → b2f6ba4d.fb56fdbbf798df33.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/b6705a4f-b9a9047de9eecfd0.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → cbe38a15.5a032598e39970c6.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → d06f9160.a3d9062f95de8ad7.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → da5176c6.6773b6c5994e1d99.js} +7 -7
  178. package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.js +1 -0
  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 +10 -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/README.md +5 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/default-loop.yaml +76 -5
  285. package/graphs/document-loop.yaml +71 -4
  286. package/graphs/implement-loop.yaml +59 -4
  287. package/graphs/journey/SCENARIOS.md +33 -0
  288. package/graphs/journey/recipes.yaml +1 -0
  289. package/graphs/journey/ta-journey.yaml +94 -0
  290. package/graphs/journey/units/author/author.yaml +20 -0
  291. package/graphs/journey/units/author/recipes.yaml +2 -0
  292. package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
  293. package/graphs/journey/units/author-dialogue/observe.ts +96 -0
  294. package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
  295. package/graphs/journey/units/green/green.yaml +20 -0
  296. package/graphs/journey/units/green/recipes.yaml +2 -0
  297. package/graphs/journey/units/pr/pr.yaml +20 -0
  298. package/graphs/journey/units/pr/recipes.yaml +2 -0
  299. package/graphs/journey/units/remember/recipes.yaml +2 -0
  300. package/graphs/journey/units/remember/remember.yaml +20 -0
  301. package/graphs/operate-loop.yaml +71 -4
  302. package/graphs/overlays/stop-heal-ladder.yaml +1 -1
  303. package/graphs/release-rehearsal/recipes.yaml +1 -1
  304. package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
  305. package/graphs/research-loop.yaml +159 -4
  306. package/graphs/test-diet/test-diet.yaml +3 -0
  307. package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
  308. package/graphs/units/dispatch-pod/recipes.yaml +14 -0
  309. package/graphs/units/entry/entry.yaml +50 -0
  310. package/graphs/units/entry/recipes.yaml +14 -0
  311. package/graphs/units/harvest/harvest.yaml +25 -0
  312. package/graphs/units/harvest/recipes.yaml +4 -0
  313. package/graphs/units/land/land.yaml +45 -0
  314. package/graphs/units/land/recipes.yaml +3 -0
  315. package/graphs/units/recipes.yaml +7 -0
  316. package/graphs/units/recover.yaml +39 -0
  317. package/graphs/units/reflect/recipes.yaml +3 -0
  318. package/graphs/units/reflect/reflect.yaml +15 -0
  319. package/graphs/units/task-agent-recover-review.yaml +17 -0
  320. package/graphs/units/task-agent-recover-wait.yaml +17 -0
  321. package/graphs/units/verbs/make-doc.yaml +34 -0
  322. package/graphs/units/verbs/recipes.yaml +33 -0
  323. package/graphs/units/verbs/verify.yaml +55 -0
  324. package/graphs/work/recipes.yaml +2 -0
  325. package/graphs/work/research-report.yaml +28 -0
  326. package/package.json +1 -1
  327. package/scripts/ci-typecheck-changed.ts +69 -16
  328. package/scripts/coord-role-pack.ts +19 -6
  329. package/scripts/docs/generate-graph-anatomy.ts +19 -2
  330. package/scripts/graph-harvest-unit.ts +22 -0
  331. package/scripts/graph-units/journey-stub.ts +6 -0
  332. package/scripts/graph-units/land-enqueue.ts +78 -0
  333. package/scripts/graph-units/recover-plan.ts +15 -0
  334. package/scripts/graph-units/reflect-node.ts +88 -0
  335. package/scripts/graph-units/ta-journey-observe.ts +109 -0
  336. package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
  337. package/scripts/graph-units/verbs/verify-stage.ts +75 -0
  338. package/scripts/graph-units/verbs-envelope.ts +139 -0
  339. package/scripts/hq/standby-snapshot.ts +30 -0
  340. package/scripts/public-export.ts +43 -1
  341. package/scripts/ratchets/train-side-invariants.sh +45 -0
  342. package/scripts/release-loop/auto-approve-node.ts +30 -16
  343. package/scripts/release-loop/docs-land-node.ts +21 -5
  344. package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
  345. package/scripts/release-loop/gate-closure.ts +5 -1
  346. package/scripts/release-loop/gate-diff.ts +1 -1
  347. package/scripts/release-loop/gate-node.ts +675 -49
  348. package/scripts/release-loop/gate-partial.ts +68 -14
  349. package/scripts/release-loop/gate-radius-live.ts +177 -0
  350. package/scripts/release-loop/gate-radius-shadow.ts +138 -0
  351. package/scripts/release-loop/gate-traffic-mode.ts +128 -0
  352. package/scripts/release-loop/gate-triage-node.ts +5 -2
  353. package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
  354. package/scripts/release-loop/known-issues-node.ts +77 -8
  355. package/scripts/release-loop/node-verdict.ts +12 -1
  356. package/scripts/release-loop/npm-publish-node.ts +66 -12
  357. package/scripts/release-loop/preflight.ts +93 -7
  358. package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
  359. package/scripts/release-loop/publish-node.ts +60 -9
  360. package/scripts/release-loop/pwa-remote.ts +166 -0
  361. package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
  362. package/scripts/release-loop/resume-cap.ts +56 -0
  363. package/scripts/release-loop/resume-release.ts +155 -19
  364. package/scripts/release-loop/resume.ts +24 -1
  365. package/scripts/release-loop/tui-sim-node.ts +8 -2
  366. package/scripts/release-loop/unattended-release.ts +10 -2
  367. package/scripts/test-diet/lib.ts +6 -1
  368. package/scripts/test-diet/node.ts +194 -13
  369. package/scripts/ux-sim.ts +39 -0
  370. package/src/acp/core-turn-bridge.ts +20 -5
  371. package/src/acp/reasoning-thought-buffer.ts +45 -0
  372. package/src/agent/self-ambient-cache.ts +8 -0
  373. package/src/agent-substrate/acp-reviewer.ts +90 -15
  374. package/src/agent-substrate/pr-reviewer.ts +17 -0
  375. package/src/agent-substrate/review-finding-key.ts +53 -0
  376. package/src/agent-substrate/self-review-cli.ts +188 -18
  377. package/src/ask-user-question/pending-questions.ts +1 -1
  378. package/src/autopilot/pr-manager.ts +393 -65
  379. package/src/budget/run-usage-rollup.ts +1 -0
  380. package/src/chat/index.ts +0 -2
  381. package/src/chat/pickers/modal-runtime.ts +10 -27
  382. package/src/chat/tool-render/dispatch.ts +62 -10
  383. package/src/cli/agent-cli.ts +13 -2
  384. package/src/cli/control-cli.ts +24 -7
  385. package/src/cli/doctor-cli.ts +4 -1
  386. package/src/cli/guardian-cli.ts +10 -0
  387. package/src/cli/light-entry-route.ts +75 -0
  388. package/src/cli/llm-detect-cli.ts +23 -1
  389. package/src/cli/pod-cli.ts +77 -3
  390. package/src/cli/pr-cli.ts +81 -14
  391. package/src/cli/pr-land-base-read.ts +2 -0
  392. package/src/cli/pr-land-overlap-evidence.ts +154 -16
  393. package/src/cli/pr-land-pod-shadow-job.ts +3 -0
  394. package/src/cli/pr-land-recovery.ts +64 -0
  395. package/src/cli/pty-takeover-cli.ts +6 -5
  396. package/src/cli/release-checklist-read-cli.ts +79 -0
  397. package/src/cli/release-cli.ts +189 -132
  398. package/src/cli/release-run-if-ready.ts +29 -28
  399. package/src/cli/release-single-flight.ts +178 -0
  400. package/src/cli/remote-resolve.ts +1 -1
  401. package/src/cli/root-tui-entry.ts +48 -0
  402. package/src/cli/seat-cli.ts +37 -0
  403. package/src/cli/setup-cli.ts +40 -1
  404. package/src/cli/sim-cli.ts +22 -0
  405. package/src/cli/tasks-cli.ts +667 -14
  406. package/src/cli/usage-cli.ts +13 -11
  407. package/src/clipboard/history.ts +179 -13
  408. package/src/config.ts +8 -1
  409. package/src/control/control-status.ts +8 -3
  410. package/src/control-plane/ledger.ts +5 -3
  411. package/src/control-plane/server.ts +5 -3
  412. package/src/core-turn/short-question.ts +5 -1
  413. package/src/dashboard/chat/acp-chat.ts +8 -0
  414. package/src/dashboard/index.ts +114 -77
  415. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
  416. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  417. package/src/dashboard/input/seat-autowake.ts +56 -3
  418. package/src/dashboard/render/theme-resolver.ts +33 -4
  419. package/src/dashboard/seat-boot-preamble.ts +1 -1
  420. package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
  421. package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
  422. package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
  423. package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
  424. package/src/dashboard/turn-preamble.ts +47 -1
  425. package/src/dashboard/turn-stream-formatter.ts +34 -1
  426. package/src/dashboard/turn-stream-runtime.ts +2 -0
  427. package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
  428. package/src/domains/guardian-tick.ts +54 -2
  429. package/src/domains/outbound-alert.ts +3 -2
  430. package/src/domains/schedule-registry.ts +16 -2
  431. package/src/extractors.ts +3 -1
  432. package/src/git-fs/idle-refresh.ts +76 -0
  433. package/src/git-fs/index.ts +18 -7
  434. package/src/git-fs/retry.ts +4 -0
  435. package/src/git-fs/runner.ts +2 -0
  436. package/src/git-fs/worktree.ts +42 -4
  437. package/src/graph-kinds/registry.ts +2 -2
  438. package/src/graph-runner/runner.ts +267 -54
  439. package/src/grok/credential.ts +15 -3
  440. package/src/harness/harness-cli-command.ts +151 -38
  441. package/src/harness/harness-incidents.ts +37 -0
  442. package/src/harness/harness-pod-dispatch.ts +38 -1
  443. package/src/harness/harness-salvage-cli.ts +14 -2
  444. package/src/harness/launch-utterance-ledger.ts +208 -0
  445. package/src/impl-discipline/detector.ts +16 -4
  446. package/src/impl-discipline/system-prompt.ts +11 -0
  447. package/src/impl-discipline/types.ts +2 -2
  448. package/src/index.ts +683 -146
  449. package/src/intake-plane/already-built-hint.ts +91 -0
  450. package/src/intake-plane/requirement-funnel.ts +29 -1
  451. package/src/knowhow/pack.ts +199 -0
  452. package/src/light-cli.ts +111 -0
  453. package/src/llm/opengateway-models.ts +11 -0
  454. package/src/llm/provider-credentials.ts +14 -0
  455. package/src/llm/provider-detect.ts +8 -1
  456. package/src/llm/runtime-model-family.ts +2 -1
  457. package/src/llm.ts +268 -65
  458. package/src/loops/budget.ts +95 -0
  459. package/src/loops/msg-wake.ts +8 -2
  460. package/src/loops/orchestrator/traffic.ts +132 -1
  461. package/src/model-tier/llm-tier-map.ts +15 -1
  462. package/src/mss/logging/log-store.ts +4 -5
  463. package/src/native-tool-catalog.ts +15 -1
  464. package/src/nexus/api/graphs-api.ts +22 -3
  465. package/src/nexus/api/http-server.ts +1 -1
  466. package/src/nexus/api/loop-resources.ts +13 -1
  467. package/src/nexus/api/ops-api.ts +12 -0
  468. package/src/oauth/claude-pty-maturity.ts +66 -0
  469. package/src/oauth/codex-access-mirror.ts +55 -0
  470. package/src/oauth/codex.ts +7 -0
  471. package/src/oauth/fallback-chain.ts +1 -1
  472. package/src/onboarding/first-run.ts +5 -3
  473. package/src/onboarding/non-interactive.ts +64 -13
  474. package/src/onboarding.ts +10 -2
  475. package/src/ops/overview-collect.ts +54 -4
  476. package/src/ops/overview.ts +31 -7
  477. package/src/pr-tool/census.ts +282 -30
  478. package/src/pr-tool/inflight-registry.ts +160 -7
  479. package/src/prompt-library/gpt6-family-addendum.ts +14 -1
  480. package/src/pty-shell/herdr-agent-report.ts +442 -0
  481. package/src/pty-shell/pty-control-ipc.ts +5 -5
  482. package/src/pty-shell/pty-manifest.ts +7 -0
  483. package/src/pty-shell/pty-write-outcome.ts +24 -6
  484. package/src/pty-shell/tui-run-state.ts +117 -3
  485. package/src/release-loop/checklist.ts +103 -5
  486. package/src/release-loop/feature-store.ts +19 -2
  487. package/src/release-loop/landed-but-yellow.ts +129 -5
  488. package/src/release-loop/light-rc.ts +1 -0
  489. package/src/release-loop/placement.ts +10 -3
  490. package/src/release-loop/rehearsal.ts +205 -25
  491. package/src/release-loop/rubric.ts +16 -2
  492. package/src/repl/index.ts +174 -17
  493. package/src/repl/ops-msg-bridge.ts +32 -0
  494. package/src/self-dev/ask-launch-flow.ts +44 -5
  495. package/src/self-dev/cli-help-text.ts +17 -0
  496. package/src/self-dev/dev-cli.ts +11 -9
  497. package/src/self-dev/draft-residue.ts +37 -1
  498. package/src/self-dev/draft-sweep.ts +188 -13
  499. package/src/self-dev/draft-triage-rules.ts +107 -0
  500. package/src/self-dev/fleet-reduce.ts +3 -2
  501. package/src/self-dev/graph-front-nodes.ts +112 -0
  502. package/src/self-dev/graph-journey-nodes.ts +11 -6
  503. package/src/self-dev/graph-journey-route.ts +60 -6
  504. package/src/self-dev/harness-run-cli.ts +3 -15
  505. package/src/self-dev/orchestrate-cli-text.ts +10 -0
  506. package/src/self-dev/orchestrate.ts +79 -3
  507. package/src/self-dev/review-provider-fallback.ts +35 -1
  508. package/src/self-dev/run-supervisor.ts +107 -12
  509. package/src/self-dev/run-types.ts +5 -1
  510. package/src/self-dev/self-orchestrate-runtime.ts +1 -11
  511. package/src/self-dev/shard-aggregate.ts +42 -5
  512. package/src/self-dev/shard-run.ts +8 -1
  513. package/src/self-implement/blocked-draft-policy.ts +20 -0
  514. package/src/self-implement/classify-shadow.ts +3 -7
  515. package/src/self-implement/doctor-visit.ts +18 -1
  516. package/src/self-implement/gate-baseline.ts +95 -12
  517. package/src/self-implement/gate-cli.ts +1 -0
  518. package/src/self-implement/gate-remote.ts +40 -25
  519. package/src/self-implement/goal-author-decompose.ts +275 -47
  520. package/src/self-implement/goal-author-identity.ts +66 -0
  521. package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
  522. package/src/self-implement/goal-author.ts +254 -120
  523. package/src/self-implement/goal-elaborate.ts +295 -0
  524. package/src/self-implement/goal-refine.ts +270 -0
  525. package/src/self-implement/graph-overlay-yaml.ts +28 -2
  526. package/src/self-implement/graph-unit-flatten.ts +103 -0
  527. package/src/self-implement/graph-unit-resolver.ts +107 -0
  528. package/src/self-implement/graph-yaml.ts +151 -1
  529. package/src/self-implement/headless-elanous-driver.ts +1 -0
  530. package/src/self-implement/knowhow-pack.ts +103 -0
  531. package/src/self-implement/orchestrator.ts +160 -45
  532. package/src/self-implement/pod-warm-pool-profile.ts +45 -0
  533. package/src/self-implement/review-mustfix-class.ts +203 -0
  534. package/src/self-implement/rework-budget-judgment.ts +5 -8
  535. package/src/self-implement/run-stop.ts +17 -2
  536. package/src/self-implement/running-runs.ts +29 -1
  537. package/src/self-implement/scope-adjacency.ts +113 -0
  538. package/src/self-implement/seams.ts +138 -4
  539. package/src/self-implement/stop-autoheal.ts +112 -2
  540. package/src/session/chat.ts +27 -0
  541. package/src/session-runtime/index.ts +1 -1
  542. package/src/session-runtime/retry-policy.ts +2 -1
  543. package/src/setup/llm-env-detect.ts +5 -0
  544. package/src/skills/tools/agent.ts +140 -14
  545. package/src/skills/tools/msg-ask.ts +100 -0
  546. package/src/skills/tools/ops-ledger.ts +2 -1
  547. package/src/skills/tools/schedule-wakeup.ts +66 -17
  548. package/src/steward/hold-hygiene.ts +24 -6
  549. package/src/steward/release-day.ts +7 -3
  550. package/src/steward/triage-budget.ts +194 -0
  551. package/src/steward/triage.ts +57 -7
  552. package/src/task-agent/actions.ts +69 -1
  553. package/src/task-agent/green-sweep.ts +4 -0
  554. package/src/task-agent/harvest-unit.ts +141 -0
  555. package/src/task-agent/live-moves.ts +257 -15
  556. package/src/task-agent/parent-host.ts +216 -6
  557. package/src/task-agent/postland-card.ts +80 -1
  558. package/src/task-agent/rejudge-on-head.ts +112 -26
  559. package/src/task-agent/repair-branch-cas.ts +4 -1
  560. package/src/task-agent/repair-cycle.ts +16 -3
  561. package/src/task-agent/run-identity.ts +4 -3
  562. package/src/task-agent/shadow.ts +19 -3
  563. package/src/task-agent/task-hand.ts +96 -36
  564. package/src/task-agent/tier-split.ts +127 -0
  565. package/src/task-agent/work-order-build.ts +24 -0
  566. package/src/task-agent/work-order.ts +3 -2
  567. package/src/task-orchestrator/generator-prompt.ts +60 -11
  568. package/src/task-orchestrator/surfaces/pod-account-broker.ts +72 -3
  569. package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
  570. package/src/task-orchestrator/surfaces/pod-command-job.ts +47 -8
  571. package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
  572. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
  573. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
  574. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +8 -2
  575. package/src/task-orchestrator/surfaces/pod-pool.ts +73 -17
  576. package/src/task-orchestrator/surfaces/pod-provenance.ts +76 -0
  577. package/src/task-orchestrator/surfaces/pod-source-receive.ts +72 -4
  578. package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
  579. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +32 -5
  580. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +3 -0
  581. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +421 -0
  582. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +2 -1
  583. package/src/task-orchestrator/surfaces/self-implement-pod.ts +588 -71
  584. package/src/task-orchestrator/surfaces/self-implement.ts +106 -2
  585. package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
  586. package/src/tool-runtime/truncation-store.ts +4 -0
  587. package/src/tui/README.md +2 -0
  588. package/src/tui/chat/background-job-status.ts +54 -0
  589. package/src/tui/chat/log-view.ts +80 -0
  590. package/src/tui/entry.ts +406 -0
  591. package/src/tui/input/composer.ts +144 -0
  592. package/src/tui/seat-mail-boot.ts +59 -0
  593. package/src/tui/slash/compact.ts +100 -0
  594. package/src/tui/slash/new-session.ts +35 -0
  595. package/src/tui-client/dashboard-session.ts +10 -1
  596. package/src/tui-client/local-chat-turn.ts +239 -0
  597. package/src/tui-client/local-harness-command.ts +63 -0
  598. package/src/tui-client/local-provider-command.ts +184 -0
  599. package/src/user-config/coercion.ts +36 -0
  600. package/src/user-config.ts +22 -43
  601. package/src/ux-sim/event-monkey.ts +378 -0
  602. package/src/ux-sim/fake-bin.ts +42 -7
  603. package/src/ux-sim/fault-nextmove-dispatch.ts +266 -0
  604. package/src/ux-sim/fault-pod-codex-503.ts +211 -0
  605. package/src/ux-sim/fault-scope-escape-lift.ts +189 -0
  606. package/src/ux-sim/scenario.ts +72 -13
  607. package/src/version/packed-revision.json +1 -1
  608. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
  611. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
  612. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
  613. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
  617. package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
  619. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
  620. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
  629. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
  630. package/apps/pwa/out/_next/static/chunks/3541-ce3a5424ed5ad7f1.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
  636. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
  640. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
  641. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +0 -226
  642. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
  644. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
  647. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/5543.a438b8ab5a13ea47.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
  653. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
  655. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
  661. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
  662. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
  663. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
  668. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
  669. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
  674. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +0 -24
  685. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/9989.3694300e5f000b14.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/setup/page-c219f2ed171131be.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
  744. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
  752. package/src/cli/g6a-registration-probe.ts +0 -16
  753. /package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → T1mBQqmkwKDLGtyisDCOd}/_ssgManifest.js +0 -0
@@ -75,10 +75,11 @@ function configuredUsageHosts(): { local: string; remote: string[] } {
75
75
  return { local, remote: [...new Set(entries.map((entry) => entry.host?.trim()).filter((host): host is string => !!host && host !== local))] };
76
76
  }
77
77
 
78
- type UsageAxis = 'stage' | 'model' | 'account';
78
+ type UsageAxis = 'stage' | 'phase' | 'model' | 'account';
79
79
  type ExtendedRunUsageInput = RunUsageInput & { stage?: string | null; account?: string | null; origin?: string; podJob?: string; job?: string; measured?: boolean };
80
80
  type AxisUsageRow = {
81
81
  stage?: string;
82
+ phase?: string;
82
83
  model?: string;
83
84
  account?: string;
84
85
  hostIds: string[];
@@ -97,7 +98,7 @@ type AxisUsageRow = {
97
98
  };
98
99
 
99
100
  type FederatedUsageRow = {
100
- runId?: string; role?: string; site?: string; stage?: string; model?: string; account?: string;
101
+ runId?: string; role?: string; site?: string; stage?: string; phase?: string; model?: string; account?: string;
101
102
  billingProvider?: string; billing?: string; hostIds: string[]; rankUsd?: number;
102
103
  calls: number; inputTokens: number; outputTokens: number; cacheReadInputTokens: number;
103
104
  cacheCreationInputTokens: number; reasoningOutputTokens: number; usdKnown: number;
@@ -122,7 +123,7 @@ function validUsageRows(value: unknown, axis: 'run' | 'role' | UsageAxis): value
122
123
  const number = row[field];
123
124
  return typeof number === 'number' && Number.isFinite(number) && number >= 0;
124
125
  })
125
- && (axis !== 'stage' && axis !== 'model' && axis !== 'account'
126
+ && (axis !== 'stage' && axis !== 'phase' && axis !== 'model' && axis !== 'account'
126
127
  || typeof row.rankUsd === 'number' && Number.isFinite(row.rankUsd));
127
128
  });
128
129
  }
@@ -137,7 +138,7 @@ function mergeUsageRows(groups: readonly FederatedUsageRow[][], axis: 'run' | 'r
137
138
  if (!previous) { merged.set(key, { ...row, hostIds: [...row.hostIds] }); continue; }
138
139
  for (const field of SUM_FIELDS) previous[field] += row[field];
139
140
  previous.hostIds = [...new Set([...previous.hostIds, ...row.hostIds])];
140
- if (axis === 'stage' || axis === 'model' || axis === 'account') previous.rankUsd = previous.usdKnown + previous.apiEquivalentUsd;
141
+ if (axis === 'stage' || axis === 'phase' || axis === 'model' || axis === 'account') previous.rankUsd = previous.usdKnown + previous.apiEquivalentUsd;
141
142
  }
142
143
  return [...merged.values()];
143
144
  }
@@ -186,6 +187,7 @@ function rollupByAxis(inputs: readonly ExtendedRunUsageInput[], axis: UsageAxis)
186
187
  const groups = new Map<string, ExtendedRunUsageInput[]>();
187
188
  for (const data of inputs) {
188
189
  const value = axis === 'stage' ? stageForUsage(data)
190
+ : axis === 'phase' ? (typeof data.phase === 'string' && data.phase.length > 0 ? data.phase : '(none)')
189
191
  : axis === 'model' ? (data.model || '(none)')
190
192
  : (data.account || '(none)');
191
193
  const group = groups.get(value) ?? [];
@@ -216,7 +218,7 @@ function rollupByAxis(inputs: readonly ExtendedRunUsageInput[], axis: UsageAxis)
216
218
  }
217
219
 
218
220
  function isUsageAxis(value: string): value is 'run' | 'role' | UsageAxis {
219
- return value === 'run' || value === 'role' || value === 'stage' || value === 'model' || value === 'account';
221
+ return value === 'run' || value === 'role' || value === 'stage' || value === 'phase' || value === 'model' || value === 'account';
220
222
  }
221
223
 
222
224
  function formatAxisUsage(row: AxisUsageRow, axis: UsageAxis): string {
@@ -249,9 +251,9 @@ export function registerUsageCommand(program: Command, deps: UsageCliDeps = {}):
249
251
 
250
252
  usage
251
253
  .command('runs')
252
- .description('저장된 llm-usage 로그를 런·역할·단계·모델·계정별로 집계한다')
254
+ .description('저장된 llm-usage 로그를 런·역할·단계·phase·모델·계정별로 집계한다')
253
255
  .option('--run <runId>', '런 ID 정확 일치')
254
- .option('--by <axis>', '집계 축 (run | role | stage | model | account)', 'run')
256
+ .option('--by <axis>', '집계 축 (run | role | stage | phase | model | account)', 'run')
255
257
  .option(...LOGS_SINCE_OPTION)
256
258
  .option('--hosts <scope>', '호스트 연합 (all: 이 호스트 + 설정된 taskAgent.parentHost)')
257
259
  .option('--json', '집계 행 JSON 출력')
@@ -298,14 +300,14 @@ export function registerUsageCommand(program: Command, deps: UsageCliDeps = {}):
298
300
  const complete = !rosterReason && hosts.every((host) => host.status === 'ok');
299
301
  const rows = mergeUsageRows(parts, opts.by as 'run' | 'role' | UsageAxis);
300
302
  if (opts.by === 'role') rows.sort((a, b) => b.calls - a.calls);
301
- if (opts.by === 'stage' || opts.by === 'model' || opts.by === 'account') rows.sort((a, b) => (b.rankUsd ?? 0) - (a.rankUsd ?? 0) || b.calls - a.calls);
303
+ if (opts.by === 'stage' || opts.by === 'phase' || opts.by === 'model' || opts.by === 'account') rows.sort((a, b) => (b.rankUsd ?? 0) - (a.rankUsd ?? 0) || b.calls - a.calls);
302
304
  if (json) { out.log(JSON.stringify({ rows, hosts, complete, ...(rosterReason ? { reason: rosterReason } : {}) }, null, 2)); return; }
303
305
  out.log(`호스트 ${hosts.filter((host) => host.status === 'ok').length}/${hosts.length} 측정 · ${complete ? '완결' : '부분 합계'}`);
304
306
  if (rosterReason) out.log(`호스트 목록: 못 잼 (${rosterReason})`);
305
307
  for (const host of hosts) if (host.status === 'unmeasured') out.log(`${host.host}: 못 잼 (${host.reason})`);
306
308
  if (rows.length === 0) { out.log('(일치하는 런 사용량 없음)'); return; }
307
309
  for (const row of rows) {
308
- if (opts.by === 'stage' || opts.by === 'model' || opts.by === 'account') out.log(formatAxisUsage(row as AxisUsageRow, opts.by));
310
+ if (opts.by === 'stage' || opts.by === 'phase' || opts.by === 'model' || opts.by === 'account') out.log(formatAxisUsage(row as AxisUsageRow, opts.by));
309
311
  else if (opts.by === 'role') out.log(`${row.role} ${row.site} ${row.model} ${row.billingProvider}/${row.billing} calls=${row.calls} input=${row.inputTokens} output=${row.outputTokens} usdKnown=${row.usdKnown} unknownCostCalls=${row.unknownCostCalls} includedCalls=${row.includedCalls} apiEquivalentUsd=${row.apiEquivalentUsd}`);
310
312
  else out.log(`${row.runId} ${row.model} ${row.billingProvider}/${row.billing} hosts=${row.hostIds.join(',') || '(none)'} calls=${row.calls} input=${row.inputTokens} output=${row.outputTokens} cacheRead=${row.cacheReadInputTokens} cacheCreation=${row.cacheCreationInputTokens} reasoning=${row.reasoningOutputTokens} usdKnown=${row.usdKnown} unknownCostCalls=${row.unknownCostCalls} includedCalls=${row.includedCalls} apiEquivalentUsd=${row.apiEquivalentUsd}`);
311
313
  }
@@ -323,14 +325,14 @@ export function registerUsageCommand(program: Command, deps: UsageCliDeps = {}):
323
325
  localFailure = '로컬 logs.db 조회 실패';
324
326
  }
325
327
  }
326
- const unwrapPod = opts.by === 'stage' || opts.by === 'model' || opts.by === 'account';
328
+ const unwrapPod = opts.by === 'stage' || opts.by === 'phase' || opts.by === 'model' || opts.by === 'account';
327
329
  // ⭐ METER-POD-ROLLUP-GAP-2 — Pod 사용량 재방출 행(podRollupKey)은 «더 완전한 한 행»만 센다(키 없는 행은 그대로).
328
330
  const selected = rows.map((row) => usageData(row, unwrapPod))
329
331
  .filter((data): data is ExtendedRunUsageInput => data !== null)
330
332
  .filter((data) => opts.run === undefined || data.runId === opts.run);
331
333
  // A returned Pod raw row and its host rollup describe the same usage. Keep raw rows when no measured rollup exists.
332
334
  const inputs = dedupePodRollupRows(unwrapPod ? excludeCoveredPodRawRows(selected) : selected);
333
- if (opts.by === 'stage' || opts.by === 'model' || opts.by === 'account') {
335
+ if (opts.by === 'stage' || opts.by === 'phase' || opts.by === 'model' || opts.by === 'account') {
334
336
  const report = rollupByAxis(inputs, opts.by);
335
337
  if (opts.hosts === 'all') { emitFederated(report, localFailure); return; }
336
338
  if (json) {
@@ -8,15 +8,19 @@
8
8
  //
9
9
  // Why polling vs an OS event hook: macOS doesn't expose a clipboard-
10
10
  // changed notification to userland binaries without entitlements.
11
- // pbpaste at 1.5s cadence is cheap (sub-millisecond per call on a
12
- // recent Mac) and the small lag is fine for "look back at what I
13
- // copied 30s ago" use cases.
11
+ // Keep a short active cadence, then back off while the TUI is idle so
12
+ // an open terminal does not spawn pbpaste every 1.5s indefinitely.
13
+ // CLASSIC-IDLE-CLIPBOARD (2026-10-21): callers that only show the history
14
+ // inside a panel start with `active: false` and flip `setActive(true)` while
15
+ // the panel is visible — a closed panel spawns zero pbpaste processes
16
+ // (5-minute idle classic TUI measured 88 reads before this change).
14
17
  //
15
18
  // Image entries: we already track a separate path-based registry for
16
19
  // pasted screenshots (context.ts). This module is text-only by
17
20
  // design — image previews live in the main scratchpad already.
18
21
 
19
22
  import { readClipboardText, isClipboardSupported } from './index.js';
23
+ import { debug } from '../debug/log.js';
20
24
 
21
25
  export interface ClipboardEntry {
22
26
  /** UTF-8 text. Trimmed of a single trailing newline so visually
@@ -29,6 +33,19 @@ export interface ClipboardEntry {
29
33
  export interface ClipboardHistoryOpts {
30
34
  /** Polling interval in ms. Defaults to 1500. */
31
35
  intervalMs?: number;
36
+ /** Start slowing clipboard reads after this much user inactivity. Defaults to 2 minutes. */
37
+ idleAfterMs?: number;
38
+ /** Poll interval multiplier after idleAfterMs. Defaults to 10 (15s with the default cadence). */
39
+ idleIntervalMultiplier?: number;
40
+ /** Start the deepest backoff after this much user inactivity. Defaults to 10 minutes. */
41
+ longIdleAfterMs?: number;
42
+ /** Poll interval multiplier after longIdleAfterMs. Defaults to 60 (90s with the default cadence). */
43
+ longIdleIntervalMultiplier?: number;
44
+ /** Start polling immediately. Defaults to true. `false` keeps the poller
45
+ * dormant (no reads, no timer) until `setActive(true)`. */
46
+ active?: boolean;
47
+ /** Busy streams keep the active cadence and restart the idle grace period when they finish. */
48
+ isBusy?: () => boolean;
32
49
  /** Cap on stored entries; oldest fall off when exceeded. Defaults
33
50
  * to 50 — enough for a typical session, not so big the list
34
51
  * becomes unscrollable. */
@@ -40,6 +57,17 @@ export interface ClipboardHistoryOpts {
40
57
  maxBytes?: number;
41
58
  }
42
59
 
60
+ /** Dependencies are injectable so tests can exercise the real poller without
61
+ * process-wide `mock.module()` state. Production callers use the defaults. */
62
+ export interface ClipboardHistoryDependencies {
63
+ readClipboardText(): Promise<string | null>;
64
+ isClipboardSupported(): boolean;
65
+ /** Observation sink for poll-state transitions. Defaults to
66
+ * `debug.log('clipboard.history', …)`; tests inject a recorder because
67
+ * the debug sink arms its own flush timer. */
68
+ observe?(event: 'poll-state', data: { active: boolean; reason: string }): void;
69
+ }
70
+
43
71
  export interface ClipboardHistory {
44
72
  /** Snapshot list, newest first. Caller may read but should not
45
73
  * mutate — use `clear` to reset. */
@@ -54,12 +82,27 @@ export interface ClipboardHistory {
54
82
  * history reflects the just-promoted entry without waiting for
55
83
  * the next tick. */
56
84
  pokeNow(): Promise<void>;
85
+ /** Mark TUI input. Wakes the poller immediately if it had slowed down. */
86
+ noteActivity(): void;
87
+ /** Notify the poller immediately when its busy source changes state. */
88
+ noteBusyChange(): void;
89
+ /** Start/stop background polling (e.g. history panel opened/closed).
90
+ * Activating reads once immediately; deactivating clears the timer.
91
+ * Repeating the current state is a no-op. */
92
+ setActive(active: boolean, reason?: string): void;
57
93
  }
58
94
 
59
95
  /** Start polling. No-op on non-clipboard platforms — returns a stub
60
96
  * with empty entries so callers don't need to guard every call. */
61
- export function startClipboardHistory(opts: ClipboardHistoryOpts = {}): ClipboardHistory {
97
+ export function startClipboardHistory(
98
+ opts: ClipboardHistoryOpts = {},
99
+ dependencies: ClipboardHistoryDependencies = { readClipboardText, isClipboardSupported },
100
+ ): ClipboardHistory {
62
101
  const intervalMs = opts.intervalMs ?? 1500;
102
+ const idleAfterMs = opts.idleAfterMs ?? 2 * 60_000;
103
+ const idleIntervalMultiplier = opts.idleIntervalMultiplier ?? 10;
104
+ const longIdleAfterMs = opts.longIdleAfterMs ?? 10 * 60_000;
105
+ const longIdleIntervalMultiplier = opts.longIdleIntervalMultiplier ?? 60;
63
106
  const maxEntries = opts.maxEntries ?? 50;
64
107
  const maxBytes = opts.maxBytes ?? 8 * 1024;
65
108
 
@@ -67,15 +110,51 @@ export function startClipboardHistory(opts: ClipboardHistoryOpts = {}): Clipboar
67
110
  const subs = new Set<() => void>();
68
111
  let stopped = false;
69
112
  let lastSeenText: string | null = null;
70
- let timer: ReturnType<typeof setInterval> | null = null;
113
+ let timer: ReturnType<typeof setTimeout> | null = null;
114
+ let inFlight: Promise<void> | null = null;
115
+ let immediatePollAfterInFlight = false;
116
+ let queuedActivityPoll: Promise<void> | null = null;
117
+ let lastActivityAt = Date.now();
118
+ let wasBusy = readBusy();
119
+ let active = opts.active ?? true;
120
+
121
+ function readBusy(): boolean {
122
+ try { return opts.isBusy?.() ?? false; } catch { return false; }
123
+ }
124
+
125
+ const idleMs = (): number => {
126
+ const busy = readBusy();
127
+ if (wasBusy && !busy) lastActivityAt = Date.now();
128
+ wasBusy = busy;
129
+ return busy ? 0 : Math.max(0, Date.now() - lastActivityAt);
130
+ };
131
+
132
+ const nextDelayMs = (): number => {
133
+ const idle = idleMs();
134
+ if (idle >= longIdleAfterMs) return intervalMs * longIdleIntervalMultiplier;
135
+ if (idle >= idleAfterMs) return intervalMs * idleIntervalMultiplier;
136
+ return intervalMs;
137
+ };
138
+
139
+ const scheduleNext = (): void => {
140
+ if (stopped || !active) return;
141
+ if (timer) clearTimeout(timer);
142
+ timer = setTimeout(() => {
143
+ timer = null;
144
+ void poll();
145
+ }, nextDelayMs());
146
+ };
71
147
 
72
- if (!isClipboardSupported()) {
148
+ if (!dependencies.isClipboardSupported()) {
73
149
  return {
74
150
  entries,
75
151
  onChange: (fn) => { subs.add(fn); return () => subs.delete(fn); },
76
152
  stop: () => { stopped = true; },
77
153
  clear: () => { entries.length = 0; },
78
154
  pokeNow: async () => { /* no-op */ },
155
+ noteActivity: () => {},
156
+ noteBusyChange: () => {},
157
+ setActive: () => {},
79
158
  };
80
159
  }
81
160
 
@@ -97,25 +176,112 @@ export function startClipboardHistory(opts: ClipboardHistoryOpts = {}): Clipboar
97
176
  for (const fn of subs) { try { fn(); } catch { /* ignore */ } }
98
177
  };
99
178
 
100
- const poll = async (): Promise<void> => {
101
- if (stopped) return;
102
- try { ingest(await readClipboardText()); } catch { /* swallow */ }
179
+ const poll = (): Promise<void> => {
180
+ if (stopped) return Promise.resolve();
181
+ if (inFlight) return inFlight;
182
+ const run = Promise.resolve().then(async (): Promise<void> => {
183
+ try { ingest(await dependencies.readClipboardText()); } catch { /* swallow */ }
184
+ finally {
185
+ inFlight = null;
186
+ if (immediatePollAfterInFlight && !stopped) {
187
+ immediatePollAfterInFlight = false;
188
+ queuedActivityPoll = poll();
189
+ void queuedActivityPoll;
190
+ } else {
191
+ immediatePollAfterInFlight = false;
192
+ scheduleNext();
193
+ }
194
+ }
195
+ });
196
+ inFlight = run;
197
+ return run;
198
+ };
199
+
200
+ const pollImmediately = (): void => {
201
+ if (inFlight) {
202
+ immediatePollAfterInFlight = true;
203
+ return;
204
+ }
205
+ void poll();
206
+ };
207
+
208
+ const noteActivity = (): void => {
209
+ const wokeFromIdle = idleMs() >= idleAfterMs;
210
+ lastActivityAt = Date.now();
211
+ wasBusy = readBusy();
212
+ if (wokeFromIdle && active) {
213
+ if (timer) clearTimeout(timer);
214
+ timer = null;
215
+ pollImmediately();
216
+ }
217
+ };
218
+
219
+ const noteBusyChange = (): void => {
220
+ const busy = readBusy();
221
+ if (busy === wasBusy) return;
222
+ wasBusy = busy;
223
+ lastActivityAt = Date.now();
224
+ if (!active) return;
225
+ if (timer) clearTimeout(timer);
226
+ timer = null;
227
+ pollImmediately();
228
+ };
229
+
230
+ const setActive = (next: boolean, reason = 'unspecified'): void => {
231
+ if (stopped || next === active) return;
232
+ active = next;
233
+ const observe = dependencies.observe
234
+ ?? ((event: string, data: unknown) => { debug.log('clipboard.history', event, data); });
235
+ try { observe('poll-state', { active, reason }); } catch { /* observation must not break polling */ }
236
+ if (timer) clearTimeout(timer);
237
+ timer = null;
238
+ if (!active) {
239
+ immediatePollAfterInFlight = false;
240
+ return;
241
+ }
242
+ lastActivityAt = Date.now();
243
+ wasBusy = readBusy();
244
+ pollImmediately();
103
245
  };
104
246
 
105
247
  // Kick off immediately so the very first frame already has at
106
248
  // least one entry (whatever's currently on the clipboard).
107
- void poll();
108
- timer = setInterval(() => { void poll(); }, intervalMs);
249
+ // A dormant poller (active:false) reads on its first setActive(true).
250
+ if (active) void poll();
109
251
 
110
252
  return {
111
253
  entries,
112
254
  onChange: (fn) => { subs.add(fn); return () => subs.delete(fn); },
113
255
  stop: () => {
114
256
  stopped = true;
115
- if (timer) clearInterval(timer);
257
+ if (timer) clearTimeout(timer);
116
258
  timer = null;
117
259
  },
118
260
  clear: () => { entries.length = 0; lastSeenText = null; },
119
- pokeNow: async () => { await poll(); },
261
+ pokeNow: async () => {
262
+ // Keep this request independent from noteActivity. If a wake poll is
263
+ // already queued behind the current read, it will satisfy this poke.
264
+ lastActivityAt = Date.now();
265
+ wasBusy = readBusy();
266
+ const currentRead = inFlight;
267
+ const canUseQueuedWake = Boolean(currentRead && immediatePollAfterInFlight);
268
+ if (timer) clearTimeout(timer);
269
+ timer = null;
270
+ if (currentRead) {
271
+ await currentRead;
272
+ if (canUseQueuedWake && queuedActivityPoll) {
273
+ await queuedActivityPoll;
274
+ return;
275
+ }
276
+ if (timer) clearTimeout(timer);
277
+ timer = null;
278
+ }
279
+ // Reads already in progress may have captured the clipboard before
280
+ // this promotion, so take a fresh snapshot after they finish.
281
+ await poll();
282
+ },
283
+ noteActivity,
284
+ noteBusyChange,
285
+ setActive,
120
286
  };
121
287
  }
package/src/config.ts CHANGED
@@ -6,6 +6,7 @@ import { lookupLlmTierSpec } from './model-tier/llm-tier-map.js';
6
6
  import { listSshHosts } from './ssh/ssh-hosts.js';
7
7
  import { isInstalledPackagePath } from './instance/installed-package.js';
8
8
  import { defaultObsidianVault } from './obsidian/default-vault.js';
9
+ import { OPENGATEWAY_DEFAULT_MODEL } from './llm/opengateway-models.js';
9
10
 
10
11
  // ── User config ──
11
12
  export const REMOTE_HOME = homedir();
@@ -191,7 +192,7 @@ export function refreshKeyFromCache(envName: string): boolean {
191
192
  * 자식 프로세스도 이 env 를 물려받는다. 반환 = 캐시로 채운 이름(값은 절대 안 싣는다).
192
193
  */
193
194
  export const DAEMON_KEY_ENV_NAMES = [
194
- 'ANTHROPIC_API_KEY', 'GEMINI_API_KEY', 'OPENAI_API_KEY', 'XAI_API_KEY', 'OPENROUTER_API_KEY',
195
+ 'ANTHROPIC_API_KEY', 'GEMINI_API_KEY', 'OPENAI_API_KEY', 'XAI_API_KEY', 'OPENROUTER_API_KEY', 'OPENGATEWAY_API_KEY',
195
196
  'ELANOUS_OPENAI_RELAY_SHARED_SECRET',
196
197
  ] as const;
197
198
 
@@ -239,6 +240,12 @@ export const OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions
239
240
  // 기본 = 사다리 `balanced`(`llm-tier-map.ts` OPENROUTER). 카탈로그 id 는 `openrouter/<vendor>/<model>`,
240
241
  // wire 로는 `openrouter/` 를 떼고 보낸다(`makeOpenRouterProvider`).
241
242
  export const OPENROUTER_MODEL = process.env.OPENROUTER_MODEL || 'openrouter/z-ai/glm-5.3';
243
+ /** Optional OpenAI-compatible gateway. Cache wins over inherited env, as for other API keys. */
244
+ export function getOpenGatewayApiKey(): string | undefined {
245
+ return keyFromCacheOrEnv('OPENGATEWAY_API_KEY');
246
+ }
247
+ export const OPENGATEWAY_API_URL = 'https://apis.opengateway.ai/v1/chat/completions';
248
+ export const OPENGATEWAY_MODEL = process.env.OPENGATEWAY_MODEL || OPENGATEWAY_DEFAULT_MODEL;
242
249
  export function getLocalLLMUrl(): string | undefined {
243
250
  return process.env.LOCAL_LLM_URL; // e.g. http://localhost:11434/v1 (ollama)
244
251
  }
@@ -33,6 +33,13 @@ export interface ControlStatusDeps {
33
33
  log?: typeof debug.log;
34
34
  }
35
35
 
36
+ /** The same read-only HQ source used by `control status` and HQ-fenced control serve. */
37
+ export function readControlHqLease(): ReturnType<typeof readHqLease> {
38
+ return readHqLease(getElanousConfigDirOverride() !== undefined
39
+ ? { store: fileLeaseStore(join(effectiveInstanceRoot(), 'hq', 'lease.json')), hostPath: join(effectiveInstanceRoot(), 'hq', 'host') }
40
+ : {});
41
+ }
42
+
36
43
  const missing = (row: ControlStatusRowName, reason: string): ControlStatusRow => ({ row, state: 'unmeasured', text: '못 쟀다', reason });
37
44
 
38
45
  function localInstallRoot(): string {
@@ -76,9 +83,7 @@ export async function collectControlStatus(deps: ControlStatusDeps = {}): Promis
76
83
  };
77
84
 
78
85
  await add('집', async () => {
79
- const readLease = deps.readLease ?? (() => readHqLease(getElanousConfigDirOverride() !== undefined
80
- ? { store: fileLeaseStore(join(effectiveInstanceRoot(), 'hq', 'lease.json')), hostPath: join(effectiveInstanceRoot(), 'hq', 'host') }
81
- : {}));
86
+ const readLease = deps.readLease ?? readControlHqLease;
82
87
  const { record, ageSeconds, expired } = await readLease();
83
88
  if (!record) return missing('집', '본부 임대 기록 없음');
84
89
  return { row: '집', state: expired ? 'warn' : 'ok',
@@ -23,6 +23,7 @@ export interface PodWorkerKey { context: string; imageDigest: string; lockHash:
23
23
  type PodWorkerState = 'idle' | 'leased' | 'sanitizing' | 'quarantined';
24
24
  interface PodWorkerLeaseAttrs {
25
25
  key: PodWorkerKey;
26
+ podUid: string;
26
27
  state: PodWorkerState;
27
28
  generation: number;
28
29
  idleTtlMs: number;
@@ -203,20 +204,20 @@ export class ResourceLedger {
203
204
  }
204
205
 
205
206
  /** A trusted host registers a clean instance; canary verification is a separate, still unwired step. */
206
- registerPodWorker(request: { workerId: string; machine: string; key: PodWorkerKey; owner: string; ttlMs: number }, now?: number): ResourceRecord {
207
+ registerPodWorker(request: { workerId: string; machine: string; podUid: string; key: PodWorkerKey; owner: string; ttlMs: number }, now?: number): ResourceRecord {
207
208
  return this.mutate(() => {
209
+ if (typeof request.podUid !== 'string' || !request.podUid.trim()) throw new ResourceLedgerError(400, 'invalid-pod-worker-uid');
208
210
  now ??= Date.now();
209
211
  const rows = this.read();
210
212
  const id = `pod-worker-lease:${request.workerId}`;
211
213
  const index = rows.findIndex(row => row.id === id);
212
214
  const previous = index < 0 ? undefined : rows[index]!;
213
215
  if (previous && previous.kind !== 'pod-worker-lease') throw new ResourceLedgerError(409, 'worker-id-conflict');
214
- if (previous && previous.owner !== request.owner) throw new ResourceLedgerError(403, 'not-owner');
215
216
  // A workerId identifies one Pod instance. Expiry never proves that a leased or quarantined Pod was cleaned.
216
217
  if (previous) throw new ResourceLedgerError(409, 'worker-id-used');
217
218
  const generation = 0;
218
219
  const row: ResourceRecord = { id, kind: 'pod-worker-lease', machine: request.machine, name: request.workerId,
219
- owner: request.owner, attrs: { key: request.key, state: 'idle', generation, idleTtlMs: request.ttlMs }, observedAt: now, ttlMs: request.ttlMs };
220
+ owner: request.owner, attrs: { key: request.key, podUid: request.podUid, state: 'idle', generation, idleTtlMs: request.ttlMs }, observedAt: now, ttlMs: request.ttlMs };
220
221
  if (index < 0) rows.push(row); else rows[index] = row;
221
222
  this.write(rows);
222
223
  return row;
@@ -229,6 +230,7 @@ export class ResourceLedger {
229
230
  const rows = this.read();
230
231
  const index = rows.findIndex(row => row.kind === 'pod-worker-lease' && (!request.machine || row.machine === request.machine)
231
232
  && Math.max(0, at - row.observedAt) < row.ttlMs && workerAttrs(row).state === 'idle'
233
+ && typeof workerAttrs(row).podUid === 'string' && workerAttrs(row).podUid.trim().length > 0
232
234
  && sameWorkerKey(workerAttrs(row).key, request.key));
233
235
  if (index < 0) throw new ResourceLedgerError(409, 'no-warm-worker');
234
236
  const row = rows[index]!;
@@ -164,15 +164,16 @@ export function startControlServer(opts: ControlServerOptions = {}): {
164
164
  if (workerRegister) {
165
165
  if (!machine) throw new ResourceLedgerError(403, 'worker-host-required');
166
166
  const body = podWorkerBody(await req.json());
167
- const { workerId, machine: workerMachine, key, ttlMs } = body;
167
+ const { workerId, machine: workerMachine, podUid, key, ttlMs } = body;
168
168
  if (typeof workerId !== 'string' || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,95}$/.test(workerId)
169
169
  || typeof workerMachine !== 'string' || !workerMachine.trim()
170
+ || typeof podUid !== 'string' || !podUid.trim()
170
171
  || typeof ttlMs !== 'number' || !Number.isSafeInteger(ttlMs) || ttlMs <= 0 || ttlMs > MAX_POD_WORKER_TTL_MS) throw new ResourceLedgerError(400, 'invalid-pod-worker-lease');
171
172
  requireMachine(workerMachine);
172
173
  const stale = await currentWorkerPrimary();
173
174
  if (stale) return stale;
174
175
  return json(await ledger.withGuardedWorkerMutation(async () => !(await currentWorkerPrimary()),
175
- () => ledger.registerPodWorker({ workerId, machine: workerMachine, key: podWorkerKey(key), ttlMs, owner })));
176
+ () => ledger.registerPodWorker({ workerId, machine: workerMachine, podUid, key: podWorkerKey(key), ttlMs, owner })));
176
177
  }
177
178
  if (workerAcquire) {
178
179
  if (scope !== 'member') throw new ResourceLedgerError(403, 'worker-consumer-required');
@@ -244,7 +245,8 @@ export function startControlServer(opts: ControlServerOptions = {}): {
244
245
  name: url.searchParams.get('name') || undefined,
245
246
  });
246
247
  return json({ resources: rows.map(row => row.kind === 'pod-worker-lease'
247
- ? { ...row, attrs: { key: row.attrs.key, state: row.attrs.state, generation: row.attrs.generation } }
248
+ ? { ...row, attrs: { key: row.attrs.key, podUid: row.attrs.podUid,
249
+ state: row.attrs.state, generation: row.attrs.generation, idleTtlMs: row.attrs.idleTtlMs } }
248
250
  : row.kind === 'port-lease'
249
251
  ? { ...row, attrs: { ...row.attrs, leaseId: undefined } }
250
252
  : row) });
@@ -105,7 +105,11 @@ function classifyTuiChatIntentBase(text: string, ctx: ShortQuestionContext): Tui
105
105
  if (!q || ctx.hasAttachments) return coding(ctx.hasAttachments ? 'attachment' : 'empty');
106
106
  if (/(?:하니스|구현|코딩|버그|리팩터|커밋|패치|테스트|시험\s*돌|빌드|배포|\b(?:implement|coding|refactor|commit|patch|tests?|build|deploy)\b)/i.test(q)) return coding('coding');
107
107
  // Destructive or executing verbs in any form (not only «…줘») are never a quick turn.
108
- if (/(?:지워|지우|삭제|제거|옮겨|옮기|돌려|실행(?!\s*중(?:인)?(?:\s|[?!.~]|$))|설치|되돌려|롤백|재시작|죽여|\b(?:delete|remove|rm|rename|move|run|install|revert|rollback|drop|kill|restart)\b)/i.test(q)) return coding('write-verb');
108
+ // A no-tool answer can transcribe its first line. Keep the verb for file changes and
109
+ // remove only this copy phrase, so another write request in the same answer is still caught.
110
+ const answerOnly = /도구\s*쓰지\s*말고\s*답해\s*:/i.test(q);
111
+ const writeVerbInput = answerOnly ? q.replace(/첫\s*줄(?:을|를)?\s*그대로\s*옮기고/g, '') : q;
112
+ if (/(?:지워|지우|삭제|제거|옮겨|옮기|돌려|실행(?!\s*중(?:인)?(?:\s|[?!.~]|$))|설치|되돌려|롤백|재시작|죽여|\b(?:delete|remove|rm|rename|move|run|install|revert|rollback|drop|kill|restart)\b)/i.test(writeVerbInput)) return coding('write-verb');
109
113
  // Allowlist, not denylist: every «…줘» request verb must be one a quick turn can do; anything else
110
114
  // (지워줘 · 돌려줘 · 옮겨줘 …) keeps the coding goal loop.
111
115
  for (const match of q.matchAll(/([가-힣]+?)\s*(?:줘|주세요|줄래|주라)/g)) {
@@ -137,6 +137,8 @@ export interface DashboardAcpChatOpts {
137
137
  /** Logger for subprocess stderr / protocol events. Route into the
138
138
  * dashboard debug log (pushLog). */
139
139
  log?: (msg: string) => void;
140
+ /** Notify idle-sensitive dashboard services when an ACP turn starts or ends. */
141
+ onBusyChange?: () => void;
140
142
  /** Dependency injection hook for tests — overrides the default
141
143
  * `globalAcpAgentManager()` lookup. Production call sites omit
142
144
  * this field. */
@@ -180,6 +182,7 @@ export interface DashboardAcpChatOpts {
180
182
  export class DashboardAcpChat {
181
183
  private readonly getCwd: () => string;
182
184
  private readonly log: (msg: string) => void;
185
+ private readonly onBusyChange?: () => void;
183
186
  private readonly agentManager: NonNullable<DashboardAcpChatOpts['agentManager']>;
184
187
  private readonly sessionStore: NonNullable<DashboardAcpChatOpts['sessionStore']>;
185
188
  private readonly permissionApprover?: AcpPermissionApprover;
@@ -209,6 +212,7 @@ export class DashboardAcpChat {
209
212
  this.getCwd = () => getSessionCwd();
210
213
  }
211
214
  this.log = opts.log ?? ((_m) => { /* default: drop */ });
215
+ this.onBusyChange = opts.onBusyChange;
212
216
  this.agentManager = opts.agentManager ?? {
213
217
  getAgent: (backendId, o) => globalAcpAgentManager().getAgent(backendId, o) as any,
214
218
  };
@@ -321,6 +325,7 @@ export class DashboardAcpChat {
321
325
  throw new Error(`${displayBackendName(backendId)} already has a turn in flight — /acp cancel first`);
322
326
  }
323
327
  sess.inFlight = true;
328
+ this.onBusyChange?.();
324
329
  if (debug.enabled) {
325
330
  handlers.pushLine(` → sending to ${displayBackendName(backendId)}…`);
326
331
  }
@@ -359,11 +364,14 @@ export class DashboardAcpChat {
359
364
  }
360
365
  this.closeStreamBuffer(sess, 'flush');
361
366
  sess.inFlight = false;
367
+ this.onBusyChange?.();
362
368
  handlers.onDone(result.stopReason);
363
369
  } catch (err) {
364
370
  if (sess) {
365
371
  this.closeStreamBuffer(sess, 'flush');
372
+ const wasBusy = sess.inFlight;
366
373
  sess.inFlight = false;
374
+ if (wasBusy) this.onBusyChange?.();
367
375
  }
368
376
  handlers.onError(err instanceof Error ? err : new Error(formatAcpError(err)));
369
377
  }