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
@@ -27,6 +27,8 @@
27
27
  // crashed wizard cannot corrupt an existing file. Mode 0600 when the
28
28
  // telegram bot token is present.
29
29
 
30
+ import { isCodexQuotaPolicy } from './oauth/codex-quota-policy.js';
31
+ import { defaultObsidianVault } from './obsidian/default-vault.js';
30
32
  import {
31
33
  existsSync, readFileSync, writeFileSync, mkdirSync, renameSync, chmodSync,
32
34
  statSync, accessSync, constants as fsConstants,
@@ -71,6 +73,10 @@ import {
71
73
  } from './plugins/adapters/claude-package.js';
72
74
  // ⭐ provider↔credential SSOT — provider 를 바꾸는 자리가 키도 함께 해석해야 401 이 안 난다(escalate 근본수리).
73
75
  import { resolveProviderCredential, observeCredentialResolution } from './llm/provider-credentials.js';
76
+ import {
77
+ parseGroundingSources,
78
+ type GroundingConfig,
79
+ } from './grounding/sources.js';
74
80
 
75
81
  // ── SkillRouter (existing) ───────────────────────────────────────────
76
82
 
@@ -198,6 +204,14 @@ export interface LLMConfig {
198
204
  * 🩸 2026-09-24(대표): 「third 부터 소진하고 그다음 team」 — 이름순(default<new<third)으론 못 만든다.
199
205
  * ⛔ 여기 없는 계정은 버리지 않는다 — 뒤로 가서 이름순으로 붙는다. */
200
206
  codexAccountOrder?: string[];
207
+ /** 대표 2026-09-28 «크레딧 사용 허가» — 주간 한도가 찬 codex 계정도 «선불 크레딧으로 계속» 쓴다(서버가 한도 소진 시 크레딧으로 넘긴다).
208
+ * 켜면 회전이 «후보 없음»(→ grok 폴백) 대신 지금 계정에 머물고, Pod 배분도 찬 계정을 사용률 낮은 순으로 쓴다.
209
+ * 순서는 여전히 «구독 잔량이 남은 계정 먼저». 기본 꺼짐(크레딧은 돈이다). */
210
+ codexCreditsAllowed?: boolean;
211
+ /** 대표 2026-09-28 codex «한도 정책» — 한도가 차면 무엇을 하나(`src/oauth/codex-quota-policy.ts` 가 canonical):
212
+ * `within-quota`(한도 안에서만 · 전부 차면 멈춤) · `fallback`(한도 안 ⊕ 폴백 체인 · 기본) · `credits`(크레딧까지).
213
+ * 회전·Pod 배분·폴백·매시 한도 알림이 «이 한 값»을 같이 읽는다. 없으면 옛 `codexCreditsAllowed` 를 읽는다. */
214
+ codexQuotaPolicy?: 'within-quota' | 'fallback' | 'credits';
201
215
  /** ⭐⭐ codex 가 «소진된 뒤» 갈 곳을 «순서»로 정한다 (대표 2026-08-13).
202
216
  *
203
217
  * 값: `['codex-rotate', 'grok']` — 아는 칸은 그 둘뿐이고, 모르는 이름은 버린다(관측에 남는다).
@@ -680,10 +694,14 @@ function skillsDefaults(): SkillsConfig {
680
694
 
681
695
  // ── Obsidian ─────────────────────────────────────────────────────────
682
696
 
683
- export interface ObsidianConfig { vault: string; }
697
+ export interface ObsidianConfig {
698
+ vault: string;
699
+ /** 격리(test) 우주의 «쓰기 시험» 볼트(예 `elantest`) — 읽기는 늘 `vault`. 볼트 쓰기 가드의 허용 목록에 든다(대표·🅞 2026-09-26). */
700
+ testVault?: string;
701
+ }
684
702
 
685
703
  function obsidianDefaults(): ObsidianConfig {
686
- return { vault: process.env.OBSIDIAN_VAULT || join(REMOTE_HOME, 'Obsidian', 'ElanvitalAI') };
704
+ return { vault: defaultObsidianVault({ env: process.env, home: REMOTE_HOME }) };
687
705
  }
688
706
 
689
707
  // ── Telegram ─────────────────────────────────────────────────────────
@@ -766,6 +784,12 @@ export interface TelegramChannel {
766
784
  }
767
785
 
768
786
  /** 저장된 telegram.channels[] 파싱. 각 항목은 botToken+chatId 필수. fail-soft. */
787
+ function normalizeKindRoles(raw: unknown): Record<string, string> | undefined {
788
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
789
+ const out = Object.fromEntries(Object.entries(raw as Record<string, unknown>).filter((e): e is [string, string] => typeof e[1] === 'string' && e[1].length > 0));
790
+ return Object.keys(out).length ? out : undefined;
791
+ }
792
+
769
793
  function normalizeTelegramChannels(raw: unknown): TelegramChannel[] | undefined {
770
794
  if (!Array.isArray(raw)) return undefined;
771
795
  const out: TelegramChannel[] = [];
@@ -806,6 +830,9 @@ export interface TelegramConfig {
806
830
  /** 누가 Q&A 폴링을 하나 — 기본(없음·`'nexus'`)은 넥서스 데몬, `'standalone'` 이면
807
831
  * 넥서스는 폴링하지 않고 `elanous telegram run` 이 맡는다. */
808
832
  poller?: 'nexus' | 'standalone';
833
+ /** 발송 목적(kind) → 채널 역할. 명시 `channels` 가 있을 때만 쓴다 — 표에 없는 kind 는 옛 `reportChannel` 로 간다.
834
+ * 기본표는 `DEFAULT_KIND_ROLES`(telegram-report.ts) · 여기 값이 덮어쓴다. */
835
+ kindRoles?: Record<string, string>;
809
836
  }
810
837
 
811
838
  const TELEGRAM_DEFAULTS: TelegramConfig = { enabled: false, allowedUsers: [] };
@@ -941,6 +968,53 @@ export interface SelfImplementClarificationEscalationConfig {
941
968
 
942
969
  export type SelfImplementChildInstanceMode = 'isolated' | 'inherit';
943
970
 
971
+ /** 자식 LLM 선호. `pinned` = 기존 provider·model 한 칸. `auto` = 사용자 `chain` 순서. */
972
+ export type ChildLlmPreferenceMode = 'pinned' | 'auto';
973
+
974
+ export interface ChildLlmChainEntry {
975
+ provider: string;
976
+ model?: string;
977
+ }
978
+
979
+ export interface ChildLlmPreferenceConfig {
980
+ /** 있으면 pinned 의 값. 기존 고정 설정. */
981
+ provider?: string;
982
+ /** 기존 고정 설정. provider 없이 model 만 있으면 mode 는 auto 다. */
983
+ model?: string;
984
+ /** 없으면 provider 가 있을 때 pinned, 없을 때 auto. model 만 있어도 provider 가 없으면 auto. */
985
+ mode?: ChildLlmPreferenceMode;
986
+ /** auto 일 때의 사용자 순서. 원소는 { provider, model? }. */
987
+ chain?: ChildLlmChainEntry[];
988
+ }
989
+
990
+ /** 예산이 모자랄 때의 행동. 판정(P15)은 이 칸을 읽기만 한다. */
991
+ export type BudgetGateOnShortfall = 'decompose' | 'wait-reset' | 'next-provider' | 'proceed';
992
+
993
+ /** 프로바이더별 사용률 상한(0~100). 이 값 이상이면 그 칸을 안 쓴다. */
994
+ export type BudgetGateMaxUsedPercent = { readonly [provider: string]: number };
995
+
996
+ /**
997
+ * 대표 2026-09-26 상한. codex 계정은 95% 이상이면 그 계정을 안 쓰고,
998
+ * grok 은 주간 최대 50% 중 🅢 가드 48% 에서 멈춘다.
999
+ * 🅞 흡수 크론의 «codex ≥80%» 는 이 판정의 상한이 아니다.
1000
+ */
1001
+ export const DEFAULT_BUDGET_GATE_MAX_USED_PERCENT: BudgetGateMaxUsedPercent = {
1002
+ 'openai-codex': 95,
1003
+ grok: 48,
1004
+ };
1005
+
1006
+ export interface HarnessBudgetGateConfig {
1007
+ /** 0~100. 기본 15. 범위 밖이면 경고와 함께 기본. */
1008
+ minHeadroomPercent: number;
1009
+ /** 기본 next-provider. 모르는 값이면 경고와 함께 기본. */
1010
+ onShortfall: BudgetGateOnShortfall;
1011
+ /**
1012
+ * 선택. 없으면 `DEFAULT_BUDGET_GATE_MAX_USED_PERCENT`.
1013
+ * 프로바이더 값이 0~100 밖이면 그 칸만 경고 후 기본.
1014
+ */
1015
+ maxUsedPercent?: BudgetGateMaxUsedPercent;
1016
+ }
1017
+
944
1018
  export interface SelfImplementToolConfig {
945
1019
  /** Absolute root that holds per-repository child worktree directories. */
946
1020
  worktreeRoot: string;
@@ -957,17 +1031,12 @@ export interface SelfImplementToolConfig {
957
1031
  prApprovalDelivery: 'terminal' | 'all';
958
1032
  /** Records SelfImplement dispatches without starting an implementation run. */
959
1033
  observeOnly: boolean;
1034
+ /** Also append terminal execution records to the authored goal document (default true). */
1035
+ goalRecordInDoc: boolean;
960
1036
  /** Controls the persistent grounding loop used while authoring goals; absent preserves it. */
961
1037
  goalAuthorPersistentGrounding?: boolean;
962
- /**
963
- * ⭐ PR 근거 아티팩트의 일곱 축이 비었을 때 **PR 준비를 막나**. 기본(absent)은 안 막는다 —
964
- * 거절 사실은 `pr-evidence-artifact` 관측으로 «항상» 남고, 차단만 명시로 켠다.
965
- */
966
- prEvidenceArtifactEnforce?: boolean;
967
1038
  /** Uses the Fabric decomposer for SelfOrchestrate requests that omit `fabric_decompose`. */
968
1039
  fabricDecompose: boolean;
969
- /** ⛔⭐ 그래프 선언을 «실행 권위»로 올린다(RFC §5 1단계 · 대표 2026-09-08). 기본 켬(`TOOLS_DEFAULTS` · 끄려면 `false` 또는 `--no-graph`). */
970
- graphAuthoritative: boolean;
971
1040
  /** Normalized SelfOrchestrate goal count that automatically selects Fabric; null disables auto-selection. */
972
1041
  fabricDecomposeAutoPathThreshold: number | null;
973
1042
  autoStop: SelfImplementAutoStopConfig;
@@ -977,8 +1046,8 @@ export interface SelfImplementToolConfig {
977
1046
  decompositionShadow: SelfImplementDecompositionShadowConfig;
978
1047
  /** Opt-in delivery of authored goal clarifications from unattended dev runs. */
979
1048
  clarificationEscalation: SelfImplementClarificationEscalationConfig;
980
- /** Optional ask-launch override; omission lets the launch flow default self-resolution ON. */
981
- selfResolveClarifications?: boolean;
1049
+ /** 사용자 자식 모델 선호. 없으면 해석기가 auto + fallbackChain 으로 만든다. */
1050
+ childLlm?: ChildLlmPreferenceConfig;
982
1051
  /** ⭐ PR-open 사전 승인 (2026-07-26 · 대표 결정 "오토 선호 · 기본 ON").
983
1052
  *
984
1053
  * self-build 가 gate 를 통과하면 **PR 을 자동 개설**한다(기본 `true`).
@@ -1063,7 +1132,7 @@ const TOOLS_DEFAULTS: ToolsConfig = {
1063
1132
  selfOrchestrate: {},
1064
1133
  nativeStructure: { enabled: false },
1065
1134
  // 대표 결정(2026-07-26): 오토 선호 — 기본 ON.
1066
- selfImplement: { worktreeRoot: join(homedir(), '.elanous', 'worktrees'), childInstanceMode: 'isolated', prApprovalDelivery: 'terminal' as const, observeOnly: false, fabricDecompose: false, graphAuthoritative: true, fabricDecomposeAutoPathThreshold: 5, autoOpenPr: true, autoStop: { enabled: true, minRung: 2 }, autoAssist: { enabled: true, minRung: 2 }, screenStallTermination: { enabled: true, minRung: 2 }, reworkBudget: { shadowStop: false, maxRounds: 3 }, decompositionShadow: { enabled: false }, clarificationEscalation: { enabled: false } },
1135
+ selfImplement: { worktreeRoot: join(homedir(), '.elanous', 'worktrees'), childInstanceMode: 'isolated', prApprovalDelivery: 'terminal' as const, observeOnly: false, goalRecordInDoc: true, fabricDecompose: false, fabricDecomposeAutoPathThreshold: 5, autoOpenPr: true, autoStop: { enabled: true, minRung: 2 }, autoAssist: { enabled: true, minRung: 2 }, screenStallTermination: { enabled: true, minRung: 2 }, reworkBudget: { shadowStop: false, maxRounds: 3 }, decompositionShadow: { enabled: false }, clarificationEscalation: { enabled: false } },
1067
1136
  };
1068
1137
 
1069
1138
  // ── Debug ────────────────────────────────────────────────────────────
@@ -1098,8 +1167,8 @@ export interface DebugConfig {
1098
1167
  /** OH9(2026-07-24) — 렌더 카테고리(dashboard·key·mouse·cursor 계열)
1099
1168
  * 발화 여부. 진단 강도 축(`level`)과 **직교**한 별도 스위치 —
1100
1169
  * 대표는 상시 diag+ 라 "진단은 켜두고 렌더만 끄는" 축이 필요하다.
1101
- * 기본 `false`(억제). `dashboard.uiMode === 'essential'` 이면 자동 OFF
1102
- * (억제 시드). `true` 로 명시하면 essential 에서도 렌더 로그를 살린다
1170
+ * 기본 `false`(억제). essential TUI 는 렌더 로그를 자동 억제한다.
1171
+ * `true` 로 명시하면 렌더 로그를 살린다
1103
1172
  * (override). 런타임 영속은 config 가 아니라 `<stateRoot>/logs/level.json`
1104
1173
  * 의 `render` 필드(overlay 오염 방지) — 이 config 값은 부팅 시드일 뿐.
1105
1174
  * 선례: `exposeFullLlmTools`(계열 통째 죽이는 불린). */
@@ -1245,13 +1314,11 @@ export interface ChatRenderingStreamingConfig {
1245
1314
  catchUpAgeMs: number;
1246
1315
  }
1247
1316
 
1248
- export interface ChatRenderingCompactBoundaryConfig {
1249
- enabled: boolean;
1250
- }
1317
+ /** Legacy exported type name; the compact boundary no longer has configurable fields. */
1318
+ export interface ChatRenderingCompactBoundaryConfig {}
1251
1319
 
1252
1320
  export interface ChatRenderingWrapConfig {
1253
1321
  urlAware: boolean;
1254
- preserveOsc8: boolean;
1255
1322
  }
1256
1323
 
1257
1324
  export type ChatRenderingToolDisplayMode = 'legacy' | 'inline-to-block';
@@ -1267,12 +1334,7 @@ export type ChatRenderingDiffTurnBrowserMode = 'all' | 'files' | 'turns';
1267
1334
 
1268
1335
  export interface ChatRenderingDiffConfig {
1269
1336
  colorTier: ChatRenderingDiffColorTier;
1270
- adaptiveBg: boolean;
1271
- syntaxPerHunk: boolean;
1272
- cache: boolean;
1273
1337
  headerStyle: ChatRenderingDiffHeaderStyle;
1274
- turnSummary: boolean;
1275
- turnBrowser: boolean;
1276
1338
  turnBrowserHistory: number;
1277
1339
  turnBrowserMode: ChatRenderingDiffTurnBrowserMode;
1278
1340
  }
@@ -1284,7 +1346,6 @@ export interface ChatRenderingHudConfig {
1284
1346
 
1285
1347
  export interface ChatRenderingConfig {
1286
1348
  streaming: ChatRenderingStreamingConfig;
1287
- compactBoundary: ChatRenderingCompactBoundaryConfig;
1288
1349
  wrap: ChatRenderingWrapConfig;
1289
1350
  tool: ChatRenderingToolConfig;
1290
1351
  diff: ChatRenderingDiffConfig;
@@ -1362,28 +1423,19 @@ export const CHAT_DEFAULTS: ChatConfig = {
1362
1423
  catchUpThresholdLines: 50,
1363
1424
  catchUpAgeMs: 200,
1364
1425
  },
1365
- compactBoundary: {
1366
- enabled: true,
1367
- },
1368
1426
  wrap: {
1369
1427
  urlAware: false,
1370
- preserveOsc8: true,
1371
1428
  },
1372
1429
  tool: {
1373
1430
  displayMode: 'inline-to-block',
1374
1431
  blockMaxLines: 8,
1375
1432
  },
1376
- diff: {
1377
- colorTier: 'auto',
1378
- adaptiveBg: true,
1379
- syntaxPerHunk: true,
1380
- cache: true,
1381
- headerStyle: 'legacy',
1382
- turnSummary: true,
1383
- turnBrowser: true,
1384
- turnBrowserHistory: 8,
1385
- turnBrowserMode: 'all',
1386
- },
1433
+ diff: {
1434
+ colorTier: 'auto',
1435
+ headerStyle: 'legacy',
1436
+ turnBrowserHistory: 8,
1437
+ turnBrowserMode: 'all',
1438
+ },
1387
1439
  hud: {
1388
1440
  gaugeWarnRatio: 0.7,
1389
1441
  gaugeDangerRatio: 0.85,
@@ -1405,19 +1457,6 @@ export interface DashboardConfig {
1405
1457
  * disabled so the bank can be populated and debugged before it
1406
1458
  * affects real LLM turns. */
1407
1459
  promptBank: DashboardPromptBankConfig;
1408
- /** First-entry layout. 'chat' seeds chatOnlyMode=true on boot so
1409
- * the app opens straight into the chat REPL; 'dashboard' (or
1410
- * undefined) keeps the legacy 3-pane grid. CLI flags
1411
- * (`--chat-only`, `--debug`) still force 'chat' regardless.
1412
- * @deprecated TUI 부활 T0 — `uiMode` 로 흡수됨. uiMode 미설정 시에만
1413
- * 참조된다 ('chat'→essential · 'dashboard'→rich). */
1414
- defaultMode?: 'chat' | 'dashboard';
1415
- /** TUI 부활 T0 (PLAN-tui-revival-essentials-2026-07-12 §3a) —
1416
- * 단일 UI 모드 축. 'essential'(기본) = codex/claude-code 패리티
1417
- * chat 전체화면 + 1줄 status line; 'rich' = 기존 전체 기능
1418
- * (3-pane grid·VW·widget·마우스). CLI `--rich` 는 이번 실행만
1419
- * rich 강제. 해석 우선순위는 views/ui-mode.ts 참조. */
1420
- uiMode?: 'essential' | 'rich';
1421
1460
  /** Chat-log fold strategy. Default `task-unit` collapses each tool
1422
1461
  * body to its header; `line` keeps the unfolder line-budget body;
1423
1462
  * `kind-unit` coalesces adjacent same-kind operations. Runtime
@@ -1694,13 +1733,12 @@ export interface SessionFabricConfig {
1694
1733
  * acp(C5d·최고위험) = ACP broadcast 를 통합 fan-out 으로 흡수 — ON 시 push 가 fanOutSessionChunk
1695
1734
  * 경로로(byte-identical parity 후) + ACP 턴이 tg/dc/pwa 로 미러. 기본 부재=OFF. */
1696
1735
  streaming?: { telegram?: boolean; discord?: boolean; acp?: boolean };
1697
- /** C5-enh 서피스 특유 노브(reactions-as-status·스트리밍 모드 등). reactions ON = 턴 시작 👀 →
1698
- * 완료 ✅/실패 ❌(편집보다 저비용 상태채널·hermes/openclaw 선례). streamingMode = off|progress|
1699
- * partial|block(§6-8·기본 partial=현 full stream). editGapMs = 편집 간격(기본 1100).
1736
+ /** C5-enh 서피스 특유 노브. streamingMode = off|progress|partial|block(§6-8·기본 partial=현 full stream).
1737
+ * editGapMs = 편집 간격(기본 1100). 반응(👀 → 완료/실패)은 늘 켬.
1700
1738
  * 텔레그램 강화(§5.2·§10-2·전부 기본 off·라이브 무접촉): typing = sendChatAction liveness ·
1701
1739
  * fairQueue = supergroup 다중토픽 라운드로빈 · rotate = scroll-jump post-new-then-delete. 기본 부재=OFF. */
1702
- telegram?: { reactions?: boolean; streamingMode?: StreamingMode; editGapMs?: number; typing?: boolean; fairQueue?: boolean; rotate?: boolean };
1703
- discord?: { reactions?: boolean; streamingMode?: StreamingMode; editGapMs?: number };
1740
+ telegram?: { streamingMode?: StreamingMode; editGapMs?: number; typing?: boolean; fairQueue?: boolean; rotate?: boolean };
1741
+ discord?: { streamingMode?: StreamingMode; editGapMs?: number };
1704
1742
  }
1705
1743
  // ── taste (Layer2 substrate · P4 중앙 진입점 수집 · 2026-07-18) ──────────
1706
1744
  // 기본 부재(=OFF·opt-in). captureEnabled=true 면 intent-gate submitIntent 최상단이
@@ -1741,6 +1779,32 @@ function parseTasteConfig(raw: unknown): TasteConfig | undefined {
1741
1779
  export interface WebSearchConfig {
1742
1780
  tavily?: { enabled?: boolean };
1743
1781
  }
1782
+
1783
+ /** OpenDesign 데몬 접속. url 이 없으면 시안 생성은 꺼진 것이다. tokenFile 은 토큰 «경로»만 담는다. */
1784
+ export interface OpenDesignConfig {
1785
+ url?: string;
1786
+ tokenFile?: string;
1787
+ }
1788
+
1789
+ export interface DesignConfig {
1790
+ openDesign?: OpenDesignConfig;
1791
+ }
1792
+
1793
+ function parseOpenDesignConfig(raw: unknown): OpenDesignConfig | undefined {
1794
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
1795
+ const r = raw as Record<string, unknown>;
1796
+ const out: OpenDesignConfig = {};
1797
+ if (typeof r.url === 'string' && r.url.trim()) out.url = r.url.trim();
1798
+ if (typeof r.tokenFile === 'string' && r.tokenFile.trim()) out.tokenFile = r.tokenFile.trim();
1799
+ return Object.keys(out).length > 0 ? out : undefined;
1800
+ }
1801
+
1802
+ function parseDesignConfig(raw: unknown): DesignConfig | undefined {
1803
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
1804
+ const r = raw as Record<string, unknown>;
1805
+ const openDesign = parseOpenDesignConfig(r.openDesign);
1806
+ return openDesign ? { openDesign } : undefined;
1807
+ }
1744
1808
  function parseWebSearchConfig(raw: unknown): WebSearchConfig | undefined {
1745
1809
  if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
1746
1810
  const r = raw as Record<string, unknown>;
@@ -1783,8 +1847,7 @@ function parseSessionFabricConfig(raw: unknown): SessionFabricConfig | undefined
1783
1847
  const raw = r[surf];
1784
1848
  if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
1785
1849
  const s = raw as Record<string, unknown>;
1786
- const surfCfg: { reactions?: boolean; streamingMode?: StreamingMode; editGapMs?: number; typing?: boolean; fairQueue?: boolean; rotate?: boolean } = {};
1787
- if (typeof s.reactions === 'boolean') surfCfg.reactions = s.reactions;
1850
+ const surfCfg: { streamingMode?: StreamingMode; editGapMs?: number; typing?: boolean; fairQueue?: boolean; rotate?: boolean } = {};
1788
1851
  if (isStreamingMode(s.streamingMode)) surfCfg.streamingMode = s.streamingMode;
1789
1852
  if (typeof s.editGapMs === 'number' && Number.isFinite(s.editGapMs) && s.editGapMs > 0) surfCfg.editGapMs = s.editGapMs;
1790
1853
  // 텔레그램 전용 강화 노브(§5.2·§10-2). discord 에 오면 무시(파서는 관대·sink 가 미사용).
@@ -1799,6 +1862,19 @@ function parseSessionFabricConfig(raw: unknown): SessionFabricConfig | undefined
1799
1862
  return Object.keys(out).length > 0 ? out : undefined;
1800
1863
  }
1801
1864
 
1865
+ function parseNextFluentConfig(raw: unknown): UserConfig['nextFluent'] {
1866
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
1867
+ const r = raw as Record<string, unknown>;
1868
+ const out: NonNullable<UserConfig['nextFluent']> = {};
1869
+ if (typeof r.personas === 'boolean') out.personas = r.personas;
1870
+ if (r.models && typeof r.models === 'object' && !Array.isArray(r.models)) {
1871
+ out.models = Object.fromEntries(
1872
+ Object.entries(r.models).filter((entry): entry is [string, string] => typeof entry[1] === 'string'),
1873
+ );
1874
+ }
1875
+ return Object.keys(out).length > 0 ? out : undefined;
1876
+ }
1877
+
1802
1878
  function parseModelTierFieldOrUndefined(v: unknown): ModelTier | undefined {
1803
1879
  return isModelTier(v) ? v : undefined;
1804
1880
  }
@@ -2336,16 +2412,13 @@ function parseToolsConfig(raw: unknown): ToolsConfig {
2336
2412
  const observeOnly = typeof selfImplRaw.observeOnly === 'boolean'
2337
2413
  ? selfImplRaw.observeOnly
2338
2414
  : TOOLS_DEFAULTS.selfImplement.observeOnly;
2415
+ const goalRecordInDoc = typeof selfImplRaw.goalRecordInDoc === 'boolean'
2416
+ ? selfImplRaw.goalRecordInDoc
2417
+ : TOOLS_DEFAULTS.selfImplement.goalRecordInDoc;
2339
2418
  const goalAuthorPersistentGrounding = typeof selfImplRaw.goalAuthorPersistentGrounding === 'boolean'
2340
2419
  ? selfImplRaw.goalAuthorPersistentGrounding
2341
2420
  : undefined;
2342
- const prEvidenceArtifactEnforce = typeof selfImplRaw.prEvidenceArtifactEnforce === 'boolean'
2343
- ? selfImplRaw.prEvidenceArtifactEnforce
2344
- : undefined;
2345
2421
  const fabricDecompose = selfImplRaw.fabricDecompose === true;
2346
- const graphAuthoritative = typeof selfImplRaw.graphAuthoritative === 'boolean'
2347
- ? selfImplRaw.graphAuthoritative
2348
- : TOOLS_DEFAULTS.selfImplement.graphAuthoritative;
2349
2422
  const fabricDecomposeAutoPathThresholdRaw = selfImplRaw.fabricDecomposeAutoPathThreshold;
2350
2423
  const fabricDecomposeAutoPathThreshold = fabricDecomposeAutoPathThresholdRaw === null
2351
2424
  ? null
@@ -2439,9 +2512,7 @@ function parseToolsConfig(raw: unknown): ToolsConfig {
2439
2512
  enabled: clarificationEscalationRaw.enabled === true,
2440
2513
  ...(clarificationTimeoutMs === undefined ? {} : { timeoutMs: clarificationTimeoutMs }),
2441
2514
  };
2442
- const selfResolveClarifications = typeof selfImplRaw.selfResolveClarifications === 'boolean'
2443
- ? selfImplRaw.selfResolveClarifications
2444
- : undefined;
2515
+ const childLlm = parseChildLlmPreference(selfImplRaw.childLlm);
2445
2516
  // ⭐ 관측(리뷰 should-fix) — 오타/비-boolean 은 기본값(ON)으로 수렴하는데, 그게 조용하면
2446
2517
  // "껐다고 믿었는데 자동 개설되는" 운영 사고가 된다. 값이 **있는데 boolean 이 아닐 때만**
2447
2518
  // 경고한다(부재는 정상). 로거 대신 stderr — 이 파일의 기존 경고와 동형(부트 시점·의존 0).
@@ -2464,8 +2535,135 @@ function parseToolsConfig(raw: unknown): ToolsConfig {
2464
2535
  runDevHarness,
2465
2536
  selfOrchestrate,
2466
2537
  nativeStructure,
2467
- selfImplement: { worktreeRoot, childInstanceMode, prApprovalDelivery, observeOnly, goalAuthorPersistentGrounding, prEvidenceArtifactEnforce, fabricDecompose, graphAuthoritative, fabricDecomposeAutoPathThreshold, autoOpenPr, autoStop, autoAssist, screenStallTermination, reworkBudget, decompositionShadow, clarificationEscalation, ...(selfResolveClarifications === undefined ? {} : { selfResolveClarifications }) },
2538
+ selfImplement: { worktreeRoot, childInstanceMode, prApprovalDelivery, observeOnly, goalRecordInDoc, goalAuthorPersistentGrounding, fabricDecompose, fabricDecomposeAutoPathThreshold, autoOpenPr, autoStop, autoAssist, screenStallTermination, reworkBudget, decompositionShadow, clarificationEscalation, ...(childLlm ? { childLlm } : {}) },
2539
+ };
2540
+ }
2541
+
2542
+ const CHILD_LLM_MODES = ['pinned', 'auto'] as const;
2543
+
2544
+ /** 잘못된 값은 경고와 함께 버린다 — 설정 한 줄이 발사를 막지 않는다. 없으면 undefined(해석기가 기본).
2545
+ * 비객체·비문자열 provider/model 도 경고 후 버리고 기본으로 진행한다. 발사를 막지 않는다. */
2546
+ export function parseChildLlmPreference(raw: unknown): ChildLlmPreferenceConfig | undefined {
2547
+ if (raw === undefined) return undefined;
2548
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
2549
+ warnUserConfigDrop('tools.selfImplement.childLlm', `객체가 아니다(${JSON.stringify(raw)}) — 버리고 기본으로 진행`);
2550
+ return undefined;
2551
+ }
2552
+ const v = raw as Record<string, unknown>;
2553
+ const out: ChildLlmPreferenceConfig = {};
2554
+ let droppedInvalidProvider = false;
2555
+ if (v.provider !== undefined) {
2556
+ if (typeof v.provider === 'string') out.provider = v.provider;
2557
+ else {
2558
+ droppedInvalidProvider = true;
2559
+ warnUserConfigDrop('tools.selfImplement.childLlm.provider', `문자열이 아니다(${JSON.stringify(v.provider)}) — 버림`);
2560
+ }
2561
+ }
2562
+ if (v.model !== undefined) {
2563
+ if (typeof v.model === 'string') out.model = v.model;
2564
+ else warnUserConfigDrop('tools.selfImplement.childLlm.model', `문자열이 아니다(${JSON.stringify(v.model)}) — 버림`);
2565
+ }
2566
+ if (v.mode !== undefined) {
2567
+ if ((CHILD_LLM_MODES as readonly string[]).includes(v.mode as string)) out.mode = v.mode as ChildLlmPreferenceMode;
2568
+ else warnUserConfigDrop('tools.selfImplement.childLlm.mode', `pinned|auto 가 아니다(${JSON.stringify(v.mode)}) — 기본으로 진행`);
2569
+ }
2570
+ if (v.chain !== undefined) {
2571
+ if (!Array.isArray(v.chain)) {
2572
+ warnUserConfigDrop('tools.selfImplement.childLlm.chain', `배열이 아니다(${JSON.stringify(v.chain)}) — 버림`);
2573
+ } else {
2574
+ const chain: ChildLlmChainEntry[] = [];
2575
+ for (const [index, item] of v.chain.entries()) {
2576
+ if (!item || typeof item !== 'object' || Array.isArray(item)) {
2577
+ warnUserConfigDrop('tools.selfImplement.childLlm.chain', `[${index}] 객체가 아니다(${JSON.stringify(item)}) — 건너뜀`);
2578
+ continue;
2579
+ }
2580
+ const entry = item as Record<string, unknown>;
2581
+ if (typeof entry.provider !== 'string' || !entry.provider.trim()) {
2582
+ warnUserConfigDrop('tools.selfImplement.childLlm.chain', `[${index}].provider 가 빈 문자열이 아니다(${JSON.stringify(entry.provider)}) — 건너뜀`);
2583
+ continue;
2584
+ }
2585
+ if (entry.model !== undefined && typeof entry.model !== 'string') {
2586
+ warnUserConfigDrop('tools.selfImplement.childLlm.chain', `[${index}].model 이 문자열이 아니다(${JSON.stringify(entry.model)}) — 건너뜀`);
2587
+ continue;
2588
+ }
2589
+ chain.push({
2590
+ provider: entry.provider,
2591
+ ...(typeof entry.model === 'string' ? { model: entry.model } : {}),
2592
+ });
2593
+ }
2594
+ out.chain = chain;
2595
+ }
2596
+ }
2597
+ // mode 추론은 여기 하지 않는다. provider 가 없으면 auto — model 만 남은 설정도 같다.
2598
+ // 기존 model-only 거절 문면은 발사 경계가 따로 보존한다.
2599
+ // 잘못된 provider 를 버린 뒤에 model 만 남으면 그 거절이 발사를 막는다.
2600
+ // 그 한 줄은 경고로 끝내고 기본으로 진행한다.
2601
+ if (droppedInvalidProvider && out.model !== undefined && out.provider === undefined && out.mode === undefined && out.chain === undefined) {
2602
+ delete out.model;
2603
+ }
2604
+ return Object.keys(out).length > 0 ? out : undefined;
2605
+ }
2606
+
2607
+ export const BUDGET_GATE_ON_SHORTFALL = ['decompose', 'wait-reset', 'next-provider', 'proceed'] as const;
2608
+ export const DEFAULT_BUDGET_GATE: HarnessBudgetGateConfig = {
2609
+ minHeadroomPercent: 15,
2610
+ onShortfall: 'next-provider',
2611
+ maxUsedPercent: { ...DEFAULT_BUDGET_GATE_MAX_USED_PERCENT },
2612
+ };
2613
+
2614
+ function percentInRange(value: unknown): value is number {
2615
+ return typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 100;
2616
+ }
2617
+
2618
+ /** 칸마다 0~100. 범위 밖·비수치는 경고 후 그 칸의 기본. 객체가 아니면 기본 전체. */
2619
+ export function parseBudgetGateMaxUsedPercent(raw: unknown): BudgetGateMaxUsedPercent {
2620
+ const fallback = { ...DEFAULT_BUDGET_GATE_MAX_USED_PERCENT };
2621
+ if (raw === undefined) return fallback;
2622
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
2623
+ warnUserConfigDrop('harness.budgetGate.maxUsedPercent', `객체가 아니다(${JSON.stringify(raw)}) — 기본 ${JSON.stringify(fallback)} 로 진행`);
2624
+ return fallback;
2625
+ }
2626
+ const out: { [provider: string]: number } = { ...fallback };
2627
+ for (const [provider, value] of Object.entries(raw as Record<string, unknown>)) {
2628
+ if (!provider.trim()) continue;
2629
+ if (percentInRange(value)) out[provider] = value;
2630
+ else {
2631
+ const kept = fallback[provider];
2632
+ warnUserConfigDrop(
2633
+ `harness.budgetGate.maxUsedPercent.${provider}`,
2634
+ `0~100 이 아니다(${JSON.stringify(value)}) — ${kept === undefined ? '버림' : `기본 ${kept} 로 진행`}`,
2635
+ );
2636
+ }
2637
+ }
2638
+ return out;
2639
+ }
2640
+
2641
+ /** 범위 밖·모르는 값은 경고와 함께 기본. 섹션이 없어도 기본을 돌려준다. */
2642
+ export function parseHarnessBudgetGate(raw: unknown): HarnessBudgetGateConfig {
2643
+ const fallback = {
2644
+ minHeadroomPercent: DEFAULT_BUDGET_GATE.minHeadroomPercent,
2645
+ onShortfall: DEFAULT_BUDGET_GATE.onShortfall,
2646
+ maxUsedPercent: { ...DEFAULT_BUDGET_GATE_MAX_USED_PERCENT },
2468
2647
  };
2648
+ if (raw === undefined) return fallback;
2649
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
2650
+ warnUserConfigDrop('harness.budgetGate', `객체가 아니다(${JSON.stringify(raw)}) — 기본 ${fallback.minHeadroomPercent}/${fallback.onShortfall} 로 진행`);
2651
+ return fallback;
2652
+ }
2653
+ const v = raw as Record<string, unknown>;
2654
+ let minHeadroomPercent = fallback.minHeadroomPercent;
2655
+ if (v.minHeadroomPercent !== undefined) {
2656
+ const n = v.minHeadroomPercent;
2657
+ if (percentInRange(n)) minHeadroomPercent = n;
2658
+ else warnUserConfigDrop('harness.budgetGate.minHeadroomPercent', `0~100 이 아니다(${JSON.stringify(n)}) — 기본 ${fallback.minHeadroomPercent} 로 진행`);
2659
+ }
2660
+ let onShortfall = fallback.onShortfall;
2661
+ if (v.onShortfall !== undefined) {
2662
+ if ((BUDGET_GATE_ON_SHORTFALL as readonly string[]).includes(v.onShortfall as string)) onShortfall = v.onShortfall as BudgetGateOnShortfall;
2663
+ else warnUserConfigDrop('harness.budgetGate.onShortfall', `허용값이 아니다(${JSON.stringify(v.onShortfall)}) — 기본 ${fallback.onShortfall} 로 진행`);
2664
+ }
2665
+ const maxUsedPercent = parseBudgetGateMaxUsedPercent(v.maxUsedPercent);
2666
+ return { minHeadroomPercent, onShortfall, maxUsedPercent };
2469
2667
  }
2470
2668
 
2471
2669
  function parseRegistryConfig(raw: unknown): RegistryConfig {
@@ -2672,7 +2870,6 @@ export interface VoiceChatConfig {
2672
2870
 
2673
2871
  export type VoiceTelegramReplyMode = 'auto' | 'text' | 'voice';
2674
2872
  export type VoiceTelegramDispatchMode = 'auto-reply' | 'tui-bridge';
2675
- export type VoiceDiscordReplyMode = 'auto' | 'text' | 'voice';
2676
2873
  export type VoiceDiscordChannelListenFilter = 'caller' | 'all';
2677
2874
  export type IntakeAmbientCaptureMode = 'off' | 'suggest' | 'capture';
2678
2875
 
@@ -2694,27 +2891,8 @@ export interface VoiceTelegramConfig {
2694
2891
  voiceLanguage?: string;
2695
2892
  }
2696
2893
 
2697
- /** Where a final PWA voice transcript dispatches.
2698
- * - 'daemon-direct': daemon calls runTurn directly. Response text
2699
- * synthesizes via the daemon TTS provider and emits as DOWNSTREAM_PCM
2700
- * frames to the browser. Usable without TUI.
2701
- * - 'tui-bridge': transcript routes through dashboard voice-input-host
2702
- * so the TUI sees the dictation as if the user typed; auto-TTS
2703
- * mirrors the response back to the browser. Requires dashboard. */
2704
- export type VoicePwaDispatchMode = 'daemon-direct' | 'tui-bridge';
2705
- export type VoiceDiscordDispatchMode = 'auto-reply' | 'tui-bridge';
2706
2894
 
2707
2895
  export interface VoiceDiscordConfig {
2708
- /** Dispatch mode for Discord text DMs.
2709
- * - 'auto-reply' (default): existing LLM/daemon turn path.
2710
- * - 'tui-bridge': inject final text into the live dashboard input. */
2711
- dispatch?: VoiceDiscordDispatchMode;
2712
- /** Reply mode for incoming Discord voice attachments.
2713
- * - 'auto' (default): user voice → voice reply; user text → text reply.
2714
- * - 'text': always text reply.
2715
- * - 'voice': always voice reply.
2716
- * No env fallback — X9 is treated as a user-config-first surface. */
2717
- replyMode?: VoiceDiscordReplyMode;
2718
2896
  /** ISO 639-1 language hint passed to STT for incoming voice
2719
2897
  * attachments. Improves Korean accuracy when set to 'ko'. */
2720
2898
  voiceLanguage?: string;
@@ -2752,11 +2930,7 @@ export interface VoiceDiscordConfig {
2752
2930
  }
2753
2931
 
2754
2932
  export interface VoicePwaConfig {
2755
- /** Dispatch mode for final transcripts received over /v1/voice/ws.
2756
- * Default is 'daemon-direct' — TUI is not assumed. No env fallback —
2757
- * PWA voice is a §1.2 신규 옵션 (sprint 22 · 2026-04-30) and is
2758
- * user-config only. */
2759
- dispatch?: VoicePwaDispatchMode;
2933
+ // 2026-09-26 설정 졸업: `voice.pwa.dispatch` 를 지웠다 — 그 값을 쓰던 `voice-pwa-dispatch.ts` 는 호출처 0(죽은 모듈)이었다.
2760
2934
  }
2761
2935
 
2762
2936
  export interface VoiceConfig {
@@ -2776,6 +2950,7 @@ export interface IntakeSurfaceConfig {
2776
2950
  export interface IntakeConfig {
2777
2951
  telegram: IntakeSurfaceConfig;
2778
2952
  discord: IntakeSurfaceConfig;
2953
+ approvals?: { repo?: string };
2779
2954
  }
2780
2955
 
2781
2956
  /** Hardcoded fallbacks used when neither user config nor env supplies
@@ -2809,22 +2984,10 @@ function normalizeVoiceVadMode(v: unknown): VoiceVadMode {
2809
2984
  if (v === 'local' || v === 'manual') return v;
2810
2985
  return 'server';
2811
2986
  }
2812
- function normalizeVoicePwaDispatch(v: unknown): VoicePwaDispatchMode | undefined {
2813
- if (v === 'daemon-direct' || v === 'tui-bridge') return v;
2814
- return undefined;
2815
- }
2816
2987
  function normalizeVoiceTelegramDispatch(v: unknown): VoiceTelegramDispatchMode | undefined {
2817
2988
  if (v === 'auto-reply' || v === 'tui-bridge') return v;
2818
2989
  return undefined;
2819
2990
  }
2820
- function normalizeVoiceDiscordDispatch(v: unknown): VoiceDiscordDispatchMode | undefined {
2821
- if (v === 'auto-reply' || v === 'tui-bridge') return v;
2822
- return undefined;
2823
- }
2824
- function normalizeVoiceDiscordReplyMode(v: unknown): VoiceDiscordReplyMode | undefined {
2825
- if (v === 'auto' || v === 'text' || v === 'voice') return v;
2826
- return undefined;
2827
- }
2828
2991
  function normalizeVoiceDiscordChannelListenFilter(
2829
2992
  v: unknown,
2830
2993
  ): VoiceDiscordChannelListenFilter | undefined {
@@ -3158,17 +3321,15 @@ export function resolveRoleModel(role: ModelRole, config: UserConfig = getUserCo
3158
3321
  return { model: resolved.model, source };
3159
3322
  }
3160
3323
 
3161
- export function graphAuthoritativeConfigValue(config: Pick<UserConfig, 'raw' | 'tools'>): boolean | undefined {
3162
- const tools = config.raw.tools;
3163
- if (!tools || typeof tools !== 'object' || Array.isArray(tools)) return undefined;
3164
- const selfImplement = (tools as Record<string, unknown>).selfImplement;
3165
- if (!selfImplement || typeof selfImplement !== 'object' || Array.isArray(selfImplement)) return undefined;
3166
- return typeof (selfImplement as Record<string, unknown>).graphAuthoritative === 'boolean'
3167
- ? config.tools.selfImplement.graphAuthoritative
3168
- : undefined;
3169
- }
3170
3324
 
3171
3325
  export interface UserConfig {
3326
+ /** Steward loop: observe-only until an independently approved act implementation exists. */
3327
+ loops?: { steward?: { mode?: 'observe' | 'act'; linearTeam?: string; roles?: Record<string, { maxConcurrent?: number }>; budget?: number; tracks?: Record<string, string> } };
3328
+ /** 🔐 Pod 의 Grok API 키 과금은 명시 opt-in 만. 생략·잘못된 값은 false.
3329
+ * budgetGate 와 같은 `harness` 객체다 — 중복 선언이면 뒤 타입이 앞을 지운다. */
3330
+ harness?: { pod?: { grokApiKeyOptIn: boolean }; budgetGate?: HarnessBudgetGateConfig; defaultRepo?: string; substrate?: 'local' | 'pod'; podPool?: string };
3331
+ /** ☸️ Pod 실행 칸 — `pool` = 기존 기본 풀(`컨텍스트[@ssh호스트][:상한]` 쉼표 · 앞이 우선). harness 실행은 인자·ELANOUS_POD_POOL·harness.podPool 다음으로 읽는다. */
3332
+ pod?: { pool?: string; /** 호스트 Git 미러 디렉터리 — Pod Job 에 읽기 전용으로 마운트한다. */ hostMirror?: string; /** 원격 그라운딩 엔드포인트(호스트 nexus · tailnet 주소) — Pod 가 토큰으로 «질의→인용»만 묻는다(P13). */ groundingUrl?: string };
3172
3333
  skillRouter: SkillRouterConfig;
3173
3334
  llm: LLMConfig;
3174
3335
  skills: SkillsConfig;
@@ -3216,6 +3377,8 @@ export interface UserConfig {
3216
3377
  taste?: TasteConfig;
3217
3378
  /** 웹 검색 프로바이더 게이트(기본 OFF — `isTavilySearchEnabled()` 로만 읽는다). */
3218
3379
  webSearch?: WebSearchConfig;
3380
+ /** OpenDesign 시안 생성. 기본 없음 = 꺼짐. url 이 없으면 클라이언트가 호출하지 않는다. */
3381
+ design?: DesignConfig;
3219
3382
  /** G8 무인 리뷰루프 auto-review 라벨 자동부착 모드(sparse·기본 opt-in). §2b ROADMAP-elanous-is-all. */
3220
3383
  autoReview?: AutoReviewConfig;
3221
3384
  /** 표시·집계 시간대 (IANA 이름 · 예 `Asia/Seoul`). 2026-07-24 신설.
@@ -3255,14 +3418,23 @@ export interface UserConfig {
3255
3418
  * an active auto-mode goal on idle. Off by default: this ignites
3256
3419
  * self-firing turns, so it stays opt-in. */
3257
3420
  dispatch?: { enabled?: boolean };
3258
- /** next-fluent(태스크 완료 시 다음 액션 1-클릭 칩·2026-07-15). 기본 OFF — 켜면 done/failed 페이즈
3259
- * 카드에 mission-fabric 액션(rebuild·split·revise…) 칩 표시. `personas` 켜면 로컬 LLM 이유 부여
3260
- * (기본 결정론·무비용). config-over-env(thunk 로 매 호출 read → 데몬 재시작 불요). */
3261
- nextFluent?: { enabled?: boolean; personas?: boolean; models?: Record<string, string> };
3421
+ /** next-fluent(태스크 완료 시 다음 액션 1-클릭 칩·2026-07-15). 라우트는 늘 켬.
3422
+ * `personas` 켜면 로컬 LLM 이유 부여(기본 결정론·무비용). */
3423
+ nextFluent?: { personas?: boolean; models?: Record<string, string> };
3262
3424
  /** Ops Observability P3 — 셀프교정 자율 경계. health check 크론이 이상 감지 시
3263
3425
  * 자동 개입(재큐/재시작)까지 할지. 기본 disarmed(관측+알림만·HITL). 매매/재부팅은
3264
3426
  * 이 게이트가 armed 여도 항상 제외. 대표 결정 전까지 undefined=false. */
3265
- ops?: { selfHeal?: { armed?: boolean } };
3427
+ ops?: { selfHeal?: { armed?: boolean }; cronRepoRoot?: string };
3428
+ /** 승인 뒤 조율 채널 페이즈 배달(기본 OFF) 및 트랙 에이전트(기본 OFF, 최대 동시 2개). */
3429
+ autopilot?: {
3430
+ trackCourier?: { enabled?: boolean; channelPr?: number; handoffMinutes?: number };
3431
+ trackAgent?: { enabled: boolean; maxConcurrent: number };
3432
+ };
3433
+ /** 하니스 예산 게이트 설정. 판정은 P15 — 여기선 칸만 싣는다. 파서는 항상 기본을 채운다.
3434
+ * 선택이다 — 기존 UserConfig 리터럴이 이 칸 없이 컴파일되게 한다. 해석기는 없으면 기본을 쓴다.
3435
+ * 타입 칸은 위 `harness.budgetGate` 한 곳이다(중복 선언 금지). */
3436
+ /** 그라운딩 출처 레지스트리. 잘못된 항목은 경고와 함께 건너뛴다. 없으면 빈 목록. */
3437
+ grounding?: GroundingConfig;
3266
3438
  raw: Record<string, unknown>;
3267
3439
  // Phase 2 (PLAN-config-unification-elanous-root-2026-05-10):
3268
3440
  // NEXUS schema co-resident at root of `~/.elanous/config.json`.
@@ -3397,8 +3569,7 @@ function parseAutoReviewConfig(raw: unknown): AutoReviewConfig | undefined {
3397
3569
  return Object.keys(out).length > 0 ? out : undefined;
3398
3570
  }
3399
3571
 
3400
- /** Copy `ops`. `ops.selfHeal.armed` is boolean only; anything else is dropped
3401
- * with one warning line and left absent. */
3572
+ /** Parse optional ops fields independently; invalid settings cannot silently select a cron cwd. */
3402
3573
  function parseOpsConfig(raw: unknown): UserConfig['ops'] | undefined {
3403
3574
  if (raw === undefined) return undefined;
3404
3575
  if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
@@ -3406,18 +3577,48 @@ function parseOpsConfig(raw: unknown): UserConfig['ops'] | undefined {
3406
3577
  return undefined;
3407
3578
  }
3408
3579
  const v = raw as Record<string, unknown>;
3409
- if (v.selfHeal === undefined) return undefined;
3410
- if (!v.selfHeal || typeof v.selfHeal !== 'object' || Array.isArray(v.selfHeal)) {
3411
- warnUserConfigDrop('ops.selfHeal', `객체가 아니다(${JSON.stringify(v.selfHeal)}) — 버림`);
3412
- return undefined;
3580
+ const parsed: NonNullable<UserConfig['ops']> = {};
3581
+ if (v.selfHeal !== undefined) {
3582
+ if (!v.selfHeal || typeof v.selfHeal !== 'object' || Array.isArray(v.selfHeal)) {
3583
+ warnUserConfigDrop('ops.selfHeal', `객체가 아니다(${JSON.stringify(v.selfHeal)}) — 버림`);
3584
+ } else {
3585
+ const armed = (v.selfHeal as Record<string, unknown>).armed;
3586
+ if (armed !== undefined) {
3587
+ if (typeof armed === 'boolean') parsed.selfHeal = { armed };
3588
+ else warnUserConfigDrop('ops.selfHeal.armed', `불리언이 아니다(${JSON.stringify(armed)}) — 버림`);
3589
+ }
3590
+ }
3413
3591
  }
3414
- const armed = (v.selfHeal as Record<string, unknown>).armed;
3415
- if (armed === undefined) return undefined;
3416
- if (typeof armed !== 'boolean') {
3417
- warnUserConfigDrop('ops.selfHeal.armed', `불리언이 아니다(${JSON.stringify(armed)}) — 버림`);
3418
- return undefined;
3592
+ if (v.cronRepoRoot !== undefined) {
3593
+ if (typeof v.cronRepoRoot === 'string' && v.cronRepoRoot.trim()) parsed.cronRepoRoot = v.cronRepoRoot.trim();
3594
+ else warnUserConfigDrop('ops.cronRepoRoot', `비어 있거나 문자열이 아니다(${JSON.stringify(v.cronRepoRoot)}) — 버림`);
3595
+ }
3596
+ return Object.keys(parsed).length ? parsed : undefined;
3597
+ }
3598
+
3599
+ function parseAutopilotConfig(raw: unknown): UserConfig['autopilot'] | undefined {
3600
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
3601
+ const values = raw as Record<string, unknown>;
3602
+ const parsed: NonNullable<UserConfig['autopilot']> = {};
3603
+ const courier = values.trackCourier;
3604
+ if (courier && typeof courier === 'object' && !Array.isArray(courier)) {
3605
+ const v = courier as Record<string, unknown>;
3606
+ parsed.trackCourier = {
3607
+ enabled: v.enabled === true,
3608
+ ...(typeof v.channelPr === 'number' && Number.isSafeInteger(v.channelPr) && v.channelPr > 0 ? { channelPr: v.channelPr } : {}),
3609
+ handoffMinutes: typeof v.handoffMinutes === 'number' && Number.isFinite(v.handoffMinutes) && v.handoffMinutes > 0 ? v.handoffMinutes : 60,
3610
+ };
3419
3611
  }
3420
- return { selfHeal: { armed } };
3612
+ const agent = values.trackAgent;
3613
+ if (agent && typeof agent === 'object' && !Array.isArray(agent)) {
3614
+ const v = agent as Record<string, unknown>;
3615
+ parsed.trackAgent = {
3616
+ enabled: v.enabled === true,
3617
+ maxConcurrent: typeof v.maxConcurrent === 'number' && Number.isSafeInteger(v.maxConcurrent) && v.maxConcurrent > 0
3618
+ ? Math.min(v.maxConcurrent, 2) : 2,
3619
+ };
3620
+ }
3621
+ return Object.keys(parsed).length > 0 ? parsed : undefined;
3421
3622
  }
3422
3623
 
3423
3624
  function parseRoleLlmConfig(raw: unknown): RoleLlmConfig | undefined {
@@ -3467,7 +3668,6 @@ function defaultConfig(): UserConfig {
3467
3668
  toolDeny: [],
3468
3669
  rendering: {
3469
3670
  streaming: { ...CHAT_DEFAULTS.rendering.streaming },
3470
- compactBoundary: { ...CHAT_DEFAULTS.rendering.compactBoundary },
3471
3671
  wrap: { ...CHAT_DEFAULTS.rendering.wrap },
3472
3672
  tool: { ...CHAT_DEFAULTS.rendering.tool },
3473
3673
  diff: { ...CHAT_DEFAULTS.rendering.diff },
@@ -3513,6 +3713,8 @@ function defaultConfig(): UserConfig {
3513
3713
  nativeStructure: { ...TOOLS_DEFAULTS.nativeStructure },
3514
3714
  selfImplement: { ...TOOLS_DEFAULTS.selfImplement },
3515
3715
  },
3716
+ harness: { budgetGate: { ...DEFAULT_BUDGET_GATE } },
3717
+ grounding: { sources: [] },
3516
3718
  raw: {},
3517
3719
  };
3518
3720
  }
@@ -3855,6 +4057,26 @@ export const RETIRED_CONFIG_KEYS: readonly RetiredConfigKey[] = [
3855
4057
  { path: 'chat.rendering.tool.inlineOneLine', reason: '읽는 곳이 없다 — 지워도 된다 (2026-09-26 설정 졸업 2)' },
3856
4058
  { path: 'vw.acpResident', reason: '읽는 곳이 없다 — 지워도 된다 (2026-09-26 설정 졸업 2 · vw.acp.resident 도 소비자 없음)' },
3857
4059
  { path: 'discord.sprint21', reason: '읽는 곳이 없다 — 지워도 된다 (2026-09-26 설정 졸업 2 · 런타임 sprint21-runtime 은 호출처 0·휴면)' },
4060
+ { path: 'tools.selfImplement.prEvidenceArtifactEnforce', reason: '차단 스위치 졸업 — PR 근거 관문은 막지 않고 관측만 한다(2026-09-26 설정 졸업 · 한 번도 기본으로 안 켜졌다)' },
4061
+ { path: 'voice.discord.dispatch', reason: '읽는 곳이 없다 — 지워도 된다 (2026-09-26 설정 졸업 2 · 값을 쓰던 디스코드 음성 어댑터는 호출처 0)' },
4062
+ { path: 'voice.discord.replyMode', reason: '읽는 곳이 없다 — 지워도 된다 (2026-09-26 설정 졸업 2 · 값을 쓰던 디스코드 음성 어댑터는 호출처 0)' },
4063
+ { path: 'voice.pwa.dispatch', reason: '읽는 곳이 없다 — 지워도 된다 (2026-09-26 설정 졸업 2 · voice-pwa-dispatch 는 호출처 0)' },
4064
+ { path: 'voice.stt.mode', reason: '타입에 없는 키 — 읽는 곳이 없다 (2026-09-26 설정 졸업 2)' },
4065
+ { path: 'voice.stt.language', reason: '타입에 없는 키 — 읽는 곳이 없다 (2026-09-26 설정 졸업 2)' },
4066
+ // 설정 졸업 1-d(2026-09-26): 3층(트리 파생)은 늘 켠다 — 리더 미지정이면 운영으로 떨어지므로 새 설치의 동작은 같다.
4067
+ { path: 'instance.treeDerivedTest', reason: '늘 켬으로 졸업 — 지워도 된다 (2026-09-26 설정 졸업 1-d)' },
4068
+ { path: 'tools.selfImplement.selfResolveClarifications', reason: '늘 켬으로 졸업 — 지워도 된다 (2026-09-26 설정 졸업 1-c · self author 도 harness 와 같이 되묻기를 자동 답변)' },
4069
+ { path: 'chat.rendering.compactBoundary.enabled', reason: '늘 켜짐 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4070
+ { path: 'chat.rendering.wrap.preserveOsc8', reason: '늘 켜짐 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4071
+ { path: 'chat.rendering.diff.adaptiveBg', reason: '늘 켜짐 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4072
+ { path: 'chat.rendering.diff.syntaxPerHunk', reason: '늘 켜짐 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4073
+ { path: 'chat.rendering.diff.cache', reason: '늘 켜짐 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4074
+ { path: 'chat.rendering.diff.turnSummary', reason: '늘 켜짐 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4075
+ { path: 'chat.rendering.diff.turnBrowser', reason: '늘 켜짐 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4076
+ { path: 'sessionFabric.telegram.reactions', reason: '늘 켬 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4077
+ { path: 'sessionFabric.discord.reactions', reason: '늘 켬 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4078
+ { path: 'nextFluent.enabled', reason: '늘 켬 — 옵션 졸업 (2026-09-26 설정 졸업 1-f)' },
4079
+ { path: 'tools.selfImplement.graphAuthoritative', reason: '2026-09-26 설정 졸업 — 그래프 권위는 항상 켬 · 지워도 된다' },
3858
4080
  ];
3859
4081
 
3860
4082
  /** 설정 원문(JSON 객체)에서 폐기 키가 «있는» 항목만 돌려준다. 순수. */
@@ -3893,6 +4115,37 @@ function observeRetiredConfigKeysOnce(raw: Record<string, unknown>): void {
3893
4115
  } catch { /* observation must never break config loading */ }
3894
4116
  }
3895
4117
 
4118
+ /** Owner tracks the steward may assign (key → what that track owns). The one place the role table lives. */
4119
+ function parseStewardTracks(input: unknown): Record<string, string> | undefined {
4120
+ if (!input || typeof input !== 'object' || Array.isArray(input)) return undefined;
4121
+ const out = Object.fromEntries(Object.entries(input as Record<string, unknown>)
4122
+ .filter((e): e is [string, string] => /^[A-Za-z][\w-]{0,15}$/.test(e[0]) && typeof e[1] === 'string' && e[1].trim().length > 0)
4123
+ .map(([k, v]) => [k, v.trim()]));
4124
+ return Object.keys(out).length ? out : undefined;
4125
+ }
4126
+
4127
+ function parseStewardLoopsConfig(input: unknown): UserConfig['loops'] {
4128
+ if (!input || typeof input !== 'object' || Array.isArray(input)) return undefined;
4129
+ const value = (input as Record<string, unknown>).steward;
4130
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
4131
+ const s = value as Record<string, unknown>;
4132
+ const roles: NonNullable<NonNullable<UserConfig['loops']>['steward']>['roles'] = {};
4133
+ if (s.roles && typeof s.roles === 'object' && !Array.isArray(s.roles)) {
4134
+ for (const [role, entry] of Object.entries(s.roles)) {
4135
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) continue;
4136
+ const max = (entry as Record<string, unknown>).maxConcurrent;
4137
+ if (typeof max === 'number' && Number.isInteger(max) && max >= 0) roles[role] = { maxConcurrent: max };
4138
+ }
4139
+ }
4140
+ return { steward: {
4141
+ mode: s.mode === 'act' ? 'act' : 'observe',
4142
+ ...(typeof s.linearTeam === 'string' && s.linearTeam.trim() ? { linearTeam: s.linearTeam.trim() } : {}),
4143
+ ...(Object.keys(roles).length ? { roles } : {}),
4144
+ ...(typeof s.budget === 'number' && Number.isFinite(s.budget) && s.budget >= 0 ? { budget: s.budget } : {}),
4145
+ ...(parseStewardTracks(s.tracks) ? { tracks: parseStewardTracks(s.tracks)! } : {}),
4146
+ } };
4147
+ }
4148
+
3896
4149
  export function buildUserConfig(path: string = defaultPath()): UserConfig {
3897
4150
  if (!existsSync(path)) return defaultConfigWithRuntimeProvider();
3898
4151
  let raw: unknown;
@@ -3904,6 +4157,9 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
3904
4157
  if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return defaultConfigWithRuntimeProvider();
3905
4158
  const rawObj = raw as Record<string, unknown>;
3906
4159
  observeRetiredConfigKeysOnce(rawObj);
4160
+ const harness = rawObj.harness && typeof rawObj.harness === 'object' && !Array.isArray(rawObj.harness) ? rawObj.harness as Record<string, unknown> : {};
4161
+ const harnessPod = harness.pod && typeof harness.pod === 'object' && !Array.isArray(harness.pod) ? harness.pod as Record<string, unknown> : {};
4162
+ const legacyPod = rawObj.pod && typeof rawObj.pod === 'object' && !Array.isArray(rawObj.pod) ? rawObj.pod as Record<string, unknown> : {};
3907
4163
 
3908
4164
  const sr = (rawObj.skillRouter ?? {}) as Record<string, unknown>;
3909
4165
  let llm = (rawObj.llm ?? {}) as Record<string, unknown>;
@@ -3952,7 +4208,6 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
3952
4208
  const chatSystemPrompt = (chat.systemPrompt ?? {}) as Record<string, unknown>;
3953
4209
  const chatRendering = (chat.rendering ?? {}) as Record<string, unknown>;
3954
4210
  const chatRenderingStreaming = (chatRendering.streaming ?? {}) as Record<string, unknown>;
3955
- const chatRenderingCompactBoundary = (chatRendering.compactBoundary ?? {}) as Record<string, unknown>;
3956
4211
  const chatRenderingWrap = (chatRendering.wrap ?? {}) as Record<string, unknown>;
3957
4212
  const chatRenderingDiff = (chatRendering.diff ?? {}) as Record<string, unknown>;
3958
4213
  const chatRenderingHud = (chatRendering.hud ?? {}) as Record<string, unknown>;
@@ -3969,6 +4224,11 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
3969
4224
  const intakeTelegram = (intake.telegram ?? {}) as Record<string, unknown>;
3970
4225
  const intakeDiscord = (intake.discord ?? {}) as Record<string, unknown>;
3971
4226
  const dash = (rawObj.dashboard ?? {}) as Record<string, unknown>;
4227
+ const retiredModeKeys = (['uiMode', 'defaultMode'] as const)
4228
+ .filter((key) => Object.prototype.hasOwnProperty.call(dash, key));
4229
+ if (retiredModeKeys.length > 0) {
4230
+ debug.log('dashboard.ui-mode', 'retired-config-ignored', { key: retiredModeKeys.join(',') });
4231
+ }
3972
4232
  const dashPromptBank = (dash.promptBank ?? {}) as Record<string, unknown>;
3973
4233
  const vw = (rawObj.vw ?? {}) as Record<string, unknown>;
3974
4234
  const acp = (rawObj.acp ?? {}) as Record<string, unknown>;
@@ -3986,8 +4246,27 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
3986
4246
  ? (rawObj.global as Record<string, unknown>)
3987
4247
  : undefined;
3988
4248
  const rawNotifications = rawGlobalObj?.notifications ?? rawObj.notifications;
4249
+ const autopilotConfig = parseAutopilotConfig(rawObj.autopilot);
4250
+ const stewardLoops = parseStewardLoopsConfig(rawObj.loops);
3989
4251
 
3990
4252
  return {
4253
+ pod: {
4254
+ ...(typeof legacyPod.pool === 'string' && legacyPod.pool.trim() ? { pool: legacyPod.pool.trim() } : {}),
4255
+ ...(typeof legacyPod.hostMirror === 'string' && legacyPod.hostMirror.trim() ? { hostMirror: legacyPod.hostMirror.trim() } : {}),
4256
+ ...(typeof legacyPod.groundingUrl === 'string' ? { groundingUrl: legacyPod.groundingUrl } : {}),
4257
+ },
4258
+ harness: {
4259
+ pod: { grokApiKeyOptIn: harnessPod.grokApiKeyOptIn === true },
4260
+ ...(harness.substrate === 'local' || harness.substrate === 'pod' ? { substrate: harness.substrate } : {}),
4261
+ ...(typeof harness.podPool === 'string' && harness.podPool.trim() ? { podPool: harness.podPool.trim() } : {}),
4262
+ ...(typeof harness.defaultRepo === 'string' && isAbsolute(harness.defaultRepo)
4263
+ ? { defaultRepo: harness.defaultRepo } : {}),
4264
+ budgetGate: parseHarnessBudgetGate(
4265
+ rawObj.harness && typeof rawObj.harness === 'object' && !Array.isArray(rawObj.harness)
4266
+ ? (rawObj.harness as Record<string, unknown>).budgetGate
4267
+ : undefined,
4268
+ ),
4269
+ },
3991
4270
  skillRouter: {
3992
4271
  autoRoute: sr.autoRoute === true,
3993
4272
  autoRouteCountdownMs: clampNum(sr.autoRouteCountdownMs, SR_DEFAULTS.autoRouteCountdownMs, 0, 10000),
@@ -4066,6 +4345,8 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4066
4345
  .filter(([, value]) => typeof value === 'number'))
4067
4346
  : undefined,
4068
4347
  // ⛔ 같은 모양(문자열 배열)이라 아래 fallbackChain 과 «같은 자»를 쓴다.
4348
+ codexCreditsAllowed: llm.codexCreditsAllowed === true ? true : undefined,
4349
+ codexQuotaPolicy: isCodexQuotaPolicy(llm.codexQuotaPolicy) ? llm.codexQuotaPolicy : undefined,
4069
4350
  codexAccountOrder: Array.isArray(llm.codexAccountOrder)
4070
4351
  ? llm.codexAccountOrder.filter((v: unknown): v is string => typeof v === 'string' && v.length > 0)
4071
4352
  : undefined,
@@ -4100,6 +4381,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4100
4381
  },
4101
4382
  obsidian: {
4102
4383
  vault: str(ob.vault) ?? obsidianDefaults().vault,
4384
+ ...(str(ob.testVault) ? { testVault: str(ob.testVault)! } : {}),
4103
4385
  },
4104
4386
  telegram: {
4105
4387
  enabled: tg.enabled === true,
@@ -4110,6 +4392,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4110
4392
  channels: normalizeTelegramChannels(tg.channels),
4111
4393
  testChannel: normalizeTestChannel(tg.testChannel),
4112
4394
  ...(tg.poller === 'standalone' || tg.poller === 'nexus' ? { poller: tg.poller } : {}),
4395
+ ...(normalizeKindRoles(tg.kindRoles) ? { kindRoles: normalizeKindRoles(tg.kindRoles)! } : {}),
4113
4396
  },
4114
4397
  discord: {
4115
4398
  enabled: dc.enabled === true,
@@ -4333,16 +4616,8 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4333
4616
  10_000,
4334
4617
  ),
4335
4618
  },
4336
- compactBoundary: {
4337
- enabled: chatRenderingCompactBoundary.enabled === false
4338
- ? false
4339
- : CHAT_DEFAULTS.rendering.compactBoundary.enabled,
4340
- },
4341
4619
  wrap: {
4342
4620
  urlAware: chatRenderingWrap.urlAware === true,
4343
- preserveOsc8: chatRenderingWrap.preserveOsc8 === false
4344
- ? false
4345
- : CHAT_DEFAULTS.rendering.wrap.preserveOsc8,
4346
4621
  },
4347
4622
  tool: {
4348
4623
  displayMode: normalizeChatRenderingToolDisplayMode(
@@ -4361,22 +4636,7 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4361
4636
  },
4362
4637
  diff: {
4363
4638
  colorTier: normalizeChatRenderingDiffColorTier(chatRenderingDiff.colorTier),
4364
- adaptiveBg: chatRenderingDiff.adaptiveBg === false
4365
- ? false
4366
- : CHAT_DEFAULTS.rendering.diff.adaptiveBg,
4367
- syntaxPerHunk: chatRenderingDiff.syntaxPerHunk === false
4368
- ? false
4369
- : CHAT_DEFAULTS.rendering.diff.syntaxPerHunk,
4370
- cache: chatRenderingDiff.cache === false
4371
- ? false
4372
- : CHAT_DEFAULTS.rendering.diff.cache,
4373
4639
  headerStyle: normalizeChatRenderingDiffHeaderStyle(chatRenderingDiff.headerStyle),
4374
- turnSummary: chatRenderingDiff.turnSummary === false
4375
- ? false
4376
- : CHAT_DEFAULTS.rendering.diff.turnSummary,
4377
- turnBrowser: chatRenderingDiff.turnBrowser === false
4378
- ? false
4379
- : CHAT_DEFAULTS.rendering.diff.turnBrowser,
4380
4640
  turnBrowserHistory: clampNum(
4381
4641
  chatRenderingDiff.turnBrowserHistory,
4382
4642
  CHAT_DEFAULTS.rendering.diff.turnBrowserHistory,
@@ -4461,12 +4721,6 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4461
4721
  ...(typeof voiceChat.multiTurn === 'boolean' ? { multiTurn: voiceChat.multiTurn } : {}),
4462
4722
  },
4463
4723
  discord: {
4464
- ...(normalizeVoiceDiscordDispatch(voiceDiscord.dispatch) !== undefined
4465
- ? { dispatch: normalizeVoiceDiscordDispatch(voiceDiscord.dispatch)! }
4466
- : {}),
4467
- ...(normalizeVoiceDiscordReplyMode(voiceDiscord.replyMode) !== undefined
4468
- ? { replyMode: normalizeVoiceDiscordReplyMode(voiceDiscord.replyMode)! }
4469
- : {}),
4470
4724
  ...(typeof voiceDiscord.voiceLanguage === 'string' && voiceDiscord.voiceLanguage.length > 0
4471
4725
  ? { voiceLanguage: voiceDiscord.voiceLanguage }
4472
4726
  : {}),
@@ -4523,9 +4777,6 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4523
4777
  : {}),
4524
4778
  },
4525
4779
  pwa: {
4526
- ...(normalizeVoicePwaDispatch(voicePwa.dispatch) !== undefined
4527
- ? { dispatch: normalizeVoicePwaDispatch(voicePwa.dispatch)! }
4528
- : {}),
4529
4780
  },
4530
4781
  },
4531
4782
  intake: {
@@ -4539,6 +4790,10 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4539
4790
  ? { ambientCapture: normalizeIntakeAmbientCaptureMode(intakeDiscord.ambientCapture)! }
4540
4791
  : {}),
4541
4792
  },
4793
+ ...(intake.approvals && typeof intake.approvals === 'object' && !Array.isArray(intake.approvals)
4794
+ && typeof (intake.approvals as Record<string, unknown>).repo === 'string'
4795
+ ? { approvals: { repo: (intake.approvals as { repo: string }).repo } }
4796
+ : {}),
4542
4797
  },
4543
4798
  dashboard: {
4544
4799
  views: dash.views && typeof dash.views === 'object' && !Array.isArray(dash.views)
@@ -4547,12 +4802,6 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4547
4802
  theme: dash.theme && typeof dash.theme === 'object' && !Array.isArray(dash.theme)
4548
4803
  ? dash.theme as Record<string, unknown>
4549
4804
  : undefined,
4550
- defaultMode: dash.defaultMode === 'chat' || dash.defaultMode === 'dashboard'
4551
- ? dash.defaultMode
4552
- : undefined,
4553
- uiMode: dash.uiMode === 'essential' || dash.uiMode === 'rich'
4554
- ? dash.uiMode
4555
- : undefined,
4556
4805
  foldMode: dash.foldMode === 'line' || dash.foldMode === 'task-unit' || dash.foldMode === 'kind-unit'
4557
4806
  ? dash.foldMode
4558
4807
  : 'task-unit',
@@ -4624,12 +4873,15 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4624
4873
  goals: parseGoalsConfig(rawObj.goals),
4625
4874
  registry: parseRegistryConfig(rawObj.registry),
4626
4875
  tools: parseToolsConfig(rawObj.tools),
4876
+ ...(stewardLoops ? { loops: stewardLoops } : {}),
4627
4877
  // M1-1: sparse — undefined when the user hasn't set anything, so
4628
4878
  // resolvers fall through to zero-config defaults.
4629
4879
  ...spreadIfDefined('modelTier', parseModelTierConfig(rawObj.modelTier)),
4630
4880
  ...spreadIfDefined('sessionFabric', parseSessionFabricConfig(rawObj.sessionFabric)),
4881
+ ...spreadIfDefined('nextFluent', parseNextFluentConfig(rawObj.nextFluent)),
4631
4882
  ...spreadIfDefined('taste', parseTasteConfig(rawObj.taste)),
4632
4883
  ...spreadIfDefined('webSearch', parseWebSearchConfig(rawObj.webSearch)),
4884
+ ...spreadIfDefined('design', parseDesignConfig(rawObj.design)),
4633
4885
  ...spreadIfDefined('budget', parseBudgetConfig(rawObj.budget)),
4634
4886
  ...spreadIfDefined('smartDefaults', parseSmartDefaultsConfig(rawObj.smartDefaults)),
4635
4887
  ...spreadIfDefined('roleModels', parseRoleModelConfig(rawObj.roleModels)),
@@ -4637,6 +4889,8 @@ export function buildUserConfig(path: string = defaultPath()): UserConfig {
4637
4889
  ...spreadIfDefined('roleLlm', parseRoleLlmConfig(rawObj.roleLlm)),
4638
4890
  ...spreadIfDefined('autoReview', parseAutoReviewConfig(rawObj.autoReview)),
4639
4891
  ...spreadIfDefined('ops', parseOpsConfig(rawObj.ops)),
4892
+ ...(autopilotConfig ? { autopilot: autopilotConfig } : {}),
4893
+ grounding: parseGroundingSources(rawObj.grounding),
4640
4894
  ...spreadIfDefined('notifications', parseNotificationsConfig(rawNotifications)),
4641
4895
  ...spreadIfDefined('mcp', parseMcpConfig(rawObj.mcp)),
4642
4896
  ...spreadIfDefined('backgroundReasoning', parseBackgroundReasoningConfig(rawObj.backgroundReasoning)),
@@ -5139,10 +5393,6 @@ export function saveUserConfig(
5139
5393
  ...CHAT_DEFAULTS.rendering.streaming,
5140
5394
  ...(cfg.chat.rendering?.streaming ?? {}),
5141
5395
  },
5142
- compactBoundary: {
5143
- ...CHAT_DEFAULTS.rendering.compactBoundary,
5144
- ...(cfg.chat.rendering?.compactBoundary ?? {}),
5145
- },
5146
5396
  wrap: {
5147
5397
  ...CHAT_DEFAULTS.rendering.wrap,
5148
5398
  ...(cfg.chat.rendering?.wrap ?? {}),
@@ -5189,11 +5439,29 @@ export function saveUserConfig(
5189
5439
  // parsers; strip from raw so stale copies don't double-write.
5190
5440
  delete rawRest.modelTier;
5191
5441
  delete rawRest.sessionFabric;
5442
+ delete rawRest.nextFluent;
5192
5443
  delete rawRest.taste;
5193
5444
  delete rawRest.budget;
5194
5445
  delete rawRest.smartDefaults;
5446
+ delete rawRest.grounding;
5447
+ const rawHarness = rawRest.harness && typeof rawRest.harness === 'object' && !Array.isArray(rawRest.harness)
5448
+ ? rawRest.harness as Record<string, unknown> : {};
5449
+ delete rawRest.harness;
5450
+ if (cfg.pod?.hostMirror) {
5451
+ const rawPod = rawRest.pod && typeof rawRest.pod === 'object' && !Array.isArray(rawRest.pod)
5452
+ ? rawRest.pod as Record<string, unknown> : {};
5453
+ rawRest.pod = { ...rawPod, hostMirror: cfg.pod.hostMirror };
5454
+ }
5195
5455
 
5196
5456
  const out: Record<string, unknown> = {
5457
+ harness: stripUndef({
5458
+ ...rawHarness,
5459
+ pod: cfg.harness?.pod ?? rawHarness.pod,
5460
+ budgetGate: cfg.harness?.budgetGate ?? rawHarness.budgetGate,
5461
+ defaultRepo: cfg.harness?.defaultRepo ?? rawHarness.defaultRepo,
5462
+ substrate: cfg.harness?.substrate,
5463
+ podPool: cfg.harness?.podPool,
5464
+ }),
5197
5465
  ...rawRest,
5198
5466
  skillRouter: cfg.skillRouter,
5199
5467
  llm: stripUndef({
@@ -5231,6 +5499,9 @@ export function saveUserConfig(
5231
5499
  codexAccountRotationThresholdPercent: cfg.llm.codexAccountRotationThresholdPercent,
5232
5500
  codexAccountRotationThresholdPercentByAccount: cfg.llm.codexAccountRotationThresholdPercentByAccount,
5233
5501
  codexAccountOrder: cfg.llm.codexAccountOrder,
5502
+ // ★ 2026-09-28: 타입·파서에만 넣고 이 whitelist 를 빠뜨려 `config set llm.codexCreditsAllowed true` 가 «직렬화 드롭» 됐다(#21375 직후 운영 실측).
5503
+ codexCreditsAllowed: cfg.llm.codexCreditsAllowed,
5504
+ codexQuotaPolicy: cfg.llm.codexQuotaPolicy,
5234
5505
  fallbackChain: cfg.llm.fallbackChain,
5235
5506
  reviewFallbackModels: cfg.llm.reviewFallbackModels,
5236
5507
  codexStore: cfg.llm.codexStore,
@@ -5265,7 +5536,7 @@ export function saveUserConfig(
5265
5536
  includeClaudePackageSkills: cfg.skills.includeClaudePackageSkills === true ? true : undefined,
5266
5537
  includeClaudePackageCommands: cfg.skills.includeClaudePackageCommands === true ? true : undefined,
5267
5538
  }),
5268
- obsidian: { vault: cfg.obsidian.vault },
5539
+ obsidian: { vault: cfg.obsidian.vault, ...(cfg.obsidian.testVault ? { testVault: cfg.obsidian.testVault } : {}) },
5269
5540
  telegram: stripUndef({
5270
5541
  enabled: cfg.telegram.enabled,
5271
5542
  botToken: cfg.telegram.botToken,
@@ -5364,12 +5635,8 @@ export function saveUserConfig(
5364
5635
  catchUpThresholdLines: chatRendering.streaming.catchUpThresholdLines,
5365
5636
  catchUpAgeMs: chatRendering.streaming.catchUpAgeMs,
5366
5637
  }),
5367
- compactBoundary: stripUndef({
5368
- enabled: chatRendering.compactBoundary.enabled,
5369
- }),
5370
5638
  wrap: stripUndef({
5371
5639
  urlAware: chatRendering.wrap.urlAware,
5372
- preserveOsc8: chatRendering.wrap.preserveOsc8,
5373
5640
  }),
5374
5641
  tool: stripUndef({
5375
5642
  displayMode: chatRendering.tool.displayMode,
@@ -5377,12 +5644,7 @@ export function saveUserConfig(
5377
5644
  }),
5378
5645
  diff: stripUndef({
5379
5646
  colorTier: chatRendering.diff.colorTier,
5380
- adaptiveBg: chatRendering.diff.adaptiveBg,
5381
- syntaxPerHunk: chatRendering.diff.syntaxPerHunk,
5382
- cache: chatRendering.diff.cache,
5383
5647
  headerStyle: chatRendering.diff.headerStyle,
5384
- turnSummary: chatRendering.diff.turnSummary,
5385
- turnBrowser: chatRendering.diff.turnBrowser,
5386
5648
  turnBrowserHistory: chatRendering.diff.turnBrowserHistory,
5387
5649
  turnBrowserMode: chatRendering.diff.turnBrowserMode,
5388
5650
  }),
@@ -5396,10 +5658,6 @@ export function saveUserConfig(
5396
5658
  views: cfg.dashboard.views,
5397
5659
  theme: cfg.dashboard.theme,
5398
5660
  promptBank: cfg.dashboard.promptBank,
5399
- // TUI 부활 T2 — uiMode 런타임 persist(/ui). defaultMode·benchmark 는
5400
- // 종전 serializer 가 드롭하던 latent bug 동반 수리 (round-trip 보존).
5401
- defaultMode: cfg.dashboard.defaultMode,
5402
- uiMode: cfg.dashboard.uiMode,
5403
5661
  foldMode: cfg.dashboard.foldMode,
5404
5662
  benchmark: cfg.dashboard.benchmark,
5405
5663
  enableVirtualWindowSwitchKeys: cfg.dashboard.enableVirtualWindowSwitchKeys,
@@ -5499,10 +5757,15 @@ export function saveUserConfig(
5499
5757
  // users' file clean (no empty modelTier:{} blobs).
5500
5758
  ...(cfg.modelTier ? { modelTier: cfg.modelTier } : {}),
5501
5759
  ...(cfg.sessionFabric ? { sessionFabric: cfg.sessionFabric } : {}),
5760
+ ...(cfg.nextFluent ? { nextFluent: cfg.nextFluent } : {}),
5502
5761
  ...(cfg.taste ? { taste: cfg.taste } : {}),
5503
5762
  ...(cfg.webSearch ? { webSearch: cfg.webSearch } : {}),
5763
+ ...(cfg.design ? { design: cfg.design } : {}),
5504
5764
  ...(cfg.budget ? { budget: cfg.budget } : {}),
5505
5765
  ...(cfg.smartDefaults ? { smartDefaults: cfg.smartDefaults } : {}),
5766
+ ...(cfg.grounding && cfg.grounding.sources.length > 0
5767
+ ? { grounding: { sources: cfg.grounding.sources } }
5768
+ : {}),
5506
5769
  };
5507
5770
  mkdirSync(dirname(path), { recursive: true });
5508
5771
  // FU3: lock-protected atomic write. Path B's patchUserConfig acquires