elanous 0.2.36 → 0.2.38

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 (741) 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/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 1026-44010f405704050c.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
  6. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 1632.7d87f998e714bede.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
  14. package/apps/pwa/out/_next/static/chunks/{7784.1f0ac4a16d190cf4.js → 2104.70e086d5174a4736.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{6566.926a1d1b7c911442.js → 214.186a430da28338f1.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
  18. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
  19. package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 2415.738b777642a02233.js} +1 -1
  20. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 3086.fb14b60ce98b53d3.js} +1 -1
  27. package/apps/pwa/out/_next/static/chunks/{3148-98efd4869d660a87.js → 3124-561f7f037943cde2.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
  31. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 3291.f6c1005387d514bd.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
  34. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
  38. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 3528.e4b8ab70d339f965.js} +2 -2
  40. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
  45. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{3031-85328a92fcce4da6.js → 4199-f7c6eb40cd0322f8.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
  57. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +90 -0
  58. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
  60. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
  63. package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
  65. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
  68. package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 5307.d7328020227880c2.js} +4 -4
  70. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
  73. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5638.107314dc479e2f37.js} +2 -2
  75. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
  80. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/{6925.562d532110879886.js → 6493.27ad77de7aac7966.js} +1 -1
  84. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +62 -0
  88. package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 7161-8f22db3ec5ed005e.js} +3 -3
  89. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 7488.966b116789f3d41a.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/{4116.a84a92a2492c080e.js → 7524.ce973525d30b3d52.js} +1 -1
  94. package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
  95. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 7628.6b16863ac3972333.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 7954.4f7a8832663ee979.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 8019.21ca554a821dad01.js} +16 -16
  102. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 8487.291666583bebe640.js} +1 -1
  107. package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 8879.ac06755bcf3e44a1.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
  111. package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 8911.bf5e712acb25fb6c.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 8994d93e.33ba491f95345fc2.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{599.c39c571b6733f2a2.js → 9223.cbcc88e0e9950426.js} +2 -2
  115. package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
  116. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
  117. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{8037.e254fd797aa224d1.js → 9581.da63ddf41acfad46.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
  121. package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/{page-e7abc34a48a6f71e.js → page-291ab19fe2acb173.js} +1 -1
  153. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-c15958835534404b.js → page-6b140f77593576eb.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → b7459770.6539b11860eb8a9c.js} +7 -7
  174. package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → b7478fef.5917716286213fcc.js} +3 -3
  175. package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/{2812ca6a.3b9f4a7a08885744.js → de8b930d.d94c0f42acf807fc.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → eaad0cba.771200940c529df7.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
  184. package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/graphs/drafts/recipes.yaml +27 -7
  279. package/graphs/release/recipes.yaml +9 -0
  280. package/graphs/release/release-loop.yaml +26 -18
  281. package/graphs/work/draft-close.yaml +54 -0
  282. package/graphs/work/green-close.yaml +37 -0
  283. package/graphs/work/recipes.yaml +46 -1
  284. package/graphs/work/run-research.yaml +35 -0
  285. package/package.json +1 -1
  286. package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
  287. package/scripts/ask-op-inbox-once.ts +17 -0
  288. package/scripts/boundary-proof-mapping-audit.ts +88 -0
  289. package/scripts/brand/check.ts +13 -4
  290. package/scripts/codex-fallback-live-probe.ts +17 -15
  291. package/scripts/fleet/node-setup.sh +32 -2
  292. package/scripts/fleet/run-light-worker.sh +9 -0
  293. package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
  294. package/scripts/gate-0226-failure-census.ts +546 -0
  295. package/scripts/goals/authoring-metrics.ts +258 -0
  296. package/scripts/graph-units/draft-close-node.ts +222 -0
  297. package/scripts/hook-order-sweep.ts +7 -4
  298. package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
  299. package/scripts/land-global-checks.ts +69 -1
  300. package/scripts/measure-nl-routing-corpus.ts +207 -2
  301. package/scripts/provision-export-redactions.ts +15 -0
  302. package/scripts/public-copy-lint.ts +122 -0
  303. package/scripts/public-export.ts +69 -2
  304. package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
  305. package/scripts/ratchets/train-side-invariants.sh +7 -1
  306. package/scripts/release-loop/cut-branch.ts +61 -12
  307. package/scripts/release-loop/docs-node.ts +140 -0
  308. package/scripts/release-loop/gate-closure.ts +48 -0
  309. package/scripts/release-loop/gate-diff.ts +2 -1
  310. package/scripts/release-loop/gate-node.ts +161 -25
  311. package/scripts/release-loop/gate-partial.ts +82 -3
  312. package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
  313. package/scripts/release-loop/gate-radius-live.ts +4 -2
  314. package/scripts/release-loop/known-issues-node.ts +6 -4
  315. package/scripts/release-loop/notes-repair.ts +216 -0
  316. package/scripts/release-loop/prepare-node.ts +61 -5
  317. package/scripts/release-loop/resume-cap.ts +2 -1
  318. package/scripts/release-loop/resume-release.ts +406 -7
  319. package/scripts/release-loop/resume-test-traffic.ts +10 -0
  320. package/scripts/release-loop/resume.ts +13 -5
  321. package/scripts/release-loop/traffic-node.ts +12 -4
  322. package/scripts/release-loop/traffic-transition.ts +53 -13
  323. package/scripts/release-loop/version-node.ts +109 -15
  324. package/scripts/train/green-leg.ts +176 -0
  325. package/scripts/tui-continue-real-evidence.ts +47 -0
  326. package/scripts/ux-sim.ts +1 -1
  327. package/scripts/video-pipeline.ts +2 -2
  328. package/src/acp/client.ts +31 -5
  329. package/src/acp/core-turn-bridge.ts +12 -1
  330. package/src/acp/stderr-summary.ts +49 -0
  331. package/src/agent/monad-agent-turn.ts +1 -0
  332. package/src/agent/run-context.ts +1 -1
  333. package/src/agent/task-notification.ts +3 -1
  334. package/src/agent/terminal-surface.ts +217 -0
  335. package/src/agent-substrate/pr-reviewer.ts +11 -3
  336. package/src/agent-substrate/review-observation.ts +10 -0
  337. package/src/agent-substrate/self-review-cli.ts +537 -57
  338. package/src/auto-research/question-ladder-contract.ts +137 -0
  339. package/src/auto-research/research-turn.ts +134 -0
  340. package/src/autopilot/discovery/doc-lint.ts +1 -1
  341. package/src/autopilot/lineage/sources.ts +1 -1
  342. package/src/autopilot/pr-manager.ts +64 -13
  343. package/src/boot/daemon-runtime.ts +35 -3
  344. package/src/boot/daemon-tools/pty-shell.ts +2 -1
  345. package/src/bots/screen-probe.ts +1 -1
  346. package/src/budget/run-usage-rollup.ts +12 -7
  347. package/src/budget/unified-usage.ts +20 -0
  348. package/src/capture/tui-self-report.ts +42 -5
  349. package/src/chat/index.ts +1 -0
  350. package/src/chat/tool-render/dispatch.ts +8 -1
  351. package/src/cli/autopilot-cli.ts +24 -9
  352. package/src/cli/decisions-cli.ts +7 -4
  353. package/src/cli/doctor-cli.ts +116 -7
  354. package/src/cli/guardian-cli.ts +3 -1
  355. package/src/cli/intake-cli.ts +48 -12
  356. package/src/cli/lesson-cli.ts +69 -9
  357. package/src/cli/logs-cli.ts +357 -2
  358. package/src/cli/memory-cli.ts +30 -1
  359. package/src/cli/msg-cli.ts +15 -11
  360. package/src/cli/pr-granularity.ts +5 -3
  361. package/src/cli/pr-land-overlap-evidence.ts +38 -5
  362. package/src/cli/pr-land-refusal.ts +1 -1
  363. package/src/cli/pty-takeover-cli.ts +58 -5
  364. package/src/cli/release-checklist-read-cli.ts +112 -4
  365. package/src/cli/release-cli.ts +89 -18
  366. package/src/cli/review-carry.ts +77 -0
  367. package/src/cli/self-update.ts +24 -6
  368. package/src/cli/self-utterances-cli.ts +13 -16
  369. package/src/cli/tasks-card-show.ts +31 -1
  370. package/src/cli/tasks-cli.ts +370 -33
  371. package/src/cli/tasks-read-cli.ts +13 -5
  372. package/src/cli/usage-cli.ts +12 -10
  373. package/src/context-bus/claude-memory-import.ts +99 -0
  374. package/src/context-bus/context-now.ts +86 -2
  375. package/src/context-bus/long-term-memory.ts +125 -0
  376. package/src/core-turn/run-core-turn.ts +9 -2
  377. package/src/core-turn/run-goal-loop.ts +5 -2
  378. package/src/core-turn/types.ts +5 -0
  379. package/src/dashboard/chat/acp-chat.ts +9 -0
  380. package/src/dashboard/index.ts +115 -30
  381. package/src/dashboard/input/agent-wake.ts +43 -0
  382. package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
  383. package/src/dashboard/input/terminal-modal-router.ts +8 -159
  384. package/src/dashboard/replay-preview.ts +25 -0
  385. package/src/dashboard/side-basic-runtime.ts +61 -0
  386. package/src/dashboard/slash-runtime/dashboard-handlers.ts +19 -8
  387. package/src/dashboard/synchronized-frame-output.ts +74 -0
  388. package/src/dashboard/term-slash-runtime.ts +2 -0
  389. package/src/dashboard/turn-preamble.ts +28 -4
  390. package/src/display/coordinator.ts +45 -12
  391. package/src/display/resize-listener.ts +41 -20
  392. package/src/display/synchronized-output-region.ts +60 -0
  393. package/src/domains/guardian-tick.ts +9 -0
  394. package/src/domains/surface-events.ts +80 -1
  395. package/src/exec-requests/planner.ts +37 -2
  396. package/src/execution-loop/launch-gate.ts +4 -3
  397. package/src/git-fs/cli-stderr.ts +45 -0
  398. package/src/git-fs/gh-cli.ts +6 -3
  399. package/src/git-fs/git-cli.ts +11 -5
  400. package/src/git-fs/watcher.ts +27 -22
  401. package/src/git-fs/worktree.ts +19 -3
  402. package/src/graph-runner/graph-cli.ts +26 -2
  403. package/src/graph-runner/graph-grow.ts +37 -9
  404. package/src/graph-runner/graph-run-api.ts +3 -2
  405. package/src/graph-runner/runner.ts +34 -7
  406. package/src/graph-wizard/generate.ts +29 -6
  407. package/src/grok/credential.ts +107 -36
  408. package/src/harness/harness-cli-command.ts +179 -33
  409. package/src/harness/review-adapter.ts +26 -6
  410. package/src/hq/fence-wrapper.ts +1 -1
  411. package/src/hq/transfer.ts +1 -1
  412. package/src/index.ts +151 -18
  413. package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
  414. package/src/intake-plane/collect-telegram-saved.ts +54 -5
  415. package/src/interactive-terminal-modal.ts +3 -0
  416. package/src/keybindings.ts +17 -22
  417. package/src/llm/provider-credentials.ts +1 -1
  418. package/src/llm/route-decision.ts +13 -0
  419. package/src/llm-tool-name.ts +37 -0
  420. package/src/llm-tool-schema.ts +55 -0
  421. package/src/llm.ts +203 -21
  422. package/src/loops/checker.ts +100 -0
  423. package/src/loops/consensus.ts +26 -2
  424. package/src/loops/loop-cli.ts +9 -4
  425. package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
  426. package/src/loops/orchestrator/inbox-once.ts +28 -0
  427. package/src/loops/orchestrator/inbox.ts +130 -1
  428. package/src/loops/orchestrator/tick.ts +55 -7
  429. package/src/maturity/feature-maturity.ts +1 -0
  430. package/src/model-tier/llm-tier-map.ts +12 -17
  431. package/src/msg/msg-store.ts +17 -0
  432. package/src/native-tool-catalog.ts +1 -1
  433. package/src/nexus/api/channel-ask-op.ts +96 -0
  434. package/src/nexus/api/discord-trigger-bot.ts +28 -1
  435. package/src/nexus/api/graph-wizard-api.ts +27 -2
  436. package/src/nexus/api/grid.ts +24 -4
  437. package/src/nexus/api/http-server.ts +1 -1
  438. package/src/nexus/api/ops-api.ts +14 -6
  439. package/src/nexus/api/telegram-trigger-bot.ts +24 -0
  440. package/src/nexus/api/terminals.ts +28 -6
  441. package/src/nexus/state/state.ts +7 -1
  442. package/src/oauth/codex-account-store.ts +34 -1
  443. package/src/ops/loops-map.ts +46 -0
  444. package/src/ops/overview-cache.ts +22 -4
  445. package/src/ops/overview.ts +41 -5
  446. package/src/patents/ledger.ts +18 -1
  447. package/src/policy/llm-policy.ts +3 -1
  448. package/src/preview/terminal.ts +4 -2
  449. package/src/prompt-cache/anthropic.ts +2 -0
  450. package/src/prompt-enhance/enhance.ts +9 -4
  451. package/src/pty-shell/availability.ts +7 -0
  452. package/src/pty-shell/herdr-agent-report.ts +40 -31
  453. package/src/pty-shell/herdr-prune-stale.ts +17 -0
  454. package/src/pty-shell/herdr-sequence-lease.ts +60 -0
  455. package/src/pty-shell/pty-control-ipc.ts +187 -18
  456. package/src/pty-shell/pty-manifest.ts +16 -2
  457. package/src/pty-shell/registry.ts +25 -15
  458. package/src/pty-shell/tui-run-state.ts +235 -1
  459. package/src/release-loop/checklist.ts +50 -5
  460. package/src/release-loop/feature-store.ts +9 -9
  461. package/src/release-loop/gate-shards.ts +61 -0
  462. package/src/release-loop/landed-but-yellow.ts +93 -12
  463. package/src/release-loop/light-rc.ts +7 -4
  464. package/src/release-loop/rehearsal.ts +1 -1
  465. package/src/repl/index.ts +18 -0
  466. package/src/research/axis-fanout.ts +133 -0
  467. package/src/research/edge-decision.ts +88 -0
  468. package/src/research/output-router.ts +127 -0
  469. package/src/research-bridge/format.ts +16 -1
  470. package/src/research-bridge/index.ts +1 -0
  471. package/src/research-bridge/invoke.ts +41 -5
  472. package/src/seat-loop/seat-report.ts +1 -0
  473. package/src/self-dev/ask-launch-flow.ts +86 -10
  474. package/src/self-dev/decompose-proposal.ts +29 -18
  475. package/src/self-dev/decompose.ts +45 -9
  476. package/src/self-dev/dev-pipeline.ts +29 -7
  477. package/src/self-dev/draft-residue.ts +221 -2
  478. package/src/self-dev/draft-sweep.ts +254 -16
  479. package/src/self-dev/draft-triage-rules.ts +19 -5
  480. package/src/self-dev/orchestrate.ts +1 -0
  481. package/src/self-dev/review-provider-fallback.ts +45 -7
  482. package/src/self-dev/run-supervisor.ts +22 -7
  483. package/src/self-dev/shard-plan.ts +48 -0
  484. package/src/self-dev/shard-run.ts +310 -6
  485. package/src/self-implement/comment-only-source.ts +54 -0
  486. package/src/self-implement/doctor-visit.ts +108 -0
  487. package/src/self-implement/gate-artifacts.ts +6 -2
  488. package/src/self-implement/gate-baseline.ts +99 -1
  489. package/src/self-implement/gate-cli.ts +231 -82
  490. package/src/self-implement/gate-failure-signature.ts +44 -0
  491. package/src/self-implement/gate-remote.ts +30 -4
  492. package/src/self-implement/gate-scope.ts +13 -1
  493. package/src/self-implement/goal-author.ts +407 -21
  494. package/src/self-implement/goal-doc/section.ts +22 -0
  495. package/src/self-implement/goal-supervisor-fill.ts +110 -27
  496. package/src/self-implement/importer-test-index.ts +215 -2
  497. package/src/self-implement/knowhow-pack.ts +125 -12
  498. package/src/self-implement/l8-merge-queue.ts +198 -32
  499. package/src/self-implement/off-diff-evidence.ts +23 -0
  500. package/src/self-implement/orchestrator.ts +369 -33
  501. package/src/self-implement/pod-inplace-worktree.ts +82 -0
  502. package/src/self-implement/pod-warm-pool-profile.ts +2 -2
  503. package/src/self-implement/premise-review.ts +7 -5
  504. package/src/self-implement/review-round-brief.ts +300 -0
  505. package/src/self-implement/rework-policy.ts +14 -0
  506. package/src/self-implement/run-ledger.ts +428 -6
  507. package/src/self-implement/run-stop.ts +1 -1
  508. package/src/self-implement/running-runs.ts +17 -3
  509. package/src/self-implement/seams.ts +45 -16
  510. package/src/self-implement/self-implement-cli.ts +26 -2
  511. package/src/self-implement/stop-autoheal.ts +1 -0
  512. package/src/self-implement/test-seams.ts +13 -1
  513. package/src/self-implement/train-reach-grouping.ts +8 -2
  514. package/src/session/channel-ask-op-envelope.ts +36 -0
  515. package/src/session/channel-op-reply-route.ts +200 -0
  516. package/src/session/chat.ts +10 -1
  517. package/src/session/id-prefix.ts +60 -0
  518. package/src/session/index.ts +6 -0
  519. package/src/session-runtime/index.ts +18 -23
  520. package/src/skills/runner.ts +7 -3
  521. package/src/skills/tools/dev-harness.ts +2 -2
  522. package/src/skills/tools/pty.ts +5 -0
  523. package/src/skills/tools/schedule-wakeup.ts +1 -6
  524. package/src/status/bar.ts +3 -3
  525. package/src/status/metrics.ts +12 -1
  526. package/src/steward/rejudge-tick.ts +12 -5
  527. package/src/steward/resync-tick.ts +31 -4
  528. package/src/storage/file-lock.ts +17 -4
  529. package/src/task-agent/actions.ts +199 -4
  530. package/src/task-agent/adopt-pr.ts +63 -2
  531. package/src/task-agent/boundary-proof-mapping.ts +12 -0
  532. package/src/task-agent/boundary-proof-producer.ts +147 -0
  533. package/src/task-agent/completion-evidence.ts +2 -1
  534. package/src/task-agent/evidence-command-normalize.ts +42 -0
  535. package/src/task-agent/export-redactions-provision.ts +43 -0
  536. package/src/task-agent/green-close-recipe.ts +239 -0
  537. package/src/task-agent/green-sweep.ts +64 -10
  538. package/src/task-agent/live-moves.ts +48 -3
  539. package/src/task-agent/map-host-adapter.ts +134 -0
  540. package/src/task-agent/map-reduce.ts +158 -0
  541. package/src/task-agent/map-run-ledger.ts +226 -0
  542. package/src/task-agent/parent-host.ts +74 -17
  543. package/src/task-agent/rejudge-on-head.ts +72 -5
  544. package/src/task-agent/repair-cycle.ts +108 -8
  545. package/src/task-agent/repair-next-move.ts +12 -2
  546. package/src/task-agent/repair-worker.ts +37 -1
  547. package/src/task-agent/review-prior-fix.ts +12 -2
  548. package/src/task-agent/shadow.ts +188 -5
  549. package/src/task-agent/task-hand.ts +253 -20
  550. package/src/task-agent/task-parent-role-llm.ts +9 -0
  551. package/src/task-agent/tier-split.ts +40 -5
  552. package/src/task-agent/work-order.ts +53 -2
  553. package/src/task-orchestrator/dispatcher.ts +46 -1
  554. package/src/task-orchestrator/generator-prompt.ts +6 -0
  555. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
  556. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
  557. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
  558. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
  559. package/src/task-orchestrator/surfaces/pod-pool.ts +77 -8
  560. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
  561. package/src/task-orchestrator/surfaces/self-implement-pod.ts +338 -79
  562. package/src/task-orchestrator/surfaces/self-implement.ts +37 -2
  563. package/src/terminal/session-registry.ts +1 -0
  564. package/src/terminal/terminal-modal-router.ts +156 -0
  565. package/src/testing/linux-env.ts +177 -0
  566. package/src/tool-hints/gate.ts +6 -4
  567. package/src/tool-hints/signals.ts +33 -1
  568. package/src/tui/chat/background-job-status.ts +8 -2
  569. package/src/tui/chat/goal-interim.ts +5 -1
  570. package/src/tui/entry.ts +722 -30
  571. package/src/tui/input/at-picker.ts +55 -0
  572. package/src/tui/sidetab/attach.ts +304 -0
  573. package/src/tui/sidetab/list.ts +176 -0
  574. package/src/tui/sidetab/nl-tool.ts +136 -0
  575. package/src/tui/slash/resume-command.ts +23 -0
  576. package/src/tui/slash/resume.ts +38 -35
  577. package/src/tui/slash/signals.ts +114 -0
  578. package/src/tui/slash/term-next.ts +72 -0
  579. package/src/tui-client/local-chat-turn.ts +31 -9
  580. package/src/user-config.ts +30 -3
  581. package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
  582. package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
  583. package/src/ux-sim/fake-gh.ts +174 -0
  584. package/src/ux-sim/fake-kubectl.ts +142 -0
  585. package/src/ux-sim/fake-llm.ts +17 -6
  586. package/src/ux-sim/next-tui-seat-scenarios.ts +176 -6
  587. package/src/ux-sim/resume-picker-device.ts +173 -0
  588. package/src/ux-sim/session-id-seed.ts +60 -0
  589. package/src/ux-sim/skills-tools-shell-device.ts +156 -0
  590. package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
  591. package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
  592. package/src/version/packed-revision.json +1 -1
  593. package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
  594. package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +0 -64
  600. package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
  601. package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
  604. package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
  609. package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
  612. package/apps/pwa/out/_next/static/chunks/2986.45d7652e4f13557e.js +0 -2
  613. package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
  614. package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
  618. package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
  619. package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
  621. package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/3757-180308bc61021b05.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
  625. package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
  629. package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
  632. package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
  634. package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
  636. package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
  641. package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
  653. package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/7481.39f7a4654907bf6e.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
  664. package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
  666. package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
  667. package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
  672. package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/ccae1c4b-0cf414f5eff1b10d.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
  739. package/scripts/migrate-monad-to-elanous.ts +0 -195
  740. package/scripts/rebrand-elanous.ts +0 -242
  741. /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
package/src/tui/entry.ts CHANGED
@@ -1,29 +1,60 @@
1
1
  import { initTui, closeTui, injectKey, readKey, type Key } from '../tui.js';
2
- import { createSession, getActiveSessionId, loadSession, resolveSessionId, setActiveSessionId } from '../session/index.js';
2
+ import { createSession, getActiveSessionId, loadSession, resolveSessionId, setActiveSessionId, updateSessionMeta } from '../session/index.js';
3
3
  import { fitLogLine, isToolFoldToggleKey, logViewLines, safeLogText, safeStatusText, streamReplyLines, toggleVisibleToolFold, toolFoldBlockStarts, wheelScroll } from './chat/log-view.js';
4
4
  import { BackgroundJobStatus } from './chat/background-job-status.js';
5
5
  import { MOUSE_RESIDUE_WINDOW_MS, MouseResidueGuard, applyComposerKey, composerViewport, emptyComposer, wheelDirection } from './input/composer.js';
6
6
  import { createInlineEditorState, type InlineEditorState } from '../input-core/inline-editor.js';
7
7
  import { isNewSessionCommand, nextTuiTitle, requestNewTuiSession } from './slash/new-session.js';
8
8
  import { COMPACT_BUSY_STATUS, COMPACT_NO_SESSION_STATUS, isCompactCommand } from './slash/compact-command.js';
9
- import { RESUME_BUSY_STATUS, parseResumeCommand, requestResumeTuiSession, resumeCandidates, resumeListLines } from './slash/resume.js';
9
+ import { RESUME_BUSY_STATUS, parseResumeCommand } from './slash/resume-command.js';
10
10
  import { reportTuiTurn } from '../pty-shell/tui-run-state.js';
11
11
  import { createPasteFold } from '../chat/paste-fold.js';
12
12
  import { createTurnTypeaheadState, dequeueTurnTypeaheadHandoff, drainTurnTypeaheadOnce, restoreTurnTypeaheadSubmission } from '../chat/turn-typeahead.js';
13
13
  import { debug } from '../debug/log.js';
14
+ import { setCliStderrSink } from '../git-fs/cli-stderr.js';
14
15
  import { createInputLagProbe } from './input-lag-probe.js';
15
16
  import type { NextTuiWakeup } from '../tui-client/next-wakeup.js';
16
17
  import { countInterimDisplay, internalTurnOriginOfText, planInterimDisplay } from './chat/goal-interim.js';
17
- import type { NextTuiSelfHealthSnapshot } from './chat/self-health-status.js';
18
18
  import { createNextLoopCommand, type NextLoopCommand } from '../tui-client/next-loop-command.js';
19
+ import { handleMissionSlash, type MissionSlashContext } from './slash/mission.js';
20
+ import { handleSignalsSlash } from './slash/signals.js';
21
+ import { updatePtyManifestSession } from '../pty-shell/pty-manifest.js';
19
22
 
20
23
  /** Status-line count of what waits for the running turn — empty when nothing waits. */
21
24
  export function nextTuiQueueSuffix(count: number): string {
22
25
  return count > 0 ? ` · 대기 ${count}` : '';
23
26
  }
24
27
 
28
+ type NextTuiTermSession = {
29
+ id: string;
30
+ title: string;
31
+ kind: string;
32
+ status: 'running' | 'backgrounded' | 'completed' | 'killed' | 'exited';
33
+ cwd?: string;
34
+ exitCode?: number | null;
35
+ };
36
+
25
37
  export interface NextTuiOptions {
26
38
  readonly resumeSessionId?: string;
39
+ readonly sidetabMode?: 'off' | 'collapsed' | 'open';
40
+ /** Read-only terminal session source; injectable so the Next slash stays testable without PTYs. */
41
+ readonly termSessions?: {
42
+ list(): readonly NextTuiTermSession[] | Promise<readonly NextTuiTermSession[]>;
43
+ };
44
+ }
45
+
46
+ const sidetabOpenBySession = new Map<string, boolean>();
47
+
48
+ interface AtPickerCandidate {
49
+ readonly label: string;
50
+ readonly absPath: string;
51
+ readonly isDir: false;
52
+ }
53
+
54
+ interface AtPickerQuery {
55
+ readonly prefix: string;
56
+ readonly start: number;
57
+ readonly end: number;
27
58
  }
28
59
 
29
60
  /** Local chat entry: history and input are TUI-owned; turn execution stays shared. */
@@ -33,9 +64,16 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
33
64
  throw new Error('elanous --tui next requires at least 20 columns and 6 rows');
34
65
  }
35
66
  const dashboardRuntime = await (await import('../tui-client/next-dashboard-runtime.js')).loadNextTuiDashboardRuntime();
36
- const requested = options.resumeSessionId ?? getActiveSessionId();
67
+ // A bare launch is a fresh human conversation. Automation CLIs share the
68
+ // active-session pointer, so only an explicit root --continue/--resume may
69
+ // attach an existing session here.
70
+ const requested = options.resumeSessionId;
37
71
  let id = requested ? resolveSessionId(requested) : null;
38
72
  if (requested && !id) throw new Error(`session not found: ${requested}`);
73
+ if (!id) {
74
+ id = createSession({ source: 'tui' }).id;
75
+ setActiveSessionId(id);
76
+ }
39
77
  let session = id ? loadSession(id) : null;
40
78
  let messages = session?.messages ?? [];
41
79
  // The seat ledger is touched only on next-TUI boot, and only when the
@@ -51,6 +89,21 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
51
89
  let scroll = 0;
52
90
  let maxScroll = 0;
53
91
  let focus: 'input' | 'log' = 'input';
92
+ let sidetabEnabled = options.sidetabMode !== 'off';
93
+ let sidetabAll = false;
94
+ let sidetabOpen = sidetabEnabled && (session?.meta.uiState?.sidetabOpen ?? sidetabOpenBySession.get(id!) ?? options.sidetabMode === 'open');
95
+ let sidetabSelected = 0;
96
+ let sidetabMode: 'list' | 'new' = 'list';
97
+ let sidetabFocused = false;
98
+ let sidetabChordPending = false;
99
+ let sidetabChordTimer: ReturnType<typeof setTimeout> | null = null;
100
+ let sidetabRemoteFrame: string | null = null;
101
+ let sidetabRows: import('./sidetab/list.js').SidetabRow[] = [];
102
+ let sidetabApi: typeof import('./sidetab/list.js') | null = null;
103
+ let sidetabAttachments: import('./sidetab/attach.js').SidetabAttachmentController | null = null;
104
+ let pendingSidetabSwitch: string | null = null;
105
+ let sidetabRefreshTimer: ReturnType<typeof setInterval> | null = null;
106
+ let paintingCoordinatorFrame = false;
54
107
  const mouseResidue = new MouseResidueGuard();
55
108
  const replay: Key[] = [];
56
109
  let escapeSnapshot: { editor: InlineEditorState; status: string; focus: 'input' | 'log'; busy: boolean } | null = null;
@@ -60,6 +113,13 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
60
113
  let historyIndex = 0;
61
114
  let draft = '';
62
115
  let activity: string[] = [];
116
+ /** Rows of the last `/resume` list — `/resume <n>` picks from what the user saw. */
117
+ let lastResumeRows: import('../session/index.js').SessionMeta[] | null = null;
118
+ let atPicker: { query: AtPickerQuery; candidates: AtPickerCandidate[]; selected: number } | null = null;
119
+ let atPickerApi: typeof import('./input/at-picker.js') | null = null;
120
+ let dismissedAtQuery = '';
121
+ const atAttachmentTokens = new Map<string, string>();
122
+ let atAttachmentOrdinal = 0;
63
123
  // Tool-output fold state, keyed by message index; long tool output renders
64
124
  // collapsed and Enter/Tab/F in the log toggles the foldable block on screen nearest the
65
125
  // bottom of the last rendered scroll window.
@@ -71,6 +131,7 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
71
131
  const backgroundJobs = new BackgroundJobStatus(id);
72
132
  const backgroundSubscription: { stop?: () => void } = {};
73
133
  const selfHealthSubscription: { stop?: () => void } = {};
134
+ let observedSessionId: string | null = null;
74
135
  let selfHealthLine: string | null = null;
75
136
  // TUI-NEXT-QUEUE-AND-WAKE — what is submitted while busy waits here (the classic FIFO state) and
76
137
  // leaves one item per settle; Esc returns it all to the prompt (classic «interrupted» drain).
@@ -95,6 +156,119 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
95
156
  const pushNotice = (line: string): void => {
96
157
  notices = [...notices, safeStatusText(line)].slice(-3);
97
158
  };
159
+ const observeSession = (
160
+ sessionId: string,
161
+ onBackground: typeof import('../tui-client/local-chat-turn.js').onLocalChatBackgroundStatus,
162
+ onSelfHealth: typeof import('../tui-client/local-chat-turn.js').onLocalChatSelfHealthStatus,
163
+ ): void => {
164
+ if (observedSessionId === sessionId) return;
165
+ backgroundSubscription.stop?.();
166
+ selfHealthSubscription.stop?.();
167
+ backgroundSubscription.stop = onBackground(sessionId, (frame) => {
168
+ if (frame === null) backgroundJobs.clear();
169
+ else backgroundJobs.accept(frame);
170
+ render();
171
+ });
172
+ selfHealthSubscription.stop = onSelfHealth(sessionId, (snapshot) => {
173
+ selfHealthLine = snapshot?.line ?? null;
174
+ render();
175
+ });
176
+ observedSessionId = sessionId;
177
+ };
178
+ const slashHandlers = new Map<string, (args: string[], context: MissionSlashContext) => Promise<void>>();
179
+ slashHandlers.set('mission', handleMissionSlash);
180
+ slashHandlers.set('signals', handleSignalsSlash);
181
+ const dispatchSlash = async (name: string, args: string[], context: MissionSlashContext): Promise<boolean> => {
182
+ const handler = slashHandlers.get(name);
183
+ if (!handler) return false;
184
+ await handler(args, context);
185
+ return true;
186
+ };
187
+ const missionWatchTimers = new Set<ReturnType<typeof setInterval>>();
188
+ let missionWatchesClosed = false;
189
+ const readyWatchIds = new Set<string>();
190
+ const runWatchIds = new Set<string>();
191
+ const startMissionReadyWatch = (missionId: string): void => {
192
+ if (readyWatchIds.has(missionId)) return;
193
+ readyWatchIds.add(missionId);
194
+ pushNotice(`미션 준비 관찰 시작: ${missionId}`);
195
+ void import('../autopilot/mission-tui-watch.js').then((watch) => {
196
+ if (missionWatchesClosed) { readyWatchIds.delete(missionId); return; }
197
+ const baseline = watch.takeMissionReadySnapshot(missionId);
198
+ let state = watch.createMissionWatchState(baseline, Date.now());
199
+ const timer = setInterval(() => {
200
+ const current = watch.takeMissionReadySnapshot(missionId);
201
+ const result = watch.advanceMissionWatch(state, current, Date.now());
202
+ state = result.state;
203
+ for (const event of result.events) {
204
+ if (event.kind === 'phases') activity.push(`미션 분해 진행 — ${event.count} 페이즈 (${missionId})`);
205
+ else if (event.kind === 'ready') {
206
+ activity.push(`미션 준비 완료 — ${event.snapshot.goal}`);
207
+ activity.push(...watch.missionDescriptionDigest(event.snapshot.description));
208
+ activity.push(...watch.renderMissionPhaseBoardLines(event.snapshot.phases, { goal: event.snapshot.goal }));
209
+ activity.push(`검토 후 /mission approve|hold ${missionId}`);
210
+ } else if (event.kind === 'resolved-elsewhere') activity.push(`미션 ${missionId} 은 다른 서피스에서 해소됨 (status=${event.status})`);
211
+ else if (event.kind === 'gone') activity.push(`미션 ${missionId} 삭제됨 · 준비 관찰 종료`);
212
+ else if (event.kind === 'timeout') activity.push(`미션 준비 관찰 타임아웃 · /mission trace ${missionId}`);
213
+ }
214
+ if (result.events.length > 0) { activity = activity.slice(-80); render(); }
215
+ if (result.done) { clearInterval(timer); missionWatchTimers.delete(timer); readyWatchIds.delete(missionId); }
216
+ }, watch.MISSION_WATCH_INTERVAL_MS);
217
+ missionWatchTimers.add(timer);
218
+ }).catch((error: unknown) => {
219
+ readyWatchIds.delete(missionId);
220
+ pushNotice(`미션 준비 관찰 실패: ${safeStatusText(error instanceof Error ? error.message : String(error))}`);
221
+ render();
222
+ });
223
+ render();
224
+ };
225
+ const startMissionRunWatch = (missionId: string): void => {
226
+ if (runWatchIds.has(missionId)) return;
227
+ runWatchIds.add(missionId);
228
+ pushNotice(`미션 실행 관찰 시작: ${missionId}`);
229
+ void import('../autopilot/mission-tui-watch.js').then((watch) => {
230
+ if (missionWatchesClosed) { runWatchIds.delete(missionId); return; }
231
+ const baseline = watch.takeMissionRunSnapshot(missionId);
232
+ let state = watch.createMissionRunWatchState(baseline, Date.now());
233
+ const timer = setInterval(() => {
234
+ const current = watch.takeMissionRunSnapshot(missionId);
235
+ const result = watch.advanceMissionRunWatch(state, current, Date.now());
236
+ state = result.state;
237
+ for (const event of result.events) {
238
+ if (event.kind === 'phase') activity.push(watch.renderMissionRunPhaseLine(event));
239
+ else if (event.kind === 'progress') activity.push(`미션 진행 ${event.phase.index + 1}/${event.total}: ${event.note}`);
240
+ else if (event.kind === 'finished') activity.push('미션 종결', ...watch.renderMissionRunReportLines(event.snapshot));
241
+ else if (event.kind === 'gone') activity.push(`미션 ${missionId} 삭제됨 · 실행 관찰 종료`);
242
+ else if (event.kind === 'timeout') activity.push(`미션 실행 관찰 타임아웃 · /mission trace ${missionId}`);
243
+ }
244
+ if (result.events.length > 0) { activity = activity.slice(-80); render(); }
245
+ if (result.done) { clearInterval(timer); missionWatchTimers.delete(timer); runWatchIds.delete(missionId); }
246
+ }, watch.MISSION_RUN_WATCH_INTERVAL_MS);
247
+ missionWatchTimers.add(timer);
248
+ if (baseline) { activity.push(watch.renderMissionRunFooter(baseline)); render(); }
249
+ }).catch((error: unknown) => {
250
+ runWatchIds.delete(missionId);
251
+ pushNotice(`미션 실행 관찰 실패: ${safeStatusText(error instanceof Error ? error.message : String(error))}`);
252
+ render();
253
+ });
254
+ render();
255
+ };
256
+ const missionContext: MissionSlashContext = {
257
+ chatLines: activity,
258
+ setChatScrollOffset: (value) => { scroll = Math.max(0, Math.min(value, maxScroll)); },
259
+ muted: (text) => text,
260
+ accent: (text) => text,
261
+ text: (text) => text,
262
+ error: (text) => text,
263
+ success: (text) => text,
264
+ warning: (text) => text,
265
+ info: (text) => text,
266
+ subtext: (text) => text,
267
+ missionTui: {
268
+ startReadyWatch: startMissionReadyWatch,
269
+ startRunWatch: startMissionRunWatch,
270
+ },
271
+ };
98
272
 
99
273
  // TURN-START-BLOCK-REST — 턴 경계 recorder: showNextTui → runLocalChatTurn 위임 턴의
100
274
  // 시작 경계(begin)와 첫 응답 경계(end · stream-open)를 세션 키로 열고 닫아
@@ -110,38 +284,221 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
110
284
  }));
111
285
 
112
286
  const render = (): void => {
287
+ if (sidetabRemoteFrame !== null) {
288
+ const columns = process.stdout.columns || 80;
289
+ const rows = process.stdout.rows || 24;
290
+ const footer = fitLogLine(` ${status} `, Math.max(1, columns));
291
+ process.stdout.write(`\x1b[H\x1b[2J${sidetabRemoteFrame}\x1b[${rows};1H\x1b[7m${footer}\x1b[0m`);
292
+ return;
293
+ }
113
294
  const columns = process.stdout.columns || 0;
114
295
  const rows = process.stdout.rows || 0;
115
296
  if (columns < 20 || rows < 6) {
116
297
  process.stdout.write(`\x1b[H\x1b[2J${fitLogLine('터미널이 너무 작습니다 · q 종료', Math.max(1, columns))}`);
117
298
  return;
118
299
  }
300
+ if (sidetabOpen && columns < 34) {
301
+ sidetabOpen = false;
302
+ sidetabMode = 'list';
303
+ status = '터미널 폭이 줄어 사이드탭을 닫았습니다';
304
+ if (sidetabRefreshTimer !== null) {
305
+ clearInterval(sidetabRefreshTimer);
306
+ sidetabRefreshTimer = null;
307
+ }
308
+ }
309
+ const sidetabWidth = sidetabOpen ? sidetabApi!.sidetabWidthForTerminal(columns) : 0;
310
+ const chatColumns = columns - sidetabWidth - (sidetabOpen ? 1 : 0);
119
311
  const backgroundLine = backgroundJobs.line();
120
312
  const footerRows = backgroundLine ? 2 : 1;
121
313
  const history = [
122
- ...logViewLines(messages, columns, expandedToolBlocks),
123
- ...notices.map((line) => fitLogLine(line, columns)),
124
- ...activity.map((line) => fitLogLine(line, columns)),
314
+ ...logViewLines(messages, chatColumns, expandedToolBlocks),
315
+ ...notices.map((line) => fitLogLine(line, chatColumns)),
316
+ ...activity.map((line) => fitLogLine(line, chatColumns)),
125
317
  ];
126
318
  const bodyRows = rows - 3 - footerRows;
127
319
  maxScroll = Math.max(0, history.length - bodyRows);
128
320
  scroll = Math.min(scroll, maxScroll);
129
321
  const start = Math.max(0, history.length - bodyRows - scroll);
130
322
  const body = history.slice(start, start + bodyRows);
131
- logWindow = { start, rows: bodyRows, columns };
132
- const title = fitLogLine(`elanous next · ${safeLogText(nextTuiTitle(session?.meta)).split('\n')[0]}`, columns);
323
+ logWindow = { start, rows: bodyRows, columns: chatColumns };
324
+ const title = fitLogLine(`elanous next · ${safeLogText(nextTuiTitle(session?.meta)).split('\n')[0]}`, chatColumns);
133
325
  const turnStatus = (!busy && focus === 'log'
134
- ? `로그 탐색 · ↑↓ 스크롤${toolFoldBlockStarts(messages, columns).length > 0 ? ' · Enter 접기/펼치기' : ''} · Esc 입력`
326
+ ? `로그 탐색 · ↑↓ 스크롤${toolFoldBlockStarts(messages, chatColumns).length > 0 ? ' · Enter 접기/펼치기' : ''} · Esc 입력`
135
327
  : status) + nextTuiQueueSuffix(queue.queuedSubmissions.length);
136
328
  const footer = backgroundLine
137
- ? [fitLogLine(backgroundLine, columns), fitLogLine(turnStatus, columns)]
138
- : [fitLogLine(turnStatus, columns)];
139
- const prompt = composerViewport(editor, columns);
140
- const header = [title, mailLine ? fitLogLine(mailLine, columns) : '─'.repeat(Math.min(columns, 80))];
141
- if (selfHealthLine) header.push(fitLogLine(selfHealthLine, columns));
329
+ ? [fitLogLine(backgroundLine, chatColumns), fitLogLine(turnStatus, chatColumns)]
330
+ : [fitLogLine(turnStatus, chatColumns)];
331
+ const prompt = composerViewport(editor, chatColumns);
332
+ const header = [title, mailLine ? fitLogLine(mailLine, chatColumns) : '─'.repeat(Math.min(chatColumns, 80))];
333
+ if (selfHealthLine) header.push(fitLogLine(selfHealthLine, chatColumns));
334
+ if (atPicker) {
335
+ const limit = Math.max(1, Math.min(6, rows - 8));
336
+ const start = Math.max(0, Math.min(atPicker.selected - limit + 1, atPicker.candidates.length - limit));
337
+ const visible = atPicker.candidates.slice(start, start + limit);
338
+ header.push(fitLogLine(visible.length ? '@ 파일 첨부 · ↑↓ 선택 · Enter 추가 · Esc 닫기' : '@ 파일 후보 없음', chatColumns));
339
+ for (const [offset, candidate] of visible.entries()) {
340
+ header.push(fitLogLine((start + offset === atPicker.selected ? '▸' : ' ') + ' ' + candidate.label, chatColumns));
341
+ }
342
+ }
142
343
  const lines = [...header, ...body, ...footer, prompt.line];
143
344
  const promptRow = lines.length;
144
- process.stdout.write(`\x1b[H\x1b[2J${lines.join('\n')}\x1b[${promptRow};${prompt.cursorCol}H\x1b[?25h`);
345
+ const sidetabLines = sidetabOpen
346
+ ? sidetabApi!.formatSidetabLines(sidetabRows, sidetabSelected, sidetabWidth, Math.max(1, rows - 1), sidetabMode)
347
+ : [];
348
+ const screenLines = sidetabOpen
349
+ ? lines.map((line, index) => `${sidetabLines[index] ?? ' '.repeat(sidetabWidth)}│${line}`)
350
+ : lines;
351
+ process.stdout.write(`\x1b[H\x1b[2J${screenLines.join('\n')}\x1b[${promptRow};${prompt.cursorCol + (sidetabOpen ? sidetabWidth + 1 : 0)}H\x1b[?25h`);
352
+ if (sidetabAttachments?.hasModal() && !paintingCoordinatorFrame) sidetabAttachments.refresh();
353
+ };
354
+
355
+ const ensureSidetabAttachments = async (): Promise<void> => {
356
+ if (sidetabAttachments) return;
357
+ sidetabAttachments = (await import('./sidetab/attach.js')).createSidetabAttachmentController({
358
+ drawBase: () => {
359
+ paintingCoordinatorFrame = true;
360
+ try { render(); } finally { paintingCoordinatorFrame = false; }
361
+ },
362
+ termSize: () => ({ cols: process.stdout.columns || 80, rows: process.stdout.rows || 24 }),
363
+ setStatus: (message) => { status = safeStatusText(message); },
364
+ drawRemoteFrame: (frame) => {
365
+ sidetabRemoteFrame = frame || null;
366
+ if (sidetabRemoteFrame !== null) {
367
+ const columns = process.stdout.columns || 80;
368
+ const rows = process.stdout.rows || 24;
369
+ const footer = fitLogLine(` ${status} `, Math.max(1, columns));
370
+ process.stdout.write(`\x1b[H\x1b[2J${sidetabRemoteFrame}\x1b[${rows};1H\x1b[7m${footer}\x1b[0m`);
371
+ }
372
+ else render();
373
+ },
374
+ });
375
+ };
376
+
377
+ const toggleSidetab = async (): Promise<void> => {
378
+ if (!sidetabEnabled) {
379
+ status = '사이드탭 off · /side on 으로 이 세션에서 켜기';
380
+ return;
381
+ }
382
+ if (!sidetabOpen && (process.stdout.columns || 0) < 34) {
383
+ status = '사이드탭은 터미널 폭 34칸 이상에서 열 수 있습니다';
384
+ return;
385
+ }
386
+ if (!sidetabApi) sidetabApi = await import('./sidetab/list.js');
387
+ sidetabRows = sidetabApi.loadSidetabRows(sidetabAll);
388
+ const current = sidetabRows.findIndex((row) => row.sessionId === id);
389
+ const next = sidetabApi.applySidetabKey({ open: sidetabOpen, selected: current >= 0 ? current : sidetabSelected }, 'toggle', sidetabRows.length);
390
+ sidetabOpen = next.open;
391
+ sidetabOpenBySession.set(id!, sidetabOpen);
392
+ updateSessionMeta(id!, (meta) => { meta.uiState = { ...meta.uiState, sidetabOpen }; });
393
+ sidetabSelected = next.selected;
394
+ sidetabMode = 'list';
395
+ if (sidetabOpen && sidetabRefreshTimer === null) {
396
+ sidetabRefreshTimer = setInterval(() => {
397
+ if (!sidetabOpen || !sidetabApi) return;
398
+ refreshSidetabRows();
399
+ render();
400
+ }, 1000);
401
+ } else if (!sidetabOpen && sidetabRefreshTimer !== null) {
402
+ clearInterval(sidetabRefreshTimer);
403
+ sidetabRefreshTimer = null;
404
+ }
405
+ };
406
+
407
+ const refreshSidetabRows = (): void => {
408
+ if (!sidetabApi) return;
409
+ const selectedId = sidetabRows[sidetabSelected]?.id;
410
+ sidetabRows = sidetabApi.loadSidetabRows(sidetabAll);
411
+ const preservedIndex = selectedId ? sidetabRows.findIndex((row) => row.id === selectedId) : -1;
412
+ sidetabSelected = preservedIndex >= 0
413
+ ? preservedIndex
414
+ : Math.min(sidetabSelected, Math.max(0, sidetabRows.length - 1));
415
+ };
416
+ const switchSidetabSession = async (requestedSessionId?: string): Promise<void> => {
417
+ const selected = sidetabRows[sidetabSelected];
418
+ const targetId = requestedSessionId ?? (selected?.kind === 'tui' ? selected.sessionId : undefined);
419
+ if (!targetId || targetId === id) return;
420
+ if (busy) {
421
+ status = '응답 중에는 세션을 전환할 수 없습니다';
422
+ return;
423
+ }
424
+ const target = loadSession(targetId);
425
+ if (!target) {
426
+ status = '세션을 읽을 수 없습니다 · 목록을 다시 열어 주세요';
427
+ return;
428
+ }
429
+ id = targetId;
430
+ session = target;
431
+ messages = target.messages;
432
+ setActiveSessionId(targetId);
433
+ updatePtyManifestSession(`tui:${process.pid}`, targetId);
434
+ backgroundJobs.setSessionId(targetId);
435
+ selfHealthLine = null;
436
+ const statusSources = await import('../tui-client/local-chat-turn.js');
437
+ observeSession(targetId, statusSources.onLocalChatBackgroundStatus, statusSources.onLocalChatSelfHealthStatus);
438
+ goalContinue?.noteHumanTurn();
439
+ lastResumeRows = null;
440
+ expandedToolBlocks.clear();
441
+ activity = [];
442
+ streamingReply = '';
443
+ scroll = 0;
444
+ maxScroll = 0;
445
+ status = '세션 전환됨 · Enter 전송 · Ctrl+Q 종료';
446
+ };
447
+ const focusSidetab = async (): Promise<void> => {
448
+ sidetabEnabled = true;
449
+ if (sidetabAttachments?.hasRemoteView()) sidetabAttachments.showMain();
450
+ if (!sidetabOpen) await toggleSidetab();
451
+ sidetabMode = 'list';
452
+ sidetabFocused = true;
453
+ status = '사이드탭 포커스 · 1–9 선택 · Esc 입력';
454
+ };
455
+ const returnToParent = (): void => {
456
+ sidetabAttachments?.showMain();
457
+ sidetabFocused = false;
458
+ focus = 'input';
459
+ status = '부모 채팅 · 입력 포커스';
460
+ };
461
+ const returnToInput = (): void => {
462
+ sidetabFocused = false;
463
+ focus = 'input';
464
+ status = '입력 포커스';
465
+ };
466
+ const selectSidetabIndex = async (index: number): Promise<void> => {
467
+ refreshSidetabRows();
468
+ if (index < 0 || index >= sidetabRows.length) {
469
+ status = `사이드탭 ${index + 1}번 항목 없음`;
470
+ return;
471
+ }
472
+ sidetabSelected = index;
473
+ const selected = sidetabRows[index]!;
474
+ if (selected.kind === 'tui') await switchSidetabSession();
475
+ else {
476
+ await ensureSidetabAttachments();
477
+ sidetabAttachments?.select(selected);
478
+ }
479
+ };
480
+
481
+ let restoreCliStderrSink: (() => void) | null = null;
482
+
483
+ const refreshAtPicker = async (): Promise<void> => {
484
+ const query = editor.text.slice(0, editor.cursor).match(/(?:^|\s)@([\p{L}\p{N}_./~\\-]*)$/u);
485
+ if (!query) {
486
+ atPicker = null;
487
+ dismissedAtQuery = '';
488
+ if (status.startsWith('@ 파일')) status = 'Enter 전송 · Esc 취소 · Ctrl+Q 종료';
489
+ return;
490
+ }
491
+ const prefix = query[1] ?? '';
492
+ const start = editor.cursor - prefix.length - 1;
493
+ const key = start + ':' + prefix;
494
+ if (dismissedAtQuery === key) { atPicker = null; return; }
495
+ if (!atPickerApi) {
496
+ atPickerApi = await import('./input/at-picker.js');
497
+ debug.log('tui.next', 'at-picker-module-loaded', { onDemand: true });
498
+ }
499
+ const candidates = await atPickerApi.listAtFiles(prefix, process.cwd());
500
+ atPicker = { query: { prefix, start, end: editor.cursor }, candidates, selected: 0 };
501
+ status = candidates.length ? '@ 파일 첨부 후보 · ↑↓ 선택 · Enter 추가' : '@ 파일 후보 없음 · 계속 입력';
145
502
  };
146
503
 
147
504
  /** Every busy path ends here: the door learns the turn is over, then the queue moves or returns to the prompt. */
@@ -181,6 +538,7 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
181
538
  activity = [];
182
539
  streamingReply = '';
183
540
  streamRenderAt = 0;
541
+ const attachments = [...atAttachmentTokens].filter(([token]) => turnText.includes(token)).map(([, path]) => path);
184
542
  if (!id) {
185
543
  id = createSession({ source: 'tui' }).id;
186
544
  setActiveSessionId(id);
@@ -209,16 +567,7 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
209
567
  turnAbort = abort;
210
568
  turnDone = import('../tui-client/local-chat-turn.js')
211
569
  .then(({ runLocalChatTurn, onLocalChatBackgroundStatus, onLocalChatSelfHealthStatus }) => {
212
- backgroundSubscription.stop ??= onLocalChatBackgroundStatus(turnSessionId, (frame) => {
213
- if (frame === null) {
214
- backgroundJobs.clear();
215
- render();
216
- } else if (backgroundJobs.accept(frame)) render();
217
- });
218
- selfHealthSubscription.stop ??= onLocalChatSelfHealthStatus(turnSessionId, (snapshot: NextTuiSelfHealthSnapshot | null) => {
219
- selfHealthLine = snapshot?.line ?? null;
220
- render();
221
- });
570
+ observeSession(turnSessionId, onLocalChatBackgroundStatus, onLocalChatSelfHealthStatus);
222
571
  let firstResponseSeen = false;
223
572
  return runLocalChatTurn(turnSessionId, turnText, abort.signal, undefined, undefined, (delta) => {
224
573
  // 첫 응답 경계: 첫 스트림 델타에서 턴 시작 트레이스를 닫는다(endedBy=stream-open).
@@ -251,6 +600,9 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
251
600
  expandedToolBlocks.clear();
252
601
  render();
253
602
  },
603
+ }, attachments, (line) => {
604
+ pushNotice(line);
605
+ render();
254
606
  });
255
607
  })
256
608
  .then(() => { status = `${compactNote}응답 완료 · Enter 전송 · Ctrl+Q 종료`; })
@@ -261,7 +613,7 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
261
613
  ? '응답 취소됨 · Enter 전송'
262
614
  : `응답 실패: ${safeStatusText(message)}`);
263
615
  })
264
- .finally(() => {
616
+ .finally(async () => {
265
617
  if (streamRenderTimer !== null) clearTimeout(streamRenderTimer);
266
618
  streamRenderTimer = null;
267
619
  session = loadSession(turnSessionId);
@@ -290,15 +642,45 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
290
642
  } else if (goalContinue && (queue.queuedSubmissions.length > 0 || editor.text.length > 0)) {
291
643
  debug.log('tui.proactive', 'yield-user-input', { queued: queue.queuedSubmissions.length, bufferedChars: editor.text.length });
292
644
  }
645
+ const switchAfterTurn = pendingSidetabSwitch;
646
+ pendingSidetabSwitch = null;
647
+ if (switchAfterTurn) await switchSidetabSession(switchAfterTurn);
293
648
  render();
294
649
  });
295
650
  };
296
651
 
652
+ if (sidetabOpen) {
653
+ sidetabApi = await import('./sidetab/list.js');
654
+ sidetabRows = sidetabApi.loadSidetabRows(sidetabAll);
655
+ sidetabRefreshTimer = setInterval(() => {
656
+ if (!sidetabApi || !sidetabOpen) return;
657
+ refreshSidetabRows();
658
+ render();
659
+ }, 1_000);
660
+ }
297
661
  initTui();
662
+ restoreCliStderrSink = setCliStderrSink(({ source, exitCode, raw }) => {
663
+ // Keep the exact bytes in the normal debug log while rendering only failures through the
664
+ // TUI-owned notice area. Writing the CLI stream to process.stderr would overwrite the prompt.
665
+ debug.log('tui.cli-stderr', 'captured', {
666
+ source,
667
+ exitCode,
668
+ text: raw.toString('utf8'),
669
+ rawBase64: raw.toString('base64'),
670
+ byteLength: raw.length,
671
+ });
672
+ if (exitCode !== 0) {
673
+ const text = raw.toString('utf8').trim() || `${source} exited with rc=${exitCode}`;
674
+ pushNotice(`[${source} stderr · rc=${exitCode}] ${text}`);
675
+ render();
676
+ }
677
+ });
298
678
  process.stdout.on('resize', render);
299
679
  try {
300
680
  {
301
681
  const { createNextTuiWakeup, setNextTuiWakeupTool } = await import('../tui-client/next-wakeup.js');
682
+ const { setNextSidetabHandler } = await import('../tui-client/local-chat-turn.js');
683
+ const { createNextSidetabHostHandler } = await import('./sidetab/nl-tool.js');
302
684
  wakeup = createNextTuiWakeup({
303
685
  isTurnRunning: () => busy,
304
686
  getBufferText: () => editor.text,
@@ -307,6 +689,28 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
307
689
  notify: (line) => { pushNotice(line); render(); },
308
690
  });
309
691
  setNextTuiWakeupTool(wakeup.tool);
692
+ setNextSidetabHandler(createNextSidetabHostHandler({
693
+ rows: async () => { if (!sidetabApi) sidetabApi = await import('./sidetab/list.js'); refreshSidetabRows(); return sidetabRows; },
694
+ selected: () => sidetabSelected,
695
+ switchSession: async (row) => {
696
+ if (!row.sessionId) return { error: '전환할 TUI 세션 id가 없습니다' };
697
+ const index = sidetabRows.findIndex((item) => item.id === row.id);
698
+ if (index < 0) return { error: '세션 목록이 갱신되어 전환을 취소했습니다' };
699
+ if (busy) {
700
+ sidetabSelected = index;
701
+ pendingSidetabSwitch = row.sessionId;
702
+ return { ok: true, action: 'switch', target: row.id, scheduled: 'after-turn' };
703
+ }
704
+ sidetabSelected = index;
705
+ await switchSidetabSession(row.sessionId);
706
+ render();
707
+ return { ok: true, action: 'switch', target: row.id };
708
+ },
709
+ attach: async (row) => { await ensureSidetabAttachments(); const ok = sidetabAttachments!.select(row); render(); return { ok, action: 'attach', target: row.id }; },
710
+ detach: () => { if (sidetabAttachments?.hasRemoteView()) sidetabAttachments.showMain(); else if (sidetabAttachments?.hasModal()) { sidetabAttachments.handleKey({ name: '\\', ctrl: true, shift: false, raw: '' }); sidetabAttachments.handleKey({ name: 'd', ctrl: false, shift: false, raw: 'd' }); } render(); return { ok: true, action: 'detach' }; },
711
+ spawn: async (character) => { await ensureSidetabAttachments(); const ok = sidetabAttachments!.spawn(character); refreshSidetabRows(); render(); return { ok, action: 'new', character }; },
712
+ kill: async (row) => { await ensureSidetabAttachments(); const ok = sidetabAttachments!.kill(row); refreshSidetabRows(); render(); return { ok, action: 'kill', target: row.id }; },
713
+ }));
310
714
  const gate = wakeup.gate;
311
715
  loopCommand = createNextLoopCommand(gate, (event, data) => debug.log('dashboard.loop', event, data));
312
716
  goalContinue = dashboardRuntime.createGoalContinue({
@@ -381,6 +785,99 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
381
785
  escapeSnapshot = null;
382
786
  }
383
787
  }
788
+ if (sidetabChordPending) {
789
+ sidetabChordPending = false;
790
+ if (sidetabChordTimer !== null) clearTimeout(sidetabChordTimer);
791
+ sidetabChordTimer = null;
792
+ if (key.name === 'up' || key.name === 'down') {
793
+ if (!sidetabApi) sidetabApi = await import('./sidetab/list.js');
794
+ refreshSidetabRows();
795
+ if (sidetabRows.length > 0) {
796
+ const delta = key.name === 'up' ? -1 : 1;
797
+ sidetabSelected = (sidetabSelected + delta + sidetabRows.length) % sidetabRows.length;
798
+ if (sidetabRows[sidetabSelected]!.kind === 'tui') await switchSidetabSession();
799
+ else {
800
+ await ensureSidetabAttachments();
801
+ sidetabAttachments?.select(sidetabRows[sidetabSelected]!);
802
+ }
803
+ }
804
+ render();
805
+ continue;
806
+ }
807
+ if (key.name.toLowerCase() === 's') {
808
+ await focusSidetab();
809
+ render();
810
+ continue;
811
+ }
812
+ if (key.name.toLowerCase() === 'p') {
813
+ returnToParent();
814
+ render();
815
+ continue;
816
+ }
817
+ if (/^[1-9]$/.test(key.name)) {
818
+ sidetabEnabled = true;
819
+ if (!sidetabOpen) await toggleSidetab();
820
+ await selectSidetabIndex(Number(key.name) - 1);
821
+ render();
822
+ continue;
823
+ }
824
+ if (key.name === 'escape') {
825
+ returnToInput();
826
+ render();
827
+ continue;
828
+ }
829
+ if (key.name.toLowerCase() === 'd' && sidetabAttachments?.hasModal()) {
830
+ sidetabAttachments.handleKey({ name: '\\', ctrl: true, shift: false });
831
+ sidetabAttachments.handleKey(key);
832
+ render();
833
+ continue;
834
+ }
835
+ if (sidetabAttachments?.hasRemoteView()) sidetabAttachments.showMain();
836
+ await toggleSidetab();
837
+ }
838
+ if (key.ctrl && key.name === '\\') {
839
+ if (!sidetabEnabled) {
840
+ status = '사이드탭 off · /side on 으로 이 세션에서 켜기';
841
+ render();
842
+ continue;
843
+ }
844
+ sidetabChordPending = true;
845
+ sidetabChordTimer = setTimeout(() => {
846
+ if (!sidetabChordPending) return;
847
+ sidetabChordPending = false;
848
+ sidetabChordTimer = null;
849
+ if (sidetabAttachments?.hasRemoteView()) sidetabAttachments.showMain();
850
+ void toggleSidetab().then(render);
851
+ }, 300);
852
+ continue;
853
+ }
854
+ if (sidetabFocused && key.name === 'escape') {
855
+ returnToInput();
856
+ render();
857
+ continue;
858
+ }
859
+ if (key.name === 'mouse' && key.mouse?.type === 'click') {
860
+ if (sidetabOpen && sidetabMode === 'list' && !sidetabAttachments?.hasRemoteView() && !sidetabAttachments?.hasModal()) {
861
+ const panelWidth = sidetabApi!.sidetabWidthForTerminal(process.stdout.columns || 0);
862
+ if (key.mouse.col <= panelWidth) {
863
+ const index = sidetabApi!.sidetabRowIndexAtTerminalRow(
864
+ sidetabRows.length,
865
+ sidetabSelected,
866
+ Math.max(1, (process.stdout.rows || 0) - 1),
867
+ key.mouse.row,
868
+ );
869
+ if (index !== null) {
870
+ await selectSidetabIndex(index);
871
+ }
872
+ }
873
+ }
874
+ render();
875
+ continue;
876
+ }
877
+ if (sidetabAttachments?.handleKey(key)) {
878
+ render();
879
+ continue;
880
+ }
384
881
  const wheel = wheelDirection(key);
385
882
  if (wheel) {
386
883
  // Wheel over the chat moves the log only; the prompt and focus stay as they were.
@@ -393,6 +890,56 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
393
890
  await turnDone;
394
891
  break;
395
892
  }
893
+ if (sidetabFocused && /^[1-9]$/.test(key.name)) {
894
+ await selectSidetabIndex(Number(key.name) - 1);
895
+ render();
896
+ continue;
897
+ }
898
+ if (sidetabFocused && key.name !== 'up' && key.name !== 'down') {
899
+ render();
900
+ continue;
901
+ }
902
+ if (sidetabOpen && sidetabMode === 'new') {
903
+ if (key.name === 'escape') {
904
+ sidetabMode = 'list';
905
+ } else {
906
+ const character = ({ s: 'shell', e: 'elanous', c: 'codex', l: 'claude' } as const)[key.name.toLowerCase() as 's' | 'e' | 'c' | 'l'];
907
+ if (character) {
908
+ await ensureSidetabAttachments();
909
+ sidetabAttachments?.spawn(character);
910
+ sidetabMode = 'list';
911
+ refreshSidetabRows();
912
+ }
913
+ }
914
+ render();
915
+ continue;
916
+ }
917
+ if (sidetabOpen && (key.name === 'up' || key.name === 'down')) {
918
+ const next = sidetabApi!.applySidetabKey({ open: sidetabOpen, selected: sidetabSelected }, key.name, sidetabRows.length);
919
+ sidetabSelected = next.selected;
920
+ if (sidetabRows[sidetabSelected]) {
921
+ if (sidetabRows[sidetabSelected]!.kind === 'tui') await switchSidetabSession();
922
+ else {
923
+ await ensureSidetabAttachments();
924
+ sidetabAttachments?.select(sidetabRows[sidetabSelected]!);
925
+ }
926
+ }
927
+ render();
928
+ continue;
929
+ }
930
+ if (sidetabOpen && editor.text.length === 0 && key.name === 'enter') {
931
+ const selected = sidetabRows[sidetabSelected];
932
+ if (selected) {
933
+ if (selected.kind === 'tui') await switchSidetabSession();
934
+ else {
935
+ await ensureSidetabAttachments();
936
+ sidetabAttachments?.select(selected);
937
+ }
938
+ refreshSidetabRows();
939
+ }
940
+ render();
941
+ continue;
942
+ }
396
943
  if (busy && (key.name === 'escape' || (key.ctrl && key.name === 'c'))) {
397
944
  turnAbort?.abort();
398
945
  interrupted = true;
@@ -427,6 +974,33 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
427
974
  render();
428
975
  continue;
429
976
  }
977
+ const activeAtPicker = atPicker as { query: AtPickerQuery; candidates: AtPickerCandidate[]; selected: number } | null;
978
+ if (!busy && focus === 'input' && activeAtPicker) {
979
+ if (key.name === 'escape') {
980
+ dismissedAtQuery = activeAtPicker.query.start + ':' + activeAtPicker.query.prefix;
981
+ atPicker = null;
982
+ status = '파일 선택 닫힘 · Enter 전송';
983
+ render();
984
+ continue;
985
+ }
986
+ if ((key.name === 'up' || key.name === 'down') && activeAtPicker.candidates.length > 0) {
987
+ activeAtPicker.selected = (activeAtPicker.selected + (key.name === 'up' ? -1 : 1) + activeAtPicker.candidates.length) % activeAtPicker.candidates.length;
988
+ render();
989
+ continue;
990
+ }
991
+ if ((key.name === 'enter' || key.name === 'return') && !key.shift && activeAtPicker.candidates[activeAtPicker.selected]) {
992
+ const candidate = activeAtPicker.candidates[activeAtPicker.selected]!;
993
+ const picked = atPickerApi!.acceptAtFile(editor.text, activeAtPicker.query, candidate, ++atAttachmentOrdinal);
994
+ editor = { text: picked.text, cursor: picked.cursor };
995
+ atAttachmentTokens.set(picked.token, candidate.absPath);
996
+ atPicker = null;
997
+ dismissedAtQuery = '';
998
+ status = '파일 첨부 추가됨 · Enter 전송';
999
+ debug.log('tui.next', 'at-picker-selected', { path: candidate.absPath });
1000
+ render();
1001
+ continue;
1002
+ }
1003
+ }
430
1004
  if (busy) {
431
1005
  const pending = applyComposerKey(editor, key);
432
1006
  editor = pending.state;
@@ -478,6 +1052,8 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
478
1052
  focus = 'input';
479
1053
  const result = applyComposerKey(editor, key);
480
1054
  editor = result.state;
1055
+ if (result.action === 'edit') await refreshAtPicker();
1056
+ else if (result.action === 'submit' || result.action === 'cancel' || result.action === 'quit') atPicker = null;
481
1057
  if (restoreDraft !== null) {
482
1058
  // A queued submission just left through this Enter; what the person was typing comes back.
483
1059
  if (result.action === 'submit') editor = createInlineEditorState(restoreDraft);
@@ -510,6 +1086,7 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
510
1086
  await closeLocalChatSession(previous);
511
1087
  }
512
1088
  id = next.id;
1089
+ lastResumeRows = null;
513
1090
  session = loadSession(id);
514
1091
  messages = [];
515
1092
  expandedToolBlocks.clear();
@@ -556,14 +1133,17 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
556
1133
  }
557
1134
  const resumeCommand = parseResumeCommand(submitted);
558
1135
  if (resumeCommand?.kind === 'list') {
559
- activity = resumeListLines(resumeCandidates(id), id).map(safeStatusText);
560
- status = '/resume <id 앞자리> 로 이어 가기 · Enter 전송';
1136
+ const { resumeCandidates, resumeListLines } = await import('./slash/resume.js');
1137
+ lastResumeRows = resumeCandidates(id);
1138
+ activity = resumeListLines(lastResumeRows, id).map(safeStatusText);
1139
+ status = '/resume <번호|id 앞자리> 로 이어 가기 · Enter 전송';
561
1140
  debug.log('tui.next', 'session-resume-list', { from: id, rows: activity.length });
562
1141
  render();
563
1142
  continue;
564
1143
  }
565
1144
  if (resumeCommand?.kind === 'load') {
566
- const next = requestResumeTuiSession({ busy, from: id, prefix: resumeCommand.prefix });
1145
+ const { requestResumeTuiSession, resumeCandidates } = await import('./slash/resume.js');
1146
+ const next = requestResumeTuiSession({ busy, from: id, prefix: resumeCommand.prefix, rows: lastResumeRows ?? resumeCandidates(id) });
567
1147
  if (next.kind === 'started') {
568
1148
  loopCommand?.run('stop');
569
1149
  const previous = id;
@@ -577,6 +1157,7 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
577
1157
  await closeLocalChatSession(previous);
578
1158
  }
579
1159
  id = next.id;
1160
+ lastResumeRows = null;
580
1161
  session = loadSession(id);
581
1162
  messages = session?.messages ?? [];
582
1163
  expandedToolBlocks.clear();
@@ -664,6 +1245,105 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
664
1245
  render();
665
1246
  continue;
666
1247
  }
1248
+ if (submitted === '/help' || submitted === '/help next') {
1249
+ activity.push(
1250
+ 'Next TUI: /side · /sidetab — 세션/PTY 목록',
1251
+ '사이드탭: Ctrl+\\ 토글 · ↑↓ 선택 · 빈 prompt Enter=attach · /side new · /side kill',
1252
+ '새 PTY: s shell · e elanous · c codex 구독 · l claude code 구독',
1253
+ 'PTY 분리: Ctrl+\\ 후 d · /term help 는 읽기 전용 목록 명령',
1254
+ );
1255
+ status = 'Enter 전송';
1256
+ render();
1257
+ continue;
1258
+ }
1259
+ if (submitted === '/side' || submitted === '/sidetab' || submitted.startsWith('/side ') || submitted.startsWith('/sidetab ')) {
1260
+ const args = submitted.slice(1).trim().split(/\s+/);
1261
+ const action = args[1]?.toLowerCase();
1262
+ if (action === 'help') {
1263
+ activity.push('/side [open|close|off|on|all|new|kill|help] · /sidetab 별칭', 'Ctrl+\\ 후 s=사이드탭 · p=부모 · 1–9=선택 · Esc=입력 · 목록 클릭=전환');
1264
+ status = 'Enter 전송';
1265
+ } else if (action === 'off') {
1266
+ const restoreOpen = sidetabOpen;
1267
+ if (sidetabOpen) await toggleSidetab();
1268
+ sidetabEnabled = false;
1269
+ if (restoreOpen) {
1270
+ sidetabOpenBySession.set(id!, true);
1271
+ updateSessionMeta(id!, (meta) => { meta.uiState = { ...meta.uiState, sidetabOpen: true }; });
1272
+ }
1273
+ status = '사이드탭 off · /side on 으로 이 세션에서 켜기';
1274
+ } else if (action === 'on') {
1275
+ sidetabEnabled = true;
1276
+ if (sidetabOpenBySession.get(id!) === true && !sidetabOpen) await toggleSidetab();
1277
+ status = sidetabOpen ? '사이드탭 on · 열림' : '사이드탭 on · /side open 으로 열기';
1278
+ } else if (action === 'open') {
1279
+ sidetabEnabled = true;
1280
+ if (!sidetabOpen) await toggleSidetab();
1281
+ } else if (action === 'close') {
1282
+ if (sidetabOpen) await toggleSidetab();
1283
+ } else if (action === 'all') {
1284
+ sidetabAll = !sidetabAll;
1285
+ sidetabEnabled = true;
1286
+ if (!sidetabOpen) await toggleSidetab();
1287
+ else refreshSidetabRows();
1288
+ status = sidetabAll ? '사이드탭 전체 목록' : '사이드탭 현재 세션 목록';
1289
+ } else if (action === 'kill') {
1290
+ if (!sidetabApi) sidetabApi = await import('./sidetab/list.js');
1291
+ refreshSidetabRows();
1292
+ const selected = sidetabRows[sidetabSelected];
1293
+ if (selected) {
1294
+ await ensureSidetabAttachments();
1295
+ sidetabAttachments?.kill(selected);
1296
+ refreshSidetabRows();
1297
+ } else {
1298
+ status = '종료할 PTY가 없습니다';
1299
+ }
1300
+ } else if (action === 'new') {
1301
+ sidetabEnabled = true;
1302
+ if (!sidetabOpen) await toggleSidetab();
1303
+ if (sidetabOpen) sidetabMode = 'new';
1304
+ } else {
1305
+ await toggleSidetab();
1306
+ }
1307
+ render();
1308
+ continue;
1309
+ }
1310
+ if (submitted === '/term' || submitted.startsWith('/term ') || submitted === '/terminal' || submitted.startsWith('/terminal ')) {
1311
+ const { dispatchNextTermSlash } = await import('./slash/term-next.js');
1312
+ const args = submitted.slice('/'.length).trim().split(/\s+/).slice(1);
1313
+ const sessions = options.termSessions ?? {
1314
+ list: async () => {
1315
+ const { listPty } = await import('../pty-shell/registry.js');
1316
+ return listPty().map((handle) => ({
1317
+ id: handle.id,
1318
+ title: handle.nickname ?? handle.cmd,
1319
+ kind: handle.kind,
1320
+ status: handle.isAlive() ? 'running' as const : 'exited' as const,
1321
+ ...(handle.workdir === undefined ? {} : { cwd: handle.workdir }),
1322
+ exitCode: handle.exitCode,
1323
+ }));
1324
+ },
1325
+ };
1326
+ await dispatchNextTermSlash(args, {
1327
+ chatLines: activity,
1328
+ setChatScrollOffset: (value) => { scroll = Math.max(0, Math.min(value, maxScroll)); },
1329
+ sessions,
1330
+ });
1331
+ status = 'Enter 전송';
1332
+ render();
1333
+ continue;
1334
+ }
1335
+ if (
1336
+ submitted === '/mission' || submitted.startsWith('/mission ')
1337
+ || submitted === '/signals' || submitted.startsWith('/signals ')
1338
+ ) {
1339
+ missionContext.chatLines = activity;
1340
+ const [command = '', ...args] = submitted.slice('/'.length).trim().split(/\s+/);
1341
+ const dispatched = await dispatchSlash(command, args, missionContext);
1342
+ if (!dispatched) activity.push('알 수 없는 슬래시 명령');
1343
+ status = 'Enter 전송';
1344
+ render();
1345
+ continue;
1346
+ }
667
1347
  // A person's turn: an internal turn opened but not yet run gives way, and the door's «last turn» moves.
668
1348
  wakeup?.gate.port.declined?.('human-turn');
669
1349
  wakeup?.gate.noteHumanTurn();
@@ -673,13 +1353,25 @@ export async function showNextTui(options: NextTuiOptions = {}): Promise<void> {
673
1353
  render();
674
1354
  }
675
1355
  } finally {
1356
+ if (sidetabRefreshTimer !== null) clearInterval(sidetabRefreshTimer);
1357
+ if (sidetabChordTimer !== null) clearTimeout(sidetabChordTimer);
1358
+ sidetabAttachments?.close();
1359
+ restoreCliStderrSink?.();
1360
+ restoreCliStderrSink = null;
676
1361
  if (residueTimer !== null) clearTimeout(residueTimer);
677
1362
  loopCommand?.dispose();
1363
+ missionWatchesClosed = true;
1364
+ for (const timer of missionWatchTimers) clearInterval(timer);
1365
+ missionWatchTimers.clear();
1366
+ readyWatchIds.clear();
1367
+ runWatchIds.clear();
678
1368
  wakeup?.dispose();
679
1369
  if (wakeup) {
680
1370
  const { setNextTuiWakeupTool } = await import('../tui-client/next-wakeup.js');
681
1371
  setNextTuiWakeupTool(null);
682
1372
  }
1373
+ const { setNextSidetabHandler } = await import('../tui-client/local-chat-turn.js');
1374
+ setNextSidetabHandler(null);
683
1375
  turnAbort?.abort();
684
1376
  await turnDone;
685
1377
  backgroundSubscription.stop?.();