elanous 0.2.10 → 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 (584) 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/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
  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-54b32bd27726588d.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-35414e0a007b4082.js +1 -0
  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 -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/drafts/draft-cleanup.yaml +19 -0
  192. package/graphs/drafts/recipes.yaml +23 -0
  193. package/graphs/intake/intake-daily.yaml +2 -1
  194. package/graphs/ops/recipes.yaml +3 -0
  195. package/graphs/ops/secret-exposure.yaml +24 -0
  196. package/graphs/release/recipes.yaml +3 -0
  197. package/graphs/release/release-loop.yaml +4 -1
  198. package/graphs/video/explainer-line.yaml +2 -2
  199. package/package.json +2 -1
  200. package/plugins/elanous-hwp/README.md +25 -0
  201. package/plugins/elanous-hwp/cli.ts +22 -0
  202. package/plugins/elanous-hwp/converter.ts +237 -0
  203. package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
  204. package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
  205. package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
  206. package/plugins/elanous-hwp/plugin.json +16 -0
  207. package/plugins/elanous-hwp/plugin.ts +40 -0
  208. package/scripts/ci-public-export-leak-gate.ts +75 -14
  209. package/scripts/ci-public-leak-gate.ts +44 -9
  210. package/scripts/context-hooks/claude-stop.sh +4 -0
  211. package/scripts/context-hooks/emit.ts +24 -0
  212. package/scripts/context-hooks/post-tool-use.sh +4 -0
  213. package/scripts/coord-channel-watch.sh +12 -0
  214. package/scripts/coord-requests-bridge.ts +143 -0
  215. package/scripts/field-feed/lib.ts +4 -0
  216. package/scripts/fleet/node-setup.sh +20 -3
  217. package/scripts/homebrew-formula-bump.ts +69 -0
  218. package/scripts/marketing/measure-site-numbers.ts +169 -0
  219. package/scripts/measure-gate-shards.ts +309 -0
  220. package/scripts/mission-request-judge.ts +31 -1
  221. package/scripts/morning-report.ts +2 -2
  222. package/scripts/opportunity-scan.ts +1 -1
  223. package/scripts/release-loop/auto-approve-node.ts +21 -4
  224. package/scripts/release-loop/cut-branch.ts +84 -0
  225. package/scripts/release-loop/gate-node.ts +14 -13
  226. package/scripts/release-loop/mac-smoke-node.ts +229 -0
  227. package/scripts/release-loop/node-verdict.ts +3 -3
  228. package/scripts/release-loop/tui-node-checks.ts +42 -0
  229. package/scripts/release-loop/tui-sim-node.ts +32 -8
  230. package/scripts/release-loop/unattended-release.ts +5 -3
  231. package/scripts/release-loop/version-node.ts +61 -10
  232. package/scripts/signal-digest-cycle.ts +2 -7
  233. package/scripts/signal-digest-photo.ts +11 -0
  234. package/scripts/tech1-public-measure.ts +94 -0
  235. package/scripts/test-diet/node.ts +1 -1
  236. package/scripts/tui-regress.ts +2 -2
  237. package/scripts/ux/demo-rehearsal.ts +243 -0
  238. package/scripts/ux/lib/rehearsal-verdict.ts +73 -0
  239. package/skills/diagram-master/SKILL.md +366 -0
  240. package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
  241. package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
  242. package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
  243. package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
  244. package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
  245. package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
  246. package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
  247. package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
  248. package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
  249. package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
  250. package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
  251. package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
  252. package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
  253. package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
  254. package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
  255. package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
  256. package/skills/diagram-master/references/examples/README.md +69 -0
  257. package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
  258. package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
  259. package/skills/diagram-master/references/pyproject.toml +16 -0
  260. package/skills/diagram-master/references/quality-checklist.md +33 -0
  261. package/skills/diagram-master/references/routing-guide.md +164 -0
  262. package/skills/diagram-master/references/uv.lock +1356 -0
  263. package/skills/google-workspace/SKILL.md +33 -0
  264. package/skills/google-workspace/scripts/gws-safe.sh +177 -0
  265. package/skills/grill-me/SKILL.md +1 -1
  266. package/skills/lecture-note-digitizer/SKILL.md +926 -0
  267. package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
  268. package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
  269. package/skills/lecture-note-digitizer/references/html-template.md +167 -0
  270. package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
  271. package/skills/omni-crawl/SKILL.md +21 -11
  272. package/skills/omni-crawl/scripts/main.ts +6 -6
  273. package/skills/omni-crawl/src/router.ts +3 -3
  274. package/skills/omni-digest/SKILL.md +17 -9
  275. package/skills/omni-digest/digest.md +2 -2
  276. package/skills/omni-digest/src/fetch.ts +30 -3
  277. package/skills/pitch-deck/SKILL.md +2 -2
  278. package/skills/pitch-deck/template.html +2 -2
  279. package/skills/youtube-master/SKILL.md +163 -0
  280. package/skills/youtube-master/package-lock.json +558 -0
  281. package/skills/youtube-master/package.json +13 -0
  282. package/skills/youtube-master/references/study-note-template.md +124 -0
  283. package/skills/youtube-master/scripts/main.ts +435 -0
  284. package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
  285. package/skills/youtube-master/src/audio.ts +63 -0
  286. package/skills/youtube-master/src/domain-staging.ts +50 -0
  287. package/skills/youtube-master/src/env.ts +36 -0
  288. package/skills/youtube-master/src/obsidian.ts +155 -0
  289. package/skills/youtube-master/src/router.ts +110 -0
  290. package/skills/youtube-master/src/stt.ts +199 -0
  291. package/skills/youtube-master/src/study-note.ts +175 -0
  292. package/skills/youtube-master/src/summarize.ts +358 -0
  293. package/skills/youtube-master/src/transcript.ts +76 -0
  294. package/skills/youtube-master/src/types.ts +91 -0
  295. package/skills/youtube-master/src/util.ts +93 -0
  296. package/skills/youtube-master/src/youtube.ts +70 -0
  297. package/skills/youtube-master/tsconfig.json +13 -0
  298. package/src/acp/server.ts +5 -2
  299. package/src/agent-mission/driver.ts +80 -10
  300. package/src/agent-mission/pty-decision.ts +71 -0
  301. package/src/agent-mission/review-loop.ts +30 -0
  302. package/src/autopilot/build/llm-conflict-merge.ts +16 -3
  303. package/src/autopilot/tool-registry.ts +2 -0
  304. package/src/boot/daemon-prompt-turn.ts +5 -0
  305. package/src/boot/daemon-runtime.ts +9 -3
  306. package/src/boot/daemon-tools/web-search.ts +3 -0
  307. package/src/card-followup/core.ts +109 -0
  308. package/src/chat/index.ts +1 -0
  309. package/src/cli/drive-input-jail.ts +101 -0
  310. package/src/cli/hooks-cli.ts +17 -3
  311. package/src/cli/make-cli.ts +43 -0
  312. package/src/cli/persona-cli.ts +90 -4
  313. package/src/cli/plugin-cli.ts +31 -22
  314. package/src/cli/pod-cli.ts +19 -9
  315. package/src/cli/pr-cli.ts +51 -15
  316. package/src/cli/pty-drive-cli.ts +41 -7
  317. package/src/cli/pty-drive-verdict.ts +40 -0
  318. package/src/cli/release-cli.ts +17 -4
  319. package/src/cli/setup-cli.ts +43 -1
  320. package/src/cli/skills-cli.ts +17 -1
  321. package/src/context-bus/claude-hooks-install.ts +10 -0
  322. package/src/context-bus/context-now-surfaces.ts +48 -0
  323. package/src/context-bus/context-now.ts +104 -0
  324. package/src/context-bus/coord-events.ts +2 -2
  325. package/src/context-bus/external-events.ts +52 -0
  326. package/src/context-bus/long-term-memory.ts +108 -0
  327. package/src/dashboard/index.ts +9 -4
  328. package/src/dashboard/slash-runtime/dashboard-handlers.ts +7 -1
  329. package/src/decisions/decision-cards.ts +10 -3
  330. package/src/decisions/decision-ledger.ts +13 -5
  331. package/src/discord/sprint21-runtime.ts +5 -1
  332. package/src/discord-self-message.ts +32 -0
  333. package/src/discord-slash-wire.ts +5 -1
  334. package/src/discord.ts +17 -1
  335. package/src/domains/core-tools.ts +3 -2
  336. package/src/domains/outbound-alert.ts +6 -1
  337. package/src/domains/telegram-kind-route.ts +51 -13
  338. package/src/exec-requests/default-outputs.ts +25 -0
  339. package/src/exec-requests/planner.ts +10 -2
  340. package/src/exec-requests/runner.ts +20 -6
  341. package/src/exec-requests/store.ts +3 -0
  342. package/src/execution-loop/launch-gate.ts +100 -0
  343. package/src/field/field-reel.ts +5 -1
  344. package/src/field-note/index.ts +201 -0
  345. package/src/field-note/transcribe.ts +248 -0
  346. package/src/graph-kinds/registry.ts +3 -3
  347. package/src/graph-runner/graph-cli.ts +61 -1
  348. package/src/graph-runner/graph-grow-llm.ts +37 -0
  349. package/src/graph-runner/graph-grow.ts +47 -0
  350. package/src/graph-runner/runner.ts +317 -25
  351. package/src/grok/agent-search.ts +8 -2
  352. package/src/guardian/secret-exposure-scan.ts +101 -0
  353. package/src/harness/harness-cli-command.ts +247 -7
  354. package/src/harness/harness-pod-dispatch.ts +43 -23
  355. package/src/harness/harness-seams.ts +38 -4
  356. package/src/harness/harness-stop.ts +23 -4
  357. package/src/harness/launch-registry.ts +91 -0
  358. package/src/harness/process-garbage.ts +5 -3
  359. package/src/hooks/dispatch.ts +82 -0
  360. package/src/hooks/expose.ts +254 -0
  361. package/src/hooks/github-shadow.ts +108 -0
  362. package/src/hooks/providers.ts +71 -5
  363. package/src/hooks/queue.ts +1 -1
  364. package/src/hooks/receiver.ts +21 -20
  365. package/src/index.ts +52 -14
  366. package/src/intake-plane/categorize.ts +18 -46
  367. package/src/intake-plane/discord-seat-work.ts +10 -0
  368. package/src/intake-plane/front-route-classifier.ts +33 -39
  369. package/src/intake-plane/persona-answer.ts +30 -0
  370. package/src/intake-plane/runtime-callables.ts +8 -1
  371. package/src/intake-plane/telegram-seat-work.ts +36 -2
  372. package/src/intake-plane/wish-folder.ts +67 -0
  373. package/src/intent-gate/gate.ts +30 -10
  374. package/src/live/detail-switch.ts +5 -0
  375. package/src/llm/difficulty.ts +57 -0
  376. package/src/llm/judge-layer.ts +101 -0
  377. package/src/llm/mission-router.ts +33 -19
  378. package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
  379. package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
  380. package/src/loops/contract/examples/steward.loop.yaml +50 -0
  381. package/src/loops/contract/loop-agent.schema.json +138 -0
  382. package/src/loops/contract/validate.ts +64 -0
  383. package/src/loops/registry.ts +20 -6
  384. package/src/market/signed-index.ts +4 -0
  385. package/src/maturity/bot-command-maturity.ts +45 -0
  386. package/src/maturity/feature-maturity.ts +26 -4
  387. package/src/model-tier/index.ts +2 -2
  388. package/src/model-tier/tier-resolver.ts +20 -20
  389. package/src/model-tier/types.ts +6 -6
  390. package/src/mss/logging/log-store.ts +15 -0
  391. package/src/nexus/api/config-model-tier.ts +5 -4
  392. package/src/nexus/api/fabric-plans.ts +53 -0
  393. package/src/nexus/api/harness-api.ts +5 -1
  394. package/src/nexus/api/health.ts +2 -0
  395. package/src/nexus/api/http-server.ts +36 -0
  396. package/src/nexus/api/inside-events.ts +226 -0
  397. package/src/nexus/api/meta-api.ts +21 -8
  398. package/src/nexus/api/missions.ts +6 -1
  399. package/src/nexus/api/ops-seats.ts +33 -0
  400. package/src/nexus/api/outputs-route.ts +44 -0
  401. package/src/nexus/api/seat-requests.ts +44 -2
  402. package/src/nexus/api/sessions-store.ts +17 -38
  403. package/src/nexus/api/sub-seat-charters.ts +34 -0
  404. package/src/nexus/api/tabs-mutations.ts +3 -1
  405. package/src/nexus/api/trace.ts +18 -6
  406. package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
  407. package/src/nexus/api/workflows.ts +80 -6
  408. package/src/nexus/index.ts +2 -0
  409. package/src/nexus/kinds/webterm.ts +2 -1
  410. package/src/nexus/webterm/pty.ts +6 -2
  411. package/src/onboarding/cli-auth-status.ts +80 -0
  412. package/src/onboarding/voice-ai.ts +3 -3
  413. package/src/org/seat-budget.ts +48 -0
  414. package/src/org/stall-escalation.ts +63 -0
  415. package/src/outputs/ledger.ts +120 -0
  416. package/src/persona/persona-todo.ts +79 -0
  417. package/src/persona/presets.ts +116 -2
  418. package/src/persona/team-set.ts +155 -0
  419. package/src/plugins/install/plugin-install.ts +14 -0
  420. package/src/plugins/maker/market-bundle.ts +109 -0
  421. package/src/plugins/maker/plugin-maker.ts +254 -11
  422. package/src/plugins/maker/wizard-generate.ts +103 -0
  423. package/src/pod-lease/admission.ts +150 -0
  424. package/src/pod-lease/dependency-state.ts +85 -0
  425. package/src/pod-lease/host-lease.ts +127 -0
  426. package/src/project/project-suggestion.ts +16 -0
  427. package/src/project/session-context.ts +24 -0
  428. package/src/release-loop/checklist.ts +2 -2
  429. package/src/release-loop/feature-store.ts +5 -3
  430. package/src/release-loop/next-md-merge.ts +58 -0
  431. package/src/release-loop/release-note.ts +59 -4
  432. package/src/seat-dispatch/seat-ask.ts +130 -0
  433. package/src/seat-dispatch/seat-questions.ts +100 -0
  434. package/src/seat-loop/seat-loop.ts +548 -29
  435. package/src/seat-loop/seat-report.ts +37 -2
  436. package/src/self-dev/dev-cli.ts +4 -1
  437. package/src/self-dev/dev-pipeline.ts +37 -1
  438. package/src/self-dev/draft-sweep.ts +38 -33
  439. package/src/self-dev/draft-triage-rules.ts +8 -5
  440. package/src/self-dev/fabric-plan-core.ts +297 -0
  441. package/src/self-dev/orchestrate.ts +36 -4
  442. package/src/self-dev/release-path-guard.ts +62 -0
  443. package/src/self-dev/shard-aggregate.ts +230 -0
  444. package/src/self-dev/shard-placement.ts +60 -0
  445. package/src/self-dev/shard-plan.ts +48 -0
  446. package/src/self-dev/shard-pod-run.ts +77 -0
  447. package/src/self-dev/shard-run.ts +105 -0
  448. package/src/self-implement/gate-baseline.ts +1 -1
  449. package/src/self-implement/gate-cli.ts +40 -1
  450. package/src/self-implement/gate-scope.ts +37 -7
  451. package/src/self-implement/graph-variant.ts +171 -0
  452. package/src/self-implement/harness-policy-gates.ts +1 -1
  453. package/src/self-implement/headless-elanous-driver.ts +22 -3
  454. package/src/self-implement/host-regate.ts +22 -1
  455. package/src/self-implement/importer-test-index.ts +2 -1
  456. package/src/self-implement/l8-merge-queue.ts +130 -0
  457. package/src/self-implement/orchestrator.ts +242 -9
  458. package/src/self-implement/route-consumer-test-index.ts +122 -0
  459. package/src/self-implement/seams.ts +72 -11
  460. package/src/self-implement/test-seams.ts +1 -0
  461. package/src/self-implement/uncommitted-work.ts +59 -0
  462. package/src/session/index.ts +36 -13
  463. package/src/skills/gift-install.ts +215 -0
  464. package/src/skills/tools/web-search.ts +4 -1
  465. package/src/steward/launch.ts +42 -26
  466. package/src/steward/steward-cards.ts +17 -9
  467. package/src/steward/triage.ts +46 -14
  468. package/src/task-cards/card-cli.ts +25 -1
  469. package/src/task-orchestrator/mission.ts +5 -0
  470. package/src/task-orchestrator/store.ts +12 -3
  471. package/src/task-orchestrator/surfaces/pod-command-job.ts +29 -7
  472. package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
  473. package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
  474. package/src/task-orchestrator/surfaces/self-implement-pod.ts +214 -40
  475. package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
  476. package/src/task-orchestrator/types.ts +2 -0
  477. package/src/telegram-card-followup.ts +16 -96
  478. package/src/telegram-commands.ts +10 -1
  479. package/src/telegram-project-command.ts +71 -0
  480. package/src/telegram-report.ts +21 -17
  481. package/src/telegram.ts +29 -3
  482. package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
  483. package/src/user-config.ts +102 -20
  484. package/src/version/packed-revision.json +1 -1
  485. package/src/web-search/grok.ts +7 -1
  486. package/src/web-search/index.ts +28 -1
  487. package/src/web-search/provider.ts +4 -0
  488. package/src/web-search/x-intent.ts +5 -0
  489. package/src/workflow-runtime/executor.ts +277 -47
  490. package/src/workflow-runtime/index.ts +1 -0
  491. package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
  492. package/src/workflow-runtime/plugin-kind-node.ts +1 -1
  493. package/src/workflow-runtime/schema.ts +79 -4
  494. package/src/workflow-runtime/types.ts +35 -4
  495. package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
  505. package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
  506. package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
  517. package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
  525. package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
  583. package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
  584. /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → Y4zKzL62sakG5momz3SoQ}/_ssgManifest.js +0 -0
@@ -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,11 +1,15 @@
1
1
  import { debug } from '../debug/log.js';
2
2
  import { telegramDecisionOwner } from '../decisions/telegram-decision-cards.js';
3
3
  import { canonicalSeatId } from '../msg/msg-store.js';
4
+ import { awaitGlobalPersonaLoad, getGlobalPersonaRegistry } from '../persona/global-registry.js';
5
+ import type { PersonaSource } from '../persona/mention-parser.js';
4
6
  import { dispatchCeoTask, type CeoCommandDeps } from '../seat-dispatch/ceo-commands.js';
5
7
  import { ceoTaskDeps, classifyCeoIntent } from '../seat-dispatch/ceo-intent.js';
8
+ import { askSeat, parseSeatAsk, type SeatAskDeps } from '../seat-dispatch/seat-ask.js';
6
9
  import { parseSeatAddress, resolveSeat } from '../seat-address/seat-address.js';
7
10
  import { getUserConfig, type UserConfig } from '../user-config.js';
8
11
  import { answerAsSeat } from './seat-answer.js';
12
+ import { answerAsPersona, resolvePersonaAddress, type PersonaAnswerDeps } from './persona-answer.js';
9
13
  import {
10
14
  submitIntakeWork,
11
15
  type SubmitIntakeWorkDeps,
@@ -16,8 +20,12 @@ export interface TelegramSeatWorkDeps extends SubmitIntakeWorkDeps {
16
20
  submit?: typeof submitIntakeWork;
17
21
  config?: UserConfig;
18
22
  answer?: typeof answerAsSeat;
23
+ personaSource?: PersonaSource;
24
+ personaAnswer?: typeof answerAsPersona;
25
+ personaAnswerDeps?: PersonaAnswerDeps;
19
26
  dispatch?: typeof dispatchCeoTask;
20
27
  commandDeps?: CeoCommandDeps;
28
+ askDeps?: SeatAskDeps;
21
29
  }
22
30
 
23
31
  /** Addressed work preserves graph intake except for one owner's private seat request. */
@@ -38,6 +46,14 @@ export async function handleTelegramSeatWork(
38
46
  return result.reply;
39
47
  };
40
48
  if (!text.startsWith('@')) {
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: 'telegram', chatId: msg.chatId, messageId: msg.messageId,
54
+ ...(msg.threadId ? { threadId: msg.threadId } : {}), ...(msg.botId ? { botId: msg.botId } : {}) },
55
+ deps.commandDeps ?? ceoTaskDeps(auth.cfg, auth.id), deps.askDeps);
56
+ }
41
57
  if (!text.trim() || /^\s*[/@@]/.test(text)) return null;
42
58
  const auth = owner();
43
59
  const configured = (auth?.cfg.raw?.seatDispatch as { defaultSeat?: unknown } | undefined)?.defaultSeat;
@@ -47,23 +63,41 @@ export async function handleTelegramSeatWork(
47
63
  const id = canonicalSeatId(seat.id);
48
64
  return ['OP', 'TC', 'MK', 'UX'].includes(id) ? sendTask(id, text, auth!.cfg, auth!.id) : null;
49
65
  }
50
- const address = parseSeatAddress(text);
66
+ const address = parseSeatAddress(text.replace(/^(@[A-Za-z][A-Za-z0-9_-]*(?:,@?[A-Za-z][A-Za-z0-9_-]*)*)/, (prefix) => prefix.replaceAll(',@', ',')));
51
67
  if (!address) return null;
52
68
 
53
69
  const seats = address.seats.map((name) => ({ name, seat: resolveSeat(name) }));
54
70
  const names = address.seats;
55
71
  debug.log('seat-address.telegram', 'parsed', { seats: names });
56
- const unknown = seats.filter(({ seat }) => !seat).map(({ name }) => `@${name}`);
72
+ const hasUnresolved = seats.some(({ seat }) => !seat);
73
+ const auth = hasUnresolved ? owner() : null;
74
+ if (hasUnresolved && auth && !deps.personaSource) await awaitGlobalPersonaLoad();
75
+ const source = hasUnresolved && auth ? (deps.personaSource ?? getGlobalPersonaRegistry()) : null;
76
+ const addressed = seats.map(({ name, seat }) => ({
77
+ name, seat, persona: !seat && source ? resolvePersonaAddress(name, source) : null,
78
+ }));
79
+ const unknown = addressed.filter(({ seat, persona }) => !seat && (!persona || !auth)).map(({ name }) => `@${name}`);
57
80
  if (unknown.length) {
58
81
  debug.log('seat-address.telegram', 'rejected', { seats: names, reason: 'unknown-seat' });
59
82
  return `어느 좌석을 말씀하시나요? ${unknown.join(', ')}은(는) 등록된 좌석이 아닙니다. 좌석을 확인해 다시 보내 주세요.`;
60
83
  }
84
+ const personas = addressed.filter(({ persona }) => persona);
85
+ if (personas.length && addressed.length !== 1) {
86
+ debug.log('persona.address', 'rejected', { reason: 'mixed' });
87
+ return '페르소나는 한 번에 하나만 부를 수 있습니다';
88
+ }
61
89
  const body = address.body.trim();
62
90
  if (!body) {
63
91
  debug.log('seat-address.telegram', 'rejected', { seats: names, reason: 'empty-body' });
64
92
  return '어떤 일을 맡길까요? 좌석 주소 뒤에 요청 내용을 적어 다시 보내 주세요.';
65
93
  }
66
94
 
95
+ if (personas.length === 1 && personas[0]?.persona) {
96
+ const { name, persona } = personas[0];
97
+ debug.log('persona.address', 'resolved', { name, personaId: persona.personaId });
98
+ return (deps.personaAnswer ?? answerAsPersona)(persona, body, deps.personaAnswerDeps);
99
+ }
100
+
67
101
  if (seats.length === 1 && seats[0]?.seat) {
68
102
  const auth = owner();
69
103
  const seatId = canonicalSeatId(seats[0].seat.id);
@@ -0,0 +1,67 @@
1
+ import { readdirSync, readFileSync, statSync, type Dirent } from 'node:fs';
2
+ import { basename, join, relative } from 'node:path';
3
+ import { CardStore } from '../task-cards/card-store.js';
4
+
5
+ export interface WishScanResult {
6
+ added: number;
7
+ updated: number;
8
+ skipped: number;
9
+ }
10
+
11
+ /** Import markdown notes without writing to the Wish folder. The card event log retains intake revisions. */
12
+ export function scanWishFolder({ dir, store }: { dir: string; store: CardStore }): WishScanResult {
13
+ let rootEntries: Dirent[];
14
+ try {
15
+ if (!statSync(dir).isDirectory()) throw new Error('not a directory');
16
+ rootEntries = readdirSync(dir, { withFileTypes: true });
17
+ } catch (error) {
18
+ if (error instanceof Error && (error.message === 'not a directory' ||
19
+ ('code' in error && (error.code === 'ENOENT' || error.code === 'ENOTDIR')))) {
20
+ throw new Error(`Wish 폴더를 찾지 못했습니다: ${dir}`);
21
+ }
22
+ throw error;
23
+ }
24
+
25
+ const paths: string[] = [];
26
+ const collect = (entries: typeof rootEntries, base: string) => {
27
+ for (const entry of entries) {
28
+ if (entry.name.startsWith('.')) continue;
29
+ const path = join(base, entry.name);
30
+ if (entry.isFile() && entry.name.endsWith('.md') && entry.name !== 'README.md') paths.push(path);
31
+ }
32
+ };
33
+ collect(rootEntries, dir);
34
+ for (const entry of rootEntries) {
35
+ if (entry.isDirectory() && !entry.name.startsWith('.')) {
36
+ const subdir = join(dir, entry.name);
37
+ collect(readdirSync(subdir, { withFileTypes: true }), subdir);
38
+ }
39
+ }
40
+ paths.sort();
41
+
42
+ const cards = new Map(store.listCards().map(card => [card.goalId, card]));
43
+ const result: WishScanResult = { added: 0, updated: 0, skipped: 0 };
44
+ for (const path of paths) {
45
+ const relPath = relative(dir, path).split('\\').join('/');
46
+ const goalId = `wish:${relPath}`;
47
+ const mtime = statSync(path).mtimeMs;
48
+ const old = cards.get(goalId);
49
+ const intakeSections = old?.sections.filter(section => section.key.startsWith('intake:wish:')) ?? [];
50
+ const lastIntake = intakeSections.at(-1);
51
+ if (lastIntake && JSON.parse(lastIntake.content).mtime === mtime) {
52
+ result.skipped++;
53
+ continue;
54
+ }
55
+ const title = /^# (.+)$/m.exec(readFileSync(path, 'utf8'))?.[1]?.trim() || basename(path, '.md');
56
+ const card = old ?? store.createCard({ goalId, title });
57
+ const intake = { source: 'wish', path: relPath, mtime, title };
58
+ store.appendSection(card.id, {
59
+ key: `intake:wish:${intakeSections.length}`,
60
+ owner: 'steward',
61
+ content: JSON.stringify(intake),
62
+ });
63
+ if (old) result.updated++;
64
+ else result.added++;
65
+ }
66
+ return result;
67
+ }
@@ -21,8 +21,10 @@
21
21
 
22
22
  import { TaskStore } from '../task-orchestrator/store.js';
23
23
  import { createMission, listMissions, normalizeMissionSource, generateMissionSlug, type MissionSource } from '../autopilot/mission-registry.js';
24
- import { triageGoal, defaultTriageClassify, type TriageCallable } from '../autopilot/triage.js';
25
- import { resolveDomain, defaultDomainClassify, type DomainClassify } from '../autopilot/domain/resolve.js';
24
+ import { triageGoal, isExecutionModel, type TriageCallable } from '../autopilot/triage.js';
25
+ import { resolveDomain, buildDomainPrompt, type DomainClassify } from '../autopilot/domain/resolve.js';
26
+ import { judge } from '../llm/judge-layer.js';
27
+ import type { ResolveRoleProviderFn, StreamLlmFn } from '../intake-plane/runtime-callables.js';
26
28
  import { isDomain } from '../autopilot/domain/types.js';
27
29
  import { autoDecomposeMission, shouldPhaseDecompose } from '../autopilot/mission-engine.js';
28
30
  import { saveMissionOrigin, type MissionOrigin } from '../autopilot/mission-origin.js';
@@ -54,12 +56,14 @@ export interface SubmitIntentInput {
54
56
  origin?: MissionOrigin;
55
57
  /** id title 생성 seam(테스트 격리·luna 우회). 없으면 generateMissionSlug(luna) 디폴트. */
56
58
  slugFn?: (goal: string) => Promise<string>;
57
- /** ★ triage 분류 seam(테스트 격리·luna 우회·2026-07-16). 없으면 defaultTriageClassify(luna) —
59
+ /** ★ triage 분류 seam(테스트 격리·luna 우회·2026-07-16). 없으면 classify 역할 judge —
58
60
  * 단 NODE_ENV=test 는 미주입(휴리스틱 baseline)으로 실 LLM 호출 방지. */
59
61
  triageClassify?: TriageCallable;
60
- /** ★ 도메인 분류 seam(테스트 격리·luna 우회·2026-07-20). 없으면 defaultDomainClassify(luna) —
62
+ /** ★ 도메인 분류 seam(테스트 격리·luna 우회·2026-07-20). 없으면 classify 역할 judge —
61
63
  * 단 NODE_ENV=test 는 미주입(키워드 baseline)으로 실 LLM 호출 방지. */
62
64
  domainClassify?: DomainClassify;
65
+ /** Injectable transport for testing the production judge path without network access. */
66
+ judgeDeps?: { streamLLM: StreamLlmFn; resolveRoleProvider: ResolveRoleProviderFn };
63
67
  }
64
68
 
65
69
  export type SubmitIntentResult =
@@ -132,14 +136,30 @@ export async function submitIntent(input: SubmitIntentInput): Promise<SubmitInte
132
136
  // 도메인 맥락 해소(§3.8·D5) — 키워드가 모호하면 최근 미션 도메인으로 기울인다
133
137
  // ("반도체 조사"→최근 투자 활동이면 investment). high 면 키워드 그대로.
134
138
  const recentDomains = listMissions(store, { limit: 8 }).map((r) => r.domain).filter(isDomain);
135
- // ★ triage(luna 주도·tier semantic 판정) + 도메인 해소 + LLM(luna) slug 를 병렬로(hot-path 무증가).
136
- // triageClassify 미주입 & test 면 휴리스틱 baseline(실 LLM 우회). 운영은 defaultTriageClassify(luna).
139
+ // ★ triage(classify 역할·tier semantic 판정) + 도메인 해소 + LLM slug 를 병렬로(hot-path 무증가).
140
+ // triageClassify 미주입 & test 면 휴리스틱 baseline(실 LLM 우회).
137
141
  const triageClassify = input.triageClassify
138
- ?? (process.env.NODE_ENV === 'test' ? undefined : defaultTriageClassify);
139
- // ★ 도메인도 luna 승격(2026-07-20) — 키워드는 주제 vs 행위유형을 못 갈라 "요약 기능 구현" 을
140
- // business(리서치·PR없음)로 오라우팅. luna 가 semantic 판정(강앵커 high 는 키워드 신뢰).
142
+ ?? (process.env.NODE_ENV === 'test' && !input.judgeDeps ? undefined : async (prompt: string) => {
143
+ const decision = await judge({ site: 'intent.triage', prompt, ...input.judgeDeps, schema: (value) => {
144
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
145
+ const row = value as Record<string, unknown>;
146
+ if (!isExecutionModel(row.executionModel) || (row.tier !== 'light' && row.tier !== 'heavy') ||
147
+ (row.rationale !== undefined && typeof row.rationale !== 'string')) return null;
148
+ return row;
149
+ } });
150
+ return decision.ok ? JSON.stringify(decision.value) : '';
151
+ });
152
+ // ★ 도메인도 의미 판정(2026-07-20) — 키워드는 주제 vs 행위유형을 못 갈라 "요약 기능 구현" 을
153
+ // business(리서치·PR없음)로 오라우팅. judge 가 semantic 판정(강앵커 high 는 키워드 신뢰).
141
154
  const domainClassify = input.domainClassify
142
- ?? (process.env.NODE_ENV === 'test' ? undefined : defaultDomainClassify);
155
+ ?? (process.env.NODE_ENV === 'test' && !input.judgeDeps ? undefined : async (goal, ctx) => {
156
+ const decision = await judge({ site: 'intent.domain', prompt: buildDomainPrompt(goal, ctx), ...input.judgeDeps, schema: (value) => {
157
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
158
+ const domain = (value as Record<string, unknown>).domain;
159
+ return isDomain(domain) ? domain : null;
160
+ } });
161
+ return decision.ok ? decision.value : null;
162
+ });
143
163
  const [resolved, slug, triage] = await Promise.all([
144
164
  resolveDomain(marker.goal, { recentDomains, classify: domainClassify }),
145
165
  (input.slugFn ?? generateMissionSlug)(marker.goal),
@@ -13,6 +13,7 @@ import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
13
13
  import { dirname, join } from 'node:path';
14
14
  import { elanousStateRoot } from '../autopilot/state-paths.js';
15
15
  import { debug } from '../debug/log.js';
16
+ import { publishInsideEvent } from '../nexus/api/inside-events.js';
16
17
  import { prodInstanceRoot } from '../instance/resolve.js';
17
18
 
18
19
  export const LIVE_DETAIL_DEFAULT_TTL_MIN = 30;
@@ -170,6 +171,10 @@ export function emitDecision(event: DecisionEvent, opts: DetailReadOptions = {})
170
171
  ...(parentRunId ? { parentRunId } : {}),
171
172
  ...(shard ? { shard } : {}),
172
173
  });
174
+ publishInsideEvent({ kind: 'pty.decision', decisionKind: event.kind, what: event.what,
175
+ reason: event.reason, purpose: event.purpose, target: event.target,
176
+ ...(runId ? { runId } : {}), ...(event.phase ? { phase: event.phase } : {}),
177
+ ...(parentRunId ? { parentRunId } : {}), ...(shard ? { shard } : {}) });
173
178
  return true;
174
179
  }
175
180
 
@@ -0,0 +1,57 @@
1
+ import { markdownSection, parseGoalType, tracedPathReferences, verbatimOriginalAsk } from '../self-implement/goal-author.js';
2
+ import { lookupLlmTierSpec } from '../model-tier/llm-tier-map.js';
3
+ import type { GoalType } from '../self-implement/goal-author.js';
4
+ import type { ModelTier } from '../model-tier/types.js';
5
+ import { ROLE_MODEL_DEFAULTS, type RoleLlmResolution } from '../user-config.js';
6
+
7
+ export interface DifficultySignals {
8
+ targetPathCount: number;
9
+ decisionSignalCount: number;
10
+ expectedChangedFileCount: number | null;
11
+ goalType: GoalType | null;
12
+ }
13
+
14
+ export type DifficultyLevel = 'small' | 'medium' | 'large';
15
+
16
+ /** Count declared target paths and authored decision signals without counting quoted run history. */
17
+ export function goalDifficultySignals(document: string): DifficultySignals {
18
+ const ask = verbatimOriginalAsk(document);
19
+ const targetLine = (ask ?? document).split(/\r?\n/)
20
+ .map((line) => /^대상 경로:\s*(.+)$/.exec(line)?.[1])
21
+ .find((line) => line !== undefined);
22
+ const namedPaths = targetLine?.split(' · ').map((path) => path.trim().replace(/^`|`$/g, '')).filter(Boolean) ?? [];
23
+ const paths = namedPaths.length ? namedPaths : tracedPathReferences(document).map(({ path }) => path);
24
+ const signals = markdownSection(document, '판정 신호') ?? '';
25
+ const candidates = signals.split(/\r?\n/).filter((line) => /^\s*- Candidate decision signal:\s*$/.test(line)).length;
26
+ const expectedResults = signals.split(/\r?\n/).filter((line) => /^\s*- Expected result:\s*\S/.test(line)).length;
27
+ const countLine = (ask ?? document).split(/\r?\n/).find((line) => /^\s*(?:-\s*)?(?:예상 (?:변경|바뀌는) 파일 수|Expected changed files(?: count)?):\s*\d+\s*$/i.test(line));
28
+ const expectedChangedFileCount = countLine ? Number(countLine.split(':').at(-1)!.trim()) : null;
29
+ return {
30
+ targetPathCount: new Set(paths).size,
31
+ decisionSignalCount: Math.max(candidates, expectedResults),
32
+ expectedChangedFileCount,
33
+ goalType: parseGoalType(document),
34
+ };
35
+ }
36
+
37
+ export function classifyGoalDifficulty(signals: DifficultySignals): DifficultyLevel {
38
+ const { targetPathCount, decisionSignalCount, expectedChangedFileCount, goalType } = signals;
39
+ if (targetPathCount > 5 || decisionSignalCount > 5 || (expectedChangedFileCount ?? 0) > 5) return 'large';
40
+ if (goalType === 'implement' && targetPathCount === 1 && decisionSignalCount === 1) return 'small';
41
+ return 'medium';
42
+ }
43
+
44
+ /** Only the baseline role default is adjustable; explicit roleLlm and older config/env layers win. */
45
+ export function implementDifficultyTier(level: DifficultyLevel, role: RoleLlmResolution): ModelTier | undefined {
46
+ if (role.source !== 'default') return undefined;
47
+ return level === 'small' ? 'budget' : level === 'large' ? 'better' : ROLE_MODEL_DEFAULTS.implement.tier;
48
+ }
49
+
50
+ export function resolveImplementDifficulty(role: RoleLlmResolution, level: DifficultyLevel): RoleLlmResolution {
51
+ const tier = implementDifficultyTier(level, role);
52
+ return tier === undefined ? role : {
53
+ ...role,
54
+ model: lookupLlmTierSpec(role.provider, tier).model,
55
+ tier,
56
+ };
57
+ }
@@ -0,0 +1,101 @@
1
+ import { debug } from '../debug/log.js';
2
+ import { resolveRoleLlm, type UserConfig } from '../user-config.js';
3
+ import type { ResolveRoleProviderFn, StreamLlmFn } from '../intake-plane/runtime-callables.js';
4
+
5
+ interface JudgeReply {
6
+ text: string;
7
+ promptTokens?: number;
8
+ completionTokens?: number;
9
+ costUsd?: number;
10
+ modelId?: string;
11
+ }
12
+
13
+ interface JudgeOptions<T = string> {
14
+ site: string;
15
+ prompt: string;
16
+ messages?: Array<{ role: 'user' | 'system' | 'assistant'; content: string }>;
17
+ /** Return null when the parsed decision is not usable. */
18
+ schema?: (value: unknown) => T | null;
19
+ signal?: AbortSignal;
20
+ /** Injectable transport for callers with an existing LLM callable. */
21
+ call?: (args: { prompt: string; signal?: AbortSignal; provider: string; model: string }) => Promise<JudgeReply>;
22
+ streamLLM?: StreamLlmFn;
23
+ resolveRoleProvider?: ResolveRoleProviderFn;
24
+ /** Optional config slice for deterministic role resolution in isolated callers. */
25
+ config?: UserConfig;
26
+ }
27
+
28
+ type JudgeResult<T> =
29
+ | { ok: true; value: T; reply: JudgeReply; provider: string; model: string }
30
+ | { ok: false; reason: 'call'; error: unknown }
31
+ | { ok: false; reason: 'schema'; rawText: string };
32
+
33
+ /** Marks a judge call that ran on an injected transport with no configured provider. */
34
+ export const UNRESOLVED = 'unresolved';
35
+
36
+ function parseJson(text: string): unknown {
37
+ const trimmed = text.trim();
38
+ const fence = trimmed.match(/```(?:json)?\s*\n([\s\S]*?)```/);
39
+ const candidate = fence ? fence[1]!.trim() : trimmed;
40
+ try { return JSON.parse(candidate); } catch { /* Models can prefix a JSON object with prose. */ }
41
+ const start = candidate.indexOf('{');
42
+ const end = candidate.lastIndexOf('}');
43
+ if (start < 0 || end <= start) return null;
44
+ try { return JSON.parse(candidate.slice(start, end + 1)); } catch { return null; }
45
+ }
46
+
47
+ /** One role-scoped classification call; errors and invalid decisions leave rule fallback to the caller. */
48
+ export async function judge<T = string>(opts: JudgeOptions<T>): Promise<JudgeResult<T>> {
49
+ const started = Date.now();
50
+ let provider = '';
51
+ let model = '';
52
+ let ok = false;
53
+ try {
54
+ const picked = opts.resolveRoleProvider?.('classify');
55
+ if (picked) {
56
+ provider = picked.provider.name;
57
+ model = picked.model ?? '';
58
+ } else {
59
+ try {
60
+ const resolved = resolveRoleLlm('classify', opts.config ? { config: opts.config } : {});
61
+ provider = resolved.provider;
62
+ model = resolved.model;
63
+ } catch (error) {
64
+ // An injected transport does not need a configured provider; a real call still fails as before.
65
+ if (!opts.call || (error as Error | undefined)?.name !== 'NoLlmProviderAvailableError') throw error;
66
+ provider = UNRESOLVED;
67
+ model = UNRESOLVED;
68
+ try { debug.log('llm.judge', 'provider-unresolved', { site: opts.site }); } catch { /* fail-soft */ }
69
+ }
70
+ }
71
+ const messages = opts.messages ?? [{ role: 'user' as const, content: opts.prompt }];
72
+ let reply: JudgeReply;
73
+ if (opts.call) {
74
+ reply = await opts.call({ prompt: opts.prompt, signal: opts.signal, provider, model });
75
+ } else {
76
+ const llm = picked && opts.streamLLM ? undefined : await import('../llm.js');
77
+ const transportProvider = picked?.provider ?? llm?.PROVIDERS[provider];
78
+ if (!transportProvider) throw new Error(`Unknown classify provider: ${provider}`);
79
+ const streamOpts = { ...(model ? { model } : {}), ...(opts.signal ? { signal: opts.signal } : {}), usageRole: 'classify' as const };
80
+ if (opts.streamLLM) {
81
+ reply = { text: await opts.streamLLM(messages, () => {}, {
82
+ ...streamOpts, provider: transportProvider as ReturnType<ResolveRoleProviderFn>['provider'],
83
+ }) };
84
+ } else {
85
+ const registeredProvider = llm?.PROVIDERS[provider];
86
+ if (!llm || !registeredProvider) throw new Error(`Unknown classify provider: ${provider}`);
87
+ reply = { text: await llm.streamLLM(messages, () => {}, { ...streamOpts, provider: registeredProvider }) };
88
+ }
89
+ }
90
+ const value = opts.schema ? opts.schema(parseJson(reply.text)) : reply.text as T;
91
+ if (value === null || value === undefined) return { ok: false, reason: 'schema', rawText: reply.text };
92
+ ok = true;
93
+ return { ok: true, value, reply, provider, model };
94
+ } catch (error) {
95
+ return { ok: false, reason: 'call', error };
96
+ } finally {
97
+ try {
98
+ debug.log('llm.judge', 'call', { site: opts.site, provider, model, ms: Date.now() - started, ok });
99
+ } catch { /* Observation must not turn an undecided call into an exception. */ }
100
+ }
101
+ }
@@ -5,10 +5,9 @@
5
5
  // mission. Tier 1 is a pure heuristic — Korean + English regex over
6
6
  // the input plus attachment + length signals. No I/O, no network.
7
7
  //
8
- // Tier 2 (local LLM grammar-constrained classifier · P1-3) and Tier 3
9
- // (cloud LLM · deferred) plug into this same `MissionRouter` interface
10
- // via composition — the predict() implementation is replaced at
11
- // factory time, the public surface stays stable so consumers
8
+ // Tier 2 (injected LLM classifier · P1-3) uses the classify-role judge layer.
9
+ // Tier 3 (cloud LLM · deferred) can plug into this same `MissionRouter` interface;
10
+ // the public surface stays stable so consumers
12
11
  // (`elanous/route/predict` envelope · iOS chip · …) don't churn.
13
12
  //
14
13
  // Default mission → provider map mirrors the ROADMAP §3.1 table:
@@ -23,6 +22,8 @@
23
22
  // flow through MissionRoutingConfig — pass the user-config slice into
24
23
  // createMissionRouter({ config }) at boot.
25
24
 
25
+ import { judge } from './judge-layer.js';
26
+
26
27
  export type MissionKind = 'plan' | 'build' | 'review' | 'research' | 'quick' | 'vision';
27
28
 
28
29
  export type MissionAttachmentKind = 'image' | 'audio' | 'video' | 'document';
@@ -211,7 +212,7 @@ function resolveEntry(
211
212
  return { provider: DEFAULT_PROVIDER[mission], model: DEFAULT_MODEL[mission] };
212
213
  }
213
214
 
214
- /** Tier 2 seam — local LLM classifier (P1-3). When confidence from
215
+ /** Tier 2 seam — injected LLM classifier (P1-3). When confidence from
215
216
  * Tier 1 drops below TIER2_THRESHOLD the router calls this client
216
217
  * to refine the mission with a grammar-constrained 1-token
217
218
  * prediction. Implementations are pluggable — the substrate today
@@ -219,14 +220,18 @@ function resolveEntry(
219
220
  * src/background-reasoning/local-llm-process.ts; a future PR wires
220
221
  * the qwen-2.5 grammar path through.
221
222
  *
222
- * Contract: respond with one of the 6 MissionKind strings + a
223
- * confidence in [0, 1]. Throw on unrecoverable error; the router
223
+ * Contract: classify with the supplied classify-role provider/model,
224
+ * respond with one of the 6 MissionKind strings + a confidence in [0, 1].
225
+ * Throw on unrecoverable error; the router
224
226
  * swallows and falls back to Tier 1. */
225
227
  export interface MissionLocalLLMClient {
226
228
  classify(input: {
227
229
  text: string;
228
230
  attachments?: ReadonlyArray<MissionAttachment>;
229
- }): Promise<{ mission: MissionKind; confidence: number }>;
231
+ /** The classify-role selection the client must use. */
232
+ provider: string;
233
+ model: string;
234
+ }): Promise<{ mission: MissionKind; confidence: number; /** The model actually used — must equal the requested one or the decision is discarded. */ model?: string }>;
230
235
  }
231
236
 
232
237
  export const TIER2_CONFIDENCE_THRESHOLD = 0.6;
@@ -320,18 +325,27 @@ export function createMissionRouter(opts?: {
320
325
  confidence = cached.confidence;
321
326
  tier = 2;
322
327
  } else {
323
- try {
324
- const refined = await localLLM.classify({
325
- text: input.text ?? '',
326
- attachments: input.attachments,
327
- });
328
- cache.set(key, refined, now());
329
- mission = refined.mission;
330
- confidence = refined.confidence;
328
+ const decision = await judge({
329
+ site: 'llm.mission-router', prompt: JSON.stringify({ text: input.text ?? '', attachments: input.attachments ?? [] }),
330
+ call: async ({ provider, model }) => {
331
+ const refined = await localLLM.classify({ text: input.text ?? '', attachments: input.attachments, provider, model });
332
+ // Enforce the classify-role model: a client that ignored it (or can't say) doesn't get to decide.
333
+ return { text: refined.model === model && model ? JSON.stringify(refined) : 'null', modelId: refined.model };
334
+ },
335
+ schema: (value) => {
336
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
337
+ const row = value as Record<string, unknown>;
338
+ if (typeof row.mission !== 'string' || !Object.hasOwn(DEFAULT_PROVIDER, row.mission) ||
339
+ typeof row.confidence !== 'number' || !Number.isFinite(row.confidence) ||
340
+ row.confidence < 0 || row.confidence > 1) return null;
341
+ return { mission: row.mission as MissionKind, confidence: row.confidence };
342
+ },
343
+ });
344
+ if (decision.ok) {
345
+ cache.set(key, decision.value, now());
346
+ mission = decision.value.mission;
347
+ confidence = decision.value.confidence;
331
348
  tier = 2;
332
- } catch {
333
- // Swallow · keep Tier 1 result. classifier hiccup
334
- // shouldn't stall the input chip.
335
349
  }
336
350
  }
337
351
  }
@@ -0,0 +1,51 @@
1
+ id: cmo-seat
2
+ version: 1.0.0
3
+ kind: seat
4
+ role: docs/roles/MK.md
5
+ graph: graphs/operate-loop.yaml
6
+ cadence:
7
+ timezone: Asia/Seoul
8
+ byDefcon:
9
+ - {defcon: 5, everyMinutes: 1440}
10
+ - {defcon: 4, everyMinutes: 720}
11
+ - {defcon: 3, everyMinutes: 240}
12
+ - {defcon: 2, everyMinutes: 60}
13
+ - {defcon: 1, everyMinutes: 15}
14
+ posture:
15
+ default: 5
16
+ levels:
17
+ - {defcon: 5, minResolution: L0, maxResolution: L2, budget: &normal {maxTokens: 6000, maxToolCalls: 6, maxCostUsd: 0.4}}
18
+ - {defcon: 4, minResolution: L0, maxResolution: L2, budget: *normal}
19
+ - {defcon: 3, minResolution: L1, maxResolution: L3, budget: &urgent {maxTokens: 12000, maxToolCalls: 12, maxCostUsd: 0.8}}
20
+ - {defcon: 2, minResolution: L1, maxResolution: L3, budget: *urgent}
21
+ - {defcon: 1, minResolution: L1, maxResolution: L3, budget: *urgent}
22
+ raiseOn: [{event: mk-checklist-red-or-request-urgent, afterTicks: 1}]
23
+ lowerOn: [{event: mk-backlog-clear, afterTicks: 2}]
24
+ hysteresis: {minDwellMinutes: 120, clearTicks: 2}
25
+ resolution:
26
+ default: L0
27
+ steps:
28
+ - {level: L0, grounding: [], budget: &scan {maxTokens: 1500, maxToolCalls: 2, maxCostUsd: 0.1}}
29
+ - {level: L1, grounding: [{tool: omni-digest, budget: *scan}], budget: *normal}
30
+ - {level: L2, grounding: [{tool: omni-crawl, budget: *normal}], budget: *urgent}
31
+ - {level: L3, grounding: [{tool: social-pulse, budget: *scan}, {tool: aside-repl, budget: *normal}], budget: *urgent}
32
+ raiseOn: {event: campaign-anomaly, afterTicks: 1}
33
+ lowerOn: {event: verified-campaign-outcome, afterTicks: 2}
34
+ grounding: [omni-digest, omni-crawl, social-pulse, aside-repl]
35
+ memory:
36
+ local: {ledger: seat-loop/MK/YYYY-MM-DD.jsonl, working: loop/cmo-seat/context}
37
+ promotesTo: [self-recall, decisions, checklist]
38
+ retention: {workingDays: 7, ledgerDays: 90}
39
+ neighbors:
40
+ - {id: op-seat, exchange: [status, request, decision, blocked], heartbeat: {everyMinutes: 1440, missedTicks: 2}, onAbsent: {action: defer, delegateTo: orchestrator}}
41
+ - {id: ux-seat, exchange: [status, request, blocked], heartbeat: {everyMinutes: 1440, missedTicks: 2}, onAbsent: {action: defer, delegateTo: orchestrator}}
42
+ - {id: tc-seat, exchange: [status, request, blocked], heartbeat: {everyMinutes: 1440, missedTicks: 2}, onAbsent: {action: defer, delegateTo: orchestrator}}
43
+ spawn:
44
+ allowed: [harness]
45
+ max: 1
46
+ reap: {afterMinutes: 120, onExit: reconcile}
47
+ hitl: {ladder: [self-heal, neighbor, orchestrator, human]}
48
+ budget: *urgent
49
+ observability:
50
+ category: loop.cmo-seat
51
+ events: [tick, posture-change, resolution-change, grounding, heartbeat, absent, exchange, spawn, reap, promote, hitl]
@@ -0,0 +1,57 @@
1
+ id: orchestrator
2
+ version: 1.0.0
3
+ kind: orchestrator
4
+ role: docs/roles/OP.md
5
+ graph: graphs/operate-loop.yaml
6
+ orchestration:
7
+ windows:
8
+ - {at: '08:00', delegateTo: [op-seat, cmo-seat, tc-seat, ux-seat], fromLedger: release/checklist-and-seat-requests}
9
+ - {at: '12:00', delegateTo: [op-seat, cmo-seat, tc-seat, ux-seat], fromLedger: seat-loop/status-and-decisions}
10
+ - {at: '18:00', delegateTo: [op-seat, cmo-seat, tc-seat, ux-seat], fromLedger: release/landings-and-blockers}
11
+ cadence:
12
+ timezone: Asia/Seoul
13
+ byDefcon:
14
+ - {defcon: 5, everyMinutes: 120}
15
+ - {defcon: 4, everyMinutes: 60}
16
+ - {defcon: 3, everyMinutes: 30}
17
+ - {defcon: 2, everyMinutes: 15}
18
+ - {defcon: 1, everyMinutes: 5}
19
+ posture:
20
+ default: 5
21
+ levels:
22
+ - {defcon: 5, minResolution: L0, maxResolution: L2, budget: &normal {maxTokens: 8000, maxToolCalls: 8, maxCostUsd: 0.5}}
23
+ - {defcon: 4, minResolution: L0, maxResolution: L2, budget: *normal}
24
+ - {defcon: 3, minResolution: L1, maxResolution: L3, budget: &urgent {maxTokens: 16000, maxToolCalls: 16, maxCostUsd: 1}}
25
+ - {defcon: 2, minResolution: L1, maxResolution: L3, budget: *urgent}
26
+ - {defcon: 1, minResolution: L1, maxResolution: L3, budget: *urgent}
27
+ raiseOn: [{event: release-red-or-neighbor-blocked, afterTicks: 1}]
28
+ lowerOn: [{event: all-seats-clear, afterTicks: 2}]
29
+ hysteresis: {minDwellMinutes: 60, clearTicks: 2}
30
+ resolution:
31
+ default: L0
32
+ steps:
33
+ - {level: L0, grounding: [], budget: &scan {maxTokens: 2000, maxToolCalls: 2, maxCostUsd: 0.1}}
34
+ - {level: L1, grounding: [{tool: omni-digest, budget: *scan}], budget: *normal}
35
+ - {level: L2, grounding: [{tool: omni-crawl, budget: *normal}, {tool: aside-repl, budget: *scan}], budget: *urgent}
36
+ - {level: L3, grounding: [{tool: social-pulse, budget: *scan}, {tool: omni-crawl, budget: *normal}], budget: *urgent}
37
+ raiseOn: {event: new-anomaly-or-unknown, afterTicks: 1}
38
+ lowerOn: {event: evidence-stable, afterTicks: 2}
39
+ grounding: [omni-digest, omni-crawl, aside-repl, social-pulse]
40
+ memory:
41
+ local: {ledger: loop/orchestrator/events, working: loop/orchestrator/context}
42
+ promotesTo: [self-recall, decisions, checklist]
43
+ retention: {workingDays: 7, ledgerDays: 90}
44
+ neighbors:
45
+ - {id: op-seat, exchange: [status, request, decision, blocked], heartbeat: {everyMinutes: 120, missedTicks: 2}, onAbsent: {action: delegate, delegateTo: steward}}
46
+ - {id: cmo-seat, exchange: [status, request, blocked], heartbeat: {everyMinutes: 120, missedTicks: 2}, onAbsent: {action: defer, delegateTo: orchestrator}}
47
+ - {id: tc-seat, exchange: [status, request, blocked], heartbeat: {everyMinutes: 120, missedTicks: 2}, onAbsent: {action: escalate, delegateTo: orchestrator}}
48
+ - {id: ux-seat, exchange: [status, request, blocked], heartbeat: {everyMinutes: 120, missedTicks: 2}, onAbsent: {action: defer, delegateTo: orchestrator}}
49
+ spawn:
50
+ allowed: [agent, harness]
51
+ max: 4
52
+ reap: {afterMinutes: 120, onExit: reconcile}
53
+ hitl: {ladder: [self-heal, neighbor, orchestrator, human]}
54
+ budget: *urgent
55
+ observability:
56
+ category: loop.orchestrator
57
+ events: [tick, posture-change, resolution-change, grounding, heartbeat, absent, exchange, spawn, reap, promote, hitl]