mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-12 04:33:29 +08:00
feat: add SQLite state store and ECC status CLI
This commit is contained in:
178
scripts/lib/state-store/migrations.js
Normal file
178
scripts/lib/state-store/migrations.js
Normal file
@@ -0,0 +1,178 @@
|
||||
'use strict';
|
||||
|
||||
const INITIAL_SCHEMA_SQL = `
|
||||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||
version INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
applied_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS sessions (
|
||||
id TEXT PRIMARY KEY,
|
||||
adapter_id TEXT NOT NULL,
|
||||
harness TEXT NOT NULL,
|
||||
state TEXT NOT NULL,
|
||||
repo_root TEXT,
|
||||
started_at TEXT,
|
||||
ended_at TEXT,
|
||||
snapshot TEXT NOT NULL CHECK (json_valid(snapshot))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_state_started_at
|
||||
ON sessions (state, started_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_started_at
|
||||
ON sessions (started_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS skill_runs (
|
||||
id TEXT PRIMARY KEY,
|
||||
skill_id TEXT NOT NULL,
|
||||
skill_version TEXT NOT NULL,
|
||||
session_id TEXT NOT NULL,
|
||||
task_description TEXT NOT NULL,
|
||||
outcome TEXT NOT NULL,
|
||||
failure_reason TEXT,
|
||||
tokens_used INTEGER,
|
||||
duration_ms INTEGER,
|
||||
user_feedback TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
FOREIGN KEY (session_id) REFERENCES sessions (id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_skill_runs_session_id_created_at
|
||||
ON skill_runs (session_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_skill_runs_created_at
|
||||
ON skill_runs (created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_skill_runs_outcome_created_at
|
||||
ON skill_runs (outcome, created_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS skill_versions (
|
||||
skill_id TEXT NOT NULL,
|
||||
version TEXT NOT NULL,
|
||||
content_hash TEXT NOT NULL,
|
||||
amendment_reason TEXT,
|
||||
promoted_at TEXT,
|
||||
rolled_back_at TEXT,
|
||||
PRIMARY KEY (skill_id, version)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_skill_versions_promoted_at
|
||||
ON skill_versions (promoted_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS decisions (
|
||||
id TEXT PRIMARY KEY,
|
||||
session_id TEXT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
rationale TEXT NOT NULL,
|
||||
alternatives TEXT NOT NULL CHECK (json_valid(alternatives)),
|
||||
supersedes TEXT,
|
||||
status TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL,
|
||||
FOREIGN KEY (session_id) REFERENCES sessions (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (supersedes) REFERENCES decisions (id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_decisions_session_id_created_at
|
||||
ON decisions (session_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_decisions_status_created_at
|
||||
ON decisions (status, created_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS install_state (
|
||||
target_id TEXT NOT NULL,
|
||||
target_root TEXT NOT NULL,
|
||||
profile TEXT,
|
||||
modules TEXT NOT NULL CHECK (json_valid(modules)),
|
||||
operations TEXT NOT NULL CHECK (json_valid(operations)),
|
||||
installed_at TEXT NOT NULL,
|
||||
source_version TEXT,
|
||||
PRIMARY KEY (target_id, target_root)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_install_state_installed_at
|
||||
ON install_state (installed_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS governance_events (
|
||||
id TEXT PRIMARY KEY,
|
||||
session_id TEXT,
|
||||
event_type TEXT NOT NULL,
|
||||
payload TEXT NOT NULL CHECK (json_valid(payload)),
|
||||
resolved_at TEXT,
|
||||
resolution TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
FOREIGN KEY (session_id) REFERENCES sessions (id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_governance_events_resolved_at_created_at
|
||||
ON governance_events (resolved_at, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_governance_events_session_id_created_at
|
||||
ON governance_events (session_id, created_at DESC);
|
||||
`;
|
||||
|
||||
const MIGRATIONS = [
|
||||
{
|
||||
version: 1,
|
||||
name: '001_initial_state_store',
|
||||
sql: INITIAL_SCHEMA_SQL,
|
||||
},
|
||||
];
|
||||
|
||||
function ensureMigrationTable(db) {
|
||||
db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||||
version INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
applied_at TEXT NOT NULL
|
||||
);
|
||||
`);
|
||||
}
|
||||
|
||||
function getAppliedMigrations(db) {
|
||||
ensureMigrationTable(db);
|
||||
return db
|
||||
.prepare(`
|
||||
SELECT version, name, applied_at
|
||||
FROM schema_migrations
|
||||
ORDER BY version ASC
|
||||
`)
|
||||
.all()
|
||||
.map(row => ({
|
||||
version: row.version,
|
||||
name: row.name,
|
||||
appliedAt: row.applied_at,
|
||||
}));
|
||||
}
|
||||
|
||||
function applyMigrations(db) {
|
||||
ensureMigrationTable(db);
|
||||
|
||||
const appliedVersions = new Set(
|
||||
db.prepare('SELECT version FROM schema_migrations').all().map(row => row.version)
|
||||
);
|
||||
const insertMigration = db.prepare(`
|
||||
INSERT INTO schema_migrations (version, name, applied_at)
|
||||
VALUES (@version, @name, @applied_at)
|
||||
`);
|
||||
|
||||
const applyPending = db.transaction(() => {
|
||||
for (const migration of MIGRATIONS) {
|
||||
if (appliedVersions.has(migration.version)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
db.exec(migration.sql);
|
||||
insertMigration.run({
|
||||
version: migration.version,
|
||||
name: migration.name,
|
||||
applied_at: new Date().toISOString(),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
applyPending();
|
||||
return getAppliedMigrations(db);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
MIGRATIONS,
|
||||
applyMigrations,
|
||||
getAppliedMigrations,
|
||||
};
|
||||
Reference in New Issue
Block a user