elanous 0.2.28 → 0.2.29

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 (609) 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/{y1ltt7oCZxVpC6zVPhZ2O → cIpv5nU9AycwYWZI9H589}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{ab4d57c2.e90bc2cb31949045.js → 058a98ba.7eb28d5e6dc03565.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{4565-67e4c620597965c8.js → 1015-9cba22a5a4554797.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +8 -0
  9. package/apps/pwa/out/_next/static/chunks/{1516.83dd2c1b86b4e507.js → 1142.65d002789ab3af7d.js} +2 -2
  10. package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +34 -0
  12. package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1516.dfaceff3fd2d0e0d.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +286 -0
  16. package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +24 -0
  17. package/apps/pwa/out/_next/static/chunks/1782-59db1b5aa06df38a.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{1743.563d3168e95825ef.js → 1852.7f7b53991fcb99ef.js} +2 -2
  19. package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +36 -0
  22. package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +64 -0
  24. package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{65ebff95.081daeff622d238e.js → 285adb1a.5654e605dddf86d2.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +115 -0
  31. package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3160-95c96f4d2a21dd26.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +90 -0
  36. package/apps/pwa/out/_next/static/chunks/328bb3ab-6628a1114fe3fb3b.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{9917-9e26abc5f7772735.js → 3396-97b97928c49190c9.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/{6196.34d6b229079e9e28.js → 3403.7199205e65124486.js} +1 -1
  40. package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/419.736c0d6f426249a7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{6def8a8e.c81f9ca41028eccf.js → 425cfc4d.fb91158e3971c39f.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/{16e57f67.3ea19e893461e611.js → 46bd8bea.2f4b4099172fcdb7.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/{5081.a240b63fad28663a.js → 4759.1f76713aefb87db5.js} +1 -1
  51. package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +94 -0
  54. package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +62 -0
  60. package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +27 -0
  63. package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +104 -0
  64. package/apps/pwa/out/_next/static/chunks/{9974.e77b4ff4884557b3.js → 5591.a35e7a217734a8b9.js} +2 -2
  65. package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +93 -0
  66. package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/{5492-e05e26a033ba80d2.js → 6013-2f769370d8b4c2c6.js} +3 -3
  69. package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +24 -0
  70. package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +2 -0
  72. package/apps/pwa/out/_next/static/chunks/{5408.377c8c543635b81f.js → 6534.1ab00f370db7b105.js} +1 -1
  73. package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +148 -0
  74. package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +149 -0
  75. package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +79 -0
  77. package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/{8578.dff22d988cc2b106.js → 6767.1fcfc9b8be83975f.js} +16 -16
  79. package/apps/pwa/out/_next/static/chunks/6776.06ff1e3b464cc607.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/{9311.24c8f5ea793253dd.js → 6853.cc5174a9dee59593.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +287 -0
  86. package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/{94.4cfed21c0b781a06.js → 7375.050ea0d72968e49f.js} +16 -16
  92. package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +77 -0
  94. package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +74 -0
  97. package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7725-4f83d5541fbdb81b.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8332.6f0f49df772e163b.js +23 -0
  102. package/apps/pwa/out/_next/static/chunks/{7483.ba01c6c209b81bba.js → 8398.73a19b39715eda04.js} +1 -1
  103. package/apps/pwa/out/_next/static/chunks/{2846.d6a433b8663819a5.js → 8471.8d2a8c74f09c36ff.js} +3 -3
  104. package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +226 -0
  106. package/apps/pwa/out/_next/static/chunks/{5785-ea8d2c633b6688e3.js → 8767-2f6a634f5abeaa01.js} +1 -1
  107. package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +32 -0
  109. package/apps/pwa/out/_next/static/chunks/8795.32573a185af18c7b.js +41 -0
  110. package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{4593.10f5b9bd702d4a6c.js → 9143.ff14585db1d275ff.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{4204.a409ab6250c0f6a8.js → 9907.49be0fcadaf214b5.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{973cbf1b.3bbcf2b41548eca7.js → a435ad95.577add051b4facb2.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-fa46d4588e8442c2.js → page-a5635eba0d73b84e.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/{page-66ad46ed0279feb9.js → page-86feb08080261a2f.js} +1 -1
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/{page-646b50f63b6fe732.js → page-8aaa6dedc4c10dfb.js} +1 -1
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/{page-6f131b51193a36f9.js → page-33bf667a5fb297bf.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-29900ed0011b2c83.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9f92737b8766009a.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{f4dfbfc0.a69fb12f854882aa.js → bc324b7c.02a09dd93f6a399b.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +122 -0
  177. package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +1 -0
  183. package/apps/pwa/out/approvals/index.html +1 -1
  184. package/apps/pwa/out/approvals/index.txt +22 -22
  185. package/apps/pwa/out/autopilot/index.html +1 -1
  186. package/apps/pwa/out/autopilot/index.txt +22 -22
  187. package/apps/pwa/out/board/index.html +1 -1
  188. package/apps/pwa/out/board/index.txt +22 -22
  189. package/apps/pwa/out/botlab/index.html +1 -1
  190. package/apps/pwa/out/botlab/index.txt +21 -21
  191. package/apps/pwa/out/bots/index.html +1 -1
  192. package/apps/pwa/out/bots/index.txt +21 -21
  193. package/apps/pwa/out/ceo/index.html +1 -1
  194. package/apps/pwa/out/ceo/index.txt +22 -22
  195. package/apps/pwa/out/chat/index.html +1 -1
  196. package/apps/pwa/out/chat/index.txt +21 -21
  197. package/apps/pwa/out/consult/index.html +1 -1
  198. package/apps/pwa/out/consult/index.txt +22 -22
  199. package/apps/pwa/out/control/index.html +1 -1
  200. package/apps/pwa/out/control/index.txt +22 -22
  201. package/apps/pwa/out/decisions/index.html +1 -1
  202. package/apps/pwa/out/decisions/index.txt +21 -21
  203. package/apps/pwa/out/design-check/index.html +1 -1
  204. package/apps/pwa/out/design-check/index.txt +22 -22
  205. package/apps/pwa/out/editor/index.html +1 -1
  206. package/apps/pwa/out/editor/index.txt +22 -22
  207. package/apps/pwa/out/exec/index.html +1 -1
  208. package/apps/pwa/out/exec/index.txt +22 -22
  209. package/apps/pwa/out/field/index.html +1 -1
  210. package/apps/pwa/out/field/index.txt +22 -22
  211. package/apps/pwa/out/healthz +1 -1
  212. package/apps/pwa/out/index.html +1 -1
  213. package/apps/pwa/out/index.txt +21 -21
  214. package/apps/pwa/out/inside/index.html +1 -1
  215. package/apps/pwa/out/inside/index.txt +21 -21
  216. package/apps/pwa/out/intake/index.html +1 -1
  217. package/apps/pwa/out/intake/index.txt +22 -22
  218. package/apps/pwa/out/live/index.html +1 -1
  219. package/apps/pwa/out/live/index.txt +22 -22
  220. package/apps/pwa/out/live-run/index.html +1 -1
  221. package/apps/pwa/out/live-run/index.txt +22 -22
  222. package/apps/pwa/out/loops/index.html +1 -1
  223. package/apps/pwa/out/loops/index.txt +21 -21
  224. package/apps/pwa/out/market/index.html +1 -1
  225. package/apps/pwa/out/market/index.txt +21 -21
  226. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  227. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  228. package/apps/pwa/out/morning/index.html +1 -1
  229. package/apps/pwa/out/morning/index.txt +22 -22
  230. package/apps/pwa/out/observatory/index.html +1 -1
  231. package/apps/pwa/out/observatory/index.txt +22 -22
  232. package/apps/pwa/out/ops/checklist/index.html +1 -1
  233. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  234. package/apps/pwa/out/ops/release/index.html +1 -1
  235. package/apps/pwa/out/ops/release/index.txt +21 -21
  236. package/apps/pwa/out/ops/seats/index.html +1 -1
  237. package/apps/pwa/out/ops/seats/index.txt +21 -21
  238. package/apps/pwa/out/outputs/index.html +1 -1
  239. package/apps/pwa/out/outputs/index.txt +21 -21
  240. package/apps/pwa/out/reflection/index.html +1 -1
  241. package/apps/pwa/out/reflection/index.txt +22 -22
  242. package/apps/pwa/out/scheduler/index.html +1 -1
  243. package/apps/pwa/out/scheduler/index.txt +22 -22
  244. package/apps/pwa/out/sessions/index.html +1 -1
  245. package/apps/pwa/out/sessions/index.txt +21 -21
  246. package/apps/pwa/out/settings/devices/index.html +1 -1
  247. package/apps/pwa/out/settings/devices/index.txt +22 -22
  248. package/apps/pwa/out/settings/index.html +1 -1
  249. package/apps/pwa/out/settings/index.txt +22 -22
  250. package/apps/pwa/out/setup/done/index.html +1 -1
  251. package/apps/pwa/out/setup/done/index.txt +22 -22
  252. package/apps/pwa/out/setup/index.html +1 -1
  253. package/apps/pwa/out/setup/index.txt +22 -22
  254. package/apps/pwa/out/share/index.html +1 -1
  255. package/apps/pwa/out/share/index.txt +22 -22
  256. package/apps/pwa/out/showroom/index.html +1 -1
  257. package/apps/pwa/out/showroom/index.txt +21 -21
  258. package/apps/pwa/out/tasks/index.html +1 -1
  259. package/apps/pwa/out/tasks/index.txt +22 -22
  260. package/apps/pwa/out/term/index.html +1 -1
  261. package/apps/pwa/out/term/index.txt +22 -22
  262. package/apps/pwa/out/today/index.html +1 -1
  263. package/apps/pwa/out/today/index.txt +22 -22
  264. package/apps/pwa/out/trace/index.html +1 -1
  265. package/apps/pwa/out/trace/index.txt +22 -22
  266. package/apps/pwa/out/vault/index.html +1 -1
  267. package/apps/pwa/out/vault/index.txt +22 -22
  268. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  269. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  270. package/apps/pwa/out/workflows/index.html +1 -1
  271. package/apps/pwa/out/workflows/index.txt +22 -22
  272. package/apps/pwa/out/workspace/index.html +1 -1
  273. package/apps/pwa/out/workspace/index.txt +22 -22
  274. package/apps/pwa/out/worktrees/index.html +1 -1
  275. package/apps/pwa/out/worktrees/index.txt +22 -22
  276. package/graphs/release/release-loop.yaml +6 -2
  277. package/package.json +1 -1
  278. package/plugins/agent-team/agents/research.md +1 -0
  279. package/scripts/ci-typecheck-changed.ts +3 -2
  280. package/scripts/coord-channel-watch.sh +26 -6
  281. package/scripts/coord-role-pack.ts +143 -0
  282. package/scripts/lib/morning-report-options.ts +41 -0
  283. package/scripts/pr-land-extra-remote-gates.ts +49 -0
  284. package/scripts/release-loop/gate-batch-safe.ts +23 -0
  285. package/scripts/release-loop/gate-history.ts +422 -0
  286. package/scripts/release-loop/gate-node.ts +310 -46
  287. package/scripts/release-loop/gate-triage-node.ts +190 -0
  288. package/scripts/release-loop/spawn-lane.ts +68 -0
  289. package/scripts/release-loop/tui-node-checks.ts +23 -0
  290. package/scripts/release-loop/version-node.ts +62 -4
  291. package/scripts/test-deterministic.ts +41 -12
  292. package/scripts/usage-rollup.ts +11 -3
  293. package/src/acp/core-turn-bridge.ts +98 -22
  294. package/src/acp/elanous-extensions.ts +2 -0
  295. package/src/acp/server.ts +2 -0
  296. package/src/agent/ref-grounding.ts +18 -0
  297. package/src/agent-substrate/pr-reviewer.ts +29 -21
  298. package/src/budget/pty-usage-reemit.ts +7 -0
  299. package/src/budget/run-usage-rollup.ts +9 -0
  300. package/src/budget/usage-daily-store.ts +98 -0
  301. package/src/capture/tui-self-report.ts +22 -4
  302. package/src/chat/index.ts +31 -10
  303. package/src/chat/pickers/modal-runtime.ts +1 -0
  304. package/src/chat/pickers/modals.ts +3 -1
  305. package/src/chat/turn-typeahead.ts +123 -16
  306. package/src/cli/dashboard-name-flag.ts +48 -0
  307. package/src/cli/doctor-cli.ts +80 -0
  308. package/src/cli/log-event-names.ts +12 -0
  309. package/src/cli/msg-cli.ts +45 -2
  310. package/src/cli/pr-cli.ts +382 -105
  311. package/src/cli/pr-land-heavy-remote.ts +233 -0
  312. package/src/cli/pr-land-overlap-evidence.ts +104 -5
  313. package/src/cli/pty-takeover-cli.ts +125 -16
  314. package/src/cli/release-cli.ts +44 -2
  315. package/src/cli/remote-resolve.ts +2 -1
  316. package/src/cli/seat-cli.ts +26 -16
  317. package/src/cli/tasks-cli.ts +8 -2
  318. package/src/cli/usage-cli.ts +146 -12
  319. package/src/cli/usage-daily-cli.ts +84 -0
  320. package/src/context-bus/context-now.ts +82 -5
  321. package/src/core-turn/auth-rejected-notice.ts +41 -0
  322. package/src/core-turn/run-core-turn.ts +13 -2
  323. package/src/core-turn/run-goal-loop.ts +17 -1
  324. package/src/core-turn/short-question.ts +45 -12
  325. package/src/core-turn/types.ts +7 -0
  326. package/src/dashboard/acp-active-model.ts +40 -0
  327. package/src/dashboard/auto-compact-runtime.ts +2 -0
  328. package/src/dashboard/boot-banner.ts +80 -0
  329. package/src/dashboard/dashboard-status-lines.ts +11 -0
  330. package/src/dashboard/detail-viewer-runtime.ts +15 -2
  331. package/src/dashboard/event-loop-stall-monitor.ts +4 -0
  332. package/src/dashboard/goal-loop-thinking.ts +16 -0
  333. package/src/dashboard/hitl-boot.ts +9 -4
  334. package/src/dashboard/index.ts +228 -387
  335. package/src/dashboard/input/chat-main-entry-runtime.ts +2 -0
  336. package/src/dashboard/input/chat-main-log-actions.ts +4 -0
  337. package/src/dashboard/input/chat-main-log-command.ts +12 -1
  338. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +172 -3
  339. package/src/dashboard/input/chat-main-session.ts +6 -2
  340. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  341. package/src/dashboard/input/chat-main-turn.ts +2 -1
  342. package/src/dashboard/input/compact-prepass-recovery.ts +97 -0
  343. package/src/dashboard/input/dashboard-chord-actions.ts +10 -1
  344. package/src/dashboard/input/dashboard-chord-runtime.ts +2 -0
  345. package/src/dashboard/input/external-input-host.ts +45 -0
  346. package/src/dashboard/input/log-fold-binding.ts +18 -0
  347. package/src/dashboard/input/mouse-wiring.ts +17 -4
  348. package/src/dashboard/input/turn-steer-bridge.ts +94 -0
  349. package/src/dashboard/log-click-runtime.ts +5 -3
  350. package/src/dashboard/running-build-status.ts +74 -0
  351. package/src/dashboard/seat-boot-preamble.ts +113 -0
  352. package/src/dashboard/seat-local-instructions.ts +305 -0
  353. package/src/dashboard/slash-runtime/dashboard-handlers.ts +100 -28
  354. package/src/dashboard/slash-runtime/model-choices.ts +35 -0
  355. package/src/dashboard/term-slash-runtime.ts +15 -0
  356. package/src/dashboard/turn-preamble.ts +30 -2
  357. package/src/dashboard/turn-session-layers.ts +176 -0
  358. package/src/dashboard/turn-stream-formatter.ts +14 -6
  359. package/src/dashboard/turn-stream-presentation-applier.ts +8 -0
  360. package/src/domains/release-tool.ts +8 -9
  361. package/src/domains/surface-events.ts +4 -1
  362. package/src/domains/watch-default-scheduler.ts +8 -9
  363. package/src/fold-stack.ts +24 -1
  364. package/src/git-fs/dirty.ts +32 -4
  365. package/src/git-fs/index.ts +43 -1
  366. package/src/graph-runner/runner.ts +1 -0
  367. package/src/harness/harness-gc.ts +32 -5
  368. package/src/index.ts +14 -1
  369. package/src/input/external-input-queue.ts +219 -0
  370. package/src/interactive-terminal-modal.ts +13 -0
  371. package/src/llm/route-decision.ts +25 -0
  372. package/src/llm-stream-retry-display.ts +59 -0
  373. package/src/llm.ts +253 -55
  374. package/src/log-entry.ts +3 -3
  375. package/src/log-pane/search.ts +29 -4
  376. package/src/loops/agent-reply.ts +256 -0
  377. package/src/loops/budget.ts +37 -7
  378. package/src/loops/loop-cli.ts +3 -2
  379. package/src/loops/msg-address.ts +57 -0
  380. package/src/loops/msg-wake.ts +282 -0
  381. package/src/loops/orchestrator/inbox.ts +60 -3
  382. package/src/loops/orchestrator/tick.ts +24 -4
  383. package/src/loops/registry.ts +42 -4
  384. package/src/memory.ts +20 -5
  385. package/src/native-tool-catalog.ts +125 -0
  386. package/src/nexus/api/http-server.ts +5 -0
  387. package/src/nexus/api/ops-api.ts +2 -0
  388. package/src/nexus/api/project-autopsy.ts +127 -0
  389. package/src/nexus/api/terminals.ts +3 -0
  390. package/src/nexus/api/workflow-approvals.ts +2 -0
  391. package/src/nexus/onboarding/first-boot-wizard.ts +56 -2
  392. package/src/oauth/codex-account-store.ts +15 -3
  393. package/src/oauth/codex-billing-route.ts +31 -0
  394. package/src/ops/overview-collect.ts +19 -2
  395. package/src/panes/log-pane.ts +67 -8
  396. package/src/persona/presets.ts +44 -0
  397. package/src/plugins/maker/wizard-generate.ts +6 -4
  398. package/src/preview/terminal.ts +14 -1
  399. package/src/prompt-cache/types.ts +2 -0
  400. package/src/prompt-enhance/enhance.ts +24 -8
  401. package/src/prompt-library/universal-preamble.ts +273 -56
  402. package/src/pty-shell/pty-control-ipc.ts +4 -1
  403. package/src/pty-shell/pty-manifest.ts +77 -5
  404. package/src/pty-shell/registry.ts +19 -2
  405. package/src/pty-shell/tui-run-state.ts +253 -0
  406. package/src/release-loop/light-rc.ts +28 -3
  407. package/src/release-loop/rehearsal.ts +1 -1
  408. package/src/render.ts +5 -1
  409. package/src/seat-loop/seat-report.ts +42 -2
  410. package/src/self-dev/run-supervisor.ts +71 -5
  411. package/src/self-dev/shard-aggregate.ts +2 -0
  412. package/src/self-dev/shard-run.ts +23 -2
  413. package/src/self-health/signatures.ts +132 -0
  414. package/src/self-implement/doctor-visit.ts +118 -0
  415. package/src/self-implement/gate-cli.ts +11 -2
  416. package/src/self-implement/goal-author-decompose.ts +80 -16
  417. package/src/self-implement/goal-author.ts +114 -72
  418. package/src/self-implement/goal-authoring-grounding.ts +1 -1
  419. package/src/self-implement/goal-file-name.ts +65 -0
  420. package/src/self-implement/ground-goal.ts +2 -1
  421. package/src/self-implement/host-regate.ts +14 -0
  422. package/src/self-implement/review-mustfix-class.ts +115 -0
  423. package/src/self-implement/run-ledger.ts +111 -7
  424. package/src/self-implement/running-runs.ts +10 -6
  425. package/src/self-implement/self-implement-runtime.ts +32 -0
  426. package/src/session/pending-input.ts +62 -11
  427. package/src/session-runtime/index.ts +7 -1
  428. package/src/skills/tools/ops-ledger.ts +707 -0
  429. package/src/skills/tools/persistent-grounding.ts +47 -7
  430. package/src/skills/tools/shell.ts +117 -1
  431. package/src/status/bar.ts +32 -2
  432. package/src/status/status-provider-info.ts +58 -0
  433. package/src/task-agent/rejudge-on-head.ts +4 -1
  434. package/src/task-agent/remote-rejudge-bind.ts +34 -5
  435. package/src/task-agent/repair-cycle.ts +13 -0
  436. package/src/task-orchestrator/surfaces/kubectl-transient-retry.ts +51 -0
  437. package/src/task-orchestrator/surfaces/pod-command-job.ts +63 -7
  438. package/src/task-orchestrator/surfaces/pod-install-slots.ts +6 -11
  439. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +76 -0
  440. package/src/task-orchestrator/surfaces/self-implement-pod.ts +107 -33
  441. package/src/terminal/session-registry.ts +6 -0
  442. package/src/thinking-line.ts +12 -3
  443. package/src/tool-runtime/index.ts +4 -0
  444. package/src/tool-runtime/ops-ledger-runtimes.ts +84 -0
  445. package/src/tool-runtime/ref-consult-runtime.ts +17 -2
  446. package/src/tool-runtime/run-shell-runtime.ts +4 -1
  447. package/src/tool-runtime/self-cognition-runtimes.ts +5 -1
  448. package/src/tui.ts +5 -0
  449. package/src/user-config.ts +54 -6
  450. package/src/ux-sim/fake-llm.ts +29 -0
  451. package/src/ux-sim/in-process-cli.ts +175 -0
  452. package/src/version/packed-revision.json +1 -1
  453. package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +0 -1
  454. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +0 -1
  455. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +0 -1
  456. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +0 -1
  457. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +0 -36
  458. package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +0 -1
  459. package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +0 -148
  460. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +0 -1
  461. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +0 -1
  463. package/apps/pwa/out/_next/static/chunks/1454-29d1d773d5996a49.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +0 -1
  465. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +0 -1
  466. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +0 -27
  467. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +0 -1
  468. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +0 -24
  472. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +0 -32
  475. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +0 -34
  477. package/apps/pwa/out/_next/static/chunks/3259-86f3be56e43eaf6a.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +0 -1
  479. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +0 -287
  482. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/4084.15ecaf4240bd9e77.js +0 -286
  487. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +0 -8
  492. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +0 -104
  494. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +0 -149
  496. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/599-56f2c0a5cc4a7295.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +0 -23
  506. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +0 -77
  510. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +0 -64
  512. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +0 -2
  514. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +0 -62
  522. package/apps/pwa/out/_next/static/chunks/7752.5cbdd0b433c54af9.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/8085-1e5fce59500a2cc2.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +0 -226
  531. package/apps/pwa/out/_next/static/chunks/83a80514-b897b64df43ce108.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +0 -93
  533. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +0 -24
  534. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +0 -115
  537. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +0 -41
  539. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +0 -74
  540. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +0 -94
  541. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +0 -90
  545. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +0 -79
  549. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/app/approvals/page-5ab1e47978577c5e.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-24453f6a302816b4.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/app/board/page-6c131d30bb1cf871.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/bots/page-dc0772b11861af51.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/chat/page-5159dc8752c6cd29.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/consult/page-c5a2478861c08b87.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/control/page-f722a9dec084e08b.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/decisions/page-256ffd365d32e100.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e0de78ae7b99f01c.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/editor/page-cfbdc44b708d9801.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/exec/page-4c741eb760f2f77c.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/field/page-e9ba98f5f1440a21.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/inside/page-dafc901bb1b72b5f.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/intake/page-2f6f303fa114ec24.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/layout-1634081c5272006c.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/live/page-ced0bcfc6542b3fc.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/live-run/page-bb1f05cd51c38944.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/market/page-db069b48a59c8c00.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-f736324afa2117c1.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/not-found-435f5e2faf02bc01.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/observatory/page-497e0eedf20e7890.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-a8d28fdf995e16ea.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8966452228753c5e.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fd5d18656cb432b6.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5663779cb1a37609.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/page-66a67eb19ebd976b.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/reflection/page-3b492aa78cf3c4a6.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c71267e7681da982.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/sessions/page-a21d1e1797172692.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-cb249e81ed339318.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/settings/page-781cfc5114e097da.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-478157214db6a023.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/setup/page-86141f12cf090b7f.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/share/page-7256c73bb1c36751.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/showroom/page-5c738ca7adef3de5.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/tasks/page-0138c8091ec17224.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/term/page-cc2f24f16d85e735.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/today/page-979d318a534e92da.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/trace/page-182d394f7e6e096b.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/vault/page-21050928a697ed7a.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-44b9d807005a9030.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/workflows/page-601fb77340e63c9a.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/workspace/page-75d3fb5d47af0edf.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-11bf9e5725a72c22.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/e117f801.e92bf10242653497.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +0 -122
  599. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +0 -1
  605. package/src/dashboard/bench-slash-runtime.ts +0 -40
  606. package/src/dashboard/input/search-modal-router.ts +0 -9
  607. package/src/dashboard/modals/pane-key-router.ts +0 -27
  608. package/src/dashboard/view-slash-runtime.ts +0 -48
  609. /package/apps/pwa/out/_next/static/{y1ltt7oCZxVpC6zVPhZ2O → cIpv5nU9AycwYWZI9H589}/_ssgManifest.js +0 -0
@@ -371,6 +371,12 @@ export interface StartOpts {
371
371
  kind?: string;
372
372
  /** 휴먼 리더블 닉네임 — 고유 id 와 함께 같은 PTY 를 부르는 다른 이름(나중에 goto 로 기억·접근). */
373
373
  nickname?: string;
374
+ /** Explicit origin for a host-owned PTY when the host process has no origin marker. */
375
+ origin?: { originRoot: string; controller?: string };
376
+ /** Explicit purpose for a host-owned PTY with no worktree goal. */
377
+ purpose?: string;
378
+ /** Seat that owns this PTY; absent for callers without a seat. */
379
+ seat?: string;
374
380
  /** 접근 모드 초기값(관찰 read/인터랙션 write/자율 auto). 기본 'write'(미션 등 헤드리스 자율은 'auto' 지정). */
375
381
  accessMode?: PtyAccessMode;
376
382
  /** 전환 정책 초기값(전환불가 locked/전환허용 open). 기본 'open'. */
@@ -766,6 +772,9 @@ export function startPty(opts: StartOpts): PtyHandle {
766
772
  id, kind: handle.kind, cmd: handle.cmd, ptyPid: adapter.pid,
767
773
  ...(handle.nickname ? { nickname: handle.nickname } : {}),
768
774
  ...(handle.workdir ? { workdir: handle.workdir } : {}),
775
+ ...(opts.origin ? { origin: opts.origin } : {}),
776
+ ...(opts.purpose ? { purpose: opts.purpose } : {}),
777
+ ...(opts.seat ? { seat: opts.seat } : {}),
769
778
  startedAt: handle.startedAt, now: Date.now(),
770
779
  identity: {
771
780
  ...(childSpaceId === undefined ? {} : { spaceId: childSpaceId }),
@@ -887,8 +896,16 @@ export function listPty(): PtyHandle[] {
887
896
  /** 닉네임 부여/변경 — 나중에 goto 로 기억·접근 쉽게. 없는 id 면 false. */
888
897
  export function renamePty(id: string, nickname: string): boolean {
889
898
  const h = getPty(id);
890
- if (!h) return false;
891
- h.setNickname(nickname);
899
+ if (h) {
900
+ h.setNickname(nickname);
901
+ return true;
902
+ }
903
+ // ⭐ 자식이 아닌 제어 대상(맨 `elanous` TUI 의 `tui:<pid>` 행 등)은 PtyHandle 이 없다 —
904
+ // 별명은 manifest 행에만 산다. 여기서 받지 않으면 IPC rename 이 그 행에 `unknown-pty` 로 진다.
905
+ const target = controlTargets.get(id);
906
+ if (!target || !target.isAlive()) return false;
907
+ if (PTY_MANIFEST_ENABLED) updatePtyManifestNickname(id, nickname.trim() || undefined, Date.now());
908
+ debug.log('pty.rename', 'control-target-renamed', { ptyId: id, nickname: nickname.trim() });
892
909
  return true;
893
910
  }
894
911
 
@@ -0,0 +1,253 @@
1
+ // ── TUI 실행 상태 — 턴(busy/idle) ⊕ 기동 판 ⊕ stale 판정 ──
2
+ //
3
+ // 바깥 제어자(`elanous pty state <ref>`)가 «지금 턴 중인가»와 «이 프로세스가 어느 판 코드로 도는가»를
4
+ // 화면 글자 grep 없이 알게 한다(대표 TUI OP 도그푸드 결함 #13).
5
+ //
6
+ // ⛔ 화면 하단 `⌥ HEAD@<sha>` 는 «세션 cwd 트리»의 HEAD 다 — 프로세스가 실은 코드가 아니다.
7
+ // 10-14 실측: 15:19 에 뜬 TUI 가 15:4x 설치 갱신(5c0f98f) 뒤에도 새 판처럼 보였다.
8
+ // ⇒ 기동 판은 «기동 때 한 번» 잡아 manifest 행에 적고, 비교 대상(설치본 · 체크아웃 HEAD)은 «읽을 때» 잰다.
9
+ //
10
+ // 기록(TUI 쪽): 행 등록 직후 `startTuiRunStateRecorder` 가 판 ⊕ idle 을 적고, 대시보드가 턴 시작·끝에
11
+ // `reportTuiTurn` 을 부른다. 기록 실패는 `debug.log('pty.tui-state', …)` — 조용히 삼키지 않는다.
12
+ // 판독(CLI 쪽): `describePtyRunState` 가 행 ⊕ 설치본 기록 ⊕ (체크아웃이면) 그 뿌리의 HEAD 로 판정한다.
13
+
14
+ import { readFileSync } from 'node:fs';
15
+ import { homedir } from 'node:os';
16
+ import { dirname, join, resolve } from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
18
+
19
+ import { debug } from '../debug/log.js';
20
+ import { runGitCommand } from '../git-fs/runner.js';
21
+ import { codeRevision, packageVersion, readInstallMetadataCommit } from '../version/code-revision.js';
22
+ import { versionedDashboardInstallDir } from '../dashboard/stale-install-check.js';
23
+ import {
24
+ updatePtyManifestBuild, updatePtyManifestTurn,
25
+ type PtyBuildIdentity, type PtyManifestRow, type PtyTurnState,
26
+ } from './pty-manifest.js';
27
+
28
+ const CODE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..', '..');
29
+
30
+ // ── 기동 판 ──
31
+
32
+ export interface RunningBuildDeps {
33
+ readonly codeRoot?: string;
34
+ readonly installRoot?: string;
35
+ readonly versionDirOf?: (codeRoot: string, installRoot?: string) => string | undefined;
36
+ readonly readInstallCommit?: (metadataPath: string) => string | undefined;
37
+ /** 체크아웃 HEAD(설치본 판 폴더가 아닐 때만). */
38
+ readonly revision?: () => string | undefined;
39
+ readonly version?: () => string;
40
+ }
41
+
42
+ /** 이 프로세스가 실은 코드의 판. 설치본 판 폴더면 그 폴더의 install.json, 아니면 코드 뿌리의 git HEAD. */
43
+ export function resolveRunningBuild(deps: RunningBuildDeps = {}): PtyBuildIdentity {
44
+ const codeRoot = deps.codeRoot ?? CODE_ROOT;
45
+ const version = (deps.version ?? packageVersion)();
46
+ const versionDir = (deps.versionDirOf ?? versionedDashboardInstallDir)(codeRoot, deps.installRoot);
47
+ if (versionDir) {
48
+ // 판 폴더의 install.json 만이 «실은 판»의 증거다 — 못 읽으면 다른 출처로 메우지 않고 모른다로 둔다.
49
+ const sha = (deps.readInstallCommit ?? readInstallMetadataCommit)(join(versionDir, 'install.json')) ?? '';
50
+ return { version, sha, source: sha ? 'installed' : 'unknown', codeRoot };
51
+ }
52
+ const sha = (deps.revision ?? codeRevision)() ?? '';
53
+ return { version, sha, source: sha ? 'checkout' : 'unknown', codeRoot };
54
+ }
55
+
56
+ let bootBuild: PtyBuildIdentity | undefined;
57
+ /** 기동 판 — 처음 부른 순간 한 번 잡고 그대로 둔다(뒤에 트리 HEAD 가 움직여도 «실은 코드»는 그대로다). */
58
+ export function runningBuild(): PtyBuildIdentity {
59
+ bootBuild ??= resolveRunningBuild();
60
+ return bootBuild;
61
+ }
62
+
63
+ // ── 설치본 기록 ──
64
+
65
+ export interface InstalledRecord {
66
+ readonly sha?: string;
67
+ /** install.json `installedAt`(epoch ms) — 못 읽으면 undefined. */
68
+ readonly installedAt?: number;
69
+ }
70
+
71
+ export function defaultInstallRoot(): string {
72
+ return join(homedir(), '.local', 'share', 'elanous');
73
+ }
74
+
75
+ /** 지금 `current` 가 가리키는 설치본의 commit ⊕ 설치 시각. */
76
+ export function readCurrentInstallRecord(installRoot = defaultInstallRoot()): InstalledRecord {
77
+ const path = join(installRoot, 'current', 'install.json');
78
+ const sha = readInstallMetadataCommit(path);
79
+ let installedAt: number | undefined;
80
+ try {
81
+ const parsed = JSON.parse(readFileSync(path, 'utf8')) as { installedAt?: unknown };
82
+ const t = typeof parsed.installedAt === 'string' ? Date.parse(parsed.installedAt) : NaN;
83
+ if (Number.isFinite(t)) installedAt = t;
84
+ } catch { /* 설치본 없음 */ }
85
+ return { ...(sha ? { sha } : {}), ...(installedAt !== undefined ? { installedAt } : {}) };
86
+ }
87
+
88
+ export function readCheckoutHead(codeRoot: string): string | undefined {
89
+ try {
90
+ const r = runGitCommand(codeRoot, ['rev-parse', 'HEAD'], { encoding: 'utf8' });
91
+ const sha = r.status === 0 ? String(r.stdout).trim() : '';
92
+ return sha || undefined;
93
+ } catch {
94
+ return undefined;
95
+ }
96
+ }
97
+
98
+ // ── stale 판정 ──
99
+
100
+ export type BuildStaleReason =
101
+ /** 설치본 판으로 떴고 지금 설치본과 같다. */
102
+ | 'same-as-installed'
103
+ /** 설치본 판으로 떴는데 그 뒤 설치본이 바뀌었다 — 재기동해야 새 판. */
104
+ | 'installed-moved'
105
+ /** 체크아웃에서 떴고 그 뿌리의 HEAD 가 같다. */
106
+ | 'same-as-checkout'
107
+ /** 체크아웃에서 떴는데 그 뿌리의 HEAD 가 움직였다. */
108
+ | 'checkout-moved'
109
+ /** 판 기록이 없는 옛 행인데 설치본이 그 행보다 늦게 깔렸다(추정 — 설치본으로 떴다면 낡았다). */
110
+ | 'started-before-install'
111
+ /** 비교할 값을 못 얻었다 — «안 낡았다»가 아니다. */
112
+ | 'unknown';
113
+
114
+ export interface BuildStaleness {
115
+ /** null = 못 쟀다(⛔ false 로 접지 않는다). */
116
+ readonly stale: boolean | null;
117
+ readonly reason: BuildStaleReason;
118
+ }
119
+
120
+ export function judgeBuildStaleness(input: {
121
+ readonly build?: PtyBuildIdentity;
122
+ readonly installed: InstalledRecord;
123
+ readonly checkoutHead?: string;
124
+ readonly startedAt?: number;
125
+ }): BuildStaleness {
126
+ const { build, installed } = input;
127
+ if (build?.sha && build.source === 'installed') {
128
+ if (!installed.sha) return { stale: null, reason: 'unknown' };
129
+ return installed.sha === build.sha ? { stale: false, reason: 'same-as-installed' } : { stale: true, reason: 'installed-moved' };
130
+ }
131
+ if (build?.sha && build.source === 'checkout') {
132
+ if (!input.checkoutHead) return { stale: null, reason: 'unknown' };
133
+ return input.checkoutHead === build.sha ? { stale: false, reason: 'same-as-checkout' } : { stale: true, reason: 'checkout-moved' };
134
+ }
135
+ if (!build && input.startedAt !== undefined && installed.installedAt !== undefined && installed.installedAt > input.startedAt) {
136
+ return { stale: true, reason: 'started-before-install' };
137
+ }
138
+ return { stale: null, reason: 'unknown' };
139
+ }
140
+
141
+ // ── 판독(CLI) ──
142
+
143
+ export type PtyTurnView = PtyTurnState | 'unknown';
144
+
145
+ export interface PtyRunStateView {
146
+ readonly turn: PtyTurnView;
147
+ readonly turnAt?: number;
148
+ readonly build: PtyBuildIdentity | null;
149
+ readonly installed: string | null;
150
+ readonly stale: boolean | null;
151
+ readonly staleReason: BuildStaleReason;
152
+ }
153
+
154
+ export interface DescribeRunStateDeps {
155
+ readonly readInstalled?: () => InstalledRecord;
156
+ readonly readCheckoutHead?: (codeRoot: string) => string | undefined;
157
+ }
158
+
159
+ /** manifest 행 하나의 턴 ⊕ 판 ⊕ stale. 행이 없거나 죽었으면 턴은 unknown. */
160
+ export function describePtyRunState(
161
+ row: Pick<PtyManifestRow, 'alive' | 'startedAt' | 'kind' | 'turnState' | 'turnAt' | 'build'> | null,
162
+ deps: DescribeRunStateDeps = {},
163
+ ): PtyRunStateView {
164
+ let installed: InstalledRecord = {};
165
+ try { installed = (deps.readInstalled ?? readCurrentInstallRecord)(); } catch { /* unknown */ }
166
+ const build = row?.build;
167
+ let checkoutHead: string | undefined;
168
+ // 판독 예외는 «모른다»(stale=null)로 — 조회 명령 자체를 깨지 않는다.
169
+ try {
170
+ if (build?.source === 'checkout' && build.codeRoot) checkoutHead = (deps.readCheckoutHead ?? readCheckoutHead)(build.codeRoot);
171
+ } catch { checkoutHead = undefined; }
172
+ // 판 기록 없는 옛 행의 «설치 뒤에 떴나» 추정은 elanous TUI 행에만 건다(셸 PTY 는 판과 무관하다).
173
+ const staleness = judgeBuildStaleness({
174
+ ...(build ? { build } : {}),
175
+ installed,
176
+ ...(checkoutHead ? { checkoutHead } : {}),
177
+ ...(row && row.kind === 'tui' ? { startedAt: row.startedAt } : {}),
178
+ });
179
+ const turn: PtyTurnView = row?.alive && row.turnState ? row.turnState : 'unknown';
180
+ return {
181
+ turn,
182
+ ...(turn !== 'unknown' && row?.turnAt ? { turnAt: row.turnAt } : {}),
183
+ build: build ?? null,
184
+ installed: installed.sha ?? null,
185
+ stale: staleness.stale,
186
+ staleReason: staleness.reason,
187
+ };
188
+ }
189
+
190
+ export function shortSha(sha: string | null | undefined): string {
191
+ return sha ? sha.slice(0, 7) : '-';
192
+ }
193
+
194
+ // ── 기록(TUI) ──
195
+
196
+ export interface TuiRunStateRecorderDeps {
197
+ readonly now?: () => number;
198
+ readonly build?: () => PtyBuildIdentity;
199
+ readonly writeBuild?: (id: string, build: PtyBuildIdentity) => boolean;
200
+ readonly writeTurn?: (id: string, turn: PtyTurnState, at: number) => boolean;
201
+ readonly log?: (event: string, data: Record<string, unknown>) => void;
202
+ }
203
+
204
+ interface ActiveRecorder {
205
+ readonly surfaceId: string;
206
+ readonly now: () => number;
207
+ readonly writeTurn: (id: string, turn: PtyTurnState, at: number) => boolean;
208
+ readonly log: (event: string, data: Record<string, unknown>) => void;
209
+ last?: PtyTurnState;
210
+ }
211
+
212
+ let active: ActiveRecorder | null = null;
213
+
214
+ const defaultLog = (event: string, data: Record<string, unknown>): void => { debug.log('pty.tui-state', event, data); };
215
+
216
+ /** TUI 행 등록 직후 부른다 — 판을 적고 턴을 idle 로 연다. 이후 `reportTuiTurn` 이 이 행에 적는다. */
217
+ export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRecorderDeps = {}): () => void {
218
+ const now = deps.now ?? Date.now;
219
+ const log = deps.log ?? defaultLog;
220
+ const writeTurn = deps.writeTurn ?? updatePtyManifestTurn;
221
+ let build: PtyBuildIdentity | undefined;
222
+ try { build = (deps.build ?? runningBuild)(); } catch (error) {
223
+ log('build-resolve-failed', { ptyId: surfaceId, error: error instanceof Error ? error.message : String(error) });
224
+ }
225
+ if (build) {
226
+ const ok = (() => { try { return (deps.writeBuild ?? updatePtyManifestBuild)(surfaceId, build); } catch { return false; } })();
227
+ log(ok ? 'build-recorded' : 'build-write-failed', { ptyId: surfaceId, sha: build.sha, version: build.version, source: build.source });
228
+ }
229
+ const recorder: ActiveRecorder = { surfaceId, now, writeTurn, log };
230
+ active = recorder;
231
+ writeTurnState(recorder, 'idle');
232
+ return () => { if (active === recorder) active = null; };
233
+ }
234
+
235
+ /** 대시보드가 턴 시작(busy)·끝(idle)에 부른다. 녹음기가 없으면(자기보고 꺼짐) 아무것도 안 한다. */
236
+ export function reportTuiTurn(turn: PtyTurnState): void {
237
+ if (!active || active.last === turn) return;
238
+ writeTurnState(active, turn);
239
+ }
240
+
241
+ function writeTurnState(recorder: ActiveRecorder, turn: PtyTurnState): void {
242
+ const at = recorder.now();
243
+ let ok = false;
244
+ try { ok = recorder.writeTurn(recorder.surfaceId, turn, at); } catch { ok = false; }
245
+ if (ok) recorder.last = turn;
246
+ // 실패는 관측으로 남긴다 — 바깥 제어자는 그 사이 «unknown/낡은 값»을 본다. 성공은 남기지 않는다(턴마다 두 줄은 소음).
247
+ else recorder.log('turn-write-failed', { ptyId: recorder.surfaceId, turn, at });
248
+ }
249
+
250
+ export function resetTuiRunStateForTesting(): void {
251
+ active = null;
252
+ bootBuild = undefined;
253
+ }
@@ -11,6 +11,7 @@ import { runSelfGateCli, type SelfGateCliOptions, type SelfGateCliResult } from
11
11
  import { dispatchHeavyCheck, isValidGateHost, type DispatchDeps, type DispatchOptions } from '../self-implement/gate-remote.js';
12
12
  import { latestPublishedPreviousVersion } from '../../scripts/release-loop/unattended-release.js';
13
13
  import { baseVersion, isReleaseVersion } from '../../scripts/release-loop/release-version.js';
14
+ import { executeTuiNodeCheck, type ExecutedTuiCheck } from '../../scripts/release-loop/tui-node-checks.js';
14
15
 
15
16
  export const LIGHT_RC_ALWAYS_FILE = 'release/light-rc-always.txt';
16
17
  export const LIGHT_RC_DEFAULT_SHARDS = 4;
@@ -31,6 +32,8 @@ export interface LightRcOptions {
31
32
  /** Release ledger root for the previous-version lookup (release run's deps.ledgerRoot). */
32
33
  ledgerRoot?: string;
33
34
  log?: (line: string) => void;
35
+ /** Rehearsal-only TUI screen check; other light-rc callers keep their current defaults. */
36
+ rehearsalTui?: boolean;
34
37
  }
35
38
 
36
39
  export interface LightRcResult {
@@ -57,6 +60,7 @@ export interface LightRcResult {
57
60
  /** LIGHT-RC-MEASURE ③ — why the gate produced no measurement (e.g. `shard-2`); null = it measured. Carried in the
58
61
  * JSON so the reason reaches the caller even when the remote child's human lines (stderr) do not. */
59
62
  unmeasured: string | null;
63
+ rehearsalTui?: ExecutedTuiCheck;
60
64
  }
61
65
 
62
66
  export interface LightRcDeps {
@@ -68,6 +72,7 @@ export interface LightRcDeps {
68
72
  dispatch?: (opts: DispatchOptions, deps?: DispatchDeps) => Promise<number>;
69
73
  /** Extra dispatch deps (runner · settings) — tests drive the real dispatch with a fake host. */
70
74
  dispatchDeps?: Omit<DispatchDeps, 'write'>;
75
+ tuiCheck?: typeof executeTuiNodeCheck;
71
76
  /** Detached checkout of `sha` for a local run whose tree is not at the measured commit (default: git worktree add
72
77
  * --detach in a temp dir ⊕ bun install); `cleanup` removes it. */
73
78
  checkout?: (sha: string, repo: string, log: (line: string) => void) => { dir: string; cleanup: () => void };
@@ -180,13 +185,21 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
180
185
  let alwaysInclude = readList(cwd);
181
186
 
182
187
  let local: SelfGateCliResult | undefined;
183
- const runLocal = () => {
188
+ let localTui: ExecutedTuiCheck | undefined;
189
+ const runLocal = async () => {
184
190
  // ① The gate scopes by its tree's HEAD — so a tree that is not at the measured commit runs in a detached checkout of it.
185
191
  const checkout = worktreeHead === measuredCommit ? undefined : (deps.checkout ?? defaultCheckout)(measuredCommit, cwd, log);
186
192
  try {
187
193
  const dir = checkout?.dir ?? cwd;
188
194
  if (checkout) alwaysInclude = readList(dir);
189
195
  local = (deps.runGate ?? runSelfGateCli)(dir, { base, shards, alwaysInclude, includeImporterTests: true });
196
+ if (opts.rehearsalTui) {
197
+ const command = async (cmd: string, args: string[], tree: string, limitMs?: number) => {
198
+ const run = spawnSync(cmd, args, { cwd: tree, encoding: 'utf8', timeout: limitMs });
199
+ return { rc: run.status ?? 2, output: `${run.stdout ?? ''}\n${run.stderr ?? ''}` };
200
+ };
201
+ localTui = await (deps.tuiCheck ?? executeTuiNodeCheck)(measuredCommit, dir, command);
202
+ }
190
203
  } finally { checkout?.cleanup(); }
191
204
  for (const line of local.lines) log(line);
192
205
  return local.exitCode;
@@ -195,7 +208,7 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
195
208
  const rc = await (deps.dispatch ?? dispatchHeavyCheck)({
196
209
  tool: 'self-gate', repo: cwd, installPwa: true, refs: [base], json: true, commit: measuredCommit,
197
210
  // The host re-runs this command with --local (and ELANOUS_GATE_REMOTE_CHILD=1), so it never recurses.
198
- remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), '--local', '--json'],
211
+ remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), '--local', '--json', ...(opts.rehearsalTui ? ['--rehearsal-tui'] : [])],
199
212
  flags: { remote: opts.local ? undefined : opts.remote ?? true, local: !!opts.local },
200
213
  runLocal,
201
214
  }, {
@@ -236,11 +249,22 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
236
249
  unmeasured: typeof remote.unmeasured === 'string' && remote.unmeasured
237
250
  ? remote.unmeasured
238
251
  : typeof remote.introduced === 'number' ? null : LIGHT_RC_REASON_NOT_REPORTED,
252
+ ...(remote.rehearsalTui ? { rehearsalTui: remote.rehearsalTui } : {}),
239
253
  };
240
254
  }
241
255
  // Unmeasured (null) or unclassified failures are never green; policy-gate findings in the gate output are reported
242
256
  // (gate rc), not a regression.
243
- result.ok = result.introduced === 0 && result.unclassified === 0;
257
+ if (opts.rehearsalTui) {
258
+ if (local) {
259
+ result.rehearsalTui = localTui ?? { outcome: 'unmeasured', detail: 'local TUI screen result missing' };
260
+ } else {
261
+ const tui = result.rehearsalTui;
262
+ result.rehearsalTui = tui && ['ok', 'fail', 'unmeasured'].includes(tui.outcome) && typeof tui.detail === 'string' && tui.detail.length > 0
263
+ ? tui : { outcome: 'unmeasured', detail: 'remote TUI screen result missing' };
264
+ }
265
+ }
266
+ result.ok = result.introduced === 0 && result.unclassified === 0 && result.unmeasured === null
267
+ && (!opts.rehearsalTui || result.rehearsalTui?.outcome === 'ok');
244
268
  debug.log('release.light-rc', 'done', { version, base, measuredCommit, worktreeHead, importerTests: result.importerTests, introduced: result.introduced, preexisting: result.preexisting, unclassified: result.unclassified, shards, remote: result.remote, unmeasured: result.unmeasured });
245
269
  return result;
246
270
  }
@@ -250,5 +274,6 @@ export function formatLightRc(result: LightRcResult): string[] {
250
274
  `${result.ok ? '✅' : '⛔'} light-rc ${result.version} · base ${result.base.slice(0, 12)} · measured ${result.measuredCommit.slice(0, 12)} · ${result.remote ? `host ${result.remote}` : 'local'} · shards ${result.shards}`,
251
275
  ` introduced ${result.introduced ?? '못 쟀다'} · preexisting ${result.preexisting ?? '못 쟀다'} · unclassified ${result.unclassified ?? '못 쟀다'} · importer tests ${result.importerTests ?? '못 쟀다'} · always-include ${result.alwaysInclude}${result.alwaysIncludeMissing.length ? ` (missing: ${result.alwaysIncludeMissing.join(', ')})` : ''} · gate rc ${result.gateExitCode}`,
252
276
  ...(result.unmeasured !== null ? [` shards: unmeasured (${result.unmeasured})`] : []),
277
+ ...(result.rehearsalTui ? [` TUI screens: ${result.rehearsalTui.outcome} (${result.rehearsalTui.detail})`] : []),
253
278
  ];
254
279
  }
@@ -290,7 +290,7 @@ export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: Rehear
290
290
  stamp.sha = gitResult(git, ['rev-parse', 'HEAD'], checkout);
291
291
  if (!stamp.sha) throw new Error('git rev-parse HEAD returned no sha');
292
292
  const regressionFiles: string[] = [];
293
- const result = await (deps.lightRc ?? ((version, cwd) => runLightRc(version, { ledgerRoot: root, head: stamp.sha, log: (line) => {
293
+ const result = await (deps.lightRc ?? ((version, cwd) => runLightRc(version, { ledgerRoot: root, head: stamp.sha, rehearsalTui: true, log: (line) => {
294
294
  for (const entry of line.split(/\r?\n/)) {
295
295
  const file = /^- introduced: (.+?)(?: > |$)/.exec(entry)?.[1];
296
296
  if (file && regressionFiles.length < 3) regressionFiles.push(file);
package/src/render.ts CHANGED
@@ -572,6 +572,10 @@ function parseAndRenderTable(lines: string[]): string {
572
572
  * Render a tool call header like Claude Code:
573
573
  * ⏺ ToolName(description)
574
574
  */
575
+ export function singleLineToolHeaderText(text: string): string {
576
+ return text.replace(/[ \t]*(?:\r\n|\r|\n|\u2028|\u2029)[ \t]*/g, ' ↵ ');
577
+ }
578
+
575
579
  export function toolHeader(
576
580
  toolName: string,
577
581
  description: string,
@@ -585,7 +589,7 @@ export function toolHeader(
585
589
  case 'error': icon = applyColor(circle, 'error'); break;
586
590
  }
587
591
  const name = chalk.bold(toolName);
588
- const desc = description ? chalk.dim(`(${description})`) : '';
592
+ const desc = description ? chalk.dim(`(${singleLineToolHeaderText(description)})`) : '';
589
593
  return `${icon} ${name}${desc}`;
590
594
  }
591
595
 
@@ -8,6 +8,7 @@ import { effectiveInstanceRoot } from '../instance/resolve.js';
8
8
  import { getUserConfig, type SeatLoopConfig } from '../user-config.js';
9
9
  import { collectDraftMetrics, collectOverlapMetrics, countSalvagedToday, type DraftMetrics, type OverlapMetrics } from '../self-dev/draft-sweep.js';
10
10
  import { queryRunningRuns } from '../self-implement/running-runs.js';
11
+ import { loadRunLedger } from '../self-implement/run-ledger.js';
11
12
  import { readTaskAgentCover } from '../cli/tasks-cli.js';
12
13
  import { formatTaskAgentCover } from '../task-agent/cover.js';
13
14
  import type { TasksCliDeps } from '../cli/tasks-cli.js';
@@ -27,6 +28,10 @@ export type SeatReportDeps = {
27
28
  /** DRAFT-NOT-ARCHIVE salvage branches since the KST day start; null = unreadable. */
28
29
  salvagedToday?: (dayStart: Date, now: Date) => Promise<number | null>;
29
30
  runningRuns?: (runIds: readonly string[]) => { running: number; unknown: number } | null;
31
+ /** Launched-run 착지 집계; null 이나 예외는 «착지 못 잼»으로 나온다. */
32
+ landedRuns?: (runIds: readonly string[]) => { landed: number; unread: number } | null;
33
+ /** 기본 집계의 runId별 읽기 경로를 시험할 때만 교체한다. */
34
+ loadLedger?: typeof loadRunLedger;
30
35
  };
31
36
  export type SeatReportResult = { seat: string; date: string; body: string; posted: boolean };
32
37
  const repoRoot = resolve(import.meta.dir, '../..');
@@ -173,10 +178,45 @@ export async function seatReport(seat: string, deps: SeatReportDeps = {}): Promi
173
178
  : ` · 도는 런 ${counts.running}(불확실 ${counts.unknown})`;
174
179
  } catch { runningDetail = ' · 도는 런 못 잼'; }
175
180
  }
176
- const body = `**[${seat}]** {{TS}} → 보고 ${date}: ${detail.join(' · ') || (classified.length ? 'OP 그림자 판단' : '원장 기록 없음')}${opDetail}${draftDetail}${runningDetail}`;
181
+ // ⭐ 사다리 ① (#25210 «도는 런» 옆): 발사된 runId 각각의 run 원장을 읽어 착지 수를 센다.
182
+ // 'merged' 사건이 있으면 착지 · 원장이 null(로컬에 없음 — Pod 런 등)이면 «원장 없음»으로 따로 센다.
183
+ let landedDetail = '';
184
+ let landed: number | null = 0;
185
+ let landedUnread: number | null = 0;
186
+ if (runIds.length) {
187
+ try {
188
+ const counts = (deps.landedRuns ?? ((ids: readonly string[]) => {
189
+ let landedCount = 0;
190
+ let unreadCount = 0;
191
+ let unreadable = false;
192
+ for (const runId of ids) {
193
+ try {
194
+ const ledger = (deps.loadLedger ?? loadRunLedger)(runId);
195
+ if (ledger === null) unreadCount += 1;
196
+ else if (ledger.some((entry) => entry.event === 'merged')) landedCount += 1;
197
+ } catch { unreadable = true; }
198
+ }
199
+ return unreadable ? null : { landed: landedCount, unread: unreadCount };
200
+ }))(runIds);
201
+ if (counts === null) {
202
+ landed = null;
203
+ landedUnread = null;
204
+ landedDetail = ' · 착지 못 잼';
205
+ } else {
206
+ landed = counts.landed;
207
+ landedUnread = counts.unread;
208
+ landedDetail = ` · 착지 ${counts.landed}(원장 없음 ${counts.unread})`;
209
+ }
210
+ } catch {
211
+ landed = null;
212
+ landedUnread = null;
213
+ landedDetail = ' · 착지 못 잼';
214
+ }
215
+ }
216
+ const body = `**[${seat}]** {{TS}} → 보고 ${date}: ${detail.join(' · ') || (classified.length ? 'OP 그림자 판단' : '원장 기록 없음')}${opDetail}${draftDetail}${runningDetail}${landedDetail}`;
177
217
  const pr = (deps.config ?? getUserConfig().loops?.seat)?.reportPr;
178
218
  const posted = deps.post === true && pr !== undefined;
179
219
  if (posted) await (deps.send ?? ((text, id, number) => defaultSend(text, id, number, deps.repo ?? repoRoot)))(body, seat, pr);
180
- try { debug.log('seat.loop', 'reported', { seat, date, entries: entries.length, posted }); } catch { /* observation is fail-soft */ }
220
+ try { debug.log('seat.loop', 'reported', { seat, date, entries: entries.length, posted, landed, landedUnread }); } catch { /* observation is fail-soft */ }
181
221
  return { seat, date, body, posted };
182
222
  }
@@ -11,6 +11,7 @@ import { sweepFrozenMerges } from '../self-implement/frozen-merges.js';
11
11
  import { routeSupervisorVerdict } from './supervisor-verdict-edges.js';
12
12
  import { recordTaskAgentShadowMove, runCardFor, type TaskAgentShadowInput } from '../task-agent/shadow.js';
13
13
  import { cardPrNumber, taskAgentStatePath } from '../task-agent/task-hand.js';
14
+ import { classifyMustFixRound, inferMustFixEvidence, type MustFixRoundClassification, type MustFixRoundObservation } from '../self-implement/review-mustfix-class.js';
14
15
 
15
16
  export interface SupervisorRound {
16
17
  round: number;
@@ -46,6 +47,8 @@ export interface SupervisorRound {
46
47
  * streak pairs rounds by this key. Omitted on older history — the guard then pairs by taskId as before.
47
48
  */
48
49
  noPrFeatureKeys?: string[];
50
+ /** REVIEW-MUSTFIX-CLASSIFY — that round's observed must-fix items; pairs the next round's classification. */
51
+ mustFix?: MustFixRoundObservation;
49
52
  }
50
53
 
51
54
  /** Failed without a PR — a result that carries either a PR number or a PR URL has one (fixtures and older producers set only one). */
@@ -116,6 +119,10 @@ export interface SupervisorDecision {
116
119
  deliverableUnmeasured: boolean;
117
120
  deliverableMergeCompleteness: 'unmeasured' | 'complete' | 'incomplete';
118
121
  reviewMustFixTrend: ReviewRework['trend'];
122
+ /** REVIEW-MUSTFIX-CLASSIFY — this round's leading must-fix class (② › ③ observed › ①); omitted when unmeasured (지금 동작 그대로). */
123
+ mustFix?: MustFixRoundClassification;
124
+ /** REVIEW-MUSTFIX-CLASSIFY — every oscillating task's measured class, so a mixed round keeps each task's decision. */
125
+ mustFixByTask?: Record<string, MustFixRoundClassification>;
119
126
  oscillation?: { taskIds: string[]; helper: 'review-oscillation'; signature: string; repairGoals?: Record<string, string>; heldTaskIds?: string[] };
120
127
  pendingDecision?: 'attempt-care-escalation';
121
128
  }
@@ -234,6 +241,41 @@ export function aggregateReviewTrend(results: readonly SelfDevJobResult[]): Revi
234
241
  return severity[Math.max(...trends.map((trend) => severity.indexOf(trend)))];
235
242
  }
236
243
 
244
+ /**
245
+ * REVIEW-MUSTFIX-CLASSIFY — this round's must-fix observation from the results' verbatim `reviewMustFix`.
246
+ * Each item carries its `taskId` so the next round pairs per task (one task's recurrence never holds another).
247
+ */
248
+ function mustFixFromResults(results: readonly SupervisorJobResult[]): MustFixRoundObservation {
249
+ const items = results.flatMap((result) => (result.reviewMustFix ?? []).map((text) => {
250
+ const evidence = inferMustFixEvidence(text);
251
+ return { text, taskId: result.taskId, ...(evidence === undefined ? {} : { evidence }) };
252
+ }));
253
+ return items.length > 0 ? { items } : {};
254
+ }
255
+
256
+ /**
257
+ * REVIEW-MUSTFIX-CLASSIFY — per-task class. `prev` is the preceding round's items of the same task or its repair
258
+ * lineage (`oscillationRepairOf`), and only when that preceding round authored a repair for it — «수리 뒤 같은 지적»
259
+ * means a repair ran between the last observation and this one, not «repaired at any time». Lineage items are
260
+ * re-scoped to this task so the pure pairing accepts them; unrelated tasks never pair.
261
+ */
262
+ function classifyTaskMustFix(result: SupervisorJobResult, preceding: SupervisorRound | undefined): MustFixRoundClassification {
263
+ const pairIds = new Set([result.taskId, ...(result.oscillationRepairOf ? [result.oscillationRepairOf] : [])]);
264
+ const repairedSincePrev = (preceding?.oscillationRepairTaskIds ?? []).some((id) => pairIds.has(id));
265
+ const prevItems = repairedSincePrev
266
+ ? (preceding?.mustFix?.items ?? []).filter((item) => item.taskId !== undefined && pairIds.has(item.taskId))
267
+ .map((item) => ({ ...item, taskId: result.taskId }))
268
+ : [];
269
+ return classifyMustFixRound(prevItems.length > 0 ? { items: prevItems } : undefined, mustFixFromResults([result]));
270
+ }
271
+
272
+ /**
273
+ * Classes that hold a task out of this round's same-run repair. Only ② acts in this slice; ③ recurring is
274
+ * observed (decision `mustFix`/`mustFixByTask` · crossReview suggestion) but behaves as ① — acting on it is a
275
+ * follow-up cell (REVIEW-MUSTFIX-CLASSIFY partial landing).
276
+ */
277
+ const MUST_FIX_HELD = new Set<MustFixRoundClassification['class']>(['post-land-evidence']);
278
+
237
279
  export function decideNextRun(input: {
238
280
  results: readonly SupervisorJobResult[];
239
281
  history?: readonly SupervisorRound[];
@@ -520,8 +562,27 @@ export function decideNextRun(input: {
520
562
  || (entry.oscillationRepairFeatures?.[index] !== undefined && entry.oscillationRepairFeatures[index] === result.feature
521
563
  && Object.values(entry.oscillationRepairGoals ?? {}).includes(result.feature))));
522
564
  // Per task: a task that already got its one oscillation repair is held for a human; a fresh one may get it.
523
- const fresh = oscillating.filter((result) => !isRepaired(result));
524
- const held = [...new Set(oscillating.filter(isRepaired).map((result) => result.taskId))];
565
+ // REVIEW-MUSTFIX-CLASSIFY — 슈퍼바이저는 추이 대신 회차 분류를 먼저 본다(대표 10-12 «노하우가 아니라 로직으로» · 임의 임계 없음).
566
+ // ① new-defect — 그대로 수렴(진동 수리 유지).
567
+ // ② post-land-evidence — 증거는 착지 뒤에만 난다 ⇒ 같은 런 재수리 0, «그림자 착지 → 관측 → live» 쪼개기 결정.
568
+ // ③ recurring — 수리 뒤 같은 지적 ⇒ 이 조각에선 관측만(교차 리뷰 제안을 결정에 싣고 동작은 ① 그대로 · 후속 칸).
569
+ // unmeasured — 분류 불가 ⇒ 지금 동작 그대로. 분류는 조각마다 — 한 조각의 분류가 다른 조각의 수리를 끊지 않는다.
570
+ const taskClasses = new Map(oscillating.map((result) => [result.taskId, classifyTaskMustFix(result, preceding)]));
571
+ const fresh = oscillating.filter((result) => !isRepaired(result) && !MUST_FIX_HELD.has(taskClasses.get(result.taskId)!.class));
572
+ const classes = [...taskClasses.values()];
573
+ // Decision-level class: ② (the only acting class) first, then observed ③, else ①.
574
+ const mustFixClass = classes.find((c) => c.class === 'post-land-evidence') ?? classes.find((c) => c.class === 'recurring')
575
+ ?? classes.find((c) => c.class === 'new-defect');
576
+ // Held = already repaired once, or classified ② — either way it never rides this round's rerun.
577
+ const classHeld = [...new Set(oscillating.filter((result) => !isRepaired(result)
578
+ && MUST_FIX_HELD.has(taskClasses.get(result.taskId)!.class)).map((result) => result.taskId))];
579
+ const held = [...new Set([...oscillating.filter(isRepaired).map((result) => result.taskId), ...classHeld])];
580
+ const repairedHeld = held.filter((id) => !classHeld.includes(id));
581
+ // Every task's measured class survives in the decision — a mixed round keeps ② split and the observed ③ cross-review suggestion both.
582
+ const mustFixByTask: Record<string, MustFixRoundClassification> = Object.fromEntries(
583
+ [...taskClasses].filter(([, c]) => c.class !== 'unmeasured'));
584
+ const heldReasons = [...new Set(classes.filter((c) => MUST_FIX_HELD.has(c.class)).map((c) => c.reason))];
585
+ const heldReasonSuffix = heldReasons.length ? ` · ${heldReasons.join(' · ')}` : '';
525
586
  const repairGoals: Record<string, string> = Object.fromEntries(fresh.flatMap((result) => {
526
587
  const goal = result.prNumber && result.reviewMustFix?.length
527
588
  ? authorRepairGoal({ pr: result.prNumber, category: 'review-oscillation', originalRequest: result.feature,
@@ -551,14 +612,16 @@ export function decideNextRun(input: {
551
612
  } : {}),
552
613
  action,
553
614
  ...(action === 'stop' ? { stopReason: 'review-oscillating' as const } : {}),
615
+ ...(mustFixClass ? { mustFix: mustFixClass } : {}),
616
+ ...(Object.keys(mustFixByTask).length ? { mustFixByTask } : {}),
554
617
  oscillation: { taskIds, helper: 'review-oscillation', signature, ...(Object.keys(repairGoals).length ? { repairGoals } : {}),
555
618
  ...(action === 'add-repair-task' && held.length ? { heldTaskIds: held } : {}) },
556
619
  pendingDecision: 'attempt-care-escalation',
557
620
  why: fresh.length === 0
558
- ? `리뷰 진동 반복 — ${signatureOf(oscillating)} · 사람 결정 필요(같은 전략 재발사 금지)`
621
+ ? `리뷰 진동 반복 — ${signatureOf(oscillating)} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}`
559
622
  : cannotRepair
560
- ? `리뷰 진동 — ${signatureOf(oscillating)} · ${input.repairGoalExecution === false ? '이 감독 경로가 수리 골 실행을 선언하지 않았다(미선언 또는 불가)' : '수리 원문/PR 관측 불가'} · 사람 결정 필요(같은 전략 재발사 금지)`
561
- : `리뷰 진동 — ${signatureOf(fresh)} · review-oscillation 수리 조각을 한 번 붙인다${input.repairGoalExecution === true ? '' : '(실행 배선 미선언 — 결정 칸만)'}${held.length ? ` · 이미 수리한 조각 ${held.join(', ')} 은 사람 결정 대기` : ''}`,
623
+ ? `리뷰 진동 — ${signatureOf(oscillating)} · ${input.repairGoalExecution === false ? '이 감독 경로가 수리 골 실행을 선언하지 않았다(미선언 또는 불가)' : '수리 원문/PR 관측 불가'} · 사람 결정 필요(같은 전략 재발사 금지)${heldReasonSuffix}`
624
+ : `리뷰 진동 — ${signatureOf(fresh)} · review-oscillation 수리 조각을 한 번 붙인다${input.repairGoalExecution === true ? '' : '(실행 배선 미선언 — 결정 칸만)'}${repairedHeld.length ? ` · 이미 수리한 조각 ${repairedHeld.join(', ')} 은 사람 결정 대기` : ''}${classHeld.length ? ` · 분류로 보류한 조각 ${classHeld.join(', ')}` : ''}${heldReasonSuffix}`,
562
625
  };
563
626
  }
564
627
 
@@ -588,6 +651,8 @@ export function appendRound(
588
651
  const t = triageRun(results.filter((result) => result.salvage !== 'launched'), undefined, false, undefined, mainSyncRelaunchSpent(history));
589
652
  const baseCompleted = countBaseCompleted(results);
590
653
  const base = roundBase(results);
654
+ // REVIEW-MUSTFIX-CLASSIFY — 회차 원장에 관측을 실어 다음 회차 짝으로 쓴다(관측 없는 옛 원장은 그대로).
655
+ const mustFix = mustFixFromResults(results.filter((result) => result.salvage !== 'launched'));
591
656
  const noPrResults = results.filter(failedWithoutPr);
592
657
  const noPrTaskIds = noPrResults.map((result) => result.taskId);
593
658
  const noPrFeatureKeys = noPrResults.map((result) => noPrStreakKey(result.feature));
@@ -597,6 +662,7 @@ export function appendRound(
597
662
  ...(baseCompleted > 0 || base !== undefined ? { baseCompleted, ...(base === undefined ? {} : { base }) } : {}),
598
663
  actionable: countActionable(t),
599
664
  ...(reviewMustFixTrend === undefined ? {} : { reviewMustFixTrend }),
665
+ ...((mustFix.items ?? []).length > 0 ? { mustFix } : {}),
600
666
  ...(results.some((result) => result.rework?.signature)
601
667
  ? { signatures: Object.fromEntries(results.filter((result) => result.rework?.signature).map((result) => [result.taskId, result.rework!.signature])) } : {}),
602
668
  ...(decision && decision.action !== 'stop' && decision.relaunchOnMain.length > 0 ? {
@@ -16,6 +16,8 @@ export interface GateShardAttempt {
16
16
  baselineExitCode: number | null;
17
17
  currentSignal?: string | null;
18
18
  baselineSignal?: string | null;
19
+ currentDiagnostic?: string;
20
+ baselineDiagnostic?: string;
19
21
  /** LIGHT-RC-MEASURE — the shard files that exist in the baseline tree, i.e. what the baseline side actually ran.
20
22
  * Absent = every shard file (the old shape). Empty = the baseline side was not run and contributes zero cases. */
21
23
  baselineFiles?: readonly string[];