@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,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":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAmCvC,sBAAsB;AAEtB,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,UAAkB,EAClB,aAAkC,EAAE,EACpC,OAAuB,SAAS,EAChC,aAAqB,GAAG;IAExB,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAE7C,EAAE,CAAC,OAAO,CAAC;;;;;;sCAMyB,CAAC;SAClC,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAEtD,OAAQ,EAAE,CAAC,OAAO,CAAC,+DAA+D,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAS,CAAC,EAAE,CAAC;AACvH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,UAAkB;IACxD,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,8DAA8D,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAQ,CAAC;IACpH,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,qBAAqB;IACrB,EAAE,CAAC,OAAO,CAAC,wGAAwG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEjI,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAQ,CAAC;IAChF,OAAO,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,QAAgB,EAAE;IAC9D,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;wDAE8B,CAAC;SACpD,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE,IAAI,KAAK,GAAG,EAAE,KAAK,CAAU,CAAC;IAEnD,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAoB;IACpD,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,mEAAmE,CAAC;SACzF,GAAG,CAAC,IAAI,CAAU,CAAC;IACtB,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC/B,CAAC;AAED,oBAAoB;AAEpB,MAAM,UAAU,UAAU,CACxB,QAAgB,EAChB,QAAgB,EAChB,YAAoB,EACpB,SAAiB,GAAG,EACpB,aAAkC,EAAE;IAEpC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IAEnB,EAAE,CAAC,OAAO,CAAC;;;;;uCAK0B,CAAC;SACnC,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAE7E,OAAQ,EAAE,CAAC,OAAO,CAAC,qFAAqF,CAAC;SACtG,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,CAAS,CAAC,EAAE,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,iEAAiE,CAAC;SACvF,GAAG,CAAC,QAAQ,CAAU,CAAC;IAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,iEAAiE,CAAC;SACvF,GAAG,CAAC,QAAQ,CAAU,CAAC;IAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AAC7B,CAAC;AAED,0BAA0B;AAE1B;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACtB,OAAe,EACf,UAAkB,CAAC,EACnB,YAAoB,GAAG,EACvB,cAAuB;IAEvB,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa;IAEhD,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC,GAAG,CAAC,OAAO,CAAQ,CAAC;IAChG,IAAI,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAE5B,IAAI,cAAc,GAAG,EAAE,CAAC;IACxB,MAAM,MAAM,GAAU,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAEnE,IAAI,cAAc,EAAE,CAAC;QACnB,cAAc,GAAG,yBAAyB,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,GAAG,GAAG;;;;;;;;;;;;;UAaJ,cAAc;;;;;;;2CAOmB,CAAC;IAE1C,iGAAiG;IACjG,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAC1E,IAAI,cAAc;QAAE,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAErD,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,WAAW,CAAU,CAAC;IAE1D,kDAAkD;IAClD,EAAE,CAAC,OAAO,CAAC;wBACW,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAErC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC;QAC7B,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC;QACxB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAC5B,QAAQ,EAAE,EAAE;KACb,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;mEAEyC,CAAC;SAC/D,GAAG,EAAW,CAAC;IAClB,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAQ3B,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IAEnB,MAAM,WAAW,GAAI,EAAE,CAAC,OAAO,CAAC,uCAAuC,CAAC,CAAC,GAAG,EAAU,CAAC,CAAC,CAAC;IACzF,MAAM,SAAS,GAAI,EAAE,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,GAAG,EAAU,CAAC,CAAC,CAAC;IACpF,MAAM,SAAS,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtE,MAAM,QAAQ,GAAG,EAAE,CAAC,OAAO,CAAC,2DAA2D,CAAC,CAAC,GAAG,EAAW,CAAC;IACxG,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,KAAK,MAAM,GAAG,IAAI,QAAQ;QAAE,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAEzD,MAAM,eAAe,GAAI,EAAE,CAAC,OAAO,CAAC,0FAA0F,CAAC,CAAC,GAAG,EAAU,CAAC,CAAC,CAAC;IAChJ,MAAM,WAAW,GAAI,EAAE,CAAC,OAAO,CAAC;;mEAEiC,CAAC,CAAC,GAAG,EAAU,CAAC,CAAC,CAAC;IAEnF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,CAAC;AACzF,CAAC;AAED,kBAAkB;AAElB,SAAS,WAAW,CAAC,GAAQ;IAC3B,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,UAAU,EAAE,GAAG,CAAC,WAAW;QAC3B,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC;QAC9C,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,IAAI,EAAE,GAAG,CAAC,IAAI;QACd,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,YAAY,EAAE,GAAG,CAAC,aAAa;QAC/B,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,GAAQ;IACzB,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,YAAY,EAAE,GAAG,CAAC,aAAa;QAC/B,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC;QAC9C,eAAe,EAAE,GAAG,CAAC,gBAAgB;QACrC,aAAa,EAAE,GAAG,CAAC,cAAc;QACjC,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC"}
|
|
@@ -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
|