' + lanes.map(lane =>
@@ -513,10 +517,11 @@ function renderControlPaneHtml() {
const branch = item.branch || (item.metadata && item.metadata.branch) || '';
const mergeGate = item.mergeGate || (item.metadata && item.metadata.mergeGate) || '';
const blocker = item.blocker || (item.metadata && item.metadata.blocker) || '';
- const owner = item.owner || item.source || 'unassigned';
+ const assigneeKind = item.assigneeKind || 'unassigned';
+ const owner = item.assignee || item.owner || (assigneeKind === 'unassigned' ? 'unassigned (JIT)' : item.source) || 'unassigned';
return '
' +
'
' + escapeHtml(item.title || item.id) + '' + statePill(item.kanbanState || item.status) + '
' +
- '
' + escapeHtml(owner) + ' - ' + escapeHtml(item.source || 'manual') + (item.priority ? ' - ' + escapeHtml(item.priority) : '') + '
' +
+ '
[' + escapeHtml(assigneeKind) + '] ' + escapeHtml(owner) + ' - ' + escapeHtml(item.source || 'manual') + (item.priority ? ' - ' + escapeHtml(item.priority) : '') + '
' +
(branch ? '
branch: ' + escapeHtml(branch) + '
' : '') +
(mergeGate ? '
merge gate: ' + escapeHtml(mergeGate) + '
' : '') +
(blocker ? '
blocker: ' + escapeHtml(blocker) + '
' : '') +
@@ -629,5 +634,5 @@ function renderControlPaneHtml() {
}
module.exports = {
- renderControlPaneHtml,
+ renderControlPaneHtml
};
diff --git a/tests/lib/control-pane-state.test.js b/tests/lib/control-pane-state.test.js
index 642b34fa..df86b7ba 100644
--- a/tests/lib/control-pane-state.test.js
+++ b/tests/lib/control-pane-state.test.js
@@ -9,11 +9,7 @@ const path = require('path');
const initSqlJs = require('sql.js');
-const {
- buildControlPaneSnapshot,
- recallKnowledgeEntries,
- resolveControlPaneConfig,
-} = require('../../scripts/lib/control-pane/state');
+const { buildControlPaneSnapshot, recallKnowledgeEntries, resolveControlPaneConfig } = require('../../scripts/lib/control-pane/state');
async function test(name, fn) {
try {
@@ -138,7 +134,7 @@ async function writeSampleEcc2Database(dbPath) {
0.42,
'2026-06-03T10:00:00Z',
'2026-06-03T10:15:00Z',
- '2026-06-03T10:15:00Z',
+ '2026-06-03T10:15:00Z'
]);
insertSession.run([
'worker-kb',
@@ -163,14 +159,18 @@ async function writeSampleEcc2Database(dbPath) {
0.07,
'2026-06-03T10:05:00Z',
'2026-06-03T10:14:00Z',
- '2026-06-03T10:14:00Z',
+ '2026-06-03T10:14:00Z'
]);
insertSession.free();
- db.run(
- 'INSERT INTO messages (from_session, to_session, content, msg_type, read, timestamp) VALUES (?, ?, ?, ?, ?, ?)',
- ['worker-kb', 'lead-hermes', 'Need approval for connector sync', 'approval_request', 0, '2026-06-03T10:16:00Z']
- );
+ db.run('INSERT INTO messages (from_session, to_session, content, msg_type, read, timestamp) VALUES (?, ?, ?, ?, ?, ?)', [
+ 'worker-kb',
+ 'lead-hermes',
+ 'Need approval for connector sync',
+ 'approval_request',
+ 0,
+ '2026-06-03T10:16:00Z'
+ ]);
const insertEntity = db.prepare(`
INSERT INTO context_graph_entities (
@@ -186,7 +186,7 @@ async function writeSampleEcc2Database(dbPath) {
'How Affaan routes Hermes Desktop, Zellij panes, Devin-style delegation, and ECC release control work.',
JSON.stringify({ source: 'hermes_workspace', platform: 'desktop' }),
'2026-06-03T10:10:00Z',
- '2026-06-03T10:10:00Z',
+ '2026-06-03T10:10:00Z'
]);
insertEntity.run([
null,
@@ -197,31 +197,34 @@ async function writeSampleEcc2Database(dbPath) {
'Operator knowledge base pattern for cross-platform agent memory.',
JSON.stringify({ source: 'workspace_notes' }),
'2026-06-03T10:11:00Z',
- '2026-06-03T10:11:00Z',
+ '2026-06-03T10:11:00Z'
]);
insertEntity.free();
- db.run(
- 'INSERT INTO context_graph_observations (session_id, entity_id, observation_type, priority, pinned, summary, details_json, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
- [
- 'lead-hermes',
- 1,
- 'operator_memory',
- 3,
- 1,
- 'Hermes Desktop and ECC should share recall before dispatching work.',
- JSON.stringify({ note: 'safe public summary only' }),
- '2026-06-03T10:12:00Z',
- ]
- );
- db.run(
- 'INSERT INTO context_graph_relations (session_id, from_entity_id, to_entity_id, relation_type, summary, created_at) VALUES (?, ?, ?, ?, ?, ?)',
- ['lead-hermes', 1, 2, 'depends_on', 'Runbook uses durable memory concepts.', '2026-06-03T10:13:00Z']
- );
- db.run(
- 'INSERT INTO context_graph_connector_checkpoints (connector_name, source_path, source_signature, updated_at) VALUES (?, ?, ?, ?)',
- ['hermes_workspace', '/notes/hermes.md', 'sig-1', '2026-06-03T10:12:00Z']
- );
+ db.run('INSERT INTO context_graph_observations (session_id, entity_id, observation_type, priority, pinned, summary, details_json, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
+ 'lead-hermes',
+ 1,
+ 'operator_memory',
+ 3,
+ 1,
+ 'Hermes Desktop and ECC should share recall before dispatching work.',
+ JSON.stringify({ note: 'safe public summary only' }),
+ '2026-06-03T10:12:00Z'
+ ]);
+ db.run('INSERT INTO context_graph_relations (session_id, from_entity_id, to_entity_id, relation_type, summary, created_at) VALUES (?, ?, ?, ?, ?, ?)', [
+ 'lead-hermes',
+ 1,
+ 2,
+ 'depends_on',
+ 'Runbook uses durable memory concepts.',
+ '2026-06-03T10:13:00Z'
+ ]);
+ db.run('INSERT INTO context_graph_connector_checkpoints (connector_name, source_path, source_signature, updated_at) VALUES (?, ?, ?, ?)', [
+ 'hermes_workspace',
+ '/notes/hermes.md',
+ 'sig-1',
+ '2026-06-03T10:12:00Z'
+ ]);
fs.writeFileSync(dbPath, Buffer.from(db.export()));
db.close();
@@ -270,10 +273,10 @@ async function writeSampleWorkItemsDatabase(dbPath) {
JSON.stringify({
branch: 'product/dynamic-workflow-team-orchestration',
mergeGate: 'focused tests and catalog check pass',
- acceptance: ['skill exists', 'content pack exists'],
+ acceptance: ['skill exists', 'content pack exists']
}),
'2026-06-04T09:00:00Z',
- '2026-06-04T09:05:00Z',
+ '2026-06-04T09:05:00Z'
]);
insertWorkItem.run([
'agent-card-002',
@@ -288,10 +291,10 @@ async function writeSampleWorkItemsDatabase(dbPath) {
null,
JSON.stringify({
branch: 'product/ecc2-knowledge-control-pane',
- mergeStateStatus: 'CLEAN',
+ mergeStateStatus: 'CLEAN'
}),
'2026-06-03T13:00:00Z',
- '2026-06-03T13:55:00Z',
+ '2026-06-03T13:55:00Z'
]);
insertWorkItem.run([
'agent-card-003',
@@ -306,10 +309,25 @@ async function writeSampleWorkItemsDatabase(dbPath) {
null,
JSON.stringify({
blocker: 'needs publish approval',
- mergeGate: 'approval packet accepted',
+ mergeGate: 'approval packet accepted'
}),
'2026-06-04T09:10:00Z',
- '2026-06-04T09:12:00Z',
+ '2026-06-04T09:12:00Z'
+ ]);
+ insertWorkItem.run([
+ 'agent-card-004',
+ 'github-issue',
+ '2290',
+ 'Triage 400k context window bug',
+ 'open',
+ 'high',
+ 'https://github.com/affaan-m/ECC/issues/2290',
+ null,
+ '/repo/ecc',
+ null,
+ JSON.stringify({}),
+ '2026-06-04T09:20:00Z',
+ '2026-06-04T09:22:00Z'
]);
insertWorkItem.free();
@@ -335,293 +353,324 @@ async function runTests() {
let passed = 0;
let failed = 0;
- if (await test('builds an operator snapshot from ECC2 SQLite and configured connectors', async () => {
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-state-'));
- const dbPath = path.join(tempDir, 'ecc2.db');
+ if (
+ await test('builds an operator snapshot from ECC2 SQLite and configured connectors', async () => {
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-state-'));
+ const dbPath = path.join(tempDir, 'ecc2.db');
- try {
- await writeSampleEcc2Database(dbPath);
- const snapshot = await buildControlPaneSnapshot({
- dbPath,
- repoRoot: path.join(__dirname, '..', '..'),
- query: 'Hermes Desktop Zellij gbrain',
- config: {
- memoryConnectors: {
- hermes_workspace: {
- kind: 'markdown_directory',
- path: '/notes',
- recurse: true,
- },
- safe_env: {
- kind: 'dotenv_file',
- path: '/notes/.env',
- includeSafeValues: false,
- },
+ try {
+ await writeSampleEcc2Database(dbPath);
+ const snapshot = await buildControlPaneSnapshot({
+ dbPath,
+ repoRoot: path.join(__dirname, '..', '..'),
+ query: 'Hermes Desktop Zellij gbrain',
+ config: {
+ memoryConnectors: {
+ hermes_workspace: {
+ kind: 'markdown_directory',
+ path: '/notes',
+ recurse: true
+ },
+ safe_env: {
+ kind: 'dotenv_file',
+ path: '/notes/.env',
+ includeSafeValues: false
+ }
+ }
+ }
+ });
+
+ assert.strictEqual(snapshot.schemaVersion, 'ecc.control-pane.snapshot.v1');
+ assert.strictEqual(snapshot.summary.totalSessions, 2);
+ assert.strictEqual(snapshot.summary.runningSessions, 1);
+ assert.strictEqual(snapshot.summary.unreadMessages, 1);
+ assert.strictEqual(snapshot.sessions[0].id, 'lead-hermes');
+ assert.deepStrictEqual(snapshot.sessions[0].detectedHarnesses, ['claude', 'codex']);
+ assert.strictEqual(snapshot.knowledge.query, 'Hermes Desktop Zellij gbrain');
+ assert.strictEqual(snapshot.knowledge.results[0].entity.name, 'Hermes revenue runbook');
+ assert.ok(snapshot.knowledge.results[0].matchedTerms.includes('hermes'));
+ assert.strictEqual(snapshot.knowledge.results[0].hasPinnedObservation, true);
+ assert.strictEqual(snapshot.connectors.length, 2);
+ assert.strictEqual(snapshot.connectors[0].name, 'hermes_workspace');
+ assert.strictEqual(snapshot.connectors[0].syncedSources, 1);
+ assert.strictEqual(snapshot.connectors[1].syncedSources, 0);
+ } finally {
+ fs.rmSync(tempDir, { recursive: true, force: true });
+ }
+ })
+ )
+ passed++;
+ else failed++;
+
+ if (
+ await test('projects state-store work items into agent Kanban summary', async () => {
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-work-items-'));
+ const dbPath = path.join(tempDir, 'ecc2.db');
+ const stateDbPath = path.join(tempDir, 'state.db');
+
+ try {
+ await writeSampleEcc2Database(dbPath);
+ await writeSampleWorkItemsDatabase(stateDbPath);
+
+ const snapshot = await buildControlPaneSnapshot({
+ dbPath,
+ stateDbPath,
+ repoRoot: path.join(__dirname, '..', '..'),
+ query: 'workflow'
+ });
+
+ const byId = id => snapshot.workItems.items.find(item => item.id === id);
+ assert.strictEqual(snapshot.workItems.totalCount, 4);
+ assert.strictEqual(snapshot.workItems.openCount, 3);
+ assert.strictEqual(snapshot.workItems.blockedCount, 1);
+ assert.strictEqual(snapshot.workItems.doneCount, 1);
+ assert.strictEqual(snapshot.workItems.kanban.running, 1);
+ assert.strictEqual(snapshot.workItems.kanban.blocked, 1);
+ assert.strictEqual(snapshot.workItems.kanban.ready, 1);
+ assert.strictEqual(byId('agent-card-003').mergeGate, 'approval packet accepted');
+ assert.strictEqual(byId('agent-card-001').branch, 'product/dynamic-workflow-team-orchestration');
+ assert.strictEqual(byId('agent-card-002').mergeGate, 'CLEAN');
+
+ // Agent + human JIT assignment view.
+ assert.strictEqual(byId('agent-card-001').assigneeKind, 'agent', 'session-linked card is agent-owned');
+ assert.strictEqual(byId('agent-card-003').assigneeKind, 'human', 'operator-owned card is human-owned');
+ assert.strictEqual(byId('agent-card-004').assigneeKind, 'unassigned', 'ownerless open card is unassigned');
+ assert.deepStrictEqual(snapshot.workItems.assignment, { agent: 1, human: 1, unassigned: 1 });
+ assert.strictEqual(snapshot.workItems.needsAssignment.length, 1);
+ assert.strictEqual(snapshot.workItems.needsAssignment[0].id, 'agent-card-004');
+ } finally {
+ fs.rmSync(tempDir, { recursive: true, force: true });
+ }
+ })
+ )
+ passed++;
+ else failed++;
+
+ if (
+ await test('treats an unreadable optional state-store database as empty work items', async () => {
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-corrupt-work-items-'));
+ const dbPath = path.join(tempDir, 'ecc2.db');
+ const stateDbPath = path.join(tempDir, 'corrupt-state.db');
+
+ try {
+ await writeSampleEcc2Database(dbPath);
+ fs.writeFileSync(stateDbPath, 'not a sqlite database', 'utf8');
+
+ const snapshot = await buildControlPaneSnapshot({
+ dbPath,
+ stateDbPath,
+ repoRoot: path.join(__dirname, '..', '..'),
+ query: 'workflow'
+ });
+
+ assert.strictEqual(snapshot.stateDatabase.exists, true);
+ assert.strictEqual(snapshot.workItems.totalCount, 0);
+ assert.strictEqual(snapshot.summary.totalSessions, 2);
+ } finally {
+ fs.rmSync(tempDir, { recursive: true, force: true });
+ }
+ })
+ )
+ passed++;
+ else failed++;
+
+ if (
+ await test('resolves config from explicit db path and TOML connector file', async () => {
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-config-'));
+ const dbPath = path.join(tempDir, 'state.db');
+ const configPath = path.join(tempDir, 'ecc2.toml');
+
+ try {
+ fs.writeFileSync(
+ configPath,
+ [
+ `db_path = "${dbPath.replace(/\\/g, '\\\\')}"`,
+ '',
+ '[memory_connectors.hermes_workspace]',
+ 'kind = "markdown_directory"',
+ 'path = "/tmp/hermes"',
+ 'recurse = true',
+ 'default_entity_type = "operator_note"'
+ ].join('\n'),
+ 'utf8'
+ );
+
+ const config = resolveControlPaneConfig({
+ cwd: tempDir,
+ configPath
+ });
+
+ assert.strictEqual(config.dbPath, dbPath);
+ assert.strictEqual(config.memoryConnectors.hermes_workspace.kind, 'markdown_directory');
+ assert.strictEqual(config.memoryConnectors.hermes_workspace.path, '/tmp/hermes');
+ } finally {
+ fs.rmSync(tempDir, { recursive: true, force: true });
+ }
+ })
+ )
+ passed++;
+ else failed++;
+
+ if (
+ await test('prefers the operator home config over stale app-support config', async () => {
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-precedence-'));
+ const homeDir = path.join(tempDir, 'home');
+ const homeConfigDir = path.join(homeDir, '.claude');
+ const appConfigDir = path.join(homeDir, 'Library', 'Application Support', 'ecc2');
+ const homeDbPath = path.join(tempDir, 'operator.db');
+ const staleDbPath = path.join(tempDir, 'stale-smoke.db');
+
+ try {
+ fs.mkdirSync(homeConfigDir, { recursive: true });
+ fs.mkdirSync(appConfigDir, { recursive: true });
+ fs.writeFileSync(path.join(appConfigDir, 'config.toml'), `db_path = "${staleDbPath.replace(/\\/g, '\\\\')}"\n`, 'utf8');
+ fs.writeFileSync(path.join(homeConfigDir, 'ecc2.toml'), `db_path = "${homeDbPath.replace(/\\/g, '\\\\')}"\n`, 'utf8');
+
+ const config = resolveControlPaneConfig({
+ cwd: tempDir,
+ env: { HOME: homeDir }
+ });
+
+ assert.strictEqual(config.dbPath, homeDbPath);
+ } finally {
+ fs.rmSync(tempDir, { recursive: true, force: true });
+ }
+ })
+ )
+ passed++;
+ else failed++;
+
+ if (
+ await test('shows configured connectors even when the SQLite database is missing', async () => {
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-missing-db-'));
+
+ try {
+ const snapshot = await buildControlPaneSnapshot({
+ repoRoot: path.join(__dirname, '..', '..'),
+ dbPath: path.join(tempDir, 'missing.db'),
+ config: {
+ memoryConnectors: {
+ hermes_workspace: {
+ kind: 'markdown_directory',
+ path: '/notes/hermes',
+ recurse: true
+ }
+ }
+ }
+ });
+
+ assert.strictEqual(snapshot.database.exists, false);
+ assert.strictEqual(snapshot.connectors.length, 1);
+ assert.strictEqual(snapshot.connectors[0].name, 'hermes_workspace');
+ assert.strictEqual(snapshot.connectors[0].syncedSources, 0);
+ } finally {
+ fs.rmSync(tempDir, { recursive: true, force: true });
+ }
+ })
+ )
+ passed++;
+ else failed++;
+
+ if (
+ await test('handles an existing SQLite database before ECC2 tables are created', async () => {
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-empty-db-'));
+ const dbPath = path.join(tempDir, 'empty.db');
+
+ try {
+ const SQL = await initSqlJs();
+ const db = new SQL.Database();
+ fs.writeFileSync(dbPath, Buffer.from(db.export()));
+ db.close();
+
+ const snapshot = await buildControlPaneSnapshot({
+ repoRoot: path.join(__dirname, '..', '..'),
+ dbPath,
+ config: {
+ memoryConnectors: {
+ workspace_notes: {
+ kind: 'markdown_directory',
+ path: '/notes',
+ includeSafeValues: false
+ }
+ }
+ }
+ });
+
+ assert.strictEqual(snapshot.database.exists, true);
+ assert.strictEqual(snapshot.summary.totalSessions, 0);
+ assert.strictEqual(snapshot.knowledge.entityCount, 0);
+ assert.strictEqual(snapshot.knowledge.observationCount, 0);
+ assert.strictEqual(snapshot.connectors[0].name, 'workspace_notes');
+ assert.strictEqual(snapshot.connectors[0].lastSyncedAt, null);
+ } finally {
+ fs.rmSync(tempDir, { recursive: true, force: true });
+ }
+ })
+ )
+ passed++;
+ else failed++;
+
+ if (
+ await test('recalls pinned knowledge when no query is provided', async () => {
+ const results = recallKnowledgeEntries({
+ entities: [
+ {
+ id: 1,
+ entityType: 'runbook',
+ name: 'Pinned runbook',
+ path: '/notes/pinned.md',
+ summary: 'Pinned operator context',
+ metadata: {},
+ updatedAt: '2026-06-03T10:00:00Z'
},
- },
- });
-
- assert.strictEqual(snapshot.schemaVersion, 'ecc.control-pane.snapshot.v1');
- assert.strictEqual(snapshot.summary.totalSessions, 2);
- assert.strictEqual(snapshot.summary.runningSessions, 1);
- assert.strictEqual(snapshot.summary.unreadMessages, 1);
- assert.strictEqual(snapshot.sessions[0].id, 'lead-hermes');
- assert.deepStrictEqual(snapshot.sessions[0].detectedHarnesses, ['claude', 'codex']);
- assert.strictEqual(snapshot.knowledge.query, 'Hermes Desktop Zellij gbrain');
- assert.strictEqual(snapshot.knowledge.results[0].entity.name, 'Hermes revenue runbook');
- assert.ok(snapshot.knowledge.results[0].matchedTerms.includes('hermes'));
- assert.strictEqual(snapshot.knowledge.results[0].hasPinnedObservation, true);
- assert.strictEqual(snapshot.connectors.length, 2);
- assert.strictEqual(snapshot.connectors[0].name, 'hermes_workspace');
- assert.strictEqual(snapshot.connectors[0].syncedSources, 1);
- assert.strictEqual(snapshot.connectors[1].syncedSources, 0);
- } finally {
- fs.rmSync(tempDir, { recursive: true, force: true });
- }
- })) passed++; else failed++;
-
- if (await test('projects state-store work items into agent Kanban summary', async () => {
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-work-items-'));
- const dbPath = path.join(tempDir, 'ecc2.db');
- const stateDbPath = path.join(tempDir, 'state.db');
-
- try {
- await writeSampleEcc2Database(dbPath);
- await writeSampleWorkItemsDatabase(stateDbPath);
-
- const snapshot = await buildControlPaneSnapshot({
- dbPath,
- stateDbPath,
- repoRoot: path.join(__dirname, '..', '..'),
- query: 'workflow',
- });
-
- assert.strictEqual(snapshot.workItems.totalCount, 3);
- assert.strictEqual(snapshot.workItems.openCount, 2);
- assert.strictEqual(snapshot.workItems.blockedCount, 1);
- assert.strictEqual(snapshot.workItems.doneCount, 1);
- assert.strictEqual(snapshot.workItems.kanban.running, 1);
- assert.strictEqual(snapshot.workItems.kanban.blocked, 1);
- assert.strictEqual(snapshot.workItems.items[0].id, 'agent-card-003');
- assert.strictEqual(snapshot.workItems.items[0].mergeGate, 'approval packet accepted');
- assert.strictEqual(snapshot.workItems.items[1].branch, 'product/dynamic-workflow-team-orchestration');
- assert.strictEqual(
- snapshot.workItems.items.find(item => item.id === 'agent-card-002').mergeGate,
- 'CLEAN'
- );
- } finally {
- fs.rmSync(tempDir, { recursive: true, force: true });
- }
- })) passed++; else failed++;
-
- if (await test('treats an unreadable optional state-store database as empty work items', async () => {
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-corrupt-work-items-'));
- const dbPath = path.join(tempDir, 'ecc2.db');
- const stateDbPath = path.join(tempDir, 'corrupt-state.db');
-
- try {
- await writeSampleEcc2Database(dbPath);
- fs.writeFileSync(stateDbPath, 'not a sqlite database', 'utf8');
-
- const snapshot = await buildControlPaneSnapshot({
- dbPath,
- stateDbPath,
- repoRoot: path.join(__dirname, '..', '..'),
- query: 'workflow',
- });
-
- assert.strictEqual(snapshot.stateDatabase.exists, true);
- assert.strictEqual(snapshot.workItems.totalCount, 0);
- assert.strictEqual(snapshot.summary.totalSessions, 2);
- } finally {
- fs.rmSync(tempDir, { recursive: true, force: true });
- }
- })) passed++; else failed++;
-
- if (await test('resolves config from explicit db path and TOML connector file', async () => {
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-config-'));
- const dbPath = path.join(tempDir, 'state.db');
- const configPath = path.join(tempDir, 'ecc2.toml');
-
- try {
- fs.writeFileSync(
- configPath,
- [
- `db_path = "${dbPath.replace(/\\/g, '\\\\')}"`,
- '',
- '[memory_connectors.hermes_workspace]',
- 'kind = "markdown_directory"',
- 'path = "/tmp/hermes"',
- 'recurse = true',
- 'default_entity_type = "operator_note"',
- ].join('\n'),
- 'utf8'
- );
-
- const config = resolveControlPaneConfig({
- cwd: tempDir,
- configPath,
- });
-
- assert.strictEqual(config.dbPath, dbPath);
- assert.strictEqual(config.memoryConnectors.hermes_workspace.kind, 'markdown_directory');
- assert.strictEqual(config.memoryConnectors.hermes_workspace.path, '/tmp/hermes');
- } finally {
- fs.rmSync(tempDir, { recursive: true, force: true });
- }
- })) passed++; else failed++;
-
- if (await test('prefers the operator home config over stale app-support config', async () => {
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-precedence-'));
- const homeDir = path.join(tempDir, 'home');
- const homeConfigDir = path.join(homeDir, '.claude');
- const appConfigDir = path.join(homeDir, 'Library', 'Application Support', 'ecc2');
- const homeDbPath = path.join(tempDir, 'operator.db');
- const staleDbPath = path.join(tempDir, 'stale-smoke.db');
-
- try {
- fs.mkdirSync(homeConfigDir, { recursive: true });
- fs.mkdirSync(appConfigDir, { recursive: true });
- fs.writeFileSync(
- path.join(appConfigDir, 'config.toml'),
- `db_path = "${staleDbPath.replace(/\\/g, '\\\\')}"\n`,
- 'utf8'
- );
- fs.writeFileSync(
- path.join(homeConfigDir, 'ecc2.toml'),
- `db_path = "${homeDbPath.replace(/\\/g, '\\\\')}"\n`,
- 'utf8'
- );
-
- const config = resolveControlPaneConfig({
- cwd: tempDir,
- env: { HOME: homeDir },
- });
-
- assert.strictEqual(config.dbPath, homeDbPath);
- } finally {
- fs.rmSync(tempDir, { recursive: true, force: true });
- }
- })) passed++; else failed++;
-
- if (await test('shows configured connectors even when the SQLite database is missing', async () => {
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-missing-db-'));
-
- try {
- const snapshot = await buildControlPaneSnapshot({
- repoRoot: path.join(__dirname, '..', '..'),
- dbPath: path.join(tempDir, 'missing.db'),
- config: {
- memoryConnectors: {
- hermes_workspace: {
- kind: 'markdown_directory',
- path: '/notes/hermes',
- recurse: true,
- },
+ {
+ id: 2,
+ entityType: 'concept',
+ name: 'Unpinned concept',
+ path: null,
+ summary: 'Secondary context',
+ metadata: {},
+ updatedAt: '2026-06-03T11:00:00Z'
+ }
+ ],
+ observations: [
+ {
+ entityId: 1,
+ priority: 4,
+ pinned: true,
+ summary: 'Pinned detail'
},
- },
+ {
+ entityId: 2,
+ priority: 2,
+ pinned: false,
+ summary: 'Other detail'
+ }
+ ],
+ relationCounts: new Map([[1, 3]]),
+ query: '',
+ limit: 0
});
- assert.strictEqual(snapshot.database.exists, false);
- assert.strictEqual(snapshot.connectors.length, 1);
- assert.strictEqual(snapshot.connectors[0].name, 'hermes_workspace');
- assert.strictEqual(snapshot.connectors[0].syncedSources, 0);
- } finally {
- fs.rmSync(tempDir, { recursive: true, force: true });
- }
- })) passed++; else failed++;
+ assert.strictEqual(results.length, 2);
+ assert.strictEqual(results[0].entity.name, 'Pinned runbook');
+ assert.strictEqual(results[0].hasPinnedObservation, true);
+ assert.strictEqual(results[0].relationCount, 3);
+ assert.strictEqual(results[1].entity.name, 'Unpinned concept');
+ })
+ )
+ passed++;
+ else failed++;
- if (await test('handles an existing SQLite database before ECC2 tables are created', async () => {
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-empty-db-'));
- const dbPath = path.join(tempDir, 'empty.db');
+ if (
+ await test('handles malformed JSON rows and all session state counters', async () => {
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-edge-db-'));
+ const dbPath = path.join(tempDir, 'ecc2.db');
- try {
- const SQL = await initSqlJs();
- const db = new SQL.Database();
- fs.writeFileSync(dbPath, Buffer.from(db.export()));
- db.close();
-
- const snapshot = await buildControlPaneSnapshot({
- repoRoot: path.join(__dirname, '..', '..'),
- dbPath,
- config: {
- memoryConnectors: {
- workspace_notes: {
- kind: 'markdown_directory',
- path: '/notes',
- includeSafeValues: false,
- },
- },
- },
- });
-
- assert.strictEqual(snapshot.database.exists, true);
- assert.strictEqual(snapshot.summary.totalSessions, 0);
- assert.strictEqual(snapshot.knowledge.entityCount, 0);
- assert.strictEqual(snapshot.knowledge.observationCount, 0);
- assert.strictEqual(snapshot.connectors[0].name, 'workspace_notes');
- assert.strictEqual(snapshot.connectors[0].lastSyncedAt, null);
- } finally {
- fs.rmSync(tempDir, { recursive: true, force: true });
- }
- })) passed++; else failed++;
-
- if (await test('recalls pinned knowledge when no query is provided', async () => {
- const results = recallKnowledgeEntries({
- entities: [
- {
- id: 1,
- entityType: 'runbook',
- name: 'Pinned runbook',
- path: '/notes/pinned.md',
- summary: 'Pinned operator context',
- metadata: {},
- updatedAt: '2026-06-03T10:00:00Z',
- },
- {
- id: 2,
- entityType: 'concept',
- name: 'Unpinned concept',
- path: null,
- summary: 'Secondary context',
- metadata: {},
- updatedAt: '2026-06-03T11:00:00Z',
- },
- ],
- observations: [
- {
- entityId: 1,
- priority: 4,
- pinned: true,
- summary: 'Pinned detail',
- },
- {
- entityId: 2,
- priority: 2,
- pinned: false,
- summary: 'Other detail',
- },
- ],
- relationCounts: new Map([[1, 3]]),
- query: '',
- limit: 0,
- });
-
- assert.strictEqual(results.length, 2);
- assert.strictEqual(results[0].entity.name, 'Pinned runbook');
- assert.strictEqual(results[0].hasPinnedObservation, true);
- assert.strictEqual(results[0].relationCount, 3);
- assert.strictEqual(results[1].entity.name, 'Unpinned concept');
- })) passed++; else failed++;
-
- if (await test('handles malformed JSON rows and all session state counters', async () => {
- const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-control-pane-edge-db-'));
- const dbPath = path.join(tempDir, 'ecc2.db');
-
- try {
- await writeSampleEcc2Database(dbPath);
- await mutateSqlDatabase(dbPath, db => {
- const insertSession = db.prepare(`
+ try {
+ await writeSampleEcc2Database(dbPath);
+ await mutateSqlDatabase(dbPath, db => {
+ const insertSession = db.prepare(`
INSERT INTO sessions (
id, task, project, task_group, agent_type, harness, detected_harnesses_json,
working_dir, state, pid, worktree_path, worktree_branch, worktree_base,
@@ -629,54 +678,52 @@ async function runTests() {
duration_secs, cost_usd, created_at, updated_at, last_heartbeat_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`);
- for (const state of ['pending', 'failed', 'stopped', 'completed']) {
- insertSession.run([
- `session-${state}`,
- `Exercise ${state}`,
- 'ECC',
- 'coverage',
- 'codex',
- '',
- state === 'failed' ? '{bad json' : '[]',
- '',
- state,
- state === 'pending' ? 'not-a-pid' : null,
- state === 'completed' ? '/tmp/worktree' : null,
- null,
- null,
- 'not-input-tokens',
- null,
- state === 'pending' ? 'not-tokens' : 10,
- null,
- null,
- null,
- state === 'failed' ? 'not-cost' : 0.1,
- '2026-06-03T11:00:00Z',
- `2026-06-03T11:0${state.length % 10}:00Z`,
- '',
- ]);
- }
- insertSession.free();
+ for (const state of ['pending', 'failed', 'stopped', 'completed']) {
+ insertSession.run([
+ `session-${state}`,
+ `Exercise ${state}`,
+ 'ECC',
+ 'coverage',
+ 'codex',
+ '',
+ state === 'failed' ? '{bad json' : '[]',
+ '',
+ state,
+ state === 'pending' ? 'not-a-pid' : null,
+ state === 'completed' ? '/tmp/worktree' : null,
+ null,
+ null,
+ 'not-input-tokens',
+ null,
+ state === 'pending' ? 'not-tokens' : 10,
+ null,
+ null,
+ null,
+ state === 'failed' ? 'not-cost' : 0.1,
+ '2026-06-03T11:00:00Z',
+ `2026-06-03T11:0${state.length % 10}:00Z`,
+ ''
+ ]);
+ }
+ insertSession.free();
- db.run(
- `INSERT INTO context_graph_entities (
+ db.run(
+ `INSERT INTO context_graph_entities (
session_id, entity_key, entity_type, name, path, summary, metadata_json, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
- [
- 'session-failed',
- 'bad:json',
- 'note',
- 'Malformed JSON knowledge',
- '/notes/malformed.md',
- 'This record should still be searchable.',
- '{bad json',
- '2026-06-03T11:20:00Z',
- '2026-06-03T11:20:00Z',
- ]
- );
- db.run(
- 'INSERT INTO context_graph_observations (session_id, entity_id, observation_type, priority, pinned, summary, details_json, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
- [
+ [
+ 'session-failed',
+ 'bad:json',
+ 'note',
+ 'Malformed JSON knowledge',
+ '/notes/malformed.md',
+ 'This record should still be searchable.',
+ '{bad json',
+ '2026-06-03T11:20:00Z',
+ '2026-06-03T11:20:00Z'
+ ]
+ );
+ db.run('INSERT INTO context_graph_observations (session_id, entity_id, observation_type, priority, pinned, summary, details_json, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', [
'session-failed',
3,
'',
@@ -684,125 +731,134 @@ async function runTests() {
0,
'Malformed details should fall back safely.',
'{bad json',
- '2026-06-03T11:21:00Z',
- ]
- );
- });
+ '2026-06-03T11:21:00Z'
+ ]);
+ });
- const snapshot = await buildControlPaneSnapshot({
- repoRoot: path.join(__dirname, '..', '..'),
- dbPath,
- query: 'Malformed',
- config: {
- memoryConnectors: {
- malformed_notes: {
- kind: 'markdown_directory',
- path: '/notes/malformed',
- recurse: false,
- defaultEntityType: 'note',
- defaultObservationType: 'operator_memory',
- includeSafeValues: true,
- },
- },
+ const snapshot = await buildControlPaneSnapshot({
+ repoRoot: path.join(__dirname, '..', '..'),
+ dbPath,
+ query: 'Malformed',
+ config: {
+ memoryConnectors: {
+ malformed_notes: {
+ kind: 'markdown_directory',
+ path: '/notes/malformed',
+ recurse: false,
+ defaultEntityType: 'note',
+ defaultObservationType: 'operator_memory',
+ includeSafeValues: true
+ }
+ }
+ }
+ });
+
+ assert.strictEqual(snapshot.summary.pendingSessions, 1);
+ assert.strictEqual(snapshot.summary.failedSessions, 1);
+ assert.strictEqual(snapshot.summary.stoppedSessions, 1);
+ assert.strictEqual(snapshot.summary.completedSessions, 1);
+ assert.strictEqual(snapshot.summary.runningSessions, 1);
+ assert.strictEqual(snapshot.summary.idleSessions, 1);
+ assert.strictEqual(snapshot.summary.totalSessions, 6);
+
+ const failedSession = snapshot.sessions.find(session => session.id === 'session-failed');
+ assert.deepStrictEqual(failedSession.detectedHarnesses, []);
+ assert.strictEqual(failedSession.metrics.costUsd, 0);
+
+ const pendingSession = snapshot.sessions.find(session => session.id === 'session-pending');
+ assert.strictEqual(pendingSession.pid, 0);
+ assert.strictEqual(pendingSession.metrics.tokensUsed, 0);
+
+ assert.strictEqual(snapshot.knowledge.results[0].entity.name, 'Malformed JSON knowledge');
+ assert.deepStrictEqual(snapshot.knowledge.results[0].entity.metadata, {});
+ assert.deepStrictEqual(snapshot.knowledge.results[0].latestObservation.details, {});
+ assert.strictEqual(snapshot.connectors[0].defaultEntityType, 'note');
+ assert.strictEqual(snapshot.connectors[0].defaultObservationType, 'operator_memory');
+ assert.strictEqual(snapshot.connectors[0].includeSafeValues, true);
+ } finally {
+ fs.rmSync(tempDir, { recursive: true, force: true });
+ }
+ })
+ )
+ passed++;
+ else failed++;
+
+ if (
+ await test('recall search covers metadata, relation caps, no matches, and tie ordering', async () => {
+ const baseEntities = [
+ {
+ id: 1,
+ entityType: 'note',
+ name: 'First shared memory',
+ path: '/notes/shared-a.md',
+ summary: 'Platform context',
+ metadata: { source: 'workspace' },
+ updatedAt: '2026-06-03T10:00:00Z'
},
+ {
+ id: 2,
+ entityType: 'note',
+ name: 'Second shared memory',
+ path: '/notes/shared-b.md',
+ summary: 'Platform context',
+ metadata: { source: 'workspace' },
+ updatedAt: '2026-06-03T12:00:00Z'
+ },
+ {
+ id: 3,
+ entityType: 'concept',
+ name: 'Markets graph',
+ path: null,
+ summary: 'Correlation graph visualization',
+ metadata: { flow: 'friction-flow' },
+ updatedAt: '2026-06-03T09:00:00Z'
+ }
+ ];
+ const observations = [
+ {
+ entityId: 3,
+ priority: 1,
+ pinned: false,
+ summary: 'Ito should expose market backtesting through ECC tools.'
+ }
+ ];
+
+ const tied = recallKnowledgeEntries({
+ entities: baseEntities,
+ observations: [],
+ relationCounts: new Map(),
+ query: 'shared',
+ limit: 50
});
+ assert.deepStrictEqual(
+ tied.map(entry => entry.entity.id),
+ [2, 1]
+ );
- assert.strictEqual(snapshot.summary.pendingSessions, 1);
- assert.strictEqual(snapshot.summary.failedSessions, 1);
- assert.strictEqual(snapshot.summary.stoppedSessions, 1);
- assert.strictEqual(snapshot.summary.completedSessions, 1);
- assert.strictEqual(snapshot.summary.runningSessions, 1);
- assert.strictEqual(snapshot.summary.idleSessions, 1);
- assert.strictEqual(snapshot.summary.totalSessions, 6);
+ const metadataHit = recallKnowledgeEntries({
+ entities: baseEntities,
+ observations,
+ relationCounts: new Map([[3, 20]]),
+ query: 'friction-flow backtesting',
+ limit: -5
+ });
+ assert.strictEqual(metadataHit.length, 1);
+ assert.strictEqual(metadataHit[0].entity.id, 3);
+ assert.strictEqual(metadataHit[0].relationCount, 20);
+ assert.ok(metadataHit[0].score >= 18);
- const failedSession = snapshot.sessions.find(session => session.id === 'session-failed');
- assert.deepStrictEqual(failedSession.detectedHarnesses, []);
- assert.strictEqual(failedSession.metrics.costUsd, 0);
-
- const pendingSession = snapshot.sessions.find(session => session.id === 'session-pending');
- assert.strictEqual(pendingSession.pid, 0);
- assert.strictEqual(pendingSession.metrics.tokensUsed, 0);
-
- assert.strictEqual(snapshot.knowledge.results[0].entity.name, 'Malformed JSON knowledge');
- assert.deepStrictEqual(snapshot.knowledge.results[0].entity.metadata, {});
- assert.deepStrictEqual(snapshot.knowledge.results[0].latestObservation.details, {});
- assert.strictEqual(snapshot.connectors[0].defaultEntityType, 'note');
- assert.strictEqual(snapshot.connectors[0].defaultObservationType, 'operator_memory');
- assert.strictEqual(snapshot.connectors[0].includeSafeValues, true);
- } finally {
- fs.rmSync(tempDir, { recursive: true, force: true });
- }
- })) passed++; else failed++;
-
- if (await test('recall search covers metadata, relation caps, no matches, and tie ordering', async () => {
- const baseEntities = [
- {
- id: 1,
- entityType: 'note',
- name: 'First shared memory',
- path: '/notes/shared-a.md',
- summary: 'Platform context',
- metadata: { source: 'workspace' },
- updatedAt: '2026-06-03T10:00:00Z',
- },
- {
- id: 2,
- entityType: 'note',
- name: 'Second shared memory',
- path: '/notes/shared-b.md',
- summary: 'Platform context',
- metadata: { source: 'workspace' },
- updatedAt: '2026-06-03T12:00:00Z',
- },
- {
- id: 3,
- entityType: 'concept',
- name: 'Markets graph',
- path: null,
- summary: 'Correlation graph visualization',
- metadata: { flow: 'friction-flow' },
- updatedAt: '2026-06-03T09:00:00Z',
- },
- ];
- const observations = [
- {
- entityId: 3,
- priority: 1,
- pinned: false,
- summary: 'Ito should expose market backtesting through ECC tools.',
- },
- ];
-
- const tied = recallKnowledgeEntries({
- entities: baseEntities,
- observations: [],
- relationCounts: new Map(),
- query: 'shared',
- limit: 50,
- });
- assert.deepStrictEqual(tied.map(entry => entry.entity.id), [2, 1]);
-
- const metadataHit = recallKnowledgeEntries({
- entities: baseEntities,
- observations,
- relationCounts: new Map([[3, 20]]),
- query: 'friction-flow backtesting',
- limit: -5,
- });
- assert.strictEqual(metadataHit.length, 1);
- assert.strictEqual(metadataHit[0].entity.id, 3);
- assert.strictEqual(metadataHit[0].relationCount, 20);
- assert.ok(metadataHit[0].score >= 18);
-
- const noHits = recallKnowledgeEntries({
- entities: baseEntities,
- observations,
- relationCounts: new Map(),
- query: 'unmatched',
- limit: 'wat',
- });
- assert.deepStrictEqual(noHits, []);
- })) passed++; else failed++;
+ const noHits = recallKnowledgeEntries({
+ entities: baseEntities,
+ observations,
+ relationCounts: new Map(),
+ query: 'unmatched',
+ limit: 'wat'
+ });
+ assert.deepStrictEqual(noHits, []);
+ })
+ )
+ passed++;
+ else failed++;
console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`);
process.exit(failed > 0 ? 1 : 0);