dual-brain 0.2.29 → 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.
- package/.dual-brain/docs/claude-code-extension-points.md +32 -0
- package/.dual-brain/docs/data-tools-capabilities.md +181 -0
- package/.dual-brain/docs/ecosystem-tools.md +91 -0
- package/.dual-brain/docs/panel-handoff.md +124 -0
- package/.dual-brain/docs/ruflo-analysis.md +48 -0
- package/bin/dual-brain.mjs +122 -51
- package/dist/mcp-server/index.d.ts +27 -0
- package/dist/mcp-server/index.js +359 -0
- package/dist/mcp-server/index.js.map +1 -0
- package/dist/src/agent-protocol.d.ts +163 -0
- package/dist/src/agent-protocol.js +368 -0
- package/dist/src/agent-protocol.js.map +1 -0
- package/dist/src/agents/registry.d.ts +52 -0
- package/dist/src/agents/registry.js +393 -0
- package/dist/src/agents/registry.js.map +1 -0
- package/dist/src/awareness.d.ts +93 -0
- package/dist/src/awareness.js +406 -0
- package/dist/src/awareness.js.map +1 -0
- package/dist/src/brief.d.ts +48 -0
- package/dist/src/brief.js +179 -0
- package/dist/src/brief.js.map +1 -0
- package/dist/src/calibration.d.ts +32 -0
- package/dist/src/calibration.js +133 -0
- package/dist/src/calibration.js.map +1 -0
- package/dist/src/checkpoint.d.ts +33 -0
- package/dist/src/checkpoint.js +99 -0
- package/dist/src/checkpoint.js.map +1 -0
- package/dist/src/ci-triage.d.ts +33 -0
- package/dist/src/ci-triage.js +193 -0
- package/dist/src/ci-triage.js.map +1 -0
- package/dist/src/cognitive-loop.d.ts +56 -0
- package/dist/src/cognitive-loop.js +495 -0
- package/dist/src/cognitive-loop.js.map +1 -0
- package/dist/src/collaboration.d.ts +147 -0
- package/dist/src/collaboration.js +438 -0
- package/dist/src/collaboration.js.map +1 -0
- package/dist/src/context-intel.d.ts +47 -0
- package/dist/src/context-intel.js +156 -0
- package/dist/src/context-intel.js.map +1 -0
- package/dist/src/context.d.ts +53 -0
- package/dist/src/context.js +332 -0
- package/dist/src/context.js.map +1 -0
- package/dist/src/continuity.d.ts +89 -0
- package/dist/src/continuity.js +230 -0
- package/dist/src/continuity.js.map +1 -0
- package/dist/src/cost-tracker.d.ts +47 -0
- package/dist/src/cost-tracker.js +170 -0
- package/dist/src/cost-tracker.js.map +1 -0
- package/dist/src/debrief.d.ts +53 -0
- package/dist/src/debrief.js +222 -0
- package/dist/src/debrief.js.map +1 -0
- package/dist/src/decide.d.ts +96 -0
- package/dist/src/decide.js +744 -0
- package/dist/src/decide.js.map +1 -0
- package/dist/src/decompose.d.ts +39 -0
- package/dist/src/decompose.js +218 -0
- package/dist/src/decompose.js.map +1 -0
- package/dist/src/detect.d.ts +91 -0
- package/dist/src/detect.js +544 -0
- package/dist/src/detect.js.map +1 -0
- package/dist/src/dispatch.d.ts +154 -0
- package/dist/src/dispatch.js +1306 -0
- package/dist/src/dispatch.js.map +1 -0
- package/dist/src/doctor.d.ts +421 -0
- package/dist/src/doctor.js +1689 -0
- package/dist/src/doctor.js.map +1 -0
- package/dist/src/engine.d.ts +70 -0
- package/dist/src/engine.js +155 -0
- package/dist/src/engine.js.map +1 -0
- package/dist/src/envelope.d.ts +36 -0
- package/dist/src/envelope.js +80 -0
- package/dist/src/envelope.js.map +1 -0
- package/dist/src/failure-memory.d.ts +55 -0
- package/dist/src/failure-memory.js +175 -0
- package/dist/src/failure-memory.js.map +1 -0
- package/dist/src/fx.d.ts +87 -0
- package/dist/src/fx.js +272 -0
- package/dist/src/fx.js.map +1 -0
- package/dist/src/governance.d.ts +93 -0
- package/dist/src/governance.js +261 -0
- package/dist/src/governance.js.map +1 -0
- package/dist/src/handoff.d.ts +11 -0
- package/dist/src/handoff.js +90 -0
- package/dist/src/handoff.js.map +1 -0
- package/dist/src/head-protocol.d.ts +76 -0
- package/dist/src/head-protocol.js +109 -0
- package/dist/src/head-protocol.js.map +1 -0
- package/dist/src/head.d.ts +222 -0
- package/dist/src/head.js +765 -0
- package/dist/src/head.js.map +1 -0
- package/dist/src/health.d.ts +132 -0
- package/dist/src/health.js +435 -0
- package/dist/src/health.js.map +1 -0
- package/dist/src/inbox.d.ts +70 -0
- package/dist/src/inbox.js +218 -0
- package/dist/src/inbox.js.map +1 -0
- package/dist/src/index.d.ts +33 -0
- package/dist/src/index.js +38 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/install-hooks.d.ts +13 -0
- package/dist/src/install-hooks.js +88 -0
- package/dist/src/install-hooks.js.map +1 -0
- package/dist/src/integrity.d.ts +59 -0
- package/dist/src/integrity.js +206 -0
- package/dist/src/integrity.js.map +1 -0
- package/dist/src/intelligence.d.ts +104 -0
- package/dist/src/intelligence.js +391 -0
- package/dist/src/intelligence.js.map +1 -0
- package/dist/src/ledger.d.ts +54 -0
- package/dist/src/ledger.js +179 -0
- package/dist/src/ledger.js.map +1 -0
- package/dist/src/living-docs.d.ts +14 -0
- package/dist/src/living-docs.js +197 -0
- package/dist/src/living-docs.js.map +1 -0
- package/dist/src/memory-tiers.d.ts +37 -0
- package/dist/src/memory-tiers.js +160 -0
- package/dist/src/memory-tiers.js.map +1 -0
- package/dist/src/model-profiles.d.ts +65 -0
- package/dist/src/model-profiles.js +568 -0
- package/dist/src/model-profiles.js.map +1 -0
- package/dist/src/models.d.ts +58 -0
- package/dist/src/models.js +327 -0
- package/dist/src/models.js.map +1 -0
- package/dist/src/narrative.d.ts +54 -0
- package/dist/src/narrative.js +163 -0
- package/dist/src/narrative.js.map +1 -0
- package/dist/src/nextstep.d.ts +16 -0
- package/dist/src/nextstep.js +103 -0
- package/dist/src/nextstep.js.map +1 -0
- package/dist/src/observer.d.ts +18 -0
- package/dist/src/observer.js +251 -0
- package/dist/src/observer.js.map +1 -0
- package/dist/src/outcome.d.ts +110 -0
- package/dist/src/outcome.js +377 -0
- package/dist/src/outcome.js.map +1 -0
- package/dist/src/pipeline.d.ts +167 -0
- package/dist/src/pipeline.js +1503 -0
- package/dist/src/pipeline.js.map +1 -0
- package/dist/src/playbook.d.ts +59 -0
- package/dist/src/playbook.js +238 -0
- package/dist/src/playbook.js.map +1 -0
- package/dist/src/pr-agent.d.ts +97 -0
- package/dist/src/pr-agent.js +195 -0
- package/dist/src/pr-agent.js.map +1 -0
- package/dist/src/predictive.d.ts +57 -0
- package/dist/src/predictive.js +230 -0
- package/dist/src/predictive.js.map +1 -0
- package/dist/src/profile.d.ts +294 -0
- package/dist/src/profile.js +1347 -0
- package/dist/src/profile.js.map +1 -0
- package/dist/src/prompt-audit.d.ts +22 -0
- package/dist/src/prompt-audit.js +194 -0
- package/dist/src/prompt-audit.js.map +1 -0
- package/dist/src/prompt-intel.d.ts +12 -0
- package/dist/src/prompt-intel.js +321 -0
- package/dist/src/prompt-intel.js.map +1 -0
- package/dist/src/provider-context.d.ts +121 -0
- package/dist/src/provider-context.js +222 -0
- package/dist/src/provider-context.js.map +1 -0
- package/dist/src/provider-manager.d.ts +92 -0
- package/dist/src/provider-manager.js +428 -0
- package/dist/src/provider-manager.js.map +1 -0
- package/dist/src/receipt.d.ts +87 -0
- package/dist/src/receipt.js +326 -0
- package/dist/src/receipt.js.map +1 -0
- package/dist/src/recommendations.d.ts +13 -0
- package/dist/src/recommendations.js +291 -0
- package/dist/src/recommendations.js.map +1 -0
- package/dist/src/redact.d.ts +15 -0
- package/dist/src/redact.js +129 -0
- package/dist/src/redact.js.map +1 -0
- package/dist/src/replit.d.ts +397 -0
- package/dist/src/replit.js +1160 -0
- package/dist/src/replit.js.map +1 -0
- package/dist/src/repo.d.ts +149 -0
- package/dist/src/repo.js +416 -0
- package/dist/src/repo.js.map +1 -0
- package/dist/src/revert.d.ts +30 -0
- package/dist/src/revert.js +166 -0
- package/dist/src/revert.js.map +1 -0
- package/dist/src/room.d.ts +102 -0
- package/dist/src/room.js +212 -0
- package/dist/src/room.js.map +1 -0
- package/dist/src/routing-advisor.d.ts +57 -0
- package/dist/src/routing-advisor.js +221 -0
- package/dist/src/routing-advisor.js.map +1 -0
- package/dist/src/self-correct.d.ts +40 -0
- package/dist/src/self-correct.js +137 -0
- package/dist/src/self-correct.js.map +1 -0
- package/dist/src/session-lock.d.ts +35 -0
- package/dist/src/session-lock.js +134 -0
- package/dist/src/session-lock.js.map +1 -0
- package/dist/src/session.d.ts +267 -0
- package/dist/src/session.js +1660 -0
- package/dist/src/session.js.map +1 -0
- package/dist/src/settings-tui.d.ts +5 -0
- package/dist/src/settings-tui.js +422 -0
- package/dist/src/settings-tui.js.map +1 -0
- package/dist/src/setup-flow.d.ts +63 -0
- package/dist/src/setup-flow.js +233 -0
- package/dist/src/setup-flow.js.map +1 -0
- package/dist/src/signal.d.ts +19 -0
- package/dist/src/signal.js +122 -0
- package/dist/src/signal.js.map +1 -0
- package/dist/src/simmer.d.ts +85 -0
- package/dist/src/simmer.js +224 -0
- package/dist/src/simmer.js.map +1 -0
- package/dist/src/state-export.d.ts +129 -0
- package/dist/src/state-export.js +233 -0
- package/dist/src/state-export.js.map +1 -0
- package/dist/src/strategy.d.ts +54 -0
- package/dist/src/strategy.js +95 -0
- package/dist/src/strategy.js.map +1 -0
- package/dist/src/subscription.d.ts +40 -0
- package/dist/src/subscription.js +189 -0
- package/dist/src/subscription.js.map +1 -0
- package/dist/src/templates.d.ts +208 -0
- package/dist/src/templates.js +238 -0
- package/dist/src/templates.js.map +1 -0
- package/dist/src/test.d.ts +9 -0
- package/dist/src/test.js +1173 -0
- package/dist/src/test.js.map +1 -0
- package/dist/src/think-engine.d.ts +67 -0
- package/dist/src/think-engine.js +412 -0
- package/dist/src/think-engine.js.map +1 -0
- package/dist/src/tui.d.ts +71 -0
- package/dist/src/tui.js +242 -0
- package/dist/src/tui.js.map +1 -0
- package/dist/src/types.d.ts +177 -0
- package/dist/src/types.js +6 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/update-check.d.ts +7 -0
- package/dist/src/update-check.js +36 -0
- package/dist/src/update-check.js.map +1 -0
- package/dist/src/wave-planner.d.ts +30 -0
- package/dist/src/wave-planner.js +281 -0
- package/dist/src/wave-planner.js.map +1 -0
- package/hooks/head-guard.sh +41 -0
- package/hooks/task-classifier.mjs +328 -0
- package/hooks/vibe-router.mjs +387 -0
- package/package.json +29 -153
- package/src/agents/registry.mjs +0 -405
- package/src/awareness.mjs +0 -425
- package/src/brief.mjs +0 -266
- package/src/calibration.mjs +0 -148
- package/src/checkpoint.mjs +0 -109
- package/src/ci-triage.mjs +0 -191
- package/src/cognitive-loop.mjs +0 -562
- package/src/collaboration.mjs +0 -545
- package/src/context-intel.mjs +0 -158
- package/src/context.mjs +0 -389
- package/src/continuity.mjs +0 -298
- package/src/cost-tracker.mjs +0 -184
- package/src/debrief.mjs +0 -228
- package/src/decide.mjs +0 -1099
- package/src/decompose.mjs +0 -331
- package/src/detect.mjs +0 -702
- package/src/dispatch.mjs +0 -1447
- package/src/doctor.mjs +0 -1607
- package/src/envelope.mjs +0 -139
- package/src/failure-memory.mjs +0 -178
- package/src/fx.mjs +0 -276
- package/src/governance.mjs +0 -279
- package/src/handoff.mjs +0 -85
- package/src/head-protocol.mjs +0 -128
- package/src/head.mjs +0 -952
- package/src/health.mjs +0 -528
- package/src/inbox.mjs +0 -195
- package/src/index.mjs +0 -44
- package/src/install-hooks.mjs +0 -100
- package/src/integrity.mjs +0 -245
- package/src/intelligence.mjs +0 -447
- package/src/ledger.mjs +0 -196
- package/src/living-docs.mjs +0 -210
- package/src/memory-tiers.mjs +0 -193
- package/src/models.mjs +0 -363
- package/src/narrative.mjs +0 -169
- package/src/nextstep.mjs +0 -100
- package/src/observer.mjs +0 -241
- package/src/outcome.mjs +0 -386
- package/src/pipeline.mjs +0 -1689
- package/src/playbook.mjs +0 -257
- package/src/pr-agent.mjs +0 -214
- package/src/predictive.mjs +0 -250
- package/src/profile.mjs +0 -1411
- package/src/prompt-audit.mjs +0 -231
- package/src/prompt-intel.mjs +0 -325
- package/src/provider-context.mjs +0 -257
- package/src/receipt.mjs +0 -344
- package/src/recommendations.mjs +0 -291
- package/src/redact.mjs +0 -192
- package/src/replit.mjs +0 -1210
- package/src/repo.mjs +0 -445
- package/src/revert.mjs +0 -149
- package/src/routing-advisor.mjs +0 -200
- package/src/self-correct.mjs +0 -146
- package/src/session-lock.mjs +0 -160
- package/src/session.mjs +0 -1655
- package/src/settings-tui.mjs +0 -373
- package/src/setup-flow.mjs +0 -215
- package/src/signal.mjs +0 -114
- package/src/simmer.mjs +0 -241
- package/src/strategy.mjs +0 -235
- package/src/subscription.mjs +0 -212
- package/src/templates.mjs +0 -260
- package/src/think-engine.mjs +0 -428
- package/src/tui.mjs +0 -276
- package/src/update-check.mjs +0 -35
- package/src/wave-planner.mjs +0 -294
package/src/update-check.mjs
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { execSync } from 'child_process';
|
|
2
|
-
import { readFileSync } from 'fs';
|
|
3
|
-
import { join, dirname } from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
|
|
6
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
|
|
8
|
-
export function getLocalVersion() {
|
|
9
|
-
try {
|
|
10
|
-
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));
|
|
11
|
-
return pkg.version;
|
|
12
|
-
} catch { return null; }
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function getLatestVersion() {
|
|
16
|
-
try {
|
|
17
|
-
const result = execSync('npm view dual-brain version 2>/dev/null', { encoding: 'utf8', timeout: 5000 });
|
|
18
|
-
return result.trim();
|
|
19
|
-
} catch { return null; }
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function checkForUpdate() {
|
|
23
|
-
const local = getLocalVersion();
|
|
24
|
-
const latest = getLatestVersion();
|
|
25
|
-
if (!local || !latest) return { updateAvailable: false, local, latest };
|
|
26
|
-
|
|
27
|
-
const localParts = local.split('.').map(Number);
|
|
28
|
-
const latestParts = latest.split('.').map(Number);
|
|
29
|
-
|
|
30
|
-
const updateAvailable = latestParts[0] > localParts[0]
|
|
31
|
-
|| (latestParts[0] === localParts[0] && latestParts[1] > localParts[1])
|
|
32
|
-
|| (latestParts[0] === localParts[0] && latestParts[1] === localParts[1] && latestParts[2] > localParts[2]);
|
|
33
|
-
|
|
34
|
-
return { updateAvailable, local, latest };
|
|
35
|
-
}
|
package/src/wave-planner.mjs
DELETED
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
// Wave Planner — Layer 2 cognitive loop
|
|
2
|
-
// Takes HEAD's deliberation output and produces structured wave-based execution plans.
|
|
3
|
-
|
|
4
|
-
const TIER_COST = {
|
|
5
|
-
search: { tokens: 5000, time: '~10s' },
|
|
6
|
-
execute: { tokens: 20000, time: '~45s' },
|
|
7
|
-
think: { tokens: 15000, time: '~30s' },
|
|
8
|
-
review: { tokens: 10000, time: '~20s' },
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
let waveCounter = 0;
|
|
12
|
-
function nextWaveId() { return `w-${Date.now().toString(36)}-${++waveCounter}`; }
|
|
13
|
-
|
|
14
|
-
/** Plan waves from HEAD's deliberation output. */
|
|
15
|
-
export function planWaves(deliberation, context = {}) {
|
|
16
|
-
const { situation = {}, uncertainties = [], result = {} } = deliberation;
|
|
17
|
-
const { files = [], priorDebriefs = [], diagnosticPatterns = [] } = context;
|
|
18
|
-
const depth = result.depth || 'light';
|
|
19
|
-
|
|
20
|
-
const blockers = uncertainties.filter(u => u.confidence < 0.3);
|
|
21
|
-
const hasFragile = situation.risk === 'high' || situation.risk === 'critical';
|
|
22
|
-
const largeScope = situation.scope === 'large';
|
|
23
|
-
const priorBlockers = priorDebriefs.filter(d => d.blockers?.length);
|
|
24
|
-
|
|
25
|
-
const waves = [];
|
|
26
|
-
const contingencies = [];
|
|
27
|
-
|
|
28
|
-
// Determine wave structure based on depth
|
|
29
|
-
if (depth === 'reflexive' || depth === 'light') {
|
|
30
|
-
waves.push(makeSingleWave(result, situation, files));
|
|
31
|
-
} else if (depth === 'full') {
|
|
32
|
-
if (blockers.length) {
|
|
33
|
-
waves.push(makeReconWave(blockers, situation, files, priorBlockers));
|
|
34
|
-
}
|
|
35
|
-
waves.push(makeImplementWave(result, situation, files, largeScope, waves));
|
|
36
|
-
if (hasFragile) {
|
|
37
|
-
waves.push(makeVerifyWave(situation, files, waves));
|
|
38
|
-
}
|
|
39
|
-
} else if (depth === 'deep') {
|
|
40
|
-
// Always start with recon for deep
|
|
41
|
-
waves.push(makeReconWave(
|
|
42
|
-
blockers.length ? blockers : uncertainties,
|
|
43
|
-
situation, files, priorBlockers
|
|
44
|
-
));
|
|
45
|
-
// Plan wave
|
|
46
|
-
waves.push({
|
|
47
|
-
id: nextWaveId(),
|
|
48
|
-
phase: 'synthesize',
|
|
49
|
-
agents: [{
|
|
50
|
-
tier: 'think',
|
|
51
|
-
objective: `Synthesize recon findings into implementation plan for: ${result.action || situation.taskShape || 'task'}`,
|
|
52
|
-
scope: files.slice(0, 10),
|
|
53
|
-
}],
|
|
54
|
-
dependsOn: [waves[0].id],
|
|
55
|
-
gateCondition: 'recon wave completed without escalation',
|
|
56
|
-
parallel: false,
|
|
57
|
-
});
|
|
58
|
-
// Implement wave
|
|
59
|
-
waves.push(makeImplementWave(result, situation, files, largeScope, waves));
|
|
60
|
-
// Verify wave
|
|
61
|
-
waves.push(makeVerifyWave(situation, files, waves));
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Force recon-first if blockers exist and first wave isn't recon
|
|
65
|
-
if (blockers.length && waves.length && waves[0].phase !== 'recon') {
|
|
66
|
-
const reconWave = makeReconWave(blockers, situation, files, priorBlockers);
|
|
67
|
-
waves.forEach(w => { if (!w.dependsOn.length) w.dependsOn.push(reconWave.id); });
|
|
68
|
-
waves.unshift(reconWave);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Build contingencies
|
|
72
|
-
if (largeScope) {
|
|
73
|
-
contingencies.push({
|
|
74
|
-
trigger: 'if wave 1 finds scope is larger than expected',
|
|
75
|
-
response: 'add-wave',
|
|
76
|
-
details: 'Split implementation into additional parallel waves by file group',
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
if (hasFragile) {
|
|
80
|
-
contingencies.push({
|
|
81
|
-
trigger: 'if implementation wave introduces regressions',
|
|
82
|
-
response: 'retry-different',
|
|
83
|
-
details: 'Re-approach with smaller incremental changes',
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
if (blockers.length) {
|
|
87
|
-
contingencies.push({
|
|
88
|
-
trigger: 'if recon cannot resolve uncertainty',
|
|
89
|
-
response: 'escalate',
|
|
90
|
-
details: 'Ask user for clarification before proceeding',
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const agentCount = waves.reduce((n, w) => n + w.agents.length, 0);
|
|
95
|
-
const dominantTier = agentCount <= 1 ? (waves[0]?.agents[0]?.tier || 'search')
|
|
96
|
-
: waves.flatMap(w => w.agents.map(a => a.tier))
|
|
97
|
-
.sort((a, b) => TIER_COST[b].tokens - TIER_COST[a].tokens)[0];
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
waves,
|
|
101
|
-
rationale: buildRationale(depth, blockers, hasFragile, largeScope),
|
|
102
|
-
estimatedCost: { waves: waves.length, agents: agentCount, tier: dominantTier },
|
|
103
|
-
contingencies,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/** Decide if the remaining plan is still valid after a wave debrief. */
|
|
108
|
-
export function shouldReplan(currentPlan, newDebrief) {
|
|
109
|
-
if (!newDebrief) return false;
|
|
110
|
-
if (newDebrief.scopeChange === 'larger' || newDebrief.scopeChange === 'different') return true;
|
|
111
|
-
if (newDebrief.pivotReason) return true;
|
|
112
|
-
if (newDebrief.confidence !== undefined && newDebrief.confidence < 0.4) return true;
|
|
113
|
-
|
|
114
|
-
// Check if blockers intersect with upcoming wave objectives
|
|
115
|
-
if (newDebrief.blockers?.length) {
|
|
116
|
-
const remaining = currentPlan.waves.filter(w => !w.completed);
|
|
117
|
-
for (const w of remaining) {
|
|
118
|
-
for (const agent of w.agents) {
|
|
119
|
-
for (const blocker of newDebrief.blockers) {
|
|
120
|
-
const bLower = (typeof blocker === 'string' ? blocker : blocker.description || '').toLowerCase();
|
|
121
|
-
if (bLower && agent.objective.toLowerCase().includes(bLower.split(' ')[0])) return true;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return false;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/** Produce a new plan incorporating what was learned. Preserves completed waves. */
|
|
130
|
-
export function replan(currentPlan, waveSummary, originalDeliberation) {
|
|
131
|
-
const completed = currentPlan.waves.filter(w => w.completed);
|
|
132
|
-
const context = {
|
|
133
|
-
files: waveSummary.filesDiscovered || [],
|
|
134
|
-
priorDebriefs: [waveSummary],
|
|
135
|
-
diagnosticPatterns: waveSummary.patterns || [],
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
// Merge learning into deliberation
|
|
139
|
-
const updated = { ...originalDeliberation };
|
|
140
|
-
if (waveSummary.scopeChange === 'larger') {
|
|
141
|
-
updated.situation = { ...updated.situation, scope: 'large' };
|
|
142
|
-
}
|
|
143
|
-
if (waveSummary.confidence !== undefined) {
|
|
144
|
-
updated.result = { ...updated.result, confidence: waveSummary.confidence };
|
|
145
|
-
}
|
|
146
|
-
if (waveSummary.newUncertainties) {
|
|
147
|
-
updated.uncertainties = [
|
|
148
|
-
...(updated.uncertainties || []),
|
|
149
|
-
...waveSummary.newUncertainties,
|
|
150
|
-
];
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const newPlan = planWaves(updated, context);
|
|
154
|
-
|
|
155
|
-
// Preserve completed waves at the front
|
|
156
|
-
newPlan.waves = [...completed, ...newPlan.waves];
|
|
157
|
-
newPlan.rationale = `Replanned after wave debrief: ${waveSummary.pivotReason || waveSummary.scopeChange || 'confidence drop'}. ${newPlan.rationale}`;
|
|
158
|
-
return newPlan;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/** Rough cost estimate for a single wave. */
|
|
162
|
-
export function estimateWaveCost(wave) {
|
|
163
|
-
let tokens = 0;
|
|
164
|
-
for (const agent of wave.agents) {
|
|
165
|
-
tokens += TIER_COST[agent.tier]?.tokens || 10000;
|
|
166
|
-
}
|
|
167
|
-
// Time: parallel agents overlap, sequential add up
|
|
168
|
-
const times = wave.agents.map(a => parseInt(TIER_COST[a.tier]?.time) || 20);
|
|
169
|
-
const seconds = wave.parallel ? Math.max(...times) : times.reduce((s, t) => s + t, 0);
|
|
170
|
-
return { tokens, time: `~${seconds}s` };
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function makeSingleWave(result, situation, files) {
|
|
174
|
-
const tier = mapActionToTier(result.action);
|
|
175
|
-
return {
|
|
176
|
-
id: nextWaveId(),
|
|
177
|
-
phase: tier === 'search' ? 'recon' : 'implement',
|
|
178
|
-
agents: [{
|
|
179
|
-
tier,
|
|
180
|
-
objective: situation.explicitAsk || situation.raw || (typeof result.action === 'string' ? result.action : result.action?.mode) || 'execute task',
|
|
181
|
-
scope: files.slice(0, 5),
|
|
182
|
-
}],
|
|
183
|
-
dependsOn: [],
|
|
184
|
-
parallel: false,
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function makeReconWave(uncertainties, situation, files, priorBlockers) {
|
|
189
|
-
const avoidApproaches = priorBlockers.flatMap(d =>
|
|
190
|
-
d.blockers?.map(b => typeof b === 'string' ? b : b.approach) || []
|
|
191
|
-
);
|
|
192
|
-
|
|
193
|
-
const agents = uncertainties.slice(0, 3).map(u => {
|
|
194
|
-
const spec = {
|
|
195
|
-
tier: 'search',
|
|
196
|
-
objective: `Resolve uncertainty: ${u.claim || u.description || 'unknown'}`,
|
|
197
|
-
scope: files.slice(0, 5),
|
|
198
|
-
};
|
|
199
|
-
if (u.wouldChangeIf) {
|
|
200
|
-
spec.conditionalPivot = { if: u.wouldChangeIf, then: 'report finding and stop' };
|
|
201
|
-
}
|
|
202
|
-
return spec;
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
// If no uncertainties provided, add a general recon agent
|
|
206
|
-
if (!agents.length) {
|
|
207
|
-
agents.push({
|
|
208
|
-
tier: 'search',
|
|
209
|
-
objective: `Explore scope and structure for: ${situation.taskShape || 'task'}`,
|
|
210
|
-
scope: files.slice(0, 5),
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Annotate agents to avoid prior failed approaches
|
|
215
|
-
if (avoidApproaches.length) {
|
|
216
|
-
for (const agent of agents) {
|
|
217
|
-
agent.objective += ` (avoid: ${avoidApproaches.join(', ')})`;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return {
|
|
222
|
-
id: nextWaveId(),
|
|
223
|
-
phase: 'recon',
|
|
224
|
-
agents,
|
|
225
|
-
dependsOn: [],
|
|
226
|
-
gateCondition: undefined,
|
|
227
|
-
parallel: agents.length > 1,
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function makeImplementWave(result, situation, files, largeScope, existingWaves) {
|
|
232
|
-
const dependsOn = existingWaves.length ? [existingWaves[existingWaves.length - 1].id] : [];
|
|
233
|
-
const agents = [];
|
|
234
|
-
|
|
235
|
-
if (largeScope && files.length > 3) {
|
|
236
|
-
// Split into parallel agents by file group
|
|
237
|
-
const groupSize = Math.ceil(files.length / 3);
|
|
238
|
-
for (let i = 0; i < files.length; i += groupSize) {
|
|
239
|
-
agents.push({
|
|
240
|
-
tier: 'execute',
|
|
241
|
-
objective: result.action || `Implement changes in file group ${Math.floor(i / groupSize) + 1}`,
|
|
242
|
-
scope: files.slice(i, i + groupSize),
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
} else {
|
|
246
|
-
agents.push({
|
|
247
|
-
tier: 'execute',
|
|
248
|
-
objective: result.action || situation.taskShape || 'implement changes',
|
|
249
|
-
scope: files.slice(0, 10),
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return {
|
|
254
|
-
id: nextWaveId(),
|
|
255
|
-
phase: 'implement',
|
|
256
|
-
agents,
|
|
257
|
-
dependsOn,
|
|
258
|
-
gateCondition: existingWaves.length ? 'prior wave completed successfully' : undefined,
|
|
259
|
-
parallel: agents.length > 1,
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function makeVerifyWave(situation, files, existingWaves) {
|
|
264
|
-
const dependsOn = existingWaves.length ? [existingWaves[existingWaves.length - 1].id] : [];
|
|
265
|
-
return {
|
|
266
|
-
id: nextWaveId(),
|
|
267
|
-
phase: 'verify',
|
|
268
|
-
agents: [{
|
|
269
|
-
tier: 'review',
|
|
270
|
-
objective: `Verify changes are correct and safe${situation.risk === 'critical' ? ' — critical risk area' : ''}`,
|
|
271
|
-
scope: files.slice(0, 10),
|
|
272
|
-
}],
|
|
273
|
-
dependsOn,
|
|
274
|
-
gateCondition: 'implementation wave completed',
|
|
275
|
-
parallel: false,
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function mapActionToTier(action) {
|
|
280
|
-
if (!action) return 'execute';
|
|
281
|
-
const a = (typeof action === 'string' ? action : `${action.type || ''} ${action.mode || ''}`).toLowerCase();
|
|
282
|
-
if (a.includes('search') || a.includes('find') || a.includes('look') || a.includes('explore')) return 'search';
|
|
283
|
-
if (a.includes('review') || a.includes('check') || a.includes('verify')) return 'review';
|
|
284
|
-
if (a.includes('think') || a.includes('plan') || a.includes('design') || a.includes('architect')) return 'think';
|
|
285
|
-
return 'execute';
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function buildRationale(depth, blockers, hasFragile, largeScope) {
|
|
289
|
-
const parts = [`Depth: ${depth}.`];
|
|
290
|
-
if (blockers.length) parts.push(`${blockers.length} blocker(s) require recon first.`);
|
|
291
|
-
if (hasFragile) parts.push('High-risk area — verification wave added.');
|
|
292
|
-
if (largeScope) parts.push('Large scope — parallel agents where possible.');
|
|
293
|
-
return parts.join(' ');
|
|
294
|
-
}
|