107 lines
3.8 KiB
JavaScript
107 lines
3.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Guard 6: Dreaming Phase Guard
|
|
* Prevents dreaming phase proliferation beyond 3 phases.
|
|
*
|
|
* → Architecture Freeze v2 (PR-1): docs/architecture-freeze-v2.md
|
|
* → Current: light, deep, rem | Legacy: rem → to be replaced by promote
|
|
*
|
|
* Currently allowed phases: light, deep, rem
|
|
* After PR-5: will be reduced to collect, promote
|
|
*
|
|
* FAIL: new dreaming phase appears (count > 3)
|
|
* PASS: phase count <= 3
|
|
*/
|
|
|
|
import { readdirSync, readFileSync, existsSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
|
|
const OPENCLAW_HOME = process.env.OPENCLAW_HOME || "/opt/homebrew/lib/node_modules/openclaw";
|
|
const EXTENSIONS_DIR = join(OPENCLAW_HOME, "dist", "extensions");
|
|
|
|
const PHASE_LIMIT = 3; // Current baseline
|
|
const POST_PR5_LIMIT = 2; // After PR-5: collect + promote
|
|
|
|
function guardDreamingPhases() {
|
|
const issues = [];
|
|
let foundPhases = [];
|
|
let source = "none";
|
|
|
|
// Check memory-core plugin config schema
|
|
const memoryCorePath = join(EXTENSIONS_DIR, "memory-core", "openclaw.plugin.json");
|
|
if (existsSync(memoryCorePath)) {
|
|
try {
|
|
const plugin = JSON.parse(readFileSync(memoryCorePath, "utf8"));
|
|
const dreaming = plugin.configSchema?.properties?.dreaming;
|
|
if (dreaming) {
|
|
const phases = dreaming.properties?.phases?.properties;
|
|
if (phases) {
|
|
foundPhases = Object.keys(phases);
|
|
source = "memory-core/openclaw.plugin.json → configSchema.properties.dreaming.properties.phases";
|
|
}
|
|
}
|
|
} catch (e) {
|
|
issues.push({ level: "ERROR", msg: `Could not parse memory-core plugin.json: ${e.message}` });
|
|
}
|
|
}
|
|
|
|
// Also check active-memory for dreaming references
|
|
const activeMemoryPath = join(EXTENSIONS_DIR, "active-memory", "openclaw.plugin.json");
|
|
if (existsSync(activeMemoryPath)) {
|
|
try {
|
|
const plugin = JSON.parse(readFileSync(activeMemoryPath, "utf8"));
|
|
// Check if active-memory references phases
|
|
const configKeys = Object.keys(plugin.configSchema?.properties || {});
|
|
if (configKeys.includes("dreaming")) {
|
|
// Active memory has dreaming config too
|
|
}
|
|
} catch {}
|
|
}
|
|
|
|
console.log("");
|
|
console.log("═══════════════════════════════════════");
|
|
console.log(" Guard 6: Dreaming Phase Guard");
|
|
console.log("═══════════════════════════════════════");
|
|
console.log("");
|
|
|
|
if (foundPhases.length === 0) {
|
|
console.log(" No dreaming phases found in plugin config schemas.");
|
|
console.log(" (This may indicate a config schema location change.)");
|
|
issues.push({ level: "WARN", msg: "Could not locate dreaming phases in config schema" });
|
|
} else {
|
|
console.log(` Source: ${source}`);
|
|
console.log(` Dreaming phases: ${foundPhases.join(", ")}`);
|
|
console.log(` Phase count: ${foundPhases.length}`);
|
|
console.log(` Current limit: ${PHASE_LIMIT} (light, deep, rem)`);
|
|
console.log(` Post-PR5 limit: ${POST_PR5_LIMIT} (collect, promote)`);
|
|
|
|
if (foundPhases.length > PHASE_LIMIT) {
|
|
issues.push({
|
|
level: "FAIL",
|
|
msg: `Dreaming phase count ${foundPhases.length} exceeds limit ${PHASE_LIMIT}`
|
|
});
|
|
} else {
|
|
console.log(`\n Phase details:`);
|
|
for (const phase of foundPhases) {
|
|
console.log(` • ${phase}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log("");
|
|
for (const issue of issues) {
|
|
console.log(` [${issue.level}] ${issue.msg}`);
|
|
}
|
|
|
|
if (issues.filter(i => i.level === "FAIL").length === 0) {
|
|
console.log(" ✓ PASS: dreaming phase count within allowed limit");
|
|
console.log(` (After PR-5, limit will be reduced from ${PHASE_LIMIT} → ${POST_PR5_LIMIT})`);
|
|
process.exit(0);
|
|
} else {
|
|
console.log(" ✗ FAIL: dreaming phase count exceeded");
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
guardDreamingPhases();
|