dual-brain 0.2.30 → 0.3.1

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 (312) hide show
  1. package/.dual-brain/docs/claude-code-extension-points.md +32 -0
  2. package/.dual-brain/docs/data-tools-capabilities.md +181 -0
  3. package/.dual-brain/docs/ecosystem-tools.md +91 -0
  4. package/.dual-brain/docs/panel-handoff.md +124 -0
  5. package/.dual-brain/docs/ruflo-analysis.md +48 -0
  6. package/bin/dual-brain.mjs +56 -56
  7. package/dist/mcp-server/index.d.ts +27 -0
  8. package/dist/mcp-server/index.js +359 -0
  9. package/dist/mcp-server/index.js.map +1 -0
  10. package/dist/src/agent-protocol.d.ts +163 -0
  11. package/dist/src/agent-protocol.js +368 -0
  12. package/dist/src/agent-protocol.js.map +1 -0
  13. package/dist/src/agents/registry.d.ts +52 -0
  14. package/dist/src/agents/registry.js +393 -0
  15. package/dist/src/agents/registry.js.map +1 -0
  16. package/dist/src/awareness.d.ts +93 -0
  17. package/dist/src/awareness.js +406 -0
  18. package/dist/src/awareness.js.map +1 -0
  19. package/dist/src/brief.d.ts +48 -0
  20. package/dist/src/brief.js +179 -0
  21. package/dist/src/brief.js.map +1 -0
  22. package/dist/src/calibration.d.ts +32 -0
  23. package/dist/src/calibration.js +133 -0
  24. package/dist/src/calibration.js.map +1 -0
  25. package/dist/src/checkpoint.d.ts +33 -0
  26. package/dist/src/checkpoint.js +99 -0
  27. package/dist/src/checkpoint.js.map +1 -0
  28. package/dist/src/ci-triage.d.ts +33 -0
  29. package/dist/src/ci-triage.js +193 -0
  30. package/dist/src/ci-triage.js.map +1 -0
  31. package/dist/src/cognitive-loop.d.ts +56 -0
  32. package/dist/src/cognitive-loop.js +495 -0
  33. package/dist/src/cognitive-loop.js.map +1 -0
  34. package/dist/src/collaboration.d.ts +147 -0
  35. package/dist/src/collaboration.js +438 -0
  36. package/dist/src/collaboration.js.map +1 -0
  37. package/dist/src/context-intel.d.ts +47 -0
  38. package/dist/src/context-intel.js +156 -0
  39. package/dist/src/context-intel.js.map +1 -0
  40. package/dist/src/context.d.ts +53 -0
  41. package/dist/src/context.js +332 -0
  42. package/dist/src/context.js.map +1 -0
  43. package/dist/src/continuity.d.ts +89 -0
  44. package/dist/src/continuity.js +230 -0
  45. package/dist/src/continuity.js.map +1 -0
  46. package/dist/src/cost-tracker.d.ts +47 -0
  47. package/dist/src/cost-tracker.js +170 -0
  48. package/dist/src/cost-tracker.js.map +1 -0
  49. package/dist/src/debrief.d.ts +53 -0
  50. package/dist/src/debrief.js +222 -0
  51. package/dist/src/debrief.js.map +1 -0
  52. package/dist/src/decide.d.ts +96 -0
  53. package/dist/src/decide.js +744 -0
  54. package/dist/src/decide.js.map +1 -0
  55. package/dist/src/decompose.d.ts +39 -0
  56. package/dist/src/decompose.js +218 -0
  57. package/dist/src/decompose.js.map +1 -0
  58. package/dist/src/detect.d.ts +91 -0
  59. package/dist/src/detect.js +544 -0
  60. package/dist/src/detect.js.map +1 -0
  61. package/dist/src/dispatch.d.ts +154 -0
  62. package/dist/src/dispatch.js +1306 -0
  63. package/dist/src/dispatch.js.map +1 -0
  64. package/dist/src/doctor.d.ts +421 -0
  65. package/dist/src/doctor.js +1689 -0
  66. package/dist/src/doctor.js.map +1 -0
  67. package/dist/src/engine.d.ts +70 -0
  68. package/dist/src/engine.js +155 -0
  69. package/dist/src/engine.js.map +1 -0
  70. package/dist/src/envelope.d.ts +36 -0
  71. package/dist/src/envelope.js +80 -0
  72. package/dist/src/envelope.js.map +1 -0
  73. package/dist/src/failure-memory.d.ts +55 -0
  74. package/dist/src/failure-memory.js +175 -0
  75. package/dist/src/failure-memory.js.map +1 -0
  76. package/dist/src/fx.d.ts +87 -0
  77. package/dist/src/fx.js +272 -0
  78. package/dist/src/fx.js.map +1 -0
  79. package/dist/src/governance.d.ts +93 -0
  80. package/dist/src/governance.js +261 -0
  81. package/dist/src/governance.js.map +1 -0
  82. package/dist/src/handoff.d.ts +11 -0
  83. package/dist/src/handoff.js +90 -0
  84. package/dist/src/handoff.js.map +1 -0
  85. package/dist/src/head-protocol.d.ts +76 -0
  86. package/dist/src/head-protocol.js +109 -0
  87. package/dist/src/head-protocol.js.map +1 -0
  88. package/dist/src/head.d.ts +222 -0
  89. package/dist/src/head.js +765 -0
  90. package/dist/src/head.js.map +1 -0
  91. package/dist/src/health.d.ts +132 -0
  92. package/dist/src/health.js +435 -0
  93. package/dist/src/health.js.map +1 -0
  94. package/dist/src/inbox.d.ts +70 -0
  95. package/dist/src/inbox.js +218 -0
  96. package/dist/src/inbox.js.map +1 -0
  97. package/dist/src/index.d.ts +33 -0
  98. package/dist/src/index.js +38 -0
  99. package/dist/src/index.js.map +1 -0
  100. package/dist/src/install-hooks.d.ts +13 -0
  101. package/dist/src/install-hooks.js +88 -0
  102. package/dist/src/install-hooks.js.map +1 -0
  103. package/dist/src/integrity.d.ts +59 -0
  104. package/dist/src/integrity.js +206 -0
  105. package/dist/src/integrity.js.map +1 -0
  106. package/dist/src/intelligence.d.ts +104 -0
  107. package/dist/src/intelligence.js +391 -0
  108. package/dist/src/intelligence.js.map +1 -0
  109. package/dist/src/ledger.d.ts +54 -0
  110. package/dist/src/ledger.js +179 -0
  111. package/dist/src/ledger.js.map +1 -0
  112. package/dist/src/living-docs.d.ts +14 -0
  113. package/dist/src/living-docs.js +197 -0
  114. package/dist/src/living-docs.js.map +1 -0
  115. package/dist/src/memory-tiers.d.ts +37 -0
  116. package/dist/src/memory-tiers.js +160 -0
  117. package/dist/src/memory-tiers.js.map +1 -0
  118. package/dist/src/model-profiles.d.ts +65 -0
  119. package/dist/src/model-profiles.js +568 -0
  120. package/dist/src/model-profiles.js.map +1 -0
  121. package/dist/src/models.d.ts +58 -0
  122. package/dist/src/models.js +327 -0
  123. package/dist/src/models.js.map +1 -0
  124. package/dist/src/narrative.d.ts +54 -0
  125. package/dist/src/narrative.js +163 -0
  126. package/dist/src/narrative.js.map +1 -0
  127. package/dist/src/nextstep.d.ts +16 -0
  128. package/dist/src/nextstep.js +103 -0
  129. package/dist/src/nextstep.js.map +1 -0
  130. package/dist/src/observer.d.ts +18 -0
  131. package/dist/src/observer.js +251 -0
  132. package/dist/src/observer.js.map +1 -0
  133. package/dist/src/outcome.d.ts +110 -0
  134. package/dist/src/outcome.js +377 -0
  135. package/dist/src/outcome.js.map +1 -0
  136. package/dist/src/pipeline.d.ts +167 -0
  137. package/dist/src/pipeline.js +1503 -0
  138. package/dist/src/pipeline.js.map +1 -0
  139. package/dist/src/playbook.d.ts +59 -0
  140. package/dist/src/playbook.js +238 -0
  141. package/dist/src/playbook.js.map +1 -0
  142. package/dist/src/pr-agent.d.ts +97 -0
  143. package/dist/src/pr-agent.js +195 -0
  144. package/dist/src/pr-agent.js.map +1 -0
  145. package/dist/src/predictive.d.ts +57 -0
  146. package/dist/src/predictive.js +230 -0
  147. package/dist/src/predictive.js.map +1 -0
  148. package/dist/src/profile.d.ts +294 -0
  149. package/dist/src/profile.js +1347 -0
  150. package/dist/src/profile.js.map +1 -0
  151. package/dist/src/prompt-audit.d.ts +22 -0
  152. package/dist/src/prompt-audit.js +194 -0
  153. package/dist/src/prompt-audit.js.map +1 -0
  154. package/dist/src/prompt-intel.d.ts +12 -0
  155. package/dist/src/prompt-intel.js +321 -0
  156. package/dist/src/prompt-intel.js.map +1 -0
  157. package/dist/src/provider-context.d.ts +121 -0
  158. package/dist/src/provider-context.js +222 -0
  159. package/dist/src/provider-context.js.map +1 -0
  160. package/dist/src/provider-manager.d.ts +92 -0
  161. package/dist/src/provider-manager.js +428 -0
  162. package/dist/src/provider-manager.js.map +1 -0
  163. package/dist/src/receipt.d.ts +87 -0
  164. package/dist/src/receipt.js +326 -0
  165. package/dist/src/receipt.js.map +1 -0
  166. package/dist/src/recommendations.d.ts +13 -0
  167. package/dist/src/recommendations.js +291 -0
  168. package/dist/src/recommendations.js.map +1 -0
  169. package/dist/src/redact.d.ts +15 -0
  170. package/dist/src/redact.js +129 -0
  171. package/dist/src/redact.js.map +1 -0
  172. package/dist/src/replit.d.ts +397 -0
  173. package/dist/src/replit.js +1160 -0
  174. package/dist/src/replit.js.map +1 -0
  175. package/dist/src/repo.d.ts +149 -0
  176. package/dist/src/repo.js +416 -0
  177. package/dist/src/repo.js.map +1 -0
  178. package/dist/src/revert.d.ts +30 -0
  179. package/dist/src/revert.js +166 -0
  180. package/dist/src/revert.js.map +1 -0
  181. package/dist/src/room.d.ts +102 -0
  182. package/dist/src/room.js +212 -0
  183. package/dist/src/room.js.map +1 -0
  184. package/dist/src/routing-advisor.d.ts +57 -0
  185. package/dist/src/routing-advisor.js +221 -0
  186. package/dist/src/routing-advisor.js.map +1 -0
  187. package/dist/src/self-correct.d.ts +40 -0
  188. package/dist/src/self-correct.js +137 -0
  189. package/dist/src/self-correct.js.map +1 -0
  190. package/dist/src/session-lock.d.ts +35 -0
  191. package/dist/src/session-lock.js +134 -0
  192. package/dist/src/session-lock.js.map +1 -0
  193. package/dist/src/session.d.ts +267 -0
  194. package/dist/src/session.js +1660 -0
  195. package/dist/src/session.js.map +1 -0
  196. package/dist/src/settings-tui.d.ts +5 -0
  197. package/dist/src/settings-tui.js +422 -0
  198. package/dist/src/settings-tui.js.map +1 -0
  199. package/dist/src/setup-flow.d.ts +63 -0
  200. package/dist/src/setup-flow.js +233 -0
  201. package/dist/src/setup-flow.js.map +1 -0
  202. package/dist/src/signal.d.ts +19 -0
  203. package/dist/src/signal.js +122 -0
  204. package/dist/src/signal.js.map +1 -0
  205. package/dist/src/simmer.d.ts +85 -0
  206. package/dist/src/simmer.js +224 -0
  207. package/dist/src/simmer.js.map +1 -0
  208. package/dist/src/state-export.d.ts +129 -0
  209. package/dist/src/state-export.js +233 -0
  210. package/dist/src/state-export.js.map +1 -0
  211. package/dist/src/strategy.d.ts +54 -0
  212. package/dist/src/strategy.js +95 -0
  213. package/dist/src/strategy.js.map +1 -0
  214. package/dist/src/subscription.d.ts +40 -0
  215. package/dist/src/subscription.js +189 -0
  216. package/dist/src/subscription.js.map +1 -0
  217. package/dist/src/templates.d.ts +208 -0
  218. package/dist/src/templates.js +238 -0
  219. package/dist/src/templates.js.map +1 -0
  220. package/dist/src/test.d.ts +9 -0
  221. package/dist/src/test.js +1173 -0
  222. package/dist/src/test.js.map +1 -0
  223. package/dist/src/think-engine.d.ts +67 -0
  224. package/dist/src/think-engine.js +412 -0
  225. package/dist/src/think-engine.js.map +1 -0
  226. package/dist/src/tui.d.ts +71 -0
  227. package/dist/src/tui.js +242 -0
  228. package/dist/src/tui.js.map +1 -0
  229. package/dist/src/types.d.ts +177 -0
  230. package/dist/src/types.js +6 -0
  231. package/dist/src/types.js.map +1 -0
  232. package/dist/src/update-check.d.ts +7 -0
  233. package/dist/src/update-check.js +36 -0
  234. package/dist/src/update-check.js.map +1 -0
  235. package/dist/src/wave-planner.d.ts +30 -0
  236. package/dist/src/wave-planner.js +281 -0
  237. package/dist/src/wave-planner.js.map +1 -0
  238. package/hooks/head-guard.sh +41 -0
  239. package/hooks/precompact.mjs +3 -3
  240. package/hooks/session-end.mjs +3 -3
  241. package/hooks/task-classifier.mjs +328 -0
  242. package/hooks/vibe-router.mjs +387 -0
  243. package/install.mjs +2 -2
  244. package/package.json +29 -153
  245. package/src/agents/registry.mjs +0 -405
  246. package/src/awareness.mjs +0 -425
  247. package/src/brief.mjs +0 -266
  248. package/src/calibration.mjs +0 -148
  249. package/src/checkpoint.mjs +0 -109
  250. package/src/ci-triage.mjs +0 -191
  251. package/src/cognitive-loop.mjs +0 -562
  252. package/src/collaboration.mjs +0 -545
  253. package/src/context-intel.mjs +0 -158
  254. package/src/context.mjs +0 -389
  255. package/src/continuity.mjs +0 -298
  256. package/src/cost-tracker.mjs +0 -184
  257. package/src/debrief.mjs +0 -228
  258. package/src/decide.mjs +0 -1099
  259. package/src/decompose.mjs +0 -331
  260. package/src/detect.mjs +0 -702
  261. package/src/dispatch.mjs +0 -1447
  262. package/src/doctor.mjs +0 -1607
  263. package/src/envelope.mjs +0 -139
  264. package/src/failure-memory.mjs +0 -178
  265. package/src/fx.mjs +0 -276
  266. package/src/governance.mjs +0 -279
  267. package/src/handoff.mjs +0 -87
  268. package/src/head-protocol.mjs +0 -128
  269. package/src/head.mjs +0 -952
  270. package/src/health.mjs +0 -528
  271. package/src/inbox.mjs +0 -195
  272. package/src/index.mjs +0 -44
  273. package/src/install-hooks.mjs +0 -100
  274. package/src/integrity.mjs +0 -245
  275. package/src/intelligence.mjs +0 -447
  276. package/src/ledger.mjs +0 -196
  277. package/src/living-docs.mjs +0 -210
  278. package/src/memory-tiers.mjs +0 -193
  279. package/src/models.mjs +0 -363
  280. package/src/narrative.mjs +0 -169
  281. package/src/nextstep.mjs +0 -100
  282. package/src/observer.mjs +0 -241
  283. package/src/outcome.mjs +0 -400
  284. package/src/pipeline.mjs +0 -1711
  285. package/src/playbook.mjs +0 -257
  286. package/src/pr-agent.mjs +0 -214
  287. package/src/predictive.mjs +0 -250
  288. package/src/profile.mjs +0 -1411
  289. package/src/prompt-audit.mjs +0 -231
  290. package/src/prompt-intel.mjs +0 -325
  291. package/src/provider-context.mjs +0 -257
  292. package/src/receipt.mjs +0 -344
  293. package/src/recommendations.mjs +0 -296
  294. package/src/redact.mjs +0 -192
  295. package/src/replit.mjs +0 -1210
  296. package/src/repo.mjs +0 -445
  297. package/src/revert.mjs +0 -149
  298. package/src/routing-advisor.mjs +0 -204
  299. package/src/self-correct.mjs +0 -147
  300. package/src/session-lock.mjs +0 -160
  301. package/src/session.mjs +0 -1655
  302. package/src/settings-tui.mjs +0 -373
  303. package/src/setup-flow.mjs +0 -223
  304. package/src/signal.mjs +0 -115
  305. package/src/simmer.mjs +0 -241
  306. package/src/strategy.mjs +0 -235
  307. package/src/subscription.mjs +0 -212
  308. package/src/templates.mjs +0 -260
  309. package/src/think-engine.mjs +0 -428
  310. package/src/tui.mjs +0 -276
  311. package/src/update-check.mjs +0 -35
  312. package/src/wave-planner.mjs +0 -294
@@ -0,0 +1,387 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vibe-router.mjs — Intent compiler for vibe coding.
4
+ * Decomposes casual natural language into structured work orders.
5
+ *
6
+ * Export: routeVibe(utterance) → { tasks, profile_hint, quality_gates }
7
+ * CLI: node vibe-router.mjs "fix login bug and update the nav"
8
+ */
9
+
10
+ import { classifyRisk, extractPaths } from './risk-classifier.mjs';
11
+
12
+ // ─── Tier Detection Patterns ───────────────────────────────────────────────
13
+ // Aligned with enforce-tier.mjs SEARCH_WORDS, THINK_WORDS, and execute patterns.
14
+
15
+ const SEARCH_WORDS = /\b(explore|search|find|grep|locate|where\s+is|list\s+files|read[-\s]?only|lookup|scan|check|look|where|what)\b/i;
16
+ const THINK_WORDS = /\b(review|plan|design|architect|decide|analyze|audit|security|code[-\s]?review|threat[-\s]?model|complex[-\s]?debug|evaluate|compare|assess)\b/i;
17
+ const EXECUTE_WORDS = /\b(fix|build|add|update|edit|implement|refactor|delete|commit|test|run|create|modify|write|change|remove|rename|move|install|deploy|migrate|convert|replace|rewrite)\b/i;
18
+
19
+ // ─── Risk Keyword Patterns ─────────────────────────────────────────────────
20
+
21
+ const RISK_KEYWORDS = [
22
+ { level: 'critical', regex: /\b(auth|credential|secret|\.env|key[s]?|token[s]?|password|encrypt|certificate)\b/i, label: 'security-sensitive' },
23
+ { level: 'high', regex: /\b(login|payment|billing|deploy|migration|ci[-/]?cd|permission|policy|schema|api[-_]?contract)\b/i, label: 'high-impact' },
24
+ { level: 'medium', regex: /\b(test|spec|config|integration|shared|util|lib)\b/i, label: 'shared/tested code' },
25
+ { level: 'low', regex: /\b(readme|docs?|comment|format|lint|style|typo|changelog|nav|ui|css|color|font|margin|padding)\b/i, label: 'docs/UI' },
26
+ ];
27
+
28
+ const LEVEL_ORDER = { critical: 3, high: 2, medium: 1, low: 0 };
29
+
30
+ // ─── Task Splitting ────────────────────────────────────────────────────────
31
+
32
+ const TASK_SEPARATORS = /\b(?:and\s+(?:also\s+)?|also\s+|plus\s+|then\s+|after\s+that\s+|,\s*(?:and\s+)?)/i;
33
+
34
+ /**
35
+ * Split a casual utterance into individual task segments.
36
+ * Handles "and", "also", "plus", "then", "after that", and comma separators.
37
+ */
38
+ function splitTasks(utterance) {
39
+ if (!utterance) return [];
40
+
41
+ const segments = utterance
42
+ .split(TASK_SEPARATORS)
43
+ .map(s => s.trim())
44
+ .filter(s => s.length > 2);
45
+
46
+ // If no split happened, the whole utterance is a single task
47
+ return segments.length === 0 ? [utterance.trim()] : segments;
48
+ }
49
+
50
+ // ─── Per-Task Classification ───────────────────────────────────────────────
51
+
52
+ function classifyTier(text) {
53
+ if (THINK_WORDS.test(text)) return 'think';
54
+ if (EXECUTE_WORDS.test(text)) return 'execute';
55
+ if (SEARCH_WORDS.test(text)) return 'search';
56
+ return 'execute'; // default
57
+ }
58
+
59
+ function classifyKeywordRisk(text) {
60
+ let highest = { level: 'low', reason: 'general task' };
61
+
62
+ for (const pattern of RISK_KEYWORDS) {
63
+ const match = text.match(pattern.regex);
64
+ if (match && LEVEL_ORDER[pattern.level] > LEVEL_ORDER[highest.level]) {
65
+ highest = { level: pattern.level, reason: `${pattern.label} (${match[0]})` };
66
+ if (pattern.level === 'critical') return highest;
67
+ }
68
+ }
69
+
70
+ return highest;
71
+ }
72
+
73
+ function classifyTask(segment) {
74
+ const tier = classifyTier(segment);
75
+
76
+ // Check keyword-based risk
77
+ const keywordRisk = classifyKeywordRisk(segment);
78
+
79
+ // Check file-path-based risk (uses risk-classifier.mjs)
80
+ const paths = extractPaths(segment);
81
+ const pathRisk = classifyRisk(paths);
82
+
83
+ // Take the higher of keyword risk and path risk
84
+ const risk = LEVEL_ORDER[pathRisk.level] > LEVEL_ORDER[keywordRisk.level]
85
+ ? pathRisk
86
+ : keywordRisk;
87
+
88
+ // Generate a clean title: capitalize first letter, trim trailing punctuation
89
+ const title = segment.charAt(0).toUpperCase() + segment.slice(1).replace(/[.!?]+$/, '');
90
+
91
+ return {
92
+ title,
93
+ tier,
94
+ risk: risk.level,
95
+ reason: risk.reason,
96
+ };
97
+ }
98
+
99
+ // ─── Profile Hint Detection ────────────────────────────────────────────────
100
+
101
+ const QUALITY_HINT_WORDS = /\b(be\s+careful|take\s+your\s+time|thorough|deep\s+dive|carefully|exhaustive|comprehensive)\b/i;
102
+ const COST_HINT_WORDS = /\b(quick|fast|just|quickly|rapid|simple|straightforward)\b/i;
103
+
104
+ function detectProfileHint(utterance) {
105
+ if (QUALITY_HINT_WORDS.test(utterance)) return 'quality-first';
106
+ if (COST_HINT_WORDS.test(utterance)) return 'cost-saver';
107
+ return null;
108
+ }
109
+
110
+ // ─── Quality Gates ─────────────────────────────────────────────────────────
111
+
112
+ function determineQualityGates(tasks) {
113
+ const gates = new Set();
114
+
115
+ let highestRisk = 'low';
116
+ for (const task of tasks) {
117
+ if (LEVEL_ORDER[task.risk] > LEVEL_ORDER[highestRisk]) {
118
+ highestRisk = task.risk;
119
+ }
120
+ }
121
+
122
+ switch (highestRisk) {
123
+ case 'critical':
124
+ gates.add('dual_brain_required');
125
+ gates.add('tests');
126
+ gates.add('user_permission');
127
+ break;
128
+ case 'high':
129
+ gates.add('dual_brain_review');
130
+ gates.add('tests');
131
+ break;
132
+ case 'medium':
133
+ gates.add('tests');
134
+ break;
135
+ case 'low':
136
+ gates.add('self_check');
137
+ break;
138
+ }
139
+
140
+ return [...gates];
141
+ }
142
+
143
+ // ─── Ordered Language Detection ───────────────────────────────────────────
144
+
145
+ const DEPENDENCY_MARKERS = /\b(then|after\s+that|once\s+\S+\s+is\s+done|before|first|next|finally|afterwards|subsequently|followed\s+by|depends?\s+on|requires?)\b/i;
146
+
147
+ // ─── Subsystem Detection ─────────────────────────────────────────────────
148
+
149
+ const SUBSYSTEM_PATTERNS = [
150
+ { key: 'auth', regex: /\b(auth|login|sign[-\s]?in|sign[-\s]?up|session|credential|password|oauth|jwt|token)\b/i },
151
+ { key: 'billing', regex: /\b(billing|payment|subscription|invoice|charge|stripe|pricing)\b/i },
152
+ { key: 'api', regex: /\b(api|endpoint|route|controller|handler|middleware|rest|graphql)\b/i },
153
+ { key: 'ui', regex: /\b(ui|nav|button|page|component|layout|style|css|modal|form|menu|sidebar|header|footer|dashboard)\b/i },
154
+ { key: 'db', regex: /\b(database|db|schema|migration|model|query|table|column|index|sql|prisma|sequelize|knex)\b/i },
155
+ { key: 'infra', regex: /\b(deploy|ci|cd|docker|k8s|terraform|infra|pipeline|build|config|env)\b/i },
156
+ { key: 'test', regex: /\b(test|spec|fixture|mock|stub|assert|coverage)\b/i },
157
+ { key: 'docs', regex: /\b(doc|readme|changelog|guide|tutorial|comment)\b/i },
158
+ ];
159
+
160
+ function detectSubsystems(text) {
161
+ const subs = new Set();
162
+ for (const pat of SUBSYSTEM_PATTERNS) {
163
+ if (pat.regex.test(text)) subs.add(pat.key);
164
+ }
165
+ return subs;
166
+ }
167
+
168
+ // ─── Risk Domain Extraction ──────────────────────────────────────────────
169
+
170
+ function getRiskDomains(task) {
171
+ const domains = new Set();
172
+ // Use subsystem as risk domain
173
+ const subs = detectSubsystems(task.title);
174
+ for (const s of subs) domains.add(s);
175
+ // Also include explicit risk reason label
176
+ if (task.reason) {
177
+ const match = task.reason.match(/^([^(]+)/);
178
+ if (match) domains.add(match[1].trim().toLowerCase());
179
+ }
180
+ return domains;
181
+ }
182
+
183
+ // ─── Complexity + Wave Recommendation ──────────────────────────────────────
184
+
185
+ function determineComplexity(tasks) {
186
+ const highestRisk = tasks.reduce(
187
+ (max, t) => LEVEL_ORDER[t.risk] > LEVEL_ORDER[max] ? t.risk : max,
188
+ 'low'
189
+ );
190
+
191
+ if (tasks.length >= 4 || highestRisk === 'high' || highestRisk === 'critical') {
192
+ return 'complex';
193
+ }
194
+ if (tasks.length >= 2 || highestRisk === 'medium') {
195
+ return 'structured';
196
+ }
197
+ return 'simple';
198
+ }
199
+
200
+ /**
201
+ * determineWave — Sequential by default, parallel only when tasks are truly independent.
202
+ *
203
+ * Returns { wave, reasons } where reasons is an array of reason codes:
204
+ * shared_surface — tasks likely touch same files
205
+ * high_risk — risky work should be sequential for review
206
+ * dependency_marker — ordered language detected in utterance
207
+ * same_subsystem — tasks in same domain/subsystem
208
+ * independent — truly independent, safe for parallel
209
+ */
210
+ function determineWave(tasks, complexity, utterance) {
211
+ if (tasks.length === 1) return { wave: 'single', reasons: [] };
212
+
213
+ const reasons = [];
214
+
215
+ // 1. Check for ordered language in the original utterance
216
+ if (utterance && DEPENDENCY_MARKERS.test(utterance)) {
217
+ reasons.push('dependency_marker');
218
+ }
219
+
220
+ // 2. Check for high/critical risk tasks
221
+ const hasHighRisk = tasks.some(t => t.risk === 'high' || t.risk === 'critical');
222
+ if (hasHighRisk) {
223
+ reasons.push('high_risk');
224
+ }
225
+
226
+ // 3. Check for overlapping subsystems between tasks
227
+ const taskSubsystems = tasks.map(t => detectSubsystems(t.title));
228
+ let hasSharedSubsystem = false;
229
+ for (let i = 0; i < taskSubsystems.length; i++) {
230
+ for (let j = i + 1; j < taskSubsystems.length; j++) {
231
+ for (const sub of taskSubsystems[i]) {
232
+ if (taskSubsystems[j].has(sub)) {
233
+ hasSharedSubsystem = true;
234
+ break;
235
+ }
236
+ }
237
+ if (hasSharedSubsystem) break;
238
+ }
239
+ if (hasSharedSubsystem) break;
240
+ }
241
+ if (hasSharedSubsystem) {
242
+ reasons.push('same_subsystem');
243
+ }
244
+
245
+ // 4. Check for overlapping file paths / shared surface area
246
+ const taskPaths = tasks.map(t => extractPaths(t.title));
247
+ let hasSharedPaths = false;
248
+ for (let i = 0; i < taskPaths.length; i++) {
249
+ for (let j = i + 1; j < taskPaths.length; j++) {
250
+ for (const p of taskPaths[i]) {
251
+ // Check if any path from task j shares a directory prefix or exact match
252
+ for (const q of taskPaths[j]) {
253
+ if (p === q || p.startsWith(q + '/') || q.startsWith(p + '/') ||
254
+ p.split('/').slice(0, -1).join('/') === q.split('/').slice(0, -1).join('/')) {
255
+ hasSharedPaths = true;
256
+ break;
257
+ }
258
+ }
259
+ if (hasSharedPaths) break;
260
+ }
261
+ if (hasSharedPaths) break;
262
+ }
263
+ if (hasSharedPaths) break;
264
+ }
265
+ if (hasSharedPaths) {
266
+ reasons.push('shared_surface');
267
+ }
268
+
269
+ // 5. Check for shared risk domains
270
+ const taskDomains = tasks.map(t => getRiskDomains(t));
271
+ let hasSharedDomain = false;
272
+ for (let i = 0; i < taskDomains.length; i++) {
273
+ for (let j = i + 1; j < taskDomains.length; j++) {
274
+ for (const d of taskDomains[i]) {
275
+ if (taskDomains[j].has(d)) {
276
+ hasSharedDomain = true;
277
+ break;
278
+ }
279
+ }
280
+ if (hasSharedDomain) break;
281
+ }
282
+ if (hasSharedDomain) break;
283
+ }
284
+ // Only add same_subsystem if not already added (risk domains overlap with subsystems)
285
+ if (hasSharedDomain && !reasons.includes('same_subsystem')) {
286
+ reasons.push('same_subsystem');
287
+ }
288
+
289
+ // Decision: parallel ONLY when no sequential reasons found
290
+ if (reasons.length === 0) {
291
+ reasons.push('independent');
292
+ return { wave: 'parallel', reasons };
293
+ }
294
+
295
+ return { wave: 'sequential', reasons };
296
+ }
297
+
298
+ // ─── Summary Generation ────────────────────────────────────────────────────
299
+
300
+ function generateSummary(tasks, complexity, wave, qualityGates, profileHint) {
301
+ const parts = [];
302
+
303
+ if (tasks.length === 1) {
304
+ const t = tasks[0];
305
+ parts.push(`Single ${t.tier} task: ${t.title} (${t.risk} risk).`);
306
+ } else {
307
+ const taskDescs = tasks.map(t => `${t.title.toLowerCase()} (${t.risk} risk, ${t.tier})`);
308
+ parts.push(`Split into ${tasks.length} tasks: ${taskDescs.join(' + ')}.`);
309
+ }
310
+
311
+ if (wave === 'parallel' && tasks.length > 1) {
312
+ parts.push('Recommend parallel agents.');
313
+ } else if (wave === 'sequential') {
314
+ parts.push('Recommend sequential execution.');
315
+ }
316
+
317
+ if (qualityGates.includes('dual_brain_required')) {
318
+ parts.push('Dual-brain review required for critical changes.');
319
+ } else if (qualityGates.includes('dual_brain_review')) {
320
+ parts.push('Dual-brain review recommended for high-risk changes.');
321
+ }
322
+
323
+ if (profileHint) {
324
+ parts.push(`Profile hint: ${profileHint}.`);
325
+ }
326
+
327
+ return parts.join(' ');
328
+ }
329
+
330
+ // ─── Main Entry Point ──────────────────────────────────────────────────────
331
+
332
+ /**
333
+ * routeVibe(utterance) — Decompose a casual natural language utterance
334
+ * into structured work orders with tier, risk, and quality gate assignments.
335
+ *
336
+ * @param {string} utterance - The user's casual description
337
+ * @returns {{ complexity, tasks, profile_hint, quality_gates, wave_recommendation, summary }}
338
+ */
339
+ function routeVibe(utterance) {
340
+ if (!utterance || typeof utterance !== 'string' || !utterance.trim()) {
341
+ return {
342
+ complexity: 'simple',
343
+ tasks: [],
344
+ profile_hint: null,
345
+ quality_gates: ['self_check'],
346
+ wave_recommendation: 'single',
347
+ summary: 'No input provided.',
348
+ };
349
+ }
350
+
351
+ const segments = splitTasks(utterance);
352
+ const tasks = segments.map(classifyTask);
353
+ const profileHint = detectProfileHint(utterance);
354
+ const qualityGates = determineQualityGates(tasks);
355
+ const complexity = determineComplexity(tasks);
356
+ const { wave, reasons } = determineWave(tasks, complexity, utterance);
357
+ const summary = generateSummary(tasks, complexity, wave, qualityGates, profileHint);
358
+
359
+ return {
360
+ complexity,
361
+ tasks,
362
+ profile_hint: profileHint,
363
+ quality_gates: qualityGates,
364
+ wave_recommendation: wave,
365
+ wave_reasons: reasons,
366
+ summary,
367
+ };
368
+ }
369
+
370
+ export { routeVibe, splitTasks, classifyTask, detectProfileHint };
371
+
372
+ // ─── CLI ───────────────────────────────────────────────────────────────────
373
+
374
+ const isMain = process.argv[1] && (
375
+ process.argv[1].endsWith('vibe-router.mjs') ||
376
+ process.argv[1].endsWith('vibe-router')
377
+ );
378
+
379
+ if (isMain) {
380
+ const utterance = process.argv.slice(2).join(' ');
381
+ if (!utterance) {
382
+ console.error('Usage: node vibe-router.mjs "fix the login bug and also update the nav"');
383
+ process.exit(1);
384
+ }
385
+ const result = routeVibe(utterance);
386
+ console.log(JSON.stringify(result, null, 2));
387
+ }
package/install.mjs CHANGED
@@ -15,8 +15,8 @@ import { dirname, join, resolve } from 'path';
15
15
  import { fileURLToPath } from 'url';
16
16
  import { spawnSync } from 'child_process';
17
17
  import { createHash } from 'crypto';
18
- import { spinner, success as fxSuccess, warn as fxWarn, error as fxError, info as fxInfo, banner, celebrate, colors, sleep, nl, getMode } from './src/fx.mjs';
19
- import { panel, signalLine, headerBar } from './src/tui.mjs';
18
+ import { spinner, success as fxSuccess, warn as fxWarn, error as fxError, info as fxInfo, banner, celebrate, colors, sleep, nl, getMode } from './dist/src/fx.js';
19
+ import { panel, signalLine, headerBar } from './dist/src/tui.js';
20
20
 
21
21
  // Skip hook installation during global npm install — hooks are installed
22
22
  // when the user runs 'dual-brain install' in their project directory.
package/package.json CHANGED
@@ -1,63 +1,24 @@
1
1
  {
2
2
  "name": "dual-brain",
3
- "version": "0.2.30",
3
+ "version": "0.3.1",
4
4
  "description": "AI orchestration across Claude + OpenAI subscriptions — smart routing, budget awareness, and dual-brain collaboration",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "dual-brain": "bin/dual-brain.mjs"
8
8
  },
9
- "main": "./src/index.mjs",
9
+ "main": "./dist/src/index.js",
10
+ "types": "./dist/src/index.d.ts",
10
11
  "exports": {
11
- ".": "./src/index.mjs",
12
- "./profile": "./src/profile.mjs",
13
- "./detect": "./src/detect.mjs",
14
- "./decide": "./src/decide.mjs",
15
- "./dispatch": "./src/dispatch.mjs",
16
- "./playbook": "./src/playbook.mjs",
17
- "./health": "./src/health.mjs",
18
- "./repo": "./src/repo.mjs",
19
- "./session": "./src/session.mjs",
20
- "./decompose": "./src/decompose.mjs",
21
- "./brief": "./src/brief.mjs",
22
- "./redact": "./src/redact.mjs",
23
- "./calibration": "./src/calibration.mjs",
24
- "./models": "./src/models.mjs",
25
- "./prompt-intel": "./src/prompt-intel.mjs",
26
- "./replit": "./src/replit.mjs",
27
- "./continuity": "./src/continuity.mjs",
28
- "./checkpoint": "./src/checkpoint.mjs",
29
- "./pr-agent": "./src/pr-agent.mjs",
30
- "./ci-triage": "./src/ci-triage.mjs",
31
- "./integrity": "./src/integrity.mjs",
32
- "./prompt-audit": "./src/prompt-audit.mjs",
33
- "./head": "./src/head.mjs",
34
- "./templates": "./src/templates.mjs",
35
- "./agents": "./src/agents/registry.mjs",
36
- "./collaboration": "./src/collaboration.mjs",
37
- "./provider-context": "./src/provider-context.mjs",
38
- "./cognitive-loop": "./src/cognitive-loop.mjs",
39
- "./debrief": "./src/debrief.mjs",
40
- "./wave-planner": "./src/wave-planner.mjs",
41
- "./predictive": "./src/predictive.mjs",
42
- "./inbox": "./src/inbox.mjs",
43
- "./head-protocol": "./src/head-protocol.mjs",
44
- "./narrative": "./src/narrative.mjs",
45
- "./simmer": "./src/simmer.mjs",
46
- "./memory-tiers": "./src/memory-tiers.mjs",
47
- "./envelope": "./src/envelope.mjs",
48
- "./session-lock": "./src/session-lock.mjs",
49
- "./governance": "./src/governance.mjs",
50
- "./context-intel": "./src/context-intel.mjs",
51
- "./signal": "./src/signal.mjs",
52
- "./routing-advisor": "./src/routing-advisor.mjs",
53
- "./subscription": "./src/subscription.mjs",
54
- "./recommendations": "./src/recommendations.mjs",
55
- "./setup-flow": "./src/setup-flow.mjs",
56
- "./self-correct": "./src/self-correct.mjs",
57
- "./settings-tui": "./src/settings-tui.mjs",
58
- "./revert": "./src/revert.mjs",
59
- "./strategy": "./src/strategy.mjs",
60
- "./handoff": "./src/handoff.mjs"
12
+ ".": { "types": "./dist/src/index.d.ts", "default": "./dist/src/index.js" },
13
+ "./engine": { "types": "./dist/src/engine.d.ts", "default": "./dist/src/engine.js" },
14
+ "./state-export": { "types": "./dist/src/state-export.d.ts", "default": "./dist/src/state-export.js" },
15
+ "./room": { "types": "./dist/src/room.d.ts", "default": "./dist/src/room.js" },
16
+ "./agent-protocol": { "types": "./dist/src/agent-protocol.d.ts", "default": "./dist/src/agent-protocol.js" },
17
+ "./provider-manager": { "types": "./dist/src/provider-manager.d.ts", "default": "./dist/src/provider-manager.js" },
18
+ "./model-profiles": { "types": "./dist/src/model-profiles.d.ts", "default": "./dist/src/model-profiles.js" },
19
+ "./signal": { "types": "./dist/src/signal.d.ts", "default": "./dist/src/signal.js" },
20
+ "./routing-advisor": { "types": "./dist/src/routing-advisor.d.ts", "default": "./dist/src/routing-advisor.js" },
21
+ "./types": { "types": "./dist/src/types.d.ts", "default": "./dist/src/types.js" }
61
22
  },
62
23
  "keywords": [
63
24
  "claude-code",
@@ -76,116 +37,27 @@
76
37
  "url": "git+https://github.com/1xmint/dual-brain.git"
77
38
  },
78
39
  "scripts": {
40
+ "build": "tsc",
79
41
  "test": "node .claude/hooks/test-orchestrator.mjs",
80
- "test:core": "node --test src/test.mjs",
81
- "prepublishOnly": "node .claude/hooks/repo-doctor.mjs",
42
+ "test:core": "node --test dist/src/test.js",
43
+ "prepublishOnly": "npm run build",
82
44
  "postinstall": "echo 'dual-brain installed. Run: dual-brain install (in your project) to set up hooks.'",
83
- "postpublish": "node scripts/verify-publish.mjs"
45
+ "postpublish": "node scripts/verify-publish.mjs",
46
+ "mcp-server": "node dist/mcp-server/index.js"
84
47
  },
85
48
  "engines": {
86
49
  "node": ">=20.0.0"
87
50
  },
88
51
  "files": [
89
- "src/profile.mjs",
90
- "src/detect.mjs",
91
- "src/decide.mjs",
92
- "src/dispatch.mjs",
93
- "src/playbook.mjs",
94
- "src/health.mjs",
95
- "src/repo.mjs",
96
- "src/session.mjs",
97
- "src/decompose.mjs",
98
- "src/brief.mjs",
99
- "src/redact.mjs",
100
- "src/calibration.mjs",
101
- "src/models.mjs",
102
- "src/pipeline.mjs",
103
- "src/context.mjs",
104
- "src/outcome.mjs",
105
- "src/observer.mjs",
106
- "src/nextstep.mjs",
107
- "src/doctor.mjs",
108
- "src/receipt.mjs",
109
- "src/failure-memory.mjs",
110
- "src/index.mjs",
111
- "src/ledger.mjs",
112
- "src/intelligence.mjs",
113
- "src/awareness.mjs",
114
- "src/tui.mjs",
115
- "src/living-docs.mjs",
116
- "src/cost-tracker.mjs",
117
- "src/think-engine.mjs",
118
- "src/install-hooks.mjs",
119
- "src/update-check.mjs",
120
- "src/prompt-intel.mjs",
121
- "src/replit.mjs",
122
- "src/fx.mjs",
123
- "src/continuity.mjs",
124
- "src/checkpoint.mjs",
125
- "src/ci-triage.mjs",
126
- "src/pr-agent.mjs",
127
- "src/integrity.mjs",
128
- "src/prompt-audit.mjs",
129
- "src/head.mjs",
130
- "src/templates.mjs",
131
- "src/agents/registry.mjs",
132
- "src/collaboration.mjs",
133
- "src/provider-context.mjs",
134
- "src/cognitive-loop.mjs",
135
- "src/debrief.mjs",
136
- "src/wave-planner.mjs",
137
- "src/predictive.mjs",
138
- "src/inbox.mjs",
139
- "src/head-protocol.mjs",
140
- "src/narrative.mjs",
141
- "src/simmer.mjs",
142
- "src/memory-tiers.mjs",
143
- "src/envelope.mjs",
144
- "src/session-lock.mjs",
145
- "src/governance.mjs",
146
- "src/context-intel.mjs",
147
- "src/signal.mjs",
148
- "src/routing-advisor.mjs",
149
- "src/subscription.mjs",
150
- "src/recommendations.mjs",
151
- "src/setup-flow.mjs",
152
- "src/self-correct.mjs",
153
- "src/settings-tui.mjs",
154
- "src/revert.mjs",
155
- "src/strategy.mjs",
156
- "src/handoff.mjs",
52
+ "dist/**/*.js",
53
+ "dist/**/*.d.ts",
54
+ "dist/**/*.js.map",
157
55
  "bin/*.mjs",
158
- "hooks/enforce-tier.mjs",
159
- "hooks/cost-logger.mjs",
160
- "hooks/cost-report.mjs",
161
- "hooks/dual-brain-review.mjs",
162
- "hooks/dual-brain-think.mjs",
163
- "hooks/quality-gate.mjs",
164
- "hooks/test-orchestrator.mjs",
165
- "hooks/setup-wizard.mjs",
166
- "hooks/health-check.mjs",
167
- "hooks/install-git-hooks.mjs",
168
- "hooks/session-report.mjs",
169
- "hooks/budget-balancer.mjs",
170
- "hooks/gpt-work-dispatcher.mjs",
171
- "hooks/profiles.mjs",
172
- "hooks/summary-checkpoint.mjs",
173
- "hooks/decision-ledger.mjs",
174
- "hooks/control-panel.mjs",
175
- "hooks/risk-classifier.mjs",
176
- "hooks/failure-detector.mjs",
177
- "hooks/plan-generator.mjs",
178
- "hooks/vibe-memory.mjs",
179
- "hooks/wave-orchestrator.mjs",
180
- "hooks/model-registry.mjs",
181
- "hooks/auto-update-wrapper.mjs",
182
- "hooks/session-end.mjs",
183
- "hooks/diagnostic-companion.mjs",
184
- "hooks/precompact.mjs",
185
- "hooks/head-guard.mjs",
186
- "hooks/auto-update.sh",
56
+ "hooks/*.mjs",
57
+ "hooks/*.sh",
187
58
  "mcp-server/*.mjs",
188
59
  "mcp-server/README.md",
60
+ ".dual-brain/docs/*.md",
189
61
  "install.mjs",
190
62
  "orchestrator.json",
191
63
  "review-rules.md",
@@ -199,5 +71,9 @@
199
71
  "agents/*.md",
200
72
  "shell-hook.sh",
201
73
  "scripts/verify-publish.mjs"
202
- ]
74
+ ],
75
+ "devDependencies": {
76
+ "@types/node": "^25.8.0",
77
+ "typescript": "^6.0.3"
78
+ }
203
79
  }