Files
openclaw/scripts/restore-ledger.js
T
Tabula Myriad a9ae1a6778 feat: Triad development iteration complete
Matrix Protocol:
- docker-compose.matrix.yml: Dendrite homeserver + PostgreSQL + Nginx TLS
- src/channels/plugins/matrix-channel.ts: OpenClaw plugin implementation
- docs/matrix-triad-setup.md: Setup guide with auth scheme (@tm1-4:triad.local)

MCP Server Integration:
- docs/mcp-triad-integration.md: SearXNG, Playwright, GitHub MCP configs
- docs/mcp-curiosity-mapping.md: Gap-to-capability mapping

Node Sync Architecture:
- src/services/node-sync-service.ts: WebSocket peer sync + presence detection
- src/services/node-sync-service.test.ts: Unit tests
- docs/node-sync-architecture.md: Architecture docs

Triad Resilience:
- scripts/triad-corruption-check.mjs: SQLite + log + config + git integrity
- docs/triad-resilience.md: Recovery procedures
- .secure/deployment-logs/README.md: Schema v2
- skills/triad-heartbeat/SKILL.md: Corruption check integration

NPM Publish Workflow:
- scripts/npm-publish.mjs: version, changelog, validate, publish, rollback
- .github/workflows/npm-publish.yml: GitHub Actions with provenance
- docs/npm-publish-guide.md: Complete documentation

All deliverables tested in Docker before production.
2026-03-24 00:44:50 -04:00

129 lines
3.7 KiB
JavaScript
Executable File

#!/usr/bin/env node
// Triad Ledger Restore — Imports JSON backup to SQLite
// Usage: node scripts/restore-ledger.js <backup-file.json>
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const workspaceRoot = path.join(__dirname, "..");
const auraPath = path.join(workspaceRoot, ".aura");
const dbPath = path.join(auraPath, "consensus.db");
const backupFile = process.argv[2];
if (!backupFile) {
console.log("❌ Usage: node scripts/restore-ledger.js <backup-file.json>");
console.log("Example: node scripts/restore-ledger.js .ledger-backups/latest.json");
process.exit(1);
}
if (!fs.existsSync(backupFile)) {
console.log(`❌ Backup file not found: ${backupFile}`);
process.exit(1);
}
console.log("🦞 Triad Ledger Restore — Starting...\n");
// Check if better-sqlite3 is available
let Database;
try {
Database = (await import("better-sqlite3")).default;
} catch {
console.log("❌ better-sqlite3 not installed. Run: npm install better-sqlite3");
process.exit(1);
}
// Read backup
const backup = JSON.parse(fs.readFileSync(backupFile, "utf8"));
console.log(`✅ Loaded backup: ${backup.timestamp}`);
// Ensure .aura exists
if (!fs.existsSync(auraPath)) {
fs.mkdirSync(auraPath, { recursive: true });
}
// Remove existing DB (fresh restore)
if (fs.existsSync(dbPath)) {
fs.unlinkSync(dbPath);
console.log("⚠️ Removed existing ledger DB (fresh restore)");
}
// Create fresh DB
const db = new Database(dbPath);
console.log(`✅ Created: ${dbPath}`);
// Run init script to create schema
const initScript = path.join(__dirname, "init-triad-ledger.js");
if (fs.existsSync(initScript)) {
console.log("⚠️ Running init script to create schema...");
// Skip init script execution, just create schema manually
}
// Create schema (from init-triad-ledger.js schema.sql)
const schemaPath = path.join(workspaceRoot, "skills", "triad-heartbeat", "schema.sql");
if (fs.existsSync(schemaPath)) {
const schema = fs.readFileSync(schemaPath, "utf8");
db.exec(schema);
console.log("✅ Schema applied");
} else {
console.log("❌ schema.sql not found. Creating minimal schema...");
db.exec(`
CREATE TABLE IF NOT EXISTS consensus_votes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT,
proposal TEXT,
result TEXT,
signers TEXT,
git_hash TEXT,
processed INTEGER DEFAULT 0,
created_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS triad_state (
node_id TEXT PRIMARY KEY,
last_heartbeat TEXT,
git_hash TEXT,
ledger_hash TEXT,
sync_status TEXT,
updated_at TEXT DEFAULT (datetime('now'))
);
CREATE TABLE IF NOT EXISTS triad_tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task TEXT,
status TEXT DEFAULT 'pending',
assigned_to TEXT,
created_at TEXT DEFAULT (datetime('now')),
completed_at TEXT
);
`);
}
// Restore data
let total = 0;
for (const [table, rows] of Object.entries(backup.tables)) {
if (!rows || rows.length === 0) {
continue;
}
const columns = Object.keys(rows[0]);
const placeholders = columns.map(() => "?").join(", ");
const insertSQL = `INSERT OR REPLACE INTO ${table} (${columns.join(", ")}) VALUES (${placeholders})`;
const stmt = db.prepare(insertSQL);
db.exec("BEGIN");
rows.forEach((row) => {
stmt.run(...columns.map((col) => row[col]));
});
db.exec("COMMIT");
total += rows.length;
console.log(`✅ Restored ${rows.length} rows to ${table}`);
}
db.close();
console.log(`\n✅ Restore complete: ${total} total records`);
console.log(`🦞 Ledger ready. Run: node scripts/init-triad-ledger.js to verify.`);