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,224 @@
1
+ // simmer.mjs — Ideas that aren't tasks yet. They sit, gather heat, and crystallize.
2
+ //
3
+ // The "song" insight: users drop ideas casually. HEAD tends to acknowledge them
4
+ // verbally then move on. The simmer buffer catches these — every idea gets stored
5
+ // with a heat score. Heat rises when: the idea recurs, evidence supports it,
6
+ // adjacent work makes it more relevant, or time passes and it keeps nagging.
7
+ // When heat crosses a threshold, the idea crystallizes into an actionable item
8
+ // and surfaces to HEAD during deliberation.
9
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
10
+ import { join } from 'node:path';
11
+ const STATE_DIR = join(process.cwd(), '.dualbrain');
12
+ const SIMMER_FILE = join(STATE_DIR, 'simmer.json');
13
+ const CRYSTALLIZE_THRESHOLD = 5;
14
+ const MAX_ITEMS = 30;
15
+ const HEAT_DECAY_PER_HOUR = 0.3;
16
+ /**
17
+ * @typedef {object} SimmerItem
18
+ * @property {string} id
19
+ * @property {string} idea - The raw idea in prose
20
+ * @property {string} origin - Where it came from (user quote, observation, debrief finding)
21
+ * @property {number} heat - Current heat score
22
+ * @property {number} createdAt
23
+ * @property {number} lastHeated - Last time heat was added
24
+ * @property {string[]} signals - Evidence trail (why heat was added)
25
+ * @property {boolean} crystallized - Whether it's crossed the threshold
26
+ * @property {string|null} crystallizedAs - What it became (task description, architecture decision, etc)
27
+ */
28
+ /**
29
+ * Add a new idea to the simmer buffer.
30
+ * If a similar idea already exists (fuzzy match), heat it instead of duplicating.
31
+ *
32
+ * @param {string} idea - The idea in natural language
33
+ * @param {object} opts
34
+ * @param {string} opts.origin - Where this came from
35
+ * @param {number} opts.initialHeat - Starting heat (default 1)
36
+ * @returns {SimmerItem} The created or heated item
37
+ */
38
+ export function add(idea, { origin = 'observation', initialHeat = 1 } = {}) {
39
+ const items = _load();
40
+ // Check for similar existing idea
41
+ const existing = _findSimilar(items, idea);
42
+ if (existing) {
43
+ return heat(existing.id, initialHeat, `Recurrence: "${idea.slice(0, 60)}"`);
44
+ }
45
+ const item = {
46
+ id: Date.now().toString(36) + Math.random().toString(36).slice(2, 5),
47
+ idea,
48
+ origin,
49
+ heat: initialHeat,
50
+ createdAt: Date.now(),
51
+ lastHeated: Date.now(),
52
+ signals: [`Created from: ${origin}`],
53
+ crystallized: false,
54
+ crystallizedAs: null,
55
+ };
56
+ items.push(item);
57
+ _save(items);
58
+ return item;
59
+ }
60
+ /**
61
+ * Add heat to an existing item. If it crosses the threshold, mark as crystallized.
62
+ *
63
+ * @param {string} id
64
+ * @param {number} amount - Heat to add (default 1)
65
+ * @param {string} signal - Why heat is being added
66
+ * @returns {SimmerItem|null}
67
+ */
68
+ export function heat(id, amount = 1, signal = '') {
69
+ const items = _load();
70
+ const item = items.find(i => i.id === id);
71
+ if (!item)
72
+ return null;
73
+ item.heat += amount;
74
+ item.lastHeated = Date.now();
75
+ if (signal)
76
+ item.signals.push(signal);
77
+ // Cap signals array
78
+ if (item.signals.length > 10) {
79
+ item.signals = item.signals.slice(-10);
80
+ }
81
+ // Check crystallization
82
+ if (!item.crystallized && item.heat >= CRYSTALLIZE_THRESHOLD) {
83
+ item.crystallized = true;
84
+ }
85
+ _save(items);
86
+ return item;
87
+ }
88
+ /**
89
+ * Get all items that have crystallized but haven't been surfaced yet.
90
+ * These should be presented to HEAD during deliberation.
91
+ *
92
+ * @returns {SimmerItem[]}
93
+ */
94
+ export function harvest() {
95
+ const items = _load();
96
+ return items.filter(i => i.crystallized && !i.crystallizedAs);
97
+ }
98
+ /**
99
+ * Mark a crystallized item as actioned — record what it became.
100
+ *
101
+ * @param {string} id
102
+ * @param {string} became - Description of what action was taken
103
+ */
104
+ export function resolve(id, became) {
105
+ const items = _load();
106
+ const item = items.find(i => i.id === id);
107
+ if (!item)
108
+ return;
109
+ item.crystallizedAs = became;
110
+ _save(items);
111
+ }
112
+ /**
113
+ * Get all active (non-resolved) simmering items, sorted by heat descending.
114
+ * Used by the narrative to include "what's brewing" context.
115
+ *
116
+ * @returns {SimmerItem[]}
117
+ */
118
+ export function active() {
119
+ const items = _load();
120
+ _applyDecay(items);
121
+ return items
122
+ .filter(i => !i.crystallizedAs)
123
+ .sort((a, b) => b.heat - a.heat);
124
+ }
125
+ /**
126
+ * Check if an idea already exists in the buffer (for deduplication).
127
+ * @param {string} idea
128
+ * @returns {SimmerItem|null}
129
+ */
130
+ export function find(idea) {
131
+ const items = _load();
132
+ return _findSimilar(items, idea);
133
+ }
134
+ /**
135
+ * Generate a brief for HEAD showing what's simmering.
136
+ * Included in the narrative context so HEAD is aware of brewing ideas.
137
+ *
138
+ * @returns {string} Prose summary of active simmer items, or empty string
139
+ */
140
+ export function brief() {
141
+ const items = active();
142
+ if (items.length === 0)
143
+ return '';
144
+ const crystallized = items.filter(i => i.crystallized);
145
+ const hot = items.filter(i => !i.crystallized && i.heat >= 3);
146
+ const warm = items.filter(i => !i.crystallized && i.heat >= 1.5 && i.heat < 3);
147
+ const parts = [];
148
+ if (crystallized.length > 0) {
149
+ parts.push(`Crystallized (ready to act): ${crystallized.map(i => i.idea.slice(0, 80)).join('; ')}`);
150
+ }
151
+ if (hot.length > 0) {
152
+ parts.push(`Hot (building momentum): ${hot.map(i => `${i.idea.slice(0, 60)} [heat:${i.heat.toFixed(1)}]`).join('; ')}`);
153
+ }
154
+ if (warm.length > 0 && parts.length < 2) {
155
+ parts.push(`Warm: ${warm.slice(0, 3).map(i => i.idea.slice(0, 50)).join('; ')}`);
156
+ }
157
+ return parts.join('\n');
158
+ }
159
+ /**
160
+ * Prune resolved and cold-dead items.
161
+ */
162
+ export function prune() {
163
+ let items = _load();
164
+ _applyDecay(items);
165
+ // Remove: resolved items older than 1h, or items with heat <= 0
166
+ const cutoff = Date.now() - 60 * 60 * 1000;
167
+ items = items.filter(i => {
168
+ if (i.crystallizedAs && i.lastHeated < cutoff)
169
+ return false;
170
+ if (i.heat <= 0)
171
+ return false;
172
+ return true;
173
+ });
174
+ _save(items);
175
+ }
176
+ // ── Internal ──────────────────────────────────────────────────────────────────
177
+ function _load() {
178
+ try {
179
+ if (existsSync(SIMMER_FILE)) {
180
+ return JSON.parse(readFileSync(SIMMER_FILE, 'utf8'));
181
+ }
182
+ }
183
+ catch { }
184
+ return [];
185
+ }
186
+ function _save(items) {
187
+ // Cap total items
188
+ if (items.length > MAX_ITEMS) {
189
+ items.sort((a, b) => b.heat - a.heat);
190
+ items = items.slice(0, MAX_ITEMS);
191
+ }
192
+ mkdirSync(STATE_DIR, { recursive: true });
193
+ writeFileSync(SIMMER_FILE, JSON.stringify(items, null, 2));
194
+ }
195
+ function _applyDecay(items) {
196
+ const now = Date.now();
197
+ for (const item of items) {
198
+ if (item.crystallized)
199
+ continue; // Crystallized items don't decay
200
+ const hoursSinceHeat = (now - item.lastHeated) / (60 * 60 * 1000);
201
+ if (hoursSinceHeat > 1) {
202
+ item.heat -= HEAT_DECAY_PER_HOUR * hoursSinceHeat;
203
+ if (item.heat < 0)
204
+ item.heat = 0;
205
+ }
206
+ }
207
+ }
208
+ function _findSimilar(items, idea) {
209
+ const normalized = idea.toLowerCase().replace(/[^a-z0-9\s]/g, '');
210
+ const words = normalized.split(/\s+/).filter(w => w.length > 4);
211
+ if (words.length === 0)
212
+ return null;
213
+ for (const item of items) {
214
+ if (item.crystallizedAs)
215
+ continue; // Skip resolved
216
+ const itemNorm = item.idea.toLowerCase().replace(/[^a-z0-9\s]/g, '');
217
+ const matchCount = words.filter(w => itemNorm.includes(w)).length;
218
+ if (matchCount >= Math.ceil(words.length * 0.5)) {
219
+ return item;
220
+ }
221
+ }
222
+ return null;
223
+ }
224
+ //# sourceMappingURL=simmer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simmer.js","sourceRoot":"","sources":["../../src/simmer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * state-export.ts — JSON state export for external consumers (web panels, dashboards).
3
+ *
4
+ * Writes orchestrator state to `.dual-brain/state/` as typed JSON files.
5
+ * All writes are atomic (write .tmp then rename) for crash safety.
6
+ * All functions are non-throwing.
7
+ */
8
+ export interface ExportedProviderEntry {
9
+ provider: string;
10
+ status: string;
11
+ lastCheck: string;
12
+ lastSuccess: string;
13
+ cooldownUntil?: string;
14
+ remainingCapacity: number;
15
+ recentDispatches: number;
16
+ consecutiveFailures: number;
17
+ }
18
+ export interface ExportedProviders {
19
+ exportedAt: string;
20
+ providers: ExportedProviderEntry[];
21
+ }
22
+ export interface ExportedRoutingPerformer {
23
+ cell: string;
24
+ model: string;
25
+ ema: number;
26
+ observations: number;
27
+ }
28
+ export interface ExportedRouting {
29
+ exportedAt: string;
30
+ totalObservations: number;
31
+ topPerformers: ExportedRoutingPerformer[];
32
+ worstPerformers: ExportedRoutingPerformer[];
33
+ cells: Record<string, Record<string, {
34
+ ema: number;
35
+ observations: number;
36
+ }>>;
37
+ }
38
+ export interface ExportedRoomEntry {
39
+ id: string;
40
+ status: string;
41
+ taskDescription: string;
42
+ created: string;
43
+ workerCount: number;
44
+ workerStatuses: Record<string, string>;
45
+ }
46
+ export interface ExportedRooms {
47
+ exportedAt: string;
48
+ rooms: ExportedRoomEntry[];
49
+ }
50
+ export interface ExportedDecisionEntry {
51
+ timestamp: string;
52
+ promptSummary: string;
53
+ model: string;
54
+ provider: string;
55
+ tier: string;
56
+ reason: string;
57
+ }
58
+ export interface ExportedDecisions {
59
+ exportedAt: string;
60
+ decisions: ExportedDecisionEntry[];
61
+ }
62
+ export interface ExportedCosts {
63
+ exportedAt: string;
64
+ period: string;
65
+ totalCost: number;
66
+ totalTokens: number;
67
+ totalActions: number;
68
+ cacheHits: number;
69
+ tokensSaved: number;
70
+ costSaved: number;
71
+ savingsRate: number;
72
+ byTier: Record<string, {
73
+ count: number;
74
+ tokens: number;
75
+ cost: number;
76
+ }>;
77
+ byModel: Record<string, {
78
+ count: number;
79
+ tokens: number;
80
+ cost: number;
81
+ }>;
82
+ trend: string;
83
+ }
84
+ export interface ExportedOutcomeEntry {
85
+ timestamp: string;
86
+ roomId: string;
87
+ outcome: Record<string, unknown>;
88
+ }
89
+ export interface ExportedOutcomes {
90
+ exportedAt: string;
91
+ outcomes: ExportedOutcomeEntry[];
92
+ }
93
+ export interface ExportedState {
94
+ exportedAt: string;
95
+ providers: ExportedProviders;
96
+ routing: ExportedRouting;
97
+ rooms: ExportedRooms;
98
+ decisions: ExportedDecisions;
99
+ costs: ExportedCosts;
100
+ outcomes: ExportedOutcomes;
101
+ }
102
+ /**
103
+ * Export full orchestrator state to `.dual-brain/state/`.
104
+ * Writes providers.json, routing.json, rooms.json, decisions.json, costs.json.
105
+ * Non-throwing: returns true on success, false on failure.
106
+ */
107
+ export declare function exportState(cwd?: string): boolean;
108
+ /**
109
+ * Append a routing decision to decisions.json (ring buffer, max 50 entries).
110
+ * Non-throwing.
111
+ */
112
+ export declare function exportDecision(decision: {
113
+ provider?: string;
114
+ model?: string;
115
+ tier?: string;
116
+ explanation?: string;
117
+ [key: string]: unknown;
118
+ }, prompt: string, cwd?: string): void;
119
+ /**
120
+ * Append an outcome to outcomes.json log.
121
+ * Non-throwing.
122
+ */
123
+ export declare function exportOutcome(roomId: string, outcome: Record<string, unknown>, cwd?: string): void;
124
+ /**
125
+ * Read all exported state files and return a combined object.
126
+ * Suitable for HTTP API or MCP tool responses.
127
+ * Non-throwing: returns partial data if some files are missing/corrupt.
128
+ */
129
+ export declare function getExportedState(cwd?: string): ExportedState;
@@ -0,0 +1,233 @@
1
+ /**
2
+ * state-export.ts — JSON state export for external consumers (web panels, dashboards).
3
+ *
4
+ * Writes orchestrator state to `.dual-brain/state/` as typed JSON files.
5
+ * All writes are atomic (write .tmp then rename) for crash safety.
6
+ * All functions are non-throwing.
7
+ */
8
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
9
+ import { join, dirname } from 'node:path';
10
+ import { getAllProviderStates } from './provider-manager.js';
11
+ import { getRoutingStats } from './routing-advisor.js';
12
+ import { listRooms, getWorkerStatuses } from './room.js';
13
+ import { getCostSummary } from './cost-tracker.js';
14
+ // ─── Constants ────────────────────────────────────────────────────────────
15
+ const STATE_DIR = '.dual-brain/state';
16
+ const MAX_DECISIONS = 50;
17
+ const MAX_OUTCOMES = 200;
18
+ // ─── Helpers ──────────────────────────────────────────────────────────────
19
+ function stateDir(cwd) {
20
+ return join(cwd || process.cwd(), STATE_DIR);
21
+ }
22
+ function stateFile(name, cwd) {
23
+ return join(stateDir(cwd), name);
24
+ }
25
+ /**
26
+ * Atomic write: write to .tmp then rename for crash safety.
27
+ */
28
+ function atomicWrite(filePath, data) {
29
+ const dir = dirname(filePath);
30
+ mkdirSync(dir, { recursive: true });
31
+ const tmp = `${filePath}.tmp.${process.pid}.${Date.now()}`;
32
+ const json = JSON.stringify(data, null, 2) + '\n';
33
+ writeFileSync(tmp, json, 'utf8');
34
+ renameSync(tmp, filePath);
35
+ }
36
+ /**
37
+ * Safely read and parse a JSON file. Returns null on any error.
38
+ */
39
+ function readJson(filePath) {
40
+ try {
41
+ if (!existsSync(filePath))
42
+ return null;
43
+ const raw = readFileSync(filePath, 'utf8');
44
+ return JSON.parse(raw);
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ }
50
+ /**
51
+ * Truncate a prompt to a short summary for the decisions log.
52
+ */
53
+ function summarizePrompt(prompt) {
54
+ const cleaned = prompt.replace(/\s+/g, ' ').trim();
55
+ if (cleaned.length <= 120)
56
+ return cleaned;
57
+ return cleaned.slice(0, 117) + '...';
58
+ }
59
+ // ─── Public API ───────────────────────────────────────────────────────────
60
+ /**
61
+ * Export full orchestrator state to `.dual-brain/state/`.
62
+ * Writes providers.json, routing.json, rooms.json, decisions.json, costs.json.
63
+ * Non-throwing: returns true on success, false on failure.
64
+ */
65
+ export function exportState(cwd) {
66
+ try {
67
+ const now = new Date().toISOString();
68
+ const resolvedCwd = cwd || process.cwd();
69
+ // ── providers.json
70
+ const providerStates = getAllProviderStates(resolvedCwd);
71
+ const providers = {
72
+ exportedAt: now,
73
+ providers: providerStates.map((ps) => ({
74
+ provider: ps.provider,
75
+ status: ps.status,
76
+ lastCheck: ps.lastCheck,
77
+ lastSuccess: ps.lastSuccess,
78
+ cooldownUntil: ps.cooldownUntil,
79
+ remainingCapacity: ps.remainingCapacity,
80
+ recentDispatches: ps.recentDispatches,
81
+ consecutiveFailures: ps.consecutiveFailures,
82
+ })),
83
+ };
84
+ atomicWrite(stateFile('providers.json', resolvedCwd), providers);
85
+ // ── routing.json
86
+ const stats = getRoutingStats(resolvedCwd);
87
+ const routing = {
88
+ exportedAt: now,
89
+ totalObservations: stats.totalObservations,
90
+ topPerformers: stats.topPerformers,
91
+ worstPerformers: stats.worstPerformers,
92
+ cells: stats.cells,
93
+ };
94
+ atomicWrite(stateFile('routing.json', resolvedCwd), routing);
95
+ // ── rooms.json
96
+ const roomSummaries = listRooms(resolvedCwd);
97
+ const roomEntries = roomSummaries.map((rs) => ({
98
+ id: rs.id,
99
+ status: rs.status,
100
+ taskDescription: rs.taskDescription,
101
+ created: rs.created,
102
+ workerCount: rs.workerCount,
103
+ workerStatuses: getWorkerStatuses(rs.id, resolvedCwd),
104
+ }));
105
+ const rooms = {
106
+ exportedAt: now,
107
+ rooms: roomEntries,
108
+ };
109
+ atomicWrite(stateFile('rooms.json', resolvedCwd), rooms);
110
+ // ── decisions.json — preserve existing, just update exportedAt
111
+ const existingDecisions = readJson(stateFile('decisions.json', resolvedCwd));
112
+ const decisions = {
113
+ exportedAt: now,
114
+ decisions: existingDecisions?.decisions ?? [],
115
+ };
116
+ atomicWrite(stateFile('decisions.json', resolvedCwd), decisions);
117
+ // ── costs.json
118
+ const costSummary = getCostSummary(resolvedCwd, 7);
119
+ const costs = {
120
+ exportedAt: now,
121
+ period: costSummary.period,
122
+ totalCost: costSummary.totalCost,
123
+ totalTokens: costSummary.totalTokens,
124
+ totalActions: costSummary.totalActions,
125
+ cacheHits: costSummary.cacheHits,
126
+ tokensSaved: costSummary.tokensSaved,
127
+ costSaved: costSummary.costSaved,
128
+ savingsRate: costSummary.savingsRate,
129
+ byTier: costSummary.byTier,
130
+ byModel: costSummary.byModel,
131
+ trend: costSummary.trend,
132
+ };
133
+ atomicWrite(stateFile('costs.json', resolvedCwd), costs);
134
+ return true;
135
+ }
136
+ catch {
137
+ return false;
138
+ }
139
+ }
140
+ /**
141
+ * Append a routing decision to decisions.json (ring buffer, max 50 entries).
142
+ * Non-throwing.
143
+ */
144
+ export function exportDecision(decision, prompt, cwd) {
145
+ try {
146
+ const resolvedCwd = cwd || process.cwd();
147
+ const filePath = stateFile('decisions.json', resolvedCwd);
148
+ const existing = readJson(filePath);
149
+ const entries = existing?.decisions ?? [];
150
+ const entry = {
151
+ timestamp: new Date().toISOString(),
152
+ promptSummary: summarizePrompt(prompt),
153
+ model: decision.model ?? 'unknown',
154
+ provider: decision.provider ?? 'unknown',
155
+ tier: decision.tier ?? 'unknown',
156
+ reason: decision.explanation ?? '',
157
+ };
158
+ entries.push(entry);
159
+ // Ring buffer: keep only the last MAX_DECISIONS entries
160
+ const trimmed = entries.length > MAX_DECISIONS
161
+ ? entries.slice(entries.length - MAX_DECISIONS)
162
+ : entries;
163
+ const output = {
164
+ exportedAt: new Date().toISOString(),
165
+ decisions: trimmed,
166
+ };
167
+ atomicWrite(filePath, output);
168
+ }
169
+ catch {
170
+ // non-throwing
171
+ }
172
+ }
173
+ /**
174
+ * Append an outcome to outcomes.json log.
175
+ * Non-throwing.
176
+ */
177
+ export function exportOutcome(roomId, outcome, cwd) {
178
+ try {
179
+ const resolvedCwd = cwd || process.cwd();
180
+ const filePath = stateFile('outcomes.json', resolvedCwd);
181
+ const existing = readJson(filePath);
182
+ const entries = existing?.outcomes ?? [];
183
+ const entry = {
184
+ timestamp: new Date().toISOString(),
185
+ roomId,
186
+ outcome,
187
+ };
188
+ entries.push(entry);
189
+ // Keep bounded (MAX_OUTCOMES)
190
+ const trimmed = entries.length > MAX_OUTCOMES
191
+ ? entries.slice(entries.length - MAX_OUTCOMES)
192
+ : entries;
193
+ const output = {
194
+ exportedAt: new Date().toISOString(),
195
+ outcomes: trimmed,
196
+ };
197
+ atomicWrite(filePath, output);
198
+ }
199
+ catch {
200
+ // non-throwing
201
+ }
202
+ }
203
+ /**
204
+ * Read all exported state files and return a combined object.
205
+ * Suitable for HTTP API or MCP tool responses.
206
+ * Non-throwing: returns partial data if some files are missing/corrupt.
207
+ */
208
+ export function getExportedState(cwd) {
209
+ const resolvedCwd = cwd || process.cwd();
210
+ const now = new Date().toISOString();
211
+ const providers = readJson(stateFile('providers.json', resolvedCwd))
212
+ ?? { exportedAt: now, providers: [] };
213
+ const routing = readJson(stateFile('routing.json', resolvedCwd))
214
+ ?? { exportedAt: now, totalObservations: 0, topPerformers: [], worstPerformers: [], cells: {} };
215
+ const rooms = readJson(stateFile('rooms.json', resolvedCwd))
216
+ ?? { exportedAt: now, rooms: [] };
217
+ const decisions = readJson(stateFile('decisions.json', resolvedCwd))
218
+ ?? { exportedAt: now, decisions: [] };
219
+ const costs = readJson(stateFile('costs.json', resolvedCwd))
220
+ ?? { exportedAt: now, period: '7 days', totalCost: 0, totalTokens: 0, totalActions: 0, cacheHits: 0, tokensSaved: 0, costSaved: 0, savingsRate: 0, byTier: {}, byModel: {}, trend: 'stable' };
221
+ const outcomes = readJson(stateFile('outcomes.json', resolvedCwd))
222
+ ?? { exportedAt: now, outcomes: [] };
223
+ return {
224
+ exportedAt: now,
225
+ providers,
226
+ routing,
227
+ rooms,
228
+ decisions,
229
+ costs,
230
+ outcomes,
231
+ };
232
+ }
233
+ //# sourceMappingURL=state-export.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-export.js","sourceRoot":"","sources":["../../src/state-export.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ interface StrategyApplicability {
2
+ maxFiles?: number;
3
+ maxComplexity?: string;
4
+ maxRisk?: string;
5
+ minFiles?: number;
6
+ minComplexity?: string;
7
+ minRisk?: string;
8
+ }
9
+ interface StrategyDef {
10
+ id: string;
11
+ label: string;
12
+ description: string;
13
+ applicability: StrategyApplicability;
14
+ cost: number;
15
+ }
16
+ export declare const STRATEGIES: Record<string, StrategyDef>;
17
+ interface Detection {
18
+ fileCount?: number;
19
+ files?: number;
20
+ complexity?: string;
21
+ risk?: string;
22
+ prompt?: string;
23
+ description?: string;
24
+ }
25
+ interface StrategyResult {
26
+ strategy: string;
27
+ reason: string;
28
+ alternatives: string[];
29
+ }
30
+ export declare function selectStrategy(detection: Detection, decision: {
31
+ model?: string;
32
+ }, profile: {
33
+ workStyle?: string;
34
+ bias?: string;
35
+ }): StrategyResult;
36
+ export declare function describeStrategy(strategyId: string): string;
37
+ interface PlanStep {
38
+ role: string;
39
+ model: string;
40
+ description: string;
41
+ }
42
+ interface StrategyWithPlan extends StrategyResult {
43
+ plan: {
44
+ steps: PlanStep[];
45
+ };
46
+ }
47
+ export declare function getStrategyForTask(detection: Detection, cwd?: string): StrategyWithPlan;
48
+ export declare function listStrategies(): {
49
+ id: string;
50
+ label: string;
51
+ description: string;
52
+ cost: number;
53
+ }[];
54
+ export {};