@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Obsidicore
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step-Level Checkpointing
|
|
3
|
+
*
|
|
4
|
+
* Every step is checkpointed independently — crash loses only the current step.
|
|
5
|
+
* Idempotent upserts via content-addressable keys + ON CONFLICT DO UPDATE.
|
|
6
|
+
* Buffer in SQLite, commit to JSONL only after step completes.
|
|
7
|
+
*/
|
|
8
|
+
import { CascadeRoundState, CascadePhase } from './engine.js';
|
|
9
|
+
export interface Checkpoint {
|
|
10
|
+
taskId: string;
|
|
11
|
+
roundIndex: number;
|
|
12
|
+
stepIndex: number;
|
|
13
|
+
stepName: string;
|
|
14
|
+
status: 'pending' | 'running' | 'done' | 'failed' | 'skipped';
|
|
15
|
+
stateSnapshot?: string;
|
|
16
|
+
errorMessage?: string;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
completedAt?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Save a checkpoint for the current step.
|
|
22
|
+
*/
|
|
23
|
+
export declare function saveCheckpoint(state: CascadeRoundState, status: Checkpoint['status'], errorMessage?: string): void;
|
|
24
|
+
/**
|
|
25
|
+
* Get all checkpoints for a cascade, organized by round.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getCheckpoints(cascadeId: string): Record<number, Checkpoint[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Find the last successful checkpoint to resume from.
|
|
30
|
+
*/
|
|
31
|
+
export declare function findResumePoint(cascadeId: string): {
|
|
32
|
+
roundIndex: number;
|
|
33
|
+
phase: CascadePhase;
|
|
34
|
+
state: CascadeRoundState | null;
|
|
35
|
+
} | null;
|
|
36
|
+
/**
|
|
37
|
+
* Check idempotency cache for a previously computed result.
|
|
38
|
+
*/
|
|
39
|
+
export declare function checkIdempotency(key: string): any | null;
|
|
40
|
+
/**
|
|
41
|
+
* Store a result in the idempotency cache.
|
|
42
|
+
*/
|
|
43
|
+
export declare function cacheIdempotent(key: string, result: any, ttlMinutes?: number): void;
|
|
44
|
+
/**
|
|
45
|
+
* Get a compact progress summary for the cascade.
|
|
46
|
+
*/
|
|
47
|
+
export declare function getProgressSummary(cascadeId: string): {
|
|
48
|
+
totalRounds: number;
|
|
49
|
+
completedRounds: number;
|
|
50
|
+
currentPhase: string;
|
|
51
|
+
completedSteps: number;
|
|
52
|
+
failedSteps: number;
|
|
53
|
+
lastActivity: string;
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=checkpoints.d.ts.map
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step-Level Checkpointing
|
|
3
|
+
*
|
|
4
|
+
* Every step is checkpointed independently — crash loses only the current step.
|
|
5
|
+
* Idempotent upserts via content-addressable keys + ON CONFLICT DO UPDATE.
|
|
6
|
+
* Buffer in SQLite, commit to JSONL only after step completes.
|
|
7
|
+
*/
|
|
8
|
+
import { getDb } from '../db/index.js';
|
|
9
|
+
import { PHASE_ORDER } from './engine.js';
|
|
10
|
+
/**
|
|
11
|
+
* Save a checkpoint for the current step.
|
|
12
|
+
*/
|
|
13
|
+
export function saveCheckpoint(state, status, errorMessage) {
|
|
14
|
+
const db = getDb();
|
|
15
|
+
const idempotencyKey = `${state.cascadeId}:${state.roundIndex}:${state.stepIndex}:${state.phase}`;
|
|
16
|
+
db.prepare(`INSERT INTO cascade_checkpoints
|
|
17
|
+
(task_id, round_index, step_index, step_name, status, state_snapshot, idempotency_key, error_message)
|
|
18
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
19
|
+
ON CONFLICT(task_id, round_index, step_index) DO UPDATE SET
|
|
20
|
+
status = excluded.status,
|
|
21
|
+
state_snapshot = COALESCE(excluded.state_snapshot, state_snapshot),
|
|
22
|
+
error_message = excluded.error_message,
|
|
23
|
+
completed_at = CASE WHEN excluded.status IN ('done','failed','skipped') THEN datetime('now') ELSE completed_at END`)
|
|
24
|
+
.run(state.cascadeId, state.roundIndex, state.stepIndex, state.phase, status, JSON.stringify(state), idempotencyKey, errorMessage);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get all checkpoints for a cascade, organized by round.
|
|
28
|
+
*/
|
|
29
|
+
export function getCheckpoints(cascadeId) {
|
|
30
|
+
const db = getDb();
|
|
31
|
+
const rows = db.prepare(`SELECT * FROM cascade_checkpoints
|
|
32
|
+
WHERE task_id = ? ORDER BY round_index, step_index`)
|
|
33
|
+
.all(cascadeId);
|
|
34
|
+
const byRound = {};
|
|
35
|
+
for (const row of rows) {
|
|
36
|
+
if (!byRound[row.round_index])
|
|
37
|
+
byRound[row.round_index] = [];
|
|
38
|
+
byRound[row.round_index].push({
|
|
39
|
+
taskId: row.task_id,
|
|
40
|
+
roundIndex: row.round_index,
|
|
41
|
+
stepIndex: row.step_index,
|
|
42
|
+
stepName: row.step_name,
|
|
43
|
+
status: row.status,
|
|
44
|
+
stateSnapshot: row.state_snapshot,
|
|
45
|
+
errorMessage: row.error_message,
|
|
46
|
+
createdAt: row.created_at,
|
|
47
|
+
completedAt: row.completed_at,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return byRound;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Find the last successful checkpoint to resume from.
|
|
54
|
+
*/
|
|
55
|
+
export function findResumePoint(cascadeId) {
|
|
56
|
+
const db = getDb();
|
|
57
|
+
const last = db.prepare(`SELECT * FROM cascade_checkpoints
|
|
58
|
+
WHERE task_id = ? AND status = 'done'
|
|
59
|
+
ORDER BY round_index DESC, step_index DESC LIMIT 1`)
|
|
60
|
+
.get(cascadeId);
|
|
61
|
+
if (!last)
|
|
62
|
+
return null;
|
|
63
|
+
const state = last.state_snapshot ? JSON.parse(last.state_snapshot) : null;
|
|
64
|
+
const phaseIdx = PHASE_ORDER.indexOf(last.step_name);
|
|
65
|
+
const nextPhase = phaseIdx >= 0 && phaseIdx < PHASE_ORDER.length - 1
|
|
66
|
+
? PHASE_ORDER[phaseIdx + 1]
|
|
67
|
+
: 'identify'; // Start new round
|
|
68
|
+
return {
|
|
69
|
+
roundIndex: phaseIdx >= PHASE_ORDER.length - 1 ? last.round_index + 1 : last.round_index,
|
|
70
|
+
phase: nextPhase,
|
|
71
|
+
state,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check idempotency cache for a previously computed result.
|
|
76
|
+
*/
|
|
77
|
+
export function checkIdempotency(key) {
|
|
78
|
+
const db = getDb();
|
|
79
|
+
// Clean expired entries
|
|
80
|
+
db.prepare("DELETE FROM idempotency_cache WHERE expires_at IS NOT NULL AND expires_at < datetime('now')").run();
|
|
81
|
+
const cached = db.prepare('SELECT result_json FROM idempotency_cache WHERE key = ?').get(key);
|
|
82
|
+
return cached ? JSON.parse(cached.result_json) : null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Store a result in the idempotency cache.
|
|
86
|
+
*/
|
|
87
|
+
export function cacheIdempotent(key, result, ttlMinutes = 60) {
|
|
88
|
+
const db = getDb();
|
|
89
|
+
db.prepare(`INSERT INTO idempotency_cache (key, result_json, expires_at)
|
|
90
|
+
VALUES (?, ?, datetime('now', '+' || ? || ' minutes'))
|
|
91
|
+
ON CONFLICT(key) DO UPDATE SET
|
|
92
|
+
result_json = excluded.result_json,
|
|
93
|
+
expires_at = excluded.expires_at`)
|
|
94
|
+
.run(key, JSON.stringify(result), ttlMinutes);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get a compact progress summary for the cascade.
|
|
98
|
+
*/
|
|
99
|
+
export function getProgressSummary(cascadeId) {
|
|
100
|
+
const db = getDb();
|
|
101
|
+
const cascade = db.prepare('SELECT current_round, max_rounds FROM cascades WHERE id = ?').get(cascadeId);
|
|
102
|
+
if (!cascade)
|
|
103
|
+
throw new Error(`Cascade ${cascadeId} not found`);
|
|
104
|
+
const stats = db.prepare(`SELECT
|
|
105
|
+
COUNT(CASE WHEN status = 'done' THEN 1 END) as completed,
|
|
106
|
+
COUNT(CASE WHEN status = 'failed' THEN 1 END) as failed,
|
|
107
|
+
MAX(COALESCE(completed_at, created_at)) as last_activity
|
|
108
|
+
FROM cascade_checkpoints WHERE task_id = ?`)
|
|
109
|
+
.get(cascadeId);
|
|
110
|
+
const currentStep = db.prepare(`SELECT step_name FROM cascade_checkpoints
|
|
111
|
+
WHERE task_id = ? AND status IN ('running','pending')
|
|
112
|
+
ORDER BY round_index DESC, step_index DESC LIMIT 1`)
|
|
113
|
+
.get(cascadeId);
|
|
114
|
+
return {
|
|
115
|
+
totalRounds: cascade.max_rounds,
|
|
116
|
+
completedRounds: cascade.current_round,
|
|
117
|
+
currentPhase: currentStep?.step_name || 'idle',
|
|
118
|
+
completedSteps: stats?.completed || 0,
|
|
119
|
+
failedSteps: stats?.failed || 0,
|
|
120
|
+
lastActivity: stats?.last_activity || 'never',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=checkpoints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkpoints.js","sourceRoot":"","sources":["../../src/cascade/checkpoints.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cascade Engine — Core FSM Loop
|
|
3
|
+
*
|
|
4
|
+
* Implements the research cascade state machine:
|
|
5
|
+
* IDENTIFY → SCREEN → EVALUATE → CONSOLIDATE → MATURE → PRUNE → SYNTHESIZE → OBSERVE → (loop|done)
|
|
6
|
+
*
|
|
7
|
+
* The AGENT orchestrates. This engine TRACKS STATE.
|
|
8
|
+
* The engine provides methods that MCP tools call; the LLM decides when/how to call them.
|
|
9
|
+
*/
|
|
10
|
+
export type CascadePhase = 'identify' | 'screen' | 'evaluate' | 'consolidate' | 'mature' | 'prune' | 'synthesize' | 'observe';
|
|
11
|
+
export interface CascadeRoundState {
|
|
12
|
+
cascadeId: string;
|
|
13
|
+
roundIndex: number;
|
|
14
|
+
phase: CascadePhase;
|
|
15
|
+
stepIndex: number;
|
|
16
|
+
explorationBudget: number;
|
|
17
|
+
searchQueries: string[];
|
|
18
|
+
findingsThisRound: number;
|
|
19
|
+
startedAt: string;
|
|
20
|
+
}
|
|
21
|
+
export interface StopCondition {
|
|
22
|
+
name: string;
|
|
23
|
+
met: boolean;
|
|
24
|
+
value: number;
|
|
25
|
+
threshold: number;
|
|
26
|
+
description: string;
|
|
27
|
+
}
|
|
28
|
+
export declare const PHASE_ORDER: CascadePhase[];
|
|
29
|
+
/**
|
|
30
|
+
* Initialize a new round of research.
|
|
31
|
+
* Sets up the round state and calculates exploration budget.
|
|
32
|
+
*/
|
|
33
|
+
export declare function initRound(cascadeId: string): CascadeRoundState;
|
|
34
|
+
/**
|
|
35
|
+
* Advance to the next phase in the cascade loop.
|
|
36
|
+
* Returns the new phase, or null if the round is complete.
|
|
37
|
+
*/
|
|
38
|
+
export declare function advancePhase(state: CascadeRoundState): CascadePhase | null;
|
|
39
|
+
/**
|
|
40
|
+
* Mark current phase as complete.
|
|
41
|
+
*/
|
|
42
|
+
export declare function completePhase(state: CascadeRoundState): void;
|
|
43
|
+
/**
|
|
44
|
+
* Resume from the last successful checkpoint.
|
|
45
|
+
*/
|
|
46
|
+
export declare function resumeFromCheckpoint(cascadeId: string): CascadeRoundState | null;
|
|
47
|
+
/**
|
|
48
|
+
* Generate search queries for the IDENTIFY phase.
|
|
49
|
+
* Uses UCB to balance exploration vs exploitation across threads.
|
|
50
|
+
*/
|
|
51
|
+
export declare function generateSearchPlan(cascadeId: string): {
|
|
52
|
+
explorationQueries: string[];
|
|
53
|
+
exploitationQueries: string[];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Create a research thread (a sub-question being investigated).
|
|
57
|
+
*/
|
|
58
|
+
export declare function createThread(cascadeId: string, question: string, type: 'technical' | 'discovery' | 'classification' | 'validation', agentName?: string, modelUsed?: string): string;
|
|
59
|
+
/**
|
|
60
|
+
* Complete a thread and update its UCB values.
|
|
61
|
+
*/
|
|
62
|
+
export declare function completeThread(threadId: string, reward: number): void;
|
|
63
|
+
/**
|
|
64
|
+
* Get round summary for synthesis.
|
|
65
|
+
*/
|
|
66
|
+
export declare function getRoundSummary(cascadeId: string, roundIndex: number): {
|
|
67
|
+
findings: any[];
|
|
68
|
+
hypotheses: any[];
|
|
69
|
+
newEntities: number;
|
|
70
|
+
newEdges: number;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cascade Engine — Core FSM Loop
|
|
3
|
+
*
|
|
4
|
+
* Implements the research cascade state machine:
|
|
5
|
+
* IDENTIFY → SCREEN → EVALUATE → CONSOLIDATE → MATURE → PRUNE → SYNTHESIZE → OBSERVE → (loop|done)
|
|
6
|
+
*
|
|
7
|
+
* The AGENT orchestrates. This engine TRACKS STATE.
|
|
8
|
+
* The engine provides methods that MCP tools call; the LLM decides when/how to call them.
|
|
9
|
+
*/
|
|
10
|
+
import { getDb, generateId } from '../db/index.js';
|
|
11
|
+
export const PHASE_ORDER = [
|
|
12
|
+
'identify', 'screen', 'evaluate', 'consolidate',
|
|
13
|
+
'mature', 'prune', 'synthesize', 'observe',
|
|
14
|
+
];
|
|
15
|
+
// --- Engine Functions ---
|
|
16
|
+
/**
|
|
17
|
+
* Initialize a new round of research.
|
|
18
|
+
* Sets up the round state and calculates exploration budget.
|
|
19
|
+
*/
|
|
20
|
+
export function initRound(cascadeId) {
|
|
21
|
+
const db = getDb();
|
|
22
|
+
const cascade = db.prepare('SELECT * FROM cascades WHERE id = ?').get(cascadeId);
|
|
23
|
+
if (!cascade)
|
|
24
|
+
throw new Error(`Cascade ${cascadeId} not found`);
|
|
25
|
+
const roundIndex = cascade.current_round;
|
|
26
|
+
const explorationBudget = Math.max(0, 1 - roundIndex / cascade.max_rounds);
|
|
27
|
+
const state = {
|
|
28
|
+
cascadeId,
|
|
29
|
+
roundIndex,
|
|
30
|
+
phase: 'identify',
|
|
31
|
+
stepIndex: 0,
|
|
32
|
+
explorationBudget,
|
|
33
|
+
searchQueries: [],
|
|
34
|
+
findingsThisRound: 0,
|
|
35
|
+
startedAt: new Date().toISOString(),
|
|
36
|
+
};
|
|
37
|
+
// Create checkpoint for round start
|
|
38
|
+
db.prepare(`INSERT INTO cascade_checkpoints (task_id, round_index, step_index, step_name, status, state_snapshot)
|
|
39
|
+
VALUES (?, ?, 0, 'round_init', 'done', ?)
|
|
40
|
+
ON CONFLICT(task_id, round_index, step_index) DO UPDATE SET status = 'done'`)
|
|
41
|
+
.run(cascadeId, roundIndex, JSON.stringify(state));
|
|
42
|
+
return state;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Advance to the next phase in the cascade loop.
|
|
46
|
+
* Returns the new phase, or null if the round is complete.
|
|
47
|
+
*/
|
|
48
|
+
export function advancePhase(state) {
|
|
49
|
+
const currentIdx = PHASE_ORDER.indexOf(state.phase);
|
|
50
|
+
if (currentIdx < 0 || currentIdx >= PHASE_ORDER.length - 1)
|
|
51
|
+
return null;
|
|
52
|
+
const nextPhase = PHASE_ORDER[currentIdx + 1];
|
|
53
|
+
state.phase = nextPhase;
|
|
54
|
+
state.stepIndex++;
|
|
55
|
+
// Checkpoint
|
|
56
|
+
const db = getDb();
|
|
57
|
+
db.prepare(`INSERT INTO cascade_checkpoints (task_id, round_index, step_index, step_name, status, state_snapshot)
|
|
58
|
+
VALUES (?, ?, ?, ?, 'running', ?)
|
|
59
|
+
ON CONFLICT(task_id, round_index, step_index) DO UPDATE SET
|
|
60
|
+
status = 'running', state_snapshot = excluded.state_snapshot`)
|
|
61
|
+
.run(state.cascadeId, state.roundIndex, state.stepIndex, nextPhase, JSON.stringify(state));
|
|
62
|
+
return nextPhase;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Mark current phase as complete.
|
|
66
|
+
*/
|
|
67
|
+
export function completePhase(state) {
|
|
68
|
+
const db = getDb();
|
|
69
|
+
db.prepare(`UPDATE cascade_checkpoints SET status = 'done', completed_at = datetime('now')
|
|
70
|
+
WHERE task_id = ? AND round_index = ? AND step_index = ?`)
|
|
71
|
+
.run(state.cascadeId, state.roundIndex, state.stepIndex);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Resume from the last successful checkpoint.
|
|
75
|
+
*/
|
|
76
|
+
export function resumeFromCheckpoint(cascadeId) {
|
|
77
|
+
const db = getDb();
|
|
78
|
+
// Find the last completed checkpoint
|
|
79
|
+
const last = db.prepare(`SELECT * FROM cascade_checkpoints
|
|
80
|
+
WHERE task_id = ? AND status = 'done'
|
|
81
|
+
ORDER BY round_index DESC, step_index DESC LIMIT 1`)
|
|
82
|
+
.get(cascadeId);
|
|
83
|
+
if (!last?.state_snapshot)
|
|
84
|
+
return null;
|
|
85
|
+
const state = JSON.parse(last.state_snapshot);
|
|
86
|
+
// Advance past the completed step
|
|
87
|
+
const nextPhase = advancePhase(state);
|
|
88
|
+
if (!nextPhase) {
|
|
89
|
+
// Round was complete — start new round
|
|
90
|
+
return initRound(cascadeId);
|
|
91
|
+
}
|
|
92
|
+
return state;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Generate search queries for the IDENTIFY phase.
|
|
96
|
+
* Uses UCB to balance exploration vs exploitation across threads.
|
|
97
|
+
*/
|
|
98
|
+
export function generateSearchPlan(cascadeId) {
|
|
99
|
+
const db = getDb();
|
|
100
|
+
const cascade = db.prepare('SELECT * FROM cascades WHERE id = ?').get(cascadeId);
|
|
101
|
+
if (!cascade)
|
|
102
|
+
throw new Error(`Cascade ${cascadeId} not found`);
|
|
103
|
+
const plan = cascade.plan_json ? JSON.parse(cascade.plan_json) : null;
|
|
104
|
+
const questions = plan?.questions || [cascade.question];
|
|
105
|
+
const budget = Math.max(0, 1 - cascade.current_round / cascade.max_rounds);
|
|
106
|
+
// Get existing threads for UCB calculation
|
|
107
|
+
const threads = db.prepare('SELECT * FROM threads WHERE cascade_id = ?').all(cascadeId);
|
|
108
|
+
const totalVisits = threads.reduce((s, t) => s + (t.ucb_visits || 0), 0) || 1;
|
|
109
|
+
// UCB scoring for existing threads
|
|
110
|
+
const C = 1.414; // Exploration constant
|
|
111
|
+
for (const thread of threads) {
|
|
112
|
+
const visits = thread.ucb_visits || 1;
|
|
113
|
+
const reward = thread.ucb_reward || 0;
|
|
114
|
+
thread.ucb_score = reward / visits + C * Math.sqrt(Math.log(totalVisits) / visits);
|
|
115
|
+
}
|
|
116
|
+
// Split budget: exploration gets novel queries, exploitation deepens existing
|
|
117
|
+
const explorationCount = Math.ceil(questions.length * budget);
|
|
118
|
+
const exploitationCount = Math.max(1, questions.length - explorationCount);
|
|
119
|
+
return {
|
|
120
|
+
explorationQueries: questions.slice(0, explorationCount),
|
|
121
|
+
exploitationQueries: threads
|
|
122
|
+
.sort((a, b) => (b.ucb_score || 0) - (a.ucb_score || 0))
|
|
123
|
+
.slice(0, exploitationCount)
|
|
124
|
+
.map((t) => t.question),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Create a research thread (a sub-question being investigated).
|
|
129
|
+
*/
|
|
130
|
+
export function createThread(cascadeId, question, type, agentName, modelUsed) {
|
|
131
|
+
const db = getDb();
|
|
132
|
+
const id = generateId();
|
|
133
|
+
db.prepare(`INSERT INTO threads (id, cascade_id, question, type, status, agent_name, model_used, started_at)
|
|
134
|
+
VALUES (?, ?, ?, ?, 'active', ?, ?, datetime('now'))`)
|
|
135
|
+
.run(id, cascadeId, question, type, agentName, modelUsed);
|
|
136
|
+
return id;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Complete a thread and update its UCB values.
|
|
140
|
+
*/
|
|
141
|
+
export function completeThread(threadId, reward) {
|
|
142
|
+
const db = getDb();
|
|
143
|
+
db.prepare(`UPDATE threads SET
|
|
144
|
+
status = 'done', completed_at = datetime('now'),
|
|
145
|
+
ucb_visits = ucb_visits + 1,
|
|
146
|
+
ucb_reward = ucb_reward + ?
|
|
147
|
+
WHERE id = ?`)
|
|
148
|
+
.run(reward, threadId);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get round summary for synthesis.
|
|
152
|
+
*/
|
|
153
|
+
export function getRoundSummary(cascadeId, roundIndex) {
|
|
154
|
+
const db = getDb();
|
|
155
|
+
const findings = db.prepare(`SELECT id, claim, confidence, trust_composite, grade_level
|
|
156
|
+
FROM findings WHERE cascade_id = ? AND cascade_round = ? AND quarantined = 0
|
|
157
|
+
ORDER BY confidence DESC`)
|
|
158
|
+
.all(cascadeId, roundIndex);
|
|
159
|
+
const hypotheses = db.prepare(`SELECT id, statement, affinity, status
|
|
160
|
+
FROM hypotheses WHERE cascade_id = ?
|
|
161
|
+
ORDER BY affinity DESC`)
|
|
162
|
+
.all(cascadeId);
|
|
163
|
+
// Approximate new entities/edges this round (by timestamp)
|
|
164
|
+
const newEntities = db.prepare(`SELECT COUNT(*) as n FROM kg_entities
|
|
165
|
+
WHERE created_at >= (SELECT MIN(created_at) FROM cascade_checkpoints WHERE task_id = ? AND round_index = ?)`).get(cascadeId, roundIndex)?.n || 0;
|
|
166
|
+
const newEdges = db.prepare(`SELECT COUNT(*) as n FROM kg_edges
|
|
167
|
+
WHERE created_at >= (SELECT MIN(created_at) FROM cascade_checkpoints WHERE task_id = ? AND round_index = ?)`).get(cascadeId, roundIndex)?.n || 0;
|
|
168
|
+
return { findings, hypotheses, newEntities, newEdges };
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/cascade/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
export interface GateResult {
|
|
13
|
+
gate: string;
|
|
14
|
+
passed: boolean;
|
|
15
|
+
value: number;
|
|
16
|
+
threshold: number;
|
|
17
|
+
description: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Check all four stopping conditions.
|
|
21
|
+
* If ANY gate says stop, cascade should conclude.
|
|
22
|
+
*/
|
|
23
|
+
export declare function evaluateStoppingGates(cascadeId: string): {
|
|
24
|
+
shouldStop: boolean;
|
|
25
|
+
gates: GateResult[];
|
|
26
|
+
recommendation: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Validate readiness to advance from one phase to the next.
|
|
30
|
+
* Returns issues that should be resolved before advancing.
|
|
31
|
+
*/
|
|
32
|
+
export declare function validatePhaseGate(cascadeId: string, fromPhase: string, toPhase: string): {
|
|
33
|
+
ready: boolean;
|
|
34
|
+
issues: string[];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Calculate information-theoretic metrics for the current round.
|
|
38
|
+
*/
|
|
39
|
+
export declare function calculateRoundMetrics(cascadeId: string): {
|
|
40
|
+
coverage: number;
|
|
41
|
+
depth: number;
|
|
42
|
+
confidence: number;
|
|
43
|
+
sourceQuality: number;
|
|
44
|
+
graphDensity: number;
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=gates.d.ts.map
|