mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 21:53:28 +08:00
* feat: add SQLite state store and ECC status CLI * fix: replace better-sqlite3 with sql.js to eliminate native module CI failures better-sqlite3 requires native C++ compilation (node-gyp, prebuild-install) which fails in CI across npm/pnpm on all platforms: - npm ci: lock file out of sync with native transitive deps - pnpm: native bindings not found at runtime - Windows: native compilation fails entirely sql.js is a pure JavaScript/WASM SQLite implementation with zero native dependencies. The adapter in index.js wraps the sql.js API to match the better-sqlite3 interface used by migrations.js and queries.js. Key implementation detail: sql.js db.export() implicitly ends active transactions, so the adapter defers disk writes (saveToDisk) until after transaction commit via an inTransaction guard flag. createStateStore is now async (sql.js requires async WASM init). Updated status.js, sessions-cli.js, and tests accordingly.
179 lines
4.6 KiB
JavaScript
179 lines
4.6 KiB
JavaScript
'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,
|
|
};
|