@obsidicore/cascade-engine 0.2.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/LICENSE +21 -0
- package/dist/cascade/checkpoints.d.ts +55 -0
- package/dist/cascade/checkpoints.js +123 -0
- package/dist/cascade/checkpoints.js.map +1 -0
- package/dist/cascade/engine.d.ts +72 -0
- package/dist/cascade/engine.js +170 -0
- package/dist/cascade/engine.js.map +1 -0
- package/dist/cascade/gates.d.ts +46 -0
- package/dist/cascade/gates.js +199 -0
- package/dist/cascade/gates.js.map +1 -0
- package/dist/cascade/research.d.ts +50 -0
- package/dist/cascade/research.js +127 -0
- package/dist/cascade/research.js.map +1 -0
- package/dist/cli.d.ts +19 -0
- package/dist/cli.js +165 -0
- package/dist/cli.js.map +1 -0
- package/dist/control/kalman.d.ts +53 -0
- package/dist/control/kalman.js +83 -0
- package/dist/control/kalman.js.map +1 -0
- package/dist/control/pid.d.ts +57 -0
- package/dist/control/pid.js +95 -0
- package/dist/control/pid.js.map +1 -0
- package/dist/control/stability.d.ts +42 -0
- package/dist/control/stability.js +117 -0
- package/dist/control/stability.js.map +1 -0
- package/dist/db/index.d.ts +26 -0
- package/dist/db/index.js +116 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/schema.sql +282 -0
- package/dist/graph/amem.d.ts +80 -0
- package/dist/graph/amem.js +190 -0
- package/dist/graph/amem.js.map +1 -0
- package/dist/graph/entities.d.ts +66 -0
- package/dist/graph/entities.js +187 -0
- package/dist/graph/entities.js.map +1 -0
- package/dist/graph/queries.d.ts +48 -0
- package/dist/graph/queries.js +176 -0
- package/dist/graph/queries.js.map +1 -0
- package/dist/hitl/dashboard.d.ts +51 -0
- package/dist/hitl/dashboard.js +135 -0
- package/dist/hitl/dashboard.js.map +1 -0
- package/dist/hitl/interventions.d.ts +36 -0
- package/dist/hitl/interventions.js +150 -0
- package/dist/hitl/interventions.js.map +1 -0
- package/dist/hitl/steering.d.ts +37 -0
- package/dist/hitl/steering.js +118 -0
- package/dist/hitl/steering.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +701 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/consolidation.d.ts +51 -0
- package/dist/memory/consolidation.js +122 -0
- package/dist/memory/consolidation.js.map +1 -0
- package/dist/memory/ncd.d.ts +40 -0
- package/dist/memory/ncd.js +90 -0
- package/dist/memory/ncd.js.map +1 -0
- package/dist/memory/sm2.d.ts +44 -0
- package/dist/memory/sm2.js +119 -0
- package/dist/memory/sm2.js.map +1 -0
- package/dist/memory/tiers.d.ts +49 -0
- package/dist/memory/tiers.js +145 -0
- package/dist/memory/tiers.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +6 -0
- package/dist/server.js.map +1 -0
- package/dist/trust/ingestion.d.ts +38 -0
- package/dist/trust/ingestion.js +147 -0
- package/dist/trust/ingestion.js.map +1 -0
- package/dist/trust/patterns.d.ts +26 -0
- package/dist/trust/patterns.js +78 -0
- package/dist/trust/patterns.js.map +1 -0
- package/dist/trust/scoring.d.ts +39 -0
- package/dist/trust/scoring.js +206 -0
- package/dist/trust/scoring.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality Gates — Evaluation between cascade phases
|
|
3
|
+
*
|
|
4
|
+
* Four stopping gates (information-theoretic):
|
|
5
|
+
* 1. Compression plateau — MDL not decreasing
|
|
6
|
+
* 2. Diminishing returns — new findings below threshold
|
|
7
|
+
* 3. Entropy floor — knowledge graph structure stabilized
|
|
8
|
+
* 4. MDL increasing — model growing without explanatory gain
|
|
9
|
+
*
|
|
10
|
+
* Plus inter-phase gates that validate readiness to advance.
|
|
11
|
+
*/
|
|
12
|
+
import { getDb } from '../db/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Check all four stopping conditions.
|
|
15
|
+
* If ANY gate says stop, cascade should conclude.
|
|
16
|
+
*/
|
|
17
|
+
export function evaluateStoppingGates(cascadeId) {
|
|
18
|
+
const db = getDb();
|
|
19
|
+
const cascade = db.prepare('SELECT * FROM cascades WHERE id = ?').get(cascadeId);
|
|
20
|
+
if (!cascade)
|
|
21
|
+
throw new Error(`Cascade ${cascadeId} not found`);
|
|
22
|
+
const gates = [];
|
|
23
|
+
// 1. Max rounds reached
|
|
24
|
+
const roundGate = {
|
|
25
|
+
gate: 'max_rounds',
|
|
26
|
+
passed: cascade.current_round < cascade.max_rounds,
|
|
27
|
+
value: cascade.current_round,
|
|
28
|
+
threshold: cascade.max_rounds,
|
|
29
|
+
description: `Round ${cascade.current_round}/${cascade.max_rounds}`,
|
|
30
|
+
};
|
|
31
|
+
gates.push(roundGate);
|
|
32
|
+
// 2. Token budget exhausted
|
|
33
|
+
const tokenGate = {
|
|
34
|
+
gate: 'token_budget',
|
|
35
|
+
passed: cascade.tokens_used < cascade.token_budget,
|
|
36
|
+
value: cascade.tokens_used,
|
|
37
|
+
threshold: cascade.token_budget,
|
|
38
|
+
description: `Tokens ${cascade.tokens_used}/${cascade.token_budget}`,
|
|
39
|
+
};
|
|
40
|
+
gates.push(tokenGate);
|
|
41
|
+
// 3. Diminishing returns — compare findings count between last 2 rounds
|
|
42
|
+
const findingsByRound = db.prepare(`SELECT cascade_round, COUNT(*) as n
|
|
43
|
+
FROM findings WHERE cascade_id = ? AND quarantined = 0
|
|
44
|
+
GROUP BY cascade_round ORDER BY cascade_round DESC LIMIT 2`)
|
|
45
|
+
.all(cascadeId);
|
|
46
|
+
if (findingsByRound.length >= 2) {
|
|
47
|
+
const currentRoundFindings = findingsByRound[0].n;
|
|
48
|
+
const prevRoundFindings = findingsByRound[1].n;
|
|
49
|
+
const ratio = prevRoundFindings > 0 ? currentRoundFindings / prevRoundFindings : 1;
|
|
50
|
+
const dimGate = {
|
|
51
|
+
gate: 'diminishing_returns',
|
|
52
|
+
passed: ratio > 0.3, // Stop if new findings < 30% of previous round
|
|
53
|
+
value: ratio,
|
|
54
|
+
threshold: 0.3,
|
|
55
|
+
description: `New findings ratio: ${Math.round(ratio * 100)}% (${currentRoundFindings} vs ${prevRoundFindings})`,
|
|
56
|
+
};
|
|
57
|
+
gates.push(dimGate);
|
|
58
|
+
}
|
|
59
|
+
// 4. Confidence convergence — average confidence above threshold
|
|
60
|
+
const avgConf = db.prepare(`SELECT AVG(confidence) as avg_conf
|
|
61
|
+
FROM findings WHERE cascade_id = ? AND quarantined = 0`)
|
|
62
|
+
.get(cascadeId);
|
|
63
|
+
if (avgConf?.avg_conf !== null) {
|
|
64
|
+
const confGate = {
|
|
65
|
+
gate: 'confidence_convergence',
|
|
66
|
+
passed: avgConf.avg_conf < 0.85, // Stop if avg confidence very high (saturated)
|
|
67
|
+
value: avgConf.avg_conf,
|
|
68
|
+
threshold: 0.85,
|
|
69
|
+
description: `Avg confidence: ${Math.round(avgConf.avg_conf * 1000) / 1000}`,
|
|
70
|
+
};
|
|
71
|
+
gates.push(confGate);
|
|
72
|
+
}
|
|
73
|
+
// 5. Entropy convergence — check recent entropy metrics
|
|
74
|
+
const entropyMetrics = db.prepare(`SELECT metric_value FROM metrics
|
|
75
|
+
WHERE cascade_id = ? AND metric_name = 'entropy'
|
|
76
|
+
ORDER BY recorded_at DESC LIMIT 3`)
|
|
77
|
+
.all(cascadeId);
|
|
78
|
+
if (entropyMetrics.length >= 3) {
|
|
79
|
+
const deltas = [];
|
|
80
|
+
for (let i = 0; i < entropyMetrics.length - 1; i++) {
|
|
81
|
+
deltas.push(Math.abs(entropyMetrics[i].metric_value - entropyMetrics[i + 1].metric_value));
|
|
82
|
+
}
|
|
83
|
+
const avgDelta = deltas.reduce((s, d) => s + d, 0) / deltas.length;
|
|
84
|
+
const entropyGate = {
|
|
85
|
+
gate: 'entropy_floor',
|
|
86
|
+
passed: avgDelta > 0.01, // Stop if entropy change < 1%
|
|
87
|
+
value: avgDelta,
|
|
88
|
+
threshold: 0.01,
|
|
89
|
+
description: `Entropy delta: ${Math.round(avgDelta * 10000) / 10000}`,
|
|
90
|
+
};
|
|
91
|
+
gates.push(entropyGate);
|
|
92
|
+
}
|
|
93
|
+
const shouldStop = gates.some(g => !g.passed);
|
|
94
|
+
let recommendation = 'Continue research.';
|
|
95
|
+
if (shouldStop) {
|
|
96
|
+
const failedGates = gates.filter(g => !g.passed).map(g => g.gate);
|
|
97
|
+
recommendation = `Stop: ${failedGates.join(', ')}. ${failedGates.includes('max_rounds') ? 'Maximum rounds reached.' :
|
|
98
|
+
failedGates.includes('token_budget') ? 'Token budget exhausted.' :
|
|
99
|
+
failedGates.includes('diminishing_returns') ? 'New findings dropping sharply — research saturated.' :
|
|
100
|
+
failedGates.includes('confidence_convergence') ? 'High confidence across findings — answers converged.' :
|
|
101
|
+
'Knowledge graph structure stabilized.'}`;
|
|
102
|
+
}
|
|
103
|
+
return { shouldStop, gates, recommendation };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Validate readiness to advance from one phase to the next.
|
|
107
|
+
* Returns issues that should be resolved before advancing.
|
|
108
|
+
*/
|
|
109
|
+
export function validatePhaseGate(cascadeId, fromPhase, toPhase) {
|
|
110
|
+
const db = getDb();
|
|
111
|
+
const issues = [];
|
|
112
|
+
switch (fromPhase) {
|
|
113
|
+
case 'identify': {
|
|
114
|
+
// Need at least 1 thread created
|
|
115
|
+
const threads = db.prepare('SELECT COUNT(*) as n FROM threads WHERE cascade_id = ? AND status IN (\'active\',\'done\')').get(cascadeId).n;
|
|
116
|
+
if (threads === 0)
|
|
117
|
+
issues.push('No research threads created. Decompose the question into sub-questions first.');
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case 'screen': {
|
|
121
|
+
// Need findings to have been screened (trust scores applied)
|
|
122
|
+
const unscored = db.prepare('SELECT COUNT(*) as n FROM findings WHERE cascade_id = ? AND trust_composite = 0.5 AND trust_signals_json IS NULL').get(cascadeId).n;
|
|
123
|
+
if (unscored > 0)
|
|
124
|
+
issues.push(`${unscored} findings haven't been trust-scored yet.`);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
case 'evaluate': {
|
|
128
|
+
// Need at least some findings with confidence > 0
|
|
129
|
+
const evaluated = db.prepare('SELECT COUNT(*) as n FROM findings WHERE cascade_id = ? AND quarantined = 0').get(cascadeId).n;
|
|
130
|
+
if (evaluated === 0)
|
|
131
|
+
issues.push('No non-quarantined findings. All findings were rejected or quarantined.');
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
case 'consolidate': {
|
|
135
|
+
// Just check we have entities in the graph
|
|
136
|
+
// (consolidation creates entities — so this is post-facto)
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
case 'mature': {
|
|
140
|
+
// Need at least 1 hypothesis
|
|
141
|
+
const hyps = db.prepare('SELECT COUNT(*) as n FROM hypotheses WHERE cascade_id = ?').get(cascadeId).n;
|
|
142
|
+
if (hyps === 0)
|
|
143
|
+
issues.push('No hypotheses to mature. Create at least one hypothesis from findings.');
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
case 'prune': {
|
|
147
|
+
// No hard requirements — pruning is optional
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case 'synthesize': {
|
|
151
|
+
// Need findings to synthesize
|
|
152
|
+
const findings = db.prepare('SELECT COUNT(*) as n FROM findings WHERE cascade_id = ? AND quarantined = 0').get(cascadeId).n;
|
|
153
|
+
if (findings === 0)
|
|
154
|
+
issues.push('No findings to synthesize.');
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
case 'observe': {
|
|
158
|
+
// Terminal — check stopping conditions
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return { ready: issues.length === 0, issues };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Calculate information-theoretic metrics for the current round.
|
|
166
|
+
*/
|
|
167
|
+
export function calculateRoundMetrics(cascadeId) {
|
|
168
|
+
const db = getDb();
|
|
169
|
+
const cascade = db.prepare('SELECT * FROM cascades WHERE id = ?').get(cascadeId);
|
|
170
|
+
if (!cascade)
|
|
171
|
+
throw new Error(`Cascade ${cascadeId} not found`);
|
|
172
|
+
const plan = cascade.plan_json ? JSON.parse(cascade.plan_json) : null;
|
|
173
|
+
const totalQuestions = plan?.questions?.length || 1;
|
|
174
|
+
// Coverage: what fraction of questions have findings
|
|
175
|
+
const questionsWithFindings = db.prepare(`SELECT COUNT(DISTINCT t.question) as n
|
|
176
|
+
FROM threads t JOIN findings f ON t.id = f.thread_id
|
|
177
|
+
WHERE t.cascade_id = ? AND f.quarantined = 0`)
|
|
178
|
+
.get(cascadeId);
|
|
179
|
+
const coverage = Math.min(1, (questionsWithFindings?.n || 0) / totalQuestions);
|
|
180
|
+
// Depth: average findings per question
|
|
181
|
+
const totalFindings = db.prepare('SELECT COUNT(*) as n FROM findings WHERE cascade_id = ? AND quarantined = 0').get(cascadeId).n;
|
|
182
|
+
const depth = Math.min(1, totalFindings / (totalQuestions * 10)); // 10 findings/question = max depth
|
|
183
|
+
// Confidence: average confidence of non-quarantined findings
|
|
184
|
+
const avgConf = db.prepare('SELECT AVG(confidence) as v FROM findings WHERE cascade_id = ? AND quarantined = 0').get(cascadeId)?.v || 0;
|
|
185
|
+
// Source quality: average trust score
|
|
186
|
+
const avgTrust = db.prepare('SELECT AVG(trust_composite) as v FROM findings WHERE cascade_id = ? AND quarantined = 0').get(cascadeId)?.v || 0.5;
|
|
187
|
+
// Graph density: 2|E|/(|V|(|V|-1)) — but capped at 1
|
|
188
|
+
const V = db.prepare('SELECT COUNT(*) as n FROM kg_entities').get().n;
|
|
189
|
+
const E = db.prepare('SELECT COUNT(*) as n FROM kg_edges').get().n;
|
|
190
|
+
const graphDensity = V > 1 ? Math.min(1, (2 * E) / (V * (V - 1))) : 0;
|
|
191
|
+
return {
|
|
192
|
+
coverage,
|
|
193
|
+
depth,
|
|
194
|
+
confidence: avgConf,
|
|
195
|
+
sourceQuality: avgTrust,
|
|
196
|
+
graphDensity,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=gates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gates.js","sourceRoot":"","sources":["../../src/cascade/gates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research Integration — Search/fetch pipeline
|
|
3
|
+
*
|
|
4
|
+
* Provides structured interfaces for research operations.
|
|
5
|
+
* The LLM performs actual web_search/web_fetch — this module
|
|
6
|
+
* structures the inputs/outputs and tracks the process.
|
|
7
|
+
*/
|
|
8
|
+
export interface SearchPlan {
|
|
9
|
+
cascadeId: string;
|
|
10
|
+
roundIndex: number;
|
|
11
|
+
queries: SearchQuery[];
|
|
12
|
+
explorationBudget: number;
|
|
13
|
+
}
|
|
14
|
+
export interface SearchQuery {
|
|
15
|
+
query: string;
|
|
16
|
+
type: 'exploration' | 'exploitation' | 'validation';
|
|
17
|
+
priority: number;
|
|
18
|
+
threadId?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface RawFinding {
|
|
21
|
+
claim: string;
|
|
22
|
+
evidence?: string;
|
|
23
|
+
sourceUrl?: string;
|
|
24
|
+
sourceType?: 'primary' | 'secondary' | 'tertiary';
|
|
25
|
+
rawConfidence?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Build a search plan from cascade state.
|
|
29
|
+
* Generates queries based on questions, existing findings, and gaps.
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildSearchPlan(cascadeId: string): SearchPlan;
|
|
32
|
+
/**
|
|
33
|
+
* Classify a query to determine which model should handle it.
|
|
34
|
+
* Returns routing info for multi-model dispatch.
|
|
35
|
+
*/
|
|
36
|
+
export declare function classifyQuery(query: string): {
|
|
37
|
+
type: 'technical' | 'discovery' | 'classification' | 'validation';
|
|
38
|
+
suggestedModel: string;
|
|
39
|
+
suggestedAgent: string;
|
|
40
|
+
reasoning: string;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Batch store findings from a research round.
|
|
44
|
+
* Returns count of new vs duplicate findings.
|
|
45
|
+
*/
|
|
46
|
+
export declare function batchStoreFindings(cascadeId: string, roundIndex: number, threadId: string | undefined, findings: RawFinding[]): {
|
|
47
|
+
stored: number;
|
|
48
|
+
duplicates: number;
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=research.d.ts.map
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research Integration — Search/fetch pipeline
|
|
3
|
+
*
|
|
4
|
+
* Provides structured interfaces for research operations.
|
|
5
|
+
* The LLM performs actual web_search/web_fetch — this module
|
|
6
|
+
* structures the inputs/outputs and tracks the process.
|
|
7
|
+
*/
|
|
8
|
+
import { getDb, contentHash } from '../db/index.js';
|
|
9
|
+
// --- Functions ---
|
|
10
|
+
/**
|
|
11
|
+
* Build a search plan from cascade state.
|
|
12
|
+
* Generates queries based on questions, existing findings, and gaps.
|
|
13
|
+
*/
|
|
14
|
+
export function buildSearchPlan(cascadeId) {
|
|
15
|
+
const db = getDb();
|
|
16
|
+
const cascade = db.prepare('SELECT * FROM cascades WHERE id = ?').get(cascadeId);
|
|
17
|
+
if (!cascade)
|
|
18
|
+
throw new Error(`Cascade ${cascadeId} not found`);
|
|
19
|
+
const plan = cascade.plan_json ? JSON.parse(cascade.plan_json) : null;
|
|
20
|
+
const questions = plan?.questions || [cascade.question];
|
|
21
|
+
const roundIndex = cascade.current_round;
|
|
22
|
+
const budget = Math.max(0, 1 - roundIndex / cascade.max_rounds);
|
|
23
|
+
const queries = [];
|
|
24
|
+
// Round 0 (SEED): all questions are exploration
|
|
25
|
+
if (roundIndex === 0) {
|
|
26
|
+
for (const q of questions) {
|
|
27
|
+
queries.push({ query: q, type: 'exploration', priority: 1.0 });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// Later rounds: mix of exploration, exploitation, validation
|
|
32
|
+
const explorationCount = Math.ceil(questions.length * budget);
|
|
33
|
+
// Exploration: questions without enough findings
|
|
34
|
+
const threadCoverage = db.prepare(`SELECT t.question, COUNT(f.id) as finding_count
|
|
35
|
+
FROM threads t LEFT JOIN findings f ON t.id = f.thread_id AND f.quarantined = 0
|
|
36
|
+
WHERE t.cascade_id = ?
|
|
37
|
+
GROUP BY t.question
|
|
38
|
+
ORDER BY finding_count ASC`)
|
|
39
|
+
.all(cascadeId);
|
|
40
|
+
for (let i = 0; i < Math.min(explorationCount, threadCoverage.length); i++) {
|
|
41
|
+
queries.push({
|
|
42
|
+
query: threadCoverage[i].question,
|
|
43
|
+
type: 'exploration',
|
|
44
|
+
priority: 1.0 - i * 0.1,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Exploitation: deepen high-confidence threads
|
|
48
|
+
const highConfThreads = db.prepare(`SELECT t.id, t.question, AVG(f.confidence) as avg_conf
|
|
49
|
+
FROM threads t JOIN findings f ON t.id = f.thread_id
|
|
50
|
+
WHERE t.cascade_id = ? AND f.quarantined = 0
|
|
51
|
+
GROUP BY t.id
|
|
52
|
+
HAVING avg_conf > 0.5
|
|
53
|
+
ORDER BY avg_conf DESC LIMIT 3`)
|
|
54
|
+
.all(cascadeId);
|
|
55
|
+
for (const thread of highConfThreads) {
|
|
56
|
+
queries.push({
|
|
57
|
+
query: thread.question,
|
|
58
|
+
type: 'exploitation',
|
|
59
|
+
priority: thread.avg_conf,
|
|
60
|
+
threadId: thread.id,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// Validation: cross-check low-confidence findings
|
|
64
|
+
const lowConfFindings = db.prepare(`SELECT claim FROM findings
|
|
65
|
+
WHERE cascade_id = ? AND quarantined = 0 AND confidence < 0.5
|
|
66
|
+
ORDER BY confidence ASC LIMIT 3`)
|
|
67
|
+
.all(cascadeId);
|
|
68
|
+
for (const f of lowConfFindings) {
|
|
69
|
+
queries.push({
|
|
70
|
+
query: `verify: ${f.claim}`,
|
|
71
|
+
type: 'validation',
|
|
72
|
+
priority: 0.8,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Sort by priority
|
|
77
|
+
queries.sort((a, b) => b.priority - a.priority);
|
|
78
|
+
return { cascadeId, roundIndex, queries, explorationBudget: budget };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Classify a query to determine which model should handle it.
|
|
82
|
+
* Returns routing info for multi-model dispatch.
|
|
83
|
+
*/
|
|
84
|
+
export function classifyQuery(query) {
|
|
85
|
+
const lower = query.toLowerCase();
|
|
86
|
+
// Classification heuristics (simple — LLM should refine these)
|
|
87
|
+
if (lower.includes('verify') || lower.includes('validate') || lower.includes('confirm') || lower.includes('cross-check')) {
|
|
88
|
+
return { type: 'validation', suggestedModel: 'sonnet', suggestedAgent: 'cross-validator', reasoning: 'Validation query — cross-reference with independent sources' };
|
|
89
|
+
}
|
|
90
|
+
if (lower.includes('how') || lower.includes('implementation') || lower.includes('architecture') || lower.includes('benchmark') || lower.includes('performance')) {
|
|
91
|
+
return { type: 'technical', suggestedModel: 'opus', suggestedAgent: 'deep-investigator', reasoning: 'Technical deep-dive — needs strong reasoning' };
|
|
92
|
+
}
|
|
93
|
+
if (lower.includes('what if') || lower.includes('could') || lower.includes('explore') || lower.includes('design') || lower.includes('philosophy')) {
|
|
94
|
+
return { type: 'discovery', suggestedModel: 'sonnet', suggestedAgent: 'research-planner', reasoning: 'Discovery/open-ended — benefits from diverse exploration' };
|
|
95
|
+
}
|
|
96
|
+
if (lower.includes('categorize') || lower.includes('sort') || lower.includes('tag') || lower.includes('extract')) {
|
|
97
|
+
return { type: 'classification', suggestedModel: 'haiku', suggestedAgent: 'research-planner', reasoning: 'Classification task — lightweight model sufficient' };
|
|
98
|
+
}
|
|
99
|
+
// Default: technical
|
|
100
|
+
return { type: 'technical', suggestedModel: 'sonnet', suggestedAgent: 'deep-investigator', reasoning: 'Default routing — general research query' };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Batch store findings from a research round.
|
|
104
|
+
* Returns count of new vs duplicate findings.
|
|
105
|
+
*/
|
|
106
|
+
export function batchStoreFindings(cascadeId, roundIndex, threadId, findings) {
|
|
107
|
+
const db = getDb();
|
|
108
|
+
let stored = 0;
|
|
109
|
+
let duplicates = 0;
|
|
110
|
+
const insertStmt = db.prepare(`INSERT INTO findings (id, thread_id, cascade_id, claim, evidence, source_url, source_type, confidence, cascade_round)
|
|
111
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
112
|
+
ON CONFLICT(id) DO UPDATE SET confidence = MAX(confidence, excluded.confidence)`);
|
|
113
|
+
const transaction = db.transaction(() => {
|
|
114
|
+
for (const f of findings) {
|
|
115
|
+
const id = contentHash(f.claim);
|
|
116
|
+
const existing = db.prepare('SELECT id FROM findings WHERE id = ?').get(id);
|
|
117
|
+
insertStmt.run(id, threadId, cascadeId, f.claim, f.evidence, f.sourceUrl, f.sourceType, f.rawConfidence ?? 0.5, roundIndex);
|
|
118
|
+
if (existing)
|
|
119
|
+
duplicates++;
|
|
120
|
+
else
|
|
121
|
+
stored++;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
transaction();
|
|
125
|
+
return { stored, duplicates };
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=research.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"research.js","sourceRoot":"","sources":["../../src/cascade/research.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* cascade-engine CLI
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* cascade-engine serve Start MCP stdio server (default)
|
|
7
|
+
* cascade-engine status Show active cascades and DB stats
|
|
8
|
+
* cascade-engine status <id> Show detailed cascade status
|
|
9
|
+
* cascade-engine graph Show knowledge graph stats
|
|
10
|
+
* cascade-engine notes Show Zettelkasten note stats
|
|
11
|
+
* cascade-engine reset Delete the database and start fresh
|
|
12
|
+
* cascade-engine db-path Print the database file path
|
|
13
|
+
* cascade-engine help Show this help
|
|
14
|
+
*
|
|
15
|
+
* Environment:
|
|
16
|
+
* CASCADE_DB_PATH Override database location (default: ~/.cascade-engine/knowledge.db)
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* cascade-engine CLI
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* cascade-engine serve Start MCP stdio server (default)
|
|
7
|
+
* cascade-engine status Show active cascades and DB stats
|
|
8
|
+
* cascade-engine status <id> Show detailed cascade status
|
|
9
|
+
* cascade-engine graph Show knowledge graph stats
|
|
10
|
+
* cascade-engine notes Show Zettelkasten note stats
|
|
11
|
+
* cascade-engine reset Delete the database and start fresh
|
|
12
|
+
* cascade-engine db-path Print the database file path
|
|
13
|
+
* cascade-engine help Show this help
|
|
14
|
+
*
|
|
15
|
+
* Environment:
|
|
16
|
+
* CASCADE_DB_PATH Override database location (default: ~/.cascade-engine/knowledge.db)
|
|
17
|
+
*/
|
|
18
|
+
import { getDb, closeDb } from './db/index.js';
|
|
19
|
+
import { getGraphStats } from './graph/entities.js';
|
|
20
|
+
import { getNoteStats } from './graph/amem.js';
|
|
21
|
+
import { existsSync, unlinkSync } from 'node:fs';
|
|
22
|
+
import { join } from 'node:path';
|
|
23
|
+
const args = process.argv.slice(2);
|
|
24
|
+
const command = args[0] || 'serve';
|
|
25
|
+
async function main() {
|
|
26
|
+
switch (command) {
|
|
27
|
+
case 'serve':
|
|
28
|
+
case 'start': {
|
|
29
|
+
// Dynamic import to avoid loading the full MCP server for other commands
|
|
30
|
+
const { default: startServer } = await import('./server.js');
|
|
31
|
+
await startServer();
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
case 'status': {
|
|
35
|
+
const db = getDb();
|
|
36
|
+
const cascadeId = args[1];
|
|
37
|
+
if (cascadeId) {
|
|
38
|
+
const cascade = db.prepare('SELECT * FROM cascades WHERE id = ? OR id LIKE ?')
|
|
39
|
+
.get(cascadeId, `${cascadeId}%`);
|
|
40
|
+
if (!cascade) {
|
|
41
|
+
console.log(`Cascade "${cascadeId}" not found.`);
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
const findings = db.prepare('SELECT COUNT(*) as n FROM findings WHERE cascade_id = ? AND quarantined = 0').get(cascade.id).n;
|
|
45
|
+
const quarantined = db.prepare('SELECT COUNT(*) as n FROM findings WHERE cascade_id = ? AND quarantined = 1').get(cascade.id).n;
|
|
46
|
+
const hypotheses = db.prepare('SELECT COUNT(*) as n FROM hypotheses WHERE cascade_id = ?').get(cascade.id).n;
|
|
47
|
+
console.log(`Cascade: ${cascade.id}`);
|
|
48
|
+
console.log(`Question: ${cascade.question}`);
|
|
49
|
+
console.log(`Status: ${cascade.status}`);
|
|
50
|
+
console.log(`Round: ${cascade.current_round}/${cascade.max_rounds}`);
|
|
51
|
+
console.log(`Findings: ${findings} (${quarantined} quarantined)`);
|
|
52
|
+
console.log(`Hypotheses: ${hypotheses}`);
|
|
53
|
+
console.log(`Tokens: ${cascade.tokens_used}/${cascade.token_budget}`);
|
|
54
|
+
console.log(`Created: ${cascade.created_at}`);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const cascades = db.prepare("SELECT id, question, status, current_round, max_rounds, created_at FROM cascades ORDER BY updated_at DESC").all();
|
|
58
|
+
if (cascades.length === 0) {
|
|
59
|
+
console.log('No cascades found. Start one with cascade_init.');
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
console.log(`${cascades.length} cascade(s):\n`);
|
|
63
|
+
for (const c of cascades) {
|
|
64
|
+
console.log(` ${c.id.slice(0, 8)} ${c.status.padEnd(13)} R${c.current_round}/${c.max_rounds} ${c.question.slice(0, 60)}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const findings = db.prepare('SELECT COUNT(*) as n FROM findings').get().n;
|
|
68
|
+
const entities = db.prepare('SELECT COUNT(*) as n FROM kg_entities').get().n;
|
|
69
|
+
const edges = db.prepare('SELECT COUNT(*) as n FROM kg_edges').get().n;
|
|
70
|
+
console.log(`\nDB totals: ${findings} findings, ${entities} entities, ${edges} edges`);
|
|
71
|
+
}
|
|
72
|
+
closeDb();
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case 'graph': {
|
|
76
|
+
const stats = getGraphStats();
|
|
77
|
+
console.log('Knowledge Graph:');
|
|
78
|
+
console.log(` Entities: ${stats.entityCount}`);
|
|
79
|
+
console.log(` Edges: ${stats.edgeCount}`);
|
|
80
|
+
console.log(` Avg degree: ${stats.avgDegree.toFixed(2)}`);
|
|
81
|
+
console.log(` Communities: ${stats.communityCounts}`);
|
|
82
|
+
console.log(` Orphans: ${stats.orphanCount}`);
|
|
83
|
+
console.log(` Tiers: ${JSON.stringify(stats.tierCounts)}`);
|
|
84
|
+
closeDb();
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case 'notes': {
|
|
88
|
+
const stats = getNoteStats();
|
|
89
|
+
console.log('Zettelkasten Notes:');
|
|
90
|
+
console.log(` Total: ${stats.totalNotes}`);
|
|
91
|
+
console.log(` Links: ${stats.totalLinks}`);
|
|
92
|
+
console.log(` Orphans: ${stats.orphanCount}`);
|
|
93
|
+
console.log(` Maturity: ${JSON.stringify(stats.maturityCounts)}`);
|
|
94
|
+
console.log(` Types: ${JSON.stringify(stats.typeCounts)}`);
|
|
95
|
+
closeDb();
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case 'db-path': {
|
|
99
|
+
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
100
|
+
const dbPath = process.env.CASCADE_DB_PATH || join(home, '.cascade-engine', 'knowledge.db');
|
|
101
|
+
console.log(dbPath);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case 'reset': {
|
|
105
|
+
const home = process.env.HOME || process.env.USERPROFILE || '';
|
|
106
|
+
const dbPath = process.env.CASCADE_DB_PATH || join(home, '.cascade-engine', 'knowledge.db');
|
|
107
|
+
if (existsSync(dbPath)) {
|
|
108
|
+
unlinkSync(dbPath);
|
|
109
|
+
// Clean up WAL and SHM files
|
|
110
|
+
if (existsSync(dbPath + '-wal'))
|
|
111
|
+
unlinkSync(dbPath + '-wal');
|
|
112
|
+
if (existsSync(dbPath + '-shm'))
|
|
113
|
+
unlinkSync(dbPath + '-shm');
|
|
114
|
+
console.log(`Deleted: ${dbPath}`);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log('No database found.');
|
|
118
|
+
}
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
case 'help':
|
|
122
|
+
case '--help':
|
|
123
|
+
case '-h': {
|
|
124
|
+
console.log(`cascade-engine — Progressive deep research MCP server
|
|
125
|
+
|
|
126
|
+
Usage:
|
|
127
|
+
cascade-engine serve Start MCP stdio server (default)
|
|
128
|
+
cascade-engine status Show active cascades and DB stats
|
|
129
|
+
cascade-engine status <id> Detailed cascade status
|
|
130
|
+
cascade-engine graph Knowledge graph statistics
|
|
131
|
+
cascade-engine notes Zettelkasten note statistics
|
|
132
|
+
cascade-engine db-path Print database file path
|
|
133
|
+
cascade-engine reset Delete database and start fresh
|
|
134
|
+
cascade-engine help Show this help
|
|
135
|
+
|
|
136
|
+
MCP Integration:
|
|
137
|
+
Add to your .mcp.json (Claude Code) or equivalent:
|
|
138
|
+
|
|
139
|
+
{
|
|
140
|
+
"mcpServers": {
|
|
141
|
+
"cascade-engine": {
|
|
142
|
+
"command": "cascade-engine",
|
|
143
|
+
"args": ["serve"]
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
Environment:
|
|
149
|
+
CASCADE_DB_PATH Override database location
|
|
150
|
+
Default: ~/.cascade-engine/knowledge.db
|
|
151
|
+
|
|
152
|
+
More info: https://github.com/geoff-obsidicore/Research-Cascade`);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
default:
|
|
156
|
+
console.error(`Unknown command: ${command}`);
|
|
157
|
+
console.error('Run "cascade-engine help" for usage.');
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
main().catch((err) => {
|
|
162
|
+
console.error('Fatal:', err);
|
|
163
|
+
process.exit(1);
|
|
164
|
+
});
|
|
165
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kalman Filter — Confidence fusion from multiple noisy sources
|
|
3
|
+
*
|
|
4
|
+
* K = P / (P + R)
|
|
5
|
+
* confidence += K × (measurement - confidence)
|
|
6
|
+
* uncertainty = (1 - K) × P
|
|
7
|
+
*
|
|
8
|
+
* High R (unreliable source) → low K → measurement discounted
|
|
9
|
+
* High P (uncertain claim) → high K → updated aggressively
|
|
10
|
+
*/
|
|
11
|
+
export interface KalmanState {
|
|
12
|
+
estimate: number;
|
|
13
|
+
uncertainty: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create initial Kalman state for a new finding.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createKalmanState(initialEstimate?: number, initialUncertainty?: number): KalmanState;
|
|
19
|
+
/**
|
|
20
|
+
* Update Kalman estimate with a new measurement.
|
|
21
|
+
*
|
|
22
|
+
* @param state Current Kalman state
|
|
23
|
+
* @param measurement New confidence measurement (0-1)
|
|
24
|
+
* @param measurementNoise R — noise of the measurement source (higher = less reliable)
|
|
25
|
+
* @returns Updated state
|
|
26
|
+
*/
|
|
27
|
+
export declare function kalmanUpdate(state: KalmanState, measurement: number, measurementNoise: number): KalmanState;
|
|
28
|
+
/**
|
|
29
|
+
* Fuse multiple measurements at once.
|
|
30
|
+
* Each measurement has its own noise level based on source reliability.
|
|
31
|
+
*/
|
|
32
|
+
export declare function fuseConfidence(measurements: {
|
|
33
|
+
value: number;
|
|
34
|
+
noise: number;
|
|
35
|
+
}[], initialEstimate?: number, initialUncertainty?: number): KalmanState;
|
|
36
|
+
/**
|
|
37
|
+
* Map source type to measurement noise.
|
|
38
|
+
* Lower noise = more trusted source.
|
|
39
|
+
*/
|
|
40
|
+
export declare function sourceToNoise(sourceType: string | undefined, trustScore: number): number;
|
|
41
|
+
/**
|
|
42
|
+
* Batch update: apply multiple findings' confidence to a single claim.
|
|
43
|
+
* Returns the fused confidence and remaining uncertainty.
|
|
44
|
+
*/
|
|
45
|
+
export declare function batchFuseForClaim(existingConfidence: number, existingUncertainty: number, newMeasurements: {
|
|
46
|
+
confidence: number;
|
|
47
|
+
sourceType?: string;
|
|
48
|
+
trustScore: number;
|
|
49
|
+
}[]): {
|
|
50
|
+
confidence: number;
|
|
51
|
+
uncertainty: number;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=kalman.d.ts.map
|