dual-brain 0.2.30 → 0.3.0

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 (309) 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/task-classifier.mjs +328 -0
  240. package/hooks/vibe-router.mjs +387 -0
  241. package/package.json +29 -153
  242. package/src/agents/registry.mjs +0 -405
  243. package/src/awareness.mjs +0 -425
  244. package/src/brief.mjs +0 -266
  245. package/src/calibration.mjs +0 -148
  246. package/src/checkpoint.mjs +0 -109
  247. package/src/ci-triage.mjs +0 -191
  248. package/src/cognitive-loop.mjs +0 -562
  249. package/src/collaboration.mjs +0 -545
  250. package/src/context-intel.mjs +0 -158
  251. package/src/context.mjs +0 -389
  252. package/src/continuity.mjs +0 -298
  253. package/src/cost-tracker.mjs +0 -184
  254. package/src/debrief.mjs +0 -228
  255. package/src/decide.mjs +0 -1099
  256. package/src/decompose.mjs +0 -331
  257. package/src/detect.mjs +0 -702
  258. package/src/dispatch.mjs +0 -1447
  259. package/src/doctor.mjs +0 -1607
  260. package/src/envelope.mjs +0 -139
  261. package/src/failure-memory.mjs +0 -178
  262. package/src/fx.mjs +0 -276
  263. package/src/governance.mjs +0 -279
  264. package/src/handoff.mjs +0 -87
  265. package/src/head-protocol.mjs +0 -128
  266. package/src/head.mjs +0 -952
  267. package/src/health.mjs +0 -528
  268. package/src/inbox.mjs +0 -195
  269. package/src/index.mjs +0 -44
  270. package/src/install-hooks.mjs +0 -100
  271. package/src/integrity.mjs +0 -245
  272. package/src/intelligence.mjs +0 -447
  273. package/src/ledger.mjs +0 -196
  274. package/src/living-docs.mjs +0 -210
  275. package/src/memory-tiers.mjs +0 -193
  276. package/src/models.mjs +0 -363
  277. package/src/narrative.mjs +0 -169
  278. package/src/nextstep.mjs +0 -100
  279. package/src/observer.mjs +0 -241
  280. package/src/outcome.mjs +0 -400
  281. package/src/pipeline.mjs +0 -1711
  282. package/src/playbook.mjs +0 -257
  283. package/src/pr-agent.mjs +0 -214
  284. package/src/predictive.mjs +0 -250
  285. package/src/profile.mjs +0 -1411
  286. package/src/prompt-audit.mjs +0 -231
  287. package/src/prompt-intel.mjs +0 -325
  288. package/src/provider-context.mjs +0 -257
  289. package/src/receipt.mjs +0 -344
  290. package/src/recommendations.mjs +0 -296
  291. package/src/redact.mjs +0 -192
  292. package/src/replit.mjs +0 -1210
  293. package/src/repo.mjs +0 -445
  294. package/src/revert.mjs +0 -149
  295. package/src/routing-advisor.mjs +0 -204
  296. package/src/self-correct.mjs +0 -147
  297. package/src/session-lock.mjs +0 -160
  298. package/src/session.mjs +0 -1655
  299. package/src/settings-tui.mjs +0 -373
  300. package/src/setup-flow.mjs +0 -223
  301. package/src/signal.mjs +0 -115
  302. package/src/simmer.mjs +0 -241
  303. package/src/strategy.mjs +0 -235
  304. package/src/subscription.mjs +0 -212
  305. package/src/templates.mjs +0 -260
  306. package/src/think-engine.mjs +0 -428
  307. package/src/tui.mjs +0 -276
  308. package/src/update-check.mjs +0 -35
  309. package/src/wave-planner.mjs +0 -294
@@ -0,0 +1,63 @@
1
+ interface DetectedEnvironment {
2
+ claude: boolean;
3
+ codex: boolean;
4
+ git: boolean;
5
+ gitBranch: string | null;
6
+ language: string;
7
+ existingConfig: boolean;
8
+ }
9
+ interface SetupAnswers {
10
+ subscription?: string;
11
+ workStyle?: string;
12
+ advanced?: AdvancedOptions;
13
+ setupMode?: string;
14
+ }
15
+ interface AdvancedOptions {
16
+ thinkEnabled?: boolean;
17
+ cascadeEnabled?: boolean;
18
+ learningEnabled?: boolean;
19
+ explorationRate?: number;
20
+ sessionLimitTokens?: number | null;
21
+ warnAtPercent?: number;
22
+ models?: Record<string, string>;
23
+ }
24
+ interface SetupConfig {
25
+ version: number;
26
+ subscription: string;
27
+ workStyle: string;
28
+ providers: {
29
+ claude: boolean;
30
+ openai: boolean;
31
+ };
32
+ routing: {
33
+ thinkEnabled: boolean;
34
+ cascadeEnabled: boolean;
35
+ learningEnabled: boolean;
36
+ explorationRate: number;
37
+ };
38
+ models: Record<string, string>;
39
+ budget: {
40
+ sessionLimitTokens: number | null;
41
+ warnAtPercent: number;
42
+ };
43
+ configuredAt: string;
44
+ setupMode: string;
45
+ detectedEnv: {
46
+ claude: boolean;
47
+ codex: boolean;
48
+ language: string;
49
+ };
50
+ }
51
+ interface SetupOptions {
52
+ nonInteractive?: boolean;
53
+ reconfigure?: boolean;
54
+ subscription?: string;
55
+ workStyle?: string;
56
+ }
57
+ export declare function detectEnvironment(cwd: string): DetectedEnvironment;
58
+ export declare function renderWelcome(detected: DetectedEnvironment): string;
59
+ export declare function renderConfirmation(config: SetupConfig): string;
60
+ export declare function buildConfig(answers: SetupAnswers, detected: DetectedEnvironment): SetupConfig;
61
+ export declare function saveConfig(config: SetupConfig, cwd: string): void;
62
+ export declare function runSetup(cwd: string, options?: SetupOptions): Promise<SetupConfig | null>;
63
+ export {};
@@ -0,0 +1,233 @@
1
+ // setup-flow.ts — Interactive first-run setup for dual-brain
2
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { createInterface } from 'node:readline';
5
+ import { execSync } from 'node:child_process';
6
+ // ── ANSI helpers ──────────────────────────────────────────────────────────────
7
+ const c = {
8
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
9
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
10
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
11
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
12
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
13
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
14
+ };
15
+ // ── Detection ─────────────────────────────────────────────────────────────────
16
+ export function detectEnvironment(cwd) {
17
+ const tryCmd = (cmd) => { try {
18
+ execSync(cmd, { stdio: 'pipe' });
19
+ return true;
20
+ }
21
+ catch {
22
+ return false;
23
+ } };
24
+ let language = 'unknown';
25
+ if (existsSync(join(cwd, 'package.json')))
26
+ language = 'node';
27
+ else if (existsSync(join(cwd, 'pyproject.toml')) ||
28
+ existsSync(join(cwd, 'setup.py')))
29
+ language = 'python';
30
+ else if (existsSync(join(cwd, 'go.mod')))
31
+ language = 'go';
32
+ else if (existsSync(join(cwd, 'Cargo.toml')))
33
+ language = 'rust';
34
+ else if (existsSync(join(cwd, 'pom.xml')))
35
+ language = 'java';
36
+ let gitBranch = null;
37
+ try {
38
+ gitBranch = execSync('git -C "' + cwd + '" branch --show-current', { stdio: 'pipe' }).toString().trim();
39
+ }
40
+ catch { }
41
+ return {
42
+ claude: tryCmd('claude --version'),
43
+ codex: tryCmd('codex --version'),
44
+ git: !!gitBranch,
45
+ gitBranch: gitBranch || null,
46
+ language,
47
+ existingConfig: existsSync(join(cwd, '.dualbrain', 'config.json')),
48
+ };
49
+ }
50
+ // ── Welcome banner ────────────────────────────────────────────────────────────
51
+ export function renderWelcome(detected) {
52
+ const row = (ok, label) => c.cyan('│') + ` ${ok ? c.green('✓') : c.dim('✗')} ${ok ? label : c.dim(label)}`.padEnd(49) + c.cyan('│');
53
+ const bar = (s) => c.cyan('│') + s.padEnd(49) + c.cyan('│');
54
+ return [
55
+ c.cyan('╭' + '─'.repeat(49) + '╮'),
56
+ bar(''),
57
+ bar(` ${c.bold('dual-brain')} — intelligent model orchestration`),
58
+ bar(''),
59
+ bar(' Detected:'),
60
+ row(detected.claude, 'Claude CLI available'),
61
+ row(detected.codex, 'Codex CLI available'),
62
+ row(detected.git, `Git repository (${detected.gitBranch || 'no branch'} branch)`),
63
+ row(detected.language !== 'unknown', `${detected.language} project`),
64
+ bar(''),
65
+ c.cyan('╰' + '─'.repeat(49) + '╯'),
66
+ ].join('\n');
67
+ }
68
+ const SUB_LABELS = {
69
+ 'claude-pro': 'Claude Pro', 'claude-max-5x': 'Claude Max 5x',
70
+ 'claude-max-20x': 'Claude Max 20x', 'chatgpt-plus': 'ChatGPT Plus',
71
+ 'chatgpt-pro': 'ChatGPT Pro', 'dual-pro': 'Both Pro tiers', 'dual-max': 'Max + Pro tiers',
72
+ };
73
+ // ── Confirmation display ──────────────────────────────────────────────────────
74
+ export function renderConfirmation(config) {
75
+ const row = (k, v) => ` ${c.dim(k.padEnd(16))} ${c.cyan(v)}`;
76
+ return [
77
+ '', c.bold(' Configuration:'), '',
78
+ row('Subscription:', SUB_LABELS[config.subscription] || config.subscription),
79
+ row('Work style:', config.workStyle),
80
+ row('Primary model:', config.models.execute),
81
+ row('Think agent:', config.routing.thinkEnabled ? 'enabled' : 'disabled'),
82
+ row('Learning:', config.routing.learningEnabled ? 'on' : 'off'),
83
+ '',
84
+ ].join('\n');
85
+ }
86
+ // ── Config builder ────────────────────────────────────────────────────────────
87
+ export function buildConfig(answers, detected) {
88
+ const { subscription = 'claude-pro', workStyle = 'balanced', advanced = {}, setupMode = 'quick' } = answers;
89
+ const dual = subscription.startsWith('dual-');
90
+ const isMax = subscription.includes('max') || subscription === 'chatgpt-pro';
91
+ const topModel = isMax ? 'opus' : 'sonnet';
92
+ const exploreRate = { aggressive: 0.3, conservative: 0.1, auto: 0.25 }[workStyle] ?? 0.2;
93
+ return {
94
+ version: 1, subscription, workStyle,
95
+ providers: { claude: subscription.startsWith('claude-') || dual, openai: subscription.startsWith('chatgpt-') || dual },
96
+ routing: {
97
+ thinkEnabled: advanced.thinkEnabled ?? true,
98
+ cascadeEnabled: advanced.cascadeEnabled ?? true,
99
+ learningEnabled: advanced.learningEnabled ?? true,
100
+ explorationRate: advanced.explorationRate ?? exploreRate,
101
+ },
102
+ models: advanced.models || { search: 'haiku', execute: 'sonnet', think: topModel, review: topModel },
103
+ budget: { sessionLimitTokens: advanced.sessionLimitTokens ?? null, warnAtPercent: advanced.warnAtPercent ?? 80 },
104
+ configuredAt: new Date().toISOString(),
105
+ setupMode,
106
+ detectedEnv: { claude: detected.claude, codex: detected.codex, language: detected.language },
107
+ };
108
+ }
109
+ // ── Save config ───────────────────────────────────────────────────────────────
110
+ export function saveConfig(config, cwd) {
111
+ const dir = join(cwd, '.dualbrain');
112
+ if (!existsSync(dir))
113
+ mkdirSync(dir, { recursive: true });
114
+ writeFileSync(join(dir, 'config.json'), JSON.stringify(config, null, 2), 'utf8');
115
+ const orchPath = join(cwd, '.claude', 'orchestrator.json');
116
+ if (existsSync(orchPath)) {
117
+ try {
118
+ const orch = JSON.parse(readFileSync(orchPath, 'utf8'));
119
+ if (!orch.providers)
120
+ orch.providers = {};
121
+ orch.providers.claude = { ...(orch.providers.claude || {}), enabled: config.providers.claude, subscription: config.subscription };
122
+ orch.providers.openai = { ...(orch.providers.openai || {}), enabled: config.providers.openai };
123
+ if (config.routing)
124
+ orch.routing = { ...(orch.routing || {}), ...config.routing };
125
+ writeFileSync(orchPath, JSON.stringify(orch, null, 2), 'utf8');
126
+ }
127
+ catch { /* non-fatal */ }
128
+ }
129
+ }
130
+ // ── Readline prompt helper ────────────────────────────────────────────────────
131
+ async function ask(rl, question, options) {
132
+ const lines = options.map((o, i) => ` ${c.cyan(String(i + 1) + ')')} ${o.label}${o.description ? c.dim(' — ' + o.description) : ''}`);
133
+ const prompt = `\n${c.bold(question)}\n${lines.join('\n')}\n${c.dim('> ')}`;
134
+ return new Promise(resolve => {
135
+ rl.question(prompt, answer => {
136
+ const trimmed = answer.trim();
137
+ const idx = parseInt(trimmed, 10) - 1;
138
+ if (idx >= 0 && idx < options.length)
139
+ resolve(options[idx].value);
140
+ else
141
+ resolve(options[0].value);
142
+ });
143
+ });
144
+ }
145
+ async function askYN(rl, question, defaultYes = true) {
146
+ return new Promise(resolve => {
147
+ rl.question(`\n${c.bold(question)} ${c.dim(defaultYes ? '(Y/n)' : '(y/N)')} `, answer => {
148
+ const t = answer.trim().toLowerCase();
149
+ if (!t)
150
+ resolve(defaultYes);
151
+ else
152
+ resolve(t === 'y' || t === 'yes');
153
+ });
154
+ });
155
+ }
156
+ // ── Main entry point ──────────────────────────────────────────────────────────
157
+ export async function runSetup(cwd, options = {}) {
158
+ const detected = detectEnvironment(cwd);
159
+ // Non-TTY fast path — stdin is piped or in CI
160
+ if (!process.stdin.isTTY && !options.nonInteractive) {
161
+ process.stderr.write('[dual-brain] Non-interactive terminal detected. Use --non-interactive flag or run in a TTY.\n');
162
+ const config = buildConfig({ subscription: 'claude-pro', workStyle: 'balanced' }, detected);
163
+ saveConfig(config, cwd);
164
+ return config;
165
+ }
166
+ // Non-interactive fast path
167
+ if (options.nonInteractive) {
168
+ const config = buildConfig({
169
+ subscription: options.subscription || 'claude-pro',
170
+ workStyle: options.workStyle || 'balanced',
171
+ setupMode: 'non-interactive',
172
+ }, detected);
173
+ saveConfig(config, cwd);
174
+ return config;
175
+ }
176
+ // Already configured?
177
+ if (detected.existingConfig && !options.reconfigure) {
178
+ console.log('\n' + c.yellow('dual-brain is already configured.') + ' Pass --reconfigure to change settings.\n');
179
+ return JSON.parse(readFileSync(join(cwd, '.dualbrain', 'config.json'), 'utf8'));
180
+ }
181
+ console.log('\n' + renderWelcome(detected) + '\n');
182
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
183
+ const close = () => rl.close();
184
+ try {
185
+ const mode = await ask(rl, 'Setup mode:', [
186
+ { label: 'Quick setup', value: 'quick', description: '3 questions, ~20 seconds' },
187
+ { label: 'Advanced', value: 'advanced', description: 'full control over routing, budgets, models' },
188
+ ]);
189
+ const subscription = await ask(rl, 'Your AI subscription:', [
190
+ { label: 'Claude Pro ($20/mo)', value: 'claude-pro' },
191
+ { label: 'Claude Max 5x ($100/mo)', value: 'claude-max-5x' },
192
+ { label: 'Claude Max 20x ($200/mo)', value: 'claude-max-20x' },
193
+ { label: 'ChatGPT Plus ($20/mo)', value: 'chatgpt-plus' },
194
+ { label: 'ChatGPT Pro ($200/mo)', value: 'chatgpt-pro' },
195
+ { label: 'Both providers (Pro tiers)', value: 'dual-pro' },
196
+ { label: 'Both providers (Max tiers)', value: 'dual-max' },
197
+ ]);
198
+ const workStyle = await ask(rl, 'How should dual-brain route your work?', [
199
+ { label: 'Balanced', value: 'balanced', description: 'smart defaults, asks before expensive ops' },
200
+ { label: 'Conservative', value: 'conservative', description: 'minimize tokens, prefer cheaper models' },
201
+ { label: 'Aggressive', value: 'aggressive', description: 'best model available, maximize quality' },
202
+ { label: 'Full auto', value: 'auto', description: 'never ask, optimize silently' },
203
+ ]);
204
+ let advanced = {};
205
+ if (mode === 'advanced') {
206
+ const thinkEnabled = await askYN(rl, 'Enable think agent?', true);
207
+ const cascadeEnabled = await askYN(rl, 'Enable cascade routing?', true);
208
+ const learningEnabled = await askYN(rl, 'Enable learning (improves routing over time)?', true);
209
+ const explorationRate = await ask(rl, 'Routing exploration rate:', [
210
+ { label: 'Low (0.1)', value: 0.1, description: 'rarely tries new routes' },
211
+ { label: 'Medium (0.2)', value: 0.2, description: 'balanced' },
212
+ { label: 'High (0.3)', value: 0.3, description: 'frequently explores alternatives' },
213
+ ]);
214
+ advanced = { thinkEnabled, cascadeEnabled, learningEnabled, explorationRate };
215
+ }
216
+ const config = buildConfig({ subscription, workStyle, advanced, setupMode: mode }, detected);
217
+ console.log(renderConfirmation(config));
218
+ if (!await askYN(rl, 'Save and start?', true)) {
219
+ console.log('\n' + c.yellow('Setup cancelled.') + '\n');
220
+ close();
221
+ return null;
222
+ }
223
+ saveConfig(config, cwd);
224
+ console.log('\n' + c.green('✓') + ' ' + c.bold('dual-brain configured.') + ' Config saved to ' + c.cyan('.dualbrain/config.json') + '\n');
225
+ close();
226
+ return config;
227
+ }
228
+ catch (err) {
229
+ close();
230
+ throw err;
231
+ }
232
+ }
233
+ //# sourceMappingURL=setup-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-flow.js","sourceRoot":"","sources":["../../src/setup-flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { Tier, TaskOutcome } from './types.ts';
2
+ export declare const EXPECTED_DURATION_MS: Record<Tier, number>;
3
+ export declare function scoreDurationRatio(durationMs: number, tier: Tier): number | null;
4
+ export declare function measureFileSurvival(outcome: TaskOutcome, cwd: string): number | null;
5
+ interface ScoreOutcomeContext {
6
+ fileSurvival?: number | null;
7
+ }
8
+ interface OutcomeScoreResult {
9
+ reward: number;
10
+ confidence: number;
11
+ signals: {
12
+ exitSuccess: number | boolean;
13
+ durationRatio: number | null;
14
+ tokenEfficiency: number | null;
15
+ fileSurvival: number | null;
16
+ };
17
+ }
18
+ export declare function scoreOutcome(outcome: TaskOutcome, context?: ScoreOutcomeContext): OutcomeScoreResult;
19
+ export {};
@@ -0,0 +1,122 @@
1
+ // signal.ts — Compound outcome signal scoring
2
+ // Combines multiple weak signals into one reliable reward score.
3
+ import { existsSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { execSync } from 'node:child_process';
6
+ export const EXPECTED_DURATION_MS = {
7
+ search: 15000,
8
+ execute: 45000,
9
+ think: 30000,
10
+ review: 40000,
11
+ };
12
+ export function scoreDurationRatio(durationMs, tier) {
13
+ try {
14
+ if (durationMs <= 0)
15
+ return null;
16
+ const expectedMs = EXPECTED_DURATION_MS[tier] || EXPECTED_DURATION_MS.execute;
17
+ const ratio = durationMs / expectedMs;
18
+ if (ratio >= 0.5 && ratio <= 1.5)
19
+ return 1.0;
20
+ if (ratio < 0.2)
21
+ return 0.5;
22
+ if (ratio > 3.0)
23
+ return 0.3;
24
+ if (ratio < 0.5)
25
+ return 0.5 + ((ratio - 0.2) / (0.5 - 0.2)) * 0.5;
26
+ // ratio 1.5–3.0
27
+ return 1.0 - ((ratio - 1.5) / (3.0 - 1.5)) * 0.7;
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ }
33
+ export function measureFileSurvival(outcome, cwd) {
34
+ try {
35
+ const files = Array.isArray(outcome.filesChanged)
36
+ ? outcome.filesChanged
37
+ : [];
38
+ if (files.length === 0)
39
+ return 1.0;
40
+ let changed;
41
+ try {
42
+ changed = new Set(execSync('git diff --name-only', { cwd, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] })
43
+ .split('\n')
44
+ .map(f => f.trim())
45
+ .filter(Boolean));
46
+ }
47
+ catch {
48
+ changed = new Set();
49
+ }
50
+ const survived = files.filter(f => {
51
+ const abs = join(cwd, f);
52
+ return existsSync(abs) && !changed.has(f);
53
+ });
54
+ return survived.length / files.length;
55
+ }
56
+ catch {
57
+ return null;
58
+ }
59
+ }
60
+ export function scoreOutcome(outcome, context = {}) {
61
+ try {
62
+ const tier = (outcome.tier ?? 'execute');
63
+ const signals = [];
64
+ // Signal 1: exit success (weight 0.3)
65
+ let exitVal;
66
+ if (outcome.success === true)
67
+ exitVal = 1.0;
68
+ else if (outcome.status === 'partial')
69
+ exitVal = 0.4;
70
+ else
71
+ exitVal = 0.0;
72
+ signals.push({ name: 'exitSuccess', value: exitVal, weight: 0.3 });
73
+ // Signal 2: duration ratio (weight 0.25)
74
+ const durationMs = outcome.durationMs ?? 0;
75
+ const durVal = durationMs > 0 ? scoreDurationRatio(durationMs, tier) : null;
76
+ signals.push({ name: 'durationRatio', value: durVal, weight: 0.25 });
77
+ // Signal 3: token efficiency (weight 0.25)
78
+ let effVal = null;
79
+ const filesChanged = outcome.filesChanged ?? 0;
80
+ const fileCount = Array.isArray(filesChanged) ? filesChanged.length : (typeof filesChanged === 'number' ? filesChanged : 0);
81
+ if (!(fileCount === 0 && tier === 'think')) {
82
+ const tokensUsed = outcome.tokensUsed?.output ??
83
+ (durationMs > 0 ? Math.round(durationMs / 100) : null);
84
+ if (tokensUsed !== null && tokensUsed !== undefined) {
85
+ const efficiency = fileCount / Math.max(1, tokensUsed / 1000);
86
+ if (efficiency > 2)
87
+ effVal = 1.0;
88
+ else if (efficiency >= 0.5)
89
+ effVal = 0.5 + ((efficiency - 0.5) / 1.5) * 0.5;
90
+ else if (efficiency < 0.1)
91
+ effVal = 0.2;
92
+ else
93
+ effVal = 0.2 + ((efficiency - 0.1) / 0.4) * 0.3;
94
+ }
95
+ }
96
+ signals.push({ name: 'tokenEfficiency', value: effVal, weight: 0.25 });
97
+ // Signal 4: file survival (weight 0.2) — delayed, may be null
98
+ const survivalVal = context.fileSurvival ?? null;
99
+ signals.push({ name: 'fileSurvival', value: survivalVal, weight: 0.2 });
100
+ // Compound score with weight redistribution
101
+ const active = signals.filter(s => s.value !== null);
102
+ const totalWeight = active.reduce((sum, s) => sum + s.weight, 0);
103
+ const reward = totalWeight > 0
104
+ ? active.reduce((sum, s) => sum + (s.value * s.weight / totalWeight), 0)
105
+ : 0;
106
+ const confidence = totalWeight;
107
+ return {
108
+ reward: Math.min(1, Math.max(0, reward)),
109
+ confidence: Math.min(1, confidence),
110
+ signals: {
111
+ exitSuccess: exitVal,
112
+ durationRatio: durVal,
113
+ tokenEfficiency: effVal,
114
+ fileSurvival: survivalVal,
115
+ },
116
+ };
117
+ }
118
+ catch {
119
+ return { reward: 0, confidence: 0, signals: { exitSuccess: false, durationRatio: null, tokenEfficiency: null, fileSurvival: null } };
120
+ }
121
+ }
122
+ //# sourceMappingURL=signal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal.js","sourceRoot":"","sources":["../../src/signal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ interface SimmerItem {
2
+ id: string;
3
+ idea: string;
4
+ origin: string;
5
+ heat: number;
6
+ createdAt: number;
7
+ lastHeated: number;
8
+ signals: string[];
9
+ crystallized: boolean;
10
+ crystallizedAs: string | null;
11
+ }
12
+ /**
13
+ * @typedef {object} SimmerItem
14
+ * @property {string} id
15
+ * @property {string} idea - The raw idea in prose
16
+ * @property {string} origin - Where it came from (user quote, observation, debrief finding)
17
+ * @property {number} heat - Current heat score
18
+ * @property {number} createdAt
19
+ * @property {number} lastHeated - Last time heat was added
20
+ * @property {string[]} signals - Evidence trail (why heat was added)
21
+ * @property {boolean} crystallized - Whether it's crossed the threshold
22
+ * @property {string|null} crystallizedAs - What it became (task description, architecture decision, etc)
23
+ */
24
+ /**
25
+ * Add a new idea to the simmer buffer.
26
+ * If a similar idea already exists (fuzzy match), heat it instead of duplicating.
27
+ *
28
+ * @param {string} idea - The idea in natural language
29
+ * @param {object} opts
30
+ * @param {string} opts.origin - Where this came from
31
+ * @param {number} opts.initialHeat - Starting heat (default 1)
32
+ * @returns {SimmerItem} The created or heated item
33
+ */
34
+ export declare function add(idea: string, { origin, initialHeat }?: {
35
+ origin?: string;
36
+ initialHeat?: number;
37
+ }): SimmerItem;
38
+ /**
39
+ * Add heat to an existing item. If it crosses the threshold, mark as crystallized.
40
+ *
41
+ * @param {string} id
42
+ * @param {number} amount - Heat to add (default 1)
43
+ * @param {string} signal - Why heat is being added
44
+ * @returns {SimmerItem|null}
45
+ */
46
+ export declare function heat(id: string, amount?: number, signal?: string): SimmerItem | null;
47
+ /**
48
+ * Get all items that have crystallized but haven't been surfaced yet.
49
+ * These should be presented to HEAD during deliberation.
50
+ *
51
+ * @returns {SimmerItem[]}
52
+ */
53
+ export declare function harvest(): SimmerItem[];
54
+ /**
55
+ * Mark a crystallized item as actioned — record what it became.
56
+ *
57
+ * @param {string} id
58
+ * @param {string} became - Description of what action was taken
59
+ */
60
+ export declare function resolve(id: string, became: string): void;
61
+ /**
62
+ * Get all active (non-resolved) simmering items, sorted by heat descending.
63
+ * Used by the narrative to include "what's brewing" context.
64
+ *
65
+ * @returns {SimmerItem[]}
66
+ */
67
+ export declare function active(): SimmerItem[];
68
+ /**
69
+ * Check if an idea already exists in the buffer (for deduplication).
70
+ * @param {string} idea
71
+ * @returns {SimmerItem|null}
72
+ */
73
+ export declare function find(idea: string): SimmerItem | null;
74
+ /**
75
+ * Generate a brief for HEAD showing what's simmering.
76
+ * Included in the narrative context so HEAD is aware of brewing ideas.
77
+ *
78
+ * @returns {string} Prose summary of active simmer items, or empty string
79
+ */
80
+ export declare function brief(): string;
81
+ /**
82
+ * Prune resolved and cold-dead items.
83
+ */
84
+ export declare function prune(): void;
85
+ export {};