elanous 0.2.0 → 0.2.5

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 (1249) hide show
  1. package/.env.example +6 -0
  2. package/README.md +17 -15
  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/06ef2eba-d1b99ac6d2ea663c.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1413-7179a49332db5a80.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/150-25c277137a9638ab.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1640-bc99ec23bbe29d12.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/1751.50b96ea9c37b49b6.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2300-de059d0ab2a16630.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/2684-05b0a81e75298c16.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/3026-2ed7e317d9b02102.js +25 -0
  13. package/apps/pwa/out/_next/static/chunks/3611-77496ada38cd6358.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/3717-68957c4dc9ceec90.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/3929-46ba9af6f9d895cc.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/4015-62c5a3744698a8da.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/4217-3c4317a7905f9eeb.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/4240-3230f230fae2d7d5.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/4271-e53e075ebd48593b.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/4377.3b125fef79576dfd.js +5 -0
  21. package/apps/pwa/out/_next/static/chunks/4440-18bb160d95819f4e.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4853-35fdbe6bdbcdc0fc.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{2a79f15a-2013e4d421d6df88.js → 4daa2798-1363d725c79f3593.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/5007-6a3b30e23ff68a6e.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/5244-12b424c42070f5ff.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/5348-bbf838e119661eee.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/5391-8793f88b03b30161.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/5611-df00af3e4e4a61bb.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/5890-dca2321773be829a.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/6123-37c9dc57ddaa7ab0.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/6588-b7975304a302ab91.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/6604-c03961962b6273b6.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/7109-cf8c87e968e83a65.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/7178-30f77877525a2efb.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/7262-871563fc9663730b.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/7294-f0eeebb92aa93459.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/7429-881af44deed6958f.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{5927.8378481a12cc8044.js → 7527.943753b6ed829f09.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/764-a01e858525a190c0.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/7868-e35d5f7985ecd3f1.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8320-51484af7b01fdfa5.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{6804.8ed6ab492bc5fc0a.js → 8617.465ca22a319c95b3.js} +1 -1
  43. package/apps/pwa/out/_next/static/chunks/{320-d7013ec072863e5e.js → 8918-482b30ce2a8ebf4c.js} +4 -4
  44. package/apps/pwa/out/_next/static/chunks/9131-52f5fad51cceca04.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{2598.814f64e3268634e7.js → 9238.2cd5f47f4bf7a2c3.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/9704-3221c102623c8d73.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-70c404c7bb6d7f0f.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/app/approvals/page-3ffd80166b1050aa.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f89e9a303515a033.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/app/board/page-4f403cd060442c95.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/botlab/page-0ac5d053f0444d21.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/bots/page-4bcc63e272ae8205.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/chat/page-880734bd07d62882.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/control/page-72bd384898d88955.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1018bbc9586ecae5.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/app/editor/page-de86f8c38076dd7b.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/healthz/route-70c404c7bb6d7f0f.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/intake/page-cd6447196d8bafe6.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/layout-e733630c47fa102b.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/live/page-d1c1a8357b161875.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/market/page-60c514128e81d787.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8b637b7e325e13c1.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/morning/page-bccce0babceae30f.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/not-found-63301d11dbe73836.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/observatory/page-a8cf0dc472060db2.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/page-02fba54881ccfa49.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/reflection/page-d5e8e90f0038f8de.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-b1ef6824f494466a.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d589bb0f233b1009.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c9bbaebef4cda059.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/settings/page-3639ce7916b92fed.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7450ae7478955653.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/setup/layout-70c404c7bb6d7f0f.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/setup/page-b41ca4abfd618452.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/share/page-b333dd79ebee3fa9.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/showroom/page-8be1227492793655.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/tasks/page-6e03e9371b552e0d.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/term/page-911411e9fca18d03.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/trace/page-792170e649b37088.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/vault/page-c40463466937bc91.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-509c798b80384536.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/workflows/page-1cac2aa21d77c417.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9626799d9b4a2cd1.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-84cd419494e16b0f.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/f6f3850d-7f324c6566002113.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/framework-361487d2da603917.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/main-app-607f5beb94cb2e07.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/main-d0222d219e29dddf.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/pages/_app-a26980a31126decc.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/pages/_error-edb2b37decf23e4d.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/webpack-2bf59c720fe9542c.js +1 -0
  92. package/apps/pwa/out/_next/static/css/eaa74e8bb2f62269.css +1 -0
  93. package/apps/pwa/out/_next/static/ktMqfrBbf8BMGac0jqLrb/_buildManifest.js +1 -0
  94. package/apps/pwa/out/approvals/index.html +1 -0
  95. package/apps/pwa/out/approvals/index.txt +32 -0
  96. package/apps/pwa/out/autopilot/index.html +1 -1
  97. package/apps/pwa/out/autopilot/index.txt +29 -26
  98. package/apps/pwa/out/board/index.html +1 -0
  99. package/apps/pwa/out/board/index.txt +32 -0
  100. package/apps/pwa/out/botlab/index.html +1 -1
  101. package/apps/pwa/out/botlab/index.txt +26 -23
  102. package/apps/pwa/out/bots/index.html +1 -1
  103. package/apps/pwa/out/bots/index.txt +26 -23
  104. package/apps/pwa/out/chat/index.html +1 -2
  105. package/apps/pwa/out/chat/index.txt +26 -23
  106. package/apps/pwa/out/control/index.html +1 -1
  107. package/apps/pwa/out/control/index.txt +29 -26
  108. package/apps/pwa/out/design-check/index.html +1 -1
  109. package/apps/pwa/out/design-check/index.txt +29 -26
  110. package/apps/pwa/out/editor/index.html +1 -0
  111. package/apps/pwa/out/editor/index.txt +33 -0
  112. package/apps/pwa/out/healthz +1 -1
  113. package/apps/pwa/out/icons/elanous-16.png +0 -0
  114. package/apps/pwa/out/icons/elanous-180.png +0 -0
  115. package/apps/pwa/out/icons/elanous-192.png +0 -0
  116. package/apps/pwa/out/icons/elanous-32.png +0 -0
  117. package/apps/pwa/out/icons/elanous-512.png +0 -0
  118. package/apps/pwa/out/index.html +1 -1
  119. package/apps/pwa/out/index.txt +26 -23
  120. package/apps/pwa/out/intake/index.html +1 -1
  121. package/apps/pwa/out/intake/index.txt +29 -26
  122. package/apps/pwa/out/live/index.html +1 -0
  123. package/apps/pwa/out/live/index.txt +32 -0
  124. package/apps/pwa/out/manifest.webmanifest +5 -2
  125. package/apps/pwa/out/market/index.html +1 -0
  126. package/apps/pwa/out/market/index.txt +29 -0
  127. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  128. package/apps/pwa/out/missions/placeholder/index.txt +26 -23
  129. package/apps/pwa/out/morning/index.html +1 -1
  130. package/apps/pwa/out/morning/index.txt +29 -26
  131. package/apps/pwa/out/observatory/index.html +1 -1
  132. package/apps/pwa/out/observatory/index.txt +29 -26
  133. package/apps/pwa/out/reflection/index.html +1 -1
  134. package/apps/pwa/out/reflection/index.txt +27 -24
  135. package/apps/pwa/out/scheduler/index.html +1 -1
  136. package/apps/pwa/out/scheduler/index.txt +29 -26
  137. package/apps/pwa/out/sessions/index.html +1 -1
  138. package/apps/pwa/out/sessions/index.txt +26 -23
  139. package/apps/pwa/out/settings/devices/index.html +1 -1
  140. package/apps/pwa/out/settings/devices/index.txt +29 -26
  141. package/apps/pwa/out/settings/index.html +1 -1
  142. package/apps/pwa/out/settings/index.txt +29 -26
  143. package/apps/pwa/out/setup/done/index.html +1 -1
  144. package/apps/pwa/out/setup/done/index.txt +29 -26
  145. package/apps/pwa/out/setup/index.html +1 -1
  146. package/apps/pwa/out/setup/index.txt +29 -26
  147. package/apps/pwa/out/share/index.html +1 -1
  148. package/apps/pwa/out/share/index.txt +29 -26
  149. package/apps/pwa/out/showroom/index.html +1 -1
  150. package/apps/pwa/out/showroom/index.txt +26 -23
  151. package/apps/pwa/out/sw-strategies.js +44 -0
  152. package/apps/pwa/out/sw.js +6 -44
  153. package/apps/pwa/out/tasks/index.html +1 -1
  154. package/apps/pwa/out/tasks/index.txt +29 -26
  155. package/apps/pwa/out/term/index.html +1 -1
  156. package/apps/pwa/out/term/index.txt +29 -26
  157. package/apps/pwa/out/trace/index.html +1 -0
  158. package/apps/pwa/out/trace/index.txt +32 -0
  159. package/apps/pwa/out/vault/index.html +1 -1
  160. package/apps/pwa/out/vault/index.txt +29 -26
  161. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  162. package/apps/pwa/out/workflows/chat-ui/index.txt +29 -26
  163. package/apps/pwa/out/workflows/index.html +1 -1
  164. package/apps/pwa/out/workflows/index.txt +29 -27
  165. package/apps/pwa/out/workspace/index.html +1 -1
  166. package/apps/pwa/out/workspace/index.txt +29 -26
  167. package/apps/pwa/out/worktrees/index.html +1 -1
  168. package/apps/pwa/out/worktrees/index.txt +29 -26
  169. package/catalog/resources.yaml +14 -17
  170. package/docs/design/systems/LICENSE +201 -0
  171. package/docs/design/systems/NOTICE.md +29 -0
  172. package/docs/design/systems/SOURCE.json +291 -0
  173. package/docs/design/systems/application/DESIGN.md +71 -0
  174. package/docs/design/systems/application/manifest.json +54 -0
  175. package/docs/design/systems/application/tokens.css +63 -0
  176. package/docs/design/systems/artistic/DESIGN.md +71 -0
  177. package/docs/design/systems/artistic/manifest.json +54 -0
  178. package/docs/design/systems/artistic/tokens.css +63 -0
  179. package/docs/design/systems/bento/DESIGN.md +71 -0
  180. package/docs/design/systems/bento/manifest.json +54 -0
  181. package/docs/design/systems/bento/tokens.css +63 -0
  182. package/docs/design/systems/bold/DESIGN.md +71 -0
  183. package/docs/design/systems/bold/manifest.json +54 -0
  184. package/docs/design/systems/bold/tokens.css +63 -0
  185. package/docs/design/systems/brutalism/DESIGN.md +71 -0
  186. package/docs/design/systems/brutalism/manifest.json +54 -0
  187. package/docs/design/systems/brutalism/tokens.css +63 -0
  188. package/docs/design/systems/cafe/DESIGN.md +71 -0
  189. package/docs/design/systems/cafe/manifest.json +54 -0
  190. package/docs/design/systems/cafe/tokens.css +63 -0
  191. package/docs/design/systems/claymorphism/DESIGN.md +71 -0
  192. package/docs/design/systems/claymorphism/manifest.json +54 -0
  193. package/docs/design/systems/claymorphism/tokens.css +63 -0
  194. package/docs/design/systems/clean/DESIGN.md +71 -0
  195. package/docs/design/systems/clean/manifest.json +54 -0
  196. package/docs/design/systems/clean/tokens.css +63 -0
  197. package/docs/design/systems/colorful/DESIGN.md +71 -0
  198. package/docs/design/systems/colorful/manifest.json +54 -0
  199. package/docs/design/systems/colorful/tokens.css +63 -0
  200. package/docs/design/systems/contemporary/DESIGN.md +71 -0
  201. package/docs/design/systems/contemporary/manifest.json +54 -0
  202. package/docs/design/systems/contemporary/tokens.css +63 -0
  203. package/docs/design/systems/corporate/DESIGN.md +71 -0
  204. package/docs/design/systems/corporate/manifest.json +54 -0
  205. package/docs/design/systems/corporate/tokens.css +63 -0
  206. package/docs/design/systems/cosmic/DESIGN.md +71 -0
  207. package/docs/design/systems/cosmic/manifest.json +54 -0
  208. package/docs/design/systems/cosmic/tokens.css +63 -0
  209. package/docs/design/systems/creative/DESIGN.md +71 -0
  210. package/docs/design/systems/creative/manifest.json +54 -0
  211. package/docs/design/systems/creative/tokens.css +63 -0
  212. package/docs/design/systems/dashboard/DESIGN.md +71 -0
  213. package/docs/design/systems/dashboard/manifest.json +54 -0
  214. package/docs/design/systems/dashboard/tokens.css +63 -0
  215. package/docs/design/systems/default/DESIGN.md +62 -0
  216. package/docs/design/systems/default/manifest.json +69 -0
  217. package/docs/design/systems/default/tokens.css +200 -0
  218. package/docs/design/systems/dithered/DESIGN.md +71 -0
  219. package/docs/design/systems/dithered/manifest.json +54 -0
  220. package/docs/design/systems/dithered/tokens.css +63 -0
  221. package/docs/design/systems/doodle/DESIGN.md +71 -0
  222. package/docs/design/systems/doodle/manifest.json +54 -0
  223. package/docs/design/systems/doodle/tokens.css +63 -0
  224. package/docs/design/systems/dramatic/DESIGN.md +71 -0
  225. package/docs/design/systems/dramatic/manifest.json +54 -0
  226. package/docs/design/systems/dramatic/tokens.css +63 -0
  227. package/docs/design/systems/editorial/DESIGN.md +71 -0
  228. package/docs/design/systems/editorial/manifest.json +54 -0
  229. package/docs/design/systems/editorial/tokens.css +63 -0
  230. package/docs/design/systems/elegant/DESIGN.md +71 -0
  231. package/docs/design/systems/elegant/manifest.json +54 -0
  232. package/docs/design/systems/elegant/tokens.css +63 -0
  233. package/docs/design/systems/energetic/DESIGN.md +72 -0
  234. package/docs/design/systems/energetic/manifest.json +54 -0
  235. package/docs/design/systems/energetic/tokens.css +63 -0
  236. package/docs/design/systems/enterprise/DESIGN.md +71 -0
  237. package/docs/design/systems/enterprise/manifest.json +54 -0
  238. package/docs/design/systems/enterprise/tokens.css +63 -0
  239. package/docs/design/systems/expressive/DESIGN.md +71 -0
  240. package/docs/design/systems/expressive/manifest.json +54 -0
  241. package/docs/design/systems/expressive/tokens.css +63 -0
  242. package/docs/design/systems/fantasy/DESIGN.md +71 -0
  243. package/docs/design/systems/fantasy/manifest.json +54 -0
  244. package/docs/design/systems/fantasy/tokens.css +63 -0
  245. package/docs/design/systems/flat/DESIGN.md +71 -0
  246. package/docs/design/systems/flat/manifest.json +54 -0
  247. package/docs/design/systems/flat/tokens.css +63 -0
  248. package/docs/design/systems/friendly/DESIGN.md +71 -0
  249. package/docs/design/systems/friendly/manifest.json +54 -0
  250. package/docs/design/systems/friendly/tokens.css +63 -0
  251. package/docs/design/systems/glassmorphism/DESIGN.md +71 -0
  252. package/docs/design/systems/glassmorphism/manifest.json +54 -0
  253. package/docs/design/systems/glassmorphism/tokens.css +63 -0
  254. package/docs/design/systems/gradient/DESIGN.md +71 -0
  255. package/docs/design/systems/gradient/manifest.json +54 -0
  256. package/docs/design/systems/gradient/tokens.css +63 -0
  257. package/docs/design/systems/luxury/DESIGN.md +71 -0
  258. package/docs/design/systems/luxury/manifest.json +54 -0
  259. package/docs/design/systems/luxury/tokens.css +63 -0
  260. package/docs/design/systems/minimal/DESIGN.md +71 -0
  261. package/docs/design/systems/minimal/manifest.json +54 -0
  262. package/docs/design/systems/minimal/tokens.css +63 -0
  263. package/docs/design/systems/modern/DESIGN.md +71 -0
  264. package/docs/design/systems/modern/manifest.json +54 -0
  265. package/docs/design/systems/modern/tokens.css +63 -0
  266. package/docs/design/systems/mono/DESIGN.md +71 -0
  267. package/docs/design/systems/mono/manifest.json +54 -0
  268. package/docs/design/systems/mono/tokens.css +63 -0
  269. package/docs/design/systems/neobrutalism/DESIGN.md +71 -0
  270. package/docs/design/systems/neobrutalism/manifest.json +54 -0
  271. package/docs/design/systems/neobrutalism/tokens.css +63 -0
  272. package/docs/design/systems/neon/DESIGN.md +71 -0
  273. package/docs/design/systems/neon/manifest.json +54 -0
  274. package/docs/design/systems/neon/tokens.css +63 -0
  275. package/docs/design/systems/neumorphism/DESIGN.md +71 -0
  276. package/docs/design/systems/neumorphism/manifest.json +54 -0
  277. package/docs/design/systems/neumorphism/tokens.css +63 -0
  278. package/docs/design/systems/paper/DESIGN.md +71 -0
  279. package/docs/design/systems/paper/manifest.json +54 -0
  280. package/docs/design/systems/paper/tokens.css +63 -0
  281. package/docs/design/systems/perspective/DESIGN.md +71 -0
  282. package/docs/design/systems/perspective/manifest.json +54 -0
  283. package/docs/design/systems/perspective/tokens.css +63 -0
  284. package/docs/design/systems/premium/DESIGN.md +71 -0
  285. package/docs/design/systems/premium/manifest.json +54 -0
  286. package/docs/design/systems/premium/tokens.css +63 -0
  287. package/docs/design/systems/professional/DESIGN.md +71 -0
  288. package/docs/design/systems/professional/manifest.json +54 -0
  289. package/docs/design/systems/professional/tokens.css +63 -0
  290. package/docs/design/systems/publication/DESIGN.md +71 -0
  291. package/docs/design/systems/publication/manifest.json +54 -0
  292. package/docs/design/systems/publication/tokens.css +63 -0
  293. package/docs/design/systems/refined/DESIGN.md +71 -0
  294. package/docs/design/systems/refined/manifest.json +54 -0
  295. package/docs/design/systems/refined/tokens.css +63 -0
  296. package/docs/design/systems/retro/DESIGN.md +71 -0
  297. package/docs/design/systems/retro/manifest.json +54 -0
  298. package/docs/design/systems/retro/tokens.css +63 -0
  299. package/docs/design/systems/shadcn/DESIGN.md +71 -0
  300. package/docs/design/systems/shadcn/manifest.json +54 -0
  301. package/docs/design/systems/shadcn/tokens.css +255 -0
  302. package/docs/design/systems/simple/DESIGN.md +71 -0
  303. package/docs/design/systems/simple/manifest.json +54 -0
  304. package/docs/design/systems/simple/tokens.css +63 -0
  305. package/docs/design/systems/skeumorphism/DESIGN.md +71 -0
  306. package/docs/design/systems/skeumorphism/manifest.json +54 -0
  307. package/docs/design/systems/skeumorphism/tokens.css +63 -0
  308. package/docs/design/systems/sleek/DESIGN.md +71 -0
  309. package/docs/design/systems/sleek/manifest.json +54 -0
  310. package/docs/design/systems/sleek/tokens.css +63 -0
  311. package/docs/design/systems/spacious/DESIGN.md +71 -0
  312. package/docs/design/systems/spacious/manifest.json +54 -0
  313. package/docs/design/systems/spacious/tokens.css +63 -0
  314. package/docs/design/systems/storytelling/DESIGN.md +71 -0
  315. package/docs/design/systems/storytelling/manifest.json +54 -0
  316. package/docs/design/systems/storytelling/tokens.css +63 -0
  317. package/docs/design/systems/tom-modern/DESIGN.md +361 -0
  318. package/docs/design/systems/tom-modern/manifest.json +16 -0
  319. package/docs/design/systems/tom-modern/tokens.css +99 -0
  320. package/docs/design/systems/vibrant/DESIGN.md +71 -0
  321. package/docs/design/systems/vibrant/manifest.json +54 -0
  322. package/docs/design/systems/vibrant/tokens.css +63 -0
  323. package/docs/design/systems/vintage/DESIGN.md +71 -0
  324. package/docs/design/systems/vintage/manifest.json +54 -0
  325. package/docs/design/systems/vintage/tokens.css +63 -0
  326. package/docs/design/systems/warm-editorial/DESIGN.md +65 -0
  327. package/docs/design/systems/warm-editorial/manifest.json +54 -0
  328. package/docs/design/systems/warm-editorial/tokens.css +63 -0
  329. package/docs/goal-context/01-goal-authoring-checks.md +18 -0
  330. package/docs/goal-context/steward-directives-2026-09-28.md +42 -0
  331. package/graphs/catalog/catalog.yaml +615 -0
  332. package/graphs/default-loop.yaml +1 -1
  333. package/graphs/document-loop.yaml +1 -1
  334. package/graphs/examples/stale-draft-digest/digest.ts +26 -0
  335. package/graphs/examples/stale-draft-digest/recipes.yaml +8 -0
  336. package/graphs/examples/stale-draft-digest/stale-draft-digest.yaml +22 -0
  337. package/graphs/heal/heal-loop.yaml +155 -0
  338. package/graphs/heal/recipes.yaml +19 -0
  339. package/graphs/implement-loop.yaml +2 -2
  340. package/graphs/intake/intake-daily.yaml +55 -0
  341. package/graphs/intake/recipes.yaml +16 -0
  342. package/graphs/landing/landing-heal.yaml +22 -0
  343. package/graphs/landing/recipes.yaml +8 -0
  344. package/graphs/launch/launch-head.yaml +66 -0
  345. package/graphs/launch/recipes.yaml +8 -0
  346. package/graphs/operate-loop.yaml +1 -1
  347. package/graphs/ops/docs-publish.yaml +31 -0
  348. package/graphs/ops/recipes.yaml +8 -0
  349. package/graphs/release/recipes.yaml +45 -0
  350. package/graphs/release/release-loop.yaml +45 -0
  351. package/graphs/research-loop.yaml +1 -1
  352. package/graphs/steward/recipes.yaml +12 -0
  353. package/graphs/steward/steward.yaml +45 -0
  354. package/graphs/video/README.md +1 -0
  355. package/graphs/video/broll-line.yaml +54 -0
  356. package/graphs/video/explainer-line.yaml +58 -0
  357. package/package.json +9 -5
  358. package/plugins/job-coach/.agents/plugins/marketplace.json +12 -0
  359. package/plugins/job-coach/.codex-plugin/plugin.json +23 -0
  360. package/plugins/job-coach/.mcp.json +9 -0
  361. package/plugins/job-coach/README.md +32 -0
  362. package/plugins/job-coach/connectors/ncs/server.ts +90 -0
  363. package/plugins/job-coach/examples/interview-sample.md +11 -0
  364. package/plugins/job-coach/graphs/course-links.ts +46 -0
  365. package/plugins/job-coach/graphs/gap-judge.ts +44 -0
  366. package/plugins/job-coach/graphs/recipes.yaml +45 -0
  367. package/plugins/job-coach/graphs/report-enterprise.yaml +28 -0
  368. package/plugins/job-coach/graphs/report.yaml +20 -0
  369. package/plugins/job-coach/graphs/run-step.ts +302 -0
  370. package/plugins/job-coach/plugin.json +26 -0
  371. package/plugins/job-coach/plugin.ts +6 -0
  372. package/plugins/job-coach/skills/career-report/SKILL.md +6 -0
  373. package/plugins/job-coach/skills/enterprise-ai-fit/SKILL.md +8 -0
  374. package/plugins/job-coach/skills/enterprise-competency/SKILL.md +8 -0
  375. package/plugins/job-coach/skills/enterprise-needs/SKILL.md +8 -0
  376. package/plugins/job-coach/skills/enterprise-roadmap/SKILL.md +8 -0
  377. package/plugins/job-coach/skills/enterprise-task-analysis/SKILL.md +8 -0
  378. package/plugins/job-coach/skills/interview-to-profile/SKILL.md +23 -0
  379. package/plugins/job-coach/skills/run-report/SKILL.md +15 -0
  380. package/scripts/backup/elanous-backup.sh +143 -14
  381. package/scripts/backup/elanous-restore.sh +122 -0
  382. package/scripts/build-docs-site.ts +4 -3
  383. package/scripts/ci-daemon-port-gate.ts +164 -0
  384. package/scripts/ci-typecheck-changed.ts +15 -1
  385. package/scripts/cli-json-exit-scan.ts +126 -0
  386. package/scripts/codex-quota-alert-format.ts +52 -0
  387. package/scripts/codex-quota-alert.ts +63 -13
  388. package/scripts/continuation-dogfood.ts +2 -1
  389. package/scripts/coord-channel-watch.sh +28 -9
  390. package/scripts/coord-post.sh +49 -12
  391. package/scripts/coord-tracks.json +6 -5
  392. package/scripts/cron-run.ts +37 -16
  393. package/scripts/daemon-port-baseline.txt +9 -0
  394. package/scripts/design/extract-corpus-bench.ts +469 -0
  395. package/scripts/design/extract-corpus-score.ts +510 -0
  396. package/scripts/design/vendor-open-design-systems.ts +100 -0
  397. package/scripts/docs-lint.ts +1 -1
  398. package/scripts/eval-bot-vs-grok.ts +79 -0
  399. package/scripts/eval-grok-live-baseline.ts +36 -0
  400. package/scripts/fixtures/front-route-corpus.sample.json +17 -0
  401. package/scripts/fleet/node-setup.sh +80 -7
  402. package/scripts/heal/run-role.ts +328 -0
  403. package/scripts/install-role-watch.sh +95 -0
  404. package/scripts/install.ps1 +11 -1
  405. package/scripts/install.sh +81 -9
  406. package/scripts/isolation-hardcode-baseline.txt +1 -1
  407. package/scripts/landing-heal/must-fix-match.ts +63 -0
  408. package/scripts/landing-heal/run-mission.ts +195 -0
  409. package/scripts/lib/front-route-measurement.ts +131 -0
  410. package/scripts/lib/pwa-scenarios/acp-replay.ts +79 -0
  411. package/scripts/lib/pwa-scenarios/cdp-driver.ts +67 -0
  412. package/scripts/lib/pwa-scenarios/runner.ts +200 -0
  413. package/scripts/lib/pwa-scenarios/scenarios.ts +202 -0
  414. package/scripts/lib/tui-sim-keys.ts +42 -0
  415. package/scripts/market/db-check.ts +212 -0
  416. package/scripts/market-posture-cycle.ts +63 -4
  417. package/scripts/measure-front-route-classifier.ts +56 -0
  418. package/scripts/media/ocr-leak-scan.sh +21 -0
  419. package/scripts/nightly-docops.ts +1 -1
  420. package/scripts/ops/channel-bot-token-migrate.ts +146 -0
  421. package/scripts/ops-health-check.ts +15 -3
  422. package/scripts/pty-scenarios/run.ts +272 -0
  423. package/scripts/public-export.ts +2 -3
  424. package/scripts/public-import-pr.ts +80 -6
  425. package/scripts/public-leak-baseline.txt +0 -7
  426. package/scripts/publish-internal-dist.ts +118 -0
  427. package/scripts/pwa-scenarios.ts +106 -0
  428. package/scripts/rebrand-elanous.ts +1 -1
  429. package/scripts/red-sweep-diff.ts +1 -1
  430. package/scripts/release-loop/auto-approve-node.ts +72 -0
  431. package/scripts/release-loop/cutoff.ts +139 -0
  432. package/scripts/release-loop/docs-land-node.ts +65 -0
  433. package/scripts/release-loop/docs-node.ts +172 -0
  434. package/scripts/release-loop/gate-diff.ts +29 -0
  435. package/scripts/release-loop/gate-node.ts +641 -0
  436. package/scripts/release-loop/node-verdict.ts +85 -0
  437. package/scripts/release-loop/prepare-node.ts +31 -0
  438. package/scripts/release-loop/publish-node.ts +61 -0
  439. package/scripts/release-loop/pwa-node-verdict.ts +45 -0
  440. package/scripts/release-loop/pwa-scenarios-node.ts +140 -0
  441. package/scripts/release-loop/release-docs.ts +109 -0
  442. package/scripts/release-loop/test-durations.ts +63 -0
  443. package/scripts/release-loop/tui-node-checks.ts +29 -0
  444. package/scripts/release-loop/tui-sim-node.ts +113 -0
  445. package/scripts/release-loop/upgrade-node.ts +26 -0
  446. package/scripts/release-loop/verify-node.ts +21 -0
  447. package/scripts/release-loop/version-node.ts +147 -0
  448. package/scripts/release-upgrade-check.sh +53 -0
  449. package/scripts/se-mission-prepare.ts +9 -15
  450. package/scripts/test-audit-coverage-per-file.sh +16 -0
  451. package/scripts/test-audit-meaningless.ts +88 -0
  452. package/scripts/test-audit-overlap-and-weak.ts +73 -0
  453. package/scripts/test-deterministic.ts +29 -6
  454. package/scripts/tui-sim.ts +59 -14
  455. package/scripts/uninstall.sh +10 -3
  456. package/scripts/ux/bump-installed.sh +20 -0
  457. package/scripts/ux/lib/cdp.ts +72 -0
  458. package/scripts/ux/record-page.ts +50 -0
  459. package/scripts/video-broll-line.ts +89 -0
  460. package/scripts/waitlist-daily-digest.ts +108 -0
  461. package/scripts/window-landings.sh +1 -1
  462. package/skills/explainer-video/SKILL.md +99 -0
  463. package/skills/explainer-video/engine/brand/elanous-mark-on-dark.svg +1 -0
  464. package/skills/explainer-video/engine/build.mjs +431 -0
  465. package/skills/explainer-video/engine/vo.ts +37 -0
  466. package/skills/explainer-video/examples/elanous-0.2.5/script.json +155 -0
  467. package/skills/motion-broll/LICENSE +25 -0
  468. package/skills/motion-broll/SKILL.md +150 -0
  469. package/skills/motion-broll/SOURCE.md +6 -0
  470. package/skills/motion-broll/engine/base.css +19 -0
  471. package/skills/motion-broll/engine/beats.js +11 -0
  472. package/skills/motion-broll/engine/build.py +21 -0
  473. package/skills/motion-broll/engine/fonts/Geist-Variable.woff2 +0 -0
  474. package/skills/motion-broll/engine/fonts/GeistMono-Medium.woff2 +0 -0
  475. package/skills/motion-broll/engine/fonts/OFL-Geist.txt +92 -0
  476. package/skills/motion-broll/engine/motion.js +146 -0
  477. package/skills/motion-broll/engine/render.js +22 -0
  478. package/skills/motion-broll/examples/opus-aoe2/01-opus-drop.html +41 -0
  479. package/skills/motion-broll/examples/opus-aoe2/02-pip-builds.html +110 -0
  480. package/skills/motion-broll/examples/opus-aoe2/03-effort-slider.html +38 -0
  481. package/skills/motion-broll/examples/opus-aoe2/04-master-prompt.html +56 -0
  482. package/skills/motion-broll/examples/opus-aoe2/05-low-vs-max.html +49 -0
  483. package/skills/motion-broll/examples/opus-aoe2/06-chapter.html +18 -0
  484. package/skills/motion-broll/examples/opus-aoe2/plan.json +14 -0
  485. package/skills/motion-broll/reference/engine-api.md +106 -0
  486. package/skills/motion-broll/scripts/composite.py +14 -0
  487. package/skills/motion-broll/scripts/inspect_video.py +34 -0
  488. package/skills/motion-broll/scripts/make_pages.py +34 -0
  489. package/skills/motion-broll/scripts/setup.sh +16 -0
  490. package/skills/motion-broll/scripts/words.py +13 -0
  491. package/skills/motion-broll/templates/compare.html +135 -0
  492. package/skills/motion-broll/templates/viewer.html +97 -0
  493. package/skills/omni-digest/SKILL.md +260 -0
  494. package/skills/omni-digest/digest.md +197 -0
  495. package/skills/omni-digest/docs/diagrams/noncode-terminal-promotion-path-2026-08-13.mmd +32 -0
  496. package/skills/omni-digest/package-lock.json +558 -0
  497. package/skills/omni-digest/package.json +13 -0
  498. package/skills/omni-digest/scripts/main.ts +404 -0
  499. package/skills/omni-digest/src/delegate.ts +34 -0
  500. package/skills/omni-digest/src/detect.ts +46 -0
  501. package/skills/omni-digest/src/diagram.ts +72 -0
  502. package/skills/omni-digest/src/domain-staging.ts +50 -0
  503. package/skills/omni-digest/src/env.ts +38 -0
  504. package/skills/omni-digest/src/fetch.ts +237 -0
  505. package/skills/omni-digest/src/media.ts +180 -0
  506. package/skills/omni-digest/src/obsidian.ts +69 -0
  507. package/skills/omni-digest/src/ocr.ts +149 -0
  508. package/skills/omni-digest/src/router.ts +60 -0
  509. package/skills/omni-digest/src/summarize.ts +87 -0
  510. package/skills/omni-digest/src/types.ts +124 -0
  511. package/skills/omni-digest/src/util.ts +34 -0
  512. package/skills/omni-digest/src/visual.ts +129 -0
  513. package/skills/omni-digest/src/x-api.ts +151 -0
  514. package/skills/omni-digest/tsconfig.json +13 -0
  515. package/src/a2a/agent-card.ts +29 -0
  516. package/src/a2a/server.ts +173 -0
  517. package/src/acp/auto-persist.ts +3 -6
  518. package/src/acp/backend-registry.ts +6 -10
  519. package/src/acp/channel-browser-shell.ts +1 -535
  520. package/src/acp/client.ts +106 -36
  521. package/src/acp/fs-roots.ts +20 -4
  522. package/src/acp/obsidian-tags.ts +6 -3
  523. package/src/acp/server.ts +189 -32
  524. package/src/agent/nested-agent-env.ts +1 -0
  525. package/src/agent/pty-binding.ts +1 -1
  526. package/src/agent/spawn-embodied-agent-in-vw.ts +5 -336
  527. package/src/agent/subagent-callable.ts +39 -1
  528. package/src/agent-mission/browser-login.ts +241 -0
  529. package/src/agent-mission/capabilities-cli.ts +33 -0
  530. package/src/agent-mission/capability-matrix.ts +31 -0
  531. package/src/agent-mission/capability-readers.ts +79 -0
  532. package/src/agent-mission/capability-types.ts +15 -0
  533. package/src/agent-mission/claude-headless.ts +131 -0
  534. package/src/agent-mission/claude-subscription.ts +57 -0
  535. package/src/agent-mission/doc-guided-install.ts +185 -0
  536. package/src/agent-mission/driver.ts +900 -69
  537. package/src/agent-mission/env-profile.ts +68 -0
  538. package/src/agent-mission/handoff.ts +128 -0
  539. package/src/agent-mission/in-agent-plugin.ts +311 -0
  540. package/src/agent-mission/mission-cli.ts +25 -1
  541. package/src/agent-mission/parse.ts +9 -4
  542. package/src/agent-mission/pr-review-watch.ts +62 -13
  543. package/src/agent-mission/resource-ladder.ts +235 -0
  544. package/src/agent-mission/tool-install.ts +249 -0
  545. package/src/agent-mission/tool-ladder.ts +37 -0
  546. package/src/agent-room/room-builder.ts +6 -600
  547. package/src/agent-substrate/review-intent.ts +43 -1
  548. package/src/auth/acp-token.ts +16 -0
  549. package/src/auth/github-app-token.ts +112 -0
  550. package/src/auth/scope.ts +8 -4
  551. package/src/auth/temp-tokens.ts +131 -0
  552. package/src/auto-research/obsidian-bridge.ts +2 -0
  553. package/src/autopilot/build/integrity-gate.ts +27 -4
  554. package/src/autopilot/build/isolated-instance.ts +2 -1
  555. package/src/autopilot/build/llm-conflict-merge.ts +27 -0
  556. package/src/autopilot/gh-rest-fallback.ts +177 -0
  557. package/src/autopilot/llm-control-brain.ts +54 -12
  558. package/src/autopilot/mission-engine.ts +15 -1
  559. package/src/autopilot/mission-notify.ts +4 -2
  560. package/src/autopilot/mission-origin.ts +5 -5
  561. package/src/autopilot/mission-phase-track.ts +52 -0
  562. package/src/autopilot/mission-tool.ts +1 -1
  563. package/src/autopilot/pr-manager.ts +51 -4
  564. package/src/autopilot/pty-control-loop.ts +94 -2
  565. package/src/autopilot/track-agent.ts +138 -0
  566. package/src/autopilot/track-courier.ts +153 -0
  567. package/src/boot/acp-server.ts +18 -18
  568. package/src/boot/check-same-origin.ts +19 -5
  569. package/src/boot/daemon-multi-llm-runtime.ts +14 -8
  570. package/src/boot/daemon-prompt-turn.ts +2 -0
  571. package/src/boot/daemon-runtime.ts +36 -14
  572. package/src/boot/daemon-tools/index.ts +16 -0
  573. package/src/boot/daemon-tools/self-implement.ts +4 -0
  574. package/src/boot/daemon-tools/types.ts +3 -0
  575. package/src/boot/daemon-tools/web-search.ts +2 -1
  576. package/src/boot/ws-bridge.ts +11 -0
  577. package/src/browser-cdp/chrome-flags.ts +7 -0
  578. package/src/browser-cdp/client.ts +2 -0
  579. package/src/browser-pane/mount.ts +1 -246
  580. package/src/budget/codex-reset-credit-state.ts +15 -0
  581. package/src/budget/fetchers/codex.ts +2 -1
  582. package/src/budget/run-usage-rollup.ts +11 -4
  583. package/src/budget/unified-usage.ts +2 -1
  584. package/src/capture/tui-self-report.ts +10 -0
  585. package/src/channel-bot-token.ts +126 -0
  586. package/src/chat/index.ts +57 -52
  587. package/src/chat/input-text-key.ts +2 -2
  588. package/src/chat/log-scroll-key.ts +12 -0
  589. package/src/chat/mode/manual.ts +2 -4
  590. package/src/chat/pickers/state.ts +10 -27
  591. package/src/chat/search/modal.ts +14 -2
  592. package/src/chat/submit-trace.ts +30 -0
  593. package/src/chat/tool-render/types.ts +1 -1
  594. package/src/chat/turn-typeahead.ts +2 -1
  595. package/src/chat/wrap.ts +6 -8
  596. package/src/cli/__fixtures__/agent-help-before/agent.txt +18 -0
  597. package/src/cli/__fixtures__/agent-help-before/registry.txt +13 -0
  598. package/src/cli/__fixtures__/agent-help-before/root.txt +100 -0
  599. package/src/cli/__fixtures__/agent-help-before/tier.txt +15 -0
  600. package/src/cli/a2a-cli.ts +52 -0
  601. package/src/cli/agent-cli.ts +726 -0
  602. package/src/cli/autopilot-cli.ts +739 -0
  603. package/src/cli/bg-launch.ts +20 -4
  604. package/src/cli/claude-plugin-setup.ts +199 -0
  605. package/src/cli/config-test-sync.ts +94 -10
  606. package/src/cli/connector-cli.ts +204 -0
  607. package/src/cli/control-cli.ts +220 -0
  608. package/src/cli/control-join-cli.ts +142 -0
  609. package/src/cli/decisions-cli.ts +94 -0
  610. package/src/cli/docs-cli.ts +38 -0
  611. package/src/cli/doctor-cli.ts +262 -77
  612. package/src/cli/doctor-distro.ts +17 -1
  613. package/src/cli/doctor-fix.ts +145 -17
  614. package/src/cli/doctor-llm-assist.ts +71 -0
  615. package/src/cli/doctor-private-files.ts +66 -0
  616. package/src/cli/doctor-readiness.ts +23 -28
  617. package/src/cli/fleet-cli.ts +63 -0
  618. package/src/cli/g6a-registration-probe.ts +16 -0
  619. package/src/cli/git-install-plan.ts +51 -0
  620. package/src/cli/hooks-cli.ts +44 -0
  621. package/src/cli/ingest-token-cli.ts +21 -0
  622. package/src/cli/intake-cli.ts +416 -0
  623. package/src/cli/labels-cli.ts +74 -0
  624. package/src/cli/leader-cli.ts +10 -159
  625. package/src/cli/live-cli.ts +48 -0
  626. package/src/cli/llm-detect-cli.ts +130 -0
  627. package/src/cli/logs-cli.ts +231 -7
  628. package/src/cli/machine-cli.ts +38 -0
  629. package/src/cli/mcp-call.ts +52 -13
  630. package/src/cli/mcp-gateway-cli.ts +94 -0
  631. package/src/cli/mcp-login.ts +116 -8
  632. package/src/cli/mcp-reload.ts +20 -3
  633. package/src/cli/nexus-dist.ts +18 -13
  634. package/src/cli/nexus-ios-bind.ts +20 -7
  635. package/src/cli/ops-cli.ts +225 -0
  636. package/src/cli/plugin-cli.ts +201 -0
  637. package/src/cli/pod-cli.ts +83 -0
  638. package/src/cli/port-lease-local.ts +124 -0
  639. package/src/cli/pr-cli.ts +12 -1
  640. package/src/cli/pr-lineage.ts +2 -1
  641. package/src/cli/provider-cli.ts +720 -0
  642. package/src/cli/pty-record-cli.ts +63 -0
  643. package/src/cli/pty-takeover-cli.ts +57 -40
  644. package/src/cli/pty-web-address.ts +52 -0
  645. package/src/cli/publish-cli.ts +44 -0
  646. package/src/cli/pwa-build.ts +18 -12
  647. package/src/cli/pwa-dev.ts +13 -8
  648. package/src/cli/pwa-registry.ts +6 -0
  649. package/src/cli/pwa-share.ts +65 -22
  650. package/src/cli/pwa-show.ts +20 -4
  651. package/src/cli/pwa-start.ts +102 -27
  652. package/src/cli/pwa-test.ts +201 -96
  653. package/src/cli/release-cli.ts +177 -7
  654. package/src/cli/remotes-cli.ts +20 -1
  655. package/src/cli/remotes.ts +2 -1
  656. package/src/cli/repo-cli.ts +315 -36
  657. package/src/cli/research-cli.ts +66 -0
  658. package/src/cli/role-cli.ts +320 -0
  659. package/src/cli/schedule-cli.ts +246 -0
  660. package/src/cli/self-update.ts +103 -12
  661. package/src/cli/setup-cli.ts +64 -2
  662. package/src/cli/shadow-cli.ts +188 -0
  663. package/src/cli/share-auto-mount.ts +12 -8
  664. package/src/cli/start-cli.ts +240 -0
  665. package/src/cli/stdout-flush.ts +8 -0
  666. package/src/cli/storage-cli.ts +334 -0
  667. package/src/cli/tailscale-serve.ts +34 -19
  668. package/src/cli/tasks-cli.ts +176 -0
  669. package/src/cli/test-state-dir-flag.ts +1 -1
  670. package/src/cli/usage-cli.ts +15 -4
  671. package/src/cli/where-cli.ts +22 -55
  672. package/src/code-edit/diff-render.ts +6 -32
  673. package/src/code-edit/source-delta-browser.ts +0 -1
  674. package/src/codex/models.ts +1 -1
  675. package/src/config.ts +8 -13
  676. package/src/connectors/event-ledger.ts +41 -0
  677. package/src/connectors/linear-projector.ts +88 -0
  678. package/src/connectors/linear.ts +143 -0
  679. package/src/connectors/types.ts +19 -0
  680. package/src/control-plane/lease-holder.ts +41 -0
  681. package/src/control-plane/ledger.ts +146 -0
  682. package/src/control-plane/light-member.ts +164 -0
  683. package/src/control-plane/member-tokens.ts +88 -0
  684. package/src/control-plane/member.ts +159 -0
  685. package/src/control-plane/port-lease-heartbeat.ts +101 -0
  686. package/src/control-plane/ports.ts +40 -0
  687. package/src/control-plane/primary.ts +169 -0
  688. package/src/control-plane/server.ts +216 -0
  689. package/src/dashboard/acp-boot.ts +14 -38
  690. package/src/dashboard/assistant-render-state-runtime.ts +2 -2
  691. package/src/dashboard/assistant-sample-runtime.ts +2 -2
  692. package/src/dashboard/auto-compact-runtime.ts +11 -16
  693. package/src/dashboard/browser-help-runtime.ts +2 -3
  694. package/src/dashboard/chat/acp-chat.ts +2 -5
  695. package/src/dashboard/code-edit-post-turn-runtime.ts +1 -2
  696. package/src/dashboard/compact-surface-assembly.ts +0 -14
  697. package/src/dashboard/compact-surface-dispatch.ts +1 -38
  698. package/src/dashboard/compact-surface-inventory.ts +0 -8
  699. package/src/dashboard/compact-surface-runtime.ts +0 -14
  700. package/src/dashboard/context-menu-provider-boot.ts +0 -9
  701. package/src/dashboard/context-window-runtime-boot.ts +0 -37
  702. package/src/dashboard/index.ts +331 -2562
  703. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +0 -6
  704. package/src/dashboard/input/chat-main-slash-command.ts +2 -2
  705. package/src/dashboard/input/dashboard-priority-key-route.ts +1 -43
  706. package/src/dashboard/input/mouse-modal-surface-runtime.ts +1 -5
  707. package/src/dashboard/input/mouse-wiring.ts +2 -3
  708. package/src/dashboard/input/no-provider-reply.ts +13 -0
  709. package/src/dashboard/layout-display-runtime-registration.ts +0 -10
  710. package/src/dashboard/modals/pane-multi.ts +1 -1
  711. package/src/dashboard/replay-preview.ts +1 -1
  712. package/src/dashboard/runtime/approvers.ts +0 -1
  713. package/src/dashboard/runtime/state-snapshot.ts +0 -90
  714. package/src/dashboard/scenario-runtime-boot.ts +16 -16
  715. package/src/dashboard/slash-runtime/dashboard-handlers.ts +134 -1456
  716. package/src/dashboard/slash-runtime/design-pick.ts +96 -0
  717. package/src/dashboard/slash-runtime/help-from-registry.ts +77 -0
  718. package/src/dashboard/slash-runtime/unknown-slash-reply.ts +78 -0
  719. package/src/dashboard/stale-install-check.ts +77 -0
  720. package/src/dashboard/surface-registry-wiring.ts +2 -15
  721. package/src/dashboard/turn-message-runtime.ts +0 -4
  722. package/src/dashboard/turn-preamble.ts +1 -1
  723. package/src/dashboard/turn-stream-formatter.ts +2 -2
  724. package/src/dashboard/turn-stream-runtime.ts +2 -2
  725. package/src/dashboard-pane-context-menu.ts +0 -14
  726. package/src/debug/log.ts +7 -0
  727. package/src/decide/boundary-shadow.ts +131 -0
  728. package/src/decisions/decision-ledger.ts +404 -0
  729. package/src/design/apply-direction.ts +209 -0
  730. package/src/design/css-root-tokens.ts +89 -0
  731. package/src/design/custom-system-create.ts +230 -0
  732. package/src/design/design-directions.ts +61 -41
  733. package/src/design/design-gate.ts +241 -0
  734. package/src/design/design-library.ts +57 -0
  735. package/src/design/design-previews.ts +138 -0
  736. package/src/design/design-systems.ts +61 -0
  737. package/src/design/lint-artifact-run.ts +46 -6
  738. package/src/design/lint-artifact.ts +5 -1
  739. package/src/design/open-design-client.ts +247 -0
  740. package/src/design/system-from-extract.ts +767 -0
  741. package/src/design/system-schema.ts +123 -0
  742. package/src/discord-slash-wire.ts +2 -1
  743. package/src/discord-test-runner.ts +2 -1
  744. package/src/discord-voice-wire.ts +2 -1
  745. package/src/discord.ts +1 -1
  746. package/src/dispatch/opportunistic-launcher.ts +24 -1
  747. package/src/domains/ops-status.ts +35 -2
  748. package/src/domains/outbound-alert.ts +24 -6
  749. package/src/domains/repeated-failure.ts +89 -0
  750. package/src/domains/schedule-manage-tool.ts +28 -8
  751. package/src/domains/schedule-migrate.ts +22 -4
  752. package/src/domains/schedule-registry.ts +88 -33
  753. package/src/domains/schedule-runs.ts +132 -0
  754. package/src/domains/schedule-state.ts +152 -0
  755. package/src/domains/telegram-kind-route.ts +21 -0
  756. package/src/element-registry/address.ts +1 -3
  757. package/src/execution-loop/dispatch-task.ts +139 -0
  758. package/src/execution-loop/gate-decision-summary.ts +29 -0
  759. package/src/execution-loop/gates.ts +197 -0
  760. package/src/git-fs/gh-cli.ts +47 -17
  761. package/src/git-fs/retry.ts +1 -0
  762. package/src/git-fs/runner.ts +1 -0
  763. package/src/git-fs/worktree.ts +6 -5
  764. package/src/github/pr-labels.ts +68 -0
  765. package/src/graph-kinds/installed-plugin-nodes.ts +95 -0
  766. package/src/graph-kinds/plugin-nodes.ts +68 -0
  767. package/src/graph-kinds/registry.ts +118 -0
  768. package/src/graph-runner/graph-cli.ts +103 -0
  769. package/src/graph-runner/graph-notify.ts +220 -0
  770. package/src/graph-runner/graph-tick.ts +119 -0
  771. package/src/graph-runner/release-manifest.ts +93 -0
  772. package/src/graph-runner/runner.ts +487 -0
  773. package/src/grok/credential.ts +158 -5
  774. package/src/grounding/ensure-grounding.ts +131 -0
  775. package/src/grounding/mirror-export.ts +89 -0
  776. package/src/grounding/mirror-manifest.ts +252 -0
  777. package/src/grounding/sources-cli.ts +209 -0
  778. package/src/grounding/sources.ts +333 -0
  779. package/src/grounding/token.ts +121 -0
  780. package/src/harness/harness-cli-command.ts +415 -23
  781. package/src/harness/harness-pod-dispatch.ts +116 -0
  782. package/src/harness/harness-stop.ts +260 -0
  783. package/src/harness/harness-substrate-default.ts +40 -0
  784. package/src/harness/harness-worktrees.ts +1 -1
  785. package/src/harness/harness-write-boundary.ts +2 -0
  786. package/src/harness/llm-decompose.ts +2 -1
  787. package/src/harness/self-send-decide.ts +233 -0
  788. package/src/harness/self-send-target.ts +22 -1
  789. package/src/harness/shell-relay.ts +5 -0
  790. package/src/harness/worktree-branch-prefix.ts +4 -3
  791. package/src/hooks/providers.ts +77 -0
  792. package/src/hooks/queue.ts +73 -0
  793. package/src/hooks/receiver.ts +133 -0
  794. package/src/index.ts +712 -3409
  795. package/src/input-core/dispatcher.ts +1 -1
  796. package/src/input-core/drag-esc-interceptor.ts +1 -1
  797. package/src/instance/current.ts +5 -5
  798. package/src/instance/leader.ts +10 -326
  799. package/src/instance/nexus-run-refusal.ts +27 -92
  800. package/src/instance/project-local-exclude.ts +27 -0
  801. package/src/instance/resolve.ts +46 -175
  802. package/src/intake-plane/capture.ts +14 -1
  803. package/src/intake-plane/check.ts +34 -14
  804. package/src/intake-plane/collect-github.ts +258 -0
  805. package/src/intake-plane/collect-pod.ts +100 -0
  806. package/src/intake-plane/collect-telegram-saved.ts +91 -0
  807. package/src/intake-plane/digest.ts +111 -0
  808. package/src/intake-plane/enrich-plugins.ts +1 -1
  809. package/src/intake-plane/front-classifier.ts +56 -0
  810. package/src/intake-plane/front-route-classifier.ts +80 -0
  811. package/src/intake-plane/front-route-rules.ts +152 -0
  812. package/src/intake-plane/grounding-docs.ts +185 -0
  813. package/src/intake-plane/harness-target.ts +20 -0
  814. package/src/intake-plane/intake-to-tasks.ts +303 -0
  815. package/src/intake-plane/items.ts +247 -0
  816. package/src/intake-plane/link-ledger.ts +27 -0
  817. package/src/intake-plane/route.ts +104 -0
  818. package/src/intake-plane/runtime-callables.ts +3 -1
  819. package/src/intake-plane/sketch-ledger.ts +34 -0
  820. package/src/intake-plane/slash.ts +30 -2
  821. package/src/intake-plane/submit-intake-work.ts +160 -0
  822. package/src/intake-plane/telegram-work.ts +56 -0
  823. package/src/iul/sidebar-shell.ts +0 -165
  824. package/src/launch-head/capability-check.ts +162 -0
  825. package/src/launch-head/launch-head-cli.ts +242 -0
  826. package/src/launch-head/load-balance.ts +81 -0
  827. package/src/live/detail-switch.ts +180 -0
  828. package/src/llm/provider-detect.ts +247 -0
  829. package/src/llm/provider-probe.ts +57 -0
  830. package/src/llm/usable-llm.ts +32 -0
  831. package/src/llm.ts +55 -23
  832. package/src/log-entry.ts +1 -1
  833. package/src/log-pane/attachment-popup.ts +1 -2
  834. package/src/loops/loop-cli.ts +37 -0
  835. package/src/loops/registry.ts +196 -0
  836. package/src/market/official-keys.ts +5 -0
  837. package/src/market/publish.ts +329 -0
  838. package/src/market/signed-index.ts +156 -0
  839. package/src/market/tgz.ts +121 -0
  840. package/src/mcp/client.ts +1 -1
  841. package/src/mcp/mcp-oauth.ts +40 -5
  842. package/src/mcp/server.ts +75 -7
  843. package/src/mcp-gateway/gateway.ts +128 -0
  844. package/src/mcp-gateway/pat-store.ts +124 -0
  845. package/src/mss/logging/log-store.ts +91 -2
  846. package/src/mss/logging/scoped-level.ts +5 -9
  847. package/src/native-tool-catalog.ts +66 -345
  848. package/src/nexus/api/connect-info.ts +23 -25
  849. package/src/nexus/api/context-url.ts +1 -1
  850. package/src/nexus/api/design-check.ts +90 -59
  851. package/src/nexus/api/design-previews-route.ts +182 -0
  852. package/src/nexus/api/design-system-create-route.ts +123 -0
  853. package/src/nexus/api/graph-approvals.ts +125 -0
  854. package/src/nexus/api/graph-kinds.ts +69 -0
  855. package/src/nexus/api/graphs-api.ts +221 -0
  856. package/src/nexus/api/harness-api.ts +31 -2
  857. package/src/nexus/api/health.ts +15 -0
  858. package/src/nexus/api/http-server.ts +328 -43
  859. package/src/nexus/api/image-generate.ts +3 -0
  860. package/src/nexus/api/ingest-token.ts +175 -0
  861. package/src/nexus/api/intake-ledger-api.ts +54 -0
  862. package/src/nexus/api/intake-route.ts +111 -0
  863. package/src/nexus/api/json-response.ts +33 -0
  864. package/src/nexus/api/live-detail.ts +47 -0
  865. package/src/nexus/api/live-shipped.ts +78 -0
  866. package/src/nexus/api/log-fabric.ts +42 -2
  867. package/src/nexus/api/markdown-publish.ts +3 -2
  868. package/src/nexus/api/mcp-http.ts +14 -9
  869. package/src/nexus/api/mcp-oauth-hint.ts +31 -0
  870. package/src/nexus/api/mcp-public-allowlist.ts +33 -0
  871. package/src/nexus/api/merge-approvals-gate.ts +79 -0
  872. package/src/nexus/api/merge-approvals.ts +307 -0
  873. package/src/nexus/api/meta-api.ts +18 -0
  874. package/src/nexus/api/next-fluent-wiring.ts +7 -9
  875. package/src/nexus/api/plugins-credentials-api.ts +47 -0
  876. package/src/nexus/api/plugins-market.ts +209 -0
  877. package/src/nexus/api/pod-credential-api.ts +187 -0
  878. package/src/nexus/api/public-routes.ts +87 -0
  879. package/src/nexus/api/rest-route-paths.ts +15 -0
  880. package/src/nexus/api/schedules-action.ts +12 -3
  881. package/src/nexus/api/schedules-read.ts +228 -0
  882. package/src/nexus/api/sessions-store.ts +8 -2
  883. package/src/nexus/api/setup-answer-priority.ts +130 -0
  884. package/src/nexus/api/setup-channel-bot.ts +56 -0
  885. package/src/nexus/api/setup-child-llm.ts +228 -0
  886. package/src/nexus/api/setup-obsidian-skills.ts +93 -0
  887. package/src/nexus/api/task-cards-api.ts +34 -0
  888. package/src/nexus/api/tasks-create.ts +136 -0
  889. package/src/nexus/api/telegram-trigger-bot.ts +3 -3
  890. package/src/nexus/api/terminals.ts +204 -18
  891. package/src/nexus/api/trace.ts +405 -0
  892. package/src/nexus/api/vault-api.ts +140 -7
  893. package/src/nexus/api/worktrees.ts +18 -2
  894. package/src/nexus/boot/register-mcp-clients.ts +135 -16
  895. package/src/nexus/daemon-endpoint.ts +85 -0
  896. package/src/nexus/default-port.ts +1 -0
  897. package/src/nexus/index.ts +362 -143
  898. package/src/nexus/onboarding/pwa-share-prompt.ts +31 -8
  899. package/src/nexus/onboarding/tailscale-probe.ts +9 -1
  900. package/src/nexus/outbound/router.ts +1 -1
  901. package/src/nexus/setup-status.ts +58 -0
  902. package/src/nexus/supervisor/lock.ts +8 -0
  903. package/src/nexus/webterm/pty.ts +15 -0
  904. package/src/oauth/codex-account-rotation.ts +122 -16
  905. package/src/oauth/codex-account-store.ts +88 -19
  906. package/src/oauth/codex-quota-policy.ts +55 -0
  907. package/src/oauth/store.ts +28 -25
  908. package/src/obsidian/default-vault.ts +17 -0
  909. package/src/obsidian/vault-write-guard.ts +46 -0
  910. package/src/onboarding/help/llm.md +2 -2
  911. package/src/onboarding.ts +27 -4
  912. package/src/panes/alt-skip-predicate.ts +4 -3
  913. package/src/panes/external-terminal-pane.ts +3 -4
  914. package/src/panes/factory.ts +1 -18
  915. package/src/panes/index.ts +1 -5
  916. package/src/panes/pane-cycle.ts +1 -1
  917. package/src/panes/types.ts +1 -1
  918. package/src/platform/env-literal.ts +4 -0
  919. package/src/plugin-hooks/dispatcher.ts +10 -4
  920. package/src/plugins/core/host.ts +108 -4
  921. package/src/plugins/core/manifest.ts +104 -7
  922. package/src/plugins/install/market-fetch.ts +250 -0
  923. package/src/plugins/install/plugin-credentials.ts +106 -0
  924. package/src/plugins/install/plugin-install.ts +518 -0
  925. package/src/policy/claude-subscription-guard.ts +25 -0
  926. package/src/preview/terminal.ts +24 -1
  927. package/src/preview-pane/mount.ts +1 -142
  928. package/src/prompt/references.ts +4 -51
  929. package/src/prompt-library/universal-preamble.ts +8 -2
  930. package/src/pty-shell/pty-control-ipc.ts +57 -3
  931. package/src/pty-shell/pty-mouse.ts +75 -0
  932. package/src/pty-shell/pty-recording.ts +108 -0
  933. package/src/pty-shell/registry.ts +53 -3
  934. package/src/python/resolve-python.ts +1 -1
  935. package/src/release-loop/checklist.ts +191 -0
  936. package/src/release-loop/manifest.ts +65 -0
  937. package/src/release-loop/release-note.ts +177 -0
  938. package/src/roles/lease-cas.ts +52 -0
  939. package/src/roles/machine-name.ts +48 -0
  940. package/src/roles/machine-profile.ts +65 -0
  941. package/src/roles/role-lease-read.ts +81 -0
  942. package/src/roles/role-lease.ts +63 -0
  943. package/src/roles/role-watch.ts +69 -0
  944. package/src/self-dev/ask-launch-flow.ts +39 -22
  945. package/src/self-dev/ask-launch-io.ts +1 -1
  946. package/src/self-dev/dev-cli.ts +290 -159
  947. package/src/self-dev/dev-pipeline.ts +157 -9
  948. package/src/self-dev/draft-sweep.ts +231 -0
  949. package/src/self-dev/draft-triage-rules.ts +42 -0
  950. package/src/self-dev/entrance-baseline.ts +156 -4
  951. package/src/self-dev/fabric-decompose-adapter.ts +10 -0
  952. package/src/self-dev/launch-preflight.ts +1 -1
  953. package/src/self-dev/orchestrate.ts +297 -20
  954. package/src/self-dev/repair-signals.ts +6 -0
  955. package/src/self-dev/run-store.ts +20 -5
  956. package/src/self-dev/run-supervisor.ts +43 -3
  957. package/src/self-implement/abandoned-classification.ts +15 -1
  958. package/src/self-implement/blocked-draft-policy.ts +6 -0
  959. package/src/self-implement/budget-gate.ts +236 -0
  960. package/src/self-implement/child-llm-preference.ts +84 -0
  961. package/src/self-implement/decision-events.ts +57 -0
  962. package/src/self-implement/decision-signal-press.ts +5 -2
  963. package/src/self-implement/dependency-change-gate.ts +90 -0
  964. package/src/self-implement/gate-baseline.ts +35 -2
  965. package/src/self-implement/gate-cli.ts +29 -7
  966. package/src/self-implement/gate-scope.ts +7 -1
  967. package/src/self-implement/goal-author-decompose.ts +22 -4
  968. package/src/self-implement/goal-author.ts +41 -3
  969. package/src/self-implement/goal-boundary.ts +65 -0
  970. package/src/self-implement/goal-clarification-escalation.ts +1 -0
  971. package/src/self-implement/goal-documents-dir.ts +6 -1
  972. package/src/self-implement/goal-execution-records.ts +58 -0
  973. package/src/self-implement/goal-run-store.ts +42 -24
  974. package/src/self-implement/graph-authority.ts +13 -28
  975. package/src/self-implement/graph-catalog.ts +48 -0
  976. package/src/self-implement/graph-run-contract.ts +127 -0
  977. package/src/self-implement/graph-templates.ts +14 -7
  978. package/src/self-implement/graph-yaml.ts +35 -6
  979. package/src/self-implement/harness-policy-gates.ts +42 -0
  980. package/src/self-implement/headless-elanous-driver.ts +30 -6
  981. package/src/self-implement/heal-triage.ts +229 -0
  982. package/src/self-implement/host-regate.ts +244 -0
  983. package/src/self-implement/non-git-consent.ts +23 -0
  984. package/src/self-implement/orchestrator.ts +488 -134
  985. package/src/self-implement/pipeline-shape.ts +1 -1
  986. package/src/self-implement/pr-evidence-artifact.ts +6 -19
  987. package/src/self-implement/prior-draft-findings.ts +128 -0
  988. package/src/self-implement/pwa-import-graph.ts +65 -0
  989. package/src/self-implement/repo-provision.ts +18 -21
  990. package/src/self-implement/report-origin.ts +39 -0
  991. package/src/self-implement/rework-policy.ts +21 -0
  992. package/src/self-implement/run-ledger-compact.ts +438 -0
  993. package/src/self-implement/run-ledger.ts +212 -29
  994. package/src/self-implement/run-report.ts +24 -0
  995. package/src/self-implement/run-status-mapping.ts +2 -0
  996. package/src/self-implement/running-runs.ts +112 -14
  997. package/src/self-implement/scoped-typecheck-config.ts +49 -0
  998. package/src/self-implement/seams.ts +207 -40
  999. package/src/self-implement/self-implement-cli.ts +17 -2
  1000. package/src/self-implement/shadow-repo.ts +350 -0
  1001. package/src/self-implement/supervision-vocabulary.ts +7 -0
  1002. package/src/shell-runner/dispatch.ts +3 -0
  1003. package/src/shell-runner/index.ts +0 -7
  1004. package/src/skills/runner.ts +0 -69
  1005. package/src/skills/tools/agent-room-slash.ts +2 -1
  1006. package/src/skills/tools/agent-room.ts +8 -140
  1007. package/src/skills/tools/agent.ts +5 -3
  1008. package/src/skills/tools/context.ts +5 -140
  1009. package/src/skills/tools/control.ts +4 -188
  1010. package/src/skills/tools/dashboard-slash.ts +3 -11
  1011. package/src/skills/tools/dashboard-state.ts +3 -5
  1012. package/src/skills/tools/dev-harness.ts +45 -2
  1013. package/src/skills/tools/omni-search.ts +29 -1
  1014. package/src/skills/tools/shell.ts +11 -29
  1015. package/src/skills/tools/spawn-coding-agent-headless.ts +6 -9
  1016. package/src/ssh/ssh-picker-modal.ts +1 -1
  1017. package/src/steward/directive.ts +99 -0
  1018. package/src/steward/steward-cards.ts +45 -0
  1019. package/src/steward/triage.ts +239 -0
  1020. package/src/storage/cli-bin.ts +67 -0
  1021. package/src/storage/object-store-visibility.ts +169 -0
  1022. package/src/storage/object-store.ts +452 -0
  1023. package/src/storage/s3.ts +53 -10
  1024. package/src/storage/storage-detect.ts +337 -0
  1025. package/src/surface/address.ts +3 -5
  1026. package/src/surface/index.ts +0 -6
  1027. package/src/surface/llm-tools.ts +1 -2
  1028. package/src/surface/shell-runner-boot.ts +4 -89
  1029. package/src/task-cards/card-cli.ts +64 -0
  1030. package/src/task-cards/card-store.ts +241 -0
  1031. package/src/task-orchestrator/boot.ts +27 -1
  1032. package/src/task-orchestrator/dispatcher.ts +49 -7
  1033. package/src/task-orchestrator/external-fingerprint.ts +10 -0
  1034. package/src/task-orchestrator/external-policy.ts +86 -0
  1035. package/src/task-orchestrator/feedback-loop.ts +4 -2
  1036. package/src/task-orchestrator/graph.ts +18 -1
  1037. package/src/task-orchestrator/runtimes/create.ts +128 -0
  1038. package/src/task-orchestrator/store.ts +78 -18
  1039. package/src/task-orchestrator/surface-registry.ts +5 -2
  1040. package/src/task-orchestrator/surfaces/external-exec.ts +180 -0
  1041. package/src/task-orchestrator/surfaces/idea-approval-pr.ts +118 -0
  1042. package/src/task-orchestrator/surfaces/index.ts +4 -3
  1043. package/src/task-orchestrator/surfaces/pod-account-broker.ts +60 -5
  1044. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +194 -0
  1045. package/src/task-orchestrator/surfaces/pod-command-job.ts +369 -0
  1046. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +207 -0
  1047. package/src/task-orchestrator/surfaces/pod-pool.ts +128 -12
  1048. package/src/task-orchestrator/surfaces/pod-skills.ts +11 -3
  1049. package/src/task-orchestrator/surfaces/pod-source-bundle.ts +147 -0
  1050. package/src/task-orchestrator/surfaces/pod-source-receive.ts +129 -0
  1051. package/src/task-orchestrator/surfaces/pod-source-spec.ts +77 -0
  1052. package/src/task-orchestrator/surfaces/self-implement-pod.ts +930 -45
  1053. package/src/task-orchestrator/surfaces/self-implement.ts +8 -1
  1054. package/src/task-orchestrator/tox-loop.ts +204 -0
  1055. package/src/task-orchestrator/types.ts +21 -1
  1056. package/src/telegram-commands.ts +8 -0
  1057. package/src/telegram-report.ts +14 -7
  1058. package/src/telegram-run.ts +18 -5
  1059. package/src/telegram.ts +92 -22
  1060. package/src/tool-runtime/acp-session-runtime.ts +28 -7
  1061. package/src/tool-runtime/agent-runtime.ts +1 -0
  1062. package/src/tool-runtime/context-runtime.ts +18 -35
  1063. package/src/tool-runtime/control-runtime.ts +8 -21
  1064. package/src/tool-runtime/dashboard-state-runtime.ts +1 -5
  1065. package/src/tool-runtime/elanous-asana-runtimes.ts +205 -0
  1066. package/src/tool-runtime/elanous-control-runtimes.ts +16 -2
  1067. package/src/tool-runtime/elanous-task-submit-runtime.ts +124 -0
  1068. package/src/tool-runtime/index.ts +4 -1
  1069. package/src/tool-runtime/scenario-runtimes.ts +22 -21
  1070. package/src/tool-runtime/scenario-target-mount.ts +6 -32
  1071. package/src/tool-runtime/types.ts +8 -0
  1072. package/src/tui/chat/attachment-summary.ts +4 -4
  1073. package/src/tui-client/acp-transport-ws-client.ts +72 -5
  1074. package/src/tui-client/headless-core-guard.ts +0 -1
  1075. package/src/tui.ts +11 -7
  1076. package/src/typecheck-ratchet.ts +15 -0
  1077. package/src/ui/hover-presenter.ts +3 -7
  1078. package/src/user-config.ts +453 -190
  1079. package/src/util/spawn-sync-output.ts +15 -0
  1080. package/src/version/code-revision.ts +34 -9
  1081. package/src/version/packed-revision.json +1 -1
  1082. package/src/video-pipeline/broll-agent.ts +102 -0
  1083. package/src/video-pipeline/recipes/broll.ts +263 -0
  1084. package/src/video-pipeline/walk-line.ts +2 -1
  1085. package/src/views/scratch-image-size.ts +10 -0
  1086. package/src/voice/channel-adapters/pwa-voice-adapter.ts +2 -18
  1087. package/src/voice/channel-adapters/telegram-voice-adapter.ts +1 -6
  1088. package/src/voice/voice-tts-singleton.ts +46 -8
  1089. package/src/web-push/vapid-keys.ts +1 -1
  1090. package/src/web-search/free.ts +77 -0
  1091. package/src/web-search/index.ts +7 -5
  1092. package/src/web-terminal/preview-tap-registry.ts +152 -43
  1093. package/src/workflow-runtime/deps-bridge.ts +4 -3
  1094. package/src/workflow-runtime/executor.ts +18 -22
  1095. package/src/workflow-runtime/node-catalog.ts +20 -1
  1096. package/src/workflow-runtime/nodes/bash.ts +1 -0
  1097. package/src/workflow-runtime/nodes/task.ts +74 -0
  1098. package/src/workflow-runtime/nodes/triggers.ts +24 -1
  1099. package/src/workflow-runtime/plugin-kind-node.ts +166 -0
  1100. package/src/workflow-runtime/schema.ts +98 -2
  1101. package/src/workflow-runtime/triggers/webhook-router.ts +43 -3
  1102. package/src/workflow-runtime/triggers/webhook-source.ts +19 -1
  1103. package/src/workflow-runtime/types.ts +76 -5
  1104. package/apps/pwa/out/_next/static/Ksn99fVf2HUWhSyV1-FC8/_buildManifest.js +0 -1
  1105. package/apps/pwa/out/_next/static/chunks/1176-4943bd83b00e53a2.js +0 -25
  1106. package/apps/pwa/out/_next/static/chunks/1380-9c652e1002032c86.js +0 -1
  1107. package/apps/pwa/out/_next/static/chunks/1863-2ea170dfec26b88b.js +0 -1
  1108. package/apps/pwa/out/_next/static/chunks/2091-2d6b7f4f16300f83.js +0 -1
  1109. package/apps/pwa/out/_next/static/chunks/2347-366617ec73babe3b.js +0 -1
  1110. package/apps/pwa/out/_next/static/chunks/3089-e60cc8f5d35ee239.js +0 -1
  1111. package/apps/pwa/out/_next/static/chunks/3158-c77ed9ea34f9cc9f.js +0 -1
  1112. package/apps/pwa/out/_next/static/chunks/3607-f0b5c5ee18fcf56a.js +0 -1
  1113. package/apps/pwa/out/_next/static/chunks/3659-05b2d5d971b42dbc.js +0 -1
  1114. package/apps/pwa/out/_next/static/chunks/3736-b6a7bfdcb8f56ec6.js +0 -1
  1115. package/apps/pwa/out/_next/static/chunks/3839-eebf298e89a7bb77.js +0 -1
  1116. package/apps/pwa/out/_next/static/chunks/4012.832a2824b978e7ee.js +0 -5
  1117. package/apps/pwa/out/_next/static/chunks/4706-d85d7f3345f3ff91.js +0 -1
  1118. package/apps/pwa/out/_next/static/chunks/526-17a6a2e0e6dc4498.js +0 -1
  1119. package/apps/pwa/out/_next/static/chunks/5508-676ac75f2757ad40.js +0 -1
  1120. package/apps/pwa/out/_next/static/chunks/5583-8a0317f4b8e68db9.js +0 -1
  1121. package/apps/pwa/out/_next/static/chunks/6258-b58f722b10e8d31d.js +0 -1
  1122. package/apps/pwa/out/_next/static/chunks/6820-32fd097e6186fdc9.js +0 -1
  1123. package/apps/pwa/out/_next/static/chunks/6852-983db7ca958634b7.js +0 -1
  1124. package/apps/pwa/out/_next/static/chunks/7235-e583e4a015e159b9.js +0 -1
  1125. package/apps/pwa/out/_next/static/chunks/7482-7b417330b24a996a.js +0 -1
  1126. package/apps/pwa/out/_next/static/chunks/7701-99b7d4dedb955bf8.js +0 -1
  1127. package/apps/pwa/out/_next/static/chunks/77f1928d-bd3777589042d3ea.js +0 -1
  1128. package/apps/pwa/out/_next/static/chunks/8366-36956cafc5e33614.js +0 -1
  1129. package/apps/pwa/out/_next/static/chunks/8370-23d0de995be666f8.js +0 -1
  1130. package/apps/pwa/out/_next/static/chunks/8617-307421f3b0e8b2a2.js +0 -1
  1131. package/apps/pwa/out/_next/static/chunks/8837-e45de46a9fedf1f5.js +0 -1
  1132. package/apps/pwa/out/_next/static/chunks/9058-0e8055a5ea3ebdd6.js +0 -1
  1133. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-84b84eca12acada4.js +0 -1
  1134. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-1f23568c29e88f7a.js +0 -1
  1135. package/apps/pwa/out/_next/static/chunks/app/botlab/page-bf6fc9aafd6135a7.js +0 -1
  1136. package/apps/pwa/out/_next/static/chunks/app/bots/page-3f8539ae4b719d2e.js +0 -1
  1137. package/apps/pwa/out/_next/static/chunks/app/chat/page-d2900febb74ecf32.js +0 -1
  1138. package/apps/pwa/out/_next/static/chunks/app/control/page-e82dec647dd79c36.js +0 -1
  1139. package/apps/pwa/out/_next/static/chunks/app/dashboard/page-096ec743a8ee955a.js +0 -1
  1140. package/apps/pwa/out/_next/static/chunks/app/design-check/page-255c2ceded4b3493.js +0 -1
  1141. package/apps/pwa/out/_next/static/chunks/app/healthz/route-84b84eca12acada4.js +0 -1
  1142. package/apps/pwa/out/_next/static/chunks/app/intake/page-2db61b2f9efba61f.js +0 -1
  1143. package/apps/pwa/out/_next/static/chunks/app/layout-e11ee17f221aaa9b.js +0 -1
  1144. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e075974e029ce4c4.js +0 -1
  1145. package/apps/pwa/out/_next/static/chunks/app/morning/page-ec5b68a9af3366a0.js +0 -1
  1146. package/apps/pwa/out/_next/static/chunks/app/not-found-986c177afb4adae6.js +0 -1
  1147. package/apps/pwa/out/_next/static/chunks/app/observatory/page-a72781461af2f2a3.js +0 -1
  1148. package/apps/pwa/out/_next/static/chunks/app/page-92781cbaafc487ad.js +0 -1
  1149. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2c14d2a1f2930f33.js +0 -1
  1150. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-22ee4bf8070b2b4d.js +0 -1
  1151. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9c06e4a8297942a8.js +0 -1
  1152. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d0cd32f6d373798f.js +0 -1
  1153. package/apps/pwa/out/_next/static/chunks/app/settings/page-0c1642018d87ebb8.js +0 -1
  1154. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-93e5e97d614df487.js +0 -1
  1155. package/apps/pwa/out/_next/static/chunks/app/setup/layout-84b84eca12acada4.js +0 -1
  1156. package/apps/pwa/out/_next/static/chunks/app/setup/page-b1ce871940d7393e.js +0 -1
  1157. package/apps/pwa/out/_next/static/chunks/app/share/page-ae154addf345febe.js +0 -1
  1158. package/apps/pwa/out/_next/static/chunks/app/showroom/page-90af3aa813d2053c.js +0 -1
  1159. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f3f962fda428a738.js +0 -1
  1160. package/apps/pwa/out/_next/static/chunks/app/term/page-1c1f7cc1d5def06d.js +0 -1
  1161. package/apps/pwa/out/_next/static/chunks/app/vault/page-09d4cbdaaacf06c1.js +0 -1
  1162. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e877b8e8ca90b27f.js +0 -1
  1163. package/apps/pwa/out/_next/static/chunks/app/workflows/page-71d902f463dea526.js +0 -1
  1164. package/apps/pwa/out/_next/static/chunks/app/workspace/page-40ea576cefa25fe6.js +0 -1
  1165. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a56a3f178c3831f6.js +0 -1
  1166. package/apps/pwa/out/_next/static/chunks/bcc499d1-804a270d878e0842.js +0 -1
  1167. package/apps/pwa/out/_next/static/chunks/framework-b25b7c5501c59b6d.js +0 -1
  1168. package/apps/pwa/out/_next/static/chunks/main-a9ec9da43387afff.js +0 -1
  1169. package/apps/pwa/out/_next/static/chunks/main-app-aa2c05954aaa6754.js +0 -1
  1170. package/apps/pwa/out/_next/static/chunks/pages/_app-bb3768fb4b84aebb.js +0 -1
  1171. package/apps/pwa/out/_next/static/chunks/pages/_error-2820ba75b87b2f5e.js +0 -1
  1172. package/apps/pwa/out/_next/static/chunks/webpack-58c73b145f189b1c.js +0 -1
  1173. package/apps/pwa/out/_next/static/css/effec8adf767aa75.css +0 -1
  1174. package/apps/pwa/out/dashboard/index.html +0 -1
  1175. package/apps/pwa/out/dashboard/index.txt +0 -26
  1176. package/src/acp/resident-shell.ts +0 -244
  1177. package/src/agent/spawn-local-llm-in-vw.ts +0 -240
  1178. package/src/dashboard/agent-spawn-tools-boot.ts +0 -14
  1179. package/src/dashboard/dock-picker-inventory.ts +0 -41
  1180. package/src/dashboard/goal-plan-hud-bridge.ts +0 -112
  1181. package/src/dashboard/hud-mirror.ts +0 -207
  1182. package/src/dashboard/input/mouse-dock-runtime.ts +0 -156
  1183. package/src/dashboard/input/mouse-hover-runtime.ts +0 -46
  1184. package/src/dashboard/input/mouse-pill-context-runtime.ts +0 -74
  1185. package/src/dashboard/input/mouse-workspace-restore-runtime.ts +0 -64
  1186. package/src/dashboard/input/scratch-actions.ts +0 -36
  1187. package/src/dashboard/input/virtual-window-key-router.ts +0 -24
  1188. package/src/dashboard/rich-scratch-viewers.ts +0 -77
  1189. package/src/dashboard/scratch-slash-runtime.ts +0 -36
  1190. package/src/dashboard/scratch-state-runtime.ts +0 -42
  1191. package/src/dashboard/scratch-widget-runtime.ts +0 -37
  1192. package/src/dashboard/sim-shell.ts +0 -313
  1193. package/src/dashboard/virtual-window-control-runtime.ts +0 -57
  1194. package/src/dashboard/virtual-window-help-runtime.ts +0 -113
  1195. package/src/dashboard/virtual-window-input-runtime.ts +0 -99
  1196. package/src/dashboard/virtual-window-mutation-runtime.ts +0 -102
  1197. package/src/dashboard/virtual-window-split-runtime.ts +0 -70
  1198. package/src/dashboard/vw-popup-openers.ts +0 -126
  1199. package/src/dashboard/window-picker-popup.ts +0 -74
  1200. package/src/dashboard/window-slash-runtime.ts +0 -108
  1201. package/src/dashboard/windowing/companion-slash.ts +0 -78
  1202. package/src/dashboard/windowing/fast-switch.ts +0 -138
  1203. package/src/dashboard/windowing/lifecycle.ts +0 -185
  1204. package/src/dashboard/windowing/virtual-windows.ts +0 -259
  1205. package/src/dashboard/windowing/visibility-chord.ts +0 -77
  1206. package/src/iul/resident-vw.ts +0 -55
  1207. package/src/panes/content-adapter.ts +0 -162
  1208. package/src/prompt/vw-reference.ts +0 -153
  1209. package/src/shell-runner/external-terminal-pane.ts +0 -157
  1210. package/src/sim/resident-vw.ts +0 -48
  1211. package/src/skills/tools/spawn-coding-agent-vw.ts +0 -181
  1212. package/src/skills/tools/virtual-windows.ts +0 -632
  1213. package/src/surface/adapters/window-surface-adapter.ts +0 -141
  1214. package/src/tool-runtime/layout-runtimes.ts +0 -81
  1215. package/src/tool-runtime/scenario-window-mount.ts +0 -207
  1216. package/src/views/ui-mode.ts +0 -100
  1217. package/src/virtual-window-context-menu.ts +0 -97
  1218. package/src/virtual-windows/addressing.ts +0 -195
  1219. package/src/virtual-windows/benchmark-preset.ts +0 -119
  1220. package/src/virtual-windows/event-bus.ts +0 -202
  1221. package/src/virtual-windows/layout/apply-planner.ts +0 -189
  1222. package/src/virtual-windows/layout/index.ts +0 -68
  1223. package/src/virtual-windows/layout/layout-commands.ts +0 -186
  1224. package/src/virtual-windows/layout/layout-tools.ts +0 -262
  1225. package/src/virtual-windows/layout/persistence.ts +0 -219
  1226. package/src/virtual-windows/layout/presets.ts +0 -114
  1227. package/src/virtual-windows/layout/restore-planner.ts +0 -223
  1228. package/src/virtual-windows/layout/serializer.ts +0 -197
  1229. package/src/virtual-windows/layout/tree.ts +0 -147
  1230. package/src/virtual-windows/layout/types.ts +0 -63
  1231. package/src/virtual-windows/layout-tree.ts +0 -389
  1232. package/src/virtual-windows/navigation.ts +0 -251
  1233. package/src/virtual-windows/pane-capture.ts +0 -142
  1234. package/src/virtual-windows/pane-content.ts +0 -611
  1235. package/src/virtual-windows/pane-spawner.ts +0 -278
  1236. package/src/virtual-windows/pty-tail-content.ts +0 -291
  1237. package/src/virtual-windows/resident-window.ts +0 -59
  1238. package/src/virtual-windows/secondary-action.ts +0 -25
  1239. package/src/virtual-windows/terminal-slot-content.ts +0 -165
  1240. package/src/virtual-windows/virtual-window.ts +0 -1301
  1241. package/src/virtual-windows/vw-local-input-target-popup.ts +0 -110
  1242. package/src/virtual-windows/vw-rename-modal.ts +0 -77
  1243. package/src/virtual-windows/vw-selector-popup.ts +0 -177
  1244. package/src/virtual-windows/window-registry.ts +0 -519
  1245. package/src/voice/channel-adapters/discord-voice-adapter.ts +0 -202
  1246. package/src/voice/voice-pwa-dispatch.ts +0 -245
  1247. package/src/window-picker-modal.ts +0 -135
  1248. /package/apps/pwa/out/_next/static/{Ksn99fVf2HUWhSyV1-FC8 → ktMqfrBbf8BMGac0jqLrb}/_ssgManifest.js +0 -0
  1249. /package/src/dashboard/{companion-slash-runtime.ts → companion-messages-runtime.ts} +0 -0
@@ -58,6 +58,10 @@ export interface DistroRemedies {
58
58
  node?: string;
59
59
  /** node 가 준비된 뒤 codex CLI 설치 한 줄. */
60
60
  codex?: string;
61
+ /** jq 설치 한 줄(없는 계열에는 추측하지 않는다). */
62
+ jq?: string;
63
+ /** ffmpeg 설치 한 줄(기본 저장소에 없는 계열에는 두지 않는다). */
64
+ ffmpeg?: string;
61
65
  /** 계열별 주의 한 줄(없으면 생략). */
62
66
  note?: string;
63
67
  }
@@ -68,6 +72,8 @@ export const DISTRO_REMEDIES: Readonly<Record<Exclude<DistroFamily, 'unknown'>,
68
72
  buildToolchain: 'xcode-select --install',
69
73
  pythonBuildDeps: 'brew install openssl readline sqlite3 xz zlib tcl-tk',
70
74
  gh: 'brew install gh',
75
+ jq: 'brew install jq',
76
+ ffmpeg: 'brew install ffmpeg',
71
77
  rg: 'brew install ripgrep',
72
78
  node: 'brew install node',
73
79
  codex: 'npm install -g @openai/codex',
@@ -77,8 +83,10 @@ export const DISTRO_REMEDIES: Readonly<Record<Exclude<DistroFamily, 'unknown'>,
77
83
  pythonBuildDeps: 'sudo apt-get install -y build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev curl git libncurses-dev xz-utils tk-dev libffi-dev liblzma-dev',
78
84
  // 🩸 09-24 빈 GCP Ubuntu 24.04 실측: 목록 갱신 없이 `apt-get install -y gh` → «Unable to locate package gh».
79
85
  gh: 'sudo apt-get update && sudo apt-get install -y gh',
86
+ jq: 'sudo apt-get update && sudo apt-get install -y jq',
87
+ ffmpeg: 'sudo apt-get update && sudo apt-get install -y ffmpeg',
80
88
  rg: 'sudo apt-get update && sudo apt-get install -y ripgrep',
81
- node: 'sudo apt-get update && sudo apt-get install -y nodejs npm',
89
+ node: 'Install Node.js 20+ using the official distribution instructions at https://nodejs.org/en/download',
82
90
  codex: 'sudo npm install -g @openai/codex',
83
91
  pythonVenv: 'sudo apt-get install -y python3-venv',
84
92
  pythonBase: 'sudo apt-get update && sudo apt-get install -y python3 python3-venv',
@@ -89,6 +97,7 @@ export const DISTRO_REMEDIES: Readonly<Record<Exclude<DistroFamily, 'unknown'>,
89
97
  pythonBuildDeps: 'sudo dnf install -y gcc make patch zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel xz-devel',
90
98
  // 🩸 2026-09-25 fedora:latest 컨테이너: dnf5 는 `config-manager --add-repo` 를 모른다. gh 는 Fedora 공식 저장소에 있다.
91
99
  gh: 'sudo dnf install -y gh',
100
+ jq: 'sudo dnf install -y jq',
92
101
  rg: 'sudo dnf install -y ripgrep',
93
102
  node: 'sudo dnf install -y nodejs npm',
94
103
  codex: 'sudo npm install -g @openai/codex',
@@ -99,6 +108,7 @@ export const DISTRO_REMEDIES: Readonly<Record<Exclude<DistroFamily, 'unknown'>,
99
108
  buildToolchain: 'sudo dnf install -y gcc-c++ make',
100
109
  pythonBuildDeps: 'sudo dnf install -y gcc make patch zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel xz-devel',
101
110
  gh: "sudo dnf install -y 'dnf-command(config-manager)' && sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && sudo dnf install -y gh",
111
+ jq: 'sudo dnf install -y jq',
102
112
  node: 'sudo dnf install -y nodejs npm',
103
113
  codex: 'sudo npm install -g @openai/codex',
104
114
  note: 'ripgrep is not in the AL2023 base repos — install it manually; the system python3 is 3.9 (older than the declared 3.12)',
@@ -108,6 +118,7 @@ export const DISTRO_REMEDIES: Readonly<Record<Exclude<DistroFamily, 'unknown'>,
108
118
  pythonBuildDeps: 'sudo yum install -y gcc make patch zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl11-devel tk-devel libffi-devel xz-devel',
109
119
  // 🩸 2026-09-25 amazonlinux:2 컨테이너: yum-config-manager 는 yum-utils 에 있고 기본 이미지엔 없다.
110
120
  gh: 'sudo yum install -y yum-utils && sudo yum-config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo && sudo yum install -y gh',
121
+ jq: 'sudo yum install -y jq',
111
122
  // ⛔ rg·node 줄을 두지 않는다(🅢 수확 2026-09-24): AL2 기본 저장소에 ripgrep·nodejs 가 없고, 제3자 저장소(COPR 등)를
112
123
  // `--sudo` 가 자동으로 붙이는 것은 위험하며 aarch64 에서는 실행도 안 된다(리뷰 must-fix). 이름만 대고 사람이 고른다.
113
124
  codex: 'sudo npm install -g @openai/codex',
@@ -119,3 +130,8 @@ export const DISTRO_REMEDIES: Readonly<Record<Exclude<DistroFamily, 'unknown'>,
119
130
  export function remediesFor(family: DistroFamily): DistroRemedies | undefined {
120
131
  return family === 'unknown' ? undefined : DISTRO_REMEDIES[family];
121
132
  }
133
+
134
+ /** 표에 명시된 도구 설치 줄만 돌려준다 — 모르는 계열·빈 칸은 undefined. */
135
+ export function toolInstallLine(tool: 'gh' | 'rg' | 'node' | 'codex' | 'jq' | 'ffmpeg', family: DistroFamily): string | undefined {
136
+ return remediesFor(family)?.[tool];
137
+ }
@@ -1,19 +1,90 @@
1
1
  import { nativeBuildEnv, nativeBuildShimDir } from '../native/native-build-env.js';
2
+ import { debug } from '../debug/log.js';
3
+ import type { GitInstallPlan } from './git-install-plan.js';
4
+ import { createInterface } from 'node:readline/promises';
5
+ import { getElanousConfigDir } from '../elanous-config-dir.js';
6
+ import { fixPrivateFiles, scanPrivateFiles } from './doctor-private-files.js';
2
7
  import { checkPythonEnv, runPythonSetup } from './python-cli.js';
3
- import { remediesFor } from './doctor-distro.js';
8
+ import { remediesFor, toolInstallLine } from './doctor-distro.js';
4
9
  import { installManagedPython, installStaticTool, linuxArch, staticToolBinDir, STATIC_TOOLS, type StaticToolName } from './doctor-static-tools.js';
5
10
  import { declaredPythonVersion, PYTHON_MIN_SUPPORTED } from '../python/resolve-python.js';
6
11
  import { randomUUID } from 'node:crypto';
7
- import { appendFileSync, chmodSync, closeSync, constants, existsSync, fchmodSync, fstatSync, lstatSync, mkdirSync, openSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync, writeSync } from 'node:fs';
12
+ import { appendFileSync, chmodSync, closeSync, constants, existsSync, fchmodSync, fstatSync, lstatSync, mkdirSync, mkdtempSync, openSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync, writeSync } from 'node:fs';
8
13
  import { spawnSync } from 'node:child_process';
9
- import { homedir } from 'node:os';
14
+ import { homedir, tmpdir } from 'node:os';
10
15
  import { dirname, join, resolve, win32 } from 'node:path';
11
16
  import { checkReadiness, ghVersionAtLeast, serviceSecretEntries, SERVICE_VERSION_FOLDER, type ReadinessDeps, type ReadinessItem } from './doctor-readiness.js';
12
17
 
18
+ export interface GitInstallResult {
19
+ ran: boolean;
20
+ ok: boolean;
21
+ detail: string;
22
+ }
23
+
24
+ /** Installation is never attempted without an explicit yes or an affirmative TTY answer. */
25
+ export async function applyGitInstall(plan: GitInstallPlan, deps: {
26
+ yes?: boolean;
27
+ interactive?: boolean;
28
+ confirm?: (display: string) => Promise<boolean>;
29
+ run?: (command: string, args: readonly string[]) => { status: number | null };
30
+ platform?: NodeJS.Platform;
31
+ json?: boolean;
32
+ sleep?: (ms: number) => Promise<void>;
33
+ now?: () => number;
34
+ waitForGitMs?: number;
35
+ pollMs?: number;
36
+ } = {}): Promise<GitInstallResult> {
37
+ const run = deps.run ?? ((command: string, args: readonly string[]) => {
38
+ const result = spawnSync(command, [...args], { stdio: ['inherit', deps.json ? process.stderr : process.stdout, process.stderr], timeout: 1_800_000 });
39
+ return { status: result.status };
40
+ });
41
+ const confirm = deps.confirm ?? (async (display: string) => {
42
+ const prompt = createInterface({ input: process.stdin, output: deps.json ? process.stderr : process.stdout });
43
+ try { return /^(y|yes)$/i.test((await prompt.question(`${display} 실행할까요? [y/N] `)).trim()); }
44
+ catch { return false; }
45
+ finally { prompt.close(); }
46
+ });
47
+ let agreed = deps.yes === true;
48
+ if (!agreed && deps.interactive === true && plan.command !== null) {
49
+ try { agreed = await confirm(plan.display); } catch { agreed = false; }
50
+ }
51
+ let ran = false;
52
+ let ok = false;
53
+ let detail = plan.command === null ? plan.display : '설치하지 않음 — --fix --yes 또는 대화형 동의가 필요합니다.';
54
+ if (agreed && plan.command) {
55
+ ran = true;
56
+ try {
57
+ let preOk = true;
58
+ for (const pre of plan.preCommands ?? []) {
59
+ if (run(pre[0]!, pre.slice(1)).status !== 0) { preOk = false; break; }
60
+ }
61
+ const installed = preOk ? run(plan.command[0]!, plan.command.slice(1)) : { status: 1 };
62
+ if (installed.status === 0) {
63
+ ok = smokeCheck('git', 'git', run);
64
+ // xcode-select returns as soon as Apple's installer window opens — wait for git to appear.
65
+ if (!ok && plan.waitForGit) {
66
+ const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
67
+ const deadline = (deps.now ?? Date.now)() + (deps.waitForGitMs ?? 15 * 60_000);
68
+ while (!ok && (deps.now ?? Date.now)() < deadline) {
69
+ await sleep(deps.pollMs ?? 10_000);
70
+ ok = smokeCheck('git', 'git', run);
71
+ }
72
+ }
73
+ }
74
+ detail = ok ? 'git init 재확인 성공' : 'git 설치 또는 git init 재확인 실패';
75
+ } catch {
76
+ detail = 'git 설치 또는 git init 재확인 실패';
77
+ }
78
+ }
79
+ debug.log('doctor.fix', 'git-install', { platform: deps.platform ?? process.platform, command: plan.command, ran, ok });
80
+ return { ran, ok, detail };
81
+ }
82
+
13
83
  export interface DoctorFixDeps {
14
84
  env?: NodeJS.ProcessEnv;
15
85
  home?: string;
16
86
  cacheDir?: string;
87
+ configDir?: string;
17
88
  readiness?: ReadinessDeps;
18
89
  readdir?: (path: string) => string[];
19
90
  exists?: (path: string) => boolean;
@@ -48,12 +119,14 @@ export interface DoctorFixDeps {
48
119
  arch?: string;
49
120
  /** 정적 도구 설치(시험 주입 · 기본 = doctor-static-tools). */
50
121
  installStaticTool?: (name: StaticToolName, dest: string) => { ok: boolean; detail: string };
122
+ /** 설치 뒤 실제 도구 동작 확인(시험 주입). */
123
+ smokeCheck?: (name: StaticToolName, dest: string) => boolean;
51
124
  /** 관리형 파이썬 설치(시험 주입). */
52
125
  installManagedPython?: (minor: string) => { python: string | null; detail: string };
53
126
  }
54
127
 
55
128
  export interface DoctorFixItem {
56
- id: 'install-path' | 'key-cache-permissions' | 'bun-tmpdir' | 'service-file' | 'service-secrets' | 'node-pty-rebuild' | 'python-env' | 'static-tools' | 'python-managed';
129
+ id: 'private-files' | 'install-path' | 'key-cache-permissions' | 'bun-tmpdir' | 'service-file' | 'service-secrets' | 'node-pty-rebuild' | 'python-env' | 'static-tools' | 'python-managed';
57
130
  path: string;
58
131
  action: string;
59
132
  status: 'fixable' | 'skipped' | 'failed';
@@ -66,7 +139,7 @@ export interface DoctorFixResult {
66
139
  exitCode: number;
67
140
  }
68
141
 
69
- type IO = Required<Omit<DoctorFixDeps, 'readiness' | 'keyNames' | 'realpath' | 'runCommand' | 'verifyNodePty' | 'pythonSetup' | 'recheckPythonEnv' | 'shimDir' | 'removeTree' | 'arch' | 'installStaticTool' | 'installManagedPython'>> & { readiness: ReadinessDeps; keyNames: readonly string[] | undefined };
142
+ type IO = Required<Omit<DoctorFixDeps, 'configDir' | 'readiness' | 'keyNames' | 'realpath' | 'runCommand' | 'verifyNodePty' | 'pythonSetup' | 'recheckPythonEnv' | 'shimDir' | 'removeTree' | 'arch' | 'installStaticTool' | 'smokeCheck' | 'installManagedPython'>> & { readiness: ReadinessDeps; keyNames: readonly string[] | undefined };
70
143
  const cachePath = Symbol('cachePath');
71
144
  type InternalFixItem = DoctorFixItem & { [cachePath]?: string };
72
145
  const START = '# >>> elanous installer PATH >>>';
@@ -391,11 +464,11 @@ function pythonEnvItem(deps: DoctorFixDeps): InternalFixItem | undefined {
391
464
  * 📏 2026-09-25 amazonlinux:2·2023 컨테이너에서 실측(`doctor-static-tools.ts` 머리말). sudo 불필요. */
392
465
  export function staticToolsNeeded(readiness: ReadinessDeps): StaticToolName[] {
393
466
  if (readiness.platform !== 'linux') return [];
394
- const remedies = remediesFor(readiness.distro ?? 'unknown');
467
+ const family = readiness.distro ?? 'unknown';
395
468
  const tools: StaticToolName[] = [];
396
- if (readiness.rgOnPath === false && !remedies?.rg) tools.push('rg');
469
+ if (readiness.rgOnPath === false && !toolInstallLine('rg', family)) tools.push('rg');
397
470
  // node 를 깔 줄이 있으면 codex 는 npm 길(sudo)로 — 없을 때만 정적 바이너리(node 불필요).
398
- if (readiness.codexOnPath === false && readiness.nodeOnPath === false && !remedies?.node) tools.push('codex');
471
+ if (readiness.codexOnPath === false && readiness.nodeOnPath === false && !toolInstallLine('node', family)) tools.push('codex');
399
472
  // codex 바이너리는 있는데 짝이 없다 — 한 벌로 다시 깐다(elanous bin 이 PATH 앞이라 그쪽이 쓰인다).
400
473
  else if (readiness.codexOnPath === true && readiness.codexCodeModeHost === false) tools.push('codex');
401
474
  // gh 가 없거나 낡았다(배포판 gh 가 GH_MIN_VERSION 미만) — 고정 판 정적 gh(elanous bin 이 PATH 앞이라 그쪽이 쓰인다).
@@ -443,8 +516,17 @@ function nodePtyItem(deps: DoctorFixDeps): InternalFixItem | undefined {
443
516
  return { id: 'node-pty-rebuild', path: plan.versionDir, action: `${envText}bun add ${plan.spec} (in ${plan.versionDir}) — then require('node-pty')`, status: 'fixable' };
444
517
  }
445
518
 
519
+ function privateFilesItem(deps: DoctorFixDeps, fs: IO): DoctorFixItem | undefined {
520
+ const configDir = deps.configDir ?? (deps.home ? join(deps.home, '.elanous') : getElanousConfigDir());
521
+ const scan = scanPrivateFiles(configDir, fs);
522
+ if (scan.dirMode === null || (scan.dirMode === 0o700 && scan.loose.length === 0)) return undefined;
523
+ return { id: 'private-files', path: configDir, action: 'chmod directory 700 and restrict private files', status: 'fixable',
524
+ reason: `directory ${scan.dirMode.toString(8)} · files ${scan.loose.length}` };
525
+ }
526
+
446
527
  export function planDoctorFixes(deps: DoctorFixDeps = {}): DoctorFixPlan {
447
528
  const fs = io(deps);
529
+ const privateFiles = privateFilesItem(deps, fs);
448
530
  const path = pathItem(fs);
449
531
  const tmpdir = tmpdirItem(fs);
450
532
  const service = serviceItem(fs);
@@ -454,7 +536,7 @@ export function planDoctorFixes(deps: DoctorFixDeps = {}): DoctorFixPlan {
454
536
  const staticTools = staticToolsItem(deps, fs);
455
537
  const pythonManaged = pythonManagedItem(deps, fs);
456
538
  return {
457
- items: [...(path ? [path] : []), ...(tmpdir ? [tmpdir] : []), ...(secrets ? [secrets] : []), ...(service ? [service] : []), ...(nodePty ? [nodePty] : []), ...(staticTools ? [staticTools] : []), ...(pythonManaged ? [pythonManaged] : []), ...(python ? [python] : []), ...cacheItems(fs)],
539
+ items: [...(path ? [path] : []), ...(tmpdir ? [tmpdir] : []), ...(secrets ? [secrets] : []), ...(service ? [service] : []), ...(nodePty ? [nodePty] : []), ...(staticTools ? [staticTools] : []), ...(pythonManaged ? [pythonManaged] : []), ...(python ? [python] : []), ...cacheItems(fs), ...(privateFiles ? [privateFiles] : [])],
458
540
  manual: checkReadiness(fs.readiness).items.filter((item) => item.status === 'manual'),
459
541
  };
460
542
  }
@@ -464,21 +546,64 @@ function defaultVerifyNodePty(packageDir: string): boolean {
464
546
  return r.status === 0;
465
547
  }
466
548
 
467
- export function applyDoctorFixes(deps: DoctorFixDeps = {}, yes = false): DoctorFixResult {
549
+ export function smokeCheck(name: StaticToolName | 'git', dest: string, run?: (command: string, args: readonly string[]) => { status: number | null }): boolean {
550
+ if (name === 'uv') return true;
551
+ if (name === 'codex-code-mode-host') {
552
+ if (run) return run(dest, ['--help']).status === 0;
553
+ const hello = Buffer.from(JSON.stringify({ type: 'connection/hello', supportedVersions: [1], requiredCapabilities: [], optionalCapabilities: [] }));
554
+ const frame = Buffer.alloc(4 + hello.length);
555
+ frame.writeUInt32LE(hello.length, 0);
556
+ hello.copy(frame, 4);
557
+ const reply = spawnSync(dest, [], { input: frame, timeout: 15_000, maxBuffer: 1024 * 1024 });
558
+ if (reply.status !== 0 || reply.stdout.length < 5) return false;
559
+ const length = reply.stdout.readUInt32LE(0);
560
+ if (length !== reply.stdout.length - 4) return false;
561
+ try {
562
+ const ready = JSON.parse(reply.stdout.subarray(4).toString('utf8')) as { type?: string; selectedVersion?: number };
563
+ return ready.type === 'connection/ready' && ready.selectedVersion === 1;
564
+ } catch { return false; }
565
+ }
566
+ const work = mkdtempSync(join(tmpdir(), name === 'git' ? 'elanous-doctor-git-' : 'elanous-doctor-tool-'));
567
+ try {
568
+ const args = name === 'git' ? ['init', work] : name === 'rg' ? ['doctor smoke', 'smoke.txt'] : name === 'gh' ? ['help'] : ['--help'];
569
+ if (name === 'rg') writeFileSync(join(work, 'smoke.txt'), 'doctor smoke\n');
570
+ return (run ? run(dest, args) : spawnSync(dest, args, { cwd: work, stdio: 'ignore', timeout: 15_000 })).status === 0;
571
+ } finally {
572
+ rmSync(work, { recursive: true, force: true });
573
+ }
574
+ }
575
+
576
+ export function applyDoctorFixes(deps: DoctorFixDeps = {}, yes = false, only?: ReadonlySet<DoctorFixItem['id']>): DoctorFixResult {
468
577
  const fs = io(deps);
469
578
  const plan = planDoctorFixes(deps);
470
579
  if (!yes) return {
471
- items: plan.items.map((item) => ({ ...item, result: item.status === 'failed' ? 'failed' : 'skipped', reason: item.reason ?? 'requires --yes' })),
472
- exitCode: plan.items.some((item) => item.status === 'failed') ? 1 : 0,
580
+ items: plan.items.map((item) => only && !only.has(item.id)
581
+ ? { ...item, result: 'skipped' as const, reason: 'not selected' }
582
+ : { ...item, result: item.status === 'failed' ? 'failed' as const : 'skipped' as const, reason: item.reason ?? 'requires --yes' }),
583
+ exitCode: plan.items.some((item) => item.status === 'failed' && (!only || only.has(item.id))) ? 1 : 0,
473
584
  };
474
585
  const items: DoctorFixResult['items'] = [];
475
586
  for (const item of plan.items) {
587
+ if (only && !only.has(item.id)) {
588
+ items.push({ ...item, result: 'skipped', reason: 'not selected' });
589
+ continue;
590
+ }
476
591
  if (item.status !== 'fixable') {
477
592
  items.push({ ...item, result: item.status === 'failed' ? 'failed' : 'skipped' });
478
593
  continue;
479
594
  }
480
595
  try {
481
- if (item.id === 'install-path') {
596
+ if (item.id === 'private-files') {
597
+ const scan = scanPrivateFiles(item.path, fs);
598
+ if (scan.dirMode === null || (scan.dirMode === 0o700 && !scan.loose.length)) {
599
+ items.push({ ...item, result: 'skipped', reason: 'permissions already private' });
600
+ continue;
601
+ }
602
+ fixPrivateFiles(scan, fs);
603
+ const after = scanPrivateFiles(item.path, fs);
604
+ const repaired = after.dirMode === 0o700 && after.loose.length === 0;
605
+ items.push({ ...item, result: repaired ? 'fixed' : 'failed', reason: repaired ? 'permissions restricted' : 'permissions remain loose' });
606
+ } else if (item.id === 'install-path') {
482
607
  // Reinspect immediately before writing; a competing installer may have changed it.
483
608
  const current = pathItem(fs);
484
609
  if (current?.status !== 'fixable') {
@@ -535,11 +660,14 @@ export function applyDoctorFixes(deps: DoctorFixDeps = {}, yes = false): DoctorF
535
660
  } else if (item.id === 'static-tools') {
536
661
  const arch = linuxArch(deps.arch)!;
537
662
  // codex 는 짝(`codex-code-mode-host`)과 «한 벌»이다 — 없으면 셸 도구가 못 뜬다(2026-09-25 L2 실측).
538
- const outcomes = staticToolsNeeded(deps.readiness ?? {})
663
+ const tools = staticToolsNeeded(deps.readiness ?? {});
664
+ const outcomes = tools
539
665
  .flatMap((tool): StaticToolName[] => (tool === 'codex' ? ['codex', 'codex-code-mode-host'] : [tool]))
540
666
  .map((tool) => (deps.installStaticTool ?? ((name, to) => installStaticTool(name, arch, to)))(tool, join(item.path, tool)));
541
- const ok = outcomes.length > 0 && outcomes.every((o) => o.ok);
542
- items.push({ ...item, result: ok ? 'fixed' : 'failed', reason: outcomes.map((o) => o.detail).join(' · ') || 'nothing to install' });
667
+ const installed = outcomes.length > 0 && outcomes.every((o) => o.ok);
668
+ const verified = installed && tools.every((tool) => (deps.smokeCheck ?? smokeCheck)(tool, join(item.path, tool)) &&
669
+ (tool !== 'codex' || (deps.smokeCheck ?? smokeCheck)('codex-code-mode-host', join(item.path, 'codex-code-mode-host'))));
670
+ items.push({ ...item, result: verified ? 'fixed' : 'failed', reason: installed && !verified ? 'installed, but smoke check failed' : outcomes.map((o) => o.detail).join(' · ') || 'nothing to install' });
543
671
  } else if (item.id === 'python-managed') {
544
672
  const got = (deps.installManagedPython ?? ((minor) => installManagedPython(minor, { env: fs.env, home: fs.home })))(managedPythonMinor());
545
673
  if (!got.python) { items.push({ ...item, result: 'failed', reason: got.detail }); continue; }
@@ -585,7 +713,7 @@ export function applyDoctorFixes(deps: DoctorFixDeps = {}, yes = false): DoctorF
585
713
  items.push({ ...item, result: repaired ? 'fixed' : 'failed', reason: repaired ? 'permissions are 600' : 'permissions remain different from 600' });
586
714
  }
587
715
  } catch {
588
- items.push({ ...item, result: 'failed', reason: item.id === 'key-cache-permissions' ? 'could not chmod or recheck cache file' : item.id === 'service-secrets' ? 'could not migrate cache or back up, write or recheck service file' : 'could not back up, write or recheck startup file' });
716
+ items.push({ ...item, result: 'failed', reason: item.id === 'key-cache-permissions' ? 'could not chmod or recheck cache file' : item.id === 'service-secrets' ? 'could not migrate cache or back up, write or recheck service file' : item.id === 'private-files' ? 'could not chmod or recheck private files' : 'could not back up, write or recheck startup file' });
589
717
  }
590
718
  }
591
719
  return { items, exitCode: items.some((item) => item.result === 'failed') ? 1 : 0 };
@@ -0,0 +1,71 @@
1
+ import { redactSecretText } from '../debug/log.js';
2
+ import type { ReadinessReport } from './doctor-readiness.js';
3
+ import type { DoctorFixItem, DoctorFixPlan } from './doctor-fix.js';
4
+
5
+ // Only tool/runtime installs are model-selectable; startup files, service units, installed code and credential stores are not.
6
+ export const ADVISABLE_DOCTOR_FIX_IDS: ReadonlySet<DoctorFixItem['id']> = new Set([
7
+ 'python-env', 'static-tools', 'python-managed',
8
+ ]);
9
+
10
+ export interface DoctorAdvice {
11
+ ok: boolean;
12
+ reason?: string;
13
+ summary: string;
14
+ order: Array<{ readinessId: string; fixId?: DoctorFixItem['id'] | 'git-install'; why: string }>;
15
+ manual: string[];
16
+ dropped: number;
17
+ }
18
+
19
+ /** The model ranks known repairs; it never supplies a command or an executable action. */
20
+ export async function adviseDoctorFixes({ report, plan, llm, locale = 'en', timeoutMs = 60_000 }: {
21
+ report: ReadinessReport;
22
+ plan: DoctorFixPlan;
23
+ llm?: (prompt: string) => Promise<string>;
24
+ locale?: 'en' | 'ko' | 'ja' | 'zh';
25
+ timeoutMs?: number;
26
+ }): Promise<DoctorAdvice> {
27
+ const empty = (reason: string): DoctorAdvice => ({ ok: false, reason, summary: '', order: [], manual: [], dropped: 0 });
28
+ if (!llm) return empty('LLM unavailable');
29
+ const language = { en: 'English', ko: 'Korean', ja: 'Japanese', zh: 'Chinese' }[locale];
30
+ const prompt = JSON.stringify({
31
+ instruction: `Read-only diagnosis. Return only JSON: {"summary":"...","order":[{"readinessId":"...","fixId":"optional catalog id or git-install","why":"..."}],"manual":["..."]}. Choose fixId only from the supplied repair plan or git-install. Never return shell commands. Do not execute anything. Write summary, why and manual in ${language}. Keep JSON keys and repair ids in English.`,
32
+ readiness: report.items.map(({ id, status, evidence, remedy }) => ({ id: redactSecretText(id), status, evidence: redactSecretText(evidence), ...(remedy === undefined ? {} : { remedy: redactSecretText(remedy) }) })),
33
+ plan: plan.items.map(({ id, action, status }) => ({ id, action: redactSecretText(action), status })),
34
+ });
35
+ let timer: ReturnType<typeof setTimeout> | undefined;
36
+ try {
37
+ const raw = await Promise.race([
38
+ Promise.resolve().then(() => llm(prompt)),
39
+ new Promise<never>((_, reject) => { timer = setTimeout(() => reject(new Error('timeout')), timeoutMs); }),
40
+ ]);
41
+ let parsed: unknown;
42
+ try { parsed = JSON.parse(raw); } catch { return empty('invalid JSON'); }
43
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return empty('invalid JSON shape');
44
+ const value = parsed as Record<string, unknown>;
45
+ if (typeof value.summary !== 'string' || !Array.isArray(value.order) || !Array.isArray(value.manual) || !value.manual.every((line: unknown) => typeof line === 'string')) return empty('invalid JSON shape');
46
+ const ids: ReadonlySet<string> = new Set(plan.items.filter((item) => item.status === 'fixable' && ADVISABLE_DOCTOR_FIX_IDS.has(item.id)).map((item) => item.id));
47
+ const readinessIds = new Set(report.items.map((item) => item.id));
48
+ const seenReadiness = new Set<string>();
49
+ const seenFix = new Set<string>();
50
+ let dropped = 0;
51
+ const order: DoctorAdvice['order'] = [];
52
+ for (const candidate of value.order as unknown[]) {
53
+ if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) { dropped++; continue; }
54
+ const { readinessId, fixId, why } = candidate as Record<string, unknown>;
55
+ if (typeof readinessId !== 'string' || !readinessIds.has(readinessId) || typeof why !== 'string'
56
+ || (fixId !== undefined && (typeof fixId !== 'string' || (fixId !== 'git-install' && !ids.has(fixId))))
57
+ || seenReadiness.has(readinessId) || (typeof fixId === 'string' && seenFix.has(fixId))) {
58
+ dropped++;
59
+ continue;
60
+ }
61
+ seenReadiness.add(readinessId);
62
+ if (typeof fixId === 'string') seenFix.add(fixId);
63
+ order.push({ readinessId, ...(fixId === undefined ? {} : { fixId: fixId as DoctorFixItem['id'] | 'git-install' }), why: redactSecretText(why) });
64
+ }
65
+ return { ok: true, summary: redactSecretText(value.summary), order, manual: value.manual.map((line: string) => redactSecretText(line)), dropped };
66
+ } catch {
67
+ return empty('LLM failed or timed out');
68
+ } finally {
69
+ if (timer) clearTimeout(timer);
70
+ }
71
+ }
@@ -0,0 +1,66 @@
1
+ import { chmodSync, existsSync, lstatSync, readdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { debug } from '../debug/log.js';
4
+
5
+ export interface PrivateFilesDeps {
6
+ exists?: (path: string) => boolean;
7
+ readdir?: (path: string) => string[];
8
+ lstat?: (path: string) => { mode: number; isDirectory?: () => boolean; isFile: () => boolean; isSymbolicLink: () => boolean };
9
+ chmod?: (path: string, mode: number) => void;
10
+ }
11
+
12
+ export interface PrivateFilesScan {
13
+ /** Directory to repair, including when only its own mode is loose. */
14
+ configDir: string;
15
+ /** null means the directory does not exist. */
16
+ dirMode: number | null;
17
+ loose: { path: string; mode: number }[];
18
+ }
19
+
20
+ export interface PrivateFilesFix {
21
+ dir: { path: string; before: number; after: number } | null;
22
+ files: { path: string; before: number; after: number }[];
23
+ }
24
+
25
+ const PRIVATE_NAME = /^(?:(?:config|secrets|auth|llm-fallback)\.json.*|.*\.bak.*)$/;
26
+
27
+ /** Inspect only immediate regular files, by name and lstat mode; never read their contents or follow links. */
28
+ export function scanPrivateFiles(configDir: string, deps: PrivateFilesDeps = {}): PrivateFilesScan {
29
+ const exists = deps.exists ?? existsSync;
30
+ if (!exists(configDir)) return { configDir, dirMode: null, loose: [] };
31
+ const lstat = deps.lstat ?? lstatSync;
32
+ const directory = lstat(configDir);
33
+ if (directory.isSymbolicLink() || directory.isFile() || (directory.isDirectory && !directory.isDirectory())) throw new Error('config directory is not a directory');
34
+ const loose: PrivateFilesScan['loose'] = [];
35
+ for (const name of (deps.readdir ?? readdirSync)(configDir).sort()) {
36
+ if (name === '.' || name === '..' || name.includes('/') || name.includes('\\') || !PRIVATE_NAME.test(name)) continue;
37
+ const path = join(configDir, name);
38
+ const stat = lstat(path);
39
+ if (stat.isFile() && !stat.isSymbolicLink() && (stat.mode & 0o044)) loose.push({ path, mode: stat.mode & 0o7777 });
40
+ }
41
+ return { configDir, dirMode: directory.mode & 0o7777, loose };
42
+ }
43
+
44
+ /** Reinspect just before chmod so stale scan modes cannot restore old owner bits. */
45
+ export function fixPrivateFiles(scan: PrivateFilesScan, deps: PrivateFilesDeps = {}): PrivateFilesFix {
46
+ const lstat = deps.lstat ?? lstatSync;
47
+ const chmod = deps.chmod ?? chmodSync;
48
+ const dirStat = lstat(scan.configDir);
49
+ if (dirStat.isSymbolicLink() || dirStat.isFile() || (dirStat.isDirectory && !dirStat.isDirectory())) throw new Error('config directory is not a directory');
50
+ const dirBefore = dirStat.mode & 0o7777;
51
+ const dir = dirBefore === 0o700 ? null : { path: scan.configDir, before: dirBefore, after: 0o700 };
52
+ if (dir) chmod(dir.path, dir.after);
53
+ const files: PrivateFilesFix['files'] = [];
54
+ for (const entry of scan.loose) {
55
+ const stat = lstat(entry.path);
56
+ if (!stat.isFile() || stat.isSymbolicLink()) continue;
57
+ const before = stat.mode & 0o7777;
58
+ const after = before & ~0o077;
59
+ if (after === before) continue;
60
+ chmod(entry.path, after);
61
+ files.push({ path: entry.path, before, after });
62
+ }
63
+ const result = { dir, files };
64
+ debug.log('doctor.private-files', 'fixed', result);
65
+ return result;
66
+ }
@@ -1,4 +1,5 @@
1
1
  import { remediesFor, type DistroFamily } from './doctor-distro.js';
2
+ import type { UsableLlm } from '../llm/usable-llm.js';
2
3
  import { providerSecretNames } from '../nexus/install/launchd.js';
3
4
  import { win32 } from 'node:path';
4
5
  /**
@@ -42,13 +43,8 @@ export interface ReadinessDeps {
42
43
  * must pass `null` rather than omit it).
43
44
  */
44
45
  provider?: string | null;
45
- /**
46
- * Codex subscription login is present. `null` means not measured.
47
- * The token itself is never passed in.
48
- */
49
- codexLogin?: boolean | null;
50
- /** LLM 을 부를 자격이 «하나라도» 있나(어떤 로그인이든 · LLM 키가 풀렸든). 없으면(undefined/null) 못 쟀다. */
51
- llmCredentialAvailable?: boolean | null;
46
+ /** Selected runtime route, already resolved with the runtime auto selector. null = unmeasured. */
47
+ usableLlm?: UsableLlm | null;
52
48
  /** `gh` is on PATH. `null` means not measured. */
53
49
  ghOnPath?: boolean | null;
54
50
  /** `gh --version` 의 판 · null/undefined = 못 쟀다. */
@@ -210,23 +206,19 @@ function providerDecision(deps: ReadinessDeps): ReadinessItem {
210
206
  return item('provider-decision', 'unknown', 'llm.provider was not measured');
211
207
  }
212
208
  const provider = deps.provider.trim() || 'auto';
213
- if (provider !== 'auto') {
214
- // 아는 provider 이름만 보여 준다 — 설정 칸에 자격 같은 값이 들어와 있어도 보고에 싣지 않는다.
215
- const shown = KNOWN_PROVIDERS.has(provider) ? provider : '(set · value not shown)';
216
- return item('provider-decision', 'ok', `llm.provider=${shown}`);
217
- }
218
- if (deps.codexLogin === undefined || deps.codexLogin === null) {
219
- return item('provider-decision', 'unknown', 'llm.provider=auto but codex login was not measured');
220
- }
221
- if (deps.codexLogin === true) {
222
- // 2026-09-24 결정(`#20142`) — auto 는 codex 구독을 먼저 쓰고 계정 회전·llm.fallbackChain 이 뒤를 잇는다.
223
- return item('provider-decision', 'ok', 'llm.provider=auto uses the codex login first; account rotation and llm.fallbackChain apply');
224
- }
225
- // 🩸 2026-09-24 빈 VM(🅢 #20263): 로그인도 키도 없는데 여기서 `ok` 가 나왔다(거짓 초록) — auto 가 고를 것이 없다.
226
- if (deps.llmCredentialAvailable === false) {
227
- return item('provider-decision', 'manual', 'llm.provider=auto but no LLM login or key was found — LLM commands will fail', 'elanous login openai-codex');
209
+ const shown = KNOWN_PROVIDERS.has(provider) ? provider : '(set · value not shown)';
210
+ if (deps.usableLlm == null) return item('provider-decision', 'unknown', `llm.provider=${shown} route was not measured`);
211
+ const { usable, provider: selected, via, why } = deps.usableLlm;
212
+ if (!usable) {
213
+ const reason = why === 'no usable LLM route selected' ? why : 'route unavailable';
214
+ const remedy = provider === 'auto' || provider === 'openai-codex' ? 'elanous login openai-codex'
215
+ : provider === 'openai' ? 'Set OPENAI_API_KEY or llm.apiKey for openai'
216
+ : provider === 'local' ? 'Set llm.baseUrl or LOCAL_LLM_URL for local'
217
+ : KNOWN_PROVIDERS.has(provider) ? `Configure credentials for llm.provider=${provider}` : undefined;
218
+ return item('provider-decision', 'manual', `llm.provider=${shown} selected no usable LLM (via none) — ${reason}`, remedy);
228
219
  }
229
- return item('provider-decision', 'ok', 'llm.provider=auto and no codex login');
220
+ const selectedName = selected && KNOWN_PROVIDERS.has(selected) ? selected : 'selected provider';
221
+ return item('provider-decision', 'ok', `llm.provider=${shown} → ${via} ${selectedName}`);
230
222
  }
231
223
 
232
224
  /** Debian 계열 apt 의 gh 는 GH_MIN_VERSION 미만이다(📏 09-25: Debian 12 = 2.23 · Ubuntu 24.04 = 2.45) — apt 로 깔면 곧바로
@@ -291,16 +283,17 @@ function harnessTools(deps: ReadinessDeps): ReadinessItem {
291
283
  const remedies = remediesFor(deps.distro ?? 'unknown');
292
284
  const commands = [
293
285
  rgOnPath === false ? remedies?.rg : undefined,
294
- nodeMissing ? remedies?.node : undefined,
295
- // node 를 깔 줄이 없으면 codex(npm) 줄도 내지 않는다 — 🩸 2026-09-25 amazonlinux:2: `sudo: npm: command not found`.
296
- codexOnPath === false && nodeOnPath != null && (!nodeMissing || remedies?.node) ? remedies?.codex : undefined,
286
+ nodeMissing && deps.distro !== 'debian' ? remedies?.node : undefined,
287
+ // On Debian, Node installation is an instruction, not a shell command: npm cannot run until Node is installed.
288
+ codexOnPath === false && nodeOnPath != null && (!nodeMissing || (deps.distro !== 'debian' && remedies?.node)) ? remedies?.codex : undefined,
297
289
  ].filter((command): command is string => command !== undefined);
290
+ const nodeInstruction = nodeMissing && deps.distro === 'debian' ? remedies?.node : undefined;
298
291
  const nodeEvidence = nodeMissing ? ' (node missing)' : codexOnPath === false && nodeOnPath == null ? ' (node not measured)' : '';
299
292
  // 계열에 설치 줄이 없는 도구는 «추측하지 않고» 이름을 댄다(예: Amazon Linux 2 의 rg·node).
300
293
  const noLine = [rgOnPath === false && !remedies?.rg ? 'rg' : '', nodeMissing && !remedies?.node ? 'node' : ''].filter(Boolean);
301
294
  const manualNote = noLine.length ? ` — no install line for this distro: install ${noLine.join(', ')} manually` : '';
302
295
  const unmeasured = rgOnPath == null || codexOnPath == null ? ' (other harness tool not measured)' : '';
303
- return item('harness-tools', 'manual', `${missing.length ? `${missing.join(' and ')} missing from harness tools` : 'codex requires node'}${nodeEvidence}${unmeasured}${manualNote}`, commands.join(' && ') || undefined);
296
+ return item('harness-tools', 'manual', `${missing.length ? `${missing.join(' and ')} missing from harness tools` : 'codex requires node'}${nodeEvidence}${unmeasured}${manualNote}${nodeInstruction && commands.length ? ` — ${nodeInstruction}` : ''}`, commands.join(' && ') || nodeInstruction);
304
297
  }
305
298
 
306
299
  function normalizeDir(value: string): string {
@@ -384,7 +377,9 @@ function serviceVersion(deps: ReadinessDeps): ReadinessItem {
384
377
  return item('service-version', 'unknown', 'health was not measured');
385
378
  }
386
379
  if (deps.health === null) {
387
- return item('service-version', 'unknown', 'health did not respond; not measured');
380
+ return deps.serviceFile === null
381
+ ? item('service-version', 'ok', 'no service installed; nothing to compare')
382
+ : item('service-version', 'unknown', 'health did not respond; not measured');
388
383
  }
389
384
  const daemonSha = typeof deps.health.daemonSha === 'string' ? deps.health.daemonSha.trim() : '';
390
385
  const revision = (deps.codeRevision ?? '').trim();
@@ -0,0 +1,63 @@
1
+ import type { Command } from 'commander';
2
+ import * as ui from '../ui.js';
3
+ import { writeStdoutJson } from './stdout-json.js';
4
+
5
+ export function registerFleetCommands(program: Command): void {
6
+ // ── fleet (멀티 인스턴스 통합 뷰 · §10 Control Plane/Fleet) ──
7
+ const fleetCmd = program.command('fleet')
8
+ .description('멀티 elanous 인스턴스 통합 뷰(READ-ONLY 연합) — 등록 인스턴스·보유 스토어 매트릭스. `logs instances` 일반화(kubectl get nodes 등가). 연합 조회는 `session list --all-instances` 등.');
9
+
10
+ fleetCmd
11
+ .command('list', { isDefault: true })
12
+ .description('등록 인스턴스 나열 — name·alive·repo·state-dir·보유 스토어(logs/sessions/tasks/memory)')
13
+ .option('--json')
14
+ .action(async (opts: { json?: boolean }) => {
15
+ const { buildFleetView } = await import('../domains/fleet.js');
16
+ const view = buildFleetView();
17
+ if (opts.json) { await writeStdoutJson(JSON.stringify(view, null, 2) + '\n'); return; }
18
+ ui.header(`Fleet (${view.length} instances · ${view.filter((v) => v.alive).length} alive)`);
19
+ for (const i of view) {
20
+ const flag = i.alive ? '●' : '○';
21
+ const s = i.stores;
22
+ const stores = [s.logs ? 'logs' : '', s.sessions ? 'sessions' : '', s.tasks ? 'tasks' : '', s.memory ? 'memory' : '', s.opsEvents ? 'ops' : '', s.schedules ? 'sched' : '', s.mandate ? 'mandate' : '', s.frame ? 'frame' : ''].filter(Boolean).join(',');
23
+ const kindTag = i.kind === 'test' ? ui.dim(' [test]') : '';
24
+ console.log(` ${flag} ${i.name.padEnd(24)}${kindTag} ${(i.liveness === 'remote' ? `remote@${i.hostname ?? 'unknown'}` : i.alive ? `pid=${i.pid}` : 'dead').padEnd(11)} [${stores}]`);
25
+ console.log(ui.dim(` ${i.stateDir}${i.repoPath ? ` ← ${i.repoPath}` : ''}`));
26
+ }
27
+ ui.info(ui.dim('연합 조회: session list · ops status · self recall `--all-instances` · fleet screen `--all`(격리 test 기본 제외·--include-test 로 포함)'));
28
+ });
29
+
30
+ fleetCmd
31
+ .command('screen')
32
+ .description('등록 elanous 인스턴스의 PTY 화면 프레임을 read-only로 조회한다')
33
+ .option('--all', '등록 인스턴스 전체를 연합 조회한다(격리 test 기본 제외)')
34
+ .option('--include-test', '--all 연합에 격리 test 인스턴스를 포함한다')
35
+ .option('--json', '구조화된 프레임 행을 출력한다')
36
+ .action(async (opts: { all?: boolean; includeTest?: boolean; json?: boolean }) => {
37
+ const { existsSync } = await import('node:fs');
38
+ const { homedir } = await import('node:os');
39
+ const { join } = await import('node:path');
40
+ const { instanceStorePaths, ptyManifestTargets } = await import('../domains/fleet.js');
41
+ const { listPtyManifestAt } = await import('../pty-shell/pty-manifest.js');
42
+ const { stripScreenAnsi } = await import('../harness/harness-screen.js');
43
+ const currentStateDir = process.env.ELANOUS_STATE_DIR?.trim() || join(homedir(), '.elanous');
44
+ const targets: Array<{ name: string; dbPath: string }> = [];
45
+ if (opts.all) {
46
+ // ⭐⭐ 열거는 `ptyManifestTargets`(SSOT) 한 곳이다 — `pty list --all` 과 **같은 함수**를 쓴다.
47
+ // ⛔ 여기서 따로 조립하면 두 창구가 조용히 갈린다(2026-07-30 리뷰 must-fix).
48
+ targets.push(...ptyManifestTargets({ includeTest: opts.includeTest === true }));
49
+ } else {
50
+ targets.push({ name: process.env.ELANOUS_INSTANCE_NAME?.trim() || 'prod', dbPath: instanceStorePaths(currentStateDir).frame });
51
+ }
52
+ const rows = targets.flatMap((target) => existsSync(target.dbPath)
53
+ ? listPtyManifestAt(target.dbPath).map((row) => ({ ...row, instance: row.instance || target.name }))
54
+ : [])
55
+ .sort((a, b) => a.frameAt - b.frameAt || a.startedAt - b.startedAt || a.id.localeCompare(b.id));
56
+ if (opts.json) { await writeStdoutJson(JSON.stringify(rows, null, 2) + '\n'); return; }
57
+ if (rows.length === 0) { console.log('(화면 프레임 없음)'); return; }
58
+ for (const row of rows) {
59
+ console.log(`── ${row.instance} · ${row.id} · ${row.kind} · ${new Date(row.frameAt).toISOString()} ──`);
60
+ console.log(stripScreenAnsi(row.frame));
61
+ }
62
+ });
63
+ }