elanous 0.2.10 → 0.2.12

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 (615) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/-6XrAoD3eU7NyMHAE4xPS/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1147-466ec15afacc1a65.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1394-ee3795b112907122.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
  8. package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/3869-3cd46526879f454c.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
  18. package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
  19. package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
  24. package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/7277-0b2fc7c16ba2d64b.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/7758-0b018a9e4fc56200.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8605-0259994816604c49.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
  47. package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/9920-5cfdc5e8fd209825.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/app/approvals/page-cb169620945d1952.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cefe8169e36cf62a.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/board/page-d2e35228bc497119.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-5c05b0da4bc1392c.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/app/bots/page-e0ccdb576812b523.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/chat/page-813c4a52c9d05ca8.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/consult/page-4731f2c215358937.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/control/page-a022b257950f39e6.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/design-check/page-a2ffc717e04b8b0a.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/editor/page-b59ee4e70fc18fcf.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/exec/page-a67e11ba962337b5.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/field/page-c172dabd796eb7a3.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/app/inside/page-1efd0cb9e0ed9d13.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/intake/page-d5dc7ff69a37b4cf.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/layout-e71c84189e8c683e.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/live/page-1d6a533ce5a6efcb.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/market/page-dfca9b7d2de0b135.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-793fa536b3a6ef37.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/morning/page-6dd3bfbbde2a5c2c.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/app/not-found-490653e8d4cc8852.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/observatory/page-77447356baad75d2.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-29e961191f6057df.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-c822f55b884d9104.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fa4ccfc432424e52.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/outputs/page-6d604227e1664b71.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/page-9c7e8f744a765daf.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/reflection/page-4048543b4b7ad5e0.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4c3a3126abed551a.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/sessions/page-64b0aecb1ca75e75.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4292d0149020e8a7.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/settings/page-db14d0be7f1c460c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-e5d8072cd7cfef73.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/app/setup/page-9547b5cec7cf76bf.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/share/page-e6dcb83265530636.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/showroom/page-45248f08d6aecae5.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/app/tasks/page-2cddeb9e2aeedc55.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/app/term/page-e297866051595d81.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/app/today/page-baba2e047872fb0f.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/app/trace/page-e895da4ec9cac345.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/app/vault/page-4344faf20216233b.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-698bb29f11864b89.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/app/workflows/page-bd6a6dc1ddc273f2.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2e9e2fb01c9da1c9.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d62ceb13411ebba4.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → f48170cc-d05d28bf87a43bf4.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +1 -0
  105. package/apps/pwa/out/_next/static/css/128fb7fb670b2fbf.css +1 -0
  106. package/apps/pwa/out/approvals/index.html +1 -1
  107. package/apps/pwa/out/approvals/index.txt +23 -23
  108. package/apps/pwa/out/autopilot/index.html +1 -1
  109. package/apps/pwa/out/autopilot/index.txt +23 -23
  110. package/apps/pwa/out/board/index.html +1 -1
  111. package/apps/pwa/out/board/index.txt +23 -23
  112. package/apps/pwa/out/botlab/index.html +1 -1
  113. package/apps/pwa/out/botlab/index.txt +22 -22
  114. package/apps/pwa/out/bots/index.html +1 -1
  115. package/apps/pwa/out/bots/index.txt +22 -22
  116. package/apps/pwa/out/chat/index.html +1 -1
  117. package/apps/pwa/out/chat/index.txt +22 -22
  118. package/apps/pwa/out/consult/index.html +1 -1
  119. package/apps/pwa/out/consult/index.txt +23 -23
  120. package/apps/pwa/out/control/index.html +1 -1
  121. package/apps/pwa/out/control/index.txt +23 -23
  122. package/apps/pwa/out/design-check/index.html +1 -1
  123. package/apps/pwa/out/design-check/index.txt +23 -23
  124. package/apps/pwa/out/editor/index.html +1 -1
  125. package/apps/pwa/out/editor/index.txt +23 -23
  126. package/apps/pwa/out/exec/index.html +1 -1
  127. package/apps/pwa/out/exec/index.txt +23 -23
  128. package/apps/pwa/out/field/index.html +1 -1
  129. package/apps/pwa/out/field/index.txt +23 -23
  130. package/apps/pwa/out/healthz +1 -1
  131. package/apps/pwa/out/index.html +1 -1
  132. package/apps/pwa/out/index.txt +22 -22
  133. package/apps/pwa/out/inside/index.html +1 -0
  134. package/apps/pwa/out/inside/index.txt +31 -0
  135. package/apps/pwa/out/intake/index.html +1 -1
  136. package/apps/pwa/out/intake/index.txt +23 -23
  137. package/apps/pwa/out/live/index.html +1 -1
  138. package/apps/pwa/out/live/index.txt +23 -23
  139. package/apps/pwa/out/market/index.html +1 -1
  140. package/apps/pwa/out/market/index.txt +22 -22
  141. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  142. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  143. package/apps/pwa/out/morning/index.html +1 -1
  144. package/apps/pwa/out/morning/index.txt +23 -23
  145. package/apps/pwa/out/observatory/index.html +1 -1
  146. package/apps/pwa/out/observatory/index.txt +23 -23
  147. package/apps/pwa/out/ops/checklist/index.html +1 -1
  148. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  149. package/apps/pwa/out/ops/release/index.html +1 -1
  150. package/apps/pwa/out/ops/release/index.txt +22 -22
  151. package/apps/pwa/out/ops/seats/index.html +1 -1
  152. package/apps/pwa/out/ops/seats/index.txt +22 -22
  153. package/apps/pwa/out/outputs/index.html +1 -0
  154. package/apps/pwa/out/outputs/index.txt +30 -0
  155. package/apps/pwa/out/reflection/index.html +1 -1
  156. package/apps/pwa/out/reflection/index.txt +23 -23
  157. package/apps/pwa/out/scheduler/index.html +1 -1
  158. package/apps/pwa/out/scheduler/index.txt +23 -23
  159. package/apps/pwa/out/sessions/index.html +1 -1
  160. package/apps/pwa/out/sessions/index.txt +22 -22
  161. package/apps/pwa/out/settings/devices/index.html +1 -1
  162. package/apps/pwa/out/settings/devices/index.txt +23 -23
  163. package/apps/pwa/out/settings/index.html +1 -1
  164. package/apps/pwa/out/settings/index.txt +23 -23
  165. package/apps/pwa/out/setup/done/index.html +1 -1
  166. package/apps/pwa/out/setup/done/index.txt +23 -23
  167. package/apps/pwa/out/setup/index.html +1 -1
  168. package/apps/pwa/out/setup/index.txt +23 -23
  169. package/apps/pwa/out/share/index.html +1 -1
  170. package/apps/pwa/out/share/index.txt +23 -23
  171. package/apps/pwa/out/showroom/index.html +1 -1
  172. package/apps/pwa/out/showroom/index.txt +22 -22
  173. package/apps/pwa/out/tasks/index.html +1 -1
  174. package/apps/pwa/out/tasks/index.txt +23 -23
  175. package/apps/pwa/out/term/index.html +1 -1
  176. package/apps/pwa/out/term/index.txt +23 -24
  177. package/apps/pwa/out/today/index.html +1 -1
  178. package/apps/pwa/out/today/index.txt +23 -23
  179. package/apps/pwa/out/trace/index.html +1 -1
  180. package/apps/pwa/out/trace/index.txt +23 -23
  181. package/apps/pwa/out/vault/index.html +1 -1
  182. package/apps/pwa/out/vault/index.txt +23 -23
  183. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  184. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  185. package/apps/pwa/out/workflows/index.html +1 -1
  186. package/apps/pwa/out/workflows/index.txt +23 -23
  187. package/apps/pwa/out/workspace/index.html +1 -1
  188. package/apps/pwa/out/workspace/index.txt +23 -24
  189. package/apps/pwa/out/worktrees/index.html +1 -1
  190. package/apps/pwa/out/worktrees/index.txt +23 -23
  191. package/graphs/context/nightly-condense.yaml +21 -0
  192. package/graphs/context/recipes.yaml +12 -0
  193. package/graphs/demo/inside-seed.yaml +20 -0
  194. package/graphs/demo/recipes.yaml +12 -0
  195. package/graphs/drafts/draft-cleanup.yaml +19 -0
  196. package/graphs/drafts/recipes.yaml +23 -0
  197. package/graphs/intake/intake-daily.yaml +2 -1
  198. package/graphs/ops/recipes.yaml +3 -0
  199. package/graphs/ops/secret-exposure.yaml +24 -0
  200. package/graphs/release/recipes.yaml +3 -0
  201. package/graphs/release/release-loop.yaml +4 -1
  202. package/graphs/video/explainer-line.yaml +2 -2
  203. package/package.json +2 -1
  204. package/plugins/card-followup/examples/sample-card.png +0 -0
  205. package/plugins/elanous-hwp/README.md +25 -0
  206. package/plugins/elanous-hwp/cli.ts +22 -0
  207. package/plugins/elanous-hwp/converter.ts +237 -0
  208. package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
  209. package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
  210. package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
  211. package/plugins/elanous-hwp/plugin.json +16 -0
  212. package/plugins/elanous-hwp/plugin.ts +40 -0
  213. package/scripts/ci-public-export-leak-gate.ts +75 -14
  214. package/scripts/ci-public-leak-gate.ts +44 -9
  215. package/scripts/context-hooks/claude-stop.sh +4 -0
  216. package/scripts/context-hooks/emit.ts +24 -0
  217. package/scripts/context-hooks/post-tool-use.sh +4 -0
  218. package/scripts/coord-channel-watch.sh +12 -0
  219. package/scripts/coord-requests-bridge.ts +143 -0
  220. package/scripts/field-feed/lib.ts +4 -0
  221. package/scripts/fleet/node-setup.sh +20 -3
  222. package/scripts/homebrew-formula-bump.ts +69 -0
  223. package/scripts/lib/telegram-inject-args.ts +31 -0
  224. package/scripts/marketing/measure-site-numbers.ts +169 -0
  225. package/scripts/measure-gate-shards.ts +309 -0
  226. package/scripts/measure-pod-memory-by-goal.ts +130 -0
  227. package/scripts/mission-request-judge.ts +31 -1
  228. package/scripts/morning-report.ts +2 -2
  229. package/scripts/opportunity-scan.ts +1 -1
  230. package/scripts/release-loop/auto-approve-node.ts +21 -4
  231. package/scripts/release-loop/checklist-gate-node.ts +2 -1
  232. package/scripts/release-loop/cut-branch.ts +84 -0
  233. package/scripts/release-loop/gate-node.ts +22 -15
  234. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  235. package/scripts/release-loop/node-verdict.ts +3 -3
  236. package/scripts/release-loop/ops-upgrade-node.ts +47 -6
  237. package/scripts/release-loop/publish-node.ts +4 -1
  238. package/scripts/release-loop/tui-node-checks.ts +42 -0
  239. package/scripts/release-loop/tui-sim-node.ts +32 -8
  240. package/scripts/release-loop/unattended-release.ts +5 -3
  241. package/scripts/release-loop/version-node.ts +74 -13
  242. package/scripts/signal-digest-cycle.ts +2 -7
  243. package/scripts/signal-digest-photo.ts +11 -0
  244. package/scripts/tech1-public-measure.ts +94 -0
  245. package/scripts/telegram-inject.ts +14 -6
  246. package/scripts/test-diet/node.ts +1 -1
  247. package/scripts/test-diet/remeasure-list.ts +112 -0
  248. package/scripts/tui-regress.ts +2 -2
  249. package/scripts/ux/demo-rehearsal.ts +247 -0
  250. package/scripts/ux/demo-seed.ts +108 -0
  251. package/scripts/ux/lib/rehearsal-verdict.ts +80 -0
  252. package/skills/diagram-master/SKILL.md +366 -0
  253. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  254. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  255. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  256. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  257. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  258. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  259. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  260. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  261. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  262. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  263. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  264. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  265. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  266. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  267. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  268. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  269. package/skills/diagram-master/references/examples/README.md +69 -0
  270. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  271. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  272. package/skills/diagram-master/references/pyproject.toml +16 -0
  273. package/skills/diagram-master/references/quality-checklist.md +33 -0
  274. package/skills/diagram-master/references/routing-guide.md +164 -0
  275. package/skills/diagram-master/references/uv.lock +1356 -0
  276. package/skills/google-workspace/SKILL.md +33 -0
  277. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  278. package/skills/grill-me/SKILL.md +1 -1
  279. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  280. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  281. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  282. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  283. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  284. package/skills/omni-crawl/SKILL.md +21 -11
  285. package/skills/omni-crawl/scripts/main.ts +6 -6
  286. package/skills/omni-crawl/src/router.ts +3 -3
  287. package/skills/omni-digest/SKILL.md +17 -9
  288. package/skills/omni-digest/digest.md +2 -2
  289. package/skills/omni-digest/src/fetch.ts +30 -3
  290. package/skills/pitch-deck/SKILL.md +2 -2
  291. package/skills/pitch-deck/template.html +2 -2
  292. package/skills/youtube-master/SKILL.md +163 -0
  293. package/skills/youtube-master/package-lock.json +558 -0
  294. package/skills/youtube-master/package.json +13 -0
  295. package/skills/youtube-master/references/study-note-template.md +124 -0
  296. package/skills/youtube-master/scripts/main.ts +435 -0
  297. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  298. package/skills/youtube-master/src/audio.ts +63 -0
  299. package/skills/youtube-master/src/domain-staging.ts +50 -0
  300. package/skills/youtube-master/src/env.ts +36 -0
  301. package/skills/youtube-master/src/obsidian.ts +155 -0
  302. package/skills/youtube-master/src/router.ts +110 -0
  303. package/skills/youtube-master/src/stt.ts +199 -0
  304. package/skills/youtube-master/src/study-note.ts +175 -0
  305. package/skills/youtube-master/src/summarize.ts +358 -0
  306. package/skills/youtube-master/src/transcript.ts +76 -0
  307. package/skills/youtube-master/src/types.ts +91 -0
  308. package/skills/youtube-master/src/util.ts +93 -0
  309. package/skills/youtube-master/src/youtube.ts +70 -0
  310. package/skills/youtube-master/tsconfig.json +13 -0
  311. package/src/acp/server.ts +5 -2
  312. package/src/agent-mission/driver.ts +215 -23
  313. package/src/agent-mission/pty-decision.ts +71 -0
  314. package/src/agent-mission/review-loop.ts +30 -0
  315. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  316. package/src/autopilot/pty-control-loop.ts +4 -1
  317. package/src/autopilot/tool-registry.ts +2 -0
  318. package/src/boot/daemon-prompt-turn.ts +5 -0
  319. package/src/boot/daemon-runtime.ts +9 -3
  320. package/src/boot/daemon-tools/web-search.ts +3 -0
  321. package/src/card-followup/core.ts +109 -0
  322. package/src/chat/index.ts +2 -0
  323. package/src/cli/drive-input-jail.ts +101 -0
  324. package/src/cli/hooks-cli.ts +17 -3
  325. package/src/cli/make-cli.ts +43 -0
  326. package/src/cli/persona-cli.ts +98 -9
  327. package/src/cli/plugin-cli.ts +31 -22
  328. package/src/cli/pod-cli.ts +36 -9
  329. package/src/cli/pod-memory-advice.ts +35 -0
  330. package/src/cli/pr-cli.ts +51 -15
  331. package/src/cli/pty-drive-cli.ts +41 -7
  332. package/src/cli/pty-drive-verdict.ts +40 -0
  333. package/src/cli/release-cli.ts +63 -10
  334. package/src/cli/setup-cli.ts +43 -1
  335. package/src/cli/skills-cli.ts +17 -1
  336. package/src/context-bus/claude-hooks-install.ts +10 -0
  337. package/src/context-bus/context-now-surfaces.ts +65 -0
  338. package/src/context-bus/context-now.ts +104 -0
  339. package/src/context-bus/coord-events.ts +2 -2
  340. package/src/context-bus/external-events.ts +52 -0
  341. package/src/context-bus/long-term-memory.ts +108 -0
  342. package/src/context-bus/nightly-condense.ts +153 -0
  343. package/src/context-bus/session-events.ts +35 -0
  344. package/src/dashboard/dashboard-status-lines.ts +2 -0
  345. package/src/dashboard/index.ts +17 -4
  346. package/src/dashboard/slash-runtime/dashboard-handlers.ts +31 -1
  347. package/src/decisions/decision-cards.ts +10 -3
  348. package/src/decisions/decision-ledger.ts +13 -5
  349. package/src/discord/sprint21-runtime.ts +5 -1
  350. package/src/discord-self-message.ts +32 -0
  351. package/src/discord-slash-wire.ts +5 -1
  352. package/src/discord.ts +17 -1
  353. package/src/domains/core-tools.ts +3 -2
  354. package/src/domains/outbound-alert.ts +105 -32
  355. package/src/domains/outbound-log-probe.ts +8 -0
  356. package/src/domains/telegram-kind-route.ts +51 -13
  357. package/src/exec-requests/default-outputs.ts +25 -0
  358. package/src/exec-requests/planner.ts +10 -2
  359. package/src/exec-requests/runner.ts +20 -6
  360. package/src/exec-requests/store.ts +3 -0
  361. package/src/execution-loop/launch-gate.ts +109 -0
  362. package/src/field/field-reel.ts +5 -1
  363. package/src/field-note/index.ts +201 -0
  364. package/src/field-note/telegram.ts +142 -0
  365. package/src/field-note/transcribe.ts +248 -0
  366. package/src/graph-kinds/registry.ts +3 -3
  367. package/src/graph-runner/graph-cli.ts +61 -1
  368. package/src/graph-runner/graph-grow-llm.ts +47 -0
  369. package/src/graph-runner/graph-grow.ts +50 -0
  370. package/src/graph-runner/runner.ts +329 -33
  371. package/src/grok/agent-search.ts +8 -2
  372. package/src/guardian/secret-exposure-scan.ts +101 -0
  373. package/src/harness/harness-cli-command.ts +375 -13
  374. package/src/harness/harness-pod-dispatch.ts +43 -23
  375. package/src/harness/harness-seams.ts +38 -4
  376. package/src/harness/harness-stop.ts +23 -4
  377. package/src/harness/launch-registry.ts +91 -0
  378. package/src/harness/process-garbage.ts +5 -3
  379. package/src/hooks/consult-intake.ts +153 -0
  380. package/src/hooks/dispatch.ts +82 -0
  381. package/src/hooks/expose.ts +254 -0
  382. package/src/hooks/github-shadow.ts +108 -0
  383. package/src/hooks/providers.ts +71 -5
  384. package/src/hooks/queue.ts +1 -1
  385. package/src/hooks/receiver.ts +94 -16
  386. package/src/index.ts +76 -14
  387. package/src/intake-plane/categorize.ts +18 -46
  388. package/src/intake-plane/discord-seat-work.ts +38 -2
  389. package/src/intake-plane/front-route-classifier.ts +33 -39
  390. package/src/intake-plane/persona-answer.ts +30 -0
  391. package/src/intake-plane/runtime-callables.ts +8 -1
  392. package/src/intake-plane/telegram-seat-work.ts +36 -2
  393. package/src/intake-plane/wish-card.ts +33 -0
  394. package/src/intake-plane/wish-folder.ts +67 -0
  395. package/src/intent-gate/gate.ts +30 -10
  396. package/src/live/detail-switch.ts +5 -0
  397. package/src/llm/difficulty.ts +57 -0
  398. package/src/llm/judge-layer.ts +101 -0
  399. package/src/llm/mission-router.ts +33 -19
  400. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  401. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  402. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  403. package/src/loops/contract/loop-agent.schema.json +138 -0
  404. package/src/loops/contract/validate.ts +64 -0
  405. package/src/loops/registry.ts +20 -6
  406. package/src/market/signed-index.ts +4 -0
  407. package/src/maturity/bot-command-maturity.ts +45 -0
  408. package/src/maturity/feature-maturity.ts +27 -4
  409. package/src/model-tier/index.ts +2 -2
  410. package/src/model-tier/tier-resolver.ts +20 -20
  411. package/src/model-tier/types.ts +6 -6
  412. package/src/mss/logging/log-store.ts +15 -0
  413. package/src/nexus/api/config-model-tier.ts +5 -4
  414. package/src/nexus/api/fabric-plans.ts +53 -0
  415. package/src/nexus/api/harness-api.ts +5 -1
  416. package/src/nexus/api/health.ts +2 -0
  417. package/src/nexus/api/http-server.ts +67 -8
  418. package/src/nexus/api/inside-events.ts +226 -0
  419. package/src/nexus/api/meta-api.ts +21 -8
  420. package/src/nexus/api/missions.ts +6 -1
  421. package/src/nexus/api/ops-seats.ts +33 -0
  422. package/src/nexus/api/outbound-report.ts +40 -7
  423. package/src/nexus/api/outputs-route.ts +44 -0
  424. package/src/nexus/api/personas.ts +95 -53
  425. package/src/nexus/api/seat-requests.ts +44 -2
  426. package/src/nexus/api/sessions-store.ts +17 -38
  427. package/src/nexus/api/sub-seat-charters.ts +34 -0
  428. package/src/nexus/api/tabs-mutations.ts +3 -1
  429. package/src/nexus/api/task-cards-api.ts +19 -0
  430. package/src/nexus/api/trace.ts +18 -6
  431. package/src/nexus/api/workflow-history.ts +88 -0
  432. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  433. package/src/nexus/api/workflows.ts +132 -6
  434. package/src/nexus/index.ts +2 -0
  435. package/src/nexus/kinds/webterm.ts +2 -1
  436. package/src/nexus/outbound/delivery-ledger.ts +17 -8
  437. package/src/nexus/outbound/router.ts +8 -3
  438. package/src/nexus/webterm/pty.ts +6 -2
  439. package/src/onboarding/cli-auth-status.ts +80 -0
  440. package/src/onboarding/voice-ai.ts +3 -3
  441. package/src/org/seat-budget.ts +48 -0
  442. package/src/org/stall-escalation.ts +63 -0
  443. package/src/outputs/ledger.ts +120 -0
  444. package/src/persona/persona-todo.ts +79 -0
  445. package/src/persona/presets.ts +123 -2
  446. package/src/persona/team-set.ts +155 -0
  447. package/src/plugins/install/plugin-install.ts +14 -0
  448. package/src/plugins/maker/market-bundle.ts +110 -0
  449. package/src/plugins/maker/plugin-maker.ts +254 -11
  450. package/src/plugins/maker/wizard-generate.ts +103 -0
  451. package/src/pod-lease/admission.ts +150 -0
  452. package/src/pod-lease/dependency-state.ts +85 -0
  453. package/src/pod-lease/host-lease.ts +127 -0
  454. package/src/project/project-suggestion.ts +16 -0
  455. package/src/project/session-context.ts +24 -0
  456. package/src/release-loop/checklist.ts +17 -5
  457. package/src/release-loop/feature-store.ts +29 -13
  458. package/src/release-loop/landed-but-yellow.ts +48 -0
  459. package/src/release-loop/next-md-merge.ts +58 -0
  460. package/src/release-loop/release-note.ts +59 -4
  461. package/src/seat-dispatch/seat-ask.ts +130 -0
  462. package/src/seat-dispatch/seat-questions.ts +100 -0
  463. package/src/seat-loop/seat-loop.ts +709 -29
  464. package/src/seat-loop/seat-report.ts +37 -2
  465. package/src/self-dev/dev-cli.ts +4 -1
  466. package/src/self-dev/dev-pipeline.ts +37 -1
  467. package/src/self-dev/draft-sweep.ts +79 -40
  468. package/src/self-dev/draft-triage-rules.ts +62 -7
  469. package/src/self-dev/fabric-plan-core.ts +297 -0
  470. package/src/self-dev/orchestrate.ts +36 -4
  471. package/src/self-dev/release-path-guard.ts +62 -0
  472. package/src/self-dev/shard-aggregate.ts +230 -0
  473. package/src/self-dev/shard-placement.ts +60 -0
  474. package/src/self-dev/shard-plan.ts +48 -0
  475. package/src/self-dev/shard-pod-run.ts +77 -0
  476. package/src/self-dev/shard-run.ts +105 -0
  477. package/src/self-implement/budget-gate.ts +29 -12
  478. package/src/self-implement/gate-baseline.ts +1 -1
  479. package/src/self-implement/gate-candidate-ranking.ts +60 -0
  480. package/src/self-implement/gate-cli.ts +40 -1
  481. package/src/self-implement/gate-scope.ts +44 -13
  482. package/src/self-implement/graph-variant.ts +171 -0
  483. package/src/self-implement/harness-policy-gates.ts +1 -1
  484. package/src/self-implement/headless-elanous-driver.ts +27 -3
  485. package/src/self-implement/host-regate.ts +22 -1
  486. package/src/self-implement/importer-test-index.ts +2 -1
  487. package/src/self-implement/l8-merge-queue.ts +130 -0
  488. package/src/self-implement/orchestrator.ts +257 -9
  489. package/src/self-implement/route-consumer-test-index.ts +122 -0
  490. package/src/self-implement/seams.ts +72 -11
  491. package/src/self-implement/test-seams.ts +2 -0
  492. package/src/self-implement/uncommitted-work.ts +59 -0
  493. package/src/session/index.ts +36 -13
  494. package/src/skills/gift-install.ts +215 -0
  495. package/src/skills/tools/web-search.ts +4 -1
  496. package/src/steward/launch.ts +42 -26
  497. package/src/steward/steward-cards.ts +17 -9
  498. package/src/steward/triage.ts +46 -14
  499. package/src/task-cards/card-cli.ts +25 -1
  500. package/src/task-orchestrator/mission.ts +5 -0
  501. package/src/task-orchestrator/store.ts +12 -3
  502. package/src/task-orchestrator/surfaces/pod-command-job.ts +43 -17
  503. package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
  504. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  505. package/src/task-orchestrator/surfaces/self-implement-pod.ts +222 -40
  506. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  507. package/src/task-orchestrator/types.ts +2 -0
  508. package/src/telegram-card-followup.ts +16 -96
  509. package/src/telegram-commands.ts +31 -1
  510. package/src/telegram-project-command.ts +145 -0
  511. package/src/telegram-report.ts +21 -17
  512. package/src/telegram.ts +61 -8
  513. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  514. package/src/user-config.ts +110 -24
  515. package/src/version/packed-revision.json +1 -1
  516. package/src/web-search/grok.ts +7 -1
  517. package/src/web-search/index.ts +28 -1
  518. package/src/web-search/provider.ts +4 -0
  519. package/src/web-search/x-intent.ts +5 -0
  520. package/src/workflow-runtime/executor.ts +277 -47
  521. package/src/workflow-runtime/index.ts +1 -0
  522. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  523. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  524. package/src/workflow-runtime/schema.ts +79 -4
  525. package/src/workflow-runtime/types.ts +35 -4
  526. package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  536. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  537. package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
  556. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  614. package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
  615. /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → -6XrAoD3eU7NyMHAE4xPS}/_ssgManifest.js +0 -0
@@ -22,7 +22,7 @@ export interface CoordEvent {
22
22
  text: string;
23
23
  summary: string;
24
24
  kind: string;
25
- refs: Pick<CoordEventInput, 'seat' | 'recipients' | 'all' | 'kind' | 'slot' | 'deadline' | 'url'>;
25
+ refs: Pick<CoordEventInput, 'seat' | 'recipients' | 'all' | 'kind' | 'slot' | 'deadline' | 'url'> & { origin?: string; source?: string; ref?: string | null };
26
26
  }
27
27
 
28
28
  function seatIds(): Set<string> {
@@ -104,7 +104,7 @@ export function listCoordEvents(opts: { since: string; seat?: string }, deps: {
104
104
  const db = deps.db ?? openSurfaceEventsDb();
105
105
  try {
106
106
  const rows = db.prepare(`SELECT id, ts, text, summary, kind, refs FROM events
107
- WHERE surface='coord:channel' AND direction='outbound' AND ts>=?
107
+ WHERE surface IN ('coord:channel', 'context:external', 'context:session') AND direction='outbound' AND ts>=?
108
108
  ${opts.seat ? "AND json_extract(refs,'$.seat')=?" : ''} ORDER BY ts ASC, rowid ASC`)
109
109
  .all(...(opts.seat ? [opts.since, opts.seat] : [opts.since])) as Array<{
110
110
  id: string; ts: string; text: string; summary: string; kind: string; refs: string;
@@ -0,0 +1,52 @@
1
+ import type { Database } from 'bun:sqlite';
2
+ import { debug, redactSecretText } from '../debug/log.js';
3
+ import { openSurfaceEventsDb, recordEvent } from '../domains/surface-events.js';
4
+
5
+ export type ExternalEventOrigin = 'claude-code' | 'codex-agent-mission' | 'harness-child';
6
+ export type ContextHookKind = 'claimed' | 'done' | 'asked' | 'guide-changed';
7
+ export type ExternalEventKind = ContextHookKind | 'started' | 'finished';
8
+ export const CONTEXT_SUMMARY_MAX = 120;
9
+ export const CONTEXT_SOURCE_MAX = 512;
10
+
11
+ export interface ExternalEventInput {
12
+ origin: ExternalEventOrigin;
13
+ kind: ExternalEventKind;
14
+ summary: string;
15
+ source: string;
16
+ at?: string;
17
+ }
18
+
19
+ /** Only a single, bounded, redacted summary and a locator enter the journal; no prompt or transcript. */
20
+ export function recordExternalEvent(input: ExternalEventInput, deps: { db?: Database } = {}): string {
21
+ if (!['claude-code', 'codex-agent-mission', 'harness-child'].includes(input.origin)) throw new Error('invalid context origin');
22
+ if (input.origin === 'claude-code'
23
+ ? !['claimed', 'done', 'asked', 'guide-changed'].includes(input.kind)
24
+ : !['started', 'finished'].includes(input.kind)) throw new Error('invalid context kind');
25
+ const summary = redactSecretText(input.summary.split(/\r?\n/, 1)[0] ?? '').trim().slice(0, CONTEXT_SUMMARY_MAX);
26
+ const source = redactSecretText(input.source.split(/\r?\n/, 1)[0] ?? '').trim();
27
+ if (!summary) throw new Error('context summary must be one nonempty line');
28
+
29
+ if (!/^(?:https?:\/\/|elanous:\/\/)[^\s]+$/.test(source) || source.length > CONTEXT_SOURCE_MAX) {
30
+ throw new Error('context source must be a link (http(s) or elanous://), at most 512 characters');
31
+ }
32
+ const db = deps.db ?? openSurfaceEventsDb();
33
+ try {
34
+ return recordEvent(db, {
35
+ surface: 'context:external', direction: 'outbound', domain: 'elanous', category: 'coordination',
36
+ kind: input.kind, text: summary, summary,
37
+ refs: JSON.stringify({ seat: input.origin, recipients: [], all: false, kind: input.kind,
38
+ slot: null, deadline: null, url: source, origin: input.origin, source }),
39
+ ...(input.at ? { ts: input.at } : {}),
40
+ });
41
+ } finally { if (!deps.db) db.close(); }
42
+ }
43
+
44
+ /** Instrumentation never changes an agent's result. Failures remain visible without logging untrusted payloads. */
45
+ export function observeExternalEvent(input: ExternalEventInput, record: typeof recordExternalEvent = recordExternalEvent): void {
46
+ try { record(input); }
47
+ catch (error) {
48
+ try { debug.log('context.external', 'record-failed', {
49
+ origin: input.origin, kind: input.kind, reason: error instanceof Error ? error.message : String(error),
50
+ }, { level: 'warn' }); } catch { /* A broken logger cannot change an agent's result. */ }
51
+ }
52
+ }
@@ -0,0 +1,108 @@
1
+ import { redactSecretText } from '../debug/log.js';
2
+ import { DecisionLedger, type DecisionEntry } from '../decisions/decision-ledger.js';
3
+ import { listCoordEvents, type CoordEvent } from './coord-events.js';
4
+
5
+ export interface MemoryItem {
6
+ project: string;
7
+ seat: string;
8
+ topic: string;
9
+ summary: string;
10
+ source: string;
11
+ updatedAt: string;
12
+ status: 'active' | 'retired';
13
+ /** A normalized, comparable assertion supplied by the summarizer; absent means no conflict judgment. */
14
+ claim?: { key: string; value: string };
15
+ conflict?: { owner: 'OP'; sources: [string, string] };
16
+ }
17
+
18
+ export type MemorySource =
19
+ | { kind: 'event'; at: string; seat: string; text: string; source: string }
20
+ | { kind: 'decision'; at: string; seat: string; text: string; source: string };
21
+
22
+ export interface MemorySummary {
23
+ project: string;
24
+ topic: string;
25
+ summary: string;
26
+ /** Only supply this when the two strings identify the same fact and mutually exclusive values. */
27
+ claim?: { key: string; value: string };
28
+ }
29
+
30
+ export interface MemoryDeps {
31
+ summarize: (source: MemorySource) => Promise<MemorySummary>;
32
+ events?: (since: string) => CoordEvent[];
33
+ decisions?: () => DecisionEntry[];
34
+ }
35
+
36
+ const DAY_MS = 86_400_000;
37
+ const oneLine = (text: string) => redactSecretText(text.split(/\r?\n/, 1)[0] ?? '').trim();
38
+
39
+ /** Condense one UTC day; callers persist the returned snapshot, not raw transcripts. Read-only ledger access. */
40
+ export async function condenseContextDay(
41
+ day: string, previous: readonly MemoryItem[], deps: MemoryDeps, now: Date = new Date(),
42
+ ): Promise<MemoryItem[]> {
43
+ if (!/^\d{4}-\d\d-\d\d$/.test(day) || new Date(`${day}T00:00:00.000Z`).toISOString().slice(0, 10) !== day) {
44
+ throw new Error('day must be a valid UTC YYYY-MM-DD');
45
+ }
46
+ const since = `${day}T00:00:00.000Z`;
47
+ const start = Date.parse(since);
48
+ const until = start + DAY_MS;
49
+ // The store compares timestamp text, so fetch the previous local day too before UTC filtering.
50
+ const events = (deps.events ?? (from => listCoordEvents({ since: from })))(new Date(start - DAY_MS).toISOString());
51
+ const decisions = (deps.decisions ?? (() => new DecisionLedger().list({ status: 'all' })))();
52
+ const sources: MemorySource[] = [
53
+ ...events.map(event => ({ kind: 'event' as const, at: event.at, seat: event.refs.seat,
54
+ text: event.summary, source: event.refs.source ?? event.refs.url ?? `elanous://context/event/${encodeURIComponent(event.id)}` })),
55
+ ...decisions.map(decision => ({ kind: 'decision' as const,
56
+ at: decision.decidedAt ?? decision.raisedAt ?? decision.importedAt ?? '',
57
+ seat: decision.raisedBy.track ?? 'OP',
58
+ text: decision.status === 'decided' ? `${decision.title}: ${decision.options.find(o => o.key === decision.choice)?.label ?? decision.note ?? decision.scqa.a ?? '결정됨'}` : `${decision.title}: ${decision.status}`,
59
+ source: `elanous://decisions/${encodeURIComponent(decision.id)}` })),
60
+ ].filter(source => {
61
+ const at = Date.parse(source.at);
62
+ return Number.isFinite(at) && at >= start && at < until;
63
+ }).sort((a, b) => Date.parse(a.at) - Date.parse(b.at) || a.source.localeCompare(b.source));
64
+
65
+ const items = new Map<string, MemoryItem>();
66
+ const keyFor = (item: Pick<MemoryItem, 'project' | 'seat' | 'topic'>) => JSON.stringify([item.project, item.seat, item.topic]);
67
+ for (const item of previous) items.set(keyFor(item), { ...item });
68
+ for (const source of sources) {
69
+ const summary = await deps.summarize(source);
70
+ const project = oneLine(summary.project);
71
+ const seat = oneLine(source.seat);
72
+ const topic = oneLine(summary.topic);
73
+ const text = oneLine(summary.summary);
74
+ const link = oneLine(source.source);
75
+ if (!project || !seat || !topic || !text || !/^(?:https?:\/\/|elanous:\/\/)[^\s]+$/.test(link)) {
76
+ throw new Error('memory summary needs a project, seat, topic, one-line summary and source link');
77
+ }
78
+ const claim = summary.claim && { key: oneLine(summary.claim.key), value: oneLine(summary.claim.value) };
79
+ if (claim && (!claim.key || !claim.value)) throw new Error('memory claim needs key and value');
80
+ const key = keyFor({ project, seat, topic });
81
+ const old = items.get(key);
82
+ // Equal timestamps are resolved by the source link, so shuffled input does not change the winner.
83
+ if (old && (Date.parse(old.updatedAt) > Date.parse(source.at)
84
+ || (Date.parse(old.updatedAt) === Date.parse(source.at) && old.source >= link))) continue;
85
+ items.set(key, { project, seat, topic, summary: text, source: link, updatedAt: source.at,
86
+ status: 'active', ...(claim ? { claim } : {}) });
87
+ }
88
+ const cutoff = now.getTime() - 30 * DAY_MS;
89
+ // Compare only the winning, non-retired assertions; a superseded claim cannot keep a decision candidate alive.
90
+ const finalItems: MemoryItem[] = [...items.values()].map(({ conflict: _conflict, ...item }) => ({ ...item,
91
+ status: Date.parse(item.updatedAt) < cutoff ? 'retired' as const : 'active' as const,
92
+ }));
93
+ finalItems.sort((a, b) => Date.parse(a.updatedAt) - Date.parse(b.updatedAt) || a.source.localeCompare(b.source)
94
+ || a.seat.localeCompare(b.seat));
95
+ for (let index = 0; index < finalItems.length; index++) {
96
+ const item = finalItems[index]!;
97
+ if (item.status !== 'active' || !item.claim) continue;
98
+ const { key, value } = item.claim;
99
+ const conflicting = finalItems.slice(0, index).find(other => other.status === 'active'
100
+ && other.project === item.project
101
+ && other.claim?.key === key && other.claim.value !== value);
102
+ if (conflicting) {
103
+ finalItems[index] = { ...item, conflict: { owner: 'OP', sources: [conflicting.source, item.source] } };
104
+ }
105
+ }
106
+ return finalItems.sort((a, b) => a.project.localeCompare(b.project) || a.seat.localeCompare(b.seat)
107
+ || a.topic.localeCompare(b.topic));
108
+ }
@@ -0,0 +1,153 @@
1
+ import { readFileSync, readdirSync, mkdirSync, writeFileSync, renameSync, existsSync } from 'node:fs';
2
+ import { dirname, join, resolve } from 'node:path';
3
+ import { streamLLM } from '../llm.js';
4
+ import { condenseContextDay, type MemoryItem, type MemorySource, type MemorySummary } from './long-term-memory.js';
5
+ import { listCoordEvents, type CoordEvent } from './coord-events.js';
6
+ import { DecisionLedger, type DecisionEntry } from '../decisions/decision-ledger.js';
7
+ import { acquireLockAsync } from '../storage/file-lock.js';
8
+
9
+ type Stage = 'collect' | 'condense' | 'record' | 'conflict-candidates';
10
+ type Input = { day?: string; events?: CoordEvent[]; decisions?: DecisionEntry[]; summaries?: Record<string, MemorySummary> };
11
+ type Context = { graphId?: string; nodeId?: string; input: Input | null; outputs: Record<string, { day?: string; events?: CoordEvent[]; decisions?: DecisionEntry[]; items?: MemoryItem[] } | null> };
12
+
13
+ const dayBefore = (date: Date) => new Date(date.getTime() - 86_400_000).toISOString().slice(0, 10);
14
+ const fileName = (value: string) => encodeURIComponent(value).replace(/\./g, '%2E');
15
+
16
+ function snapshotPath(root: string, project: string, seat: string): string {
17
+ if (project === '.' || project === '..' || seat === '.' || seat === '..') throw new Error('invalid memory path');
18
+ return join(root, 'context-memory', fileName(project), `${fileName(seat)}.json`);
19
+ }
20
+
21
+ function save(file: string, value: unknown): void {
22
+ mkdirSync(dirname(file), { recursive: true });
23
+ const temp = `${file}.${process.pid}.tmp`;
24
+ writeFileSync(temp, JSON.stringify(value, null, 2) + '\n');
25
+ renameSync(temp, file);
26
+ }
27
+
28
+ async function withCurrentDay<T>(root: string, day: string, write: () => T): Promise<T> {
29
+ const dir = join(root, 'context-memory');
30
+ mkdirSync(dir, { recursive: true });
31
+ const lock = await acquireLockAsync(join(dir, '.nightly-write.lock'));
32
+ try {
33
+ const marker = join(dir, 'latest-day');
34
+ const latest = latestDay(root);
35
+ if ((latest && latest > day) || storedItems(root).some(item =>
36
+ Date.parse(item.updatedAt) >= Date.parse(`${day}T00:00:00Z`) + 86_400_000)) {
37
+ throw new Error(`cannot replay ${day}: later project/seat memory exists`);
38
+ }
39
+ if (!lock.stillHeld()) throw new Error('nightly memory write lock lost');
40
+ // Reserve the day before touching either output, so a failed writer cannot let an older run overwrite it.
41
+ if (!latest || latest < day) save(marker, day);
42
+ return write();
43
+ } finally { lock.release(); }
44
+ }
45
+
46
+ function latestDay(root: string): string | undefined {
47
+ const marker = join(root, 'context-memory', 'latest-day');
48
+ return existsSync(marker) ? JSON.parse(readFileSync(marker, 'utf8')) as string : undefined;
49
+ }
50
+
51
+ function storedItems(root: string): MemoryItem[] {
52
+ const dir = join(root, 'context-memory');
53
+ if (!existsSync(dir)) return [];
54
+ const items: MemoryItem[] = [];
55
+ for (const project of readdirSync(dir, { withFileTypes: true })) {
56
+ if (!project.isDirectory()) continue;
57
+ for (const seat of readdirSync(join(dir, project.name))) {
58
+ if (!seat.endsWith('.json')) continue;
59
+ const content: unknown = JSON.parse(readFileSync(join(dir, project.name, seat), 'utf8'));
60
+ if (!Array.isArray(content)) throw new Error('invalid context memory file');
61
+ items.push(...content as MemoryItem[]);
62
+ }
63
+ }
64
+ return items;
65
+ }
66
+
67
+ async function summarize(source: MemorySource, injected?: Record<string, MemorySummary>): Promise<MemorySummary> {
68
+ if (injected) {
69
+ const result = injected[source.source];
70
+ if (!result) throw new Error(`missing test summary: ${source.source}`);
71
+ return result;
72
+ }
73
+ const response = await streamLLM([
74
+ { role: 'system', content: 'Summarize this one-line context event as a compact project/seat memory item. Return ONLY JSON: {"project":"...","topic":"...","summary":"...","claim":{"key":"...","value":"..."}}. Omit claim when the event makes no comparable factual assertion. Never invent a project, topic or claim.' },
75
+ { role: 'user', content: JSON.stringify(source) },
76
+ ], () => {}, { maxTokens: 350, usageRole: 'research' });
77
+ const parsed: unknown = JSON.parse(response.replace(/^```(?:json)?\s*|\s*```$/g, '').trim());
78
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('invalid memory summary');
79
+ const value = parsed as Record<string, unknown>;
80
+ if (typeof value.project !== 'string' || typeof value.topic !== 'string' || typeof value.summary !== 'string' ||
81
+ (value.claim !== undefined && (!value.claim || typeof value.claim !== 'object' || Array.isArray(value.claim) ||
82
+ typeof (value.claim as Record<string, unknown>).key !== 'string' || typeof (value.claim as Record<string, unknown>).value !== 'string'))) {
83
+ throw new Error('invalid memory summary');
84
+ }
85
+ return value as unknown as MemorySummary;
86
+ }
87
+
88
+ /** Stage outputs travel only through the graph runner's per-run contexts. No decision ledger write occurs here. */
89
+ export async function runNightlyStage(stage: Stage, context: Context, root: string, dryRun: boolean, now = new Date()): Promise<Record<string, unknown>> {
90
+ const input = context.input ?? {};
91
+ if (dryRun && stage !== 'collect' && (!input.events || !input.decisions || !input.summaries)) {
92
+ throw new Error('dry-run requires fake events, decisions and summaries');
93
+ }
94
+ const day = context.outputs.collect?.day ?? input.day ?? dayBefore(now);
95
+ if (!/^\d{4}-\d\d-\d\d$/.test(day) || new Date(`${day}T00:00:00Z`).toISOString().slice(0, 10) !== day) {
96
+ throw new Error('invalid UTC day');
97
+ }
98
+ if (stage === 'collect') {
99
+ if (!dryRun && ((latestDay(root) ?? '') > day || storedItems(root).some(item =>
100
+ Date.parse(item.updatedAt) >= Date.parse(`${day}T00:00:00Z`) + 86_400_000))) {
101
+ throw new Error(`cannot replay ${day}: later project/seat memory exists`);
102
+ }
103
+ if (dryRun && (!input.events || !input.decisions || !input.summaries)) {
104
+ throw new Error('dry-run requires fake events, decisions and summaries');
105
+ }
106
+ const events = input.events ?? listCoordEvents({ since: new Date(Date.parse(`${day}T00:00:00Z`) - 86_400_000).toISOString() });
107
+ const decisions = input.decisions ?? (dryRun ? [] : new DecisionLedger().list({ status: 'all' }));
108
+ return { outcome: 'ok', day, events, decisions };
109
+ }
110
+ const collected = context.outputs.collect;
111
+ if (!collected?.day || !collected.events || !collected.decisions) throw new Error('collect output missing');
112
+ if (stage === 'condense') {
113
+ const items = await condenseContextDay(collected.day, dryRun ? [] : storedItems(root).filter(item => Date.parse(item.updatedAt) < Date.parse(`${collected.day}T00:00:00Z`)), {
114
+ events: () => collected.events!, decisions: () => collected.decisions!,
115
+ summarize: source => summarize(source, input.summaries),
116
+ }, now);
117
+ return { outcome: 'ok', items };
118
+ }
119
+ const items = context.outputs.condense?.items;
120
+ if (!items) throw new Error('condense output missing');
121
+ if (stage === 'record') {
122
+ const grouped = new Map<string, MemoryItem[]>();
123
+ for (const item of items) {
124
+ const file = snapshotPath(root, item.project, item.seat);
125
+ grouped.set(file, [...grouped.get(file) ?? [], item]);
126
+ }
127
+ if (!dryRun) await withCurrentDay(root, day, () => {
128
+ for (const [file, group] of grouped) save(file, group);
129
+ });
130
+ return { outcome: 'ok', files: [...grouped.keys()], items: items.length, memoryItems: dryRun ? items : undefined, dryRun };
131
+ }
132
+ if (stage === 'conflict-candidates') {
133
+ if (!context.outputs.record) throw new Error('record output missing');
134
+ const candidates = items.filter(item => item.conflict && item.status === 'active').map(item => ({
135
+ project: item.project, topic: item.topic, owner: item.conflict!.owner,
136
+ sources: item.conflict!.sources, status: 'candidate' as const,
137
+ }));
138
+ if (!dryRun) await withCurrentDay(root, day, () => save(join(root, 'context-memory', 'conflict-candidates.json'), candidates));
139
+ return { outcome: 'ok', candidates, published: 0 };
140
+ }
141
+ throw new Error(`unknown stage: ${stage}`);
142
+ }
143
+
144
+ if (import.meta.main) {
145
+ const stage = process.argv[2] as Stage;
146
+ const path = process.env.ELANOUS_GRAPH_CONTEXT;
147
+ if (!path || !['collect', 'condense', 'record', 'conflict-candidates'].includes(stage)) throw new Error('invalid nightly graph stage');
148
+ const context = JSON.parse(readFileSync(path, 'utf8')) as Context;
149
+ if (context.graphId !== 'nightly-condense' || context.nodeId !== stage) throw new Error('nightly graph context mismatch');
150
+ const statePath = resolve(path, '..', '..', '..', '..');
151
+ const result = await runNightlyStage(stage, context, statePath, process.env.ELANOUS_GRAPH_DRY_RUN === '1');
152
+ console.log(JSON.stringify(result));
153
+ }
@@ -0,0 +1,35 @@
1
+ import type { Database } from 'bun:sqlite';
2
+ import { redactSecretText } from '../debug/log.js';
3
+ import { openSurfaceEventsDb, recordEvent } from '../domains/surface-events.js';
4
+
5
+ export const SESSION_EVENT_KINDS = ['task-claimed', 'task-done', 'asked', 'guidance-changed'] as const;
6
+ export type SessionEventKind = typeof SESSION_EVENT_KINDS[number];
7
+
8
+ export interface SessionEventInput {
9
+ kind: SessionEventKind;
10
+ seat: string;
11
+ text: string;
12
+ ref?: string;
13
+ at?: string;
14
+ }
15
+
16
+ /** Publish a one-line external-agent session signal to the existing context journal. */
17
+ export function emitSessionEvent(input: SessionEventInput, deps: { db?: Database } = {}): string {
18
+ if (!SESSION_EVENT_KINDS.includes(input.kind)) throw new Error('unknown context session kind');
19
+ if (!['OP', 'TC', 'MK', 'UX'].includes(input.seat)) throw new Error('context session seat must be OP|TC|MK|UX');
20
+ if (/\r|\n/.test(input.text) || !input.text.trim()) throw new Error('context session text must be one nonempty line');
21
+ if (input.ref !== undefined && (/\r|\n/.test(input.ref) || !input.ref.trim())) throw new Error('context session ref must be one nonempty line');
22
+ const summary = redactSecretText(input.text).trim().slice(0, 120);
23
+ const ref = input.ref ?? null;
24
+ const db = deps.db ?? openSurfaceEventsDb();
25
+ try {
26
+ return recordEvent(db, {
27
+ surface: 'context:session', direction: 'outbound', domain: 'elanous', category: 'coordination',
28
+ kind: input.kind, text: input.text, summary,
29
+ refs: JSON.stringify({ seat: input.seat, recipients: [], all: false, kind: input.kind,
30
+ slot: null, deadline: null, url: null, ref,
31
+ ...(ref ? { source: `elanous://context/ref/${encodeURIComponent(ref)}` } : {}) }),
32
+ ...(input.at ? { ts: input.at } : {}),
33
+ });
34
+ } finally { if (!deps.db) db.close(); }
35
+ }
@@ -5,6 +5,7 @@ export interface DashboardStatusLinesInput {
5
5
  readonly daemonAddress?: string | null;
6
6
  readonly daemonConnected: boolean;
7
7
  readonly accountName?: string | null;
8
+ readonly seatsNow?: string | null;
8
9
  readonly sessionSurfaceLines: readonly string[];
9
10
  readonly view: string;
10
11
  readonly focus: string;
@@ -31,6 +32,7 @@ export function buildDashboardStatusLines(input: DashboardStatusLinesInput): str
31
32
  `모델: ${known(input.provider)}/${known(input.model)} (${known(input.reasoning)})`,
32
33
  `연결: 데몬 ${address} ${input.daemonConnected ? '붙음' : '안 붙음'}`,
33
34
  `계정: ${input.accountName?.trim() === 'default' ? '기본' : known(input.accountName)}`,
35
+ ...(input.seatsNow ? [input.seatsNow] : []),
34
36
  '',
35
37
  '자세히',
36
38
  ...input.sessionSurfaceLines.map(line => ` ${line}`),
@@ -18,6 +18,7 @@ import type { ShootRunOptions } from '../ad-pipeline/shoot-run.js';
18
18
  import type { QcThresholds } from '../ad-pipeline/qc.js';
19
19
  import { elanousStateRoot } from '../autopilot/state-paths.js';
20
20
  import { suggestProjectForFolder } from '../project/project-store.js';
21
+ import { createProjectSuggester } from '../project/project-suggestion.js';
21
22
 
22
23
  const dashboardDefaultShootRunOptions: Required<Pick<ShootRunOptions, 'pollIntervalMs' | 'maxPollsPerJob' | 'submitStaggerMs'>> = {
23
24
  pollIntervalMs: 3_000,
@@ -883,6 +884,7 @@ import { getInputHistoryStore, inputHistoryDbPath, inputHistoryJsonPath } from '
883
884
  import { inspectActiveProvider } from '../provider-summary.js';
884
885
  import { activeCodexAccountView } from '../oauth/codex-account-store.js';
885
886
  import { buildDashboardStatusLines } from './dashboard-status-lines.js';
887
+ import { readSlashContextNow, seatsNowLine } from '../context-bus/context-now-surfaces.js';
886
888
  import { buildFirstScreenBand } from './first-screen-band.js';
887
889
  import { runNexusShow, type NexusShowResult } from '../cli/nexus-show.js';
888
890
  import {
@@ -6404,7 +6406,14 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
6404
6406
  const active = inspectActiveProvider(cfg);
6405
6407
  const reasoningProvider = (['openai-codex', 'openai', 'anthropic', 'gemini', 'grok', 'local', 'openrouter'] as const)
6406
6408
  .find(provider => active.provider === provider || active.provider === `auto:${provider}`);
6409
+ let seatsNow: string | null = null;
6410
+ try {
6411
+ seatsNow = seatsNowLine(readSlashContextNow([]), Date.now());
6412
+ } catch (error) {
6413
+ debug.log('dashboard.status', 'seats-unreadable', { error: String(error) });
6414
+ }
6407
6415
  return buildDashboardStatusLines({
6416
+ seatsNow,
6408
6417
  provider: active.provider,
6409
6418
  model: active.model,
6410
6419
  reasoning: reasoningProvider
@@ -15791,12 +15800,16 @@ Mode- and sync-specific instructions are injected per-turn when relevant — do
15791
15800
  chatLines.push(C.muted(` ${resume.turns} turns restored. Next turn continues this conversation.`));
15792
15801
  }
15793
15802
  }
15803
+ // 제안은 세션 작업 폴더 기준 — 시작 폴더 한 번이 아니라 폴더가 바뀔 때마다 다시 계산한다(IA1 리뷰 must-fix).
15804
+ const nextProjectSuggestion = createProjectSuggester(suggestProjectForFolder);
15805
+ const pushProjectSuggestion = (folder: string): void => {
15806
+ const project = nextProjectSuggestion(folder);
15807
+ if (project) chatLines.push(C.muted(` Project suggestion: ${project.name} (${project.id})`));
15808
+ };
15794
15809
  if (dashboardAcpBootResult.mode !== 'resumed' && !chat.history.some((message) => message.role !== 'system')) {
15795
- try {
15796
- const project = suggestProjectForFolder(process.cwd());
15797
- if (project) chatLines.push(C.muted(` Project suggestion: ${project.name} (${project.id})`));
15798
- } catch { /* suggestions must not interrupt the dashboard conversation */ }
15810
+ pushProjectSuggestion(getSessionCwd());
15799
15811
  }
15812
+ subscribeSessionCwd((state) => { pushProjectSuggestion(state.cwd); });
15800
15813
  chatScrollOffset = -1;
15801
15814
  void renderDashboardFirstScreenBand({
15802
15815
  history: chat.history,
@@ -272,6 +272,10 @@
272
272
  // `../index.ts`) instead of importing the type — keeps this module free
273
273
  // of circular dependency on dashboard/index.ts.
274
274
 
275
+ import { tuiNowSlash } from '../../context-bus/context-now-surfaces.js';
276
+ import { createWishCard } from '../../intake-plane/wish-card.js';
277
+ import { CardStore } from '../../task-cards/card-store.js';
278
+ import type { ContextNowDeps } from '../../context-bus/context-now.js';
275
279
  import { runRebindCommand } from '../../input-core/index.js';
276
280
  // B4 (TUI half) — /design reuses the CLI's own resolution so the three
277
281
  // surfaces (CLI, PWA panel, this) cannot answer differently.
@@ -420,6 +424,8 @@ export interface DashboardSlashContext {
420
424
  /** Existing TUI structured-question capability. Absent means /ask keeps
421
425
  * the self-dev noninteractive deferred-clarification contract. */
422
426
  surfaceUx?: Pick<SurfaceUx, 'question'>;
427
+ /** Optional wish-card store for isolated slash dispatch tests. */
428
+ wishCardStore?: CardStore;
423
429
  attachmentRowMap: { clear(): void };
424
430
  pushDebugLine(line: string): void;
425
431
  pushChatLine(line: string): void;
@@ -1358,9 +1364,33 @@ function emitReplyToChat(ctx: Pick<DashboardSlashContext, 'pushChatLine'>, line:
1358
1364
  ctx.pushChatLine(line);
1359
1365
  }
1360
1366
 
1361
- export function buildDashboardSlashRegistry(): SlashCommandRegistry<DashboardSlashContext, DashboardSlashReturn> {
1367
+ export function buildDashboardSlashRegistry(nowDeps?: ContextNowDeps): SlashCommandRegistry<DashboardSlashContext, DashboardSlashReturn> {
1362
1368
  const registry = new SlashCommandRegistry<DashboardSlashContext, DashboardSlashReturn>();
1363
1369
 
1370
+ registry.register(['now'], (args, ctx) => {
1371
+ for (const line of tuiNowSlash(args, nowDeps)) ctx.pushChatLine(line);
1372
+ });
1373
+
1374
+ registry.register('wish', (args, ctx) => {
1375
+ const text = args.join(' ').trim();
1376
+ if (!text) {
1377
+ ctx.pushChatLine(ctx.warning(' usage: /wish <소원 한 줄>'));
1378
+ ctx.setChatScrollOffset(-1);
1379
+ return;
1380
+ }
1381
+ let store: CardStore | undefined;
1382
+ try {
1383
+ store = ctx.wishCardStore ?? new CardStore();
1384
+ const card = createWishCard({ text, source: 'tui', ref: crypto.randomUUID() }, store);
1385
+ ctx.pushChatLine(ctx.success(` 소원 카드로 남겼습니다 — ${card.title}`));
1386
+ } catch (err) {
1387
+ ctx.pushChatLine(ctx.error(` 소원 카드 등록 실패 — ${err instanceof Error ? err.message : String(err)}`));
1388
+ } finally {
1389
+ if (!ctx.wishCardStore) store?.close();
1390
+ }
1391
+ ctx.setChatScrollOffset(-1);
1392
+ });
1393
+
1364
1394
  // ── B-1.a pilot ────────────────────────────────────────────────────
1365
1395
  registry.register(['quit', 'q', 'exit'], (_args, ctx) => {
1366
1396
  (ctx.exitTui ?? ctx.closeTui)();
@@ -43,6 +43,7 @@ export function renderCardText(e: DecisionEntry, extra: { note?: string; confirm
43
43
  '',
44
44
  `상황: ${e.scqa.s}`,
45
45
  `문제: ${e.scqa.c}`,
46
+ ...(e.pendingQuestion ? ['', `대기 질문 전문:\n${e.pendingQuestion}`] : []),
46
47
  ...(e.scqa.q ? [`질문: ${e.scqa.q}`] : []),
47
48
  ...(e.scqa.a ? [`제안: ${e.scqa.a}`] : []),
48
49
  '',
@@ -180,7 +181,8 @@ export class DecisionCardService {
180
181
  const entry = this.ledger.raise({
181
182
  title: question.question.split(/\r?\n/, 1)[0]!.slice(0, 120),
182
183
  category: question.impact === 'critical' ? 'irreversible' : 'scope',
183
- scqa: { s: question.question, c: question.question },
184
+ scqa: { s: Array.from(question.question.split(/\r?\n/, 1)[0]!).slice(0, 200).join(''), c: 'The requesting run is waiting for this choice.' },
185
+ pendingQuestion: question.question,
184
186
  options: question.options.map((option, index) => ({ key: keys[index]!, label: option.label, consequence: option.description })),
185
187
  recommendation: recommended !== undefined && Number.isInteger(recommended) && recommended >= 0 && recommended < question.options.length
186
188
  ? { option: keys[recommended]!, why: '런이 추천' } : { skipped: true, reason: '추천 없음' },
@@ -251,9 +253,12 @@ export class DecisionCardService {
251
253
  return { kind: 'confirm', view: renderCard(entry, { confirm: parsed.key, ...(card?.note ? { note: card.note } : {}) }), toast: '되돌릴 수 없는 결정 — 한 번 더 확인해 주세요' };
252
254
  }
253
255
  let decided: DecisionEntry;
256
+ let answerDelivery: ReturnType<DecisionLedger['decideWithDelivery']>['delivery'] = null;
254
257
  try {
255
258
  // Same ledger method the CLI `decide` uses — one record path.
256
- decided = this.ledger.decide(entry.id, parsed.key, { kind: 'human' }, card?.note);
259
+ const recorded = this.ledger.decideWithDelivery(entry.id, parsed.key, { kind: 'human' }, card?.note);
260
+ decided = recorded.entry;
261
+ answerDelivery = recorded.delivery;
257
262
  } catch (error) {
258
263
  debug.log('decisions.telegram', 'decide-failed', { platform, id: entry.id, reason: error instanceof Error ? error.message.slice(0, 80) : 'unknown' }, { level: 'warn' });
259
264
  try { const now = this.ledger.show(entry.id); if (now.status !== 'open') return { kind: 'closed', view: renderCard(now), toast: '이미 정해진 결정입니다' }; } catch { /* fall through */ }
@@ -269,7 +274,9 @@ export class DecisionCardService {
269
274
  await this.opts.replyToRaiser?.(decided, platform).catch((error: unknown) => {
270
275
  debug.log('decisions.telegram', 'reply-failed', { platform, id: decided.id, reason: error instanceof Error ? error.message.slice(0, 80) : 'unknown' }, { level: 'warn' });
271
276
  });
272
- return { kind: 'decided', view, toast: `결정했습니다: ${decided.choice?.toUpperCase()}` };
277
+ return { kind: 'decided', view, toast: answerDelivery && !answerDelivery.ok
278
+ ? `결정은 기록됐지만 런 답 전달 실패 — decisions retry-answer ${decided.id}`
279
+ : `결정했습니다: ${decided.choice?.toUpperCase()}` };
273
280
  }
274
281
 
275
282
  /** Store a memo typed after «메모 달기»; the card shows it and the eventual decision carries it. */
@@ -7,7 +7,8 @@ import { createVersionResolver, type VersionOptions, type Versions } from '../di
7
7
  import { getUserConfig } from '../user-config.js';
8
8
 
9
9
  export type DecisionCategory = 'secret' | 'publish' | 'money' | 'security' | 'scope' | 'irreversible' | 'other';
10
- export type DecisionTrack = 'S' | 'T' | 'F' | 'O';
10
+ /** Old track letters (S·T·F·O) stay readable; seat names (OP·MK·TC·UX) are the current identities. */
11
+ export type DecisionTrack = 'S' | 'T' | 'F' | 'O' | 'OP' | 'MK' | 'TC' | 'UX';
11
12
  export interface DecisionOption { key: string; label: string; consequence: string }
12
13
  export type Recommendation = { option: string; why: string } | { skipped: true; reason: string };
13
14
  export type DecisionActor = { kind: 'human' } | { kind: 'auto'; agent: string; track?: DecisionTrack; delegation: string };
@@ -17,13 +18,15 @@ export interface DecisionEntry {
17
18
  raisedBy: { agent: string; track?: DecisionTrack; session?: string }; version?: Versions;
18
19
  status: 'open' | 'decided' | 'withdrawn'; refs?: string[];
19
20
  resume?: { questionId: string; runId?: string };
21
+ /** Original pending question, including its newlines; SCQA fields are short summaries. */
22
+ pendingQuestion?: string;
20
23
  /** DEC-TG — optional deadline (UTC). Cards remind the owner two hours before it. */
21
24
  dueAt?: string;
22
25
  decidedAt?: string; decidedBy?: DecisionActor; choice?: string; note?: string; versionAtDecision?: Versions;
23
26
  withdrawnAt?: string; withdrawReason?: string;
24
27
  history: Array<{ type: 'raised' | 'options-added' | 'decided' | 'withdrawn'; at?: string; by: string; version?: Versions; choice?: string; reason?: string }>;
25
28
  }
26
- export type RaiseInput = Pick<DecisionEntry, 'title' | 'category' | 'scqa' | 'options' | 'recommendation' | 'raisedBy' | 'refs' | 'dueAt' | 'resume'> & { raisedAt?: string };
29
+ export type RaiseInput = Pick<DecisionEntry, 'title' | 'category' | 'scqa' | 'options' | 'recommendation' | 'raisedBy' | 'refs' | 'dueAt' | 'resume' | 'pendingQuestion'> & { raisedAt?: string };
27
30
  type Event = { type: 'raised'; entry: DecisionEntry } | { type: 'options-added'; id: string; at: string; options: DecisionOption[]; by: string } | { type: 'decided'; id: string; at?: string; by: DecisionActor; choice?: string; version?: Versions; note?: string } | { type: 'withdrawn'; id: string; at: string; reason: string; version: Versions };
28
31
  export interface DecisionLedgerOptions extends VersionOptions { stateDir?: string; now?: () => Date; resolveVersion?: (at: string) => Versions; writeAnswer?: typeof writePendingQuestionAnswer }
29
32
 
@@ -38,7 +41,7 @@ export class DecisionAnswerDeliveryError extends Error {
38
41
  }
39
42
  }
40
43
  const CATEGORIES: readonly string[] = ['secret', 'publish', 'money', 'security', 'scope', 'irreversible', 'other'];
41
- const TRACKS: readonly string[] = ['S', 'T', 'F', 'O'];
44
+ const TRACKS: readonly string[] = ['S', 'T', 'F', 'O', 'OP', 'MK', 'TC', 'UX'];
42
45
 
43
46
  function required(value: string, name: string): string {
44
47
  if (typeof value !== 'string' || !value.trim()) throw new Error(`${name} is required`);
@@ -86,10 +89,12 @@ function validate(input: RaiseInput, historical = false): RaiseInput {
86
89
  ? { skipped: true as const, reason: safe(single(input.recommendation.reason, 'skip reason')) }
87
90
  : { option: input.recommendation.option, why: safe(single(input.recommendation.why, 'recommendation why')) };
88
91
  if ('option' in recommendation && !options.some(o => o.key === recommendation.option)) throw new Error('recommended option not found');
89
- if (input.resume && !/^auq:[0-9a-z]+:[0-9a-z]{5}(?![\s\S])/.test(input.resume.questionId)) throw new Error('invalid resume questionId');
92
+ if (input.resume && !/^(?:auq:[0-9a-z]+:[0-9a-z]{5}|execution:[A-Za-z0-9_-]+:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?![\s\S])/.test(input.resume.questionId)) throw new Error('invalid resume questionId');
90
93
  const resume = input.resume ? { questionId: input.resume.questionId,
91
94
  ...(input.resume.runId === undefined ? {} : { runId: single(input.resume.runId, 'resume runId') }) } : undefined;
95
+ if (input.pendingQuestion !== undefined) required(input.pendingQuestion, 'pending question');
92
96
  return { ...input, title, scqa: { s, c, ...(q ? { q } : {}), ...(a ? { a } : {}) }, options, recommendation,
97
+ ...(input.pendingQuestion === undefined ? {} : { pendingQuestion: safe(input.pendingQuestion) }),
93
98
  ...(resume ? { resume } : {}),
94
99
  raisedBy: { agent: safe(single(input.raisedBy.agent, 'agent')), ...(input.raisedBy.track ? { track: input.raisedBy.track } : {}), ...(input.raisedBy.session ? { session: safe(single(input.raisedBy.session, 'session')) } : {}) },
95
100
  ...(input.refs ? { refs: input.refs.map(r => safe(single(r, 'ref'))) } : {}),
@@ -263,13 +268,16 @@ export class DecisionLedger {
263
268
  if (!pending.ok) throw new Error(pending.error);
264
269
  const target = pending.questions.find(item => item.id === questionId);
265
270
  if (!target || target.questions.length !== 1 || !target.questions[0]?.id) throw new Error('pending question target not found or ambiguous');
271
+ if (questionId.startsWith('execution:') && (!runId || target.runId !== runId || !questionId.startsWith(`execution:${runId}:`))) throw new Error('pending question run differs from decision');
272
+ if (!questionId.startsWith('execution:') && runId !== undefined && target.runId !== undefined && target.runId !== runId) throw new Error('pending question run differs from decision');
273
+ if (target.expiresAt && Date.parse(target.expiresAt) <= this.now().getTime()) throw new Error('pending question expired');
266
274
  const question = target.questions[0];
267
275
  if (question.options.length !== entry.options.length || question.options.some((option, index) =>
268
276
  entry.options[index]?.key !== String.fromCharCode(97 + index) || entry.options[index]?.label !== option.label)) {
269
277
  throw new Error('pending question options differ from decision');
270
278
  }
271
279
  const answerKey = question.id;
272
- const answer = { id: questionId, result: { answers: { [answerKey]: `${entry.choice}) ${label}` },
280
+ const answer = { id: questionId, result: { answers: { [answerKey]: questionId.startsWith('execution:') ? label : `${entry.choice}) ${label}` },
273
281
  ...(entry.note ? { otherText: { [answerKey]: entry.note } } : {}) } };
274
282
  const existing = readPendingQuestionAnswer(questionId, deps);
275
283
  if (!existing.ok) throw new Error('existing answer unreadable');
@@ -21,6 +21,7 @@
21
21
  // ⏳ Mention parser → persona LLM dispatch wire
22
22
 
23
23
  import { debug } from '../debug/log.js';
24
+ import { botAudienceFor, gateDiscordSchemas } from '../maturity/bot-command-maturity.js';
24
25
  import type { DiscordBot } from '../discord.js';
25
26
  import {
26
27
  loadLayeredPersonaDirs,
@@ -204,7 +205,10 @@ export async function wireSprint21Runtime(opts: WireSprint21Opts): Promise<Sprin
204
205
  // 6. Slash command registration
205
206
  const cmdRest = makeCommandRest({ token: opts.token, fetchImpl: opts.fetchImpl });
206
207
  async function registerSlashCommands(): Promise<number> {
207
- const schemas = router.schemas();
208
+ const allSchemas = router.schemas();
209
+ const audience = botAudienceFor('discord');
210
+ const { schemas, hidden } = gateDiscordSchemas(allSchemas, audience);
211
+ debug.log('discord.command', 'menu-filtered', { total: allSchemas.length, shown: schemas.length - hidden, ...audience });
208
212
  if (opts.devGuildId) {
209
213
  const out = await cmdRest.bulkOverwriteGuild(opts.appId, opts.devGuildId, schemas);
210
214
  log(`[sprint21-wire] registered ${out.length} slash commands to guild ${opts.devGuildId}`);