@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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cascade/checkpoints.d.ts +55 -0
  3. package/dist/cascade/checkpoints.js +123 -0
  4. package/dist/cascade/checkpoints.js.map +1 -0
  5. package/dist/cascade/engine.d.ts +72 -0
  6. package/dist/cascade/engine.js +170 -0
  7. package/dist/cascade/engine.js.map +1 -0
  8. package/dist/cascade/gates.d.ts +46 -0
  9. package/dist/cascade/gates.js +199 -0
  10. package/dist/cascade/gates.js.map +1 -0
  11. package/dist/cascade/research.d.ts +50 -0
  12. package/dist/cascade/research.js +127 -0
  13. package/dist/cascade/research.js.map +1 -0
  14. package/dist/cli.d.ts +19 -0
  15. package/dist/cli.js +165 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/control/kalman.d.ts +53 -0
  18. package/dist/control/kalman.js +83 -0
  19. package/dist/control/kalman.js.map +1 -0
  20. package/dist/control/pid.d.ts +57 -0
  21. package/dist/control/pid.js +95 -0
  22. package/dist/control/pid.js.map +1 -0
  23. package/dist/control/stability.d.ts +42 -0
  24. package/dist/control/stability.js +117 -0
  25. package/dist/control/stability.js.map +1 -0
  26. package/dist/db/index.d.ts +26 -0
  27. package/dist/db/index.js +116 -0
  28. package/dist/db/index.js.map +1 -0
  29. package/dist/db/schema.sql +282 -0
  30. package/dist/graph/amem.d.ts +80 -0
  31. package/dist/graph/amem.js +190 -0
  32. package/dist/graph/amem.js.map +1 -0
  33. package/dist/graph/entities.d.ts +66 -0
  34. package/dist/graph/entities.js +187 -0
  35. package/dist/graph/entities.js.map +1 -0
  36. package/dist/graph/queries.d.ts +48 -0
  37. package/dist/graph/queries.js +176 -0
  38. package/dist/graph/queries.js.map +1 -0
  39. package/dist/hitl/dashboard.d.ts +51 -0
  40. package/dist/hitl/dashboard.js +135 -0
  41. package/dist/hitl/dashboard.js.map +1 -0
  42. package/dist/hitl/interventions.d.ts +36 -0
  43. package/dist/hitl/interventions.js +150 -0
  44. package/dist/hitl/interventions.js.map +1 -0
  45. package/dist/hitl/steering.d.ts +37 -0
  46. package/dist/hitl/steering.js +118 -0
  47. package/dist/hitl/steering.js.map +1 -0
  48. package/dist/index.d.ts +12 -0
  49. package/dist/index.js +701 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/memory/consolidation.d.ts +51 -0
  52. package/dist/memory/consolidation.js +122 -0
  53. package/dist/memory/consolidation.js.map +1 -0
  54. package/dist/memory/ncd.d.ts +40 -0
  55. package/dist/memory/ncd.js +90 -0
  56. package/dist/memory/ncd.js.map +1 -0
  57. package/dist/memory/sm2.d.ts +44 -0
  58. package/dist/memory/sm2.js +119 -0
  59. package/dist/memory/sm2.js.map +1 -0
  60. package/dist/memory/tiers.d.ts +49 -0
  61. package/dist/memory/tiers.js +145 -0
  62. package/dist/memory/tiers.js.map +1 -0
  63. package/dist/server.d.ts +6 -0
  64. package/dist/server.js +6 -0
  65. package/dist/server.js.map +1 -0
  66. package/dist/trust/ingestion.d.ts +38 -0
  67. package/dist/trust/ingestion.js +147 -0
  68. package/dist/trust/ingestion.js.map +1 -0
  69. package/dist/trust/patterns.d.ts +26 -0
  70. package/dist/trust/patterns.js +78 -0
  71. package/dist/trust/patterns.js.map +1 -0
  72. package/dist/trust/scoring.d.ts +39 -0
  73. package/dist/trust/scoring.js +206 -0
  74. package/dist/trust/scoring.js.map +1 -0
  75. package/package.json +58 -0
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Knowledge Graph — Entity CRUD + Recursive CTE Traversal
3
+ *
4
+ * Edge-table pattern with SQLite recursive CTEs.
5
+ * Performance: 10K edges <50ms, 100K 50-500ms.
6
+ * ALWAYS ≤3 hop depth limit.
7
+ */
8
+ import { getDb } from '../db/index.js';
9
+ // --- Entity CRUD ---
10
+ export function upsertEntity(name, entityType, properties = {}, tier = 'working', importance = 0.5) {
11
+ const db = getDb();
12
+ const propsJson = JSON.stringify(properties);
13
+ db.prepare(`INSERT INTO kg_entities (name, entity_type, properties, tier, importance)
14
+ VALUES (?, ?, ?, ?, ?)
15
+ ON CONFLICT(name, entity_type) DO UPDATE SET
16
+ properties = json_patch(properties, excluded.properties),
17
+ importance = MAX(importance, excluded.importance),
18
+ last_accessed = datetime('now'),
19
+ access_count = access_count + 1`)
20
+ .run(name, entityType, propsJson, tier, importance);
21
+ return db.prepare('SELECT id FROM kg_entities WHERE name = ? AND entity_type = ?').get(name, entityType).id;
22
+ }
23
+ export function getEntity(name, entityType) {
24
+ const db = getDb();
25
+ const row = db.prepare('SELECT * FROM kg_entities WHERE name = ? AND entity_type = ?').get(name, entityType);
26
+ if (!row)
27
+ return null;
28
+ // Touch access count
29
+ db.prepare('UPDATE kg_entities SET access_count = access_count + 1, last_accessed = datetime(\'now\') WHERE id = ?').run(row.id);
30
+ return rowToEntity(row);
31
+ }
32
+ export function getEntityById(id) {
33
+ const db = getDb();
34
+ const row = db.prepare('SELECT * FROM kg_entities WHERE id = ?').get(id);
35
+ return row ? rowToEntity(row) : null;
36
+ }
37
+ export function searchEntities(query, limit = 20) {
38
+ const db = getDb();
39
+ const rows = db.prepare(`SELECT * FROM kg_entities
40
+ WHERE name LIKE ? OR entity_type LIKE ?
41
+ ORDER BY importance DESC, access_count DESC LIMIT ?`)
42
+ .all(`%${query}%`, `%${query}%`, limit);
43
+ return rows.map(rowToEntity);
44
+ }
45
+ export function getEntitiesByTier(tier) {
46
+ const db = getDb();
47
+ const rows = db.prepare('SELECT * FROM kg_entities WHERE tier = ? ORDER BY importance DESC')
48
+ .all(tier);
49
+ return rows.map(rowToEntity);
50
+ }
51
+ // --- Edge CRUD ---
52
+ export function upsertEdge(sourceId, targetId, relationType, weight = 1.0, properties = {}) {
53
+ const db = getDb();
54
+ db.prepare(`INSERT INTO kg_edges (source_id, target_id, relation_type, weight, properties)
55
+ VALUES (?, ?, ?, ?, ?)
56
+ ON CONFLICT(source_id, target_id, relation_type) DO UPDATE SET
57
+ weight = MAX(weight, excluded.weight),
58
+ activation_count = activation_count + 1,
59
+ last_activated = datetime('now')`)
60
+ .run(sourceId, targetId, relationType, weight, JSON.stringify(properties));
61
+ return db.prepare('SELECT id FROM kg_edges WHERE source_id = ? AND target_id = ? AND relation_type = ?')
62
+ .get(sourceId, targetId, relationType).id;
63
+ }
64
+ export function getEdgesFrom(entityId) {
65
+ const db = getDb();
66
+ const rows = db.prepare('SELECT * FROM kg_edges WHERE source_id = ? ORDER BY weight DESC')
67
+ .all(entityId);
68
+ return rows.map(rowToEdge);
69
+ }
70
+ export function getEdgesTo(entityId) {
71
+ const db = getDb();
72
+ const rows = db.prepare('SELECT * FROM kg_edges WHERE target_id = ? ORDER BY weight DESC')
73
+ .all(entityId);
74
+ return rows.map(rowToEdge);
75
+ }
76
+ // --- Graph Traversal ---
77
+ /**
78
+ * Traverse the graph from a starting entity using recursive CTE.
79
+ * ALWAYS bounded to maxHops ≤ 3.
80
+ */
81
+ export function traverse(startId, maxHops = 2, minWeight = 0.0, relationFilter) {
82
+ const db = getDb();
83
+ const hops = Math.min(maxHops, 3); // HARD LIMIT
84
+ const startEntity = db.prepare('SELECT name FROM kg_entities WHERE id = ?').get(startId);
85
+ if (!startEntity)
86
+ return [];
87
+ let relationClause = '';
88
+ const params = [startId, startEntity.name, hops, minWeight];
89
+ if (relationFilter) {
90
+ relationClause = 'AND e.relation_type = ?';
91
+ params.push(relationFilter);
92
+ }
93
+ const sql = `
94
+ WITH RECURSIVE graph_walk(entity_id, depth, path, visited) AS (
95
+ SELECT ?, 0, ?, ',' || CAST(? AS TEXT) || ','
96
+ UNION ALL
97
+ SELECT e.target_id, gw.depth + 1,
98
+ gw.path || ' -[' || e.relation_type || ']-> ' || tgt.name,
99
+ gw.visited || CAST(e.target_id AS TEXT) || ','
100
+ FROM graph_walk gw
101
+ JOIN kg_edges e ON e.source_id = gw.entity_id
102
+ JOIN kg_entities tgt ON tgt.id = e.target_id
103
+ WHERE gw.depth < ?
104
+ AND e.weight >= ?
105
+ AND gw.visited NOT LIKE '%,' || CAST(e.target_id AS TEXT) || ',%'
106
+ ${relationClause}
107
+ )
108
+ SELECT DISTINCT
109
+ ent.*, gw.depth, gw.path
110
+ FROM graph_walk gw
111
+ JOIN kg_entities ent ON ent.id = gw.entity_id
112
+ WHERE gw.depth > 0
113
+ ORDER BY gw.depth, ent.importance DESC`;
114
+ // Fix params order: startId, startName, startId (for visited), hops, minWeight, [relationFilter]
115
+ const queryParams = [startId, startEntity.name, startId, hops, minWeight];
116
+ if (relationFilter)
117
+ queryParams.push(relationFilter);
118
+ const rows = db.prepare(sql).all(...queryParams);
119
+ // Increment activation counts for traversed edges
120
+ db.prepare(`UPDATE kg_edges SET activation_count = activation_count + 1, last_activated = datetime('now')
121
+ WHERE source_id = ?`).run(startId);
122
+ return rows.map((row) => ({
123
+ entity: rowToEntity(row),
124
+ depth: row.depth,
125
+ path: row.path.split(' -> '),
126
+ edgeType: '',
127
+ }));
128
+ }
129
+ /**
130
+ * Find orphan entities (no incoming or outgoing edges).
131
+ */
132
+ export function findOrphans() {
133
+ const db = getDb();
134
+ const rows = db.prepare(`SELECT e.* FROM kg_entities e
135
+ WHERE NOT EXISTS (SELECT 1 FROM kg_edges WHERE source_id = e.id)
136
+ AND NOT EXISTS (SELECT 1 FROM kg_edges WHERE target_id = e.id)`)
137
+ .all();
138
+ return rows.map(rowToEntity);
139
+ }
140
+ /**
141
+ * Get graph statistics.
142
+ */
143
+ export function getGraphStats() {
144
+ const db = getDb();
145
+ const entityCount = db.prepare('SELECT COUNT(*) as n FROM kg_entities').get().n;
146
+ const edgeCount = db.prepare('SELECT COUNT(*) as n FROM kg_edges').get().n;
147
+ const avgDegree = entityCount > 0 ? (2 * edgeCount) / entityCount : 0;
148
+ const tierRows = db.prepare('SELECT tier, COUNT(*) as n FROM kg_entities GROUP BY tier').all();
149
+ const tierCounts = {};
150
+ for (const row of tierRows)
151
+ tierCounts[row.tier] = row.n;
152
+ const communityCounts = db.prepare('SELECT COUNT(DISTINCT community_id) as n FROM kg_entities WHERE community_id IS NOT NULL').get().n;
153
+ const orphanCount = db.prepare(`SELECT COUNT(*) as n FROM kg_entities e
154
+ WHERE NOT EXISTS (SELECT 1 FROM kg_edges WHERE source_id = e.id)
155
+ AND NOT EXISTS (SELECT 1 FROM kg_edges WHERE target_id = e.id)`).get().n;
156
+ return { entityCount, edgeCount, avgDegree, tierCounts, communityCounts, orphanCount };
157
+ }
158
+ // --- Helpers ---
159
+ function rowToEntity(row) {
160
+ return {
161
+ id: row.id,
162
+ name: row.name,
163
+ entityType: row.entity_type,
164
+ properties: JSON.parse(row.properties || '{}'),
165
+ communityId: row.community_id,
166
+ betweenness: row.betweenness,
167
+ tier: row.tier,
168
+ accessCount: row.access_count,
169
+ importance: row.importance,
170
+ lastAccessed: row.last_accessed,
171
+ createdAt: row.created_at,
172
+ };
173
+ }
174
+ function rowToEdge(row) {
175
+ return {
176
+ id: row.id,
177
+ sourceId: row.source_id,
178
+ targetId: row.target_id,
179
+ relationType: row.relation_type,
180
+ weight: row.weight,
181
+ properties: JSON.parse(row.properties || '{}'),
182
+ activationCount: row.activation_count,
183
+ lastActivated: row.last_activated,
184
+ createdAt: row.created_at,
185
+ };
186
+ }
187
+ //# sourceMappingURL=entities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entities.js","sourceRoot":"","sources":["../../src/graph/entities.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Advanced Graph Queries
3
+ *
4
+ * Includes the "money query" (hybrid vector + graph + FTS),
5
+ * bridge detection, and community-boundary analysis.
6
+ */
7
+ /**
8
+ * Find entities that bridge two communities (high betweenness).
9
+ * These are the most valuable for cross-domain reasoning.
10
+ */
11
+ export declare function findBridgeEntities(minBetweenness?: number, limit?: number): any[];
12
+ /**
13
+ * Find entities with high degree (potential hubs).
14
+ * Guards against hub-and-spoke collapse with max edge alert.
15
+ */
16
+ export declare function findHubs(maxEdges?: number): {
17
+ hubs: any[];
18
+ overconnected: any[];
19
+ };
20
+ /**
21
+ * Find entities that are semantically similar but topologically distant.
22
+ * These are Luhmann's "surprises" — the most valuable latent connections.
23
+ * (Requires embedding data — returns candidates for LLM analysis)
24
+ */
25
+ export declare function findLatentBridgeCandidates(minHops?: number): any[];
26
+ /**
27
+ * Compute structural entropy H_SI = -Σ(d_v/2m) × log2(d_v/2m)
28
+ * Fast proxy for graph complexity — O(n).
29
+ */
30
+ export declare function computeStructuralEntropy(): {
31
+ entropy: number;
32
+ avgDegree: number;
33
+ giantComponentFraction: number;
34
+ };
35
+ /**
36
+ * Check phase transition indicators.
37
+ * Pre-threshold → maximize breadth. Post-threshold → exploit structure.
38
+ */
39
+ export declare function checkPhaseTransition(): {
40
+ phase: 'pre_percolation' | 'near_threshold' | 'post_percolation';
41
+ indicators: Record<string, number>;
42
+ recommendation: string;
43
+ };
44
+ /**
45
+ * Find contradictions in the graph — edges where both 'supports' and 'contradicts' exist.
46
+ */
47
+ export declare function findContradictions(): any[];
48
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Advanced Graph Queries
3
+ *
4
+ * Includes the "money query" (hybrid vector + graph + FTS),
5
+ * bridge detection, and community-boundary analysis.
6
+ */
7
+ import { getDb } from '../db/index.js';
8
+ /**
9
+ * Find entities that bridge two communities (high betweenness).
10
+ * These are the most valuable for cross-domain reasoning.
11
+ */
12
+ export function findBridgeEntities(minBetweenness = 0.1, limit = 10) {
13
+ const db = getDb();
14
+ return db.prepare(`SELECT e.*, COUNT(DISTINCT e2.community_id) as communities_bridged
15
+ FROM kg_entities e
16
+ JOIN kg_edges ed ON ed.source_id = e.id
17
+ JOIN kg_entities e2 ON e2.id = ed.target_id
18
+ WHERE e.betweenness >= ?
19
+ AND e.community_id IS NOT NULL
20
+ AND e2.community_id IS NOT NULL
21
+ AND e.community_id != e2.community_id
22
+ GROUP BY e.id
23
+ ORDER BY e.betweenness DESC
24
+ LIMIT ?`)
25
+ .all(minBetweenness, limit);
26
+ }
27
+ /**
28
+ * Find entities with high degree (potential hubs).
29
+ * Guards against hub-and-spoke collapse with max edge alert.
30
+ */
31
+ export function findHubs(maxEdges = 50) {
32
+ const db = getDb();
33
+ const hubs = db.prepare(`SELECT e.id, e.name, e.entity_type, e.tier,
34
+ (SELECT COUNT(*) FROM kg_edges WHERE source_id = e.id) +
35
+ (SELECT COUNT(*) FROM kg_edges WHERE target_id = e.id) as degree
36
+ FROM kg_entities e
37
+ ORDER BY degree DESC LIMIT 20`)
38
+ .all();
39
+ const overconnected = hubs.filter(h => h.degree > maxEdges);
40
+ return { hubs, overconnected };
41
+ }
42
+ /**
43
+ * Find entities that are semantically similar but topologically distant.
44
+ * These are Luhmann's "surprises" — the most valuable latent connections.
45
+ * (Requires embedding data — returns candidates for LLM analysis)
46
+ */
47
+ export function findLatentBridgeCandidates(minHops = 4) {
48
+ const db = getDb();
49
+ // Find pairs with no short path between them
50
+ // This is approximate — full shortest path on all pairs is too expensive
51
+ // Instead, find entities in different communities with no direct edges
52
+ return db.prepare(`SELECT
53
+ e1.id as entity1_id, e1.name as entity1_name, e1.entity_type as entity1_type,
54
+ e2.id as entity2_id, e2.name as entity2_name, e2.entity_type as entity2_type,
55
+ e1.community_id as community1, e2.community_id as community2
56
+ FROM kg_entities e1
57
+ JOIN kg_entities e2 ON e1.id < e2.id
58
+ WHERE e1.community_id IS NOT NULL
59
+ AND e2.community_id IS NOT NULL
60
+ AND e1.community_id != e2.community_id
61
+ AND e1.tier IN ('working', 'core')
62
+ AND e2.tier IN ('working', 'core')
63
+ AND NOT EXISTS (
64
+ SELECT 1 FROM kg_edges
65
+ WHERE (source_id = e1.id AND target_id = e2.id)
66
+ OR (source_id = e2.id AND target_id = e1.id)
67
+ )
68
+ ORDER BY e1.importance + e2.importance DESC
69
+ LIMIT 20`)
70
+ .all();
71
+ }
72
+ /**
73
+ * Compute structural entropy H_SI = -Σ(d_v/2m) × log2(d_v/2m)
74
+ * Fast proxy for graph complexity — O(n).
75
+ */
76
+ export function computeStructuralEntropy() {
77
+ const db = getDb();
78
+ const entityCount = db.prepare('SELECT COUNT(*) as n FROM kg_entities').get().n;
79
+ const edgeCount = db.prepare('SELECT COUNT(*) as n FROM kg_edges').get().n;
80
+ if (entityCount === 0 || edgeCount === 0) {
81
+ return { entropy: 0, avgDegree: 0, giantComponentFraction: 0 };
82
+ }
83
+ const m2 = 2 * edgeCount; // sum of degrees
84
+ const avgDegree = m2 / entityCount;
85
+ // Get degree distribution
86
+ const degrees = db.prepare(`SELECT
87
+ (SELECT COUNT(*) FROM kg_edges WHERE source_id = e.id) +
88
+ (SELECT COUNT(*) FROM kg_edges WHERE target_id = e.id) as degree
89
+ FROM kg_entities e`)
90
+ .all();
91
+ // H_SI = -Σ(d_v/2m) × log2(d_v/2m)
92
+ let entropy = 0;
93
+ for (const { degree } of degrees) {
94
+ if (degree > 0) {
95
+ const p = degree / m2;
96
+ entropy -= p * Math.log2(p);
97
+ }
98
+ }
99
+ // Giant component fraction — approximate via BFS from highest-degree node
100
+ const giantComponentFraction = estimateGiantComponentFraction(db, entityCount);
101
+ return { entropy, avgDegree, giantComponentFraction };
102
+ }
103
+ /**
104
+ * Approximate giant component fraction by BFS from the highest-degree node.
105
+ */
106
+ function estimateGiantComponentFraction(db, totalNodes) {
107
+ if (totalNodes === 0)
108
+ return 0;
109
+ // Start from highest-degree node
110
+ const start = db.prepare(`SELECT e.id,
111
+ (SELECT COUNT(*) FROM kg_edges WHERE source_id = e.id) +
112
+ (SELECT COUNT(*) FROM kg_edges WHERE target_id = e.id) as degree
113
+ FROM kg_entities e ORDER BY degree DESC LIMIT 1`).get();
114
+ if (!start)
115
+ return 0;
116
+ // BFS via recursive CTE — UNION deduplicates automatically (no self-reference needed)
117
+ const reachable = db.prepare(`WITH RECURSIVE component(id) AS (
118
+ SELECT ?
119
+ UNION
120
+ SELECT e.target_id FROM component c JOIN kg_edges e ON e.source_id = c.id
121
+ UNION
122
+ SELECT e.source_id FROM component c JOIN kg_edges e ON e.target_id = c.id
123
+ )
124
+ SELECT COUNT(*) as n FROM component`)
125
+ .get(start.id);
126
+ return reachable.n / totalNodes;
127
+ }
128
+ /**
129
+ * Check phase transition indicators.
130
+ * Pre-threshold → maximize breadth. Post-threshold → exploit structure.
131
+ */
132
+ export function checkPhaseTransition() {
133
+ const { entropy, avgDegree, giantComponentFraction } = computeStructuralEntropy();
134
+ const indicators = {
135
+ avgDegree,
136
+ giantComponentFraction,
137
+ entropy,
138
+ };
139
+ if (avgDegree < 0.8 || giantComponentFraction < 0.3) {
140
+ return {
141
+ phase: 'pre_percolation',
142
+ indicators,
143
+ recommendation: 'Graph is sparse. Maximize breadth — every new edge moves toward criticality. Focus on exploration.',
144
+ };
145
+ }
146
+ if (avgDegree >= 0.8 && avgDegree <= 1.5 && giantComponentFraction >= 0.3 && giantComponentFraction <= 0.7) {
147
+ return {
148
+ phase: 'near_threshold',
149
+ indicators,
150
+ recommendation: 'Near percolation threshold! Adjacent possible growing combinatorially. Balance exploration and exploitation.',
151
+ };
152
+ }
153
+ return {
154
+ phase: 'post_percolation',
155
+ indicators,
156
+ recommendation: 'Post-percolation. Exploit structure — target community-boundary contradictions as research frontiers.',
157
+ };
158
+ }
159
+ /**
160
+ * Find contradictions in the graph — edges where both 'supports' and 'contradicts' exist.
161
+ */
162
+ export function findContradictions() {
163
+ const db = getDb();
164
+ return db.prepare(`SELECT
165
+ e1.source_id, s.name as source_name,
166
+ e1.target_id, t.name as target_name,
167
+ e1.relation_type as rel1, e1.weight as w1,
168
+ e2.relation_type as rel2, e2.weight as w2
169
+ FROM kg_edges e1
170
+ JOIN kg_edges e2 ON e1.source_id = e2.source_id AND e1.target_id = e2.target_id
171
+ JOIN kg_entities s ON s.id = e1.source_id
172
+ JOIN kg_entities t ON t.id = e1.target_id
173
+ WHERE e1.relation_type = 'supports' AND e2.relation_type = 'contradicts'`)
174
+ .all();
175
+ }
176
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/graph/queries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Dashboard — ANSI output for cascade monitoring
3
+ *
4
+ * Plain ANSI header (metrics/phase) + scrolling stdout (NDJSON with --stream-json).
5
+ * NO TUIs (crash in tmux/SSH). Optional --tui flag for future.
6
+ *
7
+ * Quality review without reading everything:
8
+ * 4 metrics at round boundaries + 3-sentence LLM summary + identified gaps
9
+ */
10
+ export interface DashboardData {
11
+ cascade: {
12
+ id: string;
13
+ question: string;
14
+ status: string;
15
+ round: number;
16
+ maxRounds: number;
17
+ };
18
+ quality: {
19
+ coverage: number;
20
+ depth: number;
21
+ confidence: number;
22
+ sourceQuality: number;
23
+ };
24
+ counts: {
25
+ findings: number;
26
+ quarantined: number;
27
+ hypotheses: number;
28
+ entities: number;
29
+ edges: number;
30
+ };
31
+ tokens: {
32
+ used: number;
33
+ budget: number;
34
+ };
35
+ explorationBudget: number;
36
+ pendingSteers: number;
37
+ interventions: string[];
38
+ }
39
+ /**
40
+ * Generate a compact ANSI dashboard string.
41
+ */
42
+ export declare function renderDashboard(data: DashboardData): string;
43
+ /**
44
+ * Build dashboard data from database state.
45
+ */
46
+ export declare function buildDashboardData(cascadeId: string): DashboardData | null;
47
+ /**
48
+ * Format a cascade status as NDJSON for streaming output.
49
+ */
50
+ export declare function toNDJSON(data: DashboardData): string;
51
+ //# sourceMappingURL=dashboard.d.ts.map
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Dashboard — ANSI output for cascade monitoring
3
+ *
4
+ * Plain ANSI header (metrics/phase) + scrolling stdout (NDJSON with --stream-json).
5
+ * NO TUIs (crash in tmux/SSH). Optional --tui flag for future.
6
+ *
7
+ * Quality review without reading everything:
8
+ * 4 metrics at round boundaries + 3-sentence LLM summary + identified gaps
9
+ */
10
+ import { getDb } from '../db/index.js';
11
+ // ANSI escape codes
12
+ const BOLD = '\x1b[1m';
13
+ const DIM = '\x1b[2m';
14
+ const GREEN = '\x1b[32m';
15
+ const YELLOW = '\x1b[33m';
16
+ const RED = '\x1b[31m';
17
+ const CYAN = '\x1b[36m';
18
+ const RESET = '\x1b[0m';
19
+ /**
20
+ * Generate a compact ANSI dashboard string.
21
+ */
22
+ export function renderDashboard(data) {
23
+ const lines = [];
24
+ // Header
25
+ lines.push(`${BOLD}${CYAN}═══ Research Cascade Dashboard ═══${RESET}`);
26
+ lines.push(`${BOLD}Q:${RESET} ${data.cascade.question.slice(0, 80)}`);
27
+ lines.push(`${BOLD}ID:${RESET} ${data.cascade.id} ${BOLD}Status:${RESET} ${colorStatus(data.cascade.status)} ${BOLD}Round:${RESET} ${data.cascade.round}/${data.cascade.maxRounds}`);
28
+ lines.push('');
29
+ // Quality metrics bar
30
+ lines.push(`${BOLD}Quality:${RESET}`);
31
+ lines.push(` Coverage: ${progressBar(data.quality.coverage, 20)} ${(data.quality.coverage * 100).toFixed(0)}%`);
32
+ lines.push(` Depth: ${progressBar(data.quality.depth, 20)} ${(data.quality.depth * 100).toFixed(0)}%`);
33
+ lines.push(` Confidence: ${progressBar(data.quality.confidence, 20)} ${(data.quality.confidence * 100).toFixed(0)}%`);
34
+ lines.push(` Source: ${progressBar(data.quality.sourceQuality, 20)} ${(data.quality.sourceQuality * 100).toFixed(0)}%`);
35
+ lines.push('');
36
+ // Counts
37
+ lines.push(`${BOLD}Counts:${RESET} ${data.counts.findings} findings | ${data.counts.quarantined} quarantined | ${data.counts.hypotheses} hypotheses | ${data.counts.entities} entities | ${data.counts.edges} edges`);
38
+ // Budget
39
+ const tokenPct = data.tokens.budget > 0 ? data.tokens.used / data.tokens.budget : 0;
40
+ lines.push(`${BOLD}Tokens:${RESET} ${progressBar(tokenPct, 20)} ${data.tokens.used.toLocaleString()}/${data.tokens.budget.toLocaleString()}`);
41
+ lines.push(`${BOLD}Explore/Exploit:${RESET} ${(data.explorationBudget * 100).toFixed(0)}% exploration`);
42
+ // Alerts
43
+ if (data.pendingSteers > 0) {
44
+ lines.push(`${YELLOW}${BOLD}⚠ ${data.pendingSteers} pending steer events${RESET}`);
45
+ }
46
+ if (data.interventions.length > 0) {
47
+ lines.push(`${RED}${BOLD}! ${data.interventions.length} interventions:${RESET}`);
48
+ for (const i of data.interventions.slice(0, 3)) {
49
+ lines.push(` ${RED}${i}${RESET}`);
50
+ }
51
+ }
52
+ lines.push(`${DIM}${CYAN}═══════════════════════════════════${RESET}`);
53
+ return lines.join('\n');
54
+ }
55
+ /**
56
+ * Build dashboard data from database state.
57
+ */
58
+ export function buildDashboardData(cascadeId) {
59
+ const db = getDb();
60
+ const cascade = db.prepare('SELECT * FROM cascades WHERE id = ?').get(cascadeId);
61
+ if (!cascade)
62
+ return null;
63
+ const findingsCount = db.prepare('SELECT COUNT(*) as n FROM findings WHERE cascade_id = ? AND quarantined = 0').get(cascadeId).n;
64
+ const quarantinedCount = db.prepare('SELECT COUNT(*) as n FROM findings WHERE cascade_id = ? AND quarantined = 1').get(cascadeId).n;
65
+ const hypothesesCount = db.prepare('SELECT COUNT(*) as n FROM hypotheses WHERE cascade_id = ?').get(cascadeId).n;
66
+ const entityCount = db.prepare('SELECT COUNT(*) as n FROM kg_entities').get().n;
67
+ const edgeCount = db.prepare('SELECT COUNT(*) as n FROM kg_edges').get().n;
68
+ const pendingSteers = db.prepare('SELECT COUNT(*) as n FROM steer_events WHERE cascade_id = ? AND applied = 0').get(cascadeId).n;
69
+ // Calculate quality metrics
70
+ const plan = cascade.plan_json ? JSON.parse(cascade.plan_json) : null;
71
+ const totalQuestions = plan?.questions?.length || 1;
72
+ const avgConf = db.prepare('SELECT AVG(confidence) as v FROM findings WHERE cascade_id = ? AND quarantined = 0').get(cascadeId)?.v || 0;
73
+ const avgTrust = db.prepare('SELECT AVG(trust_composite) as v FROM findings WHERE cascade_id = ? AND quarantined = 0').get(cascadeId)?.v || 0.5;
74
+ return {
75
+ cascade: {
76
+ id: cascadeId,
77
+ question: cascade.question,
78
+ status: cascade.status,
79
+ round: cascade.current_round,
80
+ maxRounds: cascade.max_rounds,
81
+ },
82
+ quality: {
83
+ coverage: Math.min(1, findingsCount / (totalQuestions * 3)),
84
+ depth: Math.min(1, findingsCount / (totalQuestions * 10)),
85
+ confidence: avgConf,
86
+ sourceQuality: avgTrust,
87
+ },
88
+ counts: {
89
+ findings: findingsCount,
90
+ quarantined: quarantinedCount,
91
+ hypotheses: hypothesesCount,
92
+ entities: entityCount,
93
+ edges: edgeCount,
94
+ },
95
+ tokens: { used: cascade.tokens_used, budget: cascade.token_budget },
96
+ explorationBudget: Math.max(0, 1 - cascade.current_round / cascade.max_rounds),
97
+ pendingSteers,
98
+ interventions: [],
99
+ };
100
+ }
101
+ /**
102
+ * Render a simple ASCII progress bar.
103
+ */
104
+ function progressBar(ratio, width) {
105
+ const clamped = Math.max(0, Math.min(1, ratio));
106
+ const filled = Math.round(clamped * width);
107
+ const empty = width - filled;
108
+ const color = clamped >= 0.7 ? GREEN : clamped >= 0.4 ? YELLOW : RED;
109
+ return `${color}${'█'.repeat(filled)}${DIM}${'░'.repeat(empty)}${RESET}`;
110
+ }
111
+ /**
112
+ * Color status text based on state.
113
+ */
114
+ function colorStatus(status) {
115
+ switch (status) {
116
+ case 'planning': return `${CYAN}${status}${RESET}`;
117
+ case 'investigating': return `${GREEN}${status}${RESET}`;
118
+ case 'validating': return `${YELLOW}${status}${RESET}`;
119
+ case 'synthesizing': return `${GREEN}${status}${RESET}`;
120
+ case 'complete': return `${GREEN}${BOLD}${status}${RESET}`;
121
+ case 'stalled': return `${RED}${BOLD}${status}${RESET}`;
122
+ default: return status;
123
+ }
124
+ }
125
+ /**
126
+ * Format a cascade status as NDJSON for streaming output.
127
+ */
128
+ export function toNDJSON(data) {
129
+ return JSON.stringify({
130
+ type: 'cascade_status',
131
+ timestamp: new Date().toISOString(),
132
+ ...data,
133
+ });
134
+ }
135
+ //# sourceMappingURL=dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../../src/hitl/dashboard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * HITL Intervention Taxonomy
3
+ *
4
+ * BLOCKING: Round 0 hypothesis (always), hypothesis drift >0.6, round boundaries (15min timeout)
5
+ * ADVISORY: trust <0.4 (2min), circuit breaker open (1min), confidence <0.5 (3min)
6
+ * SILENT: search planning (log only)
7
+ *
8
+ * Each intervention point has a timeout — if no human response, auto-proceeds.
9
+ */
10
+ export type InterventionLevel = 'blocking' | 'advisory' | 'silent';
11
+ export interface Intervention {
12
+ id: string;
13
+ cascadeId: string;
14
+ level: InterventionLevel;
15
+ category: string;
16
+ description: string;
17
+ context: Record<string, any>;
18
+ timeoutMinutes: number;
19
+ createdAt: string;
20
+ resolvedAt?: string;
21
+ resolution?: 'approved' | 'rejected' | 'timeout' | 'redirected';
22
+ humanComment?: string;
23
+ }
24
+ /**
25
+ * Check all intervention rules and return any that are triggered.
26
+ */
27
+ export declare function checkInterventions(cascadeId: string, context?: any): Intervention[];
28
+ /**
29
+ * Check if there are any blocking interventions that must be resolved.
30
+ */
31
+ export declare function hasBlockingInterventions(cascadeId: string): boolean;
32
+ /**
33
+ * Format interventions for display.
34
+ */
35
+ export declare function formatInterventions(interventions: Intervention[]): string;
36
+ //# sourceMappingURL=interventions.d.ts.map