elanous 0.2.34 → 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 (611) 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/{L04y73dlwKeTW-GetaTF3 → T1mBQqmkwKDLGtyisDCOd}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{5014f970-22bef0b5210f7d60.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/{2124.ed5bf480cea7f85b.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/1674.2a65fd5668e1cc5f.js +1 -0
  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/1993-c0007b7ad0c0ef41.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1c735de4.f993a30bbd3c57c4.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{8368.014caa8de2f5af34.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/2625.5d870aa999f33db1.js +34 -0
  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/{1644.35dd25240ae24e4b.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/{3121.779fafe3e44612c5.js → 3589.5444a06bcf6e775c.js} +1 -1
  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/{9131-fce7256c4180c4a5.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/4346.8601952e73bf5803.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/{6053-d893974de92e6198.js → 4441-875b97f5821ed58a.js} +1 -1
  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/{1895-60ed0e341c658bd4.js → 4705-194e64e47ca0fbdb.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/{5576-82d3703636d5c4b9.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/{7431.3051e9b8a4372d2d.js → 5101.e32282718f99ed6f.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/5154.a118f3957ed14e36.js +1 -0
  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/{2987-30cf9c2eb7b8bdd5.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/56d372f2.681ab4ec4c998fae.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/{7386.5d8e7e42e818dfb6.js → 5852.db1f7449f4f74612.js} +2 -2
  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/{3110.0a7065f25c841818.js → 6236.e18cced2d5ba6afb.js} +3 -3
  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/6b89c8bd.24df687a820500b3.js +1 -0
  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/{7005.1623d2aea78eb85f.js → 7385.50a308a477bdfc21.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/{6086.913a69e6fa3e4a8b.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/8219.baa715d1deee80e2.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8256.e3ac8421a71f82f4.js +1 -0
  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/{7193-cf355cca5ba6c5d5.js → 8437-8d5492094b166cfa.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/{2554.3b5e200f5f5cfcd6.js → 8444.4c26b379ca2b9596.js} +4 -4
  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/{2547.dd27303624cb4da8.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/{9550.d5f76828f972058c.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/{8548.036c344973968847.js → 938.66ad1ef0e5abae1c.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{3414.172ad4ca2d9b08e8.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/967-2aa39b2d04b4c690.js +1 -0
  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/{6740.43de73fc427c9fe2.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-406b47745b53f269.js +1 -0
  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-d7bff0f0905a662c.js → page-26e6c18a1a750cf6.js} +1 -1
  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-47c5d4db587266bd.js +1 -0
  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-df3445b207ceceab.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/{9a8cb466.cc9fc9e6e46038aa.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/{4fa33ebd.21c1bd5b294496e6.js → cbe38a15.5a032598e39970c6.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{abb4b98b.163e0f56e84ae35d.js → d06f9160.a3d9062f95de8ad7.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{9b48c871.204d5d13e7809bd0.js → da5176c6.6773b6c5994e1d99.js} +1 -1
  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 +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/README.md +4 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/default-loop.yaml +57 -3
  285. package/graphs/document-loop.yaml +51 -3
  286. package/graphs/implement-loop.yaml +53 -4
  287. package/graphs/journey/ta-journey.yaml +11 -1
  288. package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
  289. package/graphs/journey/units/author-dialogue/observe.ts +96 -0
  290. package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
  291. package/graphs/operate-loop.yaml +51 -3
  292. package/graphs/research-loop.yaml +137 -3
  293. package/graphs/test-diet/test-diet.yaml +3 -0
  294. package/package.json +1 -1
  295. package/scripts/coord-role-pack.ts +19 -6
  296. package/scripts/hq/standby-snapshot.ts +17 -12
  297. package/scripts/release-loop/docs-land-node.ts +21 -5
  298. package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
  299. package/scripts/release-loop/gate-node.ts +181 -22
  300. package/scripts/release-loop/gate-partial.ts +65 -11
  301. package/scripts/release-loop/gate-radius-live.ts +177 -0
  302. package/scripts/release-loop/gate-radius-shadow.ts +1 -1
  303. package/scripts/release-loop/node-verdict.ts +12 -1
  304. package/scripts/release-loop/npm-publish-node.ts +66 -12
  305. package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
  306. package/scripts/release-loop/pwa-remote.ts +166 -0
  307. package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
  308. package/scripts/release-loop/resume-release.ts +41 -4
  309. package/scripts/release-loop/unattended-release.ts +2 -0
  310. package/scripts/test-diet/lib.ts +6 -1
  311. package/scripts/test-diet/node.ts +194 -13
  312. package/scripts/ux-sim.ts +39 -0
  313. package/src/agent/self-ambient-cache.ts +8 -0
  314. package/src/agent-substrate/acp-reviewer.ts +39 -4
  315. package/src/agent-substrate/pr-reviewer.ts +17 -0
  316. package/src/agent-substrate/self-review-cli.ts +62 -13
  317. package/src/autopilot/pr-manager.ts +215 -36
  318. package/src/budget/run-usage-rollup.ts +1 -0
  319. package/src/chat/index.ts +0 -2
  320. package/src/chat/pickers/modal-runtime.ts +10 -27
  321. package/src/cli/agent-cli.ts +13 -2
  322. package/src/cli/doctor-cli.ts +4 -1
  323. package/src/cli/light-entry-route.ts +46 -6
  324. package/src/cli/pod-cli.ts +77 -3
  325. package/src/cli/pr-cli.ts +5 -2
  326. package/src/cli/pr-land-pod-shadow-job.ts +3 -0
  327. package/src/cli/release-checklist-read-cli.ts +79 -0
  328. package/src/cli/release-cli.ts +72 -102
  329. package/src/cli/remote-resolve.ts +1 -1
  330. package/src/cli/root-tui-entry.ts +48 -0
  331. package/src/cli/sim-cli.ts +22 -0
  332. package/src/cli/tasks-cli.ts +540 -31
  333. package/src/cli/usage-cli.ts +13 -11
  334. package/src/clipboard/history.ts +179 -13
  335. package/src/config.ts +8 -1
  336. package/src/dashboard/chat/acp-chat.ts +8 -0
  337. package/src/dashboard/index.ts +78 -10
  338. package/src/dashboard/render/theme-resolver.ts +33 -4
  339. package/src/domains/schedule-registry.ts +16 -2
  340. package/src/git-fs/idle-refresh.ts +76 -0
  341. package/src/git-fs/index.ts +18 -7
  342. package/src/git-fs/worktree.ts +42 -4
  343. package/src/graph-kinds/registry.ts +2 -2
  344. package/src/graph-runner/runner.ts +153 -10
  345. package/src/grok/credential.ts +10 -3
  346. package/src/harness/harness-cli-command.ts +112 -28
  347. package/src/harness/harness-incidents.ts +33 -0
  348. package/src/harness/launch-utterance-ledger.ts +208 -0
  349. package/src/impl-discipline/detector.ts +16 -4
  350. package/src/impl-discipline/system-prompt.ts +11 -0
  351. package/src/impl-discipline/types.ts +2 -2
  352. package/src/index.ts +496 -143
  353. package/src/intake-plane/already-built-hint.ts +4 -2
  354. package/src/intake-plane/requirement-funnel.ts +29 -1
  355. package/src/light-cli.ts +27 -11
  356. package/src/llm/opengateway-models.ts +11 -0
  357. package/src/llm/provider-credentials.ts +14 -0
  358. package/src/llm/provider-detect.ts +8 -1
  359. package/src/llm/runtime-model-family.ts +2 -1
  360. package/src/llm.ts +213 -56
  361. package/src/model-tier/llm-tier-map.ts +15 -1
  362. package/src/native-tool-catalog.ts +15 -1
  363. package/src/nexus/api/loop-resources.ts +13 -1
  364. package/src/oauth/codex.ts +7 -0
  365. package/src/ops/overview-collect.ts +18 -3
  366. package/src/ops/overview.ts +20 -7
  367. package/src/pr-tool/census.ts +261 -27
  368. package/src/pty-shell/pty-manifest.ts +7 -0
  369. package/src/release-loop/checklist.ts +24 -0
  370. package/src/release-loop/landed-but-yellow.ts +129 -5
  371. package/src/release-loop/light-rc.ts +1 -0
  372. package/src/release-loop/rehearsal.ts +2 -2
  373. package/src/repl/index.ts +174 -17
  374. package/src/repl/ops-msg-bridge.ts +32 -0
  375. package/src/self-dev/ask-launch-flow.ts +44 -5
  376. package/src/self-dev/cli-help-text.ts +17 -0
  377. package/src/self-dev/dev-cli.ts +11 -9
  378. package/src/self-dev/draft-residue.ts +37 -1
  379. package/src/self-dev/draft-sweep.ts +137 -11
  380. package/src/self-dev/draft-triage-rules.ts +107 -0
  381. package/src/self-dev/fleet-reduce.ts +3 -2
  382. package/src/self-dev/graph-front-nodes.ts +112 -0
  383. package/src/self-dev/graph-journey-nodes.ts +1 -0
  384. package/src/self-dev/harness-run-cli.ts +3 -15
  385. package/src/self-dev/orchestrate-cli-text.ts +10 -0
  386. package/src/self-dev/review-provider-fallback.ts +35 -1
  387. package/src/self-dev/self-orchestrate-runtime.ts +1 -11
  388. package/src/self-dev/shard-aggregate.ts +42 -5
  389. package/src/self-dev/shard-run.ts +8 -1
  390. package/src/self-implement/blocked-draft-policy.ts +20 -0
  391. package/src/self-implement/classify-shadow.ts +3 -7
  392. package/src/self-implement/doctor-visit.ts +18 -1
  393. package/src/self-implement/gate-baseline.ts +56 -17
  394. package/src/self-implement/gate-cli.ts +1 -0
  395. package/src/self-implement/gate-remote.ts +31 -20
  396. package/src/self-implement/goal-author-decompose.ts +275 -47
  397. package/src/self-implement/goal-author.ts +250 -0
  398. package/src/self-implement/goal-elaborate.ts +295 -0
  399. package/src/self-implement/goal-refine.ts +270 -0
  400. package/src/self-implement/graph-overlay-yaml.ts +14 -3
  401. package/src/self-implement/orchestrator.ts +152 -45
  402. package/src/self-implement/rework-budget-judgment.ts +5 -8
  403. package/src/self-implement/run-stop.ts +10 -1
  404. package/src/self-implement/running-runs.ts +29 -1
  405. package/src/self-implement/scope-adjacency.ts +113 -0
  406. package/src/self-implement/seams.ts +127 -24
  407. package/src/self-implement/stop-autoheal.ts +87 -1
  408. package/src/session-runtime/index.ts +1 -1
  409. package/src/setup/llm-env-detect.ts +5 -0
  410. package/src/skills/tools/agent.ts +140 -14
  411. package/src/skills/tools/msg-ask.ts +100 -0
  412. package/src/skills/tools/ops-ledger.ts +2 -1
  413. package/src/steward/hold-hygiene.ts +24 -6
  414. package/src/steward/triage-budget.ts +194 -0
  415. package/src/steward/triage.ts +20 -3
  416. package/src/task-agent/actions.ts +69 -1
  417. package/src/task-agent/green-sweep.ts +4 -0
  418. package/src/task-agent/live-moves.ts +160 -4
  419. package/src/task-agent/parent-host.ts +123 -3
  420. package/src/task-agent/shadow.ts +7 -1
  421. package/src/task-agent/task-hand.ts +54 -41
  422. package/src/task-agent/tier-split.ts +127 -0
  423. package/src/task-agent/work-order-build.ts +2 -0
  424. package/src/task-agent/work-order.ts +3 -2
  425. package/src/task-orchestrator/generator-prompt.ts +60 -11
  426. package/src/task-orchestrator/surfaces/pod-account-broker.ts +33 -0
  427. package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
  428. package/src/task-orchestrator/surfaces/pod-command-job.ts +45 -7
  429. package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
  430. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
  431. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +8 -2
  432. package/src/task-orchestrator/surfaces/pod-provenance.ts +76 -0
  433. package/src/task-orchestrator/surfaces/pod-source-receive.ts +18 -0
  434. package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
  435. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +6 -2
  436. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +3 -0
  437. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +37 -5
  438. package/src/task-orchestrator/surfaces/self-implement-pod.ts +368 -36
  439. package/src/task-orchestrator/surfaces/self-implement.ts +23 -0
  440. package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
  441. package/src/tui/README.md +2 -0
  442. package/src/tui/chat/background-job-status.ts +54 -0
  443. package/src/tui/chat/log-view.ts +80 -0
  444. package/src/tui/entry.ts +406 -0
  445. package/src/tui/input/composer.ts +144 -0
  446. package/src/tui/seat-mail-boot.ts +59 -0
  447. package/src/tui/slash/compact.ts +100 -0
  448. package/src/tui/slash/new-session.ts +35 -0
  449. package/src/tui-client/local-chat-turn.ts +239 -0
  450. package/src/tui-client/local-harness-command.ts +63 -0
  451. package/src/tui-client/local-provider-command.ts +184 -0
  452. package/src/user-config.ts +4 -2
  453. package/src/ux-sim/event-monkey.ts +378 -0
  454. package/src/ux-sim/fake-bin.ts +42 -7
  455. package/src/ux-sim/fault-nextmove-dispatch.ts +266 -0
  456. package/src/ux-sim/fault-pod-codex-503.ts +211 -0
  457. package/src/ux-sim/fault-scope-escape-lift.ts +189 -0
  458. package/src/version/packed-revision.json +1 -1
  459. package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +0 -79
  460. package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +0 -1
  461. package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +0 -94
  463. package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +0 -23
  465. package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +0 -1
  466. package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +0 -115
  467. package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +0 -8
  468. package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/3001-5a52788c813b6113.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +0 -1
  477. package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +0 -34
  479. package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +0 -1
  482. package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/3498.cf2a15a8a9e5b926.js +0 -226
  485. package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +0 -32
  487. package/apps/pwa/out/_next/static/chunks/3837.722e053fb9f321ad.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +0 -104
  490. package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +0 -286
  491. package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +0 -149
  492. package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +0 -148
  493. package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +0 -64
  494. package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +0 -74
  497. package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/5028-f0722e6114c313e7.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/5249.96a848656b582a93.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +0 -62
  504. package/apps/pwa/out/_next/static/chunks/5446.edf141cff9ef647d.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/5489.ec2dd1b5272a19dc.js +0 -24
  506. package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +0 -77
  517. package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +0 -90
  520. package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/7448.478958ffbbba0ac0.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +0 -41
  527. package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +0 -27
  530. package/apps/pwa/out/_next/static/chunks/7952.b192c31b6a0e00cc.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +0 -36
  533. package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +0 -93
  547. package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +0 -24
  549. package/apps/pwa/out/_next/static/chunks/9739.8d5f36ac67a3b236.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-398c0faa173203f7.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +0 -122
  603. package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/ffdc3a04.b9c23c1b28dd4a96.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +0 -1
  611. /package/apps/pwa/out/_next/static/{L04y73dlwKeTW-GetaTF3 → T1mBQqmkwKDLGtyisDCOd}/_ssgManifest.js +0 -0
@@ -60,8 +60,8 @@ export const AGENT_TOOL_DEFAULT_MAX_TURNS = 20;
60
60
  export const AGENT_TOOL_TURNS_CEILING = 50;
61
61
 
62
62
  /** Numeric ceiling on concurrent `run_in_background` Agent-tool fan-out.
63
- * Pure declaration — enforcement in dispatchAgent is the follow-up cell
64
- * TUI-AGENT-CAPS-WIRING (not wired here). */
63
+ * Enforced at exactly one point in `dispatchAgent` (see the
64
+ * `background-fanout-limit` block: after dedup, before `noteSeen`). */
65
65
  export const AGENT_TOOL_BACKGROUND_FANOUT_CEILING = 8;
66
66
 
67
67
  /** Clamp a caller-supplied `max_turns` onto `[1, AGENT_TOOL_TURNS_CEILING]`.
@@ -82,7 +82,9 @@ export function stripAgentToolForOneLevelNesting<T extends { name: string }>(
82
82
  }
83
83
 
84
84
  /** Live `run_in_background` tasks occupy fan-out slots until they terminal.
85
- * Pure judgement — the ceiling check that uses it is TUI-AGENT-CAPS-WIRING. */
85
+ * Counts a task list (e.g. `globalAgentRegistry.list()`). `dispatchAgent`
86
+ * enforces the per-session ceiling over its own reservation ledger
87
+ * (`backgroundFanoutSlots`) instead — see that field's doc. */
86
88
  export function countLiveBackgroundFanout(
87
89
  tasks: ReadonlyArray<{ background?: boolean; state?: string }>,
88
90
  ): number {
@@ -95,6 +97,35 @@ export function countLiveBackgroundFanout(
95
97
  return n;
96
98
  }
97
99
 
100
+ /** Fallback fan-out session key for dispatches that carry no
101
+ * `sessionCache` (agent-cli, one-off callers). All of their slots share
102
+ * one process-wide bucket so the ceiling still binds for them. */
103
+ const UNSCOPED_BACKGROUND_FANOUT_SESSION: object = Object.freeze({});
104
+
105
+ /** Fan-out slots by session (the dispatching session's `SessionCache`
106
+ * identity; WeakMap so a dropped session releases its key together with
107
+ * the cache instance). A slot is RESERVED in the same synchronous block
108
+ * as the ceiling check inside `dispatchAgent` — concurrent dispatches
109
+ * that interleave at the async definition-resolution awaits cannot all
110
+ * pass the check before any of them registers — and RELEASED when the
111
+ * registered task reaches a terminal state (done/error/aborted) via
112
+ * `globalAgentRegistry.onTaskDone`. A dispatch that throws before it
113
+ * registers releases its own reservation (see
114
+ * `releaseReservedFanoutSlot` inside `dispatchAgent`). */
115
+ const backgroundFanoutSlots = new WeakMap<object, number>();
116
+
117
+ /** Count this session's live fan-out slots (reserved or running). */
118
+ export function countSessionBackgroundFanout(session: object): number {
119
+ return backgroundFanoutSlots.get(session) ?? 0;
120
+ }
121
+
122
+ /** Release one of this session's fan-out slots (floors at zero). */
123
+ function releaseBackgroundFanoutSlot(session: object): void {
124
+ const live = backgroundFanoutSlots.get(session);
125
+ if (live === undefined || live <= 1) backgroundFanoutSlots.delete(session);
126
+ else backgroundFanoutSlots.set(session, live - 1);
127
+ }
128
+
98
129
  /** Fallback agent when subagent_type is missing or unresolvable. The
99
130
  * loader picks this up from src/agents/general-purpose.md — built
100
131
  * inline below as a defensive default in case that file is removed. */
@@ -374,19 +405,22 @@ export async function dispatchAgent(
374
405
  // burn another turn on the same work. Return a stub that points
375
406
  // the parent back to its existing history. Parents stuck in a
376
407
  // "keep re-spawning Data Collector" loop escape via this gate.
377
- if (opts.sessionCache) {
378
- const key = agentCacheKey(requestedType, requestedType, prompt);
408
+ const sessionCache = opts.sessionCache;
409
+ const cacheKey = sessionCache
410
+ ? agentCacheKey(requestedType, requestedType, prompt)
411
+ : undefined;
412
+ if (sessionCache && cacheKey) {
379
413
  // Key strategy: description is noisy (parents sometimes vary the
380
414
  // label between calls); we hash the FUNCTIONAL signature only
381
415
  // — subagent_type + prompt. Same prompt to same agent = same
382
416
  // expected work, regardless of how the call was labelled.
383
- const hit = opts.sessionCache.check(key);
417
+ const hit = sessionCache.check(cacheKey);
384
418
  if (hit) {
385
419
  const label = `Agent[${requestedType}] "${description.slice(0, 60)}"`;
386
420
  logDedupHit('agent.dedup', label, hit, {
387
421
  requestedType,
388
422
  description: description.slice(0, 80),
389
- consecutive: opts.sessionCache.consecutiveHits,
423
+ consecutive: sessionCache.consecutiveHits,
390
424
  });
391
425
 
392
426
  // Runtime-level block: same treatment as Read. When the parent
@@ -395,16 +429,16 @@ export async function dispatchAgent(
395
429
  // tool_result carries is_error=true. Soft stubs have been
396
430
  // observed to produce 6+ retries in the wild; an error break
397
431
  // the reflex loop more reliably.
398
- if (opts.sessionCache.consecutiveHits >= CONSECUTIVE_DEDUP_BLOCK_THRESHOLD) {
432
+ if (sessionCache.consecutiveHits >= CONSECUTIVE_DEDUP_BLOCK_THRESHOLD) {
399
433
  debug.log('agent.dedup', 'consecutive-block', {
400
434
  requestedType,
401
435
  description: description.slice(0, 80),
402
- consecutive: opts.sessionCache.consecutiveHits,
436
+ consecutive: sessionCache.consecutiveHits,
403
437
  threshold: CONSECUTIVE_DEDUP_BLOCK_THRESHOLD,
404
438
  });
405
439
  throw new Error(
406
440
  `RUNTIME BLOCKED — Agent[${requestedType}] "${description.slice(0, 60)}" ` +
407
- `has been spawned ${opts.sessionCache.consecutiveHits} times in a row with ` +
441
+ `has been spawned ${sessionCache.consecutiveHits} times in a row with ` +
408
442
  `no intervening progress. The previous sub-agent's final message is in ` +
409
443
  `your conversation history above — use that. Spawn an Agent with a ` +
410
444
  `DIFFERENT persona (different subagent_type or a substantively different ` +
@@ -420,9 +454,9 @@ export async function dispatchAgent(
420
454
  // ~500 chars of history noise per hit. We now emit the debug
421
455
  // event past threshold for traceability but return the normal
422
456
  // "spawn a different persona" stub — same message every hit.
423
- if (opts.sessionCache.totalHits >= DEDUP_CASCADE_HALT_THRESHOLD) {
457
+ if (sessionCache.totalHits >= DEDUP_CASCADE_HALT_THRESHOLD) {
424
458
  debug.log('agent.dedup', 'cascade-threshold', {
425
- totalHits: opts.sessionCache.totalHits,
459
+ totalHits: sessionCache.totalHits,
426
460
  threshold: DEDUP_CASCADE_HALT_THRESHOLD,
427
461
  requestedType,
428
462
  description: description.slice(0, 80),
@@ -444,7 +478,79 @@ export async function dispatchAgent(
444
478
  taskId: 'dedup',
445
479
  };
446
480
  }
447
- opts.sessionCache.noteSeen(key, `Agent[${requestedType}] ${description.slice(0, 60)}`);
481
+ }
482
+
483
+ // ── TUI-AGENT-CAPS-FU: background fan-out ceiling ──
484
+ //
485
+ // The ONE enforcement point for AGENT_TOOL_BACKGROUND_FANOUT_CEILING, and
486
+ // it sits exactly between the dedup short-circuit above and `noteSeen`
487
+ // below on purpose:
488
+ // • after dedup — a repeat of an already-answered prompt still gets the
489
+ // dedup stub instead of a fan-out refusal (it never reaches here);
490
+ // • before `noteSeen` — a refused launch must NOT register its cache
491
+ // key. Otherwise the caller's retry (same prompt, once a slot opens)
492
+ // would be answered with "you already got this result" even though no
493
+ // child ever ran, permanently poisoning the cache with a spawn that
494
+ // never happened.
495
+ //
496
+ // Live slots are counted over the shared task ledger: `background` tasks
497
+ // that have not reached a terminal state (done / error / aborted). So a
498
+ // slot re-opens the moment any background agent finishes, which is what
499
+ // lets the next launch through again.
500
+ let fanoutSession: object | undefined;
501
+ if (runInBackground) {
502
+ // Per-session scope: slots count against THIS session's cache
503
+ // identity (shared fallback bucket for cache-less callers), so a
504
+ // busy OTHER session cannot starve this one's first launch.
505
+ fanoutSession = opts.sessionCache ?? UNSCOPED_BACKGROUND_FANOUT_SESSION;
506
+ const liveBackground = countSessionBackgroundFanout(fanoutSession);
507
+ if (liveBackground >= AGENT_TOOL_BACKGROUND_FANOUT_CEILING) {
508
+ debug.log('agent.spawn', 'background-fanout-limit', {
509
+ cid: debugCorrelationId,
510
+ requestedType,
511
+ description: description.slice(0, 80),
512
+ liveBackground,
513
+ ceiling: AGENT_TOOL_BACKGROUND_FANOUT_CEILING,
514
+ }, { level: 'warn' });
515
+ // Not spawned: no registry task, no provider call, no cache entry.
516
+ // taskId is a sentinel (like 'dedup' above) so a caller can tell a
517
+ // refusal from a real spawn without parsing the prose.
518
+ return {
519
+ output:
520
+ `NOT SPAWNED — ${liveBackground} background agents are already live and the ` +
521
+ `fan-out ceiling is ${AGENT_TOOL_BACKGROUND_FANOUT_CEILING}. A slot reopens as ` +
522
+ `soon as one of them reaches a terminal state (done/error/aborted); its result ` +
523
+ `then arrives as a task-notification. Either wait for one to finish, fold this ` +
524
+ `work into an existing background spawn, or re-issue it without ` +
525
+ `run_in_background so it runs in the foreground.`,
526
+ agent: requestedType,
527
+ cid: debugCorrelationId,
528
+ durationMs: 0,
529
+ maxTurns: requestedMaxTurns,
530
+ taskId: 'background-fanout-limit',
531
+ };
532
+ }
533
+ }
534
+
535
+ if (fanoutSession !== undefined) {
536
+ // Atomic reservation: taken in the SAME synchronous block as the
537
+ // ceiling check above, before any await — concurrent dispatches
538
+ // cannot all pass the check and push this session past the ceiling
539
+ // while their definitions resolve. Released when the registered
540
+ // task terminals (see the onTaskDone subscription at spawn); a
541
+ // dispatch that throws before registering releases it in the finally
542
+ // below, including failures from definition resolution and lazy imports.
543
+ backgroundFanoutSlots.set(fanoutSession, countSessionBackgroundFanout(fanoutSession) + 1);
544
+ }
545
+ const releaseReservedFanoutSlot = (): void => {
546
+ if (fanoutSession === undefined) return;
547
+ releaseBackgroundFanoutSlot(fanoutSession);
548
+ fanoutSession = undefined;
549
+ };
550
+
551
+ try {
552
+ if (sessionCache && cacheKey) {
553
+ sessionCache.noteSeen(cacheKey, `Agent[${requestedType}] ${description.slice(0, 60)}`);
448
554
  }
449
555
 
450
556
  // Resolve the agent definition. Try the 4-layer resolver first;
@@ -536,7 +642,9 @@ export async function dispatchAgent(
536
642
  });
537
643
  } catch (error) {
538
644
  const message = error instanceof Error ? error.message : String(error);
539
- if (!message.includes('is not inside a git repo')) throw error;
645
+ if (!message.includes('is not inside a git repo')) {
646
+ throw error;
647
+ }
540
648
  childCwd = opts.cwd ?? getSessionCwd();
541
649
  appliedIsolation = 'cwd';
542
650
  debug.log('agent.spawn', 'worktree-fallback-cwd', {
@@ -679,6 +787,19 @@ export async function dispatchAgent(
679
787
  ...(runInBackground ? { background: true } : {}),
680
788
  });
681
789
 
790
+ // Terminal release for this dispatch's reserved fan-out slot: the
791
+ // registry fires this exactly once per task when it reaches a
792
+ // terminal state (done/error/aborted); until then the slot counts as
793
+ // occupied against this session's ceiling above.
794
+ if (fanoutSession !== undefined) {
795
+ const fanoutSlotSession = fanoutSession;
796
+ const fanoutSlotSubscription = globalAgentRegistry.onTaskDone((task) => {
797
+ if (!task || task.id !== handle.task.id) return;
798
+ fanoutSlotSubscription.dispose();
799
+ releaseBackgroundFanoutSlot(fanoutSlotSession);
800
+ });
801
+ fanoutSession = undefined; // the terminal subscription owns the release now
802
+ }
682
803
  // Forward parent abort to the spawned task. The registry owns the
683
804
  // child's controller; we just chain ours into it.
684
805
  if (opts.signal) {
@@ -907,4 +1028,9 @@ export async function dispatchAgent(
907
1028
  ...(childCwd ? { cwd: childCwd } : {}),
908
1029
  ...(appliedIsolation ? { isolation: appliedIsolation } : {}),
909
1030
  };
1031
+ } finally {
1032
+ // The registered task owns its slot after the handoff above. Every
1033
+ // pre-registration throw leaves fanoutSession set and releases it here.
1034
+ releaseReservedFanoutSlot();
1035
+ }
910
1036
  }
@@ -0,0 +1,100 @@
1
+ import type { LLMToolSpec } from '../../llm.js';
2
+ import { openMsgStore, validateMessageEnvelope, type Message, type MsgStore } from '../../msg/msg-store.js';
3
+
4
+ export interface MsgAskDeps {
5
+ openStore?: () => MsgStore;
6
+ sleep?: (ms: number) => Promise<void>;
7
+ monotonicNow?: () => number;
8
+ wallNow?: () => number;
9
+ signal?: AbortSignal;
10
+ }
11
+
12
+ export interface MsgAskResult extends Record<string, unknown> {
13
+ output: string;
14
+ ok: boolean;
15
+ question: Message;
16
+ reply: Message | null;
17
+ }
18
+
19
+ export function buildMsgAskTool(): LLMToolSpec {
20
+ return {
21
+ name: 'MsgAsk',
22
+ description: 'Post a durable seat question, then wait for the first message whose replyTo points to it. A timeout or cancellation keeps the posted question and returns its ID for later follow-up.',
23
+ parameters: {
24
+ type: 'object',
25
+ properties: {
26
+ from: { type: 'string', description: 'Asking seat (ALL cannot send).' },
27
+ to: { type: 'string', description: 'Recipient seat.' },
28
+ question: { type: 'string', description: 'Nonempty question body.' },
29
+ waitSeconds: { type: 'integer', description: 'Wait 0–300 seconds; default 60.' },
30
+ },
31
+ required: ['from', 'to', 'question'],
32
+ additionalProperties: false,
33
+ },
34
+ };
35
+ }
36
+
37
+ export async function dispatchMsgAsk(rawArgs: Record<string, unknown>, deps: MsgAskDeps = {}): Promise<MsgAskResult> {
38
+ const waitRaw = rawArgs.waitSeconds ?? 60;
39
+ if (typeof waitRaw !== 'number' || !Number.isSafeInteger(waitRaw) || waitRaw < 0 || waitRaw > 300) {
40
+ throw new Error("'waitSeconds' must be an integer between 0 and 300");
41
+ }
42
+ const envelope = validateMessageEnvelope({
43
+ from: rawArgs.from,
44
+ to: rawArgs.to,
45
+ body: rawArgs.question,
46
+ });
47
+ if (envelope.to === 'ALL') throw new Error("'to' must name one recipient seat for MsgAsk");
48
+ const monotonicNow = deps.monotonicNow ?? (() => performance.now());
49
+ const wallNow = deps.wallNow ?? Date.now;
50
+ const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
51
+ const store = deps.openStore?.() ?? openMsgStore();
52
+ try {
53
+ if (deps.signal?.aborted) throw new Error('ask cancelled before posting');
54
+ const question = store.post(envelope);
55
+ const startedAt = monotonicNow();
56
+ const wallStartedAt = wallNow();
57
+ const deadline = startedAt + waitRaw * 1000;
58
+ const wallDeadline = Date.parse(question.createdAt) + waitRaw * 1000;
59
+ // Ledger timestamps are wall time while the wait budget is monotonic.
60
+ // If the two clocks diverge materially, preserve the question ID and
61
+ // make the uncertain result explicit instead of accepting a late reply.
62
+ const clockAdjusted = () => Math.abs((wallNow() - wallStartedAt) - (monotonicNow() - startedAt)) > 250;
63
+ let afterId = 0;
64
+ do {
65
+ if (deps.signal?.aborted) {
66
+ return { output: `MsgAsk #${question.id} posted; wait cancelled`, ok: false, question, reply: null };
67
+ }
68
+ if (clockAdjusted()) {
69
+ return { output: `MsgAsk #${question.id} posted; clock adjusted during wait, inspect linked replies`, ok: false, question, reply: null };
70
+ }
71
+ const replies = store.listReplies(question.id, 1000, afterId);
72
+ if (clockAdjusted()) {
73
+ return { output: `MsgAsk #${question.id} posted; clock adjusted during wait, inspect linked replies`, ok: false, question, reply: null };
74
+ }
75
+ for (const reply of replies) {
76
+ afterId = reply.id;
77
+ // A replyTo link alone does not prove the intended seat answered.
78
+ // A wall-clock timestamp can move backwards by less than the clock
79
+ // adjustment guard. Never accept a reply once monotonic time expired.
80
+ // This conservatively leaves replies observed late for follow-up.
81
+ if (reply.from === question.to && reply.to === question.from
82
+ && monotonicNow() <= deadline && Date.parse(reply.createdAt) <= wallDeadline) {
83
+ return { output: `MsgAsk #${question.id} → reply #${reply.id}: ${reply.body}`, ok: true, question, reply };
84
+ }
85
+ }
86
+ const remaining = deadline - monotonicNow();
87
+ if (deps.signal?.aborted) {
88
+ return { output: `MsgAsk #${question.id} posted; wait cancelled`, ok: false, question, reply: null };
89
+ }
90
+ if (remaining <= 0) {
91
+ return { output: `MsgAsk #${question.id} posted; no linked reply within ${waitRaw}s`, ok: false, question, reply: null };
92
+ }
93
+ // A full page may repeat forever. Yield so timers and AbortSignal
94
+ // callbacks can run before asking SQLite for the next page.
95
+ await sleep(replies.length === 1000 ? 0 : Math.min(100, remaining));
96
+ } while (true);
97
+ } finally {
98
+ store.close();
99
+ }
100
+ }
@@ -3,7 +3,7 @@
3
3
  // OP TUI turns previously drove `elanous msg list/post/ack` and
4
4
  // `elanous release checklist list/move/set/add` through RunShell:
5
5
  // 1.3–2s of CLI startup per call, 30+ spawns per turn, and the CLI's
6
- // human-oriented stdout amplifying TUI screen defects. These eight
6
+ // human-oriented stdout amplifying TUI screen defects. These
7
7
  // tools reuse the SAME durable services in-process —
8
8
  //
9
9
  // • msg tools → src/msg/msg-store.ts (the SQLite ledger `elanous msg`
@@ -11,6 +11,7 @@
11
11
  // • checklist tools → src/release-loop/checklist.ts + feature-store.ts
12
12
  // (the same per-version ledger, claim history, seat/OP move rules)
13
13
  //
14
+ // MsgAsk joins this family through msg-ask.ts; the other dispatchers live here.
14
15
  // The permission and audit contract is preserved 1:1:
15
16
  // • writes record the actor from ELANOUS_TRACK (seat identity),
16
17
  // • ChecklistMove keeps the CLI routing — anonymous (no ELANOUS_TRACK)
@@ -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
  }
@@ -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));