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,89 @@
1
+ #!/usr/bin/env node
2
+ export interface HandoffSessionState {
3
+ taskDescription?: string;
4
+ filesChanged?: string[];
5
+ testsRun?: string[];
6
+ decisions?: object[];
7
+ unresolved?: string[];
8
+ routingHistory?: {
9
+ lastProvider?: string;
10
+ lastModel?: string;
11
+ failedProviders?: string[];
12
+ };
13
+ activePreferences?: string[];
14
+ resumeHint?: string;
15
+ narrative?: string;
16
+ }
17
+ export interface Handoff {
18
+ version: number;
19
+ timestamp: string;
20
+ task: string | null;
21
+ progress: {
22
+ filesChanged: string[];
23
+ testsRun: string[];
24
+ decisions: object[];
25
+ };
26
+ unresolved: string[];
27
+ routing: {
28
+ lastProvider: string | null;
29
+ lastModel: string | null;
30
+ failedProviders: string[];
31
+ };
32
+ preferences: string[];
33
+ resumeHint: string | null;
34
+ narrative: string | null;
35
+ }
36
+ /**
37
+ * Generate a compact handoff object from current session state.
38
+ * Designed to fit in ~500 tokens when serialized.
39
+ */
40
+ export declare function generateHandoff(sessionState: HandoffSessionState): Handoff;
41
+ /**
42
+ * Persist a handoff object to .dualbrain/handoffs/.
43
+ */
44
+ export declare function saveHandoff(handoff: Handoff, cwd?: string): string;
45
+ /**
46
+ * Load the most recent handoff from .dualbrain/handoffs/.
47
+ * Returns null when no handoffs exist or all are unreadable.
48
+ */
49
+ export declare function getLatestHandoff(cwd?: string): Handoff | null;
50
+ /**
51
+ * Return the age of a handoff in hours.
52
+ * Returns Infinity when the handoff has no timestamp.
53
+ */
54
+ export declare function getHandoffAge(handoff: Handoff | null): number;
55
+ export interface CompactionState {
56
+ activeTask?: string;
57
+ routingRules?: string[];
58
+ criticalDecisions?: string[];
59
+ filesInProgress?: string[];
60
+ preferences?: string[];
61
+ warnings?: string[];
62
+ }
63
+ /**
64
+ * Build a compaction-safe summary string to inject before context compression.
65
+ */
66
+ export declare function buildCompactionSurvivalKit(state: CompactionState): string;
67
+ /**
68
+ * Check for a recent handoff and build a resume context string for a new session.
69
+ * Returns null when no usable handoff exists (missing, too stale, or unreadable).
70
+ */
71
+ export declare function buildResumeBrief(cwd?: string): string | null;
72
+ /**
73
+ * Remove old handoff files, keeping only the most recent `keep` entries.
74
+ */
75
+ export declare function pruneHandoffs(cwd?: string, keep?: number): number;
76
+ export interface RoutingPattern {
77
+ type: string;
78
+ value: string;
79
+ count: number;
80
+ }
81
+ export interface RoutingPatterns {
82
+ patterns: RoutingPattern[];
83
+ confidence: number;
84
+ sampleSize: number;
85
+ }
86
+ /**
87
+ * Extract routing patterns from handoff history to inform provider/model selection.
88
+ */
89
+ export declare function extractRoutingPatterns(cwd?: string): RoutingPatterns;
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ // continuity.ts — Session continuity for dual-brain.
3
+ // Generates handoff receipts so the next session can pick up seamlessly
4
+ // when a session hits context limits, crashes, or is manually ended.
5
+ //
6
+ // Exports: generateHandoff, saveHandoff, getLatestHandoff, getHandoffAge,
7
+ // buildCompactionSurvivalKit, buildResumeBrief, pruneHandoffs,
8
+ // extractRoutingPatterns
9
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, unlinkSync } from 'node:fs';
10
+ import { join } from 'node:path';
11
+ import { load as loadNarrative } from './narrative.js';
12
+ /**
13
+ * Generate a compact handoff object from current session state.
14
+ * Designed to fit in ~500 tokens when serialized.
15
+ */
16
+ export function generateHandoff(sessionState) {
17
+ return {
18
+ version: 2,
19
+ timestamp: new Date().toISOString(),
20
+ task: sessionState.taskDescription || null,
21
+ progress: {
22
+ filesChanged: (sessionState.filesChanged || []).slice(0, 20),
23
+ testsRun: sessionState.testsRun || [],
24
+ decisions: (sessionState.decisions || []).slice(0, 5),
25
+ },
26
+ unresolved: (sessionState.unresolved || []).slice(0, 5),
27
+ routing: {
28
+ lastProvider: sessionState.routingHistory?.lastProvider || null,
29
+ lastModel: sessionState.routingHistory?.lastModel || null,
30
+ failedProviders: sessionState.routingHistory?.failedProviders || [],
31
+ },
32
+ preferences: sessionState.activePreferences || [],
33
+ resumeHint: sessionState.resumeHint || null,
34
+ narrative: sessionState.narrative || loadNarrative() || null,
35
+ };
36
+ }
37
+ // ─── Handoff persistence ──────────────────────────────────────────────────────
38
+ /**
39
+ * Persist a handoff object to .dualbrain/handoffs/.
40
+ */
41
+ export function saveHandoff(handoff, cwd) {
42
+ const dir = join(cwd || process.cwd(), '.dualbrain', 'handoffs');
43
+ mkdirSync(dir, { recursive: true });
44
+ const filename = `handoff-${Date.now()}.json`;
45
+ writeFileSync(join(dir, filename), JSON.stringify(handoff, null, 2));
46
+ return join(dir, filename);
47
+ }
48
+ /**
49
+ * Load the most recent handoff from .dualbrain/handoffs/.
50
+ * Returns null when no handoffs exist or all are unreadable.
51
+ */
52
+ export function getLatestHandoff(cwd) {
53
+ const dir = join(cwd || process.cwd(), '.dualbrain', 'handoffs');
54
+ if (!existsSync(dir))
55
+ return null;
56
+ const files = readdirSync(dir)
57
+ .filter(f => f.startsWith('handoff-') && f.endsWith('.json'))
58
+ .sort()
59
+ .reverse();
60
+ if (files.length === 0)
61
+ return null;
62
+ try {
63
+ return JSON.parse(readFileSync(join(dir, files[0]), 'utf8'));
64
+ }
65
+ catch {
66
+ return null;
67
+ }
68
+ }
69
+ /**
70
+ * Return the age of a handoff in hours.
71
+ * Returns Infinity when the handoff has no timestamp.
72
+ */
73
+ export function getHandoffAge(handoff) {
74
+ if (!handoff?.timestamp)
75
+ return Infinity;
76
+ return (Date.now() - Date.parse(handoff.timestamp)) / 3600000;
77
+ }
78
+ /**
79
+ * Build a compaction-safe summary string to inject before context compression.
80
+ */
81
+ export function buildCompactionSurvivalKit(state) {
82
+ const lines = [];
83
+ lines.push('[DUAL-BRAIN CONTINUITY]');
84
+ if (state.activeTask) {
85
+ lines.push(`TASK: ${state.activeTask}`);
86
+ }
87
+ if (state.routingRules?.length) {
88
+ lines.push(`ROUTING: ${state.routingRules.join('; ')}`);
89
+ }
90
+ if (state.criticalDecisions?.length) {
91
+ lines.push(`DECISIONS: ${state.criticalDecisions.join('; ')}`);
92
+ }
93
+ if (state.filesInProgress?.length) {
94
+ lines.push(`FILES: ${state.filesInProgress.join(', ')}`);
95
+ }
96
+ if (state.preferences?.length) {
97
+ lines.push(`PREFS: ${state.preferences.join('; ')}`);
98
+ }
99
+ if (state.warnings?.length) {
100
+ lines.push(`WARNINGS: ${state.warnings.join('; ')}`);
101
+ }
102
+ lines.push('[/DUAL-BRAIN CONTINUITY]');
103
+ return lines.join('\n');
104
+ }
105
+ // ─── Resume brief builder ─────────────────────────────────────────────────────
106
+ /**
107
+ * Check for a recent handoff and build a resume context string for a new session.
108
+ * Returns null when no usable handoff exists (missing, too stale, or unreadable).
109
+ */
110
+ export function buildResumeBrief(cwd) {
111
+ const handoff = getLatestHandoff(cwd);
112
+ if (!handoff)
113
+ return null;
114
+ const ageHours = getHandoffAge(handoff);
115
+ if (ageHours > 48)
116
+ return null; // too stale to be useful
117
+ const lines = [];
118
+ const ageLabel = ageHours < 1
119
+ ? 'just now'
120
+ : ageHours < 24
121
+ ? `${Math.round(ageHours)}h ago`
122
+ : `${Math.round(ageHours / 24)}d ago`;
123
+ lines.push(`Resuming from previous session (${ageLabel}):`);
124
+ // Narrative first — most valuable context for immersion
125
+ if (handoff.narrative) {
126
+ lines.push(` Context: ${handoff.narrative.slice(0, 300)}`);
127
+ }
128
+ if (handoff.task)
129
+ lines.push(` Task: ${handoff.task}`);
130
+ if (handoff.resumeHint)
131
+ lines.push(` Next: ${handoff.resumeHint}`);
132
+ if (handoff.progress?.filesChanged?.length) {
133
+ const shown = handoff.progress.filesChanged.slice(0, 5);
134
+ const extra = handoff.progress.filesChanged.length > 5
135
+ ? ` (+${handoff.progress.filesChanged.length - 5} more)`
136
+ : '';
137
+ lines.push(` Changed: ${shown.join(', ')}${extra}`);
138
+ }
139
+ if (handoff.unresolved?.length) {
140
+ lines.push(` Unresolved: ${handoff.unresolved.join('; ')}`);
141
+ }
142
+ if (handoff.routing?.failedProviders?.length) {
143
+ lines.push(` Note: ${handoff.routing.failedProviders.join(', ')} failed last session`);
144
+ }
145
+ return lines.join('\n');
146
+ }
147
+ // ─── Handoff cleanup ──────────────────────────────────────────────────────────
148
+ /**
149
+ * Remove old handoff files, keeping only the most recent `keep` entries.
150
+ */
151
+ export function pruneHandoffs(cwd, keep = 10) {
152
+ const dir = join(cwd || process.cwd(), '.dualbrain', 'handoffs');
153
+ if (!existsSync(dir))
154
+ return 0;
155
+ const files = readdirSync(dir)
156
+ .filter(f => f.startsWith('handoff-') && f.endsWith('.json'))
157
+ .sort()
158
+ .reverse();
159
+ let pruned = 0;
160
+ for (const f of files.slice(keep)) {
161
+ try {
162
+ unlinkSync(join(dir, f));
163
+ pruned++;
164
+ }
165
+ catch {
166
+ // Skip files that can't be removed — best-effort
167
+ }
168
+ }
169
+ return pruned;
170
+ }
171
+ /**
172
+ * Extract routing patterns from handoff history to inform provider/model selection.
173
+ */
174
+ export function extractRoutingPatterns(cwd) {
175
+ const dir = join(cwd || process.cwd(), '.dualbrain', 'handoffs');
176
+ if (!existsSync(dir))
177
+ return { patterns: [], confidence: 0, sampleSize: 0 };
178
+ const files = readdirSync(dir)
179
+ .filter(f => f.startsWith('handoff-') && f.endsWith('.json'))
180
+ .sort()
181
+ .reverse()
182
+ .slice(0, 20);
183
+ const handoffs = files
184
+ .map(f => {
185
+ try {
186
+ return JSON.parse(readFileSync(join(dir, f), 'utf8'));
187
+ }
188
+ catch {
189
+ return null;
190
+ }
191
+ })
192
+ .filter((h) => h !== null);
193
+ // Count provider/model usage patterns
194
+ const providerCounts = {};
195
+ const modelCounts = {};
196
+ const failureCounts = {};
197
+ for (const h of handoffs) {
198
+ if (h.routing?.lastProvider) {
199
+ providerCounts[h.routing.lastProvider] = (providerCounts[h.routing.lastProvider] || 0) + 1;
200
+ }
201
+ if (h.routing?.lastModel) {
202
+ modelCounts[h.routing.lastModel] = (modelCounts[h.routing.lastModel] || 0) + 1;
203
+ }
204
+ for (const fp of (h.routing?.failedProviders || [])) {
205
+ failureCounts[fp] = (failureCounts[fp] || 0) + 1;
206
+ }
207
+ }
208
+ const patterns = [];
209
+ // Most used provider
210
+ const topProvider = Object.entries(providerCounts).sort((a, b) => b[1] - a[1])[0];
211
+ if (topProvider) {
212
+ patterns.push({ type: 'preferred_provider', value: topProvider[0], count: topProvider[1] });
213
+ }
214
+ // Most used model
215
+ const topModel = Object.entries(modelCounts).sort((a, b) => b[1] - a[1])[0];
216
+ if (topModel) {
217
+ patterns.push({ type: 'preferred_model', value: topModel[0], count: topModel[1] });
218
+ }
219
+ // Frequently failing provider (threshold: 3+ failures)
220
+ const topFailure = Object.entries(failureCounts).sort((a, b) => b[1] - a[1])[0];
221
+ if (topFailure && topFailure[1] >= 3) {
222
+ patterns.push({ type: 'unreliable_provider', value: topFailure[0], count: topFailure[1] });
223
+ }
224
+ return {
225
+ patterns,
226
+ confidence: Math.min(1, handoffs.length / 10),
227
+ sampleSize: handoffs.length,
228
+ };
229
+ }
230
+ //# sourceMappingURL=continuity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"continuity.js","sourceRoot":"","sources":["../../src/continuity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ interface CostAction {
2
+ action?: string;
3
+ model?: string;
4
+ tokensEstimated?: number;
5
+ tier?: string;
6
+ wasCacheHit?: boolean;
7
+ tokensSaved?: number;
8
+ }
9
+ interface CostEntry {
10
+ timestamp: string;
11
+ action: string;
12
+ model: string;
13
+ tokensEstimated: number;
14
+ costEstimated: number;
15
+ tier: string;
16
+ wasCacheHit: boolean;
17
+ tokensSaved: number;
18
+ }
19
+ interface TierBreakdown {
20
+ count: number;
21
+ tokens: number;
22
+ cost: number;
23
+ }
24
+ interface ModelBreakdown {
25
+ count: number;
26
+ tokens: number;
27
+ cost: number;
28
+ }
29
+ interface CostSummary {
30
+ period: string;
31
+ totalCost: number;
32
+ totalTokens: number;
33
+ totalActions: number;
34
+ cacheHits: number;
35
+ tokensSaved: number;
36
+ costSaved: number;
37
+ savingsRate: number;
38
+ byTier: Record<string, TierBreakdown>;
39
+ byModel: Record<string, ModelBreakdown>;
40
+ trend: 'stable' | 'improving' | 'degrading';
41
+ }
42
+ export declare function estimateTokenCost(model: string, tokens: number): number;
43
+ export declare function trackCost(action: CostAction, cwd?: string): CostEntry | null;
44
+ export declare function getCostSummary(cwd?: string, days?: number): CostSummary;
45
+ export declare function formatCostReport(summary: CostSummary): string;
46
+ export declare function getEfficiencyScore(cwd?: string): number;
47
+ export {};
@@ -0,0 +1,170 @@
1
+ // cost-tracker.ts — Lightweight cost estimation and efficiency tracking for .dualbrain/costs.jsonl.
2
+ import { readFileSync, appendFileSync, mkdirSync, existsSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ const TOKEN_COSTS = {
5
+ 'claude-opus-4-6': 0.03,
6
+ 'claude-sonnet-4-6': 0.006,
7
+ 'claude-haiku-4-5-20251001': 0.001,
8
+ 'gpt-5.5': 0.04,
9
+ 'o3': 0.03,
10
+ 'gpt-4o': 0.005,
11
+ 'gpt-4o-mini': 0.0003,
12
+ 'default': 0.01,
13
+ };
14
+ export function estimateTokenCost(model, tokens) {
15
+ const rate = TOKEN_COSTS[model] ?? TOKEN_COSTS['default'];
16
+ return (tokens / 1000) * rate;
17
+ }
18
+ export function trackCost(action, cwd = process.cwd()) {
19
+ try {
20
+ const dir = join(cwd, '.dualbrain');
21
+ mkdirSync(dir, { recursive: true });
22
+ const entry = {
23
+ timestamp: new Date().toISOString(),
24
+ action: action.action ?? 'execute',
25
+ model: action.model ?? 'default',
26
+ tokensEstimated: action.tokensEstimated ?? 0,
27
+ costEstimated: estimateTokenCost(action.model ?? 'default', action.tokensEstimated ?? 0),
28
+ tier: action.tier ?? 'standard',
29
+ wasCacheHit: action.wasCacheHit ?? false,
30
+ tokensSaved: action.tokensSaved ?? 0,
31
+ };
32
+ appendFileSync(join(dir, 'costs.jsonl'), JSON.stringify(entry) + '\n', 'utf8');
33
+ return entry;
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ }
39
+ function readCostLines(cwd) {
40
+ const p = join(cwd, '.dualbrain', 'costs.jsonl');
41
+ if (!existsSync(p))
42
+ return [];
43
+ try {
44
+ return readFileSync(p, 'utf8').trim().split('\n').filter(Boolean).flatMap(line => {
45
+ try {
46
+ return [JSON.parse(line)];
47
+ }
48
+ catch {
49
+ return [];
50
+ }
51
+ });
52
+ }
53
+ catch {
54
+ return [];
55
+ }
56
+ }
57
+ export function getCostSummary(cwd = process.cwd(), days = 7) {
58
+ const cutoff = new Date(Date.now() - days * 86400000).toISOString();
59
+ const all = readCostLines(cwd).filter(e => e.timestamp >= cutoff);
60
+ if (all.length === 0) {
61
+ return {
62
+ period: `${days} days`,
63
+ totalCost: 0, totalTokens: 0, totalActions: 0,
64
+ cacheHits: 0, tokensSaved: 0, costSaved: 0, savingsRate: 0,
65
+ byTier: {}, byModel: {}, trend: 'stable',
66
+ };
67
+ }
68
+ let totalCost = 0, totalTokens = 0, cacheHits = 0, tokensSaved = 0;
69
+ const byTier = {};
70
+ const byModel = {};
71
+ for (const e of all) {
72
+ totalCost += e.costEstimated ?? 0;
73
+ totalTokens += e.tokensEstimated ?? 0;
74
+ if (e.wasCacheHit) {
75
+ cacheHits++;
76
+ tokensSaved += e.tokensSaved ?? 0;
77
+ }
78
+ const tier = e.tier ?? 'standard';
79
+ if (!byTier[tier])
80
+ byTier[tier] = { count: 0, tokens: 0, cost: 0 };
81
+ byTier[tier].count += 1;
82
+ byTier[tier].tokens += e.tokensEstimated ?? 0;
83
+ byTier[tier].cost += e.costEstimated ?? 0;
84
+ const model = e.model ?? 'default';
85
+ if (!byModel[model])
86
+ byModel[model] = { count: 0, tokens: 0, cost: 0 };
87
+ byModel[model].count += 1;
88
+ byModel[model].tokens += e.tokensEstimated ?? 0;
89
+ byModel[model].cost += e.costEstimated ?? 0;
90
+ }
91
+ const costSaved = estimateTokenCost('default', tokensSaved);
92
+ const savingsRate = (tokensSaved + totalTokens) > 0
93
+ ? tokensSaved / (tokensSaved + totalTokens)
94
+ : 0;
95
+ // Trend: compare first half vs second half savings rate
96
+ const mid = Math.floor(all.length / 2);
97
+ const first = all.slice(0, mid);
98
+ const second = all.slice(mid);
99
+ const halfSavings = (half) => {
100
+ const ts = half.reduce((s, e) => s + (e.tokensSaved ?? 0), 0);
101
+ const tt = half.reduce((s, e) => s + (e.tokensEstimated ?? 0), 0);
102
+ return (ts + tt) > 0 ? ts / (ts + tt) : 0;
103
+ };
104
+ let trend = 'stable';
105
+ if (all.length >= 4) {
106
+ const delta = halfSavings(second) - halfSavings(first);
107
+ if (delta > 0.05)
108
+ trend = 'improving';
109
+ else if (delta < -0.05)
110
+ trend = 'degrading';
111
+ }
112
+ return {
113
+ period: `${days} days`,
114
+ totalCost, totalTokens, totalActions: all.length,
115
+ cacheHits, tokensSaved, costSaved, savingsRate,
116
+ byTier, byModel, trend,
117
+ };
118
+ }
119
+ export function formatCostReport(summary) {
120
+ const { period, totalCost, totalTokens, totalActions, cacheHits, tokensSaved, costSaved, savingsRate, byTier, trend, } = summary;
121
+ const lines = [`COST EFFICIENCY (${period})`];
122
+ const fmtK = (n) => n >= 1000 ? `${Math.round(n / 1000)}K` : String(Math.round(n));
123
+ const fmtD = (n) => `~$${n.toFixed(2)}`;
124
+ lines.push(` Total: ${fmtD(totalCost)} (${fmtK(totalTokens)} tokens, ${totalActions} actions)`);
125
+ if (cacheHits > 0) {
126
+ const pct = Math.round(savingsRate * 100);
127
+ lines.push(` Saved: ${fmtD(costSaved)} (${fmtK(tokensSaved)} tokens from ${cacheHits} cache hits)`);
128
+ lines.push(` Savings rate: ${pct}%`);
129
+ }
130
+ const tierOrder = ['recall', 'quick', 'standard', 'deep', 'ultra'];
131
+ const tierKeys = [...new Set([...tierOrder, ...Object.keys(byTier)])].filter(k => byTier[k]);
132
+ if (tierKeys.length > 0) {
133
+ lines.push('');
134
+ lines.push(' Tier breakdown:');
135
+ for (const tier of tierKeys) {
136
+ const t = byTier[tier];
137
+ const isRecall = tier === 'recall' && (t.cost < 0.001 || t.tokens === 0);
138
+ const costStr = isRecall ? '$0.00 (cache hits!)' : fmtD(t.cost);
139
+ lines.push(` ${tier.padEnd(10)}${String(t.count).padStart(4)} actions ${costStr}`);
140
+ }
141
+ }
142
+ const trendIcon = trend === 'improving' ? '↗' : trend === 'degrading' ? '↘' : '→';
143
+ lines.push('');
144
+ if (trend !== 'stable') {
145
+ lines.push(` Trend: ${trendIcon} ${trend} (savings rate ${trend === 'improving' ? 'up' : 'down'} vs last half)`);
146
+ }
147
+ else {
148
+ lines.push(` Trend: ${trendIcon} stable`);
149
+ }
150
+ return lines.join('\n');
151
+ }
152
+ export function getEfficiencyScore(cwd = process.cwd()) {
153
+ const summary = getCostSummary(cwd, 7);
154
+ if (summary.totalActions === 0)
155
+ return 50;
156
+ const TIER_WEIGHTS = { recall: 0, quick: 1, standard: 2, deep: 4, ultra: 6 };
157
+ const totalTierCost = Object.entries(summary.byTier).reduce((s, [tier, v]) => {
158
+ return s + (TIER_WEIGHTS[tier] ?? 2) * v.count;
159
+ }, 0);
160
+ const maxPossible = summary.totalActions * (TIER_WEIGHTS['ultra'] ?? 6);
161
+ const tierScore = maxPossible > 0 ? 1 - (totalTierCost / maxPossible) : 0.5;
162
+ const cacheScore = summary.savingsRate;
163
+ const trendBonus = summary.trend === 'improving' ? 10 : summary.trend === 'degrading' ? -10 : 0;
164
+ const raw = Math.round(tierScore * 40 +
165
+ cacheScore * 40 +
166
+ 20 +
167
+ trendBonus);
168
+ return Math.max(1, Math.min(100, raw));
169
+ }
170
+ //# sourceMappingURL=cost-tracker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cost-tracker.js","sourceRoot":"","sources":["../../src/cost-tracker.ts"],"names":[],"mappings":"AAAA,oGAAoG;AAEpG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,GAA2B;IAC1C,iBAAiB,EAAY,IAAI;IACjC,mBAAmB,EAAU,KAAK;IAClC,2BAA2B,EAAE,KAAK;IAClC,SAAS,EAAoB,IAAI;IACjC,IAAI,EAAyB,IAAI;IACjC,QAAQ,EAAqB,KAAK;IAClC,aAAa,EAAgB,MAAM;IACnC,SAAS,EAAoB,IAAI;CAClC,CAAC;AAgDF,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,MAAc;IAC7D,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,SAAS,CAAC,CAAC;IAC1D,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAkB,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACvE,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACpC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,MAAM,KAAK,GAAc;YACvB,SAAS,EAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACxC,MAAM,EAAU,MAAM,CAAC,MAAM,IAAY,SAAS;YAClD,KAAK,EAAW,MAAM,CAAC,KAAK,IAAa,SAAS;YAClD,eAAe,EAAE,MAAM,CAAC,eAAe,IAAI,CAAC;YAC5C,aAAa,EAAG,iBAAiB,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS,EAAE,MAAM,CAAC,eAAe,IAAI,CAAC,CAAC;YACzF,IAAI,EAAY,MAAM,CAAC,IAAI,IAAc,UAAU;YACnD,WAAW,EAAK,MAAM,CAAC,WAAW,IAAO,KAAK;YAC9C,WAAW,EAAK,MAAM,CAAC,WAAW,IAAO,CAAC;SAC3C,CAAC;QACF,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/E,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAChC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;IACjD,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YAC/E,IAAI,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAc,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,OAAO,EAAE,CAAC;YAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE,EAAE,OAAe,CAAC;IAC1E,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IACpE,MAAM,GAAG,GAAM,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC,CAAC;IAErE,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO;YACL,MAAM,EAAE,GAAG,IAAI,OAAO;YACtB,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC;YAC7C,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;YAC1D,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ;SACzC,CAAC;IACJ,CAAC;IAED,IAAI,SAAS,GAAG,CAAC,EAAE,WAAW,GAAG,CAAC,EAAE,SAAS,GAAG,CAAC,EAAE,WAAW,GAAG,CAAC,CAAC;IACnE,MAAM,MAAM,GAAmC,EAAE,CAAC;IAClD,MAAM,OAAO,GAAmC,EAAE,CAAC;IAEnD,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,SAAS,IAAO,CAAC,CAAC,aAAa,IAAM,CAAC,CAAC;QACvC,WAAW,IAAK,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAAC,SAAS,EAAE,CAAC;YAAC,WAAW,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC;QAAC,CAAC;QAEtE,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,UAAU,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACnE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,IAAK,CAAC,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,IAAM,CAAC,CAAC,aAAa,IAAM,CAAC,CAAC;QAE9C,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,SAAS,CAAC;QACnC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,IAAK,CAAC,CAAC;QAC3B,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC;QAChD,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,IAAM,CAAC,CAAC,aAAa,IAAM,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,SAAS,GAAM,iBAAiB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC/D,MAAM,WAAW,GAAI,CAAC,WAAW,GAAG,WAAW,CAAC,GAAG,CAAC;QAClD,CAAC,CAAC,WAAW,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC;QAC3C,CAAC,CAAC,CAAC,CAAC;IAEN,wDAAwD;IACxD,MAAM,GAAG,GAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,WAAW,GAAG,CAAC,IAAiB,EAAU,EAAE;QAChD,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9D,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC;IACF,IAAI,KAAK,GAAyC,QAAQ,CAAC;IAC3D,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACpB,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QACvD,IAAI,KAAK,GAAG,IAAI;YAAQ,KAAK,GAAG,WAAW,CAAC;aACvC,IAAI,KAAK,GAAG,CAAC,IAAI;YAAE,KAAK,GAAG,WAAW,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,MAAM,EAAE,GAAG,IAAI,OAAO;QACtB,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM;QAChD,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW;QAC9C,MAAM,EAAE,OAAO,EAAE,KAAK;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAoB;IACnD,MAAM,EACJ,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAC5C,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAC9C,MAAM,EAAE,KAAK,GACd,GAAG,OAAO,CAAC;IAEZ,MAAM,KAAK,GAAG,CAAC,oBAAoB,MAAM,GAAG,CAAC,CAAC;IAE9C,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnG,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAExD,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,WAAW,CAAC,YAAY,YAAY,WAAW,CAAC,CAAC;IAEjG,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,WAAW,CAAC,gBAAgB,SAAS,cAAc,CAAC,CAAC;QACrG,KAAK,CAAC,IAAI,CAAC,mBAAmB,GAAG,GAAG,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAI,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9F,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YACvB,MAAM,QAAQ,GAAG,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;YACzE,MAAM,OAAO,GAAI,QAAQ,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAClE,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;QACzF,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAClF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,YAAY,SAAS,IAAI,KAAK,kBAAkB,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,gBAAgB,CAAC,CAAC;IACpH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,YAAY,SAAS,SAAS,CAAC,CAAC;IAC7C,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC5D,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACvC,IAAI,OAAO,CAAC,YAAY,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE1C,MAAM,YAAY,GAA2B,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACrG,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;QAC3E,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;IACjD,CAAC,EAAE,CAAC,CAAC,CAAC;IACN,MAAM,WAAW,GAAG,OAAO,CAAC,YAAY,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACxE,MAAM,SAAS,GAAK,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAE9E,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC;IACvC,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhG,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,SAAS,GAAK,EAAE;QAChB,UAAU,GAAI,EAAE;QAChB,EAAE;QACF,UAAU,CACX,CAAC;IAEF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * debrief.ts — Agent debrief parsing, integration, and wave summarization.
3
+ */
4
+ type DebriefStatus = 'success' | 'partial' | 'blocked' | 'pivoted';
5
+ type ScopeChange = 'same' | 'larger' | 'smaller' | 'different';
6
+ export interface DebriefArtifacts {
7
+ filesChanged: string[];
8
+ filesRead: string[];
9
+ testsRun: number;
10
+ }
11
+ export interface Debrief {
12
+ status: DebriefStatus;
13
+ findings: string[];
14
+ blockers: string[];
15
+ scopeChange: ScopeChange;
16
+ confidence: number;
17
+ recommendations: string[];
18
+ artifacts: DebriefArtifacts;
19
+ pivotReason: string | undefined;
20
+ unexpectedFindings: string[];
21
+ }
22
+ interface LedgerEntry {
23
+ topic: string;
24
+ confidence: number;
25
+ resolved: boolean;
26
+ isBlocker?: boolean;
27
+ }
28
+ interface SituationModel {
29
+ ledger?: LedgerEntry[];
30
+ material?: {
31
+ scopeTrend?: ScopeChange;
32
+ touchedFiles?: string[];
33
+ };
34
+ nextActions?: string[];
35
+ noticings?: string[];
36
+ confidence?: number;
37
+ [key: string]: unknown;
38
+ }
39
+ export interface WaveOutcome {
40
+ overallStatus: DebriefStatus | 'blocked';
41
+ aggregateConfidence: number;
42
+ allFindings: string[];
43
+ allBlockers: string[];
44
+ scopeDelta: ScopeChange;
45
+ nextActions: string[];
46
+ }
47
+ export declare function parseDebrief(rawOutput: unknown): Debrief;
48
+ export declare function generateDebriefInstruction(tier: string, contract?: {
49
+ scope?: string;
50
+ }): string;
51
+ export declare function integrateDebrief(currentSituation: SituationModel, debrief: Debrief): SituationModel;
52
+ export declare function summarizeWaveOutcome(debriefs: Debrief[] | null | undefined): WaveOutcome;
53
+ export {};