elanous 0.2.0 → 0.2.4

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 (1174) hide show
  1. package/.env.example +6 -0
  2. package/README.md +16 -14
  3. package/apps/pwa/out/404/index.html +1 -1
  4. package/apps/pwa/out/404.html +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1191-7b13a24117a689fa.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/2375-3fcae5186c64fe6b.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/2415.ed6428ff334c7ce2.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +25 -0
  17. package/apps/pwa/out/_next/static/chunks/{2a79f15a-2013e4d421d6df88.js → 2ea96958-e8c7e112de50b067.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/319-d37df1b6e0cbeff4.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +5 -0
  20. package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6804.8ed6ab492bc5fc0a.js → 4323.c5dfb6f503304775.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/4836-3c93795ab834381e.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{320-d7013ec072863e5e.js → 5080-1613752891fcadb4.js} +4 -4
  26. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/6062-73e68343a9814f6a.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/6090-1bd6077591603947.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/7457-f5cb1cc8db9f7453.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/8046cadf-211ca3c0e00f2b72.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8067-f74bf14d67ad98f1.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8142-011e1f474efb8b33.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8519-0059d82bdb4812bf.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/9740-52467f244755917f.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/9804-64c02c3c127d5014.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/app/approvals/page-21c3261af6ab377c.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-1991445b8ea86274.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/board/page-4ebfaee2369fe248.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/botlab/page-9fa879ebf5959096.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/bots/page-ca7c3cc305c3285a.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/chat/page-9951930add3d2051.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/control/page-4472ddf1e2458e69.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/app/design-check/page-4de08d4b766f134b.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/editor/page-7a975e2b9db1dfb7.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/intake/page-49270714ef35bb96.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/layout-33fbdf353e2a5982.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/live/page-259f122e2dd64317.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/market/page-65b82726753658e1.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-4b8df3748dc06285.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/morning/page-112f7e477bda77fd.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/not-found-542a5c0006da637c.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/observatory/page-63ffb347831262ea.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/page-98e4e359d97263b4.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/reflection/page-97e24ac675ce576e.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ac6391f26391d89d.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f45c9d45ffc43bd.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-36995b9cb5d98218.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/settings/page-0c795b577988d63f.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-b4311e2f71c6735a.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/setup/page-eb2381074df20dba.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/share/page-b01336e64eba01ae.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/showroom/page-7af7f21c1f2858ef.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/tasks/page-a98ecd364586c89b.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/term/page-57f0502dfbfa089b.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/trace/page-3467d2e1abd8a14a.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/vault/page-7842ca23d53ba682.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-ae9ac882912b0198.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/workflows/page-3a0d72e3f783bcef.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/workspace/page-f3b39fe8358c2a97.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-5a22af3181ac2afb.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/main-app-1457627bb302a22c.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +1 -0
  92. package/apps/pwa/out/_next/static/css/e66b7f5efc8df3f3.css +1 -0
  93. package/apps/pwa/out/_next/static/zoQX5iTvXOsIvCjxCe1Ji/_buildManifest.js +1 -0
  94. package/apps/pwa/out/approvals/index.html +1 -0
  95. package/apps/pwa/out/approvals/index.txt +30 -0
  96. package/apps/pwa/out/autopilot/index.html +1 -1
  97. package/apps/pwa/out/autopilot/index.txt +27 -26
  98. package/apps/pwa/out/board/index.html +1 -0
  99. package/apps/pwa/out/board/index.txt +30 -0
  100. package/apps/pwa/out/botlab/index.html +1 -1
  101. package/apps/pwa/out/botlab/index.txt +24 -23
  102. package/apps/pwa/out/bots/index.html +1 -1
  103. package/apps/pwa/out/bots/index.txt +24 -23
  104. package/apps/pwa/out/chat/index.html +1 -2
  105. package/apps/pwa/out/chat/index.txt +24 -23
  106. package/apps/pwa/out/control/index.html +1 -1
  107. package/apps/pwa/out/control/index.txt +27 -26
  108. package/apps/pwa/out/design-check/index.html +1 -1
  109. package/apps/pwa/out/design-check/index.txt +27 -26
  110. package/apps/pwa/out/editor/index.html +1 -0
  111. package/apps/pwa/out/editor/index.txt +31 -0
  112. package/apps/pwa/out/healthz +1 -1
  113. package/apps/pwa/out/index.html +1 -1
  114. package/apps/pwa/out/index.txt +24 -23
  115. package/apps/pwa/out/intake/index.html +1 -1
  116. package/apps/pwa/out/intake/index.txt +27 -26
  117. package/apps/pwa/out/live/index.html +1 -0
  118. package/apps/pwa/out/live/index.txt +30 -0
  119. package/apps/pwa/out/market/index.html +1 -0
  120. package/apps/pwa/out/market/index.txt +27 -0
  121. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  122. package/apps/pwa/out/missions/placeholder/index.txt +24 -23
  123. package/apps/pwa/out/morning/index.html +1 -1
  124. package/apps/pwa/out/morning/index.txt +27 -26
  125. package/apps/pwa/out/observatory/index.html +1 -1
  126. package/apps/pwa/out/observatory/index.txt +27 -26
  127. package/apps/pwa/out/reflection/index.html +1 -1
  128. package/apps/pwa/out/reflection/index.txt +25 -24
  129. package/apps/pwa/out/scheduler/index.html +1 -1
  130. package/apps/pwa/out/scheduler/index.txt +27 -26
  131. package/apps/pwa/out/sessions/index.html +1 -1
  132. package/apps/pwa/out/sessions/index.txt +24 -23
  133. package/apps/pwa/out/settings/devices/index.html +1 -1
  134. package/apps/pwa/out/settings/devices/index.txt +27 -26
  135. package/apps/pwa/out/settings/index.html +1 -1
  136. package/apps/pwa/out/settings/index.txt +27 -26
  137. package/apps/pwa/out/setup/done/index.html +1 -1
  138. package/apps/pwa/out/setup/done/index.txt +27 -26
  139. package/apps/pwa/out/setup/index.html +1 -1
  140. package/apps/pwa/out/setup/index.txt +27 -26
  141. package/apps/pwa/out/share/index.html +1 -1
  142. package/apps/pwa/out/share/index.txt +27 -26
  143. package/apps/pwa/out/showroom/index.html +1 -1
  144. package/apps/pwa/out/showroom/index.txt +24 -23
  145. package/apps/pwa/out/tasks/index.html +1 -1
  146. package/apps/pwa/out/tasks/index.txt +27 -26
  147. package/apps/pwa/out/term/index.html +1 -1
  148. package/apps/pwa/out/term/index.txt +27 -26
  149. package/apps/pwa/out/trace/index.html +1 -0
  150. package/apps/pwa/out/trace/index.txt +30 -0
  151. package/apps/pwa/out/vault/index.html +1 -1
  152. package/apps/pwa/out/vault/index.txt +27 -26
  153. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  154. package/apps/pwa/out/workflows/chat-ui/index.txt +27 -26
  155. package/apps/pwa/out/workflows/index.html +1 -1
  156. package/apps/pwa/out/workflows/index.txt +27 -27
  157. package/apps/pwa/out/workspace/index.html +1 -1
  158. package/apps/pwa/out/workspace/index.txt +27 -26
  159. package/apps/pwa/out/worktrees/index.html +1 -1
  160. package/apps/pwa/out/worktrees/index.txt +27 -26
  161. package/catalog/resources.yaml +8 -11
  162. package/docs/design/systems/LICENSE +201 -0
  163. package/docs/design/systems/NOTICE.md +29 -0
  164. package/docs/design/systems/SOURCE.json +291 -0
  165. package/docs/design/systems/application/DESIGN.md +71 -0
  166. package/docs/design/systems/application/manifest.json +54 -0
  167. package/docs/design/systems/application/tokens.css +63 -0
  168. package/docs/design/systems/artistic/DESIGN.md +71 -0
  169. package/docs/design/systems/artistic/manifest.json +54 -0
  170. package/docs/design/systems/artistic/tokens.css +63 -0
  171. package/docs/design/systems/bento/DESIGN.md +71 -0
  172. package/docs/design/systems/bento/manifest.json +54 -0
  173. package/docs/design/systems/bento/tokens.css +63 -0
  174. package/docs/design/systems/bold/DESIGN.md +71 -0
  175. package/docs/design/systems/bold/manifest.json +54 -0
  176. package/docs/design/systems/bold/tokens.css +63 -0
  177. package/docs/design/systems/brutalism/DESIGN.md +71 -0
  178. package/docs/design/systems/brutalism/manifest.json +54 -0
  179. package/docs/design/systems/brutalism/tokens.css +63 -0
  180. package/docs/design/systems/cafe/DESIGN.md +71 -0
  181. package/docs/design/systems/cafe/manifest.json +54 -0
  182. package/docs/design/systems/cafe/tokens.css +63 -0
  183. package/docs/design/systems/claymorphism/DESIGN.md +71 -0
  184. package/docs/design/systems/claymorphism/manifest.json +54 -0
  185. package/docs/design/systems/claymorphism/tokens.css +63 -0
  186. package/docs/design/systems/clean/DESIGN.md +71 -0
  187. package/docs/design/systems/clean/manifest.json +54 -0
  188. package/docs/design/systems/clean/tokens.css +63 -0
  189. package/docs/design/systems/colorful/DESIGN.md +71 -0
  190. package/docs/design/systems/colorful/manifest.json +54 -0
  191. package/docs/design/systems/colorful/tokens.css +63 -0
  192. package/docs/design/systems/contemporary/DESIGN.md +71 -0
  193. package/docs/design/systems/contemporary/manifest.json +54 -0
  194. package/docs/design/systems/contemporary/tokens.css +63 -0
  195. package/docs/design/systems/corporate/DESIGN.md +71 -0
  196. package/docs/design/systems/corporate/manifest.json +54 -0
  197. package/docs/design/systems/corporate/tokens.css +63 -0
  198. package/docs/design/systems/cosmic/DESIGN.md +71 -0
  199. package/docs/design/systems/cosmic/manifest.json +54 -0
  200. package/docs/design/systems/cosmic/tokens.css +63 -0
  201. package/docs/design/systems/creative/DESIGN.md +71 -0
  202. package/docs/design/systems/creative/manifest.json +54 -0
  203. package/docs/design/systems/creative/tokens.css +63 -0
  204. package/docs/design/systems/dashboard/DESIGN.md +71 -0
  205. package/docs/design/systems/dashboard/manifest.json +54 -0
  206. package/docs/design/systems/dashboard/tokens.css +63 -0
  207. package/docs/design/systems/default/DESIGN.md +62 -0
  208. package/docs/design/systems/default/manifest.json +69 -0
  209. package/docs/design/systems/default/tokens.css +200 -0
  210. package/docs/design/systems/dithered/DESIGN.md +71 -0
  211. package/docs/design/systems/dithered/manifest.json +54 -0
  212. package/docs/design/systems/dithered/tokens.css +63 -0
  213. package/docs/design/systems/doodle/DESIGN.md +71 -0
  214. package/docs/design/systems/doodle/manifest.json +54 -0
  215. package/docs/design/systems/doodle/tokens.css +63 -0
  216. package/docs/design/systems/dramatic/DESIGN.md +71 -0
  217. package/docs/design/systems/dramatic/manifest.json +54 -0
  218. package/docs/design/systems/dramatic/tokens.css +63 -0
  219. package/docs/design/systems/editorial/DESIGN.md +71 -0
  220. package/docs/design/systems/editorial/manifest.json +54 -0
  221. package/docs/design/systems/editorial/tokens.css +63 -0
  222. package/docs/design/systems/elegant/DESIGN.md +71 -0
  223. package/docs/design/systems/elegant/manifest.json +54 -0
  224. package/docs/design/systems/elegant/tokens.css +63 -0
  225. package/docs/design/systems/energetic/DESIGN.md +72 -0
  226. package/docs/design/systems/energetic/manifest.json +54 -0
  227. package/docs/design/systems/energetic/tokens.css +63 -0
  228. package/docs/design/systems/enterprise/DESIGN.md +71 -0
  229. package/docs/design/systems/enterprise/manifest.json +54 -0
  230. package/docs/design/systems/enterprise/tokens.css +63 -0
  231. package/docs/design/systems/expressive/DESIGN.md +71 -0
  232. package/docs/design/systems/expressive/manifest.json +54 -0
  233. package/docs/design/systems/expressive/tokens.css +63 -0
  234. package/docs/design/systems/fantasy/DESIGN.md +71 -0
  235. package/docs/design/systems/fantasy/manifest.json +54 -0
  236. package/docs/design/systems/fantasy/tokens.css +63 -0
  237. package/docs/design/systems/flat/DESIGN.md +71 -0
  238. package/docs/design/systems/flat/manifest.json +54 -0
  239. package/docs/design/systems/flat/tokens.css +63 -0
  240. package/docs/design/systems/friendly/DESIGN.md +71 -0
  241. package/docs/design/systems/friendly/manifest.json +54 -0
  242. package/docs/design/systems/friendly/tokens.css +63 -0
  243. package/docs/design/systems/glassmorphism/DESIGN.md +71 -0
  244. package/docs/design/systems/glassmorphism/manifest.json +54 -0
  245. package/docs/design/systems/glassmorphism/tokens.css +63 -0
  246. package/docs/design/systems/gradient/DESIGN.md +71 -0
  247. package/docs/design/systems/gradient/manifest.json +54 -0
  248. package/docs/design/systems/gradient/tokens.css +63 -0
  249. package/docs/design/systems/luxury/DESIGN.md +71 -0
  250. package/docs/design/systems/luxury/manifest.json +54 -0
  251. package/docs/design/systems/luxury/tokens.css +63 -0
  252. package/docs/design/systems/minimal/DESIGN.md +71 -0
  253. package/docs/design/systems/minimal/manifest.json +54 -0
  254. package/docs/design/systems/minimal/tokens.css +63 -0
  255. package/docs/design/systems/modern/DESIGN.md +71 -0
  256. package/docs/design/systems/modern/manifest.json +54 -0
  257. package/docs/design/systems/modern/tokens.css +63 -0
  258. package/docs/design/systems/mono/DESIGN.md +71 -0
  259. package/docs/design/systems/mono/manifest.json +54 -0
  260. package/docs/design/systems/mono/tokens.css +63 -0
  261. package/docs/design/systems/neobrutalism/DESIGN.md +71 -0
  262. package/docs/design/systems/neobrutalism/manifest.json +54 -0
  263. package/docs/design/systems/neobrutalism/tokens.css +63 -0
  264. package/docs/design/systems/neon/DESIGN.md +71 -0
  265. package/docs/design/systems/neon/manifest.json +54 -0
  266. package/docs/design/systems/neon/tokens.css +63 -0
  267. package/docs/design/systems/neumorphism/DESIGN.md +71 -0
  268. package/docs/design/systems/neumorphism/manifest.json +54 -0
  269. package/docs/design/systems/neumorphism/tokens.css +63 -0
  270. package/docs/design/systems/paper/DESIGN.md +71 -0
  271. package/docs/design/systems/paper/manifest.json +54 -0
  272. package/docs/design/systems/paper/tokens.css +63 -0
  273. package/docs/design/systems/perspective/DESIGN.md +71 -0
  274. package/docs/design/systems/perspective/manifest.json +54 -0
  275. package/docs/design/systems/perspective/tokens.css +63 -0
  276. package/docs/design/systems/premium/DESIGN.md +71 -0
  277. package/docs/design/systems/premium/manifest.json +54 -0
  278. package/docs/design/systems/premium/tokens.css +63 -0
  279. package/docs/design/systems/professional/DESIGN.md +71 -0
  280. package/docs/design/systems/professional/manifest.json +54 -0
  281. package/docs/design/systems/professional/tokens.css +63 -0
  282. package/docs/design/systems/publication/DESIGN.md +71 -0
  283. package/docs/design/systems/publication/manifest.json +54 -0
  284. package/docs/design/systems/publication/tokens.css +63 -0
  285. package/docs/design/systems/refined/DESIGN.md +71 -0
  286. package/docs/design/systems/refined/manifest.json +54 -0
  287. package/docs/design/systems/refined/tokens.css +63 -0
  288. package/docs/design/systems/retro/DESIGN.md +71 -0
  289. package/docs/design/systems/retro/manifest.json +54 -0
  290. package/docs/design/systems/retro/tokens.css +63 -0
  291. package/docs/design/systems/shadcn/DESIGN.md +71 -0
  292. package/docs/design/systems/shadcn/manifest.json +54 -0
  293. package/docs/design/systems/shadcn/tokens.css +255 -0
  294. package/docs/design/systems/simple/DESIGN.md +71 -0
  295. package/docs/design/systems/simple/manifest.json +54 -0
  296. package/docs/design/systems/simple/tokens.css +63 -0
  297. package/docs/design/systems/skeumorphism/DESIGN.md +71 -0
  298. package/docs/design/systems/skeumorphism/manifest.json +54 -0
  299. package/docs/design/systems/skeumorphism/tokens.css +63 -0
  300. package/docs/design/systems/sleek/DESIGN.md +71 -0
  301. package/docs/design/systems/sleek/manifest.json +54 -0
  302. package/docs/design/systems/sleek/tokens.css +63 -0
  303. package/docs/design/systems/spacious/DESIGN.md +71 -0
  304. package/docs/design/systems/spacious/manifest.json +54 -0
  305. package/docs/design/systems/spacious/tokens.css +63 -0
  306. package/docs/design/systems/storytelling/DESIGN.md +71 -0
  307. package/docs/design/systems/storytelling/manifest.json +54 -0
  308. package/docs/design/systems/storytelling/tokens.css +63 -0
  309. package/docs/design/systems/tom-modern/DESIGN.md +361 -0
  310. package/docs/design/systems/tom-modern/manifest.json +16 -0
  311. package/docs/design/systems/tom-modern/tokens.css +99 -0
  312. package/docs/design/systems/vibrant/DESIGN.md +71 -0
  313. package/docs/design/systems/vibrant/manifest.json +54 -0
  314. package/docs/design/systems/vibrant/tokens.css +63 -0
  315. package/docs/design/systems/vintage/DESIGN.md +71 -0
  316. package/docs/design/systems/vintage/manifest.json +54 -0
  317. package/docs/design/systems/vintage/tokens.css +63 -0
  318. package/docs/design/systems/warm-editorial/DESIGN.md +65 -0
  319. package/docs/design/systems/warm-editorial/manifest.json +54 -0
  320. package/docs/design/systems/warm-editorial/tokens.css +63 -0
  321. package/docs/goal-context/01-goal-authoring-checks.md +18 -0
  322. package/docs/goal-context/steward-directives-2026-09-28.md +44 -0
  323. package/graphs/catalog/catalog.yaml +615 -0
  324. package/graphs/default-loop.yaml +1 -1
  325. package/graphs/document-loop.yaml +1 -1
  326. package/graphs/examples/stale-draft-digest/digest.ts +26 -0
  327. package/graphs/examples/stale-draft-digest/recipes.yaml +8 -0
  328. package/graphs/examples/stale-draft-digest/stale-draft-digest.yaml +22 -0
  329. package/graphs/heal/heal-loop.yaml +155 -0
  330. package/graphs/heal/recipes.yaml +19 -0
  331. package/graphs/implement-loop.yaml +2 -2
  332. package/graphs/intake/intake-daily.yaml +55 -0
  333. package/graphs/intake/recipes.yaml +16 -0
  334. package/graphs/landing/landing-heal.yaml +22 -0
  335. package/graphs/landing/recipes.yaml +8 -0
  336. package/graphs/launch/launch-head.yaml +66 -0
  337. package/graphs/launch/recipes.yaml +8 -0
  338. package/graphs/operate-loop.yaml +1 -1
  339. package/graphs/ops/docs-publish.yaml +31 -0
  340. package/graphs/ops/recipes.yaml +8 -0
  341. package/graphs/release/recipes.yaml +38 -0
  342. package/graphs/release/release-loop.yaml +40 -0
  343. package/graphs/research-loop.yaml +1 -1
  344. package/graphs/steward/recipes.yaml +12 -0
  345. package/graphs/steward/steward.yaml +45 -0
  346. package/graphs/video/broll-line.yaml +54 -0
  347. package/package.json +7 -5
  348. package/plugins/job-coach/.agents/plugins/marketplace.json +12 -0
  349. package/plugins/job-coach/.codex-plugin/plugin.json +6 -0
  350. package/plugins/job-coach/.mcp.json +9 -0
  351. package/plugins/job-coach/README.md +20 -0
  352. package/plugins/job-coach/connectors/ncs/server.ts +89 -0
  353. package/plugins/job-coach/examples/interview-sample.md +11 -0
  354. package/plugins/job-coach/graphs/course-links.ts +46 -0
  355. package/plugins/job-coach/graphs/recipes.yaml +18 -0
  356. package/plugins/job-coach/graphs/report.yaml +20 -0
  357. package/plugins/job-coach/graphs/run-step.ts +108 -0
  358. package/plugins/job-coach/plugin.json +13 -0
  359. package/plugins/job-coach/plugin.ts +6 -0
  360. package/plugins/job-coach/skills/career-report/SKILL.md +6 -0
  361. package/plugins/job-coach/skills/interview-to-profile/SKILL.md +6 -0
  362. package/plugins/job-coach/skills/run-report/SKILL.md +15 -0
  363. package/scripts/backup/elanous-backup.sh +139 -13
  364. package/scripts/backup/elanous-restore.sh +122 -0
  365. package/scripts/ci-daemon-port-gate.ts +164 -0
  366. package/scripts/ci-typecheck-changed.ts +15 -1
  367. package/scripts/cli-json-exit-scan.ts +126 -0
  368. package/scripts/codex-quota-alert-format.ts +52 -0
  369. package/scripts/codex-quota-alert.ts +63 -13
  370. package/scripts/continuation-dogfood.ts +2 -1
  371. package/scripts/coord-channel-watch.sh +5 -5
  372. package/scripts/coord-tracks.json +5 -4
  373. package/scripts/cron-run.ts +37 -16
  374. package/scripts/daemon-port-baseline.txt +9 -0
  375. package/scripts/design/extract-corpus-bench.ts +469 -0
  376. package/scripts/design/extract-corpus-score.ts +510 -0
  377. package/scripts/design/vendor-open-design-systems.ts +100 -0
  378. package/scripts/docs-lint.ts +1 -1
  379. package/scripts/fleet/node-setup.sh +38 -4
  380. package/scripts/heal/run-role.ts +328 -0
  381. package/scripts/install-role-watch.sh +95 -0
  382. package/scripts/install.ps1 +11 -1
  383. package/scripts/install.sh +81 -9
  384. package/scripts/isolation-hardcode-baseline.txt +1 -1
  385. package/scripts/landing-heal/must-fix-match.ts +37 -0
  386. package/scripts/landing-heal/run-mission.ts +101 -0
  387. package/scripts/lib/pwa-scenarios/acp-replay.ts +79 -0
  388. package/scripts/lib/pwa-scenarios/cdp-driver.ts +67 -0
  389. package/scripts/lib/pwa-scenarios/runner.ts +200 -0
  390. package/scripts/lib/pwa-scenarios/scenarios.ts +202 -0
  391. package/scripts/market/db-check.ts +212 -0
  392. package/scripts/market-posture-cycle.ts +63 -4
  393. package/scripts/nightly-docops.ts +1 -1
  394. package/scripts/ops/channel-bot-token-migrate.ts +146 -0
  395. package/scripts/ops-health-check.ts +15 -3
  396. package/scripts/pty-scenarios/run.ts +272 -0
  397. package/scripts/public-leak-baseline.txt +0 -7
  398. package/scripts/publish-internal-dist.ts +119 -0
  399. package/scripts/pwa-scenarios.ts +106 -0
  400. package/scripts/rebrand-elanous.ts +1 -1
  401. package/scripts/release-loop/cutoff.ts +139 -0
  402. package/scripts/release-loop/docs-land-node.ts +65 -0
  403. package/scripts/release-loop/docs-node.ts +172 -0
  404. package/scripts/release-loop/gate-diff.ts +29 -0
  405. package/scripts/release-loop/gate-node.ts +353 -0
  406. package/scripts/release-loop/node-verdict.ts +85 -0
  407. package/scripts/release-loop/prepare-node.ts +31 -0
  408. package/scripts/release-loop/publish-node.ts +57 -0
  409. package/scripts/release-loop/pwa-node-verdict.ts +45 -0
  410. package/scripts/release-loop/pwa-scenarios-node.ts +140 -0
  411. package/scripts/release-loop/release-docs.ts +102 -0
  412. package/scripts/release-loop/tui-node-checks.ts +29 -0
  413. package/scripts/release-loop/tui-sim-node.ts +113 -0
  414. package/scripts/release-loop/upgrade-node.ts +25 -0
  415. package/scripts/release-loop/verify-node.ts +21 -0
  416. package/scripts/release-loop/version-node.ts +147 -0
  417. package/scripts/release-upgrade-check.sh +53 -0
  418. package/scripts/se-mission-prepare.ts +9 -15
  419. package/scripts/test-deterministic.ts +2 -1
  420. package/scripts/uninstall.sh +10 -3
  421. package/scripts/video-broll-line.ts +89 -0
  422. package/scripts/waitlist-daily-digest.ts +108 -0
  423. package/scripts/window-landings.sh +1 -1
  424. package/skills/motion-broll/LICENSE +25 -0
  425. package/skills/motion-broll/SKILL.md +150 -0
  426. package/skills/motion-broll/SOURCE.md +6 -0
  427. package/skills/motion-broll/engine/base.css +19 -0
  428. package/skills/motion-broll/engine/beats.js +11 -0
  429. package/skills/motion-broll/engine/build.py +21 -0
  430. package/skills/motion-broll/engine/fonts/Geist-Variable.woff2 +0 -0
  431. package/skills/motion-broll/engine/fonts/GeistMono-Medium.woff2 +0 -0
  432. package/skills/motion-broll/engine/fonts/OFL-Geist.txt +92 -0
  433. package/skills/motion-broll/engine/motion.js +146 -0
  434. package/skills/motion-broll/engine/render.js +22 -0
  435. package/skills/motion-broll/examples/opus-aoe2/01-opus-drop.html +41 -0
  436. package/skills/motion-broll/examples/opus-aoe2/02-pip-builds.html +110 -0
  437. package/skills/motion-broll/examples/opus-aoe2/03-effort-slider.html +38 -0
  438. package/skills/motion-broll/examples/opus-aoe2/04-master-prompt.html +56 -0
  439. package/skills/motion-broll/examples/opus-aoe2/05-low-vs-max.html +49 -0
  440. package/skills/motion-broll/examples/opus-aoe2/06-chapter.html +18 -0
  441. package/skills/motion-broll/examples/opus-aoe2/plan.json +14 -0
  442. package/skills/motion-broll/reference/engine-api.md +106 -0
  443. package/skills/motion-broll/scripts/composite.py +14 -0
  444. package/skills/motion-broll/scripts/inspect_video.py +34 -0
  445. package/skills/motion-broll/scripts/make_pages.py +34 -0
  446. package/skills/motion-broll/scripts/setup.sh +16 -0
  447. package/skills/motion-broll/scripts/words.py +13 -0
  448. package/skills/motion-broll/templates/compare.html +135 -0
  449. package/skills/motion-broll/templates/viewer.html +97 -0
  450. package/skills/omni-digest/SKILL.md +260 -0
  451. package/skills/omni-digest/digest.md +197 -0
  452. package/skills/omni-digest/docs/diagrams/noncode-terminal-promotion-path-2026-08-13.mmd +32 -0
  453. package/skills/omni-digest/package-lock.json +558 -0
  454. package/skills/omni-digest/package.json +13 -0
  455. package/skills/omni-digest/scripts/main.ts +404 -0
  456. package/skills/omni-digest/src/delegate.ts +34 -0
  457. package/skills/omni-digest/src/detect.ts +46 -0
  458. package/skills/omni-digest/src/diagram.ts +72 -0
  459. package/skills/omni-digest/src/domain-staging.ts +50 -0
  460. package/skills/omni-digest/src/env.ts +38 -0
  461. package/skills/omni-digest/src/fetch.ts +237 -0
  462. package/skills/omni-digest/src/media.ts +180 -0
  463. package/skills/omni-digest/src/obsidian.ts +69 -0
  464. package/skills/omni-digest/src/ocr.ts +149 -0
  465. package/skills/omni-digest/src/router.ts +60 -0
  466. package/skills/omni-digest/src/summarize.ts +87 -0
  467. package/skills/omni-digest/src/types.ts +124 -0
  468. package/skills/omni-digest/src/util.ts +34 -0
  469. package/skills/omni-digest/src/visual.ts +129 -0
  470. package/skills/omni-digest/src/x-api.ts +151 -0
  471. package/skills/omni-digest/tsconfig.json +13 -0
  472. package/src/a2a/agent-card.ts +29 -0
  473. package/src/a2a/server.ts +173 -0
  474. package/src/acp/auto-persist.ts +3 -6
  475. package/src/acp/backend-registry.ts +6 -10
  476. package/src/acp/channel-browser-shell.ts +1 -535
  477. package/src/acp/client.ts +106 -36
  478. package/src/acp/fs-roots.ts +20 -4
  479. package/src/acp/obsidian-tags.ts +6 -3
  480. package/src/acp/server.ts +189 -32
  481. package/src/agent/pty-binding.ts +1 -1
  482. package/src/agent/spawn-embodied-agent-in-vw.ts +5 -336
  483. package/src/agent/subagent-callable.ts +39 -1
  484. package/src/agent-mission/browser-login.ts +241 -0
  485. package/src/agent-mission/capabilities-cli.ts +33 -0
  486. package/src/agent-mission/capability-matrix.ts +31 -0
  487. package/src/agent-mission/capability-readers.ts +79 -0
  488. package/src/agent-mission/capability-types.ts +15 -0
  489. package/src/agent-mission/claude-headless.ts +131 -0
  490. package/src/agent-mission/claude-subscription.ts +57 -0
  491. package/src/agent-mission/doc-guided-install.ts +185 -0
  492. package/src/agent-mission/driver.ts +821 -69
  493. package/src/agent-mission/env-profile.ts +68 -0
  494. package/src/agent-mission/handoff.ts +128 -0
  495. package/src/agent-mission/in-agent-plugin.ts +311 -0
  496. package/src/agent-mission/mission-cli.ts +19 -1
  497. package/src/agent-mission/parse.ts +9 -4
  498. package/src/agent-mission/pr-review-watch.ts +62 -13
  499. package/src/agent-mission/resource-ladder.ts +187 -0
  500. package/src/agent-mission/tool-install.ts +249 -0
  501. package/src/agent-mission/tool-ladder.ts +37 -0
  502. package/src/agent-room/room-builder.ts +6 -600
  503. package/src/agent-substrate/review-intent.ts +43 -1
  504. package/src/auth/scope.ts +8 -4
  505. package/src/auth/temp-tokens.ts +131 -0
  506. package/src/auto-research/obsidian-bridge.ts +2 -0
  507. package/src/autopilot/build/integrity-gate.ts +27 -4
  508. package/src/autopilot/build/isolated-instance.ts +2 -1
  509. package/src/autopilot/build/llm-conflict-merge.ts +27 -0
  510. package/src/autopilot/llm-control-brain.ts +54 -12
  511. package/src/autopilot/mission-engine.ts +15 -1
  512. package/src/autopilot/mission-notify.ts +4 -2
  513. package/src/autopilot/mission-origin.ts +5 -5
  514. package/src/autopilot/mission-phase-track.ts +52 -0
  515. package/src/autopilot/mission-tool.ts +1 -1
  516. package/src/autopilot/pty-control-loop.ts +94 -2
  517. package/src/autopilot/track-agent.ts +138 -0
  518. package/src/autopilot/track-courier.ts +153 -0
  519. package/src/boot/acp-server.ts +16 -2
  520. package/src/boot/check-same-origin.ts +19 -5
  521. package/src/boot/daemon-multi-llm-runtime.ts +14 -8
  522. package/src/boot/daemon-prompt-turn.ts +2 -0
  523. package/src/boot/daemon-runtime.ts +36 -14
  524. package/src/boot/daemon-tools/index.ts +16 -0
  525. package/src/boot/daemon-tools/self-implement.ts +4 -0
  526. package/src/boot/daemon-tools/types.ts +3 -0
  527. package/src/browser-cdp/chrome-flags.ts +7 -0
  528. package/src/browser-cdp/client.ts +2 -0
  529. package/src/browser-pane/mount.ts +1 -246
  530. package/src/budget/codex-reset-credit-state.ts +15 -0
  531. package/src/budget/fetchers/codex.ts +2 -1
  532. package/src/budget/run-usage-rollup.ts +11 -4
  533. package/src/budget/unified-usage.ts +2 -1
  534. package/src/capture/tui-self-report.ts +10 -0
  535. package/src/channel-bot-token.ts +126 -0
  536. package/src/chat/index.ts +21 -45
  537. package/src/chat/input-text-key.ts +2 -2
  538. package/src/chat/mode/manual.ts +2 -4
  539. package/src/chat/pickers/state.ts +10 -27
  540. package/src/chat/search/modal.ts +14 -2
  541. package/src/chat/tool-render/types.ts +1 -1
  542. package/src/chat/turn-typeahead.ts +2 -1
  543. package/src/chat/wrap.ts +6 -8
  544. package/src/cli/__fixtures__/agent-help-before/agent.txt +18 -0
  545. package/src/cli/__fixtures__/agent-help-before/registry.txt +13 -0
  546. package/src/cli/__fixtures__/agent-help-before/root.txt +100 -0
  547. package/src/cli/__fixtures__/agent-help-before/tier.txt +15 -0
  548. package/src/cli/a2a-cli.ts +52 -0
  549. package/src/cli/agent-cli.ts +721 -0
  550. package/src/cli/autopilot-cli.ts +739 -0
  551. package/src/cli/bg-launch.ts +20 -4
  552. package/src/cli/claude-plugin-setup.ts +199 -0
  553. package/src/cli/config-test-sync.ts +94 -10
  554. package/src/cli/connector-cli.ts +204 -0
  555. package/src/cli/control-cli.ts +220 -0
  556. package/src/cli/control-join-cli.ts +142 -0
  557. package/src/cli/docs-cli.ts +38 -0
  558. package/src/cli/doctor-cli.ts +225 -26
  559. package/src/cli/doctor-distro.ts +17 -1
  560. package/src/cli/doctor-fix.ts +145 -17
  561. package/src/cli/doctor-llm-assist.ts +71 -0
  562. package/src/cli/doctor-private-files.ts +66 -0
  563. package/src/cli/doctor-readiness.ts +8 -5
  564. package/src/cli/fleet-cli.ts +63 -0
  565. package/src/cli/g6a-registration-probe.ts +16 -0
  566. package/src/cli/git-install-plan.ts +51 -0
  567. package/src/cli/hooks-cli.ts +44 -0
  568. package/src/cli/ingest-token-cli.ts +21 -0
  569. package/src/cli/intake-cli.ts +416 -0
  570. package/src/cli/labels-cli.ts +74 -0
  571. package/src/cli/leader-cli.ts +10 -159
  572. package/src/cli/live-cli.ts +48 -0
  573. package/src/cli/llm-detect-cli.ts +130 -0
  574. package/src/cli/logs-cli.ts +231 -7
  575. package/src/cli/machine-cli.ts +38 -0
  576. package/src/cli/mcp-call.ts +43 -13
  577. package/src/cli/mcp-gateway-cli.ts +90 -0
  578. package/src/cli/mcp-login.ts +116 -8
  579. package/src/cli/mcp-reload.ts +20 -3
  580. package/src/cli/nexus-dist.ts +18 -13
  581. package/src/cli/nexus-ios-bind.ts +20 -7
  582. package/src/cli/ops-cli.ts +225 -0
  583. package/src/cli/plugin-cli.ts +103 -0
  584. package/src/cli/pod-cli.ts +83 -0
  585. package/src/cli/port-lease-local.ts +124 -0
  586. package/src/cli/pr-cli.ts +12 -1
  587. package/src/cli/provider-cli.ts +720 -0
  588. package/src/cli/pty-record-cli.ts +63 -0
  589. package/src/cli/pty-takeover-cli.ts +57 -40
  590. package/src/cli/pty-web-address.ts +52 -0
  591. package/src/cli/publish-cli.ts +44 -0
  592. package/src/cli/pwa-build.ts +18 -12
  593. package/src/cli/pwa-dev.ts +13 -8
  594. package/src/cli/pwa-registry.ts +6 -0
  595. package/src/cli/pwa-share.ts +65 -22
  596. package/src/cli/pwa-show.ts +20 -4
  597. package/src/cli/pwa-start.ts +99 -27
  598. package/src/cli/pwa-test.ts +201 -96
  599. package/src/cli/release-cli.ts +90 -7
  600. package/src/cli/remotes-cli.ts +20 -1
  601. package/src/cli/remotes.ts +2 -1
  602. package/src/cli/repo-cli.ts +315 -36
  603. package/src/cli/research-cli.ts +66 -0
  604. package/src/cli/role-cli.ts +320 -0
  605. package/src/cli/schedule-cli.ts +246 -0
  606. package/src/cli/self-update.ts +98 -10
  607. package/src/cli/setup-cli.ts +64 -2
  608. package/src/cli/shadow-cli.ts +188 -0
  609. package/src/cli/share-auto-mount.ts +12 -8
  610. package/src/cli/start-cli.ts +221 -0
  611. package/src/cli/stdout-flush.ts +8 -0
  612. package/src/cli/storage-cli.ts +334 -0
  613. package/src/cli/tailscale-serve.ts +34 -19
  614. package/src/cli/tasks-cli.ts +176 -0
  615. package/src/cli/test-state-dir-flag.ts +1 -1
  616. package/src/cli/usage-cli.ts +15 -4
  617. package/src/cli/where-cli.ts +22 -55
  618. package/src/code-edit/diff-render.ts +6 -32
  619. package/src/code-edit/source-delta-browser.ts +0 -1
  620. package/src/codex/models.ts +1 -1
  621. package/src/config.ts +8 -13
  622. package/src/connectors/event-ledger.ts +41 -0
  623. package/src/connectors/linear-projector.ts +88 -0
  624. package/src/connectors/linear.ts +143 -0
  625. package/src/connectors/types.ts +19 -0
  626. package/src/control-plane/lease-holder.ts +41 -0
  627. package/src/control-plane/ledger.ts +146 -0
  628. package/src/control-plane/light-member.ts +164 -0
  629. package/src/control-plane/member-tokens.ts +88 -0
  630. package/src/control-plane/member.ts +159 -0
  631. package/src/control-plane/port-lease-heartbeat.ts +101 -0
  632. package/src/control-plane/ports.ts +40 -0
  633. package/src/control-plane/primary.ts +169 -0
  634. package/src/control-plane/server.ts +216 -0
  635. package/src/dashboard/acp-boot.ts +11 -38
  636. package/src/dashboard/assistant-render-state-runtime.ts +2 -2
  637. package/src/dashboard/assistant-sample-runtime.ts +2 -2
  638. package/src/dashboard/auto-compact-runtime.ts +11 -16
  639. package/src/dashboard/browser-help-runtime.ts +2 -3
  640. package/src/dashboard/chat/acp-chat.ts +2 -5
  641. package/src/dashboard/code-edit-post-turn-runtime.ts +1 -2
  642. package/src/dashboard/compact-surface-assembly.ts +0 -14
  643. package/src/dashboard/compact-surface-dispatch.ts +1 -38
  644. package/src/dashboard/compact-surface-inventory.ts +0 -8
  645. package/src/dashboard/compact-surface-runtime.ts +0 -14
  646. package/src/dashboard/context-menu-provider-boot.ts +0 -9
  647. package/src/dashboard/context-window-runtime-boot.ts +0 -37
  648. package/src/dashboard/index.ts +278 -2558
  649. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +0 -6
  650. package/src/dashboard/input/chat-main-slash-command.ts +2 -2
  651. package/src/dashboard/input/dashboard-priority-key-route.ts +1 -43
  652. package/src/dashboard/input/mouse-modal-surface-runtime.ts +1 -5
  653. package/src/dashboard/input/mouse-wiring.ts +2 -3
  654. package/src/dashboard/layout-display-runtime-registration.ts +0 -10
  655. package/src/dashboard/modals/pane-multi.ts +1 -1
  656. package/src/dashboard/replay-preview.ts +1 -1
  657. package/src/dashboard/runtime/approvers.ts +0 -1
  658. package/src/dashboard/runtime/state-snapshot.ts +0 -90
  659. package/src/dashboard/scenario-runtime-boot.ts +16 -16
  660. package/src/dashboard/slash-runtime/dashboard-handlers.ts +134 -1456
  661. package/src/dashboard/slash-runtime/design-pick.ts +96 -0
  662. package/src/dashboard/slash-runtime/help-from-registry.ts +77 -0
  663. package/src/dashboard/surface-registry-wiring.ts +2 -15
  664. package/src/dashboard/turn-message-runtime.ts +0 -4
  665. package/src/dashboard/turn-preamble.ts +1 -1
  666. package/src/dashboard/turn-stream-formatter.ts +2 -2
  667. package/src/dashboard/turn-stream-runtime.ts +2 -2
  668. package/src/dashboard-pane-context-menu.ts +0 -14
  669. package/src/debug/log.ts +7 -0
  670. package/src/decide/boundary-shadow.ts +131 -0
  671. package/src/design/apply-direction.ts +209 -0
  672. package/src/design/css-root-tokens.ts +89 -0
  673. package/src/design/custom-system-create.ts +230 -0
  674. package/src/design/design-directions.ts +61 -41
  675. package/src/design/design-gate.ts +241 -0
  676. package/src/design/design-library.ts +57 -0
  677. package/src/design/design-previews.ts +138 -0
  678. package/src/design/design-systems.ts +61 -0
  679. package/src/design/lint-artifact-run.ts +46 -6
  680. package/src/design/lint-artifact.ts +5 -1
  681. package/src/design/open-design-client.ts +247 -0
  682. package/src/design/system-from-extract.ts +767 -0
  683. package/src/design/system-schema.ts +123 -0
  684. package/src/discord-slash-wire.ts +2 -1
  685. package/src/discord-test-runner.ts +2 -1
  686. package/src/discord-voice-wire.ts +2 -1
  687. package/src/discord.ts +1 -1
  688. package/src/dispatch/opportunistic-launcher.ts +24 -1
  689. package/src/domains/ops-status.ts +35 -2
  690. package/src/domains/outbound-alert.ts +16 -4
  691. package/src/domains/repeated-failure.ts +89 -0
  692. package/src/domains/schedule-manage-tool.ts +28 -8
  693. package/src/domains/schedule-migrate.ts +22 -4
  694. package/src/domains/schedule-registry.ts +88 -33
  695. package/src/domains/schedule-runs.ts +132 -0
  696. package/src/domains/schedule-state.ts +152 -0
  697. package/src/element-registry/address.ts +1 -3
  698. package/src/git-fs/gh-cli.ts +47 -17
  699. package/src/git-fs/retry.ts +1 -0
  700. package/src/git-fs/runner.ts +1 -0
  701. package/src/git-fs/worktree.ts +6 -5
  702. package/src/github/pr-labels.ts +68 -0
  703. package/src/graph-kinds/plugin-nodes.ts +60 -0
  704. package/src/graph-kinds/registry.ts +118 -0
  705. package/src/graph-runner/graph-cli.ts +103 -0
  706. package/src/graph-runner/graph-notify.ts +220 -0
  707. package/src/graph-runner/graph-tick.ts +119 -0
  708. package/src/graph-runner/release-manifest.ts +93 -0
  709. package/src/graph-runner/runner.ts +457 -0
  710. package/src/grok/credential.ts +158 -5
  711. package/src/grounding/ensure-grounding.ts +131 -0
  712. package/src/grounding/mirror-export.ts +89 -0
  713. package/src/grounding/mirror-manifest.ts +252 -0
  714. package/src/grounding/sources-cli.ts +209 -0
  715. package/src/grounding/sources.ts +333 -0
  716. package/src/grounding/token.ts +115 -0
  717. package/src/harness/harness-cli-command.ts +352 -19
  718. package/src/harness/harness-pod-dispatch.ts +110 -0
  719. package/src/harness/harness-stop.ts +131 -0
  720. package/src/harness/harness-substrate-default.ts +40 -0
  721. package/src/harness/harness-worktrees.ts +1 -1
  722. package/src/harness/harness-write-boundary.ts +2 -0
  723. package/src/harness/llm-decompose.ts +2 -1
  724. package/src/harness/self-send-decide.ts +224 -0
  725. package/src/harness/shell-relay.ts +5 -0
  726. package/src/hooks/providers.ts +77 -0
  727. package/src/hooks/queue.ts +73 -0
  728. package/src/hooks/receiver.ts +133 -0
  729. package/src/index.ts +666 -3406
  730. package/src/input-core/dispatcher.ts +1 -1
  731. package/src/input-core/drag-esc-interceptor.ts +1 -1
  732. package/src/instance/current.ts +5 -5
  733. package/src/instance/leader.ts +10 -326
  734. package/src/instance/nexus-run-refusal.ts +27 -92
  735. package/src/instance/project-local-exclude.ts +27 -0
  736. package/src/instance/resolve.ts +40 -175
  737. package/src/intake-plane/capture.ts +14 -1
  738. package/src/intake-plane/check.ts +34 -14
  739. package/src/intake-plane/collect-github.ts +258 -0
  740. package/src/intake-plane/collect-pod.ts +100 -0
  741. package/src/intake-plane/collect-telegram-saved.ts +86 -0
  742. package/src/intake-plane/digest.ts +102 -0
  743. package/src/intake-plane/enrich-plugins.ts +1 -1
  744. package/src/intake-plane/front-classifier.ts +56 -0
  745. package/src/intake-plane/front-route-classifier.ts +80 -0
  746. package/src/intake-plane/front-route-rules.ts +152 -0
  747. package/src/intake-plane/grounding-docs.ts +185 -0
  748. package/src/intake-plane/harness-target.ts +20 -0
  749. package/src/intake-plane/intake-to-tasks.ts +303 -0
  750. package/src/intake-plane/items.ts +247 -0
  751. package/src/intake-plane/link-ledger.ts +27 -0
  752. package/src/intake-plane/route.ts +104 -0
  753. package/src/intake-plane/runtime-callables.ts +3 -1
  754. package/src/intake-plane/sketch-ledger.ts +34 -0
  755. package/src/intake-plane/slash.ts +30 -2
  756. package/src/intake-plane/submit-intake-work.ts +160 -0
  757. package/src/intake-plane/telegram-work.ts +56 -0
  758. package/src/iul/sidebar-shell.ts +0 -165
  759. package/src/launch-head/capability-check.ts +162 -0
  760. package/src/launch-head/launch-head-cli.ts +242 -0
  761. package/src/launch-head/load-balance.ts +81 -0
  762. package/src/live/detail-switch.ts +175 -0
  763. package/src/llm/provider-detect.ts +247 -0
  764. package/src/llm/provider-probe.ts +57 -0
  765. package/src/llm.ts +55 -23
  766. package/src/log-entry.ts +1 -1
  767. package/src/log-pane/attachment-popup.ts +1 -2
  768. package/src/loops/loop-cli.ts +37 -0
  769. package/src/loops/registry.ts +174 -0
  770. package/src/market/official-keys.ts +5 -0
  771. package/src/market/publish.ts +273 -0
  772. package/src/market/signed-index.ts +156 -0
  773. package/src/market/tgz.ts +121 -0
  774. package/src/mcp/client.ts +1 -1
  775. package/src/mcp/mcp-oauth.ts +40 -5
  776. package/src/mcp/server.ts +75 -7
  777. package/src/mcp-gateway/gateway.ts +128 -0
  778. package/src/mcp-gateway/pat-store.ts +124 -0
  779. package/src/mss/logging/log-store.ts +91 -2
  780. package/src/mss/logging/scoped-level.ts +5 -9
  781. package/src/native-tool-catalog.ts +64 -343
  782. package/src/nexus/api/connect-info.ts +23 -25
  783. package/src/nexus/api/context-url.ts +1 -1
  784. package/src/nexus/api/design-check.ts +90 -59
  785. package/src/nexus/api/design-previews-route.ts +182 -0
  786. package/src/nexus/api/design-system-create-route.ts +123 -0
  787. package/src/nexus/api/graph-kinds.ts +69 -0
  788. package/src/nexus/api/graphs-api.ts +221 -0
  789. package/src/nexus/api/harness-api.ts +31 -2
  790. package/src/nexus/api/health.ts +15 -0
  791. package/src/nexus/api/http-server.ts +274 -43
  792. package/src/nexus/api/image-generate.ts +3 -0
  793. package/src/nexus/api/ingest-token.ts +175 -0
  794. package/src/nexus/api/intake-ledger-api.ts +54 -0
  795. package/src/nexus/api/intake-route.ts +111 -0
  796. package/src/nexus/api/json-response.ts +33 -0
  797. package/src/nexus/api/live-detail.ts +47 -0
  798. package/src/nexus/api/live-shipped.ts +78 -0
  799. package/src/nexus/api/log-fabric.ts +33 -2
  800. package/src/nexus/api/markdown-publish.ts +3 -2
  801. package/src/nexus/api/mcp-http.ts +14 -9
  802. package/src/nexus/api/mcp-oauth-hint.ts +30 -0
  803. package/src/nexus/api/mcp-public-allowlist.ts +33 -0
  804. package/src/nexus/api/merge-approvals-gate.ts +79 -0
  805. package/src/nexus/api/merge-approvals.ts +306 -0
  806. package/src/nexus/api/meta-api.ts +4 -0
  807. package/src/nexus/api/next-fluent-wiring.ts +7 -9
  808. package/src/nexus/api/plugins-market.ts +125 -0
  809. package/src/nexus/api/pod-credential-api.ts +133 -0
  810. package/src/nexus/api/public-routes.ts +80 -0
  811. package/src/nexus/api/rest-route-paths.ts +15 -0
  812. package/src/nexus/api/schedules-action.ts +12 -3
  813. package/src/nexus/api/schedules-read.ts +228 -0
  814. package/src/nexus/api/sessions-store.ts +8 -2
  815. package/src/nexus/api/setup-answer-priority.ts +130 -0
  816. package/src/nexus/api/setup-channel-bot.ts +56 -0
  817. package/src/nexus/api/setup-child-llm.ts +228 -0
  818. package/src/nexus/api/setup-obsidian-skills.ts +93 -0
  819. package/src/nexus/api/task-cards-api.ts +34 -0
  820. package/src/nexus/api/tasks-create.ts +136 -0
  821. package/src/nexus/api/telegram-trigger-bot.ts +3 -3
  822. package/src/nexus/api/terminals.ts +204 -18
  823. package/src/nexus/api/trace.ts +354 -0
  824. package/src/nexus/api/vault-api.ts +140 -7
  825. package/src/nexus/api/worktrees.ts +18 -2
  826. package/src/nexus/boot/register-mcp-clients.ts +38 -4
  827. package/src/nexus/daemon-endpoint.ts +85 -0
  828. package/src/nexus/default-port.ts +1 -0
  829. package/src/nexus/index.ts +329 -111
  830. package/src/nexus/onboarding/pwa-share-prompt.ts +31 -8
  831. package/src/nexus/onboarding/tailscale-probe.ts +9 -1
  832. package/src/nexus/setup-status.ts +58 -0
  833. package/src/nexus/supervisor/lock.ts +8 -0
  834. package/src/nexus/webterm/pty.ts +15 -0
  835. package/src/oauth/codex-account-rotation.ts +122 -16
  836. package/src/oauth/codex-account-store.ts +88 -19
  837. package/src/oauth/codex-quota-policy.ts +55 -0
  838. package/src/oauth/store.ts +28 -25
  839. package/src/obsidian/default-vault.ts +17 -0
  840. package/src/obsidian/vault-write-guard.ts +46 -0
  841. package/src/onboarding/help/llm.md +2 -2
  842. package/src/onboarding.ts +2 -2
  843. package/src/panes/alt-skip-predicate.ts +4 -3
  844. package/src/panes/external-terminal-pane.ts +3 -4
  845. package/src/panes/factory.ts +1 -18
  846. package/src/panes/index.ts +1 -5
  847. package/src/panes/pane-cycle.ts +1 -1
  848. package/src/panes/types.ts +1 -1
  849. package/src/platform/env-literal.ts +4 -0
  850. package/src/plugin-hooks/dispatcher.ts +10 -4
  851. package/src/plugins/core/host.ts +94 -4
  852. package/src/plugins/core/manifest.ts +104 -7
  853. package/src/plugins/install/market-fetch.ts +249 -0
  854. package/src/plugins/install/plugin-install.ts +387 -0
  855. package/src/policy/claude-subscription-guard.ts +25 -0
  856. package/src/preview/terminal.ts +24 -1
  857. package/src/preview-pane/mount.ts +1 -142
  858. package/src/prompt/references.ts +4 -51
  859. package/src/pty-shell/pty-control-ipc.ts +57 -3
  860. package/src/pty-shell/pty-mouse.ts +75 -0
  861. package/src/pty-shell/pty-recording.ts +108 -0
  862. package/src/pty-shell/registry.ts +53 -3
  863. package/src/python/resolve-python.ts +1 -1
  864. package/src/release-loop/manifest.ts +65 -0
  865. package/src/release-loop/release-note.ts +174 -0
  866. package/src/roles/lease-cas.ts +52 -0
  867. package/src/roles/machine-name.ts +48 -0
  868. package/src/roles/machine-profile.ts +65 -0
  869. package/src/roles/role-lease-read.ts +81 -0
  870. package/src/roles/role-lease.ts +63 -0
  871. package/src/roles/role-watch.ts +69 -0
  872. package/src/self-dev/ask-launch-flow.ts +39 -22
  873. package/src/self-dev/ask-launch-io.ts +1 -1
  874. package/src/self-dev/dev-cli.ts +250 -139
  875. package/src/self-dev/dev-pipeline.ts +80 -8
  876. package/src/self-dev/draft-sweep.ts +231 -0
  877. package/src/self-dev/draft-triage-rules.ts +42 -0
  878. package/src/self-dev/entrance-baseline.ts +156 -4
  879. package/src/self-dev/fabric-decompose-adapter.ts +10 -0
  880. package/src/self-dev/launch-preflight.ts +1 -1
  881. package/src/self-dev/orchestrate.ts +297 -20
  882. package/src/self-dev/repair-signals.ts +6 -0
  883. package/src/self-dev/run-store.ts +20 -5
  884. package/src/self-dev/run-supervisor.ts +43 -3
  885. package/src/self-implement/abandoned-classification.ts +15 -1
  886. package/src/self-implement/blocked-draft-policy.ts +6 -0
  887. package/src/self-implement/budget-gate.ts +236 -0
  888. package/src/self-implement/child-llm-preference.ts +84 -0
  889. package/src/self-implement/decision-events.ts +57 -0
  890. package/src/self-implement/decision-signal-press.ts +5 -2
  891. package/src/self-implement/dependency-change-gate.ts +90 -0
  892. package/src/self-implement/gate-baseline.ts +32 -1
  893. package/src/self-implement/gate-cli.ts +29 -7
  894. package/src/self-implement/gate-scope.ts +7 -1
  895. package/src/self-implement/goal-author-decompose.ts +22 -4
  896. package/src/self-implement/goal-author.ts +23 -2
  897. package/src/self-implement/goal-boundary.ts +65 -0
  898. package/src/self-implement/goal-clarification-escalation.ts +1 -0
  899. package/src/self-implement/goal-documents-dir.ts +6 -1
  900. package/src/self-implement/goal-execution-records.ts +58 -0
  901. package/src/self-implement/goal-run-store.ts +42 -24
  902. package/src/self-implement/graph-authority.ts +13 -28
  903. package/src/self-implement/graph-catalog.ts +48 -0
  904. package/src/self-implement/graph-run-contract.ts +127 -0
  905. package/src/self-implement/graph-templates.ts +14 -7
  906. package/src/self-implement/graph-yaml.ts +35 -6
  907. package/src/self-implement/harness-policy-gates.ts +42 -0
  908. package/src/self-implement/headless-elanous-driver.ts +30 -6
  909. package/src/self-implement/heal-triage.ts +229 -0
  910. package/src/self-implement/host-regate.ts +240 -0
  911. package/src/self-implement/non-git-consent.ts +23 -0
  912. package/src/self-implement/orchestrator.ts +481 -132
  913. package/src/self-implement/pipeline-shape.ts +1 -1
  914. package/src/self-implement/pr-evidence-artifact.ts +6 -19
  915. package/src/self-implement/prior-draft-findings.ts +128 -0
  916. package/src/self-implement/pwa-import-graph.ts +65 -0
  917. package/src/self-implement/repo-provision.ts +18 -21
  918. package/src/self-implement/report-origin.ts +39 -0
  919. package/src/self-implement/rework-policy.ts +21 -0
  920. package/src/self-implement/run-ledger-compact.ts +438 -0
  921. package/src/self-implement/run-ledger.ts +212 -29
  922. package/src/self-implement/run-report.ts +24 -0
  923. package/src/self-implement/run-status-mapping.ts +2 -0
  924. package/src/self-implement/running-runs.ts +112 -14
  925. package/src/self-implement/scoped-typecheck-config.ts +49 -0
  926. package/src/self-implement/seams.ts +203 -38
  927. package/src/self-implement/self-implement-cli.ts +17 -2
  928. package/src/self-implement/shadow-repo.ts +350 -0
  929. package/src/self-implement/supervision-vocabulary.ts +7 -0
  930. package/src/shell-runner/dispatch.ts +3 -0
  931. package/src/shell-runner/index.ts +0 -7
  932. package/src/skills/runner.ts +0 -69
  933. package/src/skills/tools/agent-room-slash.ts +2 -1
  934. package/src/skills/tools/agent-room.ts +8 -140
  935. package/src/skills/tools/agent.ts +5 -3
  936. package/src/skills/tools/context.ts +5 -140
  937. package/src/skills/tools/control.ts +4 -188
  938. package/src/skills/tools/dashboard-slash.ts +3 -11
  939. package/src/skills/tools/dashboard-state.ts +3 -5
  940. package/src/skills/tools/dev-harness.ts +3 -2
  941. package/src/skills/tools/omni-search.ts +29 -1
  942. package/src/skills/tools/shell.ts +11 -29
  943. package/src/skills/tools/spawn-coding-agent-headless.ts +6 -9
  944. package/src/ssh/ssh-picker-modal.ts +1 -1
  945. package/src/steward/directive.ts +99 -0
  946. package/src/steward/triage.ts +203 -0
  947. package/src/storage/cli-bin.ts +67 -0
  948. package/src/storage/object-store-visibility.ts +169 -0
  949. package/src/storage/object-store.ts +452 -0
  950. package/src/storage/s3.ts +53 -10
  951. package/src/storage/storage-detect.ts +337 -0
  952. package/src/surface/address.ts +3 -5
  953. package/src/surface/index.ts +0 -6
  954. package/src/surface/llm-tools.ts +1 -2
  955. package/src/surface/shell-runner-boot.ts +4 -89
  956. package/src/task-cards/card-cli.ts +64 -0
  957. package/src/task-cards/card-store.ts +241 -0
  958. package/src/task-orchestrator/boot.ts +27 -1
  959. package/src/task-orchestrator/dispatcher.ts +49 -7
  960. package/src/task-orchestrator/external-fingerprint.ts +10 -0
  961. package/src/task-orchestrator/external-policy.ts +86 -0
  962. package/src/task-orchestrator/feedback-loop.ts +4 -2
  963. package/src/task-orchestrator/graph.ts +18 -1
  964. package/src/task-orchestrator/runtimes/create.ts +128 -0
  965. package/src/task-orchestrator/store.ts +78 -18
  966. package/src/task-orchestrator/surface-registry.ts +5 -2
  967. package/src/task-orchestrator/surfaces/external-exec.ts +180 -0
  968. package/src/task-orchestrator/surfaces/idea-approval-pr.ts +118 -0
  969. package/src/task-orchestrator/surfaces/index.ts +4 -3
  970. package/src/task-orchestrator/surfaces/pod-account-broker.ts +60 -5
  971. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +136 -0
  972. package/src/task-orchestrator/surfaces/pod-command-job.ts +348 -0
  973. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +177 -0
  974. package/src/task-orchestrator/surfaces/pod-pool.ts +128 -12
  975. package/src/task-orchestrator/surfaces/pod-skills.ts +11 -3
  976. package/src/task-orchestrator/surfaces/pod-source-bundle.ts +132 -0
  977. package/src/task-orchestrator/surfaces/pod-source-receive.ts +91 -0
  978. package/src/task-orchestrator/surfaces/pod-source-spec.ts +77 -0
  979. package/src/task-orchestrator/surfaces/self-implement-pod.ts +782 -41
  980. package/src/task-orchestrator/surfaces/self-implement.ts +8 -1
  981. package/src/task-orchestrator/tox-loop.ts +204 -0
  982. package/src/task-orchestrator/types.ts +21 -1
  983. package/src/telegram-commands.ts +8 -0
  984. package/src/telegram-report.ts +2 -1
  985. package/src/telegram-run.ts +18 -5
  986. package/src/telegram.ts +92 -22
  987. package/src/tool-runtime/acp-session-runtime.ts +28 -7
  988. package/src/tool-runtime/agent-runtime.ts +1 -0
  989. package/src/tool-runtime/context-runtime.ts +18 -35
  990. package/src/tool-runtime/control-runtime.ts +8 -21
  991. package/src/tool-runtime/dashboard-state-runtime.ts +1 -5
  992. package/src/tool-runtime/elanous-asana-runtimes.ts +205 -0
  993. package/src/tool-runtime/elanous-control-runtimes.ts +16 -2
  994. package/src/tool-runtime/elanous-task-submit-runtime.ts +124 -0
  995. package/src/tool-runtime/index.ts +4 -1
  996. package/src/tool-runtime/scenario-runtimes.ts +22 -21
  997. package/src/tool-runtime/scenario-target-mount.ts +6 -32
  998. package/src/tool-runtime/types.ts +8 -0
  999. package/src/tui/chat/attachment-summary.ts +4 -4
  1000. package/src/tui-client/headless-core-guard.ts +0 -1
  1001. package/src/tui.ts +8 -5
  1002. package/src/typecheck-ratchet.ts +15 -0
  1003. package/src/ui/hover-presenter.ts +3 -7
  1004. package/src/user-config.ts +427 -190
  1005. package/src/version/code-revision.ts +33 -8
  1006. package/src/version/packed-revision.json +1 -1
  1007. package/src/video-pipeline/broll-agent.ts +102 -0
  1008. package/src/video-pipeline/recipes/broll.ts +263 -0
  1009. package/src/video-pipeline/walk-line.ts +2 -1
  1010. package/src/views/scratch-image-size.ts +10 -0
  1011. package/src/voice/channel-adapters/pwa-voice-adapter.ts +2 -18
  1012. package/src/voice/channel-adapters/telegram-voice-adapter.ts +1 -6
  1013. package/src/voice/voice-tts-singleton.ts +46 -8
  1014. package/src/web-push/vapid-keys.ts +1 -1
  1015. package/src/web-search/index.ts +5 -5
  1016. package/src/web-terminal/preview-tap-registry.ts +152 -43
  1017. package/src/workflow-runtime/executor.ts +18 -22
  1018. package/src/workflow-runtime/node-catalog.ts +20 -1
  1019. package/src/workflow-runtime/nodes/bash.ts +1 -0
  1020. package/src/workflow-runtime/nodes/task.ts +74 -0
  1021. package/src/workflow-runtime/nodes/triggers.ts +24 -1
  1022. package/src/workflow-runtime/plugin-kind-node.ts +138 -0
  1023. package/src/workflow-runtime/schema.ts +98 -2
  1024. package/src/workflow-runtime/triggers/webhook-router.ts +43 -3
  1025. package/src/workflow-runtime/triggers/webhook-source.ts +19 -1
  1026. package/src/workflow-runtime/types.ts +74 -4
  1027. package/apps/pwa/out/_next/static/Ksn99fVf2HUWhSyV1-FC8/_buildManifest.js +0 -1
  1028. package/apps/pwa/out/_next/static/chunks/1176-4943bd83b00e53a2.js +0 -25
  1029. package/apps/pwa/out/_next/static/chunks/1380-9c652e1002032c86.js +0 -1
  1030. package/apps/pwa/out/_next/static/chunks/1863-2ea170dfec26b88b.js +0 -1
  1031. package/apps/pwa/out/_next/static/chunks/2091-2d6b7f4f16300f83.js +0 -1
  1032. package/apps/pwa/out/_next/static/chunks/2347-366617ec73babe3b.js +0 -1
  1033. package/apps/pwa/out/_next/static/chunks/2598.814f64e3268634e7.js +0 -1
  1034. package/apps/pwa/out/_next/static/chunks/3089-e60cc8f5d35ee239.js +0 -1
  1035. package/apps/pwa/out/_next/static/chunks/3158-c77ed9ea34f9cc9f.js +0 -1
  1036. package/apps/pwa/out/_next/static/chunks/3607-f0b5c5ee18fcf56a.js +0 -1
  1037. package/apps/pwa/out/_next/static/chunks/3659-05b2d5d971b42dbc.js +0 -1
  1038. package/apps/pwa/out/_next/static/chunks/3736-b6a7bfdcb8f56ec6.js +0 -1
  1039. package/apps/pwa/out/_next/static/chunks/3839-eebf298e89a7bb77.js +0 -1
  1040. package/apps/pwa/out/_next/static/chunks/4012.832a2824b978e7ee.js +0 -5
  1041. package/apps/pwa/out/_next/static/chunks/4706-d85d7f3345f3ff91.js +0 -1
  1042. package/apps/pwa/out/_next/static/chunks/526-17a6a2e0e6dc4498.js +0 -1
  1043. package/apps/pwa/out/_next/static/chunks/5508-676ac75f2757ad40.js +0 -1
  1044. package/apps/pwa/out/_next/static/chunks/5583-8a0317f4b8e68db9.js +0 -1
  1045. package/apps/pwa/out/_next/static/chunks/5927.8378481a12cc8044.js +0 -1
  1046. package/apps/pwa/out/_next/static/chunks/6258-b58f722b10e8d31d.js +0 -1
  1047. package/apps/pwa/out/_next/static/chunks/6820-32fd097e6186fdc9.js +0 -1
  1048. package/apps/pwa/out/_next/static/chunks/6852-983db7ca958634b7.js +0 -1
  1049. package/apps/pwa/out/_next/static/chunks/7235-e583e4a015e159b9.js +0 -1
  1050. package/apps/pwa/out/_next/static/chunks/7482-7b417330b24a996a.js +0 -1
  1051. package/apps/pwa/out/_next/static/chunks/7701-99b7d4dedb955bf8.js +0 -1
  1052. package/apps/pwa/out/_next/static/chunks/77f1928d-bd3777589042d3ea.js +0 -1
  1053. package/apps/pwa/out/_next/static/chunks/8366-36956cafc5e33614.js +0 -1
  1054. package/apps/pwa/out/_next/static/chunks/8370-23d0de995be666f8.js +0 -1
  1055. package/apps/pwa/out/_next/static/chunks/8617-307421f3b0e8b2a2.js +0 -1
  1056. package/apps/pwa/out/_next/static/chunks/8837-e45de46a9fedf1f5.js +0 -1
  1057. package/apps/pwa/out/_next/static/chunks/9058-0e8055a5ea3ebdd6.js +0 -1
  1058. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-84b84eca12acada4.js +0 -1
  1059. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-1f23568c29e88f7a.js +0 -1
  1060. package/apps/pwa/out/_next/static/chunks/app/botlab/page-bf6fc9aafd6135a7.js +0 -1
  1061. package/apps/pwa/out/_next/static/chunks/app/bots/page-3f8539ae4b719d2e.js +0 -1
  1062. package/apps/pwa/out/_next/static/chunks/app/chat/page-d2900febb74ecf32.js +0 -1
  1063. package/apps/pwa/out/_next/static/chunks/app/control/page-e82dec647dd79c36.js +0 -1
  1064. package/apps/pwa/out/_next/static/chunks/app/dashboard/page-096ec743a8ee955a.js +0 -1
  1065. package/apps/pwa/out/_next/static/chunks/app/design-check/page-255c2ceded4b3493.js +0 -1
  1066. package/apps/pwa/out/_next/static/chunks/app/healthz/route-84b84eca12acada4.js +0 -1
  1067. package/apps/pwa/out/_next/static/chunks/app/intake/page-2db61b2f9efba61f.js +0 -1
  1068. package/apps/pwa/out/_next/static/chunks/app/layout-e11ee17f221aaa9b.js +0 -1
  1069. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e075974e029ce4c4.js +0 -1
  1070. package/apps/pwa/out/_next/static/chunks/app/morning/page-ec5b68a9af3366a0.js +0 -1
  1071. package/apps/pwa/out/_next/static/chunks/app/not-found-986c177afb4adae6.js +0 -1
  1072. package/apps/pwa/out/_next/static/chunks/app/observatory/page-a72781461af2f2a3.js +0 -1
  1073. package/apps/pwa/out/_next/static/chunks/app/page-92781cbaafc487ad.js +0 -1
  1074. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2c14d2a1f2930f33.js +0 -1
  1075. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-22ee4bf8070b2b4d.js +0 -1
  1076. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9c06e4a8297942a8.js +0 -1
  1077. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d0cd32f6d373798f.js +0 -1
  1078. package/apps/pwa/out/_next/static/chunks/app/settings/page-0c1642018d87ebb8.js +0 -1
  1079. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-93e5e97d614df487.js +0 -1
  1080. package/apps/pwa/out/_next/static/chunks/app/setup/layout-84b84eca12acada4.js +0 -1
  1081. package/apps/pwa/out/_next/static/chunks/app/setup/page-b1ce871940d7393e.js +0 -1
  1082. package/apps/pwa/out/_next/static/chunks/app/share/page-ae154addf345febe.js +0 -1
  1083. package/apps/pwa/out/_next/static/chunks/app/showroom/page-90af3aa813d2053c.js +0 -1
  1084. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f3f962fda428a738.js +0 -1
  1085. package/apps/pwa/out/_next/static/chunks/app/term/page-1c1f7cc1d5def06d.js +0 -1
  1086. package/apps/pwa/out/_next/static/chunks/app/vault/page-09d4cbdaaacf06c1.js +0 -1
  1087. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e877b8e8ca90b27f.js +0 -1
  1088. package/apps/pwa/out/_next/static/chunks/app/workflows/page-71d902f463dea526.js +0 -1
  1089. package/apps/pwa/out/_next/static/chunks/app/workspace/page-40ea576cefa25fe6.js +0 -1
  1090. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a56a3f178c3831f6.js +0 -1
  1091. package/apps/pwa/out/_next/static/chunks/bcc499d1-804a270d878e0842.js +0 -1
  1092. package/apps/pwa/out/_next/static/chunks/framework-b25b7c5501c59b6d.js +0 -1
  1093. package/apps/pwa/out/_next/static/chunks/main-a9ec9da43387afff.js +0 -1
  1094. package/apps/pwa/out/_next/static/chunks/main-app-aa2c05954aaa6754.js +0 -1
  1095. package/apps/pwa/out/_next/static/chunks/pages/_app-bb3768fb4b84aebb.js +0 -1
  1096. package/apps/pwa/out/_next/static/chunks/pages/_error-2820ba75b87b2f5e.js +0 -1
  1097. package/apps/pwa/out/_next/static/chunks/webpack-58c73b145f189b1c.js +0 -1
  1098. package/apps/pwa/out/_next/static/css/effec8adf767aa75.css +0 -1
  1099. package/apps/pwa/out/dashboard/index.html +0 -1
  1100. package/apps/pwa/out/dashboard/index.txt +0 -26
  1101. package/src/acp/resident-shell.ts +0 -244
  1102. package/src/agent/spawn-local-llm-in-vw.ts +0 -240
  1103. package/src/dashboard/agent-spawn-tools-boot.ts +0 -14
  1104. package/src/dashboard/dock-picker-inventory.ts +0 -41
  1105. package/src/dashboard/goal-plan-hud-bridge.ts +0 -112
  1106. package/src/dashboard/hud-mirror.ts +0 -207
  1107. package/src/dashboard/input/mouse-dock-runtime.ts +0 -156
  1108. package/src/dashboard/input/mouse-hover-runtime.ts +0 -46
  1109. package/src/dashboard/input/mouse-pill-context-runtime.ts +0 -74
  1110. package/src/dashboard/input/mouse-workspace-restore-runtime.ts +0 -64
  1111. package/src/dashboard/input/scratch-actions.ts +0 -36
  1112. package/src/dashboard/input/virtual-window-key-router.ts +0 -24
  1113. package/src/dashboard/rich-scratch-viewers.ts +0 -77
  1114. package/src/dashboard/scratch-slash-runtime.ts +0 -36
  1115. package/src/dashboard/scratch-state-runtime.ts +0 -42
  1116. package/src/dashboard/scratch-widget-runtime.ts +0 -37
  1117. package/src/dashboard/sim-shell.ts +0 -313
  1118. package/src/dashboard/virtual-window-control-runtime.ts +0 -57
  1119. package/src/dashboard/virtual-window-help-runtime.ts +0 -113
  1120. package/src/dashboard/virtual-window-input-runtime.ts +0 -99
  1121. package/src/dashboard/virtual-window-mutation-runtime.ts +0 -102
  1122. package/src/dashboard/virtual-window-split-runtime.ts +0 -70
  1123. package/src/dashboard/vw-popup-openers.ts +0 -126
  1124. package/src/dashboard/window-picker-popup.ts +0 -74
  1125. package/src/dashboard/window-slash-runtime.ts +0 -108
  1126. package/src/dashboard/windowing/companion-slash.ts +0 -78
  1127. package/src/dashboard/windowing/fast-switch.ts +0 -138
  1128. package/src/dashboard/windowing/lifecycle.ts +0 -185
  1129. package/src/dashboard/windowing/virtual-windows.ts +0 -259
  1130. package/src/dashboard/windowing/visibility-chord.ts +0 -77
  1131. package/src/iul/resident-vw.ts +0 -55
  1132. package/src/panes/content-adapter.ts +0 -162
  1133. package/src/prompt/vw-reference.ts +0 -153
  1134. package/src/shell-runner/external-terminal-pane.ts +0 -157
  1135. package/src/sim/resident-vw.ts +0 -48
  1136. package/src/skills/tools/spawn-coding-agent-vw.ts +0 -181
  1137. package/src/skills/tools/virtual-windows.ts +0 -632
  1138. package/src/surface/adapters/window-surface-adapter.ts +0 -141
  1139. package/src/tool-runtime/layout-runtimes.ts +0 -81
  1140. package/src/tool-runtime/scenario-window-mount.ts +0 -207
  1141. package/src/views/ui-mode.ts +0 -100
  1142. package/src/virtual-window-context-menu.ts +0 -97
  1143. package/src/virtual-windows/addressing.ts +0 -195
  1144. package/src/virtual-windows/benchmark-preset.ts +0 -119
  1145. package/src/virtual-windows/event-bus.ts +0 -202
  1146. package/src/virtual-windows/layout/apply-planner.ts +0 -189
  1147. package/src/virtual-windows/layout/index.ts +0 -68
  1148. package/src/virtual-windows/layout/layout-commands.ts +0 -186
  1149. package/src/virtual-windows/layout/layout-tools.ts +0 -262
  1150. package/src/virtual-windows/layout/persistence.ts +0 -219
  1151. package/src/virtual-windows/layout/presets.ts +0 -114
  1152. package/src/virtual-windows/layout/restore-planner.ts +0 -223
  1153. package/src/virtual-windows/layout/serializer.ts +0 -197
  1154. package/src/virtual-windows/layout/tree.ts +0 -147
  1155. package/src/virtual-windows/layout/types.ts +0 -63
  1156. package/src/virtual-windows/layout-tree.ts +0 -389
  1157. package/src/virtual-windows/navigation.ts +0 -251
  1158. package/src/virtual-windows/pane-capture.ts +0 -142
  1159. package/src/virtual-windows/pane-content.ts +0 -611
  1160. package/src/virtual-windows/pane-spawner.ts +0 -278
  1161. package/src/virtual-windows/pty-tail-content.ts +0 -291
  1162. package/src/virtual-windows/resident-window.ts +0 -59
  1163. package/src/virtual-windows/secondary-action.ts +0 -25
  1164. package/src/virtual-windows/terminal-slot-content.ts +0 -165
  1165. package/src/virtual-windows/virtual-window.ts +0 -1301
  1166. package/src/virtual-windows/vw-local-input-target-popup.ts +0 -110
  1167. package/src/virtual-windows/vw-rename-modal.ts +0 -77
  1168. package/src/virtual-windows/vw-selector-popup.ts +0 -177
  1169. package/src/virtual-windows/window-registry.ts +0 -519
  1170. package/src/voice/channel-adapters/discord-voice-adapter.ts +0 -202
  1171. package/src/voice/voice-pwa-dispatch.ts +0 -245
  1172. package/src/window-picker-modal.ts +0 -135
  1173. /package/apps/pwa/out/_next/static/{Ksn99fVf2HUWhSyV1-FC8 → zoQX5iTvXOsIvCjxCe1Ji}/_ssgManifest.js +0 -0
  1174. /package/src/dashboard/{companion-slash-runtime.ts → companion-messages-runtime.ts} +0 -0
@@ -1,1301 +0,0 @@
1
- // VirtualWindow — VW-P4.
2
- //
3
- // A VirtualWindow owns a layout tree of panes (LayoutNode) plus a
4
- // map of paneId → PaneContent. It renders as a single ModalSurface
5
- // that covers the coordinator's grid (exactly one is foreground at
6
- // a time; others are detached — see WindowRegistry, VW-P5).
7
- //
8
- // Key routing:
9
- // • The dashboard-level prefix chord (Ctrl+B + sequence) is
10
- // intercepted BEFORE this class sees a key. When a key reaches
11
- // VirtualWindow.onKey, it's destined for the focused pane.
12
- // • Pane-content delegates return the standard Action shape so
13
- // tests + plugin hooks stay uniform.
14
-
15
- import { ansi, C, visibleWidth, stripAnsi } from '../tui.js';
16
- import { debug } from '../debug/log.js';
17
- import { DEFAULT_HOST_CHROME_PROFILE } from '../display/host-chrome-profile.js';
18
- import {
19
- allPaneIds,
20
- closePane,
21
- dividerAt,
22
- focusNeighbor,
23
- layoutRects,
24
- leaf,
25
- paneAt,
26
- resizePane,
27
- splitPane,
28
- SplitRejectedError,
29
- type Axis,
30
- type Direction,
31
- type DividerHit,
32
- type LayoutNode,
33
- type Rect,
34
- type SplitLimits,
35
- } from './layout-tree.js';
36
- import type { PaneRect } from './layout-tree.js';
37
- import type { PaneBroadcast, PaneContent } from './pane-content.js';
38
- import type { ModalBounds, ModalSurface } from '../display/modal-stack.js';
39
- import {
40
- isCaptureSessionEndMouseEventType,
41
- isCaptureSessionMouseEventType,
42
- isPrimaryDiscreteClickMouseEventType,
43
- isSecondaryClickMouseEventType,
44
- type Action,
45
- type DisplayMouseEvent,
46
- type KeyEvent,
47
- type SurfaceId,
48
- } from '../display/types.js';
49
- import type { CursorState } from '../display/cursor-state.js';
50
- import type { WindowId, PaneId } from './addressing.js';
51
- import { composeVisibilityBadge, badgeVisibleWidth } from '../panes/visibility-badge.js';
52
- import type { PaneVisibility } from '../panes/visual-state.js';
53
- import { secondaryActionTargetAt } from './secondary-action.js';
54
- import { paneBorderTitle } from '../panes/pane-title.js';
55
- import { pulsePhase } from '../agent-activity-hud.js';
56
- import {
57
- inlineEditorClear,
58
- type InlineEditorState,
59
- } from '../input-core/inline-editor.js';
60
- import { applyInlineEditorKey } from '../input-core/inline-editor-key.js';
61
-
62
- export interface VirtualWindowSpec {
63
- id: WindowId;
64
- title: string;
65
- rootContent: PaneContent;
66
- /** Override bounds — defaults to fullscreen over the dashboard. */
67
- bounds?: ModalBounds;
68
- /** Per-window split limits — defaults to layout-tree DEFAULT_LIMITS. */
69
- limits?: SplitLimits;
70
- /** Bundle B-7-γ — resolver for the focused pane's PaneVisualState
71
- * `visibility` axis. When set, paintPane appends a short badge
72
- * (`·H·` / `·D·` / `·ᴸ·`) to the focused pane's label for any
73
- * non-default state. Omit to keep labels unchanged (default). */
74
- visibilityResolver?: (paneId: PaneId) => PaneVisibility;
75
- /** Deterministic clock for chrome motion. Omit in prod. */
76
- now?: () => number;
77
- }
78
-
79
- export interface VirtualWindowRenderCtx {
80
- termCols: number;
81
- termRows: number;
82
- }
83
-
84
- export type LocalInputTarget =
85
- | { kind: 'focused' }
86
- | { kind: 'all' }
87
- | { kind: 'pane'; paneId: PaneId };
88
-
89
- export interface LocalInputSubmitRequest {
90
- broadcast: PaneBroadcast;
91
- target: LocalInputTarget;
92
- }
93
-
94
- export interface LocalInputTargetPickerRequest {
95
- windowId: WindowId;
96
- seedQuery?: string;
97
- }
98
-
99
- export interface VirtualWindowEvents {
100
- onPaneCreate?: (paneId: PaneId) => void;
101
- onPaneClose?: (paneId: PaneId) => void;
102
- onPaneFocus?: (paneId: PaneId) => void;
103
- onClose?: () => void;
104
- /** Fires when the user submits this window's local composer.
105
- * The host decides how to route it: focused pane, target picker,
106
- * or a legacy broadcast path. VW owns only the local input state. */
107
- onLocalInputSubmit?: (windowId: WindowId, req: LocalInputSubmitRequest) => void;
108
- /** Backward-compat path for the original per-VW sync bar contract.
109
- * New consumers should prefer `onLocalInputSubmit`. */
110
- onSyncInputSubmit?: (windowId: WindowId, text: string) => void;
111
- /** VW-U4 — fires when the user right-clicks a pane body region
112
- * (or the border). Host typically opens a pane/window selector
113
- * popup anchored at (col, row). `paneId` is null on border hits. */
114
- onShowSelector?: (windowId: WindowId, paneId: PaneId | null, col: number, row: number) => void;
115
- /** R6 — pane title right-click is distinct from pane body:
116
- * title goes through the menu-provider path while body keeps the
117
- * selector popup path. */
118
- onShowContextMenu?: (windowId: WindowId, paneId: PaneId, col: number, row: number) => void;
119
- /** Request a target-picker popup for the local composer. Host owns
120
- * the popup lifecycle; VW only exposes candidate targets/state. */
121
- onOpenLocalInputTargetPicker?: (req: LocalInputTargetPickerRequest) => void;
122
- }
123
-
124
- /** State for the per-window local composer. When active, the window
125
- * reserves rows at the bottom for a prompt-style input surface.
126
- * Keys captured there accumulate in `composed` until Enter emits a
127
- * host-routed submit event. */
128
- export interface WindowLocalComposerState {
129
- active: boolean;
130
- composed: string;
131
- /** Horizontal scroll offset so the cursor stays visible when the
132
- * composed buffer overflows the bar width. Recomputed each
133
- * render; stored so consecutive frames stay consistent. */
134
- scrollCol: number;
135
- /** U1 — caret position within `composed` (0..composed.length).
136
- * Inserts happen at this index, Backspace deletes the char
137
- * immediately before it, Delete deletes the char at the index.
138
- * Arrow keys / Home / End mutate this. */
139
- cursorPos: number;
140
- }
141
-
142
- /** Backward-compat alias while callers migrate off the old name. */
143
- export type SyncInputBarState = WindowLocalComposerState;
144
-
145
- /** U2 — upper bound on rows the per-window local composer can claim.
146
- * Panes keep at least (window_height - 2 - this_value - 1) rows so
147
- * they stay visible while the user composes a long broadcast. */
148
- export const WINDOW_LOCAL_COMPOSER_MAX_ROWS = 6;
149
- /** Backward-compat alias. */
150
- export const SYNC_BAR_MAX_ROWS = WINDOW_LOCAL_COMPOSER_MAX_ROWS;
151
-
152
- export class VirtualWindow {
153
- readonly id: WindowId;
154
- title: string;
155
- private tree: LayoutNode;
156
- private panes = new Map<PaneId, PaneContent>();
157
- private focusedPaneId: PaneId;
158
- private bounds: ModalBounds;
159
- private state: 'foreground' | 'background' | 'closed' = 'background';
160
- private limits?: SplitLimits;
161
- /** VW-U1 — when foreground, the top border + corners paint in accent
162
- * tone instead of muted so the user can spot the active window at
163
- * a glance. WindowRegistry.switchTo() flips this on the new
164
- * foreground and off on the previous one. */
165
- private borderAccent = false;
166
- /** VW-U5 — when non-null, only this pane renders, filling the full
167
- * inner rect. Other panes skip their paint pass. The layout tree
168
- * itself is unchanged — exiting zoom restores the previous view
169
- * exactly. Cleared automatically when the zoomed pane is closed. */
170
- private zoomedPaneId: PaneId | null = null;
171
- /** VW-U5 — swap target for `^B Tab`. Holds the pane that was focused
172
- * BEFORE the current focus. Updated in setFocus(); flipping between
173
- * two panes produces A → B → A → B… */
174
- private previousFocusedPaneId: PaneId | null = null;
175
- /** VW-B2 — per-pane display title overrides. When set, paintPane
176
- * renders `[abc123] custom-name` instead of the canonical
177
- * `content.title`. Map entries are cleaned up in closePaneAt. */
178
- private paneTitleOverrides = new Map<PaneId, string>();
179
- /** VW-A3 — active divider drag state. Set on click→drag start when
180
- * the initial click lands on a split boundary; cleared on release
181
- * or when the pointer leaves the modal. */
182
- private dragDivider: {
183
- hit: DividerHit;
184
- lastPointer: number;
185
- } | null = null;
186
- private readonly events: VirtualWindowEvents;
187
- /** Window-local composer state. Not persisted across sessions. */
188
- private syncBar: WindowLocalComposerState = { active: false, composed: '', scrollCol: 0, cursorPos: 0 };
189
- /** Target for the local composer. Null means "follow focused pane". */
190
- private localInputTarget: LocalInputTarget = { kind: 'focused' };
191
- /** Bundle B-7-γ — paneId → PaneVisibility resolver, populated from
192
- * VirtualWindowSpec. Null when the host didn't wire a store; in
193
- * that case paintPane treats every pane as 'visible' (no badge). */
194
- private readonly visibilityResolver: ((paneId: PaneId) => PaneVisibility) | null;
195
- private readonly now: () => number;
196
-
197
- constructor(spec: VirtualWindowSpec, events: VirtualWindowEvents = {}) {
198
- this.id = spec.id;
199
- this.title = spec.title;
200
- this.panes.set(spec.rootContent.id, spec.rootContent);
201
- this.tree = leaf(spec.rootContent.id);
202
- this.focusedPaneId = spec.rootContent.id;
203
- this.bounds = spec.bounds ?? { row: 1, col: 1, width: 80, height: 24 };
204
- this.limits = spec.limits;
205
- this.events = events;
206
- this.visibilityResolver = spec.visibilityResolver ?? null;
207
- this.now = spec.now ?? Date.now;
208
- spec.rootContent.start();
209
- this.events.onPaneCreate?.(spec.rootContent.id);
210
- }
211
-
212
- get focused(): PaneId { return this.focusedPaneId; }
213
- get isClosed(): boolean { return this.state === 'closed'; }
214
-
215
- setBounds(bounds: ModalBounds): void {
216
- this.bounds = bounds;
217
- }
218
-
219
- getBounds(): ModalBounds {
220
- return { ...this.bounds };
221
- }
222
-
223
- /** VW-U1 — called by WindowRegistry.switchTo. Idempotent. */
224
- setBorderAccent(active: boolean): void {
225
- this.borderAccent = active;
226
- }
227
-
228
- /** VW-B1 — rename the window. Registry fires a 'window:rename' event
229
- * via its wrapper so subscribers (pickers, element-registry) can
230
- * pick up the new title without re-polling. */
231
- setTitle(next: string): void {
232
- this.title = next;
233
- }
234
-
235
- /** VW-B2 — per-pane display title override. Stored on the VW so
236
- * PaneContent.title stays canonical; getPaneDisplayTitle prefers
237
- * the override when present. Passing empty string clears the
238
- * override (reverts to PaneContent.title). */
239
- setPaneTitle(paneId: PaneId, next: string): boolean {
240
- if (!this.panes.has(paneId)) return false;
241
- const trimmed = next.trim();
242
- if (!trimmed) { this.paneTitleOverrides.delete(paneId); return true; }
243
- this.paneTitleOverrides.set(paneId, trimmed);
244
- return true;
245
- }
246
-
247
- /** VW-B2 — canonical display title. Override wins when present. */
248
- getPaneDisplayTitle(paneId: PaneId): string {
249
- const override = this.paneTitleOverrides.get(paneId);
250
- if (override) return override;
251
- return this.panes.get(paneId)?.title ?? '';
252
- }
253
-
254
- getHostChromeProfile() {
255
- return this.getFocusedPane()?.hostChromeProfile ?? DEFAULT_HOST_CHROME_PROFILE;
256
- }
257
-
258
- /** VW-B2 — clear on pane close; kept as an internal helper. */
259
- private clearPaneTitleOverride(paneId: PaneId): void {
260
- this.paneTitleOverrides.delete(paneId);
261
- }
262
-
263
-
264
- isBorderAccent(): boolean {
265
- return this.borderAccent;
266
- }
267
-
268
- listPanes(): Array<{ id: PaneId; content: PaneContent }> {
269
- return [...this.panes.entries()].map(([id, content]) => ({ id, content }));
270
- }
271
-
272
- /** Phase 3a · save path — read-only accessor to the current layout
273
- * binary tree. Consumed by `snapshotWindow()` in layout/tree.ts to
274
- * produce a serializable LayoutSpec. Returned reference is the live
275
- * tree (caller must not mutate); see `layout/restore-planner.ts`
276
- * for the adapter that round-trips through LayoutSpec. */
277
- getLayoutTree(): LayoutNode {
278
- return this.tree;
279
- }
280
-
281
- getPane(id: PaneId): PaneContent | null {
282
- return this.panes.get(id) ?? null;
283
- }
284
-
285
- /** SP-D — expose the focused pane content to chord handlers that
286
- * need to probe/mutate focus-policy without poking panes Map. */
287
- getFocusedPane(): PaneContent | null {
288
- return this.panes.get(this.focusedPaneId) ?? null;
289
- }
290
-
291
- /** SP-A / A.3 — true iff the focused pane's declared focus policy
292
- * is not `output-only`. Used by window cycling to skip windows
293
- * whose focused pane is intentionally read-mostly. */
294
- hasInteractableFocus(): boolean {
295
- const pane = this.panes.get(this.focusedPaneId);
296
- if (!pane) return true;
297
- return pane.focusPolicy !== 'output-only';
298
- }
299
-
300
- getLayout(): LayoutNode {
301
- return this.tree;
302
- }
303
-
304
- paneRects(): PaneRect[] {
305
- return layoutRects(this.tree, this.innerRect());
306
- }
307
-
308
- // ─── Mutations ──────────────────────────────────────────────────
309
-
310
- /** Resize the split enclosing `paneId` along `axis` by `delta` cells.
311
- * Delegates to layout-tree's resizePane which enforces SplitLimits.
312
- * Returns true when the tree changed, false when delta rounded to
313
- * a no-op or no matching-axis split was found. */
314
- resizePaneAt(paneId: PaneId, axis: Axis, delta: number): boolean {
315
- if (!this.panes.has(paneId) || delta === 0) return false;
316
- const next = resizePane(this.tree, paneId, axis, delta, this.innerRect());
317
- if (next === this.tree) return false;
318
- this.tree = next;
319
- return true;
320
- }
321
-
322
- splitFocused(axis: Axis, newContent: PaneContent, ratio = 0.5): PaneId {
323
- return this.splitPaneAt(this.focusedPaneId, axis, newContent, ratio);
324
- }
325
-
326
- splitPaneAt(paneId: PaneId, axis: Axis, newContent: PaneContent, ratio = 0.5): PaneId {
327
- const next = splitPane({
328
- tree: this.tree,
329
- paneId,
330
- axis,
331
- newPaneId: newContent.id,
332
- ratio,
333
- bounds: this.innerRect(),
334
- limits: this.limits,
335
- });
336
- this.tree = next;
337
- this.panes.set(newContent.id, newContent);
338
- newContent.start();
339
- this.events.onPaneCreate?.(newContent.id);
340
- // Focus the new pane (tmux default).
341
- this.setFocus(newContent.id);
342
- return newContent.id;
343
- }
344
-
345
- closeFocused(): boolean {
346
- return this.closePaneAt(this.focusedPaneId);
347
- }
348
-
349
- closePaneAt(paneId: PaneId): boolean {
350
- if (!this.panes.has(paneId)) return false;
351
- const next = closePane(this.tree, paneId);
352
- const content = this.panes.get(paneId);
353
- if (content) {
354
- try { content.dispose(); } catch { /* ignore */ }
355
- }
356
- this.panes.delete(paneId);
357
- this.clearPaneTitleOverride(paneId); // VW-B2
358
- this.events.onPaneClose?.(paneId);
359
- // VW-U5 — if the closed pane was zoomed, clear the zoom flag so
360
- // the remaining panes paint normally.
361
- if (this.zoomedPaneId === paneId) this.zoomedPaneId = null;
362
- // VW-U5 — forget the closed pane from the alt-tab slot.
363
- if (this.previousFocusedPaneId === paneId) this.previousFocusedPaneId = null;
364
- if (next === null) {
365
- this.state = 'closed';
366
- this.events.onClose?.();
367
- return true;
368
- }
369
- this.tree = next;
370
- // Focus the first remaining leaf if the focused pane was closed.
371
- if (this.focusedPaneId === paneId) {
372
- const remaining = allPaneIds(this.tree);
373
- if (remaining.length > 0) this.setFocus(remaining[0]!);
374
- }
375
- return true;
376
- }
377
-
378
- setFocus(paneId: PaneId): boolean {
379
- if (!this.panes.has(paneId)) return false;
380
- if (this.focusedPaneId === paneId) return true;
381
- this.previousFocusedPaneId = this.focusedPaneId; // VW-U5
382
- this.focusedPaneId = paneId;
383
- this.events.onPaneFocus?.(paneId);
384
- return true;
385
- }
386
-
387
- /** VW-U5 — toggle zoom on the currently focused pane. When zoomed,
388
- * render() paints only the focused pane across the inner rect;
389
- * other panes retain their state but are hidden. Calling again
390
- * with the same focus clears zoom. Returns the new zoom state. */
391
- toggleZoom(): boolean {
392
- if (this.zoomedPaneId === this.focusedPaneId) {
393
- this.zoomedPaneId = null;
394
- } else {
395
- this.zoomedPaneId = this.focusedPaneId;
396
- }
397
- return this.zoomedPaneId !== null;
398
- }
399
-
400
- /** VW-U5 — whether a pane is currently zoomed. */
401
- isZoomed(): boolean {
402
- return this.zoomedPaneId !== null;
403
- }
404
-
405
- /** VW-U5 — jump focus to the pane that was focused right before the
406
- * current one. Returns the pane that ended up focused, or null when
407
- * there is no recorded previous pane (first-ever focus).
408
- *
409
- * SRF-5 — when the remembered previous pane is output-only (e.g.
410
- * a runner pane that swallows keys), we skip to the next
411
- * interactive pane if one exists. Mirrors the SP-A window-level
412
- * skip so pane-level cycling behaves consistently. Falls through
413
- * to the naive target when every alternative is also output-only
414
- * (no deadlock). */
415
- focusLastPane(): PaneId | null {
416
- const prev = this.previousFocusedPaneId;
417
- if (!prev || !this.panes.has(prev)) return null;
418
- if (prev === this.focusedPaneId) return this.focusedPaneId;
419
- const prevPane = this.panes.get(prev);
420
- const isOutputOnly = (p: PaneContent | undefined): boolean => p?.focusPolicy === 'output-only';
421
- if (isOutputOnly(prevPane)) {
422
- // Find another interactive pane (not current, not prev) before
423
- // falling back to the naive target.
424
- for (const [id, content] of this.panes) {
425
- if (id === this.focusedPaneId) continue;
426
- if (id === prev) continue;
427
- if (!isOutputOnly(content)) {
428
- this.setFocus(id);
429
- return this.focusedPaneId;
430
- }
431
- }
432
- // No interactive alternative — fall through to naive behavior.
433
- }
434
- // setFocus() rotates previousFocusedPaneId → current, so the next
435
- // call to focusLastPane() swaps back. That's the "alt-tab" feel.
436
- this.setFocus(prev);
437
- return this.focusedPaneId;
438
- }
439
-
440
- focusDirection(dir: Direction): boolean {
441
- const next = focusNeighbor(this.tree, this.focusedPaneId, dir, this.innerRect());
442
- if (!next) return false;
443
- return this.setFocus(next);
444
- }
445
-
446
- // ─── Key routing ────────────────────────────────────────────────
447
-
448
- onKey(ev: KeyEvent): Action {
449
- // T3b-c — sync input bar wins when active. Returns passthrough
450
- // for keys it doesn't recognise (e.g. mouse, unknown ctrl combos)
451
- // so they can still reach the focused pane as a fallback.
452
- if (this.syncBar.active) {
453
- const result = this.handleSyncBarKey(ev);
454
- if (result === 'consumed') return { type: 'refresh' };
455
- }
456
- const content = this.panes.get(this.focusedPaneId);
457
- if (!content) return { type: 'none' };
458
- return content.onKey(ev);
459
- }
460
-
461
- /** VW-U3 — mouse dispatch.
462
- *
463
- * Left click: if the click lands inside a pane rect, focus that
464
- * pane. Border / title clicks are a no-op (current focus kept).
465
- *
466
- * Right click: pane title emits `onShowContextMenu` so the host
467
- * can route through MenuProvider; pane body/border emits
468
- * `onShowSelector` so the host can open the pane/window picker
469
- * popup. This is the R6 coexistence rule.
470
- *
471
- * Scroll-up / scroll-down are reserved for future pane scrollback
472
- * routing — currently forwarded as-is to the focused pane via
473
- * content.onKey-like plumbing if the pane supports it (not wired
474
- * in VW-U3). */
475
- onMouse(ev: DisplayMouseEvent): Action {
476
- const rect = this.innerRect();
477
- const insideInner =
478
- ev.col >= rect.col && ev.col < rect.col + rect.width
479
- && ev.row >= rect.row && ev.row < rect.row + rect.height;
480
- const paneId = insideInner ? paneAt(this.tree, rect, ev.col, ev.row) : null;
481
- if (debug.enabled && ev.type !== 'motion') {
482
- debug.log('vw.mouse', 'dispatch', {
483
- windowId: this.id,
484
- type: ev.type,
485
- row: ev.row,
486
- col: ev.col,
487
- insideInner,
488
- paneId,
489
- focusedPaneId: this.focusedPaneId,
490
- });
491
- }
492
- if (isPrimaryDiscreteClickMouseEventType(ev.type)) {
493
- // VW-A2 — × close-button click takes precedence over pane focus.
494
- // Geometry lives in closeButtonAt so tests can assert it without
495
- // mutating state.
496
- const closeTarget = this.closeButtonAt(ev.col, ev.row);
497
- if (closeTarget) {
498
- this.closePaneAt(closeTarget);
499
- return { type: 'refresh' };
500
- }
501
- // VW-A3 — divider hit: arm drag state. The same click also
502
- // cancels any previous drag so stale state can't persist.
503
- const divider = insideInner && !this.zoomedPaneId
504
- ? dividerAt(this.tree, rect, ev.col, ev.row)
505
- : null;
506
- if (divider) {
507
- this.dragDivider = {
508
- hit: divider,
509
- lastPointer: divider.axis === 'h' ? ev.col : ev.row,
510
- };
511
- return { type: 'none' };
512
- }
513
- this.dragDivider = null;
514
- if (paneId && paneId !== this.focusedPaneId) {
515
- this.setFocus(paneId);
516
- const routed = this.routeMouseToPane(paneId, ev);
517
- if (debug.enabled) {
518
- debug.log('vw.mouse', 'click.focus-route', {
519
- windowId: this.id,
520
- paneId,
521
- routed: routed.type,
522
- });
523
- }
524
- return routed.type === 'none' ? { type: 'refresh' } : routed;
525
- }
526
- if (!paneId) return { type: 'none' };
527
- const routed = this.routeMouseToPane(paneId, ev);
528
- if (debug.enabled) {
529
- debug.log('vw.mouse', 'click.route', {
530
- windowId: this.id,
531
- paneId,
532
- routed: routed.type,
533
- });
534
- }
535
- return routed;
536
- }
537
- // VW-A3 — drag motion: while a divider is armed, convert pointer
538
- // delta into a layout-tree resizePane call. Wheel clicks / releases
539
- // outside the loop simply clear the state.
540
- if (isCaptureSessionMouseEventType(ev.type)) {
541
- if (!this.dragDivider) {
542
- const target = paneId ?? this.focusedPaneId;
543
- if (!target) return { type: 'none' };
544
- return this.routeMouseToPane(target, ev);
545
- }
546
- if (isCaptureSessionEndMouseEventType(ev.type)) {
547
- this.dragDivider = null;
548
- return { type: 'none' };
549
- }
550
- const { hit, lastPointer } = this.dragDivider;
551
- const pointer = hit.axis === 'h' ? ev.col : ev.row;
552
- const delta = pointer - lastPointer;
553
- if (delta === 0) return { type: 'none' };
554
- const next = resizePane(this.tree, hit.aPaneId, hit.axis, delta, this.innerRect());
555
- if (next !== this.tree) {
556
- this.tree = next;
557
- this.dragDivider = { hit, lastPointer: pointer };
558
- return { type: 'refresh' };
559
- }
560
- // resize refused (MIN size guard) — keep pointer anchor so the
561
- // user can drag back the other way without a jump.
562
- return { type: 'none' };
563
- }
564
- if (isSecondaryClickMouseEventType(ev.type)) {
565
- const secondary = secondaryActionTargetAt(this.paneRects(), ev.col, ev.row);
566
- if (secondary.kind === 'pane-title') {
567
- this.events.onShowContextMenu?.(this.id, secondary.paneId, ev.col, ev.row);
568
- return { type: 'none' };
569
- }
570
- if (secondary.paneId) {
571
- const routed = this.routeMouseToPane(secondary.paneId, ev);
572
- if (routed.type !== 'none') return routed;
573
- }
574
- this.events.onShowSelector?.(this.id, secondary.paneId, ev.col, ev.row);
575
- return { type: 'none' };
576
- }
577
- // VW-A1 — scroll-up/down forwards to the pane under the cursor (or
578
- // the focused pane when the cursor is outside the inner rect). The
579
- // target pane's PaneContent.onMouse decides what to do with it; static
580
- // content types (markdown, scratch) omit onMouse entirely and the
581
- // wheel becomes a no-op. Returning 'refresh' so the dashboard redraws
582
- // in case the pane updated its own scroll state.
583
- if (ev.type === 'scroll-up' || ev.type === 'scroll-down') {
584
- const target = paneId ?? this.focusedPaneId;
585
- const content = target ? this.panes.get(target) : null;
586
- if (!content?.onMouse) return { type: 'none' };
587
- this.routeMouseToPane(target, ev);
588
- return { type: 'refresh' };
589
- }
590
- return { type: 'none' };
591
- }
592
-
593
- private routeMouseToPane(paneId: PaneId, ev: DisplayMouseEvent): Action {
594
- const content = this.panes.get(paneId);
595
- if (!content?.onMouse) return { type: 'none' };
596
- const paneRect = this.paneRects().find((entry) => entry.paneId === paneId)?.rect;
597
- if (!paneRect) return { type: 'none' };
598
- const localEv: DisplayMouseEvent = {
599
- ...ev,
600
- row: ev.row - paneRect.row + 1,
601
- col: ev.col - paneRect.col + 1,
602
- };
603
- try {
604
- const result = content.onMouse(localEv);
605
- if (debug.enabled && ev.type !== 'motion') {
606
- debug.log('vw.mouse', 'pane-forward', {
607
- windowId: this.id,
608
- paneId,
609
- absRow: ev.row,
610
- absCol: ev.col,
611
- localRow: localEv.row,
612
- localCol: localEv.col,
613
- result: result.type,
614
- });
615
- }
616
- return result;
617
- } catch {
618
- if (debug.enabled) {
619
- debug.log('vw.mouse', 'pane-forward-error', {
620
- windowId: this.id,
621
- paneId,
622
- absRow: ev.row,
623
- absCol: ev.col,
624
- }, { level: 'error' });
625
- }
626
- return { type: 'none' };
627
- }
628
- }
629
-
630
- deliverBroadcastToFocused(input: PaneBroadcast): number {
631
- return this.deliverBroadcastToPane(this.focusedPaneId, input);
632
- }
633
-
634
- deliverBroadcastToPane(paneId: PaneId, input: PaneBroadcast): number {
635
- const pane = this.panes.get(paneId);
636
- if (!pane) return 0;
637
- if (pane.acceptBroadcast) pane.acceptBroadcast(input);
638
- else pane.write(input.text);
639
- return 1;
640
- }
641
-
642
- deliverBroadcastToAll(input: PaneBroadcast): number {
643
- let delivered = 0;
644
- for (const paneId of this.panes.keys()) {
645
- delivered += this.deliverBroadcastToPane(paneId, input);
646
- }
647
- return delivered;
648
- }
649
-
650
- // ─── Rendering ──────────────────────────────────────────────────
651
-
652
- render(): string {
653
- const out: string[] = [];
654
- out.push(this.paintBorder());
655
- out.push(this.paintInteriorBackground());
656
- // VW-U5 — zoom path: only the zoomed pane paints, across the full
657
- // inner rect. Other panes retain their state in the tree so exit
658
- // is a no-op teardown.
659
- if (this.zoomedPaneId && this.panes.has(this.zoomedPaneId)) {
660
- const content = this.panes.get(this.zoomedPaneId)!;
661
- const rect = this.innerRect();
662
- try {
663
- const grid = content.render({
664
- cols: Math.max(2, rect.width),
665
- rows: Math.max(2, rect.height),
666
- focused: true,
667
- });
668
- out.push(this.paintPane(rect, grid, this.zoomedPaneId));
669
- } catch { /* broken pane; skip */ }
670
- } else {
671
- const rects = this.paneRects();
672
- for (const { paneId, rect } of rects) {
673
- const content = this.panes.get(paneId);
674
- if (!content) continue;
675
- try {
676
- const grid = content.render({
677
- cols: Math.max(2, rect.width),
678
- rows: Math.max(2, rect.height),
679
- focused: paneId === this.focusedPaneId,
680
- });
681
- out.push(this.paintPane(rect, grid, paneId));
682
- } catch { /* broken pane; skip */ }
683
- }
684
- }
685
- if (this.syncBar.active) {
686
- out.push(this.paintSyncInputBar());
687
- }
688
- return out.join('');
689
- }
690
-
691
- private paintInteriorBackground(): string {
692
- const rect = this.innerRect();
693
- if (rect.width < 1 || rect.height < 1) return '';
694
- const out: string[] = [];
695
- for (let i = 0; i < rect.height; i++) {
696
- out.push(
697
- ansi.moveTo(rect.row + i, rect.col)
698
- + '\x1b[0m'
699
- + ' '.repeat(rect.width),
700
- );
701
- }
702
- return out.join('');
703
- }
704
-
705
- /** Build the ModalSurface representation for the coordinator. */
706
- asModalSurface(owner: string = 'dashboard'): ModalSurface {
707
- const surfaceId: SurfaceId = `virtual-window:${this.id}`;
708
- const self = this;
709
- return {
710
- id: surfaceId,
711
- owner: owner as ModalSurface['owner'],
712
- kind: 'modal',
713
- focus: 'owns',
714
- priority: 500,
715
- hostChromeProfile: self.getHostChromeProfile(),
716
- interactionClass: 'workspace',
717
- backgroundInteractionPolicy: 'block',
718
- windowRole: 'foreground',
719
- // IDX-F4 — virtual-window host surfaces sit at the lowest tier;
720
- // their own child modals (pickers / popups / dialogs) stack
721
- // above via the normal TIER_ORDER ordering.
722
- tier: 'vw',
723
- // VW-U3 — bounds getter now returns THIS window's actual bounds
724
- // (setBounds still updates `this.bounds`; previous hardcoded
725
- // `{1,1,80,24}` snapshot was a placeholder that broke any
726
- // bounds-aware dispatch like hit-testing mouse clicks).
727
- get bounds() {
728
- return { ...self.bounds };
729
- },
730
- render: () => [],
731
- paint: () => this.render(),
732
- cursor: () => this.cursorState(),
733
- // KX4b — VW is keyboard-exclusive while foregrounded. Any key
734
- // reaches the focused pane; the pane's Action return is
735
- // intentionally discarded (the hard-branch router did the same
736
- // before KX4) so dashboard.ts's displayRoute switch doesn't
737
- // double-dispatch refresh/focus actions the pane already owns
738
- // through its direct writes.
739
- //
740
- // VW-U2 — **except** Alt-modified keys without Ctrl: those are
741
- // reserved for dashboard-global VW navigation (Alt+N/P/1..9 fast
742
- // switch). We let them bubble past the modal surface so the
743
- // coordinator can match them against registered bindings. The
744
- // trade-off is that shell users inside a VW lose Alt-only meta
745
- // shortcuts (e.g. Alt+M in some readline configs); in exchange
746
- // the user gets a one-keystroke window switcher even while a
747
- // shell pane holds focus.
748
- onKey: (ev) => {
749
- if (ev.alt && !ev.ctrl) return 'passthrough';
750
- try { this.onKey(ev); } catch { /* isolate pane error */ }
751
- return 'consumed';
752
- },
753
- // VW-U3 — route mouse clicks into the VW. Left click focuses the
754
- // clicked pane; right-click fires onShowSelector for VW-U4. Errors
755
- // are isolated just like onKey — a buggy pane shouldn't crash
756
- // the coordinator.
757
- onMouse: (ev) => {
758
- try { return this.onMouse(ev); }
759
- catch { return { type: 'none' }; }
760
- },
761
- dispose: () => { /* close is triggered externally via WindowRegistry */ },
762
- };
763
- }
764
-
765
- dispose(): void {
766
- if (this.state === 'closed') return;
767
- this.state = 'closed';
768
- for (const pane of this.panes.values()) {
769
- try { pane.dispose(); } catch { /* ignore */ }
770
- }
771
- this.panes.clear();
772
- this.events.onClose?.();
773
- }
774
-
775
- // ─── Internals ──────────────────────────────────────────────────
776
-
777
- private innerRect(): Rect {
778
- // Reserve 1 cell on each side for the border + 1 row for title.
779
- // When the sync input bar is active, shrink the content area by
780
- // the bar's row count — one per composed line, capped at
781
- // SYNC_BAR_MAX_ROWS so the bar never eats more than ~a quarter
782
- // of the window. Pane content clips normally when the bar grows.
783
- const barRows = this.syncBar.active ? this.syncBarRowCount() : 0;
784
- return {
785
- row: this.bounds.row + 1,
786
- col: this.bounds.col + 1,
787
- width: Math.max(2, this.bounds.width - 2),
788
- height: Math.max(2, this.bounds.height - 2 - barRows),
789
- };
790
- }
791
-
792
- /** U2 — how many rows the local composer occupies. 1 for a single-line
793
- * buffer; lineCount(composed) for multi-line, capped at
794
- * WINDOW_LOCAL_COMPOSER_MAX_ROWS so panes keep at least part of the viewport. */
795
- private localComposerRowCount(): number {
796
- return this.syncBarRowCount();
797
- }
798
-
799
- /** Backward-compat internal name kept while older call sites
800
- * migrate to the local-composer terminology. */
801
- private syncBarRowCount(): number {
802
- const lines = this.syncBar.composed.split('\n').length;
803
- return Math.min(WINDOW_LOCAL_COMPOSER_MAX_ROWS, Math.max(1, lines));
804
- }
805
-
806
- // ─── Window-local composer ──────────────────────────────────────
807
-
808
- /** Toggle or set the window-local composer. */
809
- setLocalComposerActive(active: boolean): void {
810
- this.setSyncInputBar(active);
811
- }
812
-
813
- isLocalComposerActive(): boolean {
814
- return this.isSyncInputBarActive();
815
- }
816
-
817
- getLocalComposerBuffer(): string {
818
- return this.getSyncInputBuffer();
819
- }
820
-
821
- clearLocalComposer(): void {
822
- this.clearSyncInput();
823
- }
824
-
825
- getLocalComposerCursor(): number {
826
- return this.getSyncInputCursor();
827
- }
828
-
829
- getLocalInputTarget(): LocalInputTarget {
830
- return this.localInputTarget.kind === 'pane'
831
- ? { kind: 'pane', paneId: this.localInputTarget.paneId }
832
- : { kind: this.localInputTarget.kind };
833
- }
834
-
835
- setLocalInputTarget(target: LocalInputTarget): boolean {
836
- if (target.kind === 'pane' && !this.panes.has(target.paneId)) return false;
837
- this.localInputTarget = target.kind === 'pane'
838
- ? { kind: 'pane', paneId: target.paneId }
839
- : { kind: target.kind };
840
- return true;
841
- }
842
-
843
- consumeLocalComposerMentionTargetToken(): boolean {
844
- const range = this.localComposerMentionRangeAtCursor();
845
- if (!range) return false;
846
- const s = this.syncBar;
847
- let start = range.start;
848
- let end = range.end;
849
- if (s.composed[end] === ' ') end += 1;
850
- else if (start > 0 && s.composed[start - 1] === ' ') start -= 1;
851
- s.composed = s.composed.slice(0, start) + s.composed.slice(end);
852
- s.cursorPos = Math.min(start, s.composed.length);
853
- s.scrollCol = 0;
854
- return true;
855
- }
856
-
857
- listLocalInputTargets(): Array<{ target: LocalInputTarget; label: string; active: boolean }> {
858
- const out: Array<{ target: LocalInputTarget; label: string; active: boolean }> = [];
859
- out.push({
860
- target: { kind: 'focused' },
861
- label: 'focused pane',
862
- active: this.localInputTarget.kind === 'focused',
863
- });
864
- out.push({
865
- target: { kind: 'all' },
866
- label: 'all panes',
867
- active: this.localInputTarget.kind === 'all',
868
- });
869
- for (const [paneId] of this.panes) {
870
- out.push({
871
- target: { kind: 'pane', paneId },
872
- label: this.getPaneDisplayTitle(paneId) || `[${paneId.slice(0, 6)}]`,
873
- active: this.localInputTarget.kind === 'pane' && this.localInputTarget.paneId === paneId,
874
- });
875
- }
876
- return out;
877
- }
878
-
879
- /** Toggle or set the sync input bar. When turning ON, the window
880
- * reserves a row for the bar and key events flow into it instead
881
- * of the focused pane. When turning OFF, keys return to normal
882
- * pane routing. Idempotent. */
883
- setSyncInputBar(active: boolean): void {
884
- if (this.syncBar.active === active) return;
885
- this.syncBar = { active, composed: '', scrollCol: 0, cursorPos: 0 };
886
- }
887
-
888
- isSyncInputBarActive(): boolean {
889
- return this.syncBar.active;
890
- }
891
-
892
- getSyncInputBuffer(): string {
893
- return this.syncBar.composed;
894
- }
895
-
896
- /** Drop the current composed buffer without submitting. Used by the
897
- * Escape handler inside handleSyncBarKey. */
898
- clearSyncInput(): void {
899
- this.applySyncBarEditor(inlineEditorClear(this.syncBarEditorState()));
900
- this.syncBar.scrollCol = 0;
901
- }
902
-
903
- /** U1 — expose cursor position for tests + potential external UIs
904
- * that want to draw an out-of-band indicator. */
905
- getSyncInputCursor(): number {
906
- return this.syncBar.cursorPos;
907
- }
908
-
909
- /** Internal key handler for the sync input bar — returns
910
- * 'consumed' when the key was handled (prevents fallthrough to
911
- * the focused pane). Invoked from onKey() when syncBar.active. */
912
- private handleSyncBarKey(ev: KeyEvent): 'consumed' | 'passthrough' {
913
- const name = (ev.name ?? '').toLowerCase();
914
- const s = this.syncBar;
915
- if (!ev.ctrl && !ev.alt && name === '@') {
916
- this.events.onOpenLocalInputTargetPicker?.({
917
- windowId: this.id,
918
- seedQuery: this.localComposerMentionRangeAtCursor()?.query ?? undefined,
919
- });
920
- return 'consumed';
921
- }
922
- // Ctrl+G / Escape → drop the bar entirely (return to pane focus).
923
- if (name === 'escape' || (ev.ctrl && (name === 'g' || name === 'ㅎ'))) {
924
- this.setSyncInputBar(false);
925
- return 'consumed';
926
- }
927
- // U2 — Shift+Enter inserts a newline at the cursor (multi-line
928
- // compose); plain Enter submits the buffer. VW emits submit
929
- // intent here; pane-specific terminal/newline semantics are
930
- // handled by PaneContent.acceptBroadcast.
931
- if (name === 'enter' || name === 'return') {
932
- if (ev.shift) {
933
- const next = applyInlineEditorKey(this.syncBarEditorState(), ev, { shiftEnter: 'newline' });
934
- if (next) this.applySyncBarEditor(next);
935
- return 'consumed';
936
- }
937
- const text = s.composed;
938
- if (text.length > 0) {
939
- try {
940
- const inline = this.resolveInlineLocalInputTarget(text);
941
- const submitText = inline ? inline.text : text;
942
- const submitTarget = inline ? inline.target : this.getLocalInputTarget();
943
- if (inline) this.setLocalInputTarget(inline.target);
944
- if (this.events.onLocalInputSubmit) {
945
- if (submitText.length > 0) {
946
- this.events.onLocalInputSubmit(this.id, {
947
- broadcast: { mode: 'submit', text: submitText },
948
- target: submitTarget,
949
- });
950
- }
951
- }
952
- else if (submitText.length > 0) this.events.onSyncInputSubmit?.(this.id, submitText + '\r');
953
- }
954
- catch { /* host-side submit errors don't crash the VW */ }
955
- }
956
- s.composed = '';
957
- s.cursorPos = 0;
958
- s.scrollCol = 0;
959
- return 'consumed';
960
- }
961
- const next = applyInlineEditorKey(this.syncBarEditorState(), ev);
962
- if (next !== null) {
963
- this.applySyncBarEditor(next);
964
- if (ev.ctrl && name === 'u') s.scrollCol = 0;
965
- return 'consumed';
966
- }
967
- return 'passthrough';
968
- }
969
-
970
- private syncBarEditorState(): InlineEditorState {
971
- return {
972
- text: this.syncBar.composed,
973
- cursor: this.syncBar.cursorPos,
974
- };
975
- }
976
-
977
- private applySyncBarEditor(next: InlineEditorState): void {
978
- this.syncBar.composed = next.text;
979
- this.syncBar.cursorPos = next.cursor;
980
- }
981
-
982
- private localComposerMentionRangeAtCursor():
983
- | { start: number; end: number; query: string }
984
- | null {
985
- const { composed, cursorPos } = this.syncBar;
986
- if (!composed) return null;
987
- let start = cursorPos;
988
- while (start > 0 && !/\s/.test(composed[start - 1]!)) start--;
989
- let end = cursorPos;
990
- while (end < composed.length && !/\s/.test(composed[end]!)) end++;
991
- if (start >= end) return null;
992
- const token = composed.slice(start, end);
993
- if (!token.startsWith('@')) return null;
994
- return { start, end, query: token.slice(1) };
995
- }
996
-
997
- private resolveInlineLocalInputTarget(text: string):
998
- | { target: LocalInputTarget; text: string }
999
- | null {
1000
- const match = text.match(/^\s*@(\S+)(?:\s+([\s\S]*))?$/);
1001
- if (!match) return null;
1002
- const target = this.localInputTargetFromToken(match[1] ?? '');
1003
- if (!target) return null;
1004
- return {
1005
- target,
1006
- text: (match[2] ?? '').trimStart(),
1007
- };
1008
- }
1009
-
1010
- private localInputTargetFromToken(tokenRaw: string): LocalInputTarget | null {
1011
- const token = tokenRaw.trim().toLowerCase();
1012
- if (!token) return null;
1013
- if (token === 'focused') return { kind: 'focused' };
1014
- if (token === 'all') return { kind: 'all' };
1015
- for (const [paneId] of this.panes) {
1016
- const title = this.getPaneDisplayTitle(paneId);
1017
- if (title && title.trim().toLowerCase() === token) {
1018
- return { kind: 'pane', paneId };
1019
- }
1020
- }
1021
- return null;
1022
- }
1023
-
1024
- private paintBorder(): string {
1025
- const { row, col, width, height } = this.bounds;
1026
- if (width < 4 || height < 3) return '';
1027
- const innerWidth = width - 2;
1028
- const titleRaw = this.title.length > innerWidth - 6
1029
- ? this.title.slice(0, innerWidth - 7) + '…'
1030
- : this.title;
1031
- const windowLabel = ` ${C.accent(`win:${this.id}`)} ${C.text(titleRaw)} `;
1032
- const vw = visibleWidth(stripAnsi(windowLabel));
1033
- const leftPad = Math.max(1, Math.floor((innerWidth - vw) / 2));
1034
- const rightPad = Math.max(1, innerWidth - vw - leftPad);
1035
- // VW-U1 — when foreground, top border + corners render in accent
1036
- // (blue) so the user can see at a glance which window is active.
1037
- // Sides + bottom stay muted to avoid loud framing.
1038
- const top = this.borderAccent ? C.accent : C.muted;
1039
- const side = C.muted;
1040
- const out: string[] = [];
1041
- out.push(
1042
- ansi.moveTo(row, col) +
1043
- top('╭') +
1044
- top('─'.repeat(leftPad)) +
1045
- windowLabel +
1046
- top('─'.repeat(rightPad)) +
1047
- top('╮'),
1048
- );
1049
- for (let i = 0; i < height - 2; i++) {
1050
- const r = row + 1 + i;
1051
- out.push(ansi.moveTo(r, col) + side('│'));
1052
- out.push(ansi.moveTo(r, col + width - 1) + side('│'));
1053
- }
1054
- out.push(
1055
- ansi.moveTo(row + height - 1, col) +
1056
- side('╰') +
1057
- side('─'.repeat(innerWidth)) +
1058
- side('╯'),
1059
- );
1060
- return out.join('');
1061
- }
1062
-
1063
- private paintSyncInputBar(): string {
1064
- // U2 — the bar spans syncBarRowCount() rows just above the bottom
1065
- // border. The first row gets the ▶ vw:N prompt; continuation rows
1066
- // use an aligned indent so the composed body stays readable.
1067
- const rowCount = this.syncBarRowCount();
1068
- const topRow = this.bounds.row + this.bounds.height - 1 - rowCount;
1069
- const col = this.bounds.col + 1;
1070
- const width = Math.max(2, this.bounds.width - 2);
1071
- const prompt = C.accent(`▶ vw:${this.id}`) + C.muted(` ${this.localInputTargetLabel()} ▸ `);
1072
- const promptVw = visibleWidth(stripAnsi(prompt));
1073
- const contRaw = ' '.repeat(Math.max(0, promptVw - 2)) + '↪ ';
1074
- const cont = C.muted(contRaw);
1075
- const contVw = visibleWidth(stripAnsi(cont));
1076
- const bodyBudget = Math.max(1, width - promptVw);
1077
- const s = this.syncBar;
1078
-
1079
- // Compute (line, col) for cursorPos so the rendered caret lands
1080
- // on the right row when composed has embedded newlines.
1081
- const { line: cursorLine, col: cursorColInLine } = positionToLineCol(s.composed, s.cursorPos);
1082
- // Horizontal scroll tracks the current cursor line only. Each
1083
- // line paints independently; only the focused line's content
1084
- // shifts left when needed.
1085
- const lines = s.composed.split('\n');
1086
-
1087
- const out: string[] = [];
1088
- // Clear every row we're about to paint (prevents stale glyphs
1089
- // when the bar grows/shrinks between frames).
1090
- for (let r = 0; r < rowCount; r++) {
1091
- out.push(ansi.moveTo(topRow + r, col) + ' '.repeat(width) + '\x1b[0m');
1092
- }
1093
- // Window-shift the visible line slice so the cursor stays in view.
1094
- for (let r = 0; r < rowCount; r++) {
1095
- const lineIdx = r < lines.length ? r : -1;
1096
- if (lineIdx < 0) continue;
1097
- const lineText = lines[lineIdx]!;
1098
- const promptPrefix = lineIdx === 0 ? prompt : cont;
1099
- const promptCols = lineIdx === 0 ? promptVw : contVw;
1100
- const budget = Math.max(1, width - promptCols);
1101
- // Only scroll the cursor line; the others render from column 0.
1102
- let start = 0;
1103
- if (lineIdx === cursorLine) {
1104
- start = s.scrollCol;
1105
- if (cursorColInLine < start) start = cursorColInLine;
1106
- if (cursorColInLine >= start + budget) start = cursorColInLine - budget + 1;
1107
- start = Math.max(0, start);
1108
- s.scrollCol = start;
1109
- }
1110
- const slice = lineText.slice(start, start + budget);
1111
- const padded = slice + ' '.repeat(Math.max(0, budget - slice.length));
1112
- out.push(ansi.moveTo(topRow + r, col) + promptPrefix + padded);
1113
- }
1114
- // Paint the cursor cell LAST so it wins over the body paint.
1115
- const cursorRowAbs = topRow + Math.min(rowCount - 1, cursorLine);
1116
- const cursorPrompt = cursorLine === 0 ? promptVw : contVw;
1117
- const cursorCol = col + cursorPrompt + (cursorColInLine - s.scrollCol);
1118
- const underCh = (lines[cursorLine] ?? '')[cursorColInLine] ?? ' ';
1119
- out.push(ansi.moveTo(cursorRowAbs, cursorCol) + '\x1b[7m' + underCh + '\x1b[27m');
1120
- return out.join('');
1121
- }
1122
-
1123
- private cursorState(): CursorState | null {
1124
- if (this.syncBar.active) return this.localComposerCursorState();
1125
- const rect = this.zoomedPaneCursorRect();
1126
- if (!rect) return null;
1127
- const pane = this.panes.get(rect.paneId);
1128
- if (!pane || typeof pane.cursor !== 'function') return null;
1129
- try {
1130
- return pane.cursor({
1131
- cols: Math.max(2, rect.rect.width),
1132
- rows: Math.max(2, rect.rect.height),
1133
- focused: true,
1134
- row: rect.rect.row,
1135
- col: rect.rect.col,
1136
- });
1137
- } catch {
1138
- return null;
1139
- }
1140
- }
1141
-
1142
- private zoomedPaneCursorRect():
1143
- | { paneId: PaneId; rect: Rect }
1144
- | null {
1145
- if (this.zoomedPaneId && this.panes.has(this.zoomedPaneId)) {
1146
- return { paneId: this.zoomedPaneId, rect: this.innerRect() };
1147
- }
1148
- const match = this.paneRects().find((it) => it.paneId === this.focusedPaneId);
1149
- return match ? { paneId: match.paneId, rect: match.rect } : null;
1150
- }
1151
-
1152
- private localComposerCursorState(): CursorState {
1153
- const rowCount = this.syncBarRowCount();
1154
- const topRow = this.bounds.row + this.bounds.height - 1 - rowCount;
1155
- const col = this.bounds.col + 1;
1156
- const width = Math.max(2, this.bounds.width - 2);
1157
- const prompt = C.accent(`▶ vw:${this.id}`) + C.muted(` ${this.localInputTargetLabel()} ▸ `);
1158
- const promptVw = visibleWidth(stripAnsi(prompt));
1159
- const contRaw = ' '.repeat(Math.max(0, promptVw - 2)) + '↪ ';
1160
- const contVw = visibleWidth(contRaw);
1161
- const s = this.syncBar;
1162
- const { line: cursorLine, col: cursorColInLine } = positionToLineCol(s.composed, s.cursorPos);
1163
- const cursorRowAbs = topRow + Math.min(rowCount - 1, cursorLine);
1164
- const cursorPrompt = cursorLine === 0 ? promptVw : contVw;
1165
- const cursorLineText = s.composed.split('\n')[cursorLine] ?? '';
1166
- const visibleBodyCol = visibleWidth(cursorLineText.slice(s.scrollCol, cursorColInLine));
1167
- const cursorCol = col + cursorPrompt + visibleBodyCol;
1168
- return {
1169
- row: cursorRowAbs,
1170
- col: Math.max(col, Math.min(cursorCol, col + width - 1)),
1171
- visible: true,
1172
- };
1173
- }
1174
-
1175
- private localInputTargetLabel(): string {
1176
- if (this.localInputTarget.kind === 'all') return '@all';
1177
- if (this.localInputTarget.kind === 'focused') return '@focused';
1178
- return `@${this.getPaneDisplayTitle(this.localInputTarget.paneId) || this.localInputTarget.paneId.slice(0, 6)}`;
1179
- }
1180
-
1181
- private paintPane(rect: Rect, grid: string, paneId: PaneId): string {
1182
- const out: string[] = [];
1183
- const pane = this.panes.get(paneId) ?? null;
1184
- const focused = paneId === this.focusedPaneId;
1185
- const pulseActive = focused && (pane?.isAlive ?? false);
1186
- const pulse = pulseActive ? pulsePhase(this.now()) : null;
1187
- const lines = grid.split('\n');
1188
- for (let i = 0; i < rect.height; i++) {
1189
- const line = lines[i] ?? '';
1190
- // F2 (2026-04-21) — each row ends with CSI K (erase-to-EOL)
1191
- // before moving to the next row, so rows that are narrower than
1192
- // `rect.width` don't leave trailing cells holding residue from
1193
- // the previous foreground (dashboard, another VW). SGR reset
1194
- // before EL ensures the erased cells pick up the default bg.
1195
- out.push(
1196
- ansi.moveTo(rect.row + i, rect.col)
1197
- + line
1198
- + '\x1b[0m\x1b[K',
1199
- );
1200
- }
1201
- // Pane divider: draw a thin horizontal/vertical line separating
1202
- // this pane from its neighbors. Skip when adjacent to window
1203
- // border (border already paints).
1204
- const innerRight = this.bounds.col + this.bounds.width - 2;
1205
- const innerBottom = this.bounds.row + this.bounds.height - 2;
1206
- if (rect.col + rect.width - 1 < innerRight) {
1207
- for (let i = 0; i < rect.height; i++) {
1208
- out.push(ansi.moveTo(rect.row + i, rect.col + rect.width - 1) + C.muted('│'));
1209
- }
1210
- }
1211
- if (rect.row + rect.height - 1 < innerBottom) {
1212
- out.push(
1213
- ansi.moveTo(rect.row + rect.height - 1, rect.col) +
1214
- C.muted('─'.repeat(rect.width)),
1215
- );
1216
- }
1217
- // Pane label on the top border for every pane.
1218
- // Focus changes the chrome treatment, but the pane title itself
1219
- // remains visible for all panes so split layouts (showroom,
1220
- // 2x2, 4x4) preserve local identity without requiring focus.
1221
- {
1222
- const override = this.paneTitleOverrides.get(paneId);
1223
- const displayTitle = this.getPaneDisplayTitle(paneId);
1224
- const baseTitle = override ?? (displayTitle || `[${paneId.slice(0, 6)}]`);
1225
- const vis: PaneVisibility = this.visibilityResolver?.(paneId) ?? 'visible';
1226
- const pulseGlyph = pulseActive ? (pulse === 'A' ? '●' : '○') : '';
1227
- const badge = focused ? composeVisibilityBadge(vis) : '';
1228
- const badgeW = focused ? badgeVisibleWidth(vis) : 0;
1229
- const closeReserve = focused && this.panes.size > 1 && !this.zoomedPaneId && rect.width >= 4 ? 2 : 0;
1230
- const pulseW = pulseGlyph ? 2 : 0;
1231
- const titleBudget = Math.max(0, rect.width - closeReserve - pulseW - (badge ? badgeW + 1 : 0));
1232
- const titleState =
1233
- pulseActive && pulse === 'B'
1234
- ? 'pulse-b'
1235
- : pulseActive
1236
- ? 'pulse-a'
1237
- : focused
1238
- ? 'active'
1239
- : 'inactive';
1240
- const labelCore = paneBorderTitle(baseTitle, titleState, titleBudget);
1241
- const labelWithPulse = pulseGlyph && labelCore ? `${labelCore} ${pulseGlyph}` : labelCore;
1242
- const label = badge && labelWithPulse ? `${labelWithPulse} ${badge}` : labelWithPulse;
1243
- const labelW = Math.min(visibleWidth(label), Math.max(0, rect.width - closeReserve));
1244
- if (labelW > 0) {
1245
- out.push(ansi.moveTo(rect.row, rect.col) + '\x1b[0m' + ' '.repeat(labelW));
1246
- out.push(ansi.moveTo(rect.row, rect.col) + label);
1247
- }
1248
- if (debug.enabled) {
1249
- debug.log('vw.pane.label.paint', paneId.slice(0, 6), {
1250
- paneId, focused, pulse,
1251
- labelWidth: labelW, rectRow: rect.row, rectCol: rect.col,
1252
- baseTitle,
1253
- visibility: vis, badgeW,
1254
- });
1255
- }
1256
- }
1257
- // VW-A2 — close `×` glyph on the focused pane's top-right corner.
1258
- // Hidden for solo panes (use `^B X` to close the whole window) and
1259
- // whenever the pane is zoomed — the × would overlap the zoomed
1260
- // label and users rarely want to close a pane they're focused on
1261
- // in zoom mode anyway.
1262
- if (
1263
- paneId === this.focusedPaneId
1264
- && this.panes.size > 1
1265
- && !this.zoomedPaneId
1266
- && rect.width >= 4
1267
- ) {
1268
- const closeCol = rect.col + rect.width - 2;
1269
- out.push(ansi.moveTo(rect.row, closeCol) + C.error('×'));
1270
- }
1271
- return out.join('');
1272
- }
1273
-
1274
- /** VW-A2 — hit-test for the per-pane `×` close button. Returns the
1275
- * pane id whose close button covers (col, row), or null. Kept
1276
- * separate from onMouse so tests can validate the geometry without
1277
- * side-effecting focus / close. */
1278
- closeButtonAt(col: number, row: number): PaneId | null {
1279
- if (this.panes.size < 2) return null;
1280
- if (this.zoomedPaneId) return null;
1281
- for (const { paneId, rect } of this.paneRects()) {
1282
- if (paneId !== this.focusedPaneId) continue;
1283
- if (rect.width < 4) continue;
1284
- const closeCol = rect.col + rect.width - 2;
1285
- if (row === rect.row && col === closeCol) return paneId;
1286
- }
1287
- return null;
1288
- }
1289
- }
1290
-
1291
- /** U2 — convert an absolute cursor offset into (line, col) given
1292
- * newline-separated composed buffer. Used by the multi-line paint
1293
- * path to place the caret in the right row. */
1294
- function positionToLineCol(text: string, pos: number): { line: number; col: number } {
1295
- let line = 0;
1296
- let lineStart = 0;
1297
- for (let i = 0; i < pos && i < text.length; i++) {
1298
- if (text[i] === '\n') { line += 1; lineStart = i + 1; }
1299
- }
1300
- return { line, col: pos - lineStart };
1301
- }