elanous 0.2.9 → 0.2.11

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 (694) 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/Y4zKzL62sakG5momz3SoQ/_buildManifest.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1394-556de6d71bbdb0fb.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
  7. package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/2310-7a59f043f6db207e.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/2548-6e316138d347cefe.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/3869-a39d1d9921e10d43.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
  19. package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
  20. package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
  25. package/apps/pwa/out/_next/static/chunks/507-5acd98bd6dab2d8a.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/5445-745eb795c5963d79.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/5845-e6c003ce8d5fd36a.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
  31. package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/8605-ea5bee9dfae512c7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.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-1dcdc58fc2de2454.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-6a061bd97f0b9398.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/app/board/page-cb95a7432c9ee744.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-f972fc1c00a62e88.js → page-b12b6d2f8d2d1aea.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/app/bots/page-b9efe868bfd36255.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/app/chat/page-7c97dcdfe2e37a60.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/app/consult/page-8fd36984f549270a.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/app/control/page-5721537ca8a3598c.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/app/design-check/page-b654240a572e4c48.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/app/editor/page-b9750abc897508c3.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/app/exec/page-4cd1de371f8ad048.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/app/field/page-d99f89657828421c.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-50cb2a0eb15e6c83.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/app/intake/page-c8b1ccda6ba7ae98.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/app/layout-d6b1d156fb95e74b.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/app/live/page-2a9932ddb62d76bd.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/app/market/page-9688f5b4f1ff950f.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6b15dd6456c5df09.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/app/morning/{page-adfbd2ba9598e59a.js → page-35414e0a007b4082.js} +1 -1
  72. package/apps/pwa/out/_next/static/chunks/app/not-found-e7a529e0507ac86c.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/app/observatory/page-e001823c35c9dd67.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-371423d1a573d64b.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4b764b125339ac17.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cdf8e4b01067bcf1.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3a24072b35470157.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/app/page-94c82eb0ae5abb32.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/app/reflection/page-0be8d4b2ced75ba0.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d37cb0d52f9b6bd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/app/sessions/page-686da0df9bf23e5c.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4dc614f3ce043e63.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/app/settings/page-53f80edc6b8dc07c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-d02c782fc792e2af.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-239c17b911b84e72.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/app/share/page-dc6a79fb003f746c.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/app/showroom/page-0fffb84cafdc9da6.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/app/tasks/page-1218753c82d585f6.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/app/term/page-4b5935e67531efb5.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/app/today/page-3285bc87caf1eaa5.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/app/trace/page-ad553b0e06505ecd.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/app/vault/page-fca096e3e860306f.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ebfa78f0d9885c3.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/app/workflows/page-3dc5f21f7e39622d.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/app/workspace/page-c6da2b468454532d.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-93bc70e36f595414.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/543f56bcb1f79fca.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 -0
  152. package/apps/pwa/out/ops/seats/index.txt +30 -0
  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 -0
  178. package/apps/pwa/out/today/index.txt +33 -0
  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/drafts/draft-cleanup.yaml +19 -0
  192. package/graphs/drafts/recipes.yaml +23 -0
  193. package/graphs/field/field-feed.yaml +2 -0
  194. package/graphs/implement-loop.yaml +1 -1
  195. package/graphs/intake/intake-daily.yaml +2 -1
  196. package/graphs/ops/recipes.yaml +3 -0
  197. package/graphs/ops/secret-exposure.yaml +24 -0
  198. package/graphs/release/recipes.yaml +3 -0
  199. package/graphs/release/release-loop.yaml +4 -1
  200. package/graphs/video/explainer-line.yaml +2 -2
  201. package/package.json +2 -1
  202. package/plugins/card-followup/graphs/run-step.ts +48 -13
  203. package/plugins/doc-draft/graphs/doc-draft.yaml +3 -3
  204. package/plugins/doc-draft/graphs/run-step.ts +13 -6
  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/ci-pwa-build-gate.ts +160 -0
  216. package/scripts/context-hooks/claude-stop.sh +4 -0
  217. package/scripts/context-hooks/emit.ts +24 -0
  218. package/scripts/context-hooks/post-tool-use.sh +4 -0
  219. package/scripts/coord-channel-watch.sh +54 -8
  220. package/scripts/coord-digest.ts +199 -0
  221. package/scripts/coord-post.sh +60 -3
  222. package/scripts/coord-requests-bridge.ts +143 -0
  223. package/scripts/field-feed/lib.ts +4 -0
  224. package/scripts/fleet/node-setup.sh +20 -3
  225. package/scripts/homebrew-formula-bump.ts +69 -0
  226. package/scripts/install.ps1 +68 -9
  227. package/scripts/install.sh +39 -12
  228. package/scripts/lib/pwa-scenarios/scenarios.ts +20 -0
  229. package/scripts/lib/tui-regress-checks.ts +146 -0
  230. package/scripts/marketing/measure-site-numbers.ts +169 -0
  231. package/scripts/measure-gate-shards.ts +309 -0
  232. package/scripts/memory-lifecycle-cycle.ts +2 -2
  233. package/scripts/mission-request-judge.ts +31 -1
  234. package/scripts/morning-report.ts +2 -2
  235. package/scripts/opportunity-scan.ts +1 -1
  236. package/scripts/ops-now-probe.ts +327 -0
  237. package/scripts/publish-internal-dist.ts +11 -1
  238. package/scripts/release-loop/auto-approve-node.ts +21 -4
  239. package/scripts/release-loop/cut-branch.ts +84 -0
  240. package/scripts/release-loop/cutoff.ts +19 -8
  241. package/scripts/release-loop/gate-node.ts +14 -13
  242. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  243. package/scripts/release-loop/node-verdict.ts +3 -3
  244. package/scripts/release-loop/ops-upgrade-node.ts +72 -16
  245. package/scripts/release-loop/release-readiness.ts +9 -0
  246. package/scripts/release-loop/tui-node-checks.ts +42 -0
  247. package/scripts/release-loop/tui-sim-node.ts +32 -8
  248. package/scripts/release-loop/unattended-release.ts +5 -3
  249. package/scripts/release-loop/version-node.ts +112 -13
  250. package/scripts/repo-watch-cycle.ts +1 -1
  251. package/scripts/retro-cycle.ts +2 -2
  252. package/scripts/schedule-health-report.ts +1 -1
  253. package/scripts/signal-digest-cycle.ts +2 -7
  254. package/scripts/signal-digest-photo.ts +11 -0
  255. package/scripts/storyboard/storyboard.ts +5 -161
  256. package/scripts/tech1-public-measure.ts +94 -0
  257. package/scripts/test-diet/lib.ts +30 -1
  258. package/scripts/test-diet/node.ts +83 -8
  259. package/scripts/test-timeout-audit.ts +114 -0
  260. package/scripts/tree-sync-alert.ts +1 -1
  261. package/scripts/tui-regress.ts +71 -0
  262. package/scripts/ux/demo-rehearsal.ts +243 -0
  263. package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
  264. package/scripts/waitlist-daily-digest.ts +1 -1
  265. package/skills/diagram-master/SKILL.md +366 -0
  266. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  267. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  268. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  269. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  270. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  271. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  272. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  273. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  274. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  275. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  276. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  277. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  278. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  279. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  280. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  281. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  282. package/skills/diagram-master/references/examples/README.md +69 -0
  283. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  284. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  285. package/skills/diagram-master/references/pyproject.toml +16 -0
  286. package/skills/diagram-master/references/quality-checklist.md +33 -0
  287. package/skills/diagram-master/references/routing-guide.md +164 -0
  288. package/skills/diagram-master/references/uv.lock +1356 -0
  289. package/skills/explainer-video/SKILL.md +4 -0
  290. package/skills/explainer-video/engine/reel.mjs +18 -13
  291. package/skills/explainer-video/engine/reel.sh +24 -5
  292. package/skills/explainer-video/engine/stitch.mjs +145 -0
  293. package/skills/google-workspace/SKILL.md +33 -0
  294. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  295. package/skills/grill-me/SKILL.md +1 -1
  296. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  297. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  298. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  299. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  300. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  301. package/skills/omni-crawl/SKILL.md +21 -11
  302. package/skills/omni-crawl/scripts/main.ts +6 -6
  303. package/skills/omni-crawl/src/router.ts +3 -3
  304. package/skills/omni-digest/SKILL.md +17 -9
  305. package/skills/omni-digest/digest.md +2 -2
  306. package/skills/omni-digest/src/fetch.ts +30 -3
  307. package/skills/pitch-deck/SKILL.md +36 -0
  308. package/skills/pitch-deck/template.html +80 -0
  309. package/skills/youtube-master/SKILL.md +163 -0
  310. package/skills/youtube-master/package-lock.json +558 -0
  311. package/skills/youtube-master/package.json +13 -0
  312. package/skills/youtube-master/references/study-note-template.md +124 -0
  313. package/skills/youtube-master/scripts/main.ts +435 -0
  314. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  315. package/skills/youtube-master/src/audio.ts +63 -0
  316. package/skills/youtube-master/src/domain-staging.ts +50 -0
  317. package/skills/youtube-master/src/env.ts +36 -0
  318. package/skills/youtube-master/src/obsidian.ts +155 -0
  319. package/skills/youtube-master/src/router.ts +110 -0
  320. package/skills/youtube-master/src/stt.ts +199 -0
  321. package/skills/youtube-master/src/study-note.ts +175 -0
  322. package/skills/youtube-master/src/summarize.ts +358 -0
  323. package/skills/youtube-master/src/transcript.ts +76 -0
  324. package/skills/youtube-master/src/types.ts +91 -0
  325. package/skills/youtube-master/src/util.ts +93 -0
  326. package/skills/youtube-master/src/youtube.ts +70 -0
  327. package/skills/youtube-master/tsconfig.json +13 -0
  328. package/src/acp/codex-approval-adapter.ts +9 -3
  329. package/src/acp/core-turn-bridge.ts +117 -18
  330. package/src/acp/fact-question.ts +11 -0
  331. package/src/acp/server.ts +53 -9
  332. package/src/acp/tool-approval.ts +126 -0
  333. package/src/acp/turn-runner.ts +36 -0
  334. package/src/agent/monad-agent-turn.ts +8 -0
  335. package/src/agent-mission/driver.ts +80 -10
  336. package/src/agent-mission/pty-decision.ts +71 -0
  337. package/src/agent-mission/review-loop.ts +30 -0
  338. package/src/ask-user-question/pending-questions.ts +25 -10
  339. package/src/ask-user-question/types.ts +9 -0
  340. package/src/auth/setup-link-tokens.ts +16 -5
  341. package/src/autopilot/build/integrity-gate.ts +12 -0
  342. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  343. package/src/autopilot/tool-registry.ts +2 -0
  344. package/src/boot/daemon-prompt-turn.ts +8 -0
  345. package/src/boot/daemon-runtime.ts +9 -3
  346. package/src/boot/daemon-tools/index.ts +8 -0
  347. package/src/boot/daemon-tools/types.ts +2 -0
  348. package/src/boot/daemon-tools/web-search.ts +4 -0
  349. package/src/card-followup/core.ts +109 -0
  350. package/src/chat/ctrl-c-in-input.ts +14 -0
  351. package/src/chat/index.ts +53 -0
  352. package/src/chat/pickers/state.ts +6 -2
  353. package/src/cli/agent-cli.ts +7 -0
  354. package/src/cli/decisions-cli.ts +25 -3
  355. package/src/cli/doctor-bundle-upload.ts +68 -0
  356. package/src/cli/doctor-cli.ts +38 -4
  357. package/src/cli/drive-input-jail.ts +101 -0
  358. package/src/cli/hooks-cli.ts +17 -3
  359. package/src/cli/make-cli.ts +43 -0
  360. package/src/cli/ops-cli.ts +20 -0
  361. package/src/cli/persona-cli.ts +90 -4
  362. package/src/cli/plugin-cli.ts +31 -22
  363. package/src/cli/pod-cli.ts +61 -2
  364. package/src/cli/pr-cli.ts +82 -17
  365. package/src/cli/pty-drive-cli.ts +41 -7
  366. package/src/cli/pty-drive-verdict.ts +40 -0
  367. package/src/cli/pwa-stop.ts +163 -13
  368. package/src/cli/pwa-test.ts +3 -0
  369. package/src/cli/release-cli.ts +80 -24
  370. package/src/cli/self-update.ts +14 -0
  371. package/src/cli/setup-cli.ts +43 -1
  372. package/src/cli/skills-cli.ts +17 -1
  373. package/src/cli/storyboard-cli.ts +37 -0
  374. package/src/cli/test-state-dir-flag.ts +11 -4
  375. package/src/connectors/linear.ts +146 -0
  376. package/src/context-bus/claude-hooks-install.ts +10 -0
  377. package/src/context-bus/context-now-surfaces.ts +48 -0
  378. package/src/context-bus/context-now.ts +104 -0
  379. package/src/context-bus/coord-events.ts +115 -0
  380. package/src/context-bus/external-events.ts +52 -0
  381. package/src/context-bus/long-term-memory.ts +108 -0
  382. package/src/dashboard/dashboard-boot-fixture.ts +23 -0
  383. package/src/dashboard/index.ts +63 -21
  384. package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -1
  385. package/src/dashboard/slash-runtime/help-from-registry.ts +43 -28
  386. package/src/decisions/decision-cards.ts +58 -3
  387. package/src/decisions/decision-ledger.ts +85 -6
  388. package/src/decisions/decision-linear-projection.ts +157 -0
  389. package/src/decisions/web-push-decision-cards.ts +50 -0
  390. package/src/directive/interpretation-card.ts +36 -0
  391. package/src/discord/sprint21-runtime.ts +5 -1
  392. package/src/discord-self-message.ts +32 -0
  393. package/src/discord-slash-wire.ts +5 -1
  394. package/src/discord.ts +19 -2
  395. package/src/domains/coo-admin-tool.ts +62 -0
  396. package/src/domains/core-tools.ts +13 -4
  397. package/src/domains/elanous-card.ts +29 -0
  398. package/src/domains/ops-facts-tool.ts +76 -0
  399. package/src/domains/outbound-alert.ts +46 -13
  400. package/src/domains/release-tool.ts +168 -0
  401. package/src/domains/telegram-kind-route.ts +65 -9
  402. package/src/exec-requests/default-outputs.ts +25 -0
  403. package/src/exec-requests/planner.ts +106 -28
  404. package/src/exec-requests/runner.ts +123 -12
  405. package/src/exec-requests/store.ts +11 -2
  406. package/src/execution-loop/launch-gate.ts +100 -0
  407. package/src/field/field-media.ts +10 -7
  408. package/src/field/field-reel.ts +19 -5
  409. package/src/field-note/index.ts +201 -0
  410. package/src/field-note/transcribe.ts +248 -0
  411. package/src/git-fs/worktree.ts +45 -6
  412. package/src/graph-kinds/registry.ts +3 -3
  413. package/src/graph-runner/graph-approval-card.ts +113 -0
  414. package/src/graph-runner/graph-cli.ts +189 -4
  415. package/src/graph-runner/graph-grow-llm.ts +37 -0
  416. package/src/graph-runner/graph-grow.ts +47 -0
  417. package/src/graph-runner/graph-notify.ts +25 -3
  418. package/src/graph-runner/runner.ts +453 -35
  419. package/src/grok/agent-search.ts +8 -2
  420. package/src/guardian/secret-exposure-scan.ts +101 -0
  421. package/src/harness/browser-verify.ts +25 -2
  422. package/src/harness/harness-cli-command.ts +478 -42
  423. package/src/harness/harness-incidents-writer.fixture.ts +24 -0
  424. package/src/harness/harness-incidents.ts +129 -0
  425. package/src/harness/harness-pod-dispatch.ts +43 -23
  426. package/src/harness/harness-seams.ts +38 -4
  427. package/src/harness/harness-stop.ts +75 -6
  428. package/src/harness/launch-registry.ts +91 -0
  429. package/src/harness/process-garbage.ts +5 -3
  430. package/src/hitl/clarification-policy.ts +3 -1
  431. package/src/hooks/dispatch.ts +82 -0
  432. package/src/hooks/expose.ts +254 -0
  433. package/src/hooks/github-shadow.ts +108 -0
  434. package/src/hooks/providers.ts +71 -5
  435. package/src/hooks/queue.ts +1 -1
  436. package/src/hooks/receiver.ts +21 -20
  437. package/src/index.ts +206 -49
  438. package/src/intake-plane/author-goals.ts +37 -4
  439. package/src/intake-plane/categorize.ts +18 -46
  440. package/src/intake-plane/check.ts +3 -0
  441. package/src/intake-plane/discord-seat-work.ts +57 -2
  442. package/src/intake-plane/front-route-classifier.ts +33 -39
  443. package/src/intake-plane/persona-answer.ts +30 -0
  444. package/src/intake-plane/runtime-callables.ts +8 -1
  445. package/src/intake-plane/seat-doc-route.ts +170 -6
  446. package/src/intake-plane/telegram-seat-work.ts +80 -4
  447. package/src/intake-plane/telegram-work.ts +1 -0
  448. package/src/intake-plane/wish-folder.ts +67 -0
  449. package/src/intent-gate/gate.ts +30 -10
  450. package/src/live/detail-switch.ts +5 -0
  451. package/src/llm/difficulty.ts +57 -0
  452. package/src/llm/judge-layer.ts +101 -0
  453. package/src/llm/mission-router.ts +33 -19
  454. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  455. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  456. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  457. package/src/loops/contract/loop-agent.schema.json +138 -0
  458. package/src/loops/contract/validate.ts +64 -0
  459. package/src/loops/registry.ts +20 -6
  460. package/src/market/signed-index.ts +4 -0
  461. package/src/maturity/bot-command-maturity.ts +45 -0
  462. package/src/maturity/cli-maturity.ts +34 -0
  463. package/src/maturity/feature-maturity.ts +120 -1
  464. package/src/maturity/tui-slash-maturity.ts +31 -0
  465. package/src/memory.ts +32 -4
  466. package/src/model-tier/index.ts +2 -2
  467. package/src/model-tier/tier-resolver.ts +20 -20
  468. package/src/model-tier/types.ts +6 -6
  469. package/src/mss/logging/log-store.ts +15 -0
  470. package/src/nexus/api/config-model-tier.ts +5 -4
  471. package/src/nexus/api/exec-requests.ts +33 -3
  472. package/src/nexus/api/fabric-plans.ts +53 -0
  473. package/src/nexus/api/harness-api.ts +5 -1
  474. package/src/nexus/api/health.ts +2 -0
  475. package/src/nexus/api/http-server.ts +89 -1
  476. package/src/nexus/api/inside-events.ts +226 -0
  477. package/src/nexus/api/meta-api.ts +32 -8
  478. package/src/nexus/api/missions.ts +6 -1
  479. package/src/nexus/api/ops-api.ts +10 -1
  480. package/src/nexus/api/ops-seats-sources.ts +37 -7
  481. package/src/nexus/api/ops-seats.ts +49 -6
  482. package/src/nexus/api/outputs-route.ts +44 -0
  483. package/src/nexus/api/seat-requests.ts +132 -10
  484. package/src/nexus/api/sessions-store.ts +42 -0
  485. package/src/nexus/api/setup-codex-login.ts +160 -0
  486. package/src/nexus/api/sub-seat-charters.ts +34 -0
  487. package/src/nexus/api/tabs-mutations.ts +3 -1
  488. package/src/nexus/api/trace.ts +18 -6
  489. package/src/nexus/api/usage-api.ts +102 -0
  490. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  491. package/src/nexus/api/workflows.ts +80 -6
  492. package/src/nexus/index.ts +47 -4
  493. package/src/nexus/kinds/webterm.ts +2 -1
  494. package/src/nexus/webterm/pty.ts +6 -2
  495. package/src/onboarding/cli-auth-status.ts +80 -0
  496. package/src/onboarding/first-run.ts +89 -0
  497. package/src/onboarding/lan-address.ts +45 -0
  498. package/src/onboarding/voice-ai.ts +3 -3
  499. package/src/onboarding/web-first.ts +119 -24
  500. package/src/onboarding.ts +4 -0
  501. package/src/ops-now/ops-now-refresh.ts +100 -0
  502. package/src/org/seat-budget.ts +48 -0
  503. package/src/org/stall-escalation.ts +63 -0
  504. package/src/outputs/ledger.ts +120 -0
  505. package/src/persona/persona-todo.ts +79 -0
  506. package/src/persona/presets.ts +116 -2
  507. package/src/persona/team-set.ts +155 -0
  508. package/src/plugins/install/plugin-install.ts +14 -0
  509. package/src/plugins/maker/market-bundle.ts +109 -0
  510. package/src/plugins/maker/plugin-maker.ts +254 -11
  511. package/src/plugins/maker/wizard-generate.ts +103 -0
  512. package/src/pod-lease/admission.ts +150 -0
  513. package/src/pod-lease/dependency-state.ts +85 -0
  514. package/src/pod-lease/host-lease.ts +127 -0
  515. package/src/project/project-store.ts +115 -0
  516. package/src/project/project-suggestion.ts +16 -0
  517. package/src/project/session-context.ts +24 -0
  518. package/src/release-loop/checklist.ts +79 -5
  519. package/src/release-loop/feature-store.ts +159 -24
  520. package/src/release-loop/next-md-merge.ts +58 -0
  521. package/src/release-loop/release-note.ts +59 -4
  522. package/src/release-loop/release-schedule.ts +53 -0
  523. package/src/repl/index.ts +7 -0
  524. package/src/seat-dispatch/ceo-commands.ts +41 -8
  525. package/src/seat-dispatch/ceo-intent.ts +38 -0
  526. package/src/seat-dispatch/seat-ask.ts +130 -0
  527. package/src/seat-dispatch/seat-questions.ts +100 -0
  528. package/src/seat-loop/seat-loop.ts +750 -0
  529. package/src/seat-loop/seat-report.ts +99 -0
  530. package/src/self-dev/decompose.ts +66 -11
  531. package/src/self-dev/dev-cli.ts +4 -1
  532. package/src/self-dev/dev-pipeline.ts +37 -1
  533. package/src/self-dev/draft-sweep.ts +38 -33
  534. package/src/self-dev/draft-triage-rules.ts +8 -5
  535. package/src/self-dev/fabric-plan-core.ts +297 -0
  536. package/src/self-dev/orchestrate.ts +36 -4
  537. package/src/self-dev/release-path-guard.ts +62 -0
  538. package/src/self-dev/run-store.ts +10 -1
  539. package/src/self-dev/shard-aggregate.ts +230 -0
  540. package/src/self-dev/shard-placement.ts +60 -0
  541. package/src/self-dev/shard-plan.ts +48 -0
  542. package/src/self-dev/shard-pod-run.ts +77 -0
  543. package/src/self-dev/shard-run.ts +105 -0
  544. package/src/self-implement/execution-clarification.ts +115 -0
  545. package/src/self-implement/gate-baseline.ts +1 -1
  546. package/src/self-implement/gate-cli.ts +46 -4
  547. package/src/self-implement/gate-scope.ts +37 -7
  548. package/src/self-implement/graph-variant.ts +171 -0
  549. package/src/self-implement/harness-policy-gates.ts +1 -1
  550. package/src/self-implement/headless-elanous-driver.ts +22 -3
  551. package/src/self-implement/host-regate.ts +22 -1
  552. package/src/self-implement/importer-test-index.ts +2 -1
  553. package/src/self-implement/l8-merge-queue.ts +130 -0
  554. package/src/self-implement/orchestrator.ts +279 -12
  555. package/src/self-implement/pipeline-shape.ts +1 -1
  556. package/src/self-implement/route-consumer-test-index.ts +122 -0
  557. package/src/self-implement/run-status-mapping.ts +5 -3
  558. package/src/self-implement/seams.ts +72 -11
  559. package/src/self-implement/test-seams.ts +1 -0
  560. package/src/self-implement/uncommitted-work.ts +59 -0
  561. package/src/session/chat.ts +2 -0
  562. package/src/session/index.ts +45 -13
  563. package/src/shell-env-bootstrap.ts +17 -0
  564. package/src/skills/gift-install.ts +215 -0
  565. package/src/skills/tools/web-search.ts +4 -1
  566. package/src/steward/directive.ts +51 -2
  567. package/src/steward/launch.ts +266 -0
  568. package/src/steward/outcome-notify.ts +115 -0
  569. package/src/steward/steward-cards.ts +25 -11
  570. package/src/steward/triage-plan.ts +32 -4
  571. package/src/steward/triage.ts +129 -13
  572. package/src/steward/working-backwards.ts +64 -0
  573. package/src/storyboard/storyboard.ts +141 -0
  574. package/src/task-cards/card-cli.ts +25 -1
  575. package/src/task-cards/card-store.ts +2 -2
  576. package/src/task-orchestrator/mission.ts +5 -0
  577. package/src/task-orchestrator/store.ts +12 -3
  578. package/src/task-orchestrator/surfaces/pod-command-job.ts +29 -7
  579. package/src/task-orchestrator/surfaces/pod-lease.ts +397 -0
  580. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  581. package/src/task-orchestrator/surfaces/self-implement-pod.ts +214 -40
  582. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  583. package/src/task-orchestrator/types.ts +2 -0
  584. package/src/telegram-card-followup.ts +153 -0
  585. package/src/telegram-commands.ts +10 -1
  586. package/src/telegram-project-command.ts +71 -0
  587. package/src/telegram-report.ts +29 -19
  588. package/src/telegram-run.ts +7 -0
  589. package/src/telegram.ts +58 -11
  590. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  591. package/src/tool-runtime/types.ts +4 -0
  592. package/src/tui-client/dashboard-session.ts +2 -0
  593. package/src/user-config.ts +216 -27
  594. package/src/version/packed-revision.json +1 -1
  595. package/src/web-push/notify-exec-request.ts +32 -0
  596. package/src/web-search/grok.ts +7 -1
  597. package/src/web-search/index.ts +28 -1
  598. package/src/web-search/provider.ts +4 -0
  599. package/src/web-search/x-intent.ts +5 -0
  600. package/src/workflow-runtime/executor.ts +277 -47
  601. package/src/workflow-runtime/index.ts +1 -0
  602. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  603. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  604. package/src/workflow-runtime/schema.ts +79 -4
  605. package/src/workflow-runtime/types.ts +35 -4
  606. package/apps/pwa/out/_next/static/bFI5EEwg7T6aG88ibX4Zq/_buildManifest.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  617. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  618. package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/5080-1613752891fcadb4.js +0 -10
  622. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6090-85a3f05f954e5697.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6284-69db415193d5f8bd.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7032-f4ef698518fba61c.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/8067-d976b441a104ab74.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/8519-5632377cce994f86.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8630-cdfc61e82c653ffc.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8894-e263b332208e3957.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/9454-139040d37c79dbc9.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/9740-8f5ff96c522b5f55.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fb7c2d458f32fcad.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-35e2713597dd24d1.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/board/page-918b656f064577ba.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/bots/page-5f30e00693527ebd.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/chat/page-7fbae173b3c103a7.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b4edcce364062ea.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/control/page-c5794f484c251f44.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1130d8eefcd87e76.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/editor/page-973996d584f008c1.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/exec/page-016e2bda04eecb1f.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/field/page-b4d6d9a3b56f2940.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/intake/page-ec49a466121233ba.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/layout-f72db356744ceade.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/live/page-a6fd9b50d1b85378.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/market/page-8b0402a46a749a3d.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-037f83e2a1edc8e2.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/not-found-46fedff57d4bec67.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/observatory/page-0cf318e9dcee2bbf.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-899b327cb8b6845c.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6c1e6ba743a29dfe.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/page-1a8e4807292f6b17.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/reflection/page-28deba6bcb834916.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-de68e2205794037d.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/sessions/page-c71c33a573230672.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-0df30e0c7e50148a.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/settings/page-4fc56790fe0d2682.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-59df2aebb38a7c1e.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/setup/page-4647be5dbcbd0795.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/share/page-e025892bda74b743.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/showroom/page-a0955de73b89f078.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/tasks/page-369846d2921af584.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/term/page-72cbc1c8cdd0f65d.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/trace/page-77b28bfb0996d5ea.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/vault/page-3220c4934f49c6c2.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-90670589b87abea8.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/workflows/page-7df9243ed021a4cc.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/workspace/page-4498c3853f4f688d.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-35bedde6d885f08f.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/main-app-6870f30ea99f8346.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  692. package/apps/pwa/out/_next/static/css/f92f63a5df0ba229.css +0 -1
  693. package/src/dashboard/turn-typeahead-echo.ts +0 -23
  694. /package/apps/pwa/out/_next/static/{bFI5EEwg7T6aG88ibX4Zq → Y4zKzL62sakG5momz3SoQ}/_ssgManifest.js +0 -0
@@ -2,7 +2,8 @@
2
2
  * intake check → 골 저작 연결. 판정 「없음」마다 기존 골 중복을 먼저 보고, 없으면 골 저작기로 골 문서를 쓰고 lint 한 뒤 멈춘다.
3
3
  * 하니스는 발사하지 않는다. 골: 내부 문서 `ASK-intake-check-authors-goals-for-gaps-2026-09-24`
4
4
  */
5
- import { existsSync, readdirSync, readFileSync } from 'node:fs';
5
+ import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
6
+ import { CardStore, taskCardsDir } from '../task-cards/card-store.js';
6
7
  import { join, relative } from 'node:path';
7
8
  import { debug } from '../debug/log.js';
8
9
  import { resolveGoalDocumentsDir } from '../self-implement/goal-documents-dir.js';
@@ -42,7 +43,22 @@ function defaultGoalDocs(root: string): { path: string; text: string }[] {
42
43
  .map((name) => ({ path: relative(root, join(dir, name)), text: readFileSync(join(dir, name), 'utf8') }));
43
44
  }
44
45
 
45
- function authorAsk(item: IntakeCheckItem): string {
46
+ function prfaqSignals(sourceRef: string | undefined, root: string): { source: string; signals: string[] } | undefined {
47
+ if (!sourceRef?.startsWith('linear:') || !existsSync(taskCardsDir(root))) return undefined;
48
+ const store = new CardStore(root);
49
+ try {
50
+ const cards = store.listCards();
51
+ const matches = cards.filter(row => row.goalId === sourceRef);
52
+ const card = matches.length === 1 ? matches[0] : undefined;
53
+ const section = [...(card?.sections ?? [])].reverse().find(row => row.key.startsWith('prfaq:'));
54
+ if (!section) return undefined;
55
+ const criteria = section.content.split('⑧ 판정 기준')[1]?.split('⑨')[0] ?? '';
56
+ const signals = criteria.split('\n').map(line => line.trim().replace(/^-\s*/, '')).filter(line => /^판정 신호: 조건 = .+; 관측 = .+; 기대 = .+\.$/.test(line)).slice(0, 2);
57
+ return signals.length ? { source: `${card!.goalId} / ${section.key}`, signals } : undefined;
58
+ } finally { store.close(); }
59
+ }
60
+
61
+ function authorAsk(item: IntakeCheckItem, evidence?: { source: string; signals: string[] }): string {
46
62
  // The first line leads the ask and `제목:` is the title the author forwards (parseAskProseTitle), so both are the fact.
47
63
  return [
48
64
  item.fact,
@@ -52,9 +68,23 @@ function authorAsk(item: IntakeCheckItem): string {
52
68
  '백틱 이름은 대조에 쓴 검색 표지일 뿐이다 — 그 문자열이 저장소에 생기는 것을 판정 신호로 삼지 말고, 사실이 말하는 동작을 판정 신호로 쓴다.',
53
69
  `대조 결과: ${item.current}`,
54
70
  ...(item.quotes.length > 0 ? [`출처 인용: ${item.quotes.join(' / ')}`] : []),
71
+ ...(evidence ? [`아래 판정 신호를 골 문서 ## 판정 신호에 원문 그대로 인용하라. 출처: 카드 ${evidence.source}`, ...evidence.signals] : []),
55
72
  ].join('\n');
56
73
  }
57
74
 
75
+ function appendPrfaqSignals(document: string, evidence: { source: string; signals: string[] }): string {
76
+ const section = /^## 판정 신호\s*$/m.exec(document);
77
+ if (!section) throw new Error('Authored goal has no ## 판정 신호 section');
78
+ const start = section.index + section[0].length;
79
+ const end = document.slice(start).search(/^## /m);
80
+ const boundary = end < 0 ? document.length : start + end;
81
+ const block = document.slice(start, boundary);
82
+ const missing = evidence.signals.filter(signal => !block.includes(signal));
83
+ const source = block.includes(`출처: 카드 ${evidence.source}`) ? '' : `출처: 카드 ${evidence.source}\n`;
84
+ if (!missing.length && !source) return document;
85
+ return document.slice(0, boundary) + `\n${source}${missing.map(signal => `- ${signal}`).join('\n')}\n` + document.slice(boundary);
86
+ }
87
+
58
88
  export async function authorIntakeGoals(
59
89
  items: readonly IntakeCheckItem[],
60
90
  deps: IntakeAuthorDeps,
@@ -84,8 +114,11 @@ export async function authorIntakeGoals(
84
114
  }
85
115
  authored++;
86
116
  try {
87
- const written = await deps.author(authorAsk(item), `intake check: ${opts.source}`);
88
- const lintErrors = deps.lintErrors(written.document);
117
+ const evidence = prfaqSignals(item.sourceRef, deps.root);
118
+ const written = await deps.author(authorAsk(item, evidence), `intake check: ${opts.source}`);
119
+ const document = evidence ? appendPrfaqSignals(written.document, evidence) : written.document;
120
+ if (document !== written.document) writeFileSync(join(deps.root, written.path), document);
121
+ const lintErrors = deps.lintErrors(document);
89
122
  outcomes.push({ fact: item.fact, status: 'authored', goalPath: written.path, lintErrors });
90
123
  } catch (error) {
91
124
  outcomes.push({ fact: item.fact, status: 'author-failed', reason: error instanceof Error ? error.message : String(error) });
@@ -25,6 +25,7 @@ import type {
25
25
  } from './enrich.js';
26
26
  import { summariseContext } from './enrich.js';
27
27
  import { buildResponseFormatHeader } from './prompt-format.js';
28
+ import { judge } from '../llm/judge-layer.js';
28
29
 
29
30
  // ──────────────────── Closed sets ──────────────────────────────────────
30
31
 
@@ -69,7 +70,7 @@ export interface CategorizeResult {
69
70
  }
70
71
 
71
72
  export interface CategorizeCallable {
72
- (args: { prompt: string; signal?: AbortSignal }): Promise<{
73
+ (args: { prompt: string; signal?: AbortSignal; provider?: string; model?: string }): Promise<{
73
74
  text: string;
74
75
  promptTokens?: number;
75
76
  completionTokens?: number;
@@ -219,26 +220,6 @@ export function buildCategorizePrompt(decomposition: EnrichedDecomposition): str
219
220
 
220
221
  // ──────────────────── Parse + coerce ──────────────────────────────────
221
222
 
222
- function extractJsonBlock(text: string): unknown | null {
223
- const trimmed = text.trim();
224
- const fence = trimmed.match(/```(?:json)?\n([\s\S]*?)```/);
225
- const candidate = fence ? fence[1]! : trimmed;
226
- try {
227
- return JSON.parse(candidate);
228
- } catch {
229
- const open = candidate.indexOf('{');
230
- const close = candidate.lastIndexOf('}');
231
- if (open >= 0 && close > open) {
232
- try {
233
- return JSON.parse(candidate.slice(open, close + 1));
234
- } catch {
235
- return null;
236
- }
237
- }
238
- return null;
239
- }
240
- }
241
-
242
223
  function coerceConfidence(v: unknown): 'high' | 'medium' | 'low' {
243
224
  if (v === 'high' || v === 'medium' || v === 'low') return v;
244
225
  return 'medium';
@@ -306,27 +287,18 @@ export async function categorizeDecomposition(
306
287
 
307
288
  const prompt = buildCategorizePrompt(decomposition);
308
289
 
309
- let raw;
310
- try {
311
- raw = await opts.callable({ prompt, signal: opts.signal });
312
- } catch (err) {
313
- if (opts.strict) {
314
- throw new CategorizeError(
315
- 'LLM_CALL_FAILED',
316
- err instanceof Error ? err.message : String(err),
317
- );
318
- }
319
- return {
320
- categorizations: Object.fromEntries(tasks.map((t) => [t.key, fallbackRow(t.key)])),
321
- fallback: true,
322
- };
323
- }
324
-
325
- const parsed = extractJsonBlock(raw.text);
326
- const coerced = parsed ? coerceCategorizations(parsed, validKeys) : null;
327
- if (coerced === null) {
290
+ const decision = await judge({
291
+ site: 'intake.categorize', prompt, signal: opts.signal,
292
+ call: ({ prompt, signal, provider, model }) => opts.callable({ prompt, signal, provider, model }),
293
+ schema: (parsed) => coerceCategorizations(parsed, validKeys),
294
+ });
295
+ if (!decision.ok) {
328
296
  if (opts.strict) {
329
- throw new CategorizeError('PARSE_FAILED', 'no usable categorizations', raw.text);
297
+ if (decision.reason === 'call') {
298
+ throw new CategorizeError('LLM_CALL_FAILED',
299
+ decision.error instanceof Error ? decision.error.message : String(decision.error));
300
+ }
301
+ throw new CategorizeError('PARSE_FAILED', 'no usable categorizations', decision.rawText);
330
302
  }
331
303
  return {
332
304
  categorizations: Object.fromEntries(tasks.map((t) => [t.key, fallbackRow(t.key)])),
@@ -336,7 +308,7 @@ export async function categorizeDecomposition(
336
308
 
337
309
  // Backfill any missing tasks with the fallback shape so callers can
338
310
  // index by key without null checks.
339
- const filled: Record<string, TaskCategorization> = { ...coerced };
311
+ const filled: Record<string, TaskCategorization> = { ...decision.value };
340
312
  for (const t of tasks) {
341
313
  if (!filled[t.key]) filled[t.key] = fallbackRow(t.key);
342
314
  }
@@ -344,10 +316,10 @@ export async function categorizeDecomposition(
344
316
  categorizations: filled,
345
317
  fallback: false,
346
318
  usage: {
347
- promptTokens: raw.promptTokens,
348
- completionTokens: raw.completionTokens,
349
- costUsd: raw.costUsd,
350
- modelId: raw.modelId,
319
+ promptTokens: decision.reply.promptTokens,
320
+ completionTokens: decision.reply.completionTokens,
321
+ costUsd: decision.reply.costUsd,
322
+ modelId: decision.reply.modelId,
351
323
  },
352
324
  };
353
325
  }
@@ -63,6 +63,8 @@ export interface IntakeCheckEvidence {
63
63
 
64
64
  export interface IntakeCheckItem {
65
65
  readonly fact: string;
66
+ /** Source identity preserved from the supplied fact for card-backed goal evidence. */
67
+ readonly sourceRef?: string;
66
68
  readonly originalClaims?: readonly string[];
67
69
  readonly quotes: readonly string[];
68
70
  readonly verdict: IntakeCheckVerdict;
@@ -1415,6 +1417,7 @@ export function runIntakeCheck(
1415
1417
  const item: IntakeCheckItem = {
1416
1418
  ...judged,
1417
1419
  quotes: [quote],
1420
+ ...(fact.sourceRef ? { sourceRef: fact.sourceRef } : {}),
1418
1421
  ...(fact.originalClaim ? { originalClaims: [fact.originalClaim] } : {}),
1419
1422
  };
1420
1423
  merged.set(key, item);
@@ -1,4 +1,12 @@
1
+ import { debug } from '../debug/log.js';
2
+ import { discordDecisionOwner } from '../decisions/discord-decision-cards.js';
3
+ import { canonicalSeatId } from '../msg/msg-store.js';
4
+ import { dispatchCeoTask, type CeoCommandDeps } from '../seat-dispatch/ceo-commands.js';
5
+ import { ceoTaskDeps, classifyCeoIntent } from '../seat-dispatch/ceo-intent.js';
6
+ import { askSeat, parseSeatAsk, type SeatAskDeps } from '../seat-dispatch/seat-ask.js';
1
7
  import { parseSeatAddress, resolveSeat } from '../seat-address/seat-address.js';
8
+ import { getUserConfig, type UserConfig } from '../user-config.js';
9
+ import { answerAsSeat } from './seat-answer.js';
2
10
  import {
3
11
  submitIntakeWork,
4
12
  type SubmitIntakeWorkDeps,
@@ -7,21 +15,56 @@ import {
7
15
  export interface DiscordSeatWorkMessage {
8
16
  channelId: string;
9
17
  messageId: string;
18
+ userId?: string;
19
+ isDm?: boolean;
10
20
  threadId?: string;
11
21
  }
12
22
 
13
23
  export interface DiscordSeatWorkDeps extends SubmitIntakeWorkDeps {
14
24
  submit?: typeof submitIntakeWork;
25
+ config?: UserConfig;
26
+ answer?: typeof answerAsSeat;
27
+ dispatch?: typeof dispatchCeoTask;
28
+ commandDeps?: CeoCommandDeps;
29
+ askDeps?: SeatAskDeps;
15
30
  }
16
31
 
17
- /** Addressed Discord work goes through the graph intake door, not the chat turn. */
32
+ /** Addressed work preserves graph intake except for one owner's private seat request. */
18
33
  export async function handleDiscordSeatWork(
19
34
  text: string,
20
35
  msg: DiscordSeatWorkMessage,
21
36
  deps: DiscordSeatWorkDeps = {},
22
37
  ): Promise<string | null> {
38
+ const owner = (): { cfg: UserConfig; id: string } | null => {
39
+ if (!msg.isDm || !msg.userId) return null;
40
+ const cfg = deps.config ?? getUserConfig();
41
+ const id = discordDecisionOwner(cfg);
42
+ return id && id === msg.userId ? { cfg, id } : null;
43
+ };
44
+ const sendTask = async (seat: string, body: string, cfg: UserConfig, id: string): Promise<string> => {
45
+ const result = await (deps.dispatch ?? dispatchCeoTask)(seat, body, deps.commandDeps ?? ceoTaskDeps(cfg, id), { via: 'discord' });
46
+ debug.log('seat.dispatch', 'intent', { seat, intent: 'task', via: 'discord', outcome: result.channel });
47
+ return result.reply;
48
+ };
49
+ if (parseSeatAsk(text)) {
50
+ const auth = owner();
51
+ if (!auth) return null;
52
+ if (!deps.askDeps) throw new Error('seat ask delivery unavailable');
53
+ return askSeat(text, { channel: 'discord', channelId: msg.channelId, messageId: msg.messageId,
54
+ ...(msg.threadId ? { threadId: msg.threadId } : {}) },
55
+ deps.commandDeps ?? ceoTaskDeps(auth.cfg, auth.id), deps.askDeps);
56
+ }
23
57
  const address = parseSeatAddress(text);
24
- if (!address) return null;
58
+ if (!address) {
59
+ if (!text.trim() || /^\s*[/@@]/.test(text)) return null;
60
+ const auth = owner();
61
+ const configured = (auth?.cfg.raw?.seatDispatch as { defaultSeat?: unknown } | undefined)?.defaultSeat;
62
+ if (typeof configured !== 'string' || classifyCeoIntent(text) !== 'task') return null;
63
+ const seat = resolveSeat(configured);
64
+ if (!seat) return null;
65
+ const id = canonicalSeatId(seat.id);
66
+ return ['OP', 'TC', 'MK', 'UX'].includes(id) ? sendTask(id, text, auth!.cfg, auth!.id) : null;
67
+ }
25
68
 
26
69
  const seats = address.seats.map((name) => ({ name, seat: resolveSeat(name) }));
27
70
  const unknown = seats.filter(({ seat }) => !seat).map(({ name }) => `@${name}`);
@@ -29,6 +72,18 @@ export async function handleDiscordSeatWork(
29
72
  const body = address.body.trim();
30
73
  if (!body) return '어떤 일을 맡길까요? 좌석 주소 뒤에 요청 내용을 적어 다시 보내 주세요.';
31
74
 
75
+ if (seats.length === 1 && seats[0]?.seat) {
76
+ const auth = owner();
77
+ const seatId = canonicalSeatId(seats[0].seat.id);
78
+ if (auth && ['OP', 'TC', 'MK', 'UX'].includes(seatId)) {
79
+ const intent = classifyCeoIntent(body);
80
+ if (intent === 'task') return sendTask(seatId, body, auth.cfg, auth.id);
81
+ const answer = await (deps.answer ?? answerAsSeat)(seats[0].name, body);
82
+ debug.log('seat.dispatch', 'intent', { seat: seatId, intent, via: 'discord', outcome: answer ? 'answered' : 'intake' });
83
+ if (answer) return answer.text;
84
+ }
85
+ }
86
+
32
87
  const reportTo = {
33
88
  channel: 'discord' as const,
34
89
  channelId: msg.channelId,
@@ -1,7 +1,6 @@
1
1
  import { debug } from '../debug/log.js';
2
- import type { ModelRole } from '../user-config.js';
3
- import type { ResolveRoleProviderFn, StreamLlmFn, ProviderRegistry } from './runtime-callables.js';
4
- import { extractJsonBlock } from './decompose.js';
2
+ import type { ResolveRoleProviderFn, StreamLlmFn } from './runtime-callables.js';
3
+ import { judge } from '../llm/judge-layer.js';
5
4
  import {
6
5
  INTAKE_FRONT_ROUTE_TRACKS,
7
6
  type IntakeFrontRouteDecision,
@@ -14,17 +13,6 @@ interface ClassifierDeps {
14
13
  minConfidence?: number;
15
14
  }
16
15
 
17
- function loadRoleProvider(): ResolveRoleProviderFn {
18
- const { resolveRoleLlm } = require('../user-config.js') as {
19
- resolveRoleLlm: (role: ModelRole) => { provider: string; model: string };
20
- };
21
- const { PROVIDERS } = require('../llm.js') as { PROVIDERS: ProviderRegistry };
22
- return (role) => {
23
- const resolved = resolveRoleLlm(role);
24
- return { provider: PROVIDERS[resolved.provider] ?? { name: resolved.provider }, model: resolved.model };
25
- };
26
- }
27
-
28
16
  /** Classify only after the deterministic front-route rules return rule-unknown. */
29
17
  export async function classifyIntakeFrontRoute(
30
18
  text: string,
@@ -43,32 +31,38 @@ export async function classifyIntakeFrontRoute(
43
31
  const failed = (cause: string) => finish('ask-human', 0, `classifier-failed:${cause}`, 'failed');
44
32
 
45
33
  try {
46
- const rolePick = (deps.resolveRoleProvider ?? loadRoleProvider())('classify');
47
- provider = rolePick.provider.name;
48
- const streamLLM = deps.streamLLM ?? (require('../llm.js') as { streamLLM: StreamLlmFn }).streamLLM;
49
- const response = await streamLLM([
50
- { role: 'system', content: [
51
- 'Classify the intake text into exactly one track:',
52
- 'absorb: read, save, or summarize external material.',
53
- 'tasks: a list of independent to-dos.',
54
- 'graph: an implementation or multi-step workflow request.',
55
- 'ask-human: ambiguous intent requiring human choice.',
56
- 'Return only one JSON object: {"track":"...","confidence":0.0,"reason":"..."}. Confidence must be between 0 and 1.',
57
- ].join('\n') },
58
- { role: 'user', content: text },
59
- ], () => {}, { provider: rolePick.provider, ...(rolePick.model ? { model: rolePick.model } : {}), usageRole: 'classify' });
60
-
61
- // 실제 모델은 JSON 을 ```json 펜스로 감싸거나 앞뒤에 말을 붙이곤 한다 — 같은 디렉토리의 다른 호출자와 같은 관대한 추출을 쓴다.
62
- const parsed: unknown = extractJsonBlock(response);
63
- if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) return failed('invalid-json');
64
- const candidate = parsed as Record<string, unknown>;
65
- if (typeof candidate.track !== 'string' ||
66
- !(INTAKE_FRONT_ROUTE_TRACKS as readonly string[]).includes(candidate.track)) return failed('invalid-track');
67
- if (typeof candidate.confidence !== 'number' || !Number.isFinite(candidate.confidence) ||
68
- candidate.confidence < 0 || candidate.confidence > 1) return failed('invalid-confidence');
69
- if (typeof candidate.reason !== 'string') return failed('invalid-reason');
34
+ const decision = await judge({
35
+ site: 'intake.front-route',
36
+ prompt: text,
37
+ messages: [
38
+ { role: 'system', content: [
39
+ 'Classify the intake text into exactly one track:',
40
+ 'absorb: read, save, or summarize external material.',
41
+ 'tasks: a list of independent to-dos.',
42
+ 'graph: an implementation or multi-step workflow request.',
43
+ 'ask-human: ambiguous intent requiring human choice.',
44
+ 'Return only one JSON object: {"track":"...","confidence":0.0,"reason":"..."}. Confidence must be between 0 and 1.',
45
+ ].join('\n') },
46
+ { role: 'user', content: text },
47
+ ],
48
+ streamLLM: deps.streamLLM,
49
+ resolveRoleProvider: deps.resolveRoleProvider,
50
+ schema: (parsed) => {
51
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) return null;
52
+ const candidate = parsed as Record<string, unknown>;
53
+ if (typeof candidate.track !== 'string' ||
54
+ !(INTAKE_FRONT_ROUTE_TRACKS as readonly string[]).includes(candidate.track)) return null;
55
+ if (typeof candidate.confidence !== 'number' || !Number.isFinite(candidate.confidence) ||
56
+ candidate.confidence < 0 || candidate.confidence > 1) return null;
57
+ if (typeof candidate.reason !== 'string') return null;
58
+ return { track: candidate.track as IntakeFrontRouteTrack, confidence: candidate.confidence, reason: candidate.reason };
59
+ },
60
+ });
61
+ provider = decision.ok ? decision.provider : provider;
62
+ if (!decision.ok) return failed(decision.reason === 'schema' ? 'invalid-json' : 'llm-error');
63
+ const candidate = decision.value;
70
64
 
71
- const track = candidate.track as IntakeFrontRouteTrack;
65
+ const track = candidate.track;
72
66
  const confidence = candidate.confidence;
73
67
  if (confidence < (deps.minConfidence ?? 0.6)) {
74
68
  return finish('ask-human', confidence, `classifier-low-confidence:${track}`, 'low-confidence');
@@ -0,0 +1,30 @@
1
+ import { debug } from '../debug/log.js';
2
+ import { resolveMention, type PersonaSource } from '../persona/mention-parser.js';
3
+ import type { PersonaProfile } from '../persona/types.js';
4
+
5
+ export interface PersonaAnswerDeps {
6
+ complete?: (prompt: string) => Promise<string>;
7
+ }
8
+
9
+ /** Resolve the registry mention first, then an exact display name. */
10
+ export function resolvePersonaAddress(name: string, source: PersonaSource): PersonaProfile | null {
11
+ const mention = resolveMention(name, source);
12
+ if (mention) return mention;
13
+ const needle = name.replace(/^@/, '').toLocaleLowerCase();
14
+ return source.list().find((persona) => persona.displayName.toLocaleLowerCase() === needle) ?? null;
15
+ }
16
+
17
+ async function defaultComplete(prompt: string): Promise<string> {
18
+ const { streamLLM } = await import('../llm.js');
19
+ const { tierModel } = await import('../llm/model-defaults.js');
20
+ return streamLLM([{ role: 'user', content: prompt }], () => {}, { model: tierModel('better') });
21
+ }
22
+
23
+ export async function answerAsPersona(persona: PersonaProfile, question: string, deps: PersonaAnswerDeps = {}): Promise<string> {
24
+ const prompt = `${persona.systemPrompt ?? `너는 ${persona.displayName} 이다`}\n\n## 질문\n${question}`;
25
+ const raw = await (deps.complete ?? defaultComplete)(prompt);
26
+ const answer = `@${persona.displayName}\n${raw.trim()}`;
27
+ const text = Array.from(answer).slice(0, 3_500).join('');
28
+ debug.log('persona.address', 'answered', { personaId: persona.personaId, chars: Array.from(text).length });
29
+ return text;
30
+ }
@@ -305,7 +305,14 @@ export function buildRealIntakeCallables(
305
305
  };
306
306
 
307
307
  const decompose: DecomposeMemoCallable = (args) => promptCallable(args);
308
- const categorize: CategorizeCallable = (args) => promptCallable(args);
308
+ const categorize: CategorizeCallable = async (args) => {
309
+ const text = await streamLLM([{ role: 'user', content: args.prompt }], () => {}, {
310
+ ...(args.provider ? { provider: providers[args.provider] } : {}),
311
+ ...(args.model ? { model: args.model } : {}),
312
+ ...(args.signal ? { signal: args.signal } : {}), usageRole: 'classify',
313
+ });
314
+ return { text, modelId: args.model };
315
+ };
309
316
  const align: AlignCallable = (args) => promptCallable(args);
310
317
 
311
318
  /** Synth callable — wraps R3 `synthWorkflowFromIntent`. Hands it a
@@ -1,6 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { readFileSync } from 'node:fs';
3
- import { join } from 'node:path';
2
+ import { readFileSync, realpathSync, statSync } from 'node:fs';
3
+ import { isAbsolute, join, relative, resolve } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import type { MissionOrigin } from '../autopilot/mission-origin.js';
6
6
  import { debug } from '../debug/log.js';
@@ -15,7 +15,7 @@ import { answerAsSeat, isNoGraphFailure } from './seat-answer.js';
15
15
  const POLL_MS = 5_000;
16
16
  const TIMEOUT_MS = 30 * 60_000;
17
17
  const DOC = /전략|한\s*장|원페이저|기획|보도자료|글|메모|초안|\b(?:one-pager|strategy|post|memo|draft)\b/i;
18
- const CODE = /구현|버그|고쳐|\b(?:fix|implement|PR)\b/i;
18
+ const CODE = /구현|버그|고쳐|\b(?:fix|implement)\b|\bPR\b(?!\s*#?\d+\b)/i;
19
19
  const RESEARCH = /전략|시장|경쟁|\bstrategy\b/i;
20
20
  /** EV12a — a question or a request for status / a report is answered, never turned into a code goal. */
21
21
  const ASK = /상황|현황|진행|준비|어때|어떻게|알려|보고|정리|요약|공유|\?|?|\b(?:status|update|report|summary|summari[sz]e|how|what)\b/i;
@@ -30,6 +30,8 @@ export interface SeatDocDeps {
30
30
  submitExec?: (text: string) => Promise<{ id: string }>;
31
31
  getExec?: (id: string) => Promise<ExecSnapshot | null>;
32
32
  getFile?: (path: string) => Promise<string>;
33
+ /** Resolve only references explicitly supplied in the request; null means their claims cannot be verified. */
34
+ readSource?: (ref: string) => Promise<string | null>;
33
35
  publishFile?: (content: string, key: string) => string | null;
34
36
  sendOutbound?: typeof sendOutbound;
35
37
  sleep?: (ms: number) => Promise<void>;
@@ -97,6 +99,160 @@ async function execFile(path: string): Promise<string> {
97
99
  return (await execResponse(path.slice('/v1/exec-requests'.length))).text();
98
100
  }
99
101
 
102
+ const SUPPLIED_REF = /https?:\/\/[^\s<>()[\]]+|\bPR\s*#?\d+\b|(?:\.?\.?\/|[\w.-]+\/)[\w./-]+\.(?:md|txt|csv|json|pdf)\b|\b[\w.-]+\.(?:md|txt|csv|json|pdf)\b/gi;
103
+ // Keep units and grammatical particles with the figure; never backtrack from 42% to 42.
104
+ const NUMBER = /(?<![\p{L}\p{N}_#.,])([+-]?\d+(?:[,.]\d+)*(?:(?:%|년|월|일|명|건|원|배)(?![\p{N}_%A-Za-z]|[.,]\d)|(?![\p{L}\p{N}_%]|[.,]\d)))(은|는|이|가|을|를|에|의|도|만|에서|으로|와|과)?/gu;
105
+
106
+ function suppliedReferences(text: string): string[] {
107
+ return [...new Set([...text.matchAll(SUPPLIED_REF)].map(([ref]) => ref!.replace(/[.,;]+$/, '')))];
108
+ }
109
+
110
+ const SOURCE_TIMEOUT_MS = 5_000;
111
+ const MAX_SOURCE_BYTES = 200_000;
112
+ // The default resolver only reads repository-local files and these two public HTTPS hosts.
113
+ const SOURCE_URL_HOSTS = new Set(['github.com', 'raw.githubusercontent.com']);
114
+
115
+ function allowedSourceUrl(value: string): boolean {
116
+ try {
117
+ const url = new URL(value);
118
+ return url.protocol === 'https:' && SOURCE_URL_HOSTS.has(url.hostname)
119
+ && !url.username && !url.password && !url.port;
120
+ } catch { return false; }
121
+ }
122
+
123
+ async function readPublicSource(ref: string): Promise<string | null> {
124
+ let url = ref;
125
+ const signal = AbortSignal.timeout(SOURCE_TIMEOUT_MS);
126
+ for (let redirects = 0; redirects < 3; redirects++) {
127
+ if (!allowedSourceUrl(url)) return null;
128
+ const response = await fetch(url, { signal, redirect: 'manual' });
129
+ if (response.status >= 300 && response.status < 400) {
130
+ const location = response.headers.get('location');
131
+ if (!location) return null;
132
+ url = new URL(location, url).href;
133
+ continue;
134
+ }
135
+ if (!response.ok || !/^(?:text\/|application\/(?:json|xml))/.test(response.headers.get('content-type') ?? '')) return null;
136
+ if (Number(response.headers.get('content-length') ?? 0) > MAX_SOURCE_BYTES) {
137
+ await response.body?.cancel();
138
+ return null;
139
+ }
140
+ if (!response.body) return null;
141
+ const reader = response.body.getReader();
142
+ const chunks: Uint8Array[] = [];
143
+ let size = 0;
144
+ try {
145
+ while (true) {
146
+ const { done, value } = await reader.read();
147
+ if (done) break;
148
+ size += value.byteLength;
149
+ if (size > MAX_SOURCE_BYTES) return null;
150
+ chunks.push(value);
151
+ }
152
+ const bytes = new Uint8Array(size);
153
+ let offset = 0;
154
+ for (const chunk of chunks) { bytes.set(chunk, offset); offset += chunk.byteLength; }
155
+ return new TextDecoder().decode(bytes);
156
+ } finally {
157
+ if (size > MAX_SOURCE_BYTES) await reader.cancel();
158
+ reader.releaseLock();
159
+ }
160
+ }
161
+ return null;
162
+ }
163
+
164
+ async function defaultReadSource(ref: string): Promise<string | null> {
165
+ try {
166
+ if (/^https?:\/\//i.test(ref)) return await readPublicSource(ref);
167
+ if (/^PR\s*#?\d+$/i.test(ref)) {
168
+ const number = ref.match(/\d+/)![0];
169
+ const child = Bun.spawn(['gh', 'pr', 'view', number, '--json', 'title,body'], { stdout: 'pipe', stderr: 'ignore' });
170
+ let timer: ReturnType<typeof setTimeout> | undefined;
171
+ const timeout = new Promise<null>(finish => {
172
+ timer = setTimeout(() => { child.kill(9); finish(null); }, SOURCE_TIMEOUT_MS);
173
+ });
174
+ try {
175
+ const result = await Promise.race([
176
+ Promise.all([new Response(child.stdout).text(), child.exited]).then(([out, code]) => ({ out, code })),
177
+ timeout,
178
+ ]);
179
+ if (!result || result.code !== 0 || result.out.length > MAX_SOURCE_BYTES) return null;
180
+ const pr = JSON.parse(result.out) as { title?: string; body?: string };
181
+ return `${pr.title ?? ''}\n${pr.body ?? ''}`;
182
+ } finally { clearTimeout(timer); }
183
+ }
184
+ const root = realpathSync(process.cwd());
185
+ const actual = realpathSync(resolve(root, ref));
186
+ const within = relative(root, actual);
187
+ if (isAbsolute(within) || within === '..' || within.startsWith('../')) return null;
188
+ const file = statSync(actual);
189
+ if (!file.isFile() || file.size > MAX_SOURCE_BYTES || /\.pdf$/i.test(actual)) return null;
190
+ return readFileSync(actual, 'utf8');
191
+ } catch { return null; }
192
+ }
193
+
194
+ function citationFor(ref: string): string {
195
+ return /^PR\s*#?(\d+)$/i.test(ref) ? `PR #${ref.match(/\d+/)![0]}` : ref;
196
+ }
197
+
198
+ function claimLabel(line: string, offset: number, length: number): string | null {
199
+ const before = line.slice(0, offset).split(/[,;:,;。.!?\n]/).at(-1) ?? '';
200
+ const after = (line.slice(offset + length).split(/[,;:,;。.!?\n]/)[0] ?? '').replace(/^\s*(?:\[출처: [^\]]+\]|«확인 필요»)/, '');
201
+ // Never borrow a label from another figure in the same clause.
202
+ if ([...before.matchAll(NUMBER), ...after.matchAll(NUMBER)].length) return null;
203
+ const left = before.trim().replace(/^(?:[#*>-]+\s*)+/, '');
204
+ const right = after.match(/^\s*([\p{L}]{2,}(?:\s+[\p{L}]{2,})*)/u)?.[1];
205
+ return /[\p{L}]{2,}/u.test(left) ? left : right ?? null;
206
+ }
207
+
208
+ const CLAIM_DIRECTION = /증가|상승|성장|확대|개선|감소|하락|축소|악화/g;
209
+ const CLAIM_FORECAST = /예상|전망|예측|추정|계획|예정|기대|목표|가능성/;
210
+ // Range and approximation words change what a figure claims («42%» ≠ «42% 미만»); both sides must carry the same set.
211
+ const CLAIM_QUALIFIER = /미만|이하|이상|초과|이내|약|최대|최소|가량|정도|내외|안팎|넘게|넘는|남짓|까지|부터|대략|거의|이상의|under|over|about|up to|at least|at most|less than|more than|nearly|almost/giu;
212
+
213
+ function claimDirection(segment: string): string | undefined {
214
+ const directions = [...segment.matchAll(CLAIM_DIRECTION)];
215
+ if (directions.length > 1) return undefined;
216
+ const direction = directions[0];
217
+ const after = direction ? segment.slice(direction.index + direction[0].length) : '';
218
+ const negated = direction && /^\s*(?:하지\s*(?:않|못)|않|못|안\s*(?:했|함)|없|아니)/u.test(after);
219
+ // Polarity outside the recognized predicate is ambiguous; do not use it to establish provenance.
220
+ if (/않|못|안\s|없|아니/u.test(segment) && !negated) return undefined;
221
+ const qualifiers = [...new Set([...segment.matchAll(CLAIM_QUALIFIER)].map(match => match[0].toLowerCase().replace(/^이상의$/, '이상')))].sort().join(',');
222
+ return `${direction?.[0] ?? ''}|${negated ? 'negated' : 'affirmed'}|${CLAIM_FORECAST.test(segment) ? 'forecast' : 'observed'}|${qualifiers}`;
223
+ }
224
+
225
+ function hasClaimPair(source: string, number: string, label: string, direction: string | undefined): boolean {
226
+ if (direction === undefined) return false;
227
+ return source.split(/\n|,(?=\s)|[;:,;。!?]|\.(?!\d)/).some(segment => {
228
+ const figures = [...segment.matchAll(NUMBER)];
229
+ if (figures.length !== 1 || figures[0]![1] !== number) return false;
230
+ return claimLabel(segment, figures[0]!.index, figures[0]![0].length) === label
231
+ && claimDirection(segment) === direction;
232
+ });
233
+ }
234
+
235
+ function citeDocumentNumbers(content: string, sources: Map<string, string | null>): string {
236
+ let fenced = false;
237
+ return content.split('\n').map(line => {
238
+ if (/^\s*```/.test(line)) { fenced = !fenced; return line; }
239
+ if (fenced || /^\s*(?:참고 자료|출처:)/.test(line)) return line;
240
+ const occupied = [...line.matchAll(/https?:\/\/\S+|\[출처: [^\]]+\]|(?:\.?\.?\/|[\w.-]+\/)[\w./-]+\.(?:md|txt|csv|json|pdf)|\b[\w.-]+\.(?:md|txt|csv|json|pdf)\b/g)]
241
+ .map(match => [match.index, match.index + match[0].length] as const);
242
+ const annotated = new RegExp(`${NUMBER.source}(?:\\s*(?:\\[출처: [^\\]]+\\]|«확인 필요»))?`, 'gu');
243
+ return line.replace(annotated, (claim, number: string, particle: string | undefined, offset: number) => {
244
+ if (occupied.some(([start, end]) => offset >= start && offset < end)) return claim;
245
+ const figure = `${number}${particle ?? ''}`;
246
+ const label = claimLabel(line, offset, claim.length);
247
+ const before = line.slice(0, offset).split(/[,;:,;。.!?]/).at(-1) ?? '';
248
+ const after = line.slice(offset + claim.length).split(/[,;:,;。.!?]/)[0] ?? '';
249
+ const direction = claimDirection(`${before} ${after}`);
250
+ const matches = label ? [...sources].filter(([, source]) => source && hasClaimPair(source, number, label, direction)) : [];
251
+ return matches.length === 1 ? `${figure} [출처: ${citationFor(matches[0]![0])}]` : `${figure} «확인 필요»`;
252
+ });
253
+ }).join('\n');
254
+ }
255
+
100
256
  function chatPwaUrl(): string | undefined {
101
257
  const endpoint = resolveDaemonEndpoint({ purpose: 'write' });
102
258
  return endpoint?.pwaUrl;
@@ -115,14 +271,15 @@ function accessiblePwaUrl(value: string | undefined): string | undefined {
115
271
  } catch { return undefined; }
116
272
  }
117
273
 
118
- async function fileLinks(id: string, result: ExecSnapshot, deps: SeatDocDeps): Promise<Map<string, string>> {
274
+ async function fileLinks(id: string, result: ExecSnapshot, deps: SeatDocDeps, sources: Map<string, string | null>): Promise<Map<string, string>> {
119
275
  const links = new Map<string, string>();
120
276
  for (const entry of result.results) {
121
277
  if (entry.kind !== 'report' && entry.kind !== 'text') continue;
122
278
  if (!entry.url.startsWith(`/v1/exec-requests/${encodeURIComponent(id)}/files/`)) continue;
123
279
  try {
124
280
  // The authenticated daemon route is the only source of bytes; a raw file path is never trusted.
125
- const content = await (deps.getFile ?? execFile)(entry.url);
281
+ const raw = await (deps.getFile ?? execFile)(entry.url);
282
+ const content = sources.size ? citeDocumentNumbers(raw, sources) : raw;
126
283
  const ext = entry.kind === 'report' ? 'md' : 'txt';
127
284
  const digest = createHash('sha256').update(content).digest('hex');
128
285
  const key = `seat-doc/${encodeURIComponent(id)}/${digest}.${ext}`;
@@ -158,6 +315,13 @@ export async function submitSeatDocRequest({ text, reportTo, deps = {} }: {
158
315
  const body = parseSeatAddress(text)?.body.trim() ?? text.trim();
159
316
  let withoutResearch = false;
160
317
  let requestText = text;
318
+ const refs = suppliedReferences(body);
319
+ const sources = new Map<string, string | null>();
320
+ for (const ref of refs) {
321
+ try { sources.set(ref, await (deps.readSource ?? defaultReadSource)(ref)); }
322
+ catch { sources.set(ref, null); }
323
+ }
324
+ if (refs.length) requestText += '\n\n문서 수치 근거 규칙: 제공된 파일·URL·PR 번호의 실제 내용을 확인하고, 근거가 확인된 각 수치 바로 뒤에 [출처: <파일|PR|명령>] 형식으로 실물 참조를 붙이세요. 근거를 확인할 수 없는 수치는 삭제하거나 바꾸지 말고 «확인 필요»로 표시하세요. 서로 다른 출처에 같은 숫자가 있다는 이유만으로 출처를 추정하지 마세요.';
161
325
  if (RESEARCH.test(body)) {
162
326
  try {
163
327
  const sources = (await (deps.research ?? research)(body)).slice(0, 5);
@@ -196,7 +360,7 @@ export async function submitSeatDocRequest({ text, reportTo, deps = {} }: {
196
360
  if (now() < deadline) await sleep(Math.min(POLL_MS, Math.max(0, deadline - now())));
197
361
  }
198
362
  log('settled', { id, status: result?.status ?? (lookupAvailable ? 'timeout' : 'lookup-unavailable'), lastConfirmedStatus });
199
- const links = result?.status === 'done' ? await fileLinks(id, result, deps) : new Map<string, string>();
363
+ const links = result?.status === 'done' ? await fileLinks(id, result, deps, sources) : new Map<string, string>();
200
364
  let reply = message(id, result, withoutResearch, lookupAvailable, accessiblePwaUrl((deps.pwaUrl ?? chatPwaUrl)()), links);
201
365
  if (isNoGraphFailure(result)) {
202
366
  // EV12d — a question with no fitting graph gets the seat's own answer, not «문서 요청 실패».