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
@@ -17,6 +17,8 @@ import { createHash } from 'node:crypto';
17
17
  import { dirname, join } from 'node:path';
18
18
  import { elanousStateRoot } from '../autopilot/state-paths.js';
19
19
  import { prevScheduledFire } from './cron-match.js';
20
+ import { debug } from '../debug/log.js';
21
+ import { deriveScheduleName, ensureScheduleRunsSchema, recordScheduleRun } from './schedule-runs.js';
20
22
 
21
23
  /** 스케줄 레지스트리 DB 정본 경로 — state-dir 존중(lazy · Phase B). prod(ELANOUS_STATE_DIR
22
24
  * 미설정)=`~/.elanous/schedules.db`(무변경) · 격리 test 인스턴스=자기 루트(빈 시작). 종전
@@ -38,6 +40,7 @@ export interface ScheduleRow {
38
40
  category: ScheduleCategory;
39
41
  domain: string | null; // finance | <future>
40
42
  enabled: number;
43
+ disabled_reason?: string | null; // vanished (inventory) | manual (explicit off) | null
41
44
  last_seen: string | null;
42
45
  last_run: string | null;
43
46
  note: string | null;
@@ -59,14 +62,14 @@ export function openSchedulesDb(path: string = schedulesDbPath()): Database {
59
62
  if (path !== ':memory:') mkdirSync(dirname(path), { recursive: true });
60
63
  const db = new Database(path);
61
64
  db.run('PRAGMA busy_timeout = 2000');
62
- const schemaObjects = db.prepare(`SELECT name FROM sqlite_master WHERE name IN ('schedule_registry', 'idx_sched_cat')`).all() as Array<{ name: string }>;
65
+ const schemaObjects = db.prepare(`SELECT name FROM sqlite_master WHERE name IN ('schedule_registry', 'idx_sched_cat', 'schedule_runs', 'idx_schedule_runs_schedule_fired')`).all() as Array<{ name: string }>;
63
66
  const schemaNames = new Set(schemaObjects.map(({ name }) => name));
64
67
  if (!schemaNames.has('schedule_registry')) {
65
68
  db.run(`CREATE TABLE IF NOT EXISTS schedule_registry(
66
69
  id TEXT PRIMARY KEY, name TEXT NOT NULL, source TEXT NOT NULL,
67
70
  cron TEXT, interval_ms INT, command TEXT,
68
71
  category TEXT NOT NULL, domain TEXT,
69
- enabled INT DEFAULT 1, last_seen TEXT, last_run TEXT,
72
+ enabled INT DEFAULT 1, disabled_reason TEXT, last_seen TEXT, last_run TEXT,
70
73
  note TEXT, managed_by TEXT DEFAULT 'manual', raw TEXT,
71
74
  run_via TEXT DEFAULT 'crontab',
72
75
  last_status TEXT, last_exit INT, last_duration_ms INT,
@@ -77,6 +80,7 @@ export function openSchedulesDb(path: string = schedulesDbPath()): Database {
77
80
  // 마이그레이션 — 기존 DB에 없는 컬럼 추가(S2 run_via + 실행관측성 P1).
78
81
  const cols = (db.prepare(`PRAGMA table_info(schedule_registry)`).all() as Array<{ name: string }>).map(c => c.name);
79
82
  if (!cols.includes('run_via')) db.run(`ALTER TABLE schedule_registry ADD COLUMN run_via TEXT DEFAULT 'crontab'`);
83
+ if (!cols.includes('disabled_reason')) db.run(`ALTER TABLE schedule_registry ADD COLUMN disabled_reason TEXT`);
80
84
  // 실행 결과 추적(P1) — "발화만 기록"에서 "성공/실패·소요·경로까지" 확장.
81
85
  if (!cols.includes('last_status')) db.run(`ALTER TABLE schedule_registry ADD COLUMN last_status TEXT`);
82
86
  if (!cols.includes('last_exit')) db.run(`ALTER TABLE schedule_registry ADD COLUMN last_exit INT`);
@@ -85,6 +89,8 @@ export function openSchedulesDb(path: string = schedulesDbPath()): Database {
85
89
  if (!cols.includes('last_error')) db.run(`ALTER TABLE schedule_registry ADD COLUMN last_error TEXT`);
86
90
  // 오토파일럿 계보(AL2) — 이 크론을 만든 미션(apm_id). null=오토파일럿 산물 아님.
87
91
  if (!cols.includes('autopilot_id')) db.run(`ALTER TABLE schedule_registry ADD COLUMN autopilot_id TEXT`);
92
+ // 다시 열 때는 DDL 을 안 돌린다(기존 규칙) — 이력 표·색인이 이미 있으면 건너뛴다.
93
+ if (!schemaNames.has('schedule_runs') || !schemaNames.has('idx_schedule_runs_schedule_fired')) ensureScheduleRunsSchema(db);
88
94
  return db;
89
95
  }
90
96
 
@@ -134,6 +140,7 @@ export interface RunResult {
134
140
  durationMs?: number | null; // 소요(ms)
135
141
  via?: string; // tick | catchup | manual
136
142
  error?: string | null; // 에러 요약(있으면)
143
+ runId?: string | null; // 외부 실행과의 상관관계
137
144
  }
138
145
  /** 직전 실행 상태 조회(자기기억 이상 온셋 dedup 용·데몬 경로). 없으면 null. */
139
146
  export function getLastStatus(db: Database, id: string): string | null {
@@ -142,12 +149,24 @@ export function getLastStatus(db: Database, id: string): string | null {
142
149
  }
143
150
 
144
151
  export function markResult(db: Database, id: string, r: RunResult): void {
152
+ const at = r.at ?? new Date().toISOString();
153
+ const via = r.via ?? 'tick';
145
154
  db.run(
146
155
  `UPDATE schedule_registry SET last_run=?, last_status=?, last_exit=?,
147
156
  last_duration_ms=?, last_via=?, last_error=? WHERE id=?`,
148
- [r.at ?? new Date().toISOString(), r.status, r.exit ?? null,
149
- r.durationMs ?? null, r.via ?? 'tick', r.error ?? null, id],
157
+ [at, r.status, r.exit ?? null,
158
+ r.durationMs ?? null, via, r.error ?? null, id],
150
159
  );
160
+ const row = db.query(`SELECT name FROM schedule_registry WHERE id = ?`).get(id) as { name: string } | null;
161
+ if (!row) return;
162
+ try {
163
+ recordScheduleRun(db, id, {
164
+ at, status: r.status, exit: r.exit ?? null,
165
+ durationMs: r.durationMs ?? null, via, runId: r.runId ?? process.env.ELANOUS_RUN_ID ?? null,
166
+ });
167
+ } catch (error) {
168
+ debug.log('schedule.registry', 'run-history-write-failed', { id, error: String(error) });
169
+ }
151
170
  }
152
171
 
153
172
  // ── 스케줄 헬스(P2 관측성) — "무엇이 밀렸나/실패했나" 순수 판정 ──────────
@@ -268,24 +287,42 @@ export function cronEntryId(cron: string, effectiveCommand: string): string {
268
287
  }
269
288
 
270
289
  /** ★ 관측성 래퍼 unwrap (RFC-scheduler-execution-observability·2026-07-15) — crontab 라인이
271
- * `bun scripts/cron-run.ts scripts/X.ts --a` 로 래핑돼도 id/name 파생은 안쪽 실제 target 기준으로.
272
- * `scripts/cron-run.ts ` 토큰만 제거 → 래핑 전 원본과 동일 문자열 → id(sha1) 불변·마이그레이션 0.
290
+ * `bun scripts/cron-run.ts --schedule-id <id> scripts/X.ts --a` 로 래핑돼도 id/name 파생은 안쪽 실제 target 기준으로.
291
+ * 래퍼와 그 id 인자만 제거 → 래핑 전 원본과 동일 문자열 → id(sha1) 불변·마이그레이션 0.
273
292
  * 순수·멱등(비래핑 라인은 그대로 반환). */
274
293
  export function unwrapCronCommand(command: string): string {
275
- return command.replace(/(?:[^\s]*\/)?cron-run\.ts\s+/, '');
294
+ const shell = command.replace(/(?:\S*\/)?bun\s+(?:\S*\/)?cron-run\.ts\s+(?:--schedule-id\s+\S+\s+)?--shell\s+/, '');
295
+ if (shell !== command) return shell;
296
+ return command.replace(/(?:[^\s]*\/)?cron-run\.ts\s+(?:--schedule-id\s+\S+\s+)?/, '');
276
297
  }
277
298
 
278
- /** crontab 라인을 관측성 래퍼로 감싼다(P3) — `bun scripts/X.ts` → `bun scripts/cron-run.ts scripts/X.ts`.
299
+ /** crontab 라인을 관측성 래퍼로 감싼다(P3) — `bun scripts/X.ts` → `bun scripts/cron-run.ts --schedule-id <id> scripts/X.ts`.
279
300
  * bun .ts 잡만(.sh 는 bun 미실행·skip). 이미 래핑됐거나 cron-run 자신이면 그대로. 순수·멱등. */
280
301
  export function wrapCronLine(line: string): string {
281
302
  if (/cron-run\.ts/.test(line)) return line; // 이미 래핑
303
+ const parsed = parseCronLine(line);
304
+ if (!parsed) return line;
305
+ const id = cronEntryId(parsed.cron, parsed.command);
282
306
  // bun 직후의 target(상대 scripts/X.ts 또는 절대 .../scripts/X.ts) 앞에 래퍼 삽입. cron-run 자신 제외.
283
- return line.replace(/(\bbun\s+)(\S*scripts\/(?!cron-run\b)[\w.-]+\.ts)/, '$1scripts/cron-run.ts $2');
307
+ return line.replace(/(\bbun\s+)(\S*scripts\/(?!cron-run\b)[\w.-]+\.ts)/, (_match, bun: string, target: string) =>
308
+ `${bun}scripts/cron-run.ts --schedule-id ${id} ${target}`);
309
+ }
310
+
311
+ /** 셸 해석기가 명시된 .sh 발화만 래핑한다. 원래 해석기 토큰과 인자를 그대로 보존한다. */
312
+ export function wrapShellCronLine(line: string, opts: { bun: string; cronRun: string }): string {
313
+ if (/cron-run\.ts/.test(line)) return line;
314
+ const parsed = parseCronLine(line);
315
+ if (!parsed) return line;
316
+ const id = cronEntryId(parsed.cron, parsed.command);
317
+ return line.replace(/^(\s*\S+(?:\s+\S+){4}\s+(?:cd\s+\S+\s+&&\s+)?)((?:\S*\/)?(?:bash|zsh|sh))(?=\s+\S+\.sh(?:\s|$))/, (_match, prefix: string, interpreter: string) =>
318
+ `${prefix}${opts.bun} ${opts.cronRun} --schedule-id ${id} --shell ${interpreter}`);
284
319
  }
285
320
 
286
- /** wrapCronLine 역 — 래퍼 제거(가역). 비래핑 라인은 그대로. */
321
+ /** wrapCronLine / wrapShellCronLine 역 — 래퍼와 id 인자 제거(가역). 비래핑 라인은 그대로. */
287
322
  export function unwrapCronLine(line: string): string {
288
- return line.replace(/(\bbun\s+)(?:\S*\/)?cron-run\.ts\s+/, '$1');
323
+ const shell = line.replace(/(?:\S*\/)?bun\s+(?:\S*\/)?cron-run\.ts\s+(?:--schedule-id\s+\S+\s+)?--shell\s+/, '');
324
+ if (shell !== line) return shell;
325
+ return line.replace(/(\bbun\s+)(?:\S*\/)?cron-run\.ts\s+(?:--schedule-id\s+\S+\s+)?/, '$1');
289
326
  }
290
327
 
291
328
  /** ★ 삭제 안전 가드(2026-07-15) — 대상 행의 crontab 라인(raw)을 다른 활성 행이 공유하나? 순수.
@@ -298,9 +335,11 @@ export function sharesCrontabLine(rows: readonly { id: string; raw?: string | nu
298
335
  /** 스크립트 basename 추출 (scripts/foo.ts|sh → foo). 없으면 커맨드 첫 토큰. 래퍼는 unwrap 후 파생. */
299
336
  export function scriptName(command: string): string {
300
337
  const c = unwrapCronCommand(command);
338
+ const noCd = c.replace(/^cd\s+\S+\s*&&\s*/, '');
339
+ const shellTarget = noCd.match(/^(?:\S*\/)?(?:bash|zsh|sh)\s+(\S+\.sh)(?=\s|$)/);
340
+ if (shellTarget) return shellTarget[1]!.split('/').pop()!.replace(/\.sh$/, '');
301
341
  const m = c.match(/scripts\/([\w.-]+?)\.(?:ts|sh|mjs|js)\b/);
302
342
  if (m) return m[1]!;
303
- const noCd = c.replace(/^cd\s+\S+\s*&&\s*/, '');
304
343
  const tokens = noCd.split(/\s+/);
305
344
  // bun/node 런처면 다음 토큰(실 스크립트)을 이름 원천으로 — `bun bin/elanous.mjs` → elanous.mjs(bun 아님).
306
345
  let head = tokens[0] ?? c;
@@ -323,7 +362,10 @@ export function inferCategory(command: string): ScheduleCategory {
323
362
 
324
363
  /** 현재 crontab 원문 반환(없으면 ''). */
325
364
  export function readCrontab(): string {
326
- try { return execFileSync('crontab', ['-l'], { encoding: 'utf-8' }); }
365
+ // ⛔ stderr 를 물려받지 않는다 — 크론이 없는 기계에서 「no crontab for <user>」가 TUI 화면 한가운데 찍혔다
366
+ // (2026-09-26 베어 Ubuntu 26.04 실측 · UX 17). 크론 없음은 정상이라 빈 문자열이다.
367
+ // env 명시 — bun 은 env 없이 부르면 «기동 시» PATH 로 찾는다(시험이 PATH 앞에 둔 가짜 crontab 을 지나쳐 실물을 연다).
368
+ try { return execFileSync('crontab', ['-l'], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'], env: process.env }); }
327
369
  catch { return ''; } // no crontab for user
328
370
  }
329
371
 
@@ -333,7 +375,9 @@ export function readCrontab(): string {
333
375
  export function inventoryCrontab(db: Database, opts: { crontab?: string; now?: string } = {}): { total: number; added: number; disabled: number; vanished: number } {
334
376
  const text = opts.crontab ?? readCrontab();
335
377
  const now = opts.now ?? new Date().toISOString();
336
- const existing = new Set((db.prepare(`SELECT id FROM schedule_registry`).all() as Array<{ id: string }>).map(r => r.id));
378
+ const existing = new Map((db.prepare(`SELECT id, name, command, source, run_via FROM schedule_registry`).all() as Array<{
379
+ id: string; name: string; command: string | null; source: string; run_via: string;
380
+ }>).map(r => [r.id, r]));
337
381
  let total = 0, added = 0, disabled = 0, vanished = 0;
338
382
  const seenIds = new Set<string>();
339
383
  for (const line of text.split('\n')) {
@@ -348,9 +392,9 @@ export function inventoryCrontab(db: Database, opts: { crontab?: string; now?: s
348
392
  const off = parseDisabledCronLine(line);
349
393
  if (!off) continue;
350
394
  const offId = cronEntryId(off.cron, unwrapCronCommand(off.command));
351
- if (!existing.has(offId)) continue;
395
+ if (existing.get(offId)?.source !== 'crontab' || existing.get(offId)?.run_via === 'trigger') continue;
352
396
  seenIds.add(offId);
353
- db.run(`UPDATE schedule_registry SET enabled = 0, last_seen = ? WHERE id = ?`, [now, offId]);
397
+ db.run(`UPDATE schedule_registry SET enabled = 0, disabled_reason = 'manual', last_seen = ? WHERE id = ?`, [now, offId]);
354
398
  disabled++;
355
399
  continue;
356
400
  }
@@ -359,19 +403,32 @@ export function inventoryCrontab(db: Database, opts: { crontab?: string; now?: s
359
403
  // → 래핑 전후 id(sha1) 동일·last_run/계보/adopt 승계·마이그레이션 0. command/raw 는 실제 라인 보존.
360
404
  const eff = unwrapCronCommand(parsed.command);
361
405
  const id = cronEntryId(parsed.cron, eff);
362
- const name = scriptName(eff);
406
+ const prior = existing.get(id);
407
+ const name = prior && prior.command === parsed.command ? prior.name : deriveScheduleName(eff);
363
408
  const category = inferCategory(eff);
364
409
  seenIds.add(id);
365
- if (!existing.has(id)) added++;
410
+ // A lingering crontab line after migration is not a request to override the
411
+ // trigger's state (including an explicit disable). Keep the migrated row intact.
412
+ if (prior?.run_via === 'trigger') continue;
413
+ if (!prior) added++;
366
414
  db.run(
367
415
  `INSERT INTO schedule_registry (id, name, source, cron, command, category, domain, enabled, last_seen, managed_by, raw)
368
416
  VALUES (?, ?, 'crontab', ?, ?, ?, 'finance', 1, ?, 'manual', ?)
369
417
  ON CONFLICT(id) DO UPDATE SET
370
418
  name=excluded.name, cron=excluded.cron, command=excluded.command,
371
- category=excluded.category, enabled=1, last_seen=excluded.last_seen, raw=excluded.raw`,
419
+ category=excluded.category, enabled=1, disabled_reason=NULL, last_seen=excluded.last_seen, raw=excluded.raw`,
372
420
  [id, name, parsed.cron, parsed.command, category, now, line.trim()],
373
421
  );
374
422
  }
423
+ // Only repair rows with recorded inventory provenance. Legacy disabled rows have
424
+ // no disable reason; last_via='trigger' alone cannot distinguish manual disable.
425
+ const repair = db.prepare(`SELECT id FROM schedule_registry WHERE source = 'crontab'
426
+ AND run_via = 'trigger' AND enabled = 0 AND last_via = 'trigger'
427
+ AND disabled_reason = 'vanished'`).all() as Array<{ id: string }>;
428
+ for (const { id } of repair) {
429
+ db.run(`UPDATE schedule_registry SET source = 'trigger', enabled = 1, disabled_reason = NULL WHERE id = ?`, [id]);
430
+ debug.log('schedule.registry', 'trigger-row-repaired', { id });
431
+ }
375
432
  // ⭐ 줄이 통째로 지워진 crontab-origin 행 — 주석도 활성도 아니니 루프가 안 본다.
376
433
  // ⛔ 행을 지우지 않는다(prune 계약). 끄기만 한다.
377
434
  // ⛔ source='crontab' 만 — inventoryInternalSchedules 가 넣는 내부 행은 crontab 에
@@ -379,11 +436,11 @@ export function inventoryCrontab(db: Database, opts: { crontab?: string; now?: s
379
436
  // ⛔ 빈 문자열은 읽기 실패와 같다 — 「전부 사라졌다」로 읽으면 한 번의 실패가 전 스케줄을 끈다.
380
437
  if (text !== '') {
381
438
  const missing = db.prepare(
382
- `SELECT id FROM schedule_registry WHERE source = 'crontab' AND enabled = 1`,
439
+ `SELECT id FROM schedule_registry WHERE source = 'crontab' AND enabled = 1 AND run_via != 'trigger'`,
383
440
  ).all() as Array<{ id: string }>;
384
441
  for (const row of missing) {
385
442
  if (seenIds.has(row.id)) continue;
386
- db.run(`UPDATE schedule_registry SET enabled = 0 WHERE id = ?`, [row.id]);
443
+ db.run(`UPDATE schedule_registry SET enabled = 0, disabled_reason = 'vanished' WHERE id = ?`, [row.id]);
387
444
  vanished++;
388
445
  }
389
446
  }
@@ -534,25 +591,23 @@ export function installedCronRoot(
534
591
  * 크론 `cd` 대상. 🩸 2026-09-24: 전역 `elanous`·데몬이 설치본으로 옮긴 뒤 `import.meta.dir` 는 판 폴더
535
592
  * (`~/.local/share/elanous/versions/<판>/node_modules/elanous`)로 풀린다 — 그 경로를 크론에 박으면
536
593
  * 야간 정리(#20214)가 그 판을 지우는 날 크론이 조용히 죽는다.
537
- * ⇒ 설치본이면 ① 리더 트리(`~/.elanous/leader.json` — 종전 크론이 `cd` 하던 체크아웃) ② 없으면 고정 경로 `current`.
594
+ * ⇒ 설치본이면 설정 `ops.cronRepoRoot` 우선, 없으면 고정 경로 `current`.
538
595
  * 설치본이 아니면(체크아웃) 그대로.
539
596
  */
540
597
  export function cronRepoRoot(
541
598
  codeRoot: string,
542
- deps: { home?: string; exists?: (p: string) => boolean; readLeader?: () => string | null } = {},
599
+ deps: { exists?: (p: string) => boolean; configuredRoot?: () => string | undefined } = {},
543
600
  ): string {
544
601
  const exists = deps.exists ?? existsSync;
545
602
  const m = /^(.*)\/versions\/[^/]+\/node_modules\/elanous\/?$/.exec(codeRoot.replace(/\\/g, '/'));
546
603
  if (!m || hasGitAbove(codeRoot, exists)) return codeRoot;
547
- const home = deps.home ?? homedir();
548
- const leader = (deps.readLeader ?? (() => {
604
+ const configured = (deps.configuredRoot ?? (() => {
549
605
  try {
550
- const raw = JSON.parse(readFileSync(join(home, '.elanous', 'leader.json'), 'utf-8')) as { tree?: unknown };
551
- return typeof raw.tree === 'string' ? raw.tree : null;
552
- } catch { return null; }
553
- }))();
554
- if (leader && exists(leader)) return leader;
555
- return `${m[1]}/current/node_modules/elanous`;
606
+ const { getUserConfig } = require('../user-config.js') as typeof import('../user-config.js');
607
+ return getUserConfig().ops?.cronRepoRoot;
608
+ } catch { return undefined; }
609
+ }))()?.trim();
610
+ return configured || `${m[1]}/current/node_modules/elanous`;
556
611
  }
557
612
 
558
613
  function hasGitAbove(dir: string, exists: (p: string) => boolean): boolean {
@@ -583,7 +638,7 @@ export function buildCronLine(
583
638
  cron: string, command: string,
584
639
  opts: { repo?: string; bun?: string; logName?: string } = {},
585
640
  ): string {
586
- const repo = opts.repo ?? repoRoot();
641
+ const repo = opts.repo ?? repoRoot(); // default cron cwd → cronRepoRoot → ops.cronRepoRoot or installed current
587
642
  const bun = opts.bun ?? process.execPath; // 데몬은 bun 하에서 구동
588
643
  const cmd = command.trim();
589
644
  // cron의 기본 PATH에는 ~/.bun/bin이 없을 수 있다. 직접 실행과 cd/세미콜론 뒤의
@@ -644,6 +699,6 @@ export function applyCrontab(text: string, opts: { backupDir?: string; now?: str
644
699
  const stamp = (opts.now ?? new Date().toISOString()).replace(/[:.]/g, '-');
645
700
  const backup = join(dir, `crontab-cronmanage-${stamp}.bak`);
646
701
  try { writeFileSync(backup, readCrontab()); } catch { /* 최초엔 빈 crontab */ }
647
- execFileSync('crontab', ['-'], { input: text.replace(/\n*$/, '\n'), encoding: 'utf-8' });
702
+ execFileSync('crontab', ['-'], { input: text.replace(/\n*$/, '\n'), encoding: 'utf-8', env: process.env });
648
703
  return backup;
649
704
  }
@@ -0,0 +1,132 @@
1
+ import type { Database } from 'bun:sqlite';
2
+
3
+ /** A fired execution belongs to the stable registry id, not to a derived (and possibly shared) name. */
4
+ export interface ScheduleRun {
5
+ id: number;
6
+ schedule_id: string;
7
+ fired_at: string;
8
+ status: string;
9
+ exit: number | null;
10
+ duration_ms: number | null;
11
+ via: string;
12
+ run_id: string | null;
13
+ log_ref: string | null;
14
+ }
15
+
16
+ export interface ScheduleRunResult {
17
+ at?: string;
18
+ status: string;
19
+ exit?: number | null;
20
+ durationMs?: number | null;
21
+ via?: string;
22
+ runId?: string | null;
23
+ logRef?: string | null;
24
+ }
25
+
26
+ /** Called by the schedules.db opener; also usable with an isolated in-memory Database. */
27
+ export function ensureScheduleRunsSchema(db: Database): void {
28
+ db.run(`CREATE TABLE IF NOT EXISTS schedule_runs (
29
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
30
+ schedule_id TEXT NOT NULL,
31
+ fired_at TEXT NOT NULL,
32
+ status TEXT NOT NULL,
33
+ exit INTEGER,
34
+ duration_ms INTEGER,
35
+ via TEXT NOT NULL,
36
+ run_id TEXT,
37
+ log_ref TEXT
38
+ )`);
39
+ db.run(`CREATE INDEX IF NOT EXISTS idx_schedule_runs_schedule_fired
40
+ ON schedule_runs(schedule_id, fired_at DESC, id DESC)`);
41
+ }
42
+
43
+ function utcScheduleTime(value: string, field: 'at' | 'before' | 'cursor.firedAt'): string {
44
+ const match = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(?:\.\d{1,9})?(?:Z|([+-])(\d\d):(\d\d))$/.exec(value);
45
+ if (!match) throw new RangeError(`${field} must be an ISO timestamp`);
46
+ const [, y, mo, d, h, mi, s, , tzH, tzM] = match;
47
+ const year = Number(y), month = Number(mo), day = Number(d);
48
+ const daysInMonth = [31, year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28,
49
+ 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
50
+ if (month < 1 || month > 12 || day < 1 || day > daysInMonth[month - 1]!
51
+ || Number(h) > 23 || Number(mi) > 59 || Number(s) > 59
52
+ || (tzH !== undefined && (Number(tzH) > 23 || Number(tzM) > 59))
53
+ || !Number.isFinite(Date.parse(value))) {
54
+ throw new RangeError(`${field} must be an ISO timestamp`);
55
+ }
56
+ // 기록 시각(at)은 ms 로 맞춰 저장하고, 조회 경계(before·cursor)는 원문 그대로 SQL julianday 에 넘긴다(ms 아래 자릿수 보존).
57
+ return field === 'at' ? new Date(value).toISOString() : value;
58
+ }
59
+
60
+ /** Append a fire; retain the newest 500 per schedule (including simultaneous fires). */
61
+ export function recordScheduleRun(db: Database, scheduleId: string, result: ScheduleRunResult): void {
62
+ const firedAt = utcScheduleTime(result.at ?? new Date().toISOString(), 'at');
63
+ db.transaction(() => {
64
+ db.run(`INSERT INTO schedule_runs
65
+ (schedule_id, fired_at, status, exit, duration_ms, via, run_id, log_ref)
66
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
67
+ scheduleId, firedAt, result.status,
68
+ result.exit ?? null, result.durationMs ?? null, result.via ?? 'unknown',
69
+ result.runId ?? null, result.logRef ?? null,
70
+ ]);
71
+ db.run(`DELETE FROM schedule_runs WHERE schedule_id = ? AND id NOT IN (
72
+ SELECT id FROM schedule_runs WHERE schedule_id = ?
73
+ ORDER BY fired_at DESC, id DESC LIMIT 500
74
+ )`, [scheduleId, scheduleId]);
75
+ })();
76
+ }
77
+
78
+ /** Exclusive ISO before filter, or a (firedAt, id) cursor for lossless equal-time paging. */
79
+ /** ISO 시각 → 1970 이후 나노초(BigInt) — 오프셋·소수 9자리까지 보존(SQLite julianday 는 ms 아래를 버린다). 못 읽으면 null. */
80
+ function instantNs(value: string): bigint | null {
81
+ const m = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(?:\.(\d{1,9}))?(?:Z|([+-])(\d\d):(\d\d))$/.exec(value);
82
+ if (!m) return null;
83
+ const [, y, mo, d, h, mi, sec, frac = '', sign, tzH = '0', tzM = '0'] = m;
84
+ const ms = Date.UTC(Number(y), Number(mo) - 1, Number(d), Number(h), Number(mi), Number(sec));
85
+ if (!Number.isFinite(ms)) return null;
86
+ const offsetMin = sign ? (sign === '-' ? -1 : 1) * (Number(tzH) * 60 + Number(tzM)) : 0;
87
+ return (BigInt(ms) - BigInt(offsetMin) * 60_000n) * 1_000_000n + BigInt(frac.padEnd(9, '0'));
88
+ }
89
+
90
+ export function listScheduleRuns(
91
+ db: Database, scheduleId: string,
92
+ opts: { limit?: number; before?: string; cursor?: { firedAt: string; id: number } } = {},
93
+ ): ScheduleRun[] {
94
+ const limit = opts.limit ?? 50;
95
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 500) throw new RangeError('limit must be an integer from 1 to 500');
96
+ const before = opts.before === undefined ? undefined : instantNs(utcScheduleTime(opts.before, 'before'));
97
+ const cursor = opts.cursor === undefined ? undefined : {
98
+ ns: instantNs(utcScheduleTime(opts.cursor.firedAt, 'cursor.firedAt')), id: opts.cursor.id,
99
+ };
100
+ if (cursor && (!Number.isSafeInteger(cursor.id) || cursor.id < 1)) throw new RangeError('cursor.id must be a positive safe integer');
101
+ // 표가 아직 없으면(이력 도입 전 DB · 읽기만 하는 경로) 빈 이력이다.
102
+ if (!db.prepare(`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'schedule_runs'`).get()) return [];
103
+ // 스케줄마다 최근 500줄만 남기므로 그 스케줄 행을 모두 읽어 «순간»으로 거르고 정렬한다 — 오프셋·소수 자릿수가 다른 옛 기록이 섞여도 경계가 맞다.
104
+ const rows = db.prepare(`SELECT id, schedule_id, fired_at, status, exit, duration_ms, via, run_id, log_ref
105
+ FROM schedule_runs WHERE schedule_id = ?`).all(scheduleId) as ScheduleRun[];
106
+ const withNs = rows.map((row) => ({ row, ns: instantNs(String(row.fired_at)) }))
107
+ .filter((r): r is { row: ScheduleRun; ns: bigint } => r.ns !== null)
108
+ .filter(({ ns }) => before === undefined || before === null || ns < before)
109
+ .filter(({ row, ns }) => !cursor || cursor.ns === null || ns < cursor.ns || (ns === cursor.ns && Number(row.id) < cursor.id));
110
+ withNs.sort((a, b) => (a.ns === b.ns ? (Number(b.row.id) > Number(a.row.id) ? 1 : -1) : (b.ns > a.ns ? 1 : -1)));
111
+ return withNs.slice(0, limit).map(({ row }) => row);
112
+ }
113
+
114
+ /** Prefer the actual task/subcommand over its shell, Bun, and elanous launchers. */
115
+ export function deriveScheduleName(command: string): string {
116
+ let cmd = command.trim();
117
+ cmd = cmd.replace(/^cd\s+\S+\s*&&\s*/, '');
118
+ cmd = cmd.replace(/^(?:(?:env\s+)?[A-Za-z_][A-Za-z_0-9]*=\S+\s+)+/, '');
119
+ cmd = cmd.replace(/^(?:\S*\/)?(?:bun(?:\s+run)?|node)\s+/, '');
120
+ cmd = cmd.replace(/^(?:\S*\/)?(?:scripts\/)?cron-run\.ts\s+(?:(?:--schedule-id\s+\S+|--shell\s+\S+)\s+)*/, '');
121
+ cmd = cmd.replace(/^(?:\S*\/)?(?:bun(?:\s+run)?|node)\s+/, '');
122
+ cmd = cmd.replace(/^(?:\S*\/)?(?:bash|zsh|sh)\s+/, '');
123
+ cmd = cmd.replace(/^(?:\S*\/)?bin\/elanous\.mjs\s+|^elanous\s+/, '');
124
+ const tokens = cmd.split(/\s+/);
125
+ const head = tokens[0] ?? '';
126
+ if (/\.(?:ts|js|mjs|sh)$/.test(head)) {
127
+ const script = head.split('/').pop()!.replace(/\.(?:ts|js|mjs|sh)$/, '');
128
+ const arg = tokens[1];
129
+ return script === 'bot-routine' && arg && !arg.startsWith('-') ? `${script} ${arg}` : script;
130
+ }
131
+ return tokens.slice(0, head === 'harness' ? 3 : 2).filter(Boolean).join(' ') || command.trim();
132
+ }
@@ -0,0 +1,152 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { cronMatches, matchField } from './cron-match.js';
3
+ import { calendarFields, resolveTimeZone } from '../time/format.js';
4
+ import { parseCronLine, unwrapCronCommand, type ScheduleRow } from './schedule-registry.js';
5
+
6
+ export type ScheduleState = 'live' | 'firing' | 'stale' | 'off';
7
+ /** Next scheduled instants in the runner's configured timezone, including DST folds/gaps. */
8
+ export function nextRuns(cron: string, now: Date, count = 5, opts?: { timeZone?: string }): string[] {
9
+ const fields = cron.trim().split(/\s+/);
10
+ if (fields.length !== 5 || !fields.every(f => /^[\d*,\-/]+$/.test(f)) ||
11
+ !Number.isFinite(now.getTime()) || !Number.isInteger(count) || count < 1) return [];
12
+ const [minute, hour, dom, month, dow] = fields as [string, string, string, string, string];
13
+ if (count > 5) return [];
14
+ const minutes = Array.from({ length: 60 }, (_, i) => i).filter(i => matchField(minute, i, 0, 59));
15
+ const hours = Array.from({ length: 24 }, (_, i) => i).filter(i => matchField(hour, i, 0, 23));
16
+ if (!minutes.length || !hours.length || !Array.from({ length: 12 }, (_, i) => i + 1).some(i => matchField(month, i, 1, 12))) return [];
17
+ const timeZone = opts?.timeZone ?? resolveTimeZone().timeZone;
18
+ const start = calendarFields(now, { timeZone });
19
+ const result: number[] = [];
20
+ // Five leap-day occurrences can span 20 years. For the API's count=5,
21
+ // even impossible dates require only ~14,600 cheap calendar checks.
22
+ const firstDay = Date.UTC(start.year, start.month - 1, start.day);
23
+ const endDay = Date.UTC(start.year + Math.max(6, Math.min(count, 5) * 8), start.month - 1, start.day);
24
+ for (let day = firstDay; day < endDay && result.length < count; day += 86_400_000) {
25
+ const date = new Date(day);
26
+ const mon = date.getUTCMonth() + 1, dateNum = date.getUTCDate();
27
+ if (!matchField(month, mon, 1, 12)) continue;
28
+ const weekday = date.getUTCDay();
29
+ const domMatches = matchField(dom, dateNum, 1, 31);
30
+ const dowMatches = matchField(dow.replace(/7/g, '0'), weekday, 0, 6);
31
+ if (dom !== '*' && dow !== '*' ? !(domMatches || dowMatches) : !(domMatches && dowMatches)) continue;
32
+
33
+ // UTC noon of this wall date and its neighbors cover ordinary DST folds/gaps.
34
+ // Validate each projected instant with the runner's canonical cron matcher.
35
+ const offsets = new Set<number>();
36
+ for (const delta of [-12, 12, 36]) {
37
+ const sample = day + delta * 3_600_000;
38
+ const wall = calendarFields(new Date(sample), { timeZone });
39
+ offsets.add((Date.UTC(wall.year, wall.month - 1, wall.day, wall.hour, wall.minute) - sample) / 60_000);
40
+ }
41
+ const candidates: number[] = [];
42
+ for (const h of hours) for (const m of minutes) {
43
+ const wallMs = day + h * 3_600_000 + m * 60_000;
44
+ for (const offset of offsets) {
45
+ const ms = wallMs - offset * 60_000;
46
+ if (ms > now.getTime()) candidates.push(ms);
47
+ }
48
+ }
49
+ candidates.sort((a, b) => a - b);
50
+ for (const ms of candidates) {
51
+ if (ms === result[result.length - 1]) continue;
52
+ if (cronMatches(cron, new Date(ms), { timeZone })) result.push(ms);
53
+ if (result.length === count) break;
54
+ }
55
+ }
56
+ return result.map(ms => new Date(ms).toISOString());
57
+ }
58
+
59
+ function futureRuns(row: ScheduleRow, now: Date): string[] {
60
+ if (row.cron) return nextRuns(row.cron, now, 5);
61
+ if (row.interval_ms && row.interval_ms > 0) {
62
+ const origin = row.last_run ? Date.parse(row.last_run) : now.getTime();
63
+ const base = Number.isFinite(origin) ? origin : now.getTime();
64
+ const first = base + (Math.floor((now.getTime() - base) / row.interval_ms) + 1) * row.interval_ms;
65
+ return Array.from({ length: 5 }, (_, i) => new Date(first + i * row.interval_ms!).toISOString());
66
+ }
67
+ return [];
68
+ }
69
+
70
+ /** Only actual scheduler ownership confers liveness; registry.enabled is not evidence. */
71
+ export function computeScheduleState({ row, crontabLines, triggerRegistered, launchdLoaded, now, nextRuns: upcoming, timeZone }: {
72
+ row: ScheduleRow;
73
+ crontabLines: readonly string[];
74
+ triggerRegistered: boolean;
75
+ launchdLoaded: boolean;
76
+ now: Date;
77
+ nextRuns: readonly string[];
78
+ timeZone?: string;
79
+ }): ScheduleState {
80
+ const inCrontab = crontabLines.some(line => {
81
+ const parsed = parseCronLine(line);
82
+ return !!parsed && parsed.cron === row.cron &&
83
+ (unwrapCronCommand(parsed.command).trim() === unwrapCronCommand(row.command ?? '').trim() ||
84
+ (!!row.raw && line.trim() === row.raw.trim()));
85
+ });
86
+ const owned = inCrontab || triggerRegistered || launchdLoaded;
87
+ if (!owned) return 'off';
88
+ const last = row.last_run ? Date.parse(row.last_run) : NaN;
89
+ const interval = row.interval_ms && row.interval_ms > 0 ? row.interval_ms : null;
90
+ const first = upcoming.length ? Date.parse(upcoming[0]!) : NaN;
91
+ const second = upcoming.length > 1 ? Date.parse(upcoming[1]!) : NaN;
92
+ const period = interval ?? (Number.isFinite(first) && Number.isFinite(second) ? second - first : null);
93
+ // No recorded fire means a miss cannot be measured — that is `no-history` (a card flag), not `stale` (a suspected miss).
94
+ if (!Number.isFinite(last)) return 'live';
95
+ if (row.cron) {
96
+ // Only due instants after the last fire can be missed. In particular, a
97
+ // weekday cron has no missing fires over the weekend, however long it is.
98
+ const due = nextRuns(row.cron, new Date(last), 3, { timeZone });
99
+ if (due.length === 3 && Date.parse(due[2]!) <= now.getTime()) return 'stale';
100
+ } else if (period && period > 0 && now.getTime() - last > 2 * period) return 'stale';
101
+ if (period && period > 0 && now.getTime() - last <= period) return 'firing';
102
+ return 'live';
103
+ }
104
+
105
+ function normalizedCommand(command: string | null): string {
106
+ return unwrapCronCommand(command ?? '').trim()
107
+ .replace(/\s*>>?\s*\S+(?:\s+2>&1)?\s*$/, '')
108
+ .replace(/^(?:cd\s+\S+\s*&&\s*)?(?:\S*\/)?(?:bun|node)\s+/, '')
109
+ .replace(/\s+/g, ' ');
110
+ }
111
+
112
+ /** Mark every concurrently owned copy, not historical/off copies. */
113
+ export function findDuplicates<T extends { command: string | null; state: ScheduleState; flags?: string[] }>(rows: T[]): T[] {
114
+ const byCommand = new Map<string, T[]>();
115
+ for (const row of rows) {
116
+ if (row.state === 'off') continue;
117
+ const key = normalizedCommand(row.command);
118
+ if (key) byCommand.set(key, [...(byCommand.get(key) ?? []), row]);
119
+ }
120
+ for (const group of byCommand.values()) {
121
+ if (group.length < 2) continue;
122
+ for (const row of group) row.flags = [...new Set([...(row.flags ?? []), 'duplicate'])];
123
+ }
124
+ return rows;
125
+ }
126
+
127
+ export function displayName(command: string): string {
128
+ let text = command.trim().replace(/^cd\s+(?:'[^']+'|"[^"]+"|\S+)\s*&&\s*/, '');
129
+ text = text.replace(/^(?:(?:export\s+)?[\w]+=(?:'[^']*'|"[^"]*"|\S+)\s+)+/, '');
130
+ text = text.replace(/^(?:\S*\/)?(?:bun|node)\s+/, '');
131
+ text = text.replace(/^(?:\S*\/)?scripts\/cron-run\.ts\s+(?:--shell\s+(?:bash|sh|zsh)\s+)?/, '');
132
+ text = text.replace(/^(?:\S*\/)?bin\/elanous\.mjs\s*/, '');
133
+ text = text.replace(/^(?:\S*\/)?scripts\//, 'scripts/');
134
+ text = text.replace(/^elanous\s+/, '');
135
+ return text.replace(/\s*>>?\s*\S+(?:\s+2>&1)?\s*$/, '').trim() || command.trim();
136
+ }
137
+
138
+ export interface LaunchdEntry { label: string; pid: number | null; lastExit: number | null }
139
+
140
+ /** launchctl list only; never load/unload services. */
141
+ export function listLaunchdElanous({ run = () => execFileSync('launchctl', ['list'], { encoding: 'utf8' }) }: {
142
+ run?: () => string;
143
+ } = {}): LaunchdEntry[] {
144
+ try {
145
+ return run().split('\n').slice(1).map(line => {
146
+ const m = /^\s*(-|\d+)\s+(-|\d+)\s+(com\.elanous\.[^\s]+)\s*$/.exec(line);
147
+ return m ? { label: m[3]!, pid: m[1] === '-' ? null : Number(m[1]), lastExit: m[2] === '-' ? null : Number(m[2]) } : null;
148
+ }).filter((entry): entry is LaunchdEntry => entry !== null);
149
+ } catch { return []; }
150
+ }
151
+
152
+ export { futureRuns };
@@ -0,0 +1,21 @@
1
+ // 발송 목적(kind) → 텔레그램 채널 역할 · 대상. 가벼운 모듈(telegram.ts 를 import 하지 않는다 — outbound-alert 순환 방지).
2
+ // 표에 없는 kind 는 undefined → 부르는 쪽이 옛 reportChannel 로 간다(투자 알림 등 기존 동작 그대로).
3
+ import type { UserConfig } from '../user-config.js';
4
+ import { channelForRole, resolveTelegramChannels } from './telegram-channels.js';
5
+
6
+ export const DEFAULT_KIND_ROLES: Readonly<Record<string, string>> = {
7
+ intake: 'system', 'ops-report': 'system', 'ops-alert': 'system', 'ops-health': 'system',
8
+ };
9
+
10
+ export function roleForKind(cfg: UserConfig, kind?: string): string | undefined {
11
+ if (!kind) return undefined;
12
+ return cfg.telegram.kindRoles?.[kind] ?? DEFAULT_KIND_ROLES[kind];
13
+ }
14
+
15
+ /** The channel for a purpose kind — only with explicit `telegram.channels` and a mapped role. */
16
+ export function kindRouteTarget(cfg: UserConfig, kind?: string): { botToken: string; chatId: number } | null {
17
+ const role = roleForKind(cfg, kind);
18
+ if (!role || !cfg.telegram.channels?.length) return null;
19
+ const ch = channelForRole(resolveTelegramChannels(cfg.telegram), role);
20
+ return ch?.botToken && Number.isFinite(ch.chatId) ? { botToken: ch.botToken, chatId: ch.chatId } : null;
21
+ }
@@ -11,9 +11,7 @@
11
11
  // tool:Bash → { kind:'tool', id:'Bash' }
12
12
  //
13
13
  // Permissive: accepts optional leading '@'. Unknown prefixes return null
14
- // so callers can fall back to kind-specific legacy parsers (e.g.
15
- // virtual-windows/addressing.ts still handles bare `pane:hex` +
16
- // combined `win:N/pane:hex` forms).
14
+ // so callers can fall back to kind-specific parsers.
17
15
 
18
16
  import { ADDR_PREFIX_TO_KIND, KIND_PREFIX, type ElementKind, type ParsedElementAddress } from './types.js';
19
17