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
@@ -0,0 +1,23 @@
1
+ /** Lightweight `/resume` and `/session` command parsing for Next TUI startup. */
2
+ export const RESUME_BUSY_STATUS = '응답 중에는 /resume 을 받지 않습니다 · 완료(또는 Esc 취소) 뒤 다시';
3
+ /** Rows shown by `/resume` and `/session list`. */
4
+ export const RESUME_LIST_LIMIT = 12;
5
+
6
+ export type ResumeCommand =
7
+ | { readonly kind: 'list' }
8
+ | { readonly kind: 'load'; readonly prefix: string };
9
+
10
+ /** `/resume` · `/session` · `/session list|ls` → list; `/resume <id>` · `/session load|resume <id>` → load. */
11
+ export function parseResumeCommand(text: string): ResumeCommand | null {
12
+ const [cmd, sub, arg, ...rest] = text.trim().split(/\s+/);
13
+ if (rest.length > 0) return null;
14
+ if (cmd === '/resume') {
15
+ if (arg !== undefined) return null;
16
+ return sub === undefined ? { kind: 'list' } : { kind: 'load', prefix: sub };
17
+ }
18
+ if (cmd === '/session' || cmd === '/sessions') {
19
+ if (sub === undefined || ((sub === 'list' || sub === 'ls') && arg === undefined)) return { kind: 'list' };
20
+ if ((sub === 'load' || sub === 'resume') && arg !== undefined) return { kind: 'load', prefix: arg };
21
+ }
22
+ return null;
23
+ }
@@ -3,73 +3,76 @@
3
3
  // n8n restart «/resume» started an investigation instead of showing the sessions to pick from.
4
4
  import { debug } from '../../debug/log.js';
5
5
  import { listSessions, resolveSessionId, setActiveSessionId, type SessionMeta } from '../../session/index.js';
6
-
7
- export const RESUME_BUSY_STATUS = '응답 중에는 /resume 을 받지 않습니다 · 완료(또는 Esc 취소) 뒤 다시';
8
- /** Rows shown by `/resume` · `/session list`. */
9
- export const RESUME_LIST_LIMIT = 12;
10
-
11
- export type ResumeCommand =
12
- | { readonly kind: 'list' }
13
- | { readonly kind: 'load'; readonly prefix: string };
14
-
15
- /** `/resume` · `/session` · `/session list|ls` → list; `/resume <id>` · `/session load|resume <id>` → load. */
16
- export function parseResumeCommand(text: string): ResumeCommand | null {
17
- const [cmd, sub, arg, ...rest] = text.trim().split(/\s+/);
18
- if (rest.length > 0) return null;
19
- if (cmd === '/resume') {
20
- if (arg !== undefined) return null;
21
- return sub === undefined ? { kind: 'list' } : { kind: 'load', prefix: sub };
22
- }
23
- if (cmd === '/session' || cmd === '/sessions') {
24
- if (sub === undefined || ((sub === 'list' || sub === 'ls') && arg === undefined)) return { kind: 'list' };
25
- if ((sub === 'load' || sub === 'resume') && arg !== undefined) return { kind: 'load', prefix: arg };
26
- }
27
- return null;
28
- }
6
+ import { RESUME_BUSY_STATUS, RESUME_LIST_LIMIT } from './resume-command.js';
7
+ import { idPrefixCell, sessionIdPrefixes, sessionListTime } from '../../session/id-prefix.js';
8
+ export { RESUME_BUSY_STATUS, RESUME_LIST_LIMIT, parseResumeCommand } from './resume-command.js';
9
+ export type { ResumeCommand } from './resume-command.js';
29
10
 
30
11
  /** Recent conversations, newest first — the rows `/resume` shows (empty scratch sessions hidden, the active one kept). */
31
12
  export function resumeCandidates(activeId: string | null, limit = RESUME_LIST_LIMIT): SessionMeta[] {
32
13
  return listSessions({ limit, hideEmpty: true, ...(activeId ? { keepIds: [activeId] } : {}) });
33
14
  }
34
15
 
35
- /** One line per session: marker · 8-char id · updated · turns · title. */
16
+ /**
17
+ * One numbered line per session: number · marker · unique id prefix · updated · turns · title.
18
+ * The number is what `/resume <n>` takes (next TUI has no arrow picker — the list is the picker);
19
+ * the prefix grows past 8 characters when another stored session shares them.
20
+ */
36
21
  export function resumeListLines(rows: readonly SessionMeta[], activeId: string | null): string[] {
37
22
  if (rows.length === 0) return ['저장된 대화 없음'];
23
+ const prefixes = sessionIdPrefixes(rows.map((m) => m.id));
24
+ const numberWidth = String(rows.length).length;
38
25
  return [
39
- `최근 대화 ${rows.length}개 · /resume <id 앞자리> 로 이어 가기`,
40
- ...rows.map((m) => {
26
+ `최근 대화 ${rows.length}개 · /resume <번호> 또는 /resume <id 앞자리> 로 이어 가기`,
27
+ ...rows.map((m, i) => {
41
28
  const marker = m.id === activeId ? '▸' : ' ';
42
- const when = m.updatedAt.slice(5, 16).replace('T', ' ');
29
+ const when = sessionListTime(m.updatedAt);
43
30
  const title = (m.title || '(제목 없음)').split('\n')[0]!.slice(0, 48);
44
- return `${marker} ${m.id.slice(0, 8)} ${when} ${String(m.messageCount).padStart(3)}t ${title}`;
31
+ return `${String(i + 1).padStart(numberWidth)}. ${marker} ${idPrefixCell(prefixes, m.id)} ${when} ${String(m.messageCount).padStart(3)}t ${title}`;
45
32
  }),
46
33
  ];
47
34
  }
48
35
 
36
+ /** `/resume 3` → the 3rd row of the list the user saw. Only 1–3 digits within the list count as a number. */
37
+ export function resumeRowByNumber(arg: string, rows: readonly SessionMeta[]): SessionMeta | null {
38
+ if (!/^\d{1,3}$/.test(arg)) return null;
39
+ const n = Number(arg);
40
+ return n >= 1 && n <= rows.length ? rows[n - 1]! : null;
41
+ }
42
+
49
43
  export type ResumeTuiSessionResult =
50
44
  | { readonly kind: 'started'; readonly id: string; readonly status: string }
51
45
  | { readonly kind: 'rejected'; readonly status: string };
52
46
 
53
47
  /** Resolve the prefix and make that session active; rejects while a turn runs or when the prefix misses. */
54
- export function requestResumeTuiSession(input: { readonly busy: boolean; readonly from: string | null; readonly prefix: string }): ResumeTuiSessionResult {
48
+ export function requestResumeTuiSession(input: {
49
+ readonly busy: boolean;
50
+ readonly from: string | null;
51
+ readonly prefix: string;
52
+ /** The rows the last `/resume` list showed, so `/resume <n>` picks the row the user saw. */
53
+ readonly rows?: readonly SessionMeta[];
54
+ }): ResumeTuiSessionResult {
55
55
  const { busy, from, prefix } = input;
56
56
  if (busy) {
57
57
  debug.log('tui.next', 'session-resume-rejected', { from, prefix, reason: 'busy' });
58
58
  return { kind: 'rejected', status: RESUME_BUSY_STATUS };
59
59
  }
60
- let id: string | null;
60
+ const byNumber = input.rows ? resumeRowByNumber(prefix, input.rows) : null;
61
+ let id: string | null = byNumber?.id ?? null;
61
62
  try {
62
- id = resolveSessionId(prefix);
63
+ if (!byNumber) id = resolveSessionId(prefix);
63
64
  } catch (error) {
64
65
  debug.log('tui.next', 'session-resume-rejected', { from, prefix, reason: 'ambiguous' });
65
66
  return { kind: 'rejected', status: error instanceof Error ? error.message : String(error) };
66
67
  }
67
68
  if (!id) {
68
69
  debug.log('tui.next', 'session-resume-rejected', { from, prefix, reason: 'not-found' });
69
- return { kind: 'rejected', status: `"${prefix}" 로 시작하는 대화 없음 · /resume 으로 목록 보기` };
70
+ return { kind: 'rejected', status: `"${prefix}" 번호·앞자리에 맞는 대화 없음 · /resume 으로 목록 보기` };
70
71
  }
71
- if (id === from) return { kind: 'rejected', status: `이미 이 대화다 · ${id.slice(0, 8)}` };
72
+ const shortId = sessionIdPrefixes([id]).get(id) ?? id;
73
+ if (id === from) return { kind: 'rejected', status: `이미 이 대화다 · ${shortId}` };
72
74
  setActiveSessionId(id);
73
- debug.log('tui.next', 'session-resume', { from, to: id });
74
- return { kind: 'started', id, status: `대화 이어 가기 · ${id.slice(0, 8)} · 이전 = ${from ? from.slice(0, 8) : '없음'}` };
75
+ debug.log('tui.next', 'session-resume', { from, to: id, by: byNumber ? 'number' : 'prefix' });
76
+ const shortFrom = from ? (sessionIdPrefixes([from]).get(from) ?? from) : '없음';
77
+ return { kind: 'started', id, status: `대화 이어 가기 · ${shortId} · 이전 = ${shortFrom}` };
75
78
  }
@@ -0,0 +1,114 @@
1
+ // TUI-SLASH-SIGNALS — Next TUI `/signals` 슬래시 묶음(관측 전용).
2
+ //
3
+ // classic 의 /signals 는 dashboard 전용 registry/runtime 에 살지만, 이 handler 는 Next TUI 가
4
+ // 직접 소유한다. src/input/control-signal-observer.ts 의 실제 defaultControlSignalObserver()
5
+ // 싱글턴에서 읽기 API(list·latest·countsByKind)만 소비한다 — observer mutation(clear·detach)과
6
+ // signal emission(버스 발행)은 명시적으로 범위 밖이며, dashboard/index.ts 는 import 하지 않는다.
7
+
8
+ import { defaultControlSignalObserver } from '../../input/control-signal-observer.js';
9
+ import type { ControlSignal } from '../../input/control-signal.js';
10
+
11
+ /** `/signals`가 ctx 에서 쓰는 것만(구조 타입 — NextTuiContext 가 이 계약을 만족한다). */
12
+ export interface SignalsSlashContext {
13
+ chatLines: string[];
14
+ setChatScrollOffset(value: number): void;
15
+ muted(text: string): string;
16
+ accent(text: string): string;
17
+ text(text: string): string;
18
+ error(text: string): string;
19
+ warning(text: string): string;
20
+ info(text: string): string;
21
+ }
22
+
23
+ const SIGNALS_USAGE = 'usage: /signals [help|status|latest|list [kind]]';
24
+
25
+ function signalClock(createdAt: string): string {
26
+ return createdAt.slice(11, 19);
27
+ }
28
+
29
+ /** 관측된 신호 한 줄 요약 — 관측 API가 보증하는 필드(kind·urgency·createdAt·scope.sessionId)만 읽는다. */
30
+ function signalSummary(signal: ControlSignal): string {
31
+ const sessionId = signal.scope?.sessionId;
32
+ return `[${signal.urgency}] ${signal.kind} · ${signalClock(signal.createdAt)}${sessionId ? ` · session ${sessionId}` : ''}`;
33
+ }
34
+
35
+ function signalsHelp(ctx: SignalsSlashContext): void {
36
+ ctx.chatLines.push(ctx.accent('❯ /signals help'));
37
+ ctx.chatLines.push(ctx.warning(` ${SIGNALS_USAGE}`));
38
+ ctx.chatLines.push(ctx.muted(' · status — 종류별 관측 신호 수 요약'));
39
+ ctx.chatLines.push(ctx.muted(' · latest — 최신 신호 1건'));
40
+ ctx.chatLines.push(ctx.muted(' · list [kind] — 신호 목록(선택 kind 필터)'));
41
+ ctx.chatLines.push(ctx.muted(' · clear·emit 은 관측 전용 경계상 이 명령 범위 밖입니다'));
42
+ ctx.setChatScrollOffset(-1);
43
+ }
44
+
45
+ function signalsStatus(ctx: SignalsSlashContext): void {
46
+ ctx.chatLines.push(ctx.accent('❯ /signals status'));
47
+ const counts = defaultControlSignalObserver().countsByKind();
48
+ const kinds = Object.keys(counts).sort();
49
+ const total = kinds.reduce((sum, kind) => sum + (counts[kind] ?? 0), 0);
50
+ if (total === 0) {
51
+ ctx.chatLines.push(ctx.muted(' 관측된 신호 없음 (총 0건)'));
52
+ ctx.setChatScrollOffset(-1);
53
+ return;
54
+ }
55
+ ctx.chatLines.push(ctx.text(` 신호 총 ${total}건 · 종류 ${kinds.length}종`));
56
+ for (const kind of kinds) {
57
+ ctx.chatLines.push(ctx.muted(` · ${kind} ×${counts[kind] ?? 0}`));
58
+ }
59
+ ctx.setChatScrollOffset(-1);
60
+ }
61
+
62
+ function signalsLatest(ctx: SignalsSlashContext): void {
63
+ ctx.chatLines.push(ctx.accent('❯ /signals latest'));
64
+ const latest = defaultControlSignalObserver().latest();
65
+ if (!latest) {
66
+ ctx.chatLines.push(ctx.muted(' 최신 신호 없음 — 아직 관측된 control-signal 이 없습니다'));
67
+ } else {
68
+ ctx.chatLines.push(` ${ctx.info(signalSummary(latest))}`);
69
+ }
70
+ ctx.setChatScrollOffset(-1);
71
+ }
72
+
73
+ function signalsList(args: string[], ctx: SignalsSlashContext): void {
74
+ const kind = (args[1] ?? '').trim();
75
+ const signals = defaultControlSignalObserver().list(kind ? { kind } : undefined);
76
+ ctx.chatLines.push(ctx.accent(`❯ /signals list${kind ? ` ${kind}` : ''} (${signals.length}건)`));
77
+ if (signals.length === 0) {
78
+ ctx.chatLines.push(ctx.muted(' 관측된 신호 없음'));
79
+ }
80
+ for (const [index, signal] of signals.entries()) {
81
+ ctx.chatLines.push(` ${ctx.muted(`${index + 1}. ${signalSummary(signal)}`)}`);
82
+ }
83
+ ctx.setChatScrollOffset(-1);
84
+ }
85
+
86
+ /** `/signals` 본체 — 관측 전용. help·status·latest·list 만 실행하고 clear·emit 은 거절한다. */
87
+ export async function handleSignalsSlash(args: string[], ctx: SignalsSlashContext): Promise<void> {
88
+ const sub = (args[0] ?? 'status').toLowerCase();
89
+ ctx.chatLines.push('');
90
+ if (sub === 'help') {
91
+ signalsHelp(ctx);
92
+ return;
93
+ }
94
+ if (sub === 'status') {
95
+ signalsStatus(ctx);
96
+ return;
97
+ }
98
+ if (sub === 'latest') {
99
+ signalsLatest(ctx);
100
+ return;
101
+ }
102
+ if (sub === 'list') {
103
+ signalsList(args, ctx);
104
+ return;
105
+ }
106
+ ctx.chatLines.push(ctx.accent(`❯ /signals ${sub}`));
107
+ if (sub === 'clear' || sub === 'emit') {
108
+ ctx.chatLines.push(ctx.error(` ✗ out of scope — /signals는 관측 전용입니다 (${sub} 미지원)`));
109
+ } else {
110
+ ctx.chatLines.push(ctx.warning(` unknown subcommand: ${sub}`));
111
+ }
112
+ ctx.chatLines.push(ctx.warning(` ${SIGNALS_USAGE}`));
113
+ ctx.setChatScrollOffset(-1);
114
+ }
@@ -0,0 +1,72 @@
1
+ /** Read-only terminal view exposed to the Next TUI. Tests can inject an isolated fake. */
2
+ export interface NextTuiTermSession {
3
+ readonly id: string;
4
+ readonly title: string;
5
+ readonly kind: string;
6
+ readonly status: 'running' | 'backgrounded' | 'completed' | 'killed' | 'exited';
7
+ readonly cwd?: string;
8
+ readonly exitCode?: number | null;
9
+ }
10
+
11
+ export interface NextTuiTermSlashContext {
12
+ readonly chatLines: string[];
13
+ readonly setChatScrollOffset: (value: number) => void;
14
+ readonly sessions: { list(): readonly NextTuiTermSession[] | Promise<readonly NextTuiTermSession[]> };
15
+ }
16
+
17
+ const isLive = (session: NextTuiTermSession): boolean =>
18
+ session.status === 'running' || session.status === 'backgrounded';
19
+
20
+ const unknownOrValue = (value: string | number | null | undefined): string =>
21
+ value === null || value === undefined || value === '' ? 'unknown' : String(value);
22
+
23
+ function sessionLines(sessions: readonly NextTuiTermSession[]): string[] {
24
+ if (sessions.length === 0) return [' No terminal sessions.'];
25
+ return sessions.map((session) => {
26
+ const exit = isLive(session) ? 'not-exited' : unknownOrValue(session.exitCode);
27
+ return ` ${session.status.padEnd(12)} ${session.id.slice(-8)} ${session.title} · cwd=${unknownOrValue(session.cwd)} · exitCode=${exit}`;
28
+ });
29
+ }
30
+
31
+ function matrixLines(sessions: readonly NextTuiTermSession[]): string[] {
32
+ if (sessions.length === 0) return [' No terminal sessions.'];
33
+ return [
34
+ ' term:ID character transport placement groups title',
35
+ ...sessions.map((session) => {
36
+ const dead = isLive(session) ? '' : ' exited';
37
+ return ` ${session.id.padEnd(10)} ${session.kind.padEnd(12)} pty pty - ${session.title}${dead}`;
38
+ }),
39
+ ];
40
+ }
41
+
42
+ /** Next TUI exposes only read-only terminal inventory and status. */
43
+ export async function handleNextTuiTermSlash(args: string[], context: NextTuiTermSlashContext): Promise<void> {
44
+ const command = (args[0] ?? 'help').trim().toLowerCase();
45
+ if (command === '' || command === 'help') {
46
+ context.chatLines.push(
47
+ ' /term help Show Next TUI terminal commands.',
48
+ ' /term list List terminal sessions.',
49
+ ' /term status Show live/exited session counts.',
50
+ ' /term matrix Show terminal transport and liveness.',
51
+ ' /side Open the Next TUI session/PTY sidetab.',
52
+ ' Unknown cwd or exit codes are shown as unknown.',
53
+ ' Next TUI mutations use explicit /side new and /side kill commands.',
54
+ );
55
+ } else if (command === 'status') {
56
+ const sessions = await context.sessions.list();
57
+ const live = sessions.filter(isLive).length;
58
+ const exited = sessions.length - live;
59
+ context.chatLines.push(` Terminal sessions: ${live} live · ${exited} exited.`);
60
+ } else if (command === 'list' || command === 'matrix') {
61
+ const sessions = await context.sessions.list();
62
+ context.chatLines.push(...(command === 'list' ? sessionLines(sessions) : matrixLines(sessions)));
63
+ } else {
64
+ context.chatLines.push(` Unsupported /term command in Next TUI: ${command}. Try /term help.`);
65
+ }
66
+ context.setChatScrollOffset(-1);
67
+ }
68
+
69
+ /** The entry point reaches this only for `/term` or `/terminal` input. */
70
+ export async function dispatchNextTermSlash(args: string[], context: NextTuiTermSlashContext): Promise<void> {
71
+ await handleNextTuiTermSlash(args, context);
72
+ }
@@ -2,8 +2,14 @@
2
2
  import type { NextTuiCompactDeps, NextTuiCompactOutcome } from '../tui/slash/compact.js';
3
3
  import { NEXT_TUI_WAKEUP_IPC_ENV, answerWakeupCall, isWakeupCallMessage, nextTuiWakeupTool } from './next-wakeup.js';
4
4
  import { isNextTuiSelfHealthSnapshot, type NextTuiSelfHealthSnapshot } from '../tui/chat/self-health-status.js';
5
+ import { answerNextSidetabCall, isNextSidetabCall, type NextSidetabHandler } from '../tui/sidetab/nl-tool.js';
5
6
 
6
7
  const STATUS_PREFIX = 'ELANOUS_TUI_BG_STATUS\t';
8
+ let nextSidetabHandler: NextSidetabHandler | null = null;
9
+
10
+ export function setNextSidetabHandler(handler: NextSidetabHandler | null): void {
11
+ nextSidetabHandler = handler;
12
+ }
7
13
 
8
14
  interface TurnResult {
9
15
  event?: string | null;
@@ -18,6 +24,7 @@ interface TurnResult {
18
24
  interface WaitingTurn {
19
25
  turnId: string;
20
26
  onDelta?: (text: string) => void;
27
+ onStatus?: (text: string) => void;
21
28
  resolve: (result: TurnResult) => void;
22
29
  reject: (error: Error) => void;
23
30
  }
@@ -37,6 +44,7 @@ class LocalChatSession {
37
44
  // TUI-NEXT-QUEUE-AND-WAKE: the child's ScheduleWakeup asks this process over Bun IPC — the scheduler
38
45
  // lives here because the child dies on Esc and /new. No tool registered → no IPC, env unchanged.
39
46
  const wakeupTool = nextTuiWakeupTool();
47
+ const sidetabHandler = nextSidetabHandler;
40
48
  this.child = Bun.spawn({
41
49
  cmd: [process.execPath, cli, 'repl', '--session', sessionId, '--json', '--stdin-jsonl'],
42
50
  stdin: 'pipe', stdout: 'pipe', stderr: 'pipe',
@@ -44,13 +52,19 @@ class LocalChatSession {
44
52
  ...process.env, ELANOUS_NEXT_TUI_BG_STATUS: '1', ELANOUS_NEXT_TUI_STREAM: '1',
45
53
  ELANOUS_NEXT_TUI_SELF_HEALTH: '1',
46
54
  ...(wakeupTool ? { [NEXT_TUI_WAKEUP_IPC_ENV]: '1' } : {}),
55
+ ELANOUS_NEXT_TUI_SIDETAB_IPC: sidetabHandler ? '1' : '0',
47
56
  },
48
- ...(wakeupTool ? {
57
+ ...(wakeupTool || sidetabHandler ? {
49
58
  ipc: (message: unknown, child: { send(message: unknown): unknown }) => {
50
- if (!isWakeupCallMessage(message)) return;
51
- void answerWakeupCall(wakeupTool, message).then((reply) => {
52
- try { child.send(reply); } catch { /* the child exited mid-call; its dispatch times out */ }
53
- });
59
+ if (wakeupTool && isWakeupCallMessage(message)) {
60
+ void answerWakeupCall(wakeupTool, message).then((reply) => {
61
+ try { child.send(reply); } catch { /* the child exited mid-call; its dispatch times out */ }
62
+ });
63
+ } else if (sidetabHandler && isNextSidetabCall(message)) {
64
+ void answerNextSidetabCall(sidetabHandler, message).then((reply) => {
65
+ try { child.send(reply); } catch { /* the child exited mid-call; its dispatch times out */ }
66
+ });
67
+ }
54
68
  },
55
69
  } : {}),
56
70
  });
@@ -86,6 +100,12 @@ class LocalChatSession {
86
100
  }
87
101
  return;
88
102
  }
103
+ if (result.event === 'status') {
104
+ if (result.turnId === waiting.turnId && typeof result.text === 'string') {
105
+ try { waiting.onStatus?.(result.text); } catch { /* renderer cannot break the turn */ }
106
+ }
107
+ return;
108
+ }
89
109
  // Future side-channel events cannot complete a turn. Legacy final
90
110
  // frames have no event; typed final frames use event=result.
91
111
  if ('event' in result && result.event !== 'result') return;
@@ -155,12 +175,12 @@ class LocalChatSession {
155
175
  }
156
176
  }
157
177
 
158
- async turn(prompt: string, writePrompt?: (payload: string) => Promise<void>, onDelta?: (text: string) => void): Promise<TurnResult> {
178
+ async turn(prompt: string, writePrompt?: (payload: string) => Promise<void>, onDelta?: (text: string) => void, attachments: readonly string[] = [], onStatus?: (text: string) => void): Promise<TurnResult> {
159
179
  if (this.closed) throw new Error('REPL child exited');
160
180
  if (this.waiting) throw new Error('REPL turn already running');
161
181
  const turnId = `tui-${++this.turnCount}`;
162
- const payload = `${JSON.stringify({ prompt, id: turnId })}\n`;
163
- const response = new Promise<TurnResult>((resolve, reject) => { this.waiting = { turnId, onDelta, resolve, reject }; });
182
+ const payload = JSON.stringify({ prompt, id: turnId, ...(attachments.length ? { attachments } : {}) }) + '\n';
183
+ const response = new Promise<TurnResult>((resolve, reject) => { this.waiting = { turnId, onDelta, onStatus, resolve, reject }; });
164
184
  try {
165
185
  if (writePrompt) await writePrompt(payload);
166
186
  else await this.writeInput(payload);
@@ -237,6 +257,8 @@ export async function runLocalChatTurn(
237
257
  writePrompt?: (payload: string) => Promise<void>,
238
258
  onDelta?: (text: string) => void,
239
259
  compact: LocalChatTurnCompact = {},
260
+ attachments: readonly string[] = [],
261
+ onStatus?: (line: string) => void,
240
262
  ): Promise<void> {
241
263
  if (signal.aborted) throw new Error('응답을 취소했습니다');
242
264
  if (!cli) throw new Error('elanous CLI entry is unavailable');
@@ -258,7 +280,7 @@ export async function runLocalChatTurn(
258
280
  try {
259
281
  result = await session.turn(text, writePrompt, (delta) => {
260
282
  if (!signal.aborted) onDelta?.(delta);
261
- });
283
+ }, attachments, (line) => { if (!signal.aborted) onStatus?.(line); });
262
284
  } catch (error) {
263
285
  if (signal.aborted) throw new Error('응답을 취소했습니다');
264
286
  await closeLocalChatSession(sessionId);
@@ -864,7 +864,7 @@ function normalizeReportChannel(raw: unknown): TelegramReportChannel | undefined
864
864
  export interface TelegramTestChannel {
865
865
  botToken: string;
866
866
  allowedUsers?: number[];
867
- /** 무인 주입(scripts/telegram-inject.ts·#24)의 대상 봇 username(예: `@example_temp_bot`). 봇이 여럿일
867
+ /** 무인 주입(scripts/telegram-inject.ts·#24)의 대상 봇 username(예: `@test_helper_bot`). 봇이 여럿일
868
868
  * 때 어느 봇(테스트 채널용)에 objective 를 주입할지 명시. env `TELEGRAM_TEST_BOT`/`--to` 로도 지정 가능. */
869
869
  botUsername?: string;
870
870
  }
@@ -901,7 +901,7 @@ export interface TelegramChannel {
901
901
  chatId: number;
902
902
  interactive: boolean;
903
903
  roles: string[];
904
- /** 봇 username(예: `example_monad_bot`). 무인 유틸(scripts/telegram-inject.ts)이
904
+ /** 봇 username(예: `primary_bot`). 무인 유틸(scripts/telegram-inject.ts)이
905
905
  * role/name 으로 대상 봇을 config 한 곳에서 찾도록 하는 조회용 필드. 선택. */
906
906
  botUsername?: string;
907
907
  }
@@ -3391,8 +3391,22 @@ export function parseSubscriptionReviewerSpec(raw: unknown): SubscriptionReviewe
3391
3391
  return { provider: 'claude-acp', ...(v.executor ? { executor: v.executor as 'cct' | 'cc' } : {}) };
3392
3392
  }
3393
3393
 
3394
+ /** Stable PR-number allocation for the three self-review lanes. Zero disables a lane. */
3395
+ export interface ReviewerMixSpec { sol: number; claude: number; glm: number }
3396
+
3397
+ export function parseReviewerMixSpec(raw: unknown): ReviewerMixSpec | undefined {
3398
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
3399
+ const value = raw as Record<string, unknown>;
3400
+ if (Object.keys(value).some(key => key !== 'sol' && key !== 'claude' && key !== 'glm')) return undefined;
3401
+ const weights = [value.sol, value.claude, value.glm];
3402
+ if (weights.some(weight => !Number.isSafeInteger(weight) || (weight as number) < 0) ||
3403
+ weights.every(weight => weight === 0) ||
3404
+ !Number.isSafeInteger(weights.reduce<number>((sum, weight) => sum + (weight as number), 0))) return undefined;
3405
+ return { sol: value.sol as number, claude: value.claude as number, glm: value.glm as number };
3406
+ }
3407
+
3394
3408
  /** 역할별 LLM 선택(sparse). `reviewer` is the opt-in harness ACP lane. */
3395
- export type RoleLlmConfig = Partial<Record<ModelRole, RoleLlmSpec>> & { reviewer?: SubscriptionReviewerSpec };
3409
+ export type RoleLlmConfig = Partial<Record<ModelRole, RoleLlmSpec>> & { reviewer?: SubscriptionReviewerSpec; reviewerMix?: ReviewerMixSpec };
3396
3410
 
3397
3411
  export type ModelResolutionSource = 'config' | 'tier' | 'environment' | 'default';
3398
3412
 
@@ -3887,6 +3901,8 @@ function parseProjectsConfig(raw: unknown): Record<string, ProjectConfig> | unde
3887
3901
  }
3888
3902
 
3889
3903
  export interface UserConfig {
3904
+ /** Next TUI sidetab visibility: off disables it, collapsed starts folded, open starts visible. */
3905
+ tui?: { sidetab?: 'off' | 'collapsed' | 'open' };
3890
3906
  projects?: Record<string, ProjectConfig>;
3891
3907
  /** Default personal topic watch; absent = enabled when user sources exist. */
3892
3908
  watch?: { enabled?: boolean };
@@ -4354,6 +4370,10 @@ function parseRoleLlmConfig(raw: unknown): RoleLlmConfig | undefined {
4354
4370
  parsed.reviewer = parseSubscriptionReviewerSpec(values.reviewer);
4355
4371
  if (!parsed.reviewer) warnUserConfigDrop('roleLlm.reviewer', 'claude-acp reviewer 설정이 유효하지 않아 무시');
4356
4372
  }
4373
+ if (values.reviewerMix !== undefined) {
4374
+ parsed.reviewerMix = parseReviewerMixSpec(values.reviewerMix);
4375
+ if (!parsed.reviewerMix) warnUserConfigDrop('roleLlm.reviewerMix', '리뷰 비율 설정이 유효하지 않아 무시');
4376
+ }
4357
4377
  // ⛔ config 로딩은 «나머지를 살리려고» 잘못된 칸을 버리는데, 그 사실이 어디에도 안 남으면
4358
4378
  // 사용자는 「왜 내 설정이 안 먹지」를 영영 못 푼다(CLI 는 이름을 대며 거부하는데 여기만 조용했다).
4359
4379
  // ⇒ 버린 것을 «이름과 이유»로 남긴다. 로딩 자체는 계속한다.
@@ -4374,6 +4394,7 @@ function parseRoleLlmConfig(raw: unknown): RoleLlmConfig | undefined {
4374
4394
 
4375
4395
  function defaultConfig(): UserConfig {
4376
4396
  return {
4397
+ tui: { sidetab: 'collapsed' },
4377
4398
  cli: { helpRole: 'owner' },
4378
4399
  coo: { linearProject: '외부 행정·큰 일 (COO)' },
4379
4400
  decisions: { linearProjection: { enabled: false }, requireCrossCheck: false,
@@ -5110,9 +5131,11 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
5110
5131
 
5111
5132
  const nexus = rawObj.nexus && typeof rawObj.nexus === 'object' && !Array.isArray(rawObj.nexus)
5112
5133
  ? rawObj.nexus as Record<string, unknown> : {};
5134
+ const tuiRaw = rawObj.tui && typeof rawObj.tui === 'object' && !Array.isArray(rawObj.tui) ? rawObj.tui as Record<string, unknown> : {};
5113
5135
  const gateRemoteConfig = parseGateRemoteConfig(rawObj.gateRemote);
5114
5136
  const projects = parseProjectsConfig(rawObj.projects);
5115
5137
  return {
5138
+ tui: { sidetab: tuiRaw.sidetab === 'off' || tuiRaw.sidetab === 'open' ? tuiRaw.sidetab : 'collapsed' },
5116
5139
  ...(projects ? { projects } : {}),
5117
5140
  ...(rawObj.starter && typeof rawObj.starter === 'object' && !Array.isArray(rawObj.starter)
5118
5141
  && Array.isArray((rawObj.starter as Record<string, unknown>).topics)
@@ -6469,6 +6492,8 @@ export function saveUserConfig(
6469
6492
  },
6470
6493
  };
6471
6494
  const rawRest = { ...(cfg.raw ?? {}) };
6495
+ const rawTui = rawRest.tui && typeof rawRest.tui === 'object' && !Array.isArray(rawRest.tui)
6496
+ ? rawRest.tui as Record<string, unknown> : {};
6472
6497
  // projects: raw entries are kept verbatim — an invalid entry loaded from disk is preserved, not blocked (its error
6473
6498
  // surfaces in resolveRubricAxes) — and typed axes handed to save are validated (invalid ones refuse the save).
6474
6499
  const rawProjectsValue = rawRest.projects;
@@ -6751,6 +6776,8 @@ export function saveUserConfig(
6751
6776
  debug: cfg.debug,
6752
6777
  logs: cfg.logs,
6753
6778
  shell: cfg.shell,
6779
+ // Preserve newer/unknown TUI settings while the typed config only knows sidetab.
6780
+ tui: { ...rawTui, ...cfg.tui },
6754
6781
  errorReports: cfg.errorReports ? stripUndef({ ...cfg.errorReports }) : undefined,
6755
6782
  chat: stripUndef({
6756
6783
  fastPath: cfg.chat.fastPath,
@@ -0,0 +1,136 @@
1
+ // ux-sim device — boot daemon-tools PtyShellStart stage (L2: env injection).
2
+ //
3
+ // TUI-NO-SELF-NEST (#27) needs evidence that travels the REAL call path, not
4
+ // a source-string check: the stage below injects a TUI PTY context
5
+ // (ELANOUS_PARENT_PTY_ID / ELANOUS_NEST_DEPTH — the same material
6
+ // src/pty-shell/registry.ts stamps into a child's identity) and then calls
7
+ // the production dispatcher `dispatchPtyShellTool` in
8
+ // src/boot/daemon-tools/pty-shell.ts, which is where PtyShellStart is
9
+ // actually served. The stage records command · rc · output tail so the run
10
+ // transcript can go straight into a PR body.
11
+ //
12
+ // The stage never wants a live nested TUI: when a scenario is expected to be
13
+ // refused, the dispatcher answers with `{ output: guidance }` and no PTY is
14
+ // created. If a scenario slips through, the stage kills the spawned PTY
15
+ // before reporting so the run leaves nothing behind.
16
+
17
+ import { dispatchPtyShellTool } from '../boot/daemon-tools/pty-shell.js';
18
+ import {
19
+ decideTuiSelfNest,
20
+ TUI_SELF_NEST_REJECT_MARKER,
21
+ type TuiSelfNestDecision,
22
+ } from '../agent/terminal-surface.js';
23
+
24
+ export interface PtyShellStageInput {
25
+ /** argv of the spawn request — e.g. ['eln'] or ['/usr/bin/eln', 'chat']. */
26
+ argv: string[];
27
+ /** Injected "inside a TUI" material. null ⇒ no TUI context. */
28
+ parentPtyId?: string | null;
29
+ /** Injected nest depth (ELANOUS_NEST_DEPTH). */
30
+ nestDepth?: number;
31
+ /** Extra PtyShellStart args (workdir, env, …) merged into the call. */
32
+ extraArgs?: Record<string, unknown>;
33
+ }
34
+
35
+ export interface PtyShellStageResult {
36
+ /** The argv as it crossed the production dispatcher. */
37
+ command: string;
38
+ /** 0 = the stage produced the outcome the scenario asked for. */
39
+ rc: number;
40
+ /** True when the production path refused the spawn with guidance. */
41
+ rejected: boolean;
42
+ /** Full output returned by the production dispatcher. */
43
+ output: string;
44
+ /** Last 3 lines of output — what the PR body quotes. */
45
+ outputTail: string;
46
+ /** A PTY that was created despite the scenario (leak guard). */
47
+ spawnedPid: string | null;
48
+ }
49
+
50
+ const ENV_KEYS = ['ELANOUS_PARENT_PTY_ID', 'ELANOUS_NEST_DEPTH', 'ELANOUS_PTY_ID'] as const;
51
+
52
+ function snapshotEnv(): Record<string, string | undefined> {
53
+ const saved: Record<string, string | undefined> = {};
54
+ for (const key of ENV_KEYS) saved[key] = process.env[key];
55
+ return saved;
56
+ }
57
+
58
+ function restoreEnv(saved: Record<string, string | undefined>): void {
59
+ for (const key of ENV_KEYS) {
60
+ const value = saved[key];
61
+ if (value === undefined) delete process.env[key];
62
+ else process.env[key] = value;
63
+ }
64
+ }
65
+
66
+ function tailOf(output: string, lines = 3): string {
67
+ return output.split('\n').filter((l) => l.length > 0).slice(-lines).join('\n');
68
+ }
69
+
70
+ /** Apply the scenario's TUI context to this process, exactly as a TUI-owned
71
+ * seat shell would have it, then run the production PtyShellStart path. */
72
+ export async function runPtyShellStartStage(input: PtyShellStageInput): Promise<PtyShellStageResult> {
73
+ const saved = snapshotEnv();
74
+ const parentPtyId = input.parentPtyId ?? null;
75
+ const nestDepth = input.nestDepth ?? 0;
76
+ try {
77
+ if (parentPtyId) {
78
+ process.env.ELANOUS_PARENT_PTY_ID = parentPtyId;
79
+ // pty-identity's getCurrentPtyId() reads its own pty id; mirror it so
80
+ // the stage exercises both halves of readTuiNestEnv's source chain.
81
+ process.env.ELANOUS_PTY_ID = parentPtyId;
82
+ } else {
83
+ delete process.env.ELANOUS_PARENT_PTY_ID;
84
+ delete process.env.ELANOUS_PTY_ID;
85
+ }
86
+ if (nestDepth > 0) process.env.ELANOUS_NEST_DEPTH = String(nestDepth);
87
+ else delete process.env.ELANOUS_NEST_DEPTH;
88
+
89
+ const [cmd, ...args] = input.argv;
90
+ const result = await dispatchPtyShellTool('PtyShellStart', {
91
+ ...(input.extraArgs ?? {}),
92
+ cmd: cmd ?? '',
93
+ args,
94
+ });
95
+
96
+ const shaped = (result ?? {}) as { output?: unknown; process_id?: unknown; id?: unknown };
97
+ const output = typeof shaped.output === 'string' ? shaped.output : JSON.stringify(result ?? null);
98
+ const rejected = output.includes(TUI_SELF_NEST_REJECT_MARKER);
99
+ const rawPid = shaped.process_id ?? shaped.id;
100
+ const spawnedPid = rejected || rawPid === undefined ? null : String(rawPid);
101
+ if (spawnedPid) {
102
+ try { await dispatchPtyShellTool('PtyShellKill', { process_id: spawnedPid }); } catch { /* leak guard */ }
103
+ }
104
+ return {
105
+ command: input.argv.join(' '),
106
+ rc: rejected ? 0 : 1,
107
+ rejected,
108
+ output,
109
+ outputTail: tailOf(output),
110
+ spawnedPid,
111
+ };
112
+ } finally {
113
+ restoreEnv(saved);
114
+ }
115
+ }
116
+
117
+ /** Classifier-only view of the same scenario — used for the allow-list rows
118
+ * (commands that must keep running) without spawning anything. */
119
+ export function inspectPtyShellStartStage(input: PtyShellStageInput): TuiSelfNestDecision {
120
+ const saved = snapshotEnv();
121
+ try {
122
+ if (input.parentPtyId) {
123
+ process.env.ELANOUS_PARENT_PTY_ID = input.parentPtyId;
124
+ process.env.ELANOUS_PTY_ID = input.parentPtyId;
125
+ } else {
126
+ delete process.env.ELANOUS_PARENT_PTY_ID;
127
+ delete process.env.ELANOUS_PTY_ID;
128
+ }
129
+ if ((input.nestDepth ?? 0) > 0) process.env.ELANOUS_NEST_DEPTH = String(input.nestDepth);
130
+ else delete process.env.ELANOUS_NEST_DEPTH;
131
+ const [cmd, ...args] = input.argv;
132
+ return decideTuiSelfNest([cmd ?? '', ...args]);
133
+ } finally {
134
+ restoreEnv(saved);
135
+ }
136
+ }